config.rs 105 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954
  1. // Copyright 2019-2024 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. //! The Tauri configuration used at runtime.
  5. //!
  6. //! It is pulled from a `tauri.conf.json` file and the [`Config`] struct is generated at compile time.
  7. //!
  8. //! # Stability
  9. //!
  10. //! This is a core functionality that is not considered part of the stable API.
  11. //! If you use it, note that it may include breaking changes in the future.
  12. //!
  13. //! These items are intended to be non-breaking from a de/serialization standpoint only.
  14. //! Using and modifying existing config values will try to avoid breaking changes, but they are
  15. //! free to add fields in the future - causing breaking changes for creating and full destructuring.
  16. //!
  17. //! To avoid this, [ignore unknown fields when destructuring] with the `{my, config, ..}` pattern.
  18. //! If you need to create the Rust config directly without deserializing, then create the struct
  19. //! the [Struct Update Syntax] with `..Default::default()`, which may need a
  20. //! `#[allow(clippy::needless_update)]` attribute if you are declaring all fields.
  21. //!
  22. //! [ignore unknown fields when destructuring]: https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#ignoring-remaining-parts-of-a-value-with-
  23. //! [Struct Update Syntax]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax
  24. #[cfg(feature = "schema")]
  25. use schemars::JsonSchema;
  26. use semver::Version;
  27. use serde::{
  28. de::{Deserializer, Error as DeError, Visitor},
  29. Deserialize, Serialize, Serializer,
  30. };
  31. use serde_json::Value as JsonValue;
  32. use serde_untagged::UntaggedEnumVisitor;
  33. use serde_with::skip_serializing_none;
  34. use url::Url;
  35. use std::{
  36. collections::HashMap,
  37. fmt::{self, Display},
  38. fs::read_to_string,
  39. path::PathBuf,
  40. str::FromStr,
  41. };
  42. /// Items to help with parsing content into a [`Config`].
  43. pub mod parse;
  44. use crate::{acl::capability::Capability, TitleBarStyle, WindowEffect, WindowEffectState};
  45. pub use self::parse::parse;
  46. fn default_true() -> bool {
  47. true
  48. }
  49. /// An URL to open on a Tauri webview window.
  50. #[derive(PartialEq, Eq, Debug, Clone, Serialize)]
  51. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  52. #[serde(untagged)]
  53. #[non_exhaustive]
  54. pub enum WebviewUrl {
  55. /// An external URL. Must use either the `http` or `https` schemes.
  56. External(Url),
  57. /// The path portion of an app URL.
  58. /// For instance, to load `tauri://localhost/users/john`,
  59. /// you can simply provide `users/john` in this configuration.
  60. App(PathBuf),
  61. /// A custom protocol url, for example, `doom://index.html`
  62. CustomProtocol(Url),
  63. }
  64. impl<'de> Deserialize<'de> for WebviewUrl {
  65. fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
  66. where
  67. D: Deserializer<'de>,
  68. {
  69. #[derive(Deserialize)]
  70. #[serde(untagged)]
  71. enum WebviewUrlDeserializer {
  72. Url(Url),
  73. Path(PathBuf),
  74. }
  75. match WebviewUrlDeserializer::deserialize(deserializer)? {
  76. WebviewUrlDeserializer::Url(u) => {
  77. if u.scheme() == "https" || u.scheme() == "http" {
  78. Ok(Self::External(u))
  79. } else {
  80. Ok(Self::CustomProtocol(u))
  81. }
  82. }
  83. WebviewUrlDeserializer::Path(p) => Ok(Self::App(p)),
  84. }
  85. }
  86. }
  87. impl fmt::Display for WebviewUrl {
  88. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  89. match self {
  90. Self::External(url) | Self::CustomProtocol(url) => write!(f, "{url}"),
  91. Self::App(path) => write!(f, "{}", path.display()),
  92. }
  93. }
  94. }
  95. impl Default for WebviewUrl {
  96. fn default() -> Self {
  97. Self::App("index.html".into())
  98. }
  99. }
  100. /// A bundle referenced by tauri-bundler.
  101. #[derive(Debug, PartialEq, Eq, Clone)]
  102. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  103. #[cfg_attr(feature = "schema", schemars(rename_all = "lowercase"))]
  104. pub enum BundleType {
  105. /// The debian bundle (.deb).
  106. Deb,
  107. /// The RPM bundle (.rpm).
  108. Rpm,
  109. /// The AppImage bundle (.appimage).
  110. AppImage,
  111. /// The Microsoft Installer bundle (.msi).
  112. Msi,
  113. /// The NSIS bundle (.exe).
  114. Nsis,
  115. /// The macOS application bundle (.app).
  116. App,
  117. /// The Apple Disk Image bundle (.dmg).
  118. Dmg,
  119. }
  120. impl BundleType {
  121. /// All bundle types.
  122. fn all() -> &'static [Self] {
  123. &[
  124. BundleType::Deb,
  125. BundleType::Rpm,
  126. BundleType::AppImage,
  127. BundleType::Msi,
  128. BundleType::Nsis,
  129. BundleType::App,
  130. BundleType::Dmg,
  131. ]
  132. }
  133. }
  134. impl Display for BundleType {
  135. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  136. write!(
  137. f,
  138. "{}",
  139. match self {
  140. Self::Deb => "deb",
  141. Self::Rpm => "rpm",
  142. Self::AppImage => "appimage",
  143. Self::Msi => "msi",
  144. Self::Nsis => "nsis",
  145. Self::App => "app",
  146. Self::Dmg => "dmg",
  147. }
  148. )
  149. }
  150. }
  151. impl Serialize for BundleType {
  152. fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
  153. where
  154. S: Serializer,
  155. {
  156. serializer.serialize_str(self.to_string().as_ref())
  157. }
  158. }
  159. impl<'de> Deserialize<'de> for BundleType {
  160. fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
  161. where
  162. D: Deserializer<'de>,
  163. {
  164. let s = String::deserialize(deserializer)?;
  165. match s.to_lowercase().as_str() {
  166. "deb" => Ok(Self::Deb),
  167. "rpm" => Ok(Self::Rpm),
  168. "appimage" => Ok(Self::AppImage),
  169. "msi" => Ok(Self::Msi),
  170. "nsis" => Ok(Self::Nsis),
  171. "app" => Ok(Self::App),
  172. "dmg" => Ok(Self::Dmg),
  173. _ => Err(DeError::custom(format!("unknown bundle target '{s}'"))),
  174. }
  175. }
  176. }
  177. /// Targets to bundle. Each value is case insensitive.
  178. #[derive(Debug, PartialEq, Eq, Clone)]
  179. pub enum BundleTarget {
  180. /// Bundle all targets.
  181. All,
  182. /// A list of bundle targets.
  183. List(Vec<BundleType>),
  184. /// A single bundle target.
  185. One(BundleType),
  186. }
  187. #[cfg(feature = "schema")]
  188. impl schemars::JsonSchema for BundleTarget {
  189. fn schema_name() -> std::string::String {
  190. "BundleTarget".to_owned()
  191. }
  192. fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
  193. let any_of = vec![
  194. schemars::schema::SchemaObject {
  195. const_value: Some("all".into()),
  196. metadata: Some(Box::new(schemars::schema::Metadata {
  197. description: Some("Bundle all targets.".to_owned()),
  198. ..Default::default()
  199. })),
  200. ..Default::default()
  201. }
  202. .into(),
  203. schemars::_private::metadata::add_description(
  204. gen.subschema_for::<Vec<BundleType>>(),
  205. "A list of bundle targets.",
  206. ),
  207. schemars::_private::metadata::add_description(
  208. gen.subschema_for::<BundleType>(),
  209. "A single bundle target.",
  210. ),
  211. ];
  212. schemars::schema::SchemaObject {
  213. subschemas: Some(Box::new(schemars::schema::SubschemaValidation {
  214. any_of: Some(any_of),
  215. ..Default::default()
  216. })),
  217. metadata: Some(Box::new(schemars::schema::Metadata {
  218. description: Some("Targets to bundle. Each value is case insensitive.".to_owned()),
  219. ..Default::default()
  220. })),
  221. ..Default::default()
  222. }
  223. .into()
  224. }
  225. }
  226. impl Default for BundleTarget {
  227. fn default() -> Self {
  228. Self::All
  229. }
  230. }
  231. impl Serialize for BundleTarget {
  232. fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
  233. where
  234. S: Serializer,
  235. {
  236. match self {
  237. Self::All => serializer.serialize_str("all"),
  238. Self::List(l) => l.serialize(serializer),
  239. Self::One(t) => serializer.serialize_str(t.to_string().as_ref()),
  240. }
  241. }
  242. }
  243. impl<'de> Deserialize<'de> for BundleTarget {
  244. fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
  245. where
  246. D: Deserializer<'de>,
  247. {
  248. #[derive(Deserialize, Serialize)]
  249. #[serde(untagged)]
  250. pub enum BundleTargetInner {
  251. List(Vec<BundleType>),
  252. One(BundleType),
  253. All(String),
  254. }
  255. match BundleTargetInner::deserialize(deserializer)? {
  256. BundleTargetInner::All(s) if s.to_lowercase() == "all" => Ok(Self::All),
  257. BundleTargetInner::All(t) => Err(DeError::custom(format!(
  258. "invalid bundle type {t}, expected one of `all`, {}",
  259. BundleType::all()
  260. .iter()
  261. .map(|b| format!("`{b}`"))
  262. .collect::<Vec<_>>()
  263. .join(", ")
  264. ))),
  265. BundleTargetInner::List(l) => Ok(Self::List(l)),
  266. BundleTargetInner::One(t) => Ok(Self::One(t)),
  267. }
  268. }
  269. }
  270. impl BundleTarget {
  271. /// Gets the bundle targets as a [`Vec`]. The vector is empty when set to [`BundleTarget::All`].
  272. #[allow(dead_code)]
  273. pub fn to_vec(&self) -> Vec<BundleType> {
  274. match self {
  275. Self::All => BundleType::all().to_vec(),
  276. Self::List(list) => list.clone(),
  277. Self::One(i) => vec![i.clone()],
  278. }
  279. }
  280. }
  281. /// Configuration for AppImage bundles.
  282. ///
  283. /// See more: <https://tauri.app/v1/api/config#appimageconfig>
  284. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  285. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  286. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  287. pub struct AppImageConfig {
  288. /// Include additional gstreamer dependencies needed for audio and video playback.
  289. /// This increases the bundle size by ~15-35MB depending on your build system.
  290. #[serde(default, alias = "bundle-media-framework")]
  291. pub bundle_media_framework: bool,
  292. /// The files to include in the Appimage Binary.
  293. #[serde(default)]
  294. pub files: HashMap<PathBuf, PathBuf>,
  295. }
  296. /// Configuration for Debian (.deb) bundles.
  297. ///
  298. /// See more: <https://tauri.app/v1/api/config#debconfig>
  299. #[skip_serializing_none]
  300. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  301. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  302. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  303. pub struct DebConfig {
  304. /// The list of deb dependencies your application relies on.
  305. pub depends: Option<Vec<String>>,
  306. /// The list of dependencies the package provides.
  307. pub provides: Option<Vec<String>>,
  308. /// The list of package conflicts.
  309. pub conflicts: Option<Vec<String>>,
  310. /// The list of package replaces.
  311. pub replaces: Option<Vec<String>>,
  312. /// The files to include on the package.
  313. #[serde(default)]
  314. pub files: HashMap<PathBuf, PathBuf>,
  315. /// Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
  316. pub section: Option<String>,
  317. /// Change the priority of the Debian Package. By default, it is set to `optional`.
  318. /// Recognized Priorities as of now are : `required`, `important`, `standard`, `optional`, `extra`
  319. pub priority: Option<String>,
  320. /// Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See
  321. /// <https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes>
  322. pub changelog: Option<PathBuf>,
  323. /// Path to a custom desktop file Handlebars template.
  324. ///
  325. /// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
  326. #[serde(alias = "desktop-template")]
  327. pub desktop_template: Option<PathBuf>,
  328. /// Path to script that will be executed before the package is unpacked. See
  329. /// <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>
  330. #[serde(alias = "pre-install-script")]
  331. pub pre_install_script: Option<PathBuf>,
  332. /// Path to script that will be executed after the package is unpacked. See
  333. /// <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>
  334. #[serde(alias = "post-install-script")]
  335. pub post_install_script: Option<PathBuf>,
  336. /// Path to script that will be executed before the package is removed. See
  337. /// <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>
  338. #[serde(alias = "pre-remove-script")]
  339. pub pre_remove_script: Option<PathBuf>,
  340. /// Path to script that will be executed after the package is removed. See
  341. /// <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>
  342. #[serde(alias = "post-remove-script")]
  343. pub post_remove_script: Option<PathBuf>,
  344. }
  345. /// Configuration for Linux bundles.
  346. ///
  347. /// See more: <https://tauri.app/v1/api/config#linuxconfig>
  348. #[skip_serializing_none]
  349. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  350. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  351. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  352. pub struct LinuxConfig {
  353. /// Configuration for the AppImage bundle.
  354. #[serde(default)]
  355. pub appimage: AppImageConfig,
  356. /// Configuration for the Debian bundle.
  357. #[serde(default)]
  358. pub deb: DebConfig,
  359. /// Configuration for the RPM bundle.
  360. #[serde(default)]
  361. pub rpm: RpmConfig,
  362. }
  363. /// Configuration for RPM bundles.
  364. #[skip_serializing_none]
  365. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  366. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  367. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  368. pub struct RpmConfig {
  369. /// The list of RPM dependencies your application relies on.
  370. pub depends: Option<Vec<String>>,
  371. /// The list of RPM dependencies your application provides.
  372. pub provides: Option<Vec<String>>,
  373. /// The list of RPM dependencies your application conflicts with. They must not be present
  374. /// in order for the package to be installed.
  375. pub conflicts: Option<Vec<String>>,
  376. /// The list of RPM dependencies your application supersedes - if this package is installed,
  377. /// packages listed as "obsoletes" will be automatically removed (if they are present).
  378. pub obsoletes: Option<Vec<String>>,
  379. /// The RPM release tag.
  380. #[serde(default = "default_release")]
  381. pub release: String,
  382. /// The RPM epoch.
  383. #[serde(default)]
  384. pub epoch: u32,
  385. /// The files to include on the package.
  386. #[serde(default)]
  387. pub files: HashMap<PathBuf, PathBuf>,
  388. /// Path to a custom desktop file Handlebars template.
  389. ///
  390. /// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
  391. #[serde(alias = "desktop-template")]
  392. pub desktop_template: Option<PathBuf>,
  393. /// Path to script that will be executed before the package is unpacked. See
  394. /// <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>
  395. #[serde(alias = "pre-install-script")]
  396. pub pre_install_script: Option<PathBuf>,
  397. /// Path to script that will be executed after the package is unpacked. See
  398. /// <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>
  399. #[serde(alias = "post-install-script")]
  400. pub post_install_script: Option<PathBuf>,
  401. /// Path to script that will be executed before the package is removed. See
  402. /// <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>
  403. #[serde(alias = "pre-remove-script")]
  404. pub pre_remove_script: Option<PathBuf>,
  405. /// Path to script that will be executed after the package is removed. See
  406. /// <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>
  407. #[serde(alias = "post-remove-script")]
  408. pub post_remove_script: Option<PathBuf>,
  409. }
  410. impl Default for RpmConfig {
  411. fn default() -> Self {
  412. Self {
  413. depends: None,
  414. provides: None,
  415. conflicts: None,
  416. obsoletes: None,
  417. release: default_release(),
  418. epoch: 0,
  419. files: Default::default(),
  420. desktop_template: None,
  421. pre_install_script: None,
  422. post_install_script: None,
  423. pre_remove_script: None,
  424. post_remove_script: None,
  425. }
  426. }
  427. }
  428. fn default_release() -> String {
  429. "1".into()
  430. }
  431. /// Position coordinates struct.
  432. #[derive(Default, Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  433. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  434. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  435. pub struct Position {
  436. /// X coordinate.
  437. pub x: u32,
  438. /// Y coordinate.
  439. pub y: u32,
  440. }
  441. /// Size of the window.
  442. #[derive(Default, Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  443. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  444. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  445. pub struct Size {
  446. /// Width of the window.
  447. pub width: u32,
  448. /// Height of the window.
  449. pub height: u32,
  450. }
  451. /// Configuration for Apple Disk Image (.dmg) bundles.
  452. ///
  453. /// See more: <https://tauri.app/v1/api/config#dmgconfig>
  454. #[skip_serializing_none]
  455. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  456. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  457. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  458. pub struct DmgConfig {
  459. /// Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`.
  460. pub background: Option<PathBuf>,
  461. /// Position of volume window on screen.
  462. pub window_position: Option<Position>,
  463. /// Size of volume window.
  464. #[serde(default = "dmg_window_size", alias = "window-size")]
  465. pub window_size: Size,
  466. /// Position of app file on window.
  467. #[serde(default = "dmg_app_position", alias = "app-position")]
  468. pub app_position: Position,
  469. /// Position of application folder on window.
  470. #[serde(
  471. default = "dmg_application_folder_position",
  472. alias = "application-folder-position"
  473. )]
  474. pub application_folder_position: Position,
  475. }
  476. impl Default for DmgConfig {
  477. fn default() -> Self {
  478. Self {
  479. background: None,
  480. window_position: None,
  481. window_size: dmg_window_size(),
  482. app_position: dmg_app_position(),
  483. application_folder_position: dmg_application_folder_position(),
  484. }
  485. }
  486. }
  487. fn dmg_window_size() -> Size {
  488. Size {
  489. width: 660,
  490. height: 400,
  491. }
  492. }
  493. fn dmg_app_position() -> Position {
  494. Position { x: 180, y: 170 }
  495. }
  496. fn dmg_application_folder_position() -> Position {
  497. Position { x: 480, y: 170 }
  498. }
  499. fn de_macos_minimum_system_version<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
  500. where
  501. D: Deserializer<'de>,
  502. {
  503. let version = Option::<String>::deserialize(deserializer)?;
  504. match version {
  505. Some(v) if v.is_empty() => Ok(macos_minimum_system_version()),
  506. e => Ok(e),
  507. }
  508. }
  509. /// Configuration for the macOS bundles.
  510. ///
  511. /// See more: <https://tauri.app/v1/api/config#macconfig>
  512. #[skip_serializing_none]
  513. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  514. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  515. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  516. pub struct MacConfig {
  517. /// A list of strings indicating any macOS X frameworks that need to be bundled with the application.
  518. ///
  519. /// If a name is used, ".framework" must be omitted and it will look for standard install locations. You may also use a path to a specific framework.
  520. pub frameworks: Option<Vec<String>>,
  521. /// The files to include in the application relative to the Contents directory.
  522. #[serde(default)]
  523. pub files: HashMap<PathBuf, PathBuf>,
  524. /// A version string indicating the minimum macOS X version that the bundled application supports. Defaults to `10.13`.
  525. ///
  526. /// Setting it to `null` completely removes the `LSMinimumSystemVersion` field on the bundle's `Info.plist`
  527. /// and the `MACOSX_DEPLOYMENT_TARGET` environment variable.
  528. ///
  529. /// An empty string is considered an invalid value so the default value is used.
  530. #[serde(
  531. deserialize_with = "de_macos_minimum_system_version",
  532. default = "macos_minimum_system_version",
  533. alias = "minimum-system-version"
  534. )]
  535. pub minimum_system_version: Option<String>,
  536. /// Allows your application to communicate with the outside world.
  537. /// It should be a lowercase, without port and protocol domain name.
  538. #[serde(alias = "exception-domain")]
  539. pub exception_domain: Option<String>,
  540. /// Identity to use for code signing.
  541. #[serde(alias = "signing-identity")]
  542. pub signing_identity: Option<String>,
  543. /// Whether the codesign should enable [hardened runtime] (for executables) or not.
  544. ///
  545. /// [hardened runtime]: <https://developer.apple.com/documentation/security/hardened_runtime>
  546. #[serde(alias = "hardened-runtime", default = "default_true")]
  547. pub hardened_runtime: bool,
  548. /// Provider short name for notarization.
  549. #[serde(alias = "provider-short-name")]
  550. pub provider_short_name: Option<String>,
  551. /// Path to the entitlements file.
  552. pub entitlements: Option<String>,
  553. /// DMG-specific settings.
  554. #[serde(default)]
  555. pub dmg: DmgConfig,
  556. }
  557. impl Default for MacConfig {
  558. fn default() -> Self {
  559. Self {
  560. frameworks: None,
  561. files: HashMap::new(),
  562. minimum_system_version: macos_minimum_system_version(),
  563. exception_domain: None,
  564. signing_identity: None,
  565. hardened_runtime: true,
  566. provider_short_name: None,
  567. entitlements: None,
  568. dmg: Default::default(),
  569. }
  570. }
  571. }
  572. fn macos_minimum_system_version() -> Option<String> {
  573. Some("10.13".into())
  574. }
  575. fn ios_minimum_system_version() -> String {
  576. "13.0".into()
  577. }
  578. /// Configuration for a target language for the WiX build.
  579. ///
  580. /// See more: <https://tauri.app/v1/api/config#wixlanguageconfig>
  581. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  582. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  583. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  584. pub struct WixLanguageConfig {
  585. /// The path to a locale (`.wxl`) file. See <https://wixtoolset.org/documentation/manual/v3/howtos/ui_and_localization/build_a_localized_version.html>.
  586. #[serde(alias = "locale-path")]
  587. pub locale_path: Option<String>,
  588. }
  589. /// The languages to build using WiX.
  590. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  591. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  592. #[serde(untagged)]
  593. pub enum WixLanguage {
  594. /// A single language to build, without configuration.
  595. One(String),
  596. /// A list of languages to build, without configuration.
  597. List(Vec<String>),
  598. /// A map of languages and its configuration.
  599. Localized(HashMap<String, WixLanguageConfig>),
  600. }
  601. impl Default for WixLanguage {
  602. fn default() -> Self {
  603. Self::One("en-US".into())
  604. }
  605. }
  606. /// Configuration for the MSI bundle using WiX.
  607. ///
  608. /// See more: <https://tauri.app/v1/api/config#wixconfig>
  609. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  610. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  611. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  612. pub struct WixConfig {
  613. /// The installer languages to build. See <https://docs.microsoft.com/en-us/windows/win32/msi/localizing-the-error-and-actiontext-tables>.
  614. #[serde(default)]
  615. pub language: WixLanguage,
  616. /// A custom .wxs template to use.
  617. pub template: Option<PathBuf>,
  618. /// A list of paths to .wxs files with WiX fragments to use.
  619. #[serde(default, alias = "fragment-paths")]
  620. pub fragment_paths: Vec<PathBuf>,
  621. /// The ComponentGroup element ids you want to reference from the fragments.
  622. #[serde(default, alias = "component-group-refs")]
  623. pub component_group_refs: Vec<String>,
  624. /// The Component element ids you want to reference from the fragments.
  625. #[serde(default, alias = "component-refs")]
  626. pub component_refs: Vec<String>,
  627. /// The FeatureGroup element ids you want to reference from the fragments.
  628. #[serde(default, alias = "feature-group-refs")]
  629. pub feature_group_refs: Vec<String>,
  630. /// The Feature element ids you want to reference from the fragments.
  631. #[serde(default, alias = "feature-refs")]
  632. pub feature_refs: Vec<String>,
  633. /// The Merge element ids you want to reference from the fragments.
  634. #[serde(default, alias = "merge-refs")]
  635. pub merge_refs: Vec<String>,
  636. /// Create an elevated update task within Windows Task Scheduler.
  637. #[serde(default, alias = "enable-elevated-update-task")]
  638. pub enable_elevated_update_task: bool,
  639. /// Path to a bitmap file to use as the installation user interface banner.
  640. /// This bitmap will appear at the top of all but the first page of the installer.
  641. ///
  642. /// The required dimensions are 493px × 58px.
  643. #[serde(alias = "banner-path")]
  644. pub banner_path: Option<PathBuf>,
  645. /// Path to a bitmap file to use on the installation user interface dialogs.
  646. /// It is used on the welcome and completion dialogs.
  647. /// The required dimensions are 493px × 312px.
  648. #[serde(alias = "dialog-image-path")]
  649. pub dialog_image_path: Option<PathBuf>,
  650. }
  651. /// Compression algorithms used in the NSIS installer.
  652. ///
  653. /// See <https://nsis.sourceforge.io/Reference/SetCompressor>
  654. #[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
  655. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  656. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  657. pub enum NsisCompression {
  658. /// ZLIB uses the deflate algorithm, it is a quick and simple method. With the default compression level it uses about 300 KB of memory.
  659. Zlib,
  660. /// BZIP2 usually gives better compression ratios than ZLIB, but it is a bit slower and uses more memory. With the default compression level it uses about 4 MB of memory.
  661. Bzip2,
  662. /// LZMA (default) is a new compression method that gives very good compression ratios. The decompression speed is high (10-20 MB/s on a 2 GHz CPU), the compression speed is lower. The memory size that will be used for decompression is the dictionary size plus a few KBs, the default is 8 MB.
  663. Lzma,
  664. /// Disable compression
  665. None,
  666. }
  667. impl Default for NsisCompression {
  668. fn default() -> Self {
  669. Self::Lzma
  670. }
  671. }
  672. /// Install Modes for the NSIS installer.
  673. #[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
  674. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  675. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  676. pub enum NSISInstallerMode {
  677. /// Default mode for the installer.
  678. ///
  679. /// Install the app by default in a directory that doesn't require Administrator access.
  680. ///
  681. /// Installer metadata will be saved under the `HKCU` registry path.
  682. CurrentUser,
  683. /// Install the app by default in the `Program Files` folder directory requires Administrator
  684. /// access for the installation.
  685. ///
  686. /// Installer metadata will be saved under the `HKLM` registry path.
  687. PerMachine,
  688. /// Combines both modes and allows the user to choose at install time
  689. /// whether to install for the current user or per machine. Note that this mode
  690. /// will require Administrator access even if the user wants to install it for the current user only.
  691. ///
  692. /// Installer metadata will be saved under the `HKLM` or `HKCU` registry path based on the user's choice.
  693. Both,
  694. }
  695. impl Default for NSISInstallerMode {
  696. fn default() -> Self {
  697. Self::CurrentUser
  698. }
  699. }
  700. /// Configuration for the Installer bundle using NSIS.
  701. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  702. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  703. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  704. pub struct NsisConfig {
  705. /// A custom .nsi template to use.
  706. pub template: Option<PathBuf>,
  707. /// The path to a bitmap file to display on the header of installers pages.
  708. ///
  709. /// The recommended dimensions are 150px x 57px.
  710. #[serde(alias = "header-image")]
  711. pub header_image: Option<PathBuf>,
  712. /// The path to a bitmap file for the Welcome page and the Finish page.
  713. ///
  714. /// The recommended dimensions are 164px x 314px.
  715. #[serde(alias = "sidebar-image")]
  716. pub sidebar_image: Option<PathBuf>,
  717. /// The path to an icon file used as the installer icon.
  718. #[serde(alias = "install-icon")]
  719. pub installer_icon: Option<PathBuf>,
  720. /// Whether the installation will be for all users or just the current user.
  721. #[serde(default, alias = "install-mode")]
  722. pub install_mode: NSISInstallerMode,
  723. /// A list of installer languages.
  724. /// By default the OS language is used. If the OS language is not in the list of languages, the first language will be used.
  725. /// To allow the user to select the language, set `display_language_selector` to `true`.
  726. ///
  727. /// See <https://github.com/kichik/nsis/tree/9465c08046f00ccb6eda985abbdbf52c275c6c4d/Contrib/Language%20files> for the complete list of languages.
  728. pub languages: Option<Vec<String>>,
  729. /// A key-value pair where the key is the language and the
  730. /// value is the path to a custom `.nsh` file that holds the translated text for tauri's custom messages.
  731. ///
  732. /// See <https://github.com/tauri-apps/tauri/blob/dev/crates/tauri-bundler/src/bundle/windows/templates/nsis-languages/English.nsh> for an example `.nsh` file.
  733. ///
  734. /// **Note**: the key must be a valid NSIS language and it must be added to [`NsisConfig`] languages array,
  735. pub custom_language_files: Option<HashMap<String, PathBuf>>,
  736. /// Whether to display a language selector dialog before the installer and uninstaller windows are rendered or not.
  737. /// By default the OS language is selected, with a fallback to the first language in the `languages` array.
  738. #[serde(default, alias = "display-language-selector")]
  739. pub display_language_selector: bool,
  740. /// Set the compression algorithm used to compress files in the installer.
  741. ///
  742. /// See <https://nsis.sourceforge.io/Reference/SetCompressor>
  743. #[serde(default)]
  744. pub compression: NsisCompression,
  745. /// Set the folder name for the start menu shortcut.
  746. ///
  747. /// Use this option if you have multiple apps and wish to group their shortcuts under one folder
  748. /// or if you generally prefer to set your shortcut inside a folder.
  749. ///
  750. /// Examples:
  751. /// - `AwesomePublisher`, shortcut will be placed in `%AppData%\Microsoft\Windows\Start Menu\Programs\AwesomePublisher\<your-app>.lnk`
  752. /// - If unset, shortcut will be placed in `%AppData%\Microsoft\Windows\Start Menu\Programs\<your-app>.lnk`
  753. #[serde(alias = "start-menu-folder")]
  754. pub start_menu_folder: Option<String>,
  755. /// A path to a `.nsh` file that contains special NSIS macros to be hooked into the
  756. /// main installer.nsi script.
  757. ///
  758. /// Supported hooks are:
  759. /// - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.
  760. /// - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.
  761. /// - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.
  762. /// - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.
  763. ///
  764. ///
  765. /// ### Example
  766. ///
  767. /// ```nsh
  768. /// !macro NSIS_HOOK_PREINSTALL
  769. /// MessageBox MB_OK "PreInstall"
  770. /// !macroend
  771. ///
  772. /// !macro NSIS_HOOK_POSTINSTALL
  773. /// MessageBox MB_OK "PostInstall"
  774. /// !macroend
  775. ///
  776. /// !macro NSIS_HOOK_PREUNINSTALL
  777. /// MessageBox MB_OK "PreUnInstall"
  778. /// !macroend
  779. ///
  780. /// !macro NSIS_HOOK_POSTUNINSTALL
  781. /// MessageBox MB_OK "PostUninstall"
  782. /// !macroend
  783. ///
  784. /// ```
  785. #[serde(alias = "installer-hooks")]
  786. pub installer_hooks: Option<PathBuf>,
  787. /// Try to ensure that the WebView2 version is equal to or newer than this version,
  788. /// if the user's WebView2 is older than this version,
  789. /// the installer will try to trigger a WebView2 update.
  790. #[serde(alias = "minimum-webview2-version")]
  791. pub minimum_webview2_version: Option<String>,
  792. }
  793. /// Install modes for the Webview2 runtime.
  794. /// Note that for the updater bundle [`Self::DownloadBootstrapper`] is used.
  795. ///
  796. /// For more information see <https://tauri.app/v1/guides/building/windows>.
  797. #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
  798. #[serde(tag = "type", rename_all = "camelCase", deny_unknown_fields)]
  799. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  800. pub enum WebviewInstallMode {
  801. /// Do not install the Webview2 as part of the Windows Installer.
  802. Skip,
  803. /// Download the bootstrapper and run it.
  804. /// Requires an internet connection.
  805. /// Results in a smaller installer size, but is not recommended on Windows 7.
  806. DownloadBootstrapper {
  807. /// Instructs the installer to run the bootstrapper in silent mode. Defaults to `true`.
  808. #[serde(default = "default_true")]
  809. silent: bool,
  810. },
  811. /// Embed the bootstrapper and run it.
  812. /// Requires an internet connection.
  813. /// Increases the installer size by around 1.8MB, but offers better support on Windows 7.
  814. EmbedBootstrapper {
  815. /// Instructs the installer to run the bootstrapper in silent mode. Defaults to `true`.
  816. #[serde(default = "default_true")]
  817. silent: bool,
  818. },
  819. /// Embed the offline installer and run it.
  820. /// Does not require an internet connection.
  821. /// Increases the installer size by around 127MB.
  822. OfflineInstaller {
  823. /// Instructs the installer to run the installer in silent mode. Defaults to `true`.
  824. #[serde(default = "default_true")]
  825. silent: bool,
  826. },
  827. /// Embed a fixed webview2 version and use it at runtime.
  828. /// Increases the installer size by around 180MB.
  829. FixedRuntime {
  830. /// The path to the fixed runtime to use.
  831. ///
  832. /// The fixed version can be downloaded [on the official website](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section).
  833. /// The `.cab` file must be extracted to a folder and this folder path must be defined on this field.
  834. path: PathBuf,
  835. },
  836. }
  837. impl Default for WebviewInstallMode {
  838. fn default() -> Self {
  839. Self::DownloadBootstrapper { silent: true }
  840. }
  841. }
  842. /// Custom Signing Command configuration.
  843. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  844. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  845. #[serde(rename_all = "camelCase", deny_unknown_fields, untagged)]
  846. pub enum CustomSignCommandConfig {
  847. /// A string notation of the script to execute.
  848. ///
  849. /// "%1" will be replaced with the path to the binary to be signed.
  850. ///
  851. /// This is a simpler notation for the command.
  852. /// Tauri will split the string with `' '` and use the first element as the command name and the rest as arguments.
  853. ///
  854. /// If you need to use whitespace in the command or arguments, use the object notation [`Self::ScriptWithOptions`].
  855. Command(String),
  856. /// An object notation of the command.
  857. ///
  858. /// This is more complex notation for the command but
  859. /// this allows you to use whitespace in the command and arguments.
  860. CommandWithOptions {
  861. /// The command to run to sign the binary.
  862. cmd: String,
  863. /// The arguments to pass to the command.
  864. ///
  865. /// "%1" will be replaced with the path to the binary to be signed.
  866. args: Vec<String>,
  867. },
  868. }
  869. /// Windows bundler configuration.
  870. ///
  871. /// See more: <https://tauri.app/v1/api/config#windowsconfig>
  872. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  873. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  874. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  875. pub struct WindowsConfig {
  876. /// Specifies the file digest algorithm to use for creating file signatures.
  877. /// Required for code signing. SHA-256 is recommended.
  878. #[serde(alias = "digest-algorithm")]
  879. pub digest_algorithm: Option<String>,
  880. /// Specifies the SHA1 hash of the signing certificate.
  881. #[serde(alias = "certificate-thumbprint")]
  882. pub certificate_thumbprint: Option<String>,
  883. /// Server to use during timestamping.
  884. #[serde(alias = "timestamp-url")]
  885. pub timestamp_url: Option<String>,
  886. /// Whether to use Time-Stamp Protocol (TSP, a.k.a. RFC 3161) for the timestamp server. Your code signing provider may
  887. /// use a TSP timestamp server, like e.g. SSL.com does. If so, enable TSP by setting to true.
  888. #[serde(default)]
  889. pub tsp: bool,
  890. /// The installation mode for the Webview2 runtime.
  891. #[serde(default, alias = "webview-install-mode")]
  892. pub webview_install_mode: WebviewInstallMode,
  893. /// Validates a second app installation, blocking the user from installing an older version if set to `false`.
  894. ///
  895. /// For instance, if `1.2.1` is installed, the user won't be able to install app version `1.2.0` or `1.1.5`.
  896. ///
  897. /// The default value of this flag is `true`.
  898. #[serde(default = "default_true", alias = "allow-downgrades")]
  899. pub allow_downgrades: bool,
  900. /// Configuration for the MSI generated with WiX.
  901. pub wix: Option<WixConfig>,
  902. /// Configuration for the installer generated with NSIS.
  903. pub nsis: Option<NsisConfig>,
  904. /// Specify a custom command to sign the binaries.
  905. /// This command needs to have a `%1` in args which is just a placeholder for the binary path,
  906. /// which we will detect and replace before calling the command.
  907. ///
  908. /// By Default we use `signtool.exe` which can be found only on Windows so
  909. /// if you are on another platform and want to cross-compile and sign you will
  910. /// need to use another tool like `osslsigncode`.
  911. #[serde(alias = "sign-command")]
  912. pub sign_command: Option<CustomSignCommandConfig>,
  913. }
  914. impl Default for WindowsConfig {
  915. fn default() -> Self {
  916. Self {
  917. digest_algorithm: None,
  918. certificate_thumbprint: None,
  919. timestamp_url: None,
  920. tsp: false,
  921. webview_install_mode: Default::default(),
  922. allow_downgrades: true,
  923. wix: None,
  924. nsis: None,
  925. sign_command: None,
  926. }
  927. }
  928. }
  929. /// macOS-only. Corresponds to CFBundleTypeRole
  930. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  931. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  932. pub enum BundleTypeRole {
  933. /// CFBundleTypeRole.Editor. Files can be read and edited.
  934. #[default]
  935. Editor,
  936. /// CFBundleTypeRole.Viewer. Files can be read.
  937. Viewer,
  938. /// CFBundleTypeRole.Shell
  939. Shell,
  940. /// CFBundleTypeRole.QLGenerator
  941. QLGenerator,
  942. /// CFBundleTypeRole.None
  943. None,
  944. }
  945. impl Display for BundleTypeRole {
  946. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  947. match self {
  948. Self::Editor => write!(f, "Editor"),
  949. Self::Viewer => write!(f, "Viewer"),
  950. Self::Shell => write!(f, "Shell"),
  951. Self::QLGenerator => write!(f, "QLGenerator"),
  952. Self::None => write!(f, "None"),
  953. }
  954. }
  955. }
  956. /// An extension for a [`FileAssociation`].
  957. ///
  958. /// A leading `.` is automatically stripped.
  959. #[derive(Debug, PartialEq, Eq, Clone, Serialize)]
  960. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  961. pub struct AssociationExt(pub String);
  962. impl fmt::Display for AssociationExt {
  963. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  964. write!(f, "{}", self.0)
  965. }
  966. }
  967. impl<'d> serde::Deserialize<'d> for AssociationExt {
  968. fn deserialize<D: Deserializer<'d>>(deserializer: D) -> Result<Self, D::Error> {
  969. let ext = String::deserialize(deserializer)?;
  970. if let Some(ext) = ext.strip_prefix('.') {
  971. Ok(AssociationExt(ext.into()))
  972. } else {
  973. Ok(AssociationExt(ext))
  974. }
  975. }
  976. }
  977. /// File association
  978. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  979. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  980. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  981. pub struct FileAssociation {
  982. /// File extensions to associate with this app. e.g. 'png'
  983. pub ext: Vec<AssociationExt>,
  984. /// The name. Maps to `CFBundleTypeName` on macOS. Default to `ext[0]`
  985. pub name: Option<String>,
  986. /// The association description. Windows-only. It is displayed on the `Type` column on Windows Explorer.
  987. pub description: Option<String>,
  988. /// The app's role with respect to the type. Maps to `CFBundleTypeRole` on macOS.
  989. #[serde(default)]
  990. pub role: BundleTypeRole,
  991. /// The mime-type e.g. 'image/png' or 'text/plain'. Linux-only.
  992. #[serde(alias = "mime-type")]
  993. pub mime_type: Option<String>,
  994. }
  995. /// Deep link protocol configuration.
  996. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  997. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  998. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  999. pub struct DeepLinkProtocol {
  1000. /// URL schemes to associate with this app without `://`. For example `my-app`
  1001. pub schemes: Vec<String>,
  1002. /// The protocol name. **macOS-only** and maps to `CFBundleTypeName`. Defaults to `<bundle-id>.<schemes[0]>`
  1003. pub name: Option<String>,
  1004. /// The app's role for these schemes. **macOS-only** and maps to `CFBundleTypeRole`.
  1005. #[serde(default)]
  1006. pub role: BundleTypeRole,
  1007. }
  1008. /// Definition for bundle resources.
  1009. /// Can be either a list of paths to include or a map of source to target paths.
  1010. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1011. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1012. #[serde(rename_all = "camelCase", deny_unknown_fields, untagged)]
  1013. pub enum BundleResources {
  1014. /// A list of paths to include.
  1015. List(Vec<String>),
  1016. /// A map of source to target paths.
  1017. Map(HashMap<String, String>),
  1018. }
  1019. impl BundleResources {
  1020. /// Adds a path to the resource collection.
  1021. pub fn push(&mut self, path: impl Into<String>) {
  1022. match self {
  1023. Self::List(l) => l.push(path.into()),
  1024. Self::Map(l) => {
  1025. let path = path.into();
  1026. l.insert(path.clone(), path);
  1027. }
  1028. }
  1029. }
  1030. }
  1031. /// Updater type
  1032. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1033. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1034. #[serde(rename_all = "camelCase", deny_unknown_fields, untagged)]
  1035. pub enum Updater {
  1036. /// Generates lagacy zipped v1 compatible updaters
  1037. String(V1Compatible),
  1038. /// Produce updaters and their signatures or not
  1039. // Can't use untagged on enum field here: https://github.com/GREsau/schemars/issues/222
  1040. Bool(bool),
  1041. }
  1042. impl Default for Updater {
  1043. fn default() -> Self {
  1044. Self::Bool(false)
  1045. }
  1046. }
  1047. /// Generates lagacy zipped v1 compatible updaters
  1048. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1049. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1050. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1051. pub enum V1Compatible {
  1052. /// Generates lagacy zipped v1 compatible updaters
  1053. V1Compatible,
  1054. }
  1055. /// Configuration for tauri-bundler.
  1056. ///
  1057. /// See more: <https://tauri.app/v1/api/config#bundleconfig>
  1058. #[skip_serializing_none]
  1059. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1060. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1061. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1062. pub struct BundleConfig {
  1063. /// Whether Tauri should bundle your application or just output the executable.
  1064. #[serde(default)]
  1065. pub active: bool,
  1066. /// The bundle targets, currently supports ["deb", "rpm", "appimage", "nsis", "msi", "app", "dmg"] or "all".
  1067. #[serde(default)]
  1068. pub targets: BundleTarget,
  1069. #[serde(default)]
  1070. /// Produce updaters and their signatures or not
  1071. pub create_updater_artifacts: Updater,
  1072. /// The application's publisher. Defaults to the second element in the identifier string.
  1073. ///
  1074. /// Currently maps to the Manufacturer property of the Windows Installer
  1075. /// and the Maintainer field of debian packages if the Cargo.toml does not have the authors field.
  1076. pub publisher: Option<String>,
  1077. /// A url to the home page of your application. If unset, will
  1078. /// fallback to `homepage` defined in `Cargo.toml`.
  1079. ///
  1080. /// Supported bundle targets: `deb`, `rpm`, `nsis` and `msi`.
  1081. pub homepage: Option<String>,
  1082. /// The app's icons
  1083. #[serde(default)]
  1084. pub icon: Vec<String>,
  1085. /// App resources to bundle.
  1086. /// Each resource is a path to a file or directory.
  1087. /// Glob patterns are supported.
  1088. pub resources: Option<BundleResources>,
  1089. /// A copyright string associated with your application.
  1090. pub copyright: Option<String>,
  1091. /// The package's license identifier to be included in the appropriate bundles.
  1092. /// If not set, defaults to the license from the Cargo.toml file.
  1093. pub license: Option<String>,
  1094. /// The path to the license file to be included in the appropriate bundles.
  1095. #[serde(alias = "license-file")]
  1096. pub license_file: Option<PathBuf>,
  1097. /// The application kind.
  1098. ///
  1099. /// Should be one of the following:
  1100. /// Business, DeveloperTool, Education, Entertainment, Finance, Game, ActionGame, AdventureGame, ArcadeGame, BoardGame, CardGame, CasinoGame, DiceGame, EducationalGame, FamilyGame, KidsGame, MusicGame, PuzzleGame, RacingGame, RolePlayingGame, SimulationGame, SportsGame, StrategyGame, TriviaGame, WordGame, GraphicsAndDesign, HealthcareAndFitness, Lifestyle, Medical, Music, News, Photography, Productivity, Reference, SocialNetworking, Sports, Travel, Utility, Video, Weather.
  1101. pub category: Option<String>,
  1102. /// File associations to application.
  1103. pub file_associations: Option<Vec<FileAssociation>>,
  1104. /// A short description of your application.
  1105. #[serde(alias = "short-description")]
  1106. pub short_description: Option<String>,
  1107. /// A longer, multi-line description of the application.
  1108. #[serde(alias = "long-description")]
  1109. pub long_description: Option<String>,
  1110. /// Whether to use the project's `target` directory, for caching build tools (e.g., Wix and NSIS) when building this application. Defaults to `false`.
  1111. ///
  1112. /// If true, tools will be cached in `target\.tauri-tools`.
  1113. /// If false, tools will be cached in the current user's platform-specific cache directory.
  1114. ///
  1115. /// An example where it can be appropriate to set this to `true` is when building this application as a Windows System user (e.g., AWS EC2 workloads),
  1116. /// because the Window system's app data directory is restricted.
  1117. #[serde(default, alias = "use-local-tools-dir")]
  1118. pub use_local_tools_dir: bool,
  1119. /// A list of—either absolute or relative—paths to binaries to embed with your application.
  1120. ///
  1121. /// Note that Tauri will look for system-specific binaries following the pattern "binary-name{-target-triple}{.system-extension}".
  1122. ///
  1123. /// E.g. for the external binary "my-binary", Tauri looks for:
  1124. ///
  1125. /// - "my-binary-x86_64-pc-windows-msvc.exe" for Windows
  1126. /// - "my-binary-x86_64-apple-darwin" for macOS
  1127. /// - "my-binary-x86_64-unknown-linux-gnu" for Linux
  1128. ///
  1129. /// so don't forget to provide binaries for all targeted platforms.
  1130. #[serde(alias = "external-bin")]
  1131. pub external_bin: Option<Vec<String>>,
  1132. /// Configuration for the Windows bundles.
  1133. #[serde(default)]
  1134. pub windows: WindowsConfig,
  1135. /// Configuration for the Linux bundles.
  1136. #[serde(default)]
  1137. pub linux: LinuxConfig,
  1138. /// Configuration for the macOS bundles.
  1139. #[serde(rename = "macOS", alias = "macos", default)]
  1140. pub macos: MacConfig,
  1141. /// iOS configuration.
  1142. #[serde(rename = "iOS", alias = "ios", default)]
  1143. pub ios: IosConfig,
  1144. /// Android configuration.
  1145. #[serde(default)]
  1146. pub android: AndroidConfig,
  1147. }
  1148. /// a tuple struct of RGBA colors. Each value has minimum of 0 and maximum of 255.
  1149. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, Default)]
  1150. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1151. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1152. pub struct Color(pub u8, pub u8, pub u8, pub u8);
  1153. impl From<Color> for (u8, u8, u8, u8) {
  1154. fn from(value: Color) -> Self {
  1155. (value.0, value.1, value.2, value.3)
  1156. }
  1157. }
  1158. /// The window effects configuration object
  1159. #[skip_serializing_none]
  1160. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize, Default)]
  1161. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1162. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1163. pub struct WindowEffectsConfig {
  1164. /// List of Window effects to apply to the Window.
  1165. /// Conflicting effects will apply the first one and ignore the rest.
  1166. pub effects: Vec<WindowEffect>,
  1167. /// Window effect state **macOS Only**
  1168. pub state: Option<WindowEffectState>,
  1169. /// Window effect corner radius **macOS Only**
  1170. pub radius: Option<f64>,
  1171. /// Window effect color. Affects [`WindowEffect::Blur`] and [`WindowEffect::Acrylic`] only
  1172. /// on Windows 10 v1903+. Doesn't have any effect on Windows 7 or Windows 11.
  1173. pub color: Option<Color>,
  1174. }
  1175. /// The window configuration object.
  1176. ///
  1177. /// See more: <https://tauri.app/v1/api/config#windowconfig>
  1178. #[skip_serializing_none]
  1179. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  1180. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1181. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1182. pub struct WindowConfig {
  1183. /// The window identifier. It must be alphanumeric.
  1184. #[serde(default = "default_window_label")]
  1185. pub label: String,
  1186. /// Whether Tauri should create this window at app startup or not.
  1187. ///
  1188. /// When this is set to `false` you must manually grab the config object via `app.config().app.windows`
  1189. /// and create it with [`WebviewWindowBuilder::from_config`](https://docs.rs/tauri/2.0.0-rc/tauri/webview/struct.WebviewWindowBuilder.html#method.from_config).
  1190. #[serde(default = "default_true")]
  1191. pub create: bool,
  1192. /// The window webview URL.
  1193. #[serde(default)]
  1194. pub url: WebviewUrl,
  1195. /// The user agent for the webview
  1196. #[serde(alias = "user-agent")]
  1197. pub user_agent: Option<String>,
  1198. /// Whether the drag and drop is enabled or not on the webview. By default it is enabled.
  1199. ///
  1200. /// Disabling it is required to use HTML5 drag and drop on the frontend on Windows.
  1201. #[serde(default = "default_true", alias = "drag-drop-enabled")]
  1202. pub drag_drop_enabled: bool,
  1203. /// Whether or not the window starts centered or not.
  1204. #[serde(default)]
  1205. pub center: bool,
  1206. /// The horizontal position of the window's top left corner
  1207. pub x: Option<f64>,
  1208. /// The vertical position of the window's top left corner
  1209. pub y: Option<f64>,
  1210. /// The window width.
  1211. #[serde(default = "default_width")]
  1212. pub width: f64,
  1213. /// The window height.
  1214. #[serde(default = "default_height")]
  1215. pub height: f64,
  1216. /// The min window width.
  1217. #[serde(alias = "min-width")]
  1218. pub min_width: Option<f64>,
  1219. /// The min window height.
  1220. #[serde(alias = "min-height")]
  1221. pub min_height: Option<f64>,
  1222. /// The max window width.
  1223. #[serde(alias = "max-width")]
  1224. pub max_width: Option<f64>,
  1225. /// The max window height.
  1226. #[serde(alias = "max-height")]
  1227. pub max_height: Option<f64>,
  1228. /// Whether the window is resizable or not. When resizable is set to false, native window's maximize button is automatically disabled.
  1229. #[serde(default = "default_true")]
  1230. pub resizable: bool,
  1231. /// Whether the window's native maximize button is enabled or not.
  1232. /// If resizable is set to false, this setting is ignored.
  1233. ///
  1234. /// ## Platform-specific
  1235. ///
  1236. /// - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode.
  1237. /// - **Linux / iOS / Android:** Unsupported.
  1238. #[serde(default = "default_true")]
  1239. pub maximizable: bool,
  1240. /// Whether the window's native minimize button is enabled or not.
  1241. ///
  1242. /// ## Platform-specific
  1243. ///
  1244. /// - **Linux / iOS / Android:** Unsupported.
  1245. #[serde(default = "default_true")]
  1246. pub minimizable: bool,
  1247. /// Whether the window's native close button is enabled or not.
  1248. ///
  1249. /// ## Platform-specific
  1250. ///
  1251. /// - **Linux:** "GTK+ will do its best to convince the window manager not to show a close button.
  1252. /// Depending on the system, this function may not have any effect when called on a window that is already visible"
  1253. /// - **iOS / Android:** Unsupported.
  1254. #[serde(default = "default_true")]
  1255. pub closable: bool,
  1256. /// The window title.
  1257. #[serde(default = "default_title")]
  1258. pub title: String,
  1259. /// Whether the window starts as fullscreen or not.
  1260. #[serde(default)]
  1261. pub fullscreen: bool,
  1262. /// Whether the window will be initially focused or not.
  1263. #[serde(default = "default_true")]
  1264. pub focus: bool,
  1265. /// Whether the window is transparent or not.
  1266. ///
  1267. /// Note that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri > macOSPrivateApi`.
  1268. /// WARNING: Using private APIs on `macOS` prevents your application from being accepted to the `App Store`.
  1269. #[serde(default)]
  1270. pub transparent: bool,
  1271. /// Whether the window is maximized or not.
  1272. #[serde(default)]
  1273. pub maximized: bool,
  1274. /// Whether the window is visible or not.
  1275. #[serde(default = "default_true")]
  1276. pub visible: bool,
  1277. /// Whether the window should have borders and bars.
  1278. #[serde(default = "default_true")]
  1279. pub decorations: bool,
  1280. /// Whether the window should always be below other windows.
  1281. #[serde(default, alias = "always-on-bottom")]
  1282. pub always_on_bottom: bool,
  1283. /// Whether the window should always be on top of other windows.
  1284. #[serde(default, alias = "always-on-top")]
  1285. pub always_on_top: bool,
  1286. /// Whether the window should be visible on all workspaces or virtual desktops.
  1287. ///
  1288. /// ## Platform-specific
  1289. ///
  1290. /// - **Windows / iOS / Android:** Unsupported.
  1291. #[serde(default, alias = "visible-on-all-workspaces")]
  1292. pub visible_on_all_workspaces: bool,
  1293. /// Prevents the window contents from being captured by other apps.
  1294. #[serde(default, alias = "content-protected")]
  1295. pub content_protected: bool,
  1296. /// If `true`, hides the window icon from the taskbar on Windows and Linux.
  1297. #[serde(default, alias = "skip-taskbar")]
  1298. pub skip_taskbar: bool,
  1299. /// The initial window theme. Defaults to the system theme. Only implemented on Windows and macOS 10.14+.
  1300. pub theme: Option<crate::Theme>,
  1301. /// The style of the macOS title bar.
  1302. #[serde(default, alias = "title-bar-style")]
  1303. pub title_bar_style: TitleBarStyle,
  1304. /// If `true`, sets the window title to be hidden on macOS.
  1305. #[serde(default, alias = "hidden-title")]
  1306. pub hidden_title: bool,
  1307. /// Whether clicking an inactive window also clicks through to the webview on macOS.
  1308. #[serde(default, alias = "accept-first-mouse")]
  1309. pub accept_first_mouse: bool,
  1310. /// Defines the window [tabbing identifier] for macOS.
  1311. ///
  1312. /// Windows with matching tabbing identifiers will be grouped together.
  1313. /// If the tabbing identifier is not set, automatic tabbing will be disabled.
  1314. ///
  1315. /// [tabbing identifier]: <https://developer.apple.com/documentation/appkit/nswindow/1644704-tabbingidentifier>
  1316. #[serde(default, alias = "tabbing-identifier")]
  1317. pub tabbing_identifier: Option<String>,
  1318. /// Defines additional browser arguments on Windows. By default wry passes `--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection`
  1319. /// so if you use this method, you also need to disable these components by yourself if you want.
  1320. #[serde(default, alias = "additional-browser-args")]
  1321. pub additional_browser_args: Option<String>,
  1322. /// Whether or not the window has shadow.
  1323. ///
  1324. /// ## Platform-specific
  1325. ///
  1326. /// - **Windows:**
  1327. /// - `false` has no effect on decorated window, shadow are always ON.
  1328. /// - `true` will make undecorated window have a 1px white border,
  1329. /// and on Windows 11, it will have a rounded corners.
  1330. /// - **Linux:** Unsupported.
  1331. #[serde(default = "default_true")]
  1332. pub shadow: bool,
  1333. /// Window effects.
  1334. ///
  1335. /// Requires the window to be transparent.
  1336. ///
  1337. /// ## Platform-specific:
  1338. ///
  1339. /// - **Windows**: If using decorations or shadows, you may want to try this workaround <https://github.com/tauri-apps/tao/issues/72#issuecomment-975607891>
  1340. /// - **Linux**: Unsupported
  1341. #[serde(default, alias = "window-effects")]
  1342. pub window_effects: Option<WindowEffectsConfig>,
  1343. /// Whether or not the webview should be launched in incognito mode.
  1344. ///
  1345. /// ## Platform-specific:
  1346. ///
  1347. /// - **Android**: Unsupported.
  1348. #[serde(default)]
  1349. pub incognito: bool,
  1350. /// Sets the window associated with this label to be the parent of the window to be created.
  1351. ///
  1352. /// ## Platform-specific
  1353. ///
  1354. /// - **Windows**: This sets the passed parent as an owner window to the window to be created.
  1355. /// From [MSDN owned windows docs](https://docs.microsoft.com/en-us/windows/win32/winmsg/window-features#owned-windows):
  1356. /// - An owned window is always above its owner in the z-order.
  1357. /// - The system automatically destroys an owned window when its owner is destroyed.
  1358. /// - An owned window is hidden when its owner is minimized.
  1359. /// - **Linux**: This makes the new window transient for parent, see <https://docs.gtk.org/gtk3/method.Window.set_transient_for.html>
  1360. /// - **macOS**: This adds the window as a child of parent, see <https://developer.apple.com/documentation/appkit/nswindow/1419152-addchildwindow?language=objc>
  1361. pub parent: Option<String>,
  1362. /// The proxy URL for the WebView for all network requests.
  1363. ///
  1364. /// Must be either a `http://` or a `socks5://` URL.
  1365. ///
  1366. /// ## Platform-specific
  1367. ///
  1368. /// - **macOS**: Requires the `macos-proxy` feature flag and only compiles for macOS 14+.
  1369. pub proxy_url: Option<Url>,
  1370. /// Whether page zooming by hotkeys is enabled
  1371. ///
  1372. /// ## Platform-specific:
  1373. ///
  1374. /// - **Windows**: Controls WebView2's [`IsZoomControlEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2settings?view=webview2-winrt-1.0.2420.47#iszoomcontrolenabled) setting.
  1375. /// - **MacOS / Linux**: Injects a polyfill that zooms in and out with `ctrl/command` + `-/=`,
  1376. /// 20% in each step, ranging from 20% to 1000%. Requires `webview:allow-set-webview-zoom` permission
  1377. ///
  1378. /// - **Android / iOS**: Unsupported.
  1379. #[serde(default)]
  1380. pub zoom_hotkeys_enabled: bool,
  1381. }
  1382. impl Default for WindowConfig {
  1383. fn default() -> Self {
  1384. Self {
  1385. label: default_window_label(),
  1386. url: WebviewUrl::default(),
  1387. create: true,
  1388. user_agent: None,
  1389. drag_drop_enabled: true,
  1390. center: false,
  1391. x: None,
  1392. y: None,
  1393. width: default_width(),
  1394. height: default_height(),
  1395. min_width: None,
  1396. min_height: None,
  1397. max_width: None,
  1398. max_height: None,
  1399. resizable: true,
  1400. maximizable: true,
  1401. minimizable: true,
  1402. closable: true,
  1403. title: default_title(),
  1404. fullscreen: false,
  1405. focus: false,
  1406. transparent: false,
  1407. maximized: false,
  1408. visible: true,
  1409. decorations: true,
  1410. always_on_bottom: false,
  1411. always_on_top: false,
  1412. visible_on_all_workspaces: false,
  1413. content_protected: false,
  1414. skip_taskbar: false,
  1415. theme: None,
  1416. title_bar_style: Default::default(),
  1417. hidden_title: false,
  1418. accept_first_mouse: false,
  1419. tabbing_identifier: None,
  1420. additional_browser_args: None,
  1421. shadow: true,
  1422. window_effects: None,
  1423. incognito: false,
  1424. parent: None,
  1425. proxy_url: None,
  1426. zoom_hotkeys_enabled: false,
  1427. }
  1428. }
  1429. }
  1430. fn default_window_label() -> String {
  1431. "main".to_string()
  1432. }
  1433. fn default_width() -> f64 {
  1434. 800f64
  1435. }
  1436. fn default_height() -> f64 {
  1437. 600f64
  1438. }
  1439. fn default_title() -> String {
  1440. "Tauri App".to_string()
  1441. }
  1442. /// A Content-Security-Policy directive source list.
  1443. /// See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/Sources#sources>.
  1444. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1445. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1446. #[serde(rename_all = "camelCase", untagged)]
  1447. pub enum CspDirectiveSources {
  1448. /// An inline list of CSP sources. Same as [`Self::List`], but concatenated with a space separator.
  1449. Inline(String),
  1450. /// A list of CSP sources. The collection will be concatenated with a space separator for the CSP string.
  1451. List(Vec<String>),
  1452. }
  1453. impl Default for CspDirectiveSources {
  1454. fn default() -> Self {
  1455. Self::List(Vec::new())
  1456. }
  1457. }
  1458. impl From<CspDirectiveSources> for Vec<String> {
  1459. fn from(sources: CspDirectiveSources) -> Self {
  1460. match sources {
  1461. CspDirectiveSources::Inline(source) => source.split(' ').map(|s| s.to_string()).collect(),
  1462. CspDirectiveSources::List(l) => l,
  1463. }
  1464. }
  1465. }
  1466. impl CspDirectiveSources {
  1467. /// Whether the given source is configured on this directive or not.
  1468. pub fn contains(&self, source: &str) -> bool {
  1469. match self {
  1470. Self::Inline(s) => s.contains(&format!("{source} ")) || s.contains(&format!(" {source}")),
  1471. Self::List(l) => l.contains(&source.into()),
  1472. }
  1473. }
  1474. /// Appends the given source to this directive.
  1475. pub fn push<S: AsRef<str>>(&mut self, source: S) {
  1476. match self {
  1477. Self::Inline(s) => {
  1478. s.push(' ');
  1479. s.push_str(source.as_ref());
  1480. }
  1481. Self::List(l) => {
  1482. l.push(source.as_ref().to_string());
  1483. }
  1484. }
  1485. }
  1486. /// Extends this CSP directive source list with the given array of sources.
  1487. pub fn extend(&mut self, sources: Vec<String>) {
  1488. for s in sources {
  1489. self.push(s);
  1490. }
  1491. }
  1492. }
  1493. /// A Content-Security-Policy definition.
  1494. /// See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>.
  1495. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1496. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1497. #[serde(rename_all = "camelCase", untagged)]
  1498. pub enum Csp {
  1499. /// The entire CSP policy in a single text string.
  1500. Policy(String),
  1501. /// An object mapping a directive with its sources values as a list of strings.
  1502. DirectiveMap(HashMap<String, CspDirectiveSources>),
  1503. }
  1504. impl From<HashMap<String, CspDirectiveSources>> for Csp {
  1505. fn from(map: HashMap<String, CspDirectiveSources>) -> Self {
  1506. Self::DirectiveMap(map)
  1507. }
  1508. }
  1509. impl From<Csp> for HashMap<String, CspDirectiveSources> {
  1510. fn from(csp: Csp) -> Self {
  1511. match csp {
  1512. Csp::Policy(policy) => {
  1513. let mut map = HashMap::new();
  1514. for directive in policy.split(';') {
  1515. let mut tokens = directive.trim().split(' ');
  1516. if let Some(directive) = tokens.next() {
  1517. let sources = tokens.map(|s| s.to_string()).collect::<Vec<String>>();
  1518. map.insert(directive.to_string(), CspDirectiveSources::List(sources));
  1519. }
  1520. }
  1521. map
  1522. }
  1523. Csp::DirectiveMap(m) => m,
  1524. }
  1525. }
  1526. }
  1527. impl Display for Csp {
  1528. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  1529. match self {
  1530. Self::Policy(s) => write!(f, "{s}"),
  1531. Self::DirectiveMap(m) => {
  1532. let len = m.len();
  1533. let mut i = 0;
  1534. for (directive, sources) in m {
  1535. let sources: Vec<String> = sources.clone().into();
  1536. write!(f, "{} {}", directive, sources.join(" "))?;
  1537. i += 1;
  1538. if i != len {
  1539. write!(f, "; ")?;
  1540. }
  1541. }
  1542. Ok(())
  1543. }
  1544. }
  1545. }
  1546. }
  1547. /// The possible values for the `dangerous_disable_asset_csp_modification` config option.
  1548. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1549. #[serde(untagged)]
  1550. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1551. pub enum DisabledCspModificationKind {
  1552. /// If `true`, disables all CSP modification.
  1553. /// `false` is the default value and it configures Tauri to control the CSP.
  1554. Flag(bool),
  1555. /// Disables the given list of CSP directives modifications.
  1556. List(Vec<String>),
  1557. }
  1558. impl DisabledCspModificationKind {
  1559. /// Determines whether the given CSP directive can be modified or not.
  1560. pub fn can_modify(&self, directive: &str) -> bool {
  1561. match self {
  1562. Self::Flag(f) => !f,
  1563. Self::List(l) => !l.contains(&directive.into()),
  1564. }
  1565. }
  1566. }
  1567. impl Default for DisabledCspModificationKind {
  1568. fn default() -> Self {
  1569. Self::Flag(false)
  1570. }
  1571. }
  1572. /// Protocol scope definition.
  1573. /// It is a list of glob patterns that restrict the API access from the webview.
  1574. ///
  1575. /// Each pattern can start with a variable that resolves to a system base directory.
  1576. /// The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`,
  1577. /// `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`,
  1578. /// `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`,
  1579. /// `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.
  1580. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1581. #[serde(untagged)]
  1582. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1583. pub enum FsScope {
  1584. /// A list of paths that are allowed by this scope.
  1585. AllowedPaths(Vec<PathBuf>),
  1586. /// A complete scope configuration.
  1587. #[serde(rename_all = "camelCase")]
  1588. Scope {
  1589. /// A list of paths that are allowed by this scope.
  1590. #[serde(default)]
  1591. allow: Vec<PathBuf>,
  1592. /// A list of paths that are not allowed by this scope.
  1593. /// This gets precedence over the [`Self::Scope::allow`] list.
  1594. #[serde(default)]
  1595. deny: Vec<PathBuf>,
  1596. /// Whether or not paths that contain components that start with a `.`
  1597. /// will require that `.` appears literally in the pattern; `*`, `?`, `**`,
  1598. /// or `[...]` will not match. This is useful because such files are
  1599. /// conventionally considered hidden on Unix systems and it might be
  1600. /// desirable to skip them when listing files.
  1601. ///
  1602. /// Defaults to `true` on Unix systems and `false` on Windows
  1603. // dotfiles are not supposed to be exposed by default on unix
  1604. #[serde(alias = "require-literal-leading-dot")]
  1605. require_literal_leading_dot: Option<bool>,
  1606. },
  1607. }
  1608. impl Default for FsScope {
  1609. fn default() -> Self {
  1610. Self::AllowedPaths(Vec::new())
  1611. }
  1612. }
  1613. impl FsScope {
  1614. /// The list of allowed paths.
  1615. pub fn allowed_paths(&self) -> &Vec<PathBuf> {
  1616. match self {
  1617. Self::AllowedPaths(p) => p,
  1618. Self::Scope { allow, .. } => allow,
  1619. }
  1620. }
  1621. /// The list of forbidden paths.
  1622. pub fn forbidden_paths(&self) -> Option<&Vec<PathBuf>> {
  1623. match self {
  1624. Self::AllowedPaths(_) => None,
  1625. Self::Scope { deny, .. } => Some(deny),
  1626. }
  1627. }
  1628. }
  1629. /// Config for the asset custom protocol.
  1630. ///
  1631. /// See more: <https://tauri.app/v1/api/config#assetprotocolconfig>
  1632. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1633. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1634. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1635. pub struct AssetProtocolConfig {
  1636. /// The access scope for the asset protocol.
  1637. #[serde(default)]
  1638. pub scope: FsScope,
  1639. /// Enables the asset protocol.
  1640. #[serde(default)]
  1641. pub enable: bool,
  1642. }
  1643. /// Security configuration.
  1644. ///
  1645. /// See more: <https://tauri.app/v1/api/config#securityconfig>
  1646. #[skip_serializing_none]
  1647. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1648. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1649. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1650. pub struct SecurityConfig {
  1651. /// The Content Security Policy that will be injected on all HTML files on the built application.
  1652. /// If [`dev_csp`](#SecurityConfig.devCsp) is not specified, this value is also injected on dev.
  1653. ///
  1654. /// This is a really important part of the configuration since it helps you ensure your WebView is secured.
  1655. /// See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>.
  1656. pub csp: Option<Csp>,
  1657. /// The Content Security Policy that will be injected on all HTML files on development.
  1658. ///
  1659. /// This is a really important part of the configuration since it helps you ensure your WebView is secured.
  1660. /// See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>.
  1661. #[serde(alias = "dev-csp")]
  1662. pub dev_csp: Option<Csp>,
  1663. /// Freeze the `Object.prototype` when using the custom protocol.
  1664. #[serde(default, alias = "freeze-prototype")]
  1665. pub freeze_prototype: bool,
  1666. /// Disables the Tauri-injected CSP sources.
  1667. ///
  1668. /// At compile time, Tauri parses all the frontend assets and changes the Content-Security-Policy
  1669. /// to only allow loading of your own scripts and styles by injecting nonce and hash sources.
  1670. /// This stricts your CSP, which may introduce issues when using along with other flexing sources.
  1671. ///
  1672. /// This configuration option allows both a boolean and a list of strings as value.
  1673. /// A boolean instructs Tauri to disable the injection for all CSP injections,
  1674. /// and a list of strings indicates the CSP directives that Tauri cannot inject.
  1675. ///
  1676. /// **WARNING:** Only disable this if you know what you are doing and have properly configured the CSP.
  1677. /// Your application might be vulnerable to XSS attacks without this Tauri protection.
  1678. #[serde(default, alias = "dangerous-disable-asset-csp-modification")]
  1679. pub dangerous_disable_asset_csp_modification: DisabledCspModificationKind,
  1680. /// Custom protocol config.
  1681. #[serde(default, alias = "asset-protocol")]
  1682. pub asset_protocol: AssetProtocolConfig,
  1683. /// The pattern to use.
  1684. #[serde(default)]
  1685. pub pattern: PatternKind,
  1686. /// List of capabilities that are enabled on the application.
  1687. ///
  1688. /// If the list is empty, all capabilities are included.
  1689. #[serde(default)]
  1690. pub capabilities: Vec<CapabilityEntry>,
  1691. }
  1692. /// A capability entry which can be either an inlined capability or a reference to a capability defined on its own file.
  1693. #[derive(Debug, Clone, PartialEq, Serialize)]
  1694. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1695. #[serde(untagged)]
  1696. pub enum CapabilityEntry {
  1697. /// An inlined capability.
  1698. Inlined(Capability),
  1699. /// Reference to a capability identifier.
  1700. Reference(String),
  1701. }
  1702. impl<'de> Deserialize<'de> for CapabilityEntry {
  1703. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  1704. where
  1705. D: Deserializer<'de>,
  1706. {
  1707. UntaggedEnumVisitor::new()
  1708. .string(|string| Ok(Self::Reference(string.to_owned())))
  1709. .map(|map| map.deserialize::<Capability>().map(Self::Inlined))
  1710. .deserialize(deserializer)
  1711. }
  1712. }
  1713. /// The application pattern.
  1714. #[skip_serializing_none]
  1715. #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
  1716. #[serde(rename_all = "lowercase", tag = "use", content = "options")]
  1717. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1718. pub enum PatternKind {
  1719. /// Brownfield pattern.
  1720. Brownfield,
  1721. /// Isolation pattern. Recommended for security purposes.
  1722. Isolation {
  1723. /// The dir containing the index.html file that contains the secure isolation application.
  1724. dir: PathBuf,
  1725. },
  1726. }
  1727. impl Default for PatternKind {
  1728. fn default() -> Self {
  1729. Self::Brownfield
  1730. }
  1731. }
  1732. /// The App configuration object.
  1733. ///
  1734. /// See more: <https://tauri.app/v1/api/config#appconfig>
  1735. #[skip_serializing_none]
  1736. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1737. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1738. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1739. pub struct AppConfig {
  1740. /// The app windows configuration.
  1741. #[serde(default)]
  1742. pub windows: Vec<WindowConfig>,
  1743. /// Security configuration.
  1744. #[serde(default)]
  1745. pub security: SecurityConfig,
  1746. /// Configuration for app tray icon.
  1747. #[serde(alias = "tray-icon")]
  1748. pub tray_icon: Option<TrayIconConfig>,
  1749. /// MacOS private API configuration. Enables the transparent background API and sets the `fullScreenEnabled` preference to `true`.
  1750. #[serde(rename = "macOSPrivateApi", alias = "macos-private-api", default)]
  1751. pub macos_private_api: bool,
  1752. /// Whether we should inject the Tauri API on `window.__TAURI__` or not.
  1753. #[serde(default, alias = "with-global-tauri")]
  1754. pub with_global_tauri: bool,
  1755. /// If set to true "identifier" will be set as GTK app ID (on systems that use GTK).
  1756. #[serde(rename = "enableGTKAppId", alias = "enable-gtk-app-id", default)]
  1757. pub enable_gtk_app_id: bool,
  1758. }
  1759. impl AppConfig {
  1760. /// Returns all Cargo features.
  1761. pub fn all_features() -> Vec<&'static str> {
  1762. vec![
  1763. "tray-icon",
  1764. "macos-private-api",
  1765. "protocol-asset",
  1766. "isolation",
  1767. ]
  1768. }
  1769. /// Returns the enabled Cargo features.
  1770. pub fn features(&self) -> Vec<&str> {
  1771. let mut features = Vec::new();
  1772. if self.tray_icon.is_some() {
  1773. features.push("tray-icon");
  1774. }
  1775. if self.macos_private_api {
  1776. features.push("macos-private-api");
  1777. }
  1778. if self.security.asset_protocol.enable {
  1779. features.push("protocol-asset");
  1780. }
  1781. if let PatternKind::Isolation { .. } = self.security.pattern {
  1782. features.push("isolation");
  1783. }
  1784. features.sort_unstable();
  1785. features
  1786. }
  1787. }
  1788. /// Configuration for application tray icon.
  1789. ///
  1790. /// See more: <https://tauri.app/v1/api/config#trayiconconfig>
  1791. #[skip_serializing_none]
  1792. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1793. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1794. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1795. pub struct TrayIconConfig {
  1796. /// Set an id for this tray icon so you can reference it later, defaults to `main`.
  1797. pub id: Option<String>,
  1798. /// Path to the default icon to use for the tray icon.
  1799. ///
  1800. /// Note: this stores the image in raw pixels to the final binary,
  1801. /// so keep the icon size (width and height) small
  1802. /// or else it's going to bloat your final executable
  1803. #[serde(alias = "icon-path")]
  1804. pub icon_path: PathBuf,
  1805. /// A Boolean value that determines whether the image represents a [template](https://developer.apple.com/documentation/appkit/nsimage/1520017-template?language=objc) image on macOS.
  1806. #[serde(default, alias = "icon-as-template")]
  1807. pub icon_as_template: bool,
  1808. /// A Boolean value that determines whether the menu should appear when the tray icon receives a left click on macOS.
  1809. #[serde(default = "default_true", alias = "menu-on-left-click")]
  1810. pub menu_on_left_click: bool,
  1811. /// Title for MacOS tray
  1812. pub title: Option<String>,
  1813. /// Tray icon tooltip on Windows and macOS
  1814. pub tooltip: Option<String>,
  1815. }
  1816. /// General configuration for the iOS target.
  1817. #[skip_serializing_none]
  1818. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1819. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1820. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1821. pub struct IosConfig {
  1822. /// A custom [XcodeGen] project.yml template to use.
  1823. ///
  1824. /// [XcodeGen]: <https://github.com/yonaskolb/XcodeGen>
  1825. pub template: Option<PathBuf>,
  1826. /// A list of strings indicating any iOS frameworks that need to be bundled with the application.
  1827. ///
  1828. /// Note that you need to recreate the iOS project for the changes to be applied.
  1829. pub frameworks: Option<Vec<String>>,
  1830. /// The development team. This value is required for iOS development because code signing is enforced.
  1831. /// The `APPLE_DEVELOPMENT_TEAM` environment variable can be set to overwrite it.
  1832. #[serde(alias = "development-team")]
  1833. pub development_team: Option<String>,
  1834. /// A version string indicating the minimum iOS version that the bundled application supports. Defaults to `13.0`.
  1835. ///
  1836. /// Maps to the IPHONEOS_DEPLOYMENT_TARGET value.
  1837. #[serde(
  1838. alias = "minimum-system-version",
  1839. default = "ios_minimum_system_version"
  1840. )]
  1841. pub minimum_system_version: String,
  1842. }
  1843. impl Default for IosConfig {
  1844. fn default() -> Self {
  1845. Self {
  1846. template: None,
  1847. frameworks: None,
  1848. development_team: None,
  1849. minimum_system_version: ios_minimum_system_version(),
  1850. }
  1851. }
  1852. }
  1853. /// General configuration for the iOS target.
  1854. #[skip_serializing_none]
  1855. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1856. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1857. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1858. pub struct AndroidConfig {
  1859. /// The minimum API level required for the application to run.
  1860. /// The Android system will prevent the user from installing the application if the system's API level is lower than the value specified.
  1861. #[serde(alias = "min-sdk-version", default = "default_min_sdk_version")]
  1862. pub min_sdk_version: u32,
  1863. /// The version code of the application.
  1864. /// It is limited to 2,100,000,000 as per Google Play Store requirements.
  1865. ///
  1866. /// By default we use your configured version and perform the following math:
  1867. /// versionCode = version.major * 1000000 + version.minor * 1000 + version.patch
  1868. #[serde(alias = "version-code")]
  1869. #[cfg_attr(feature = "schema", validate(range(min = 1, max = 2_100_000_000)))]
  1870. pub version_code: Option<u32>,
  1871. }
  1872. impl Default for AndroidConfig {
  1873. fn default() -> Self {
  1874. Self {
  1875. min_sdk_version: default_min_sdk_version(),
  1876. version_code: None,
  1877. }
  1878. }
  1879. }
  1880. fn default_min_sdk_version() -> u32 {
  1881. 24
  1882. }
  1883. /// Defines the URL or assets to embed in the application.
  1884. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1885. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1886. #[serde(untagged, deny_unknown_fields)]
  1887. #[non_exhaustive]
  1888. pub enum FrontendDist {
  1889. /// An external URL that should be used as the default application URL.
  1890. Url(Url),
  1891. /// Path to a directory containing the frontend dist assets.
  1892. Directory(PathBuf),
  1893. /// An array of files to embed on the app.
  1894. Files(Vec<PathBuf>),
  1895. }
  1896. impl std::fmt::Display for FrontendDist {
  1897. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  1898. match self {
  1899. Self::Url(url) => write!(f, "{url}"),
  1900. Self::Directory(p) => write!(f, "{}", p.display()),
  1901. Self::Files(files) => write!(f, "{}", serde_json::to_string(files).unwrap()),
  1902. }
  1903. }
  1904. }
  1905. /// Describes the shell command to run before `tauri dev`.
  1906. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1907. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1908. #[serde(rename_all = "camelCase", untagged)]
  1909. pub enum BeforeDevCommand {
  1910. /// Run the given script with the default options.
  1911. Script(String),
  1912. /// Run the given script with custom options.
  1913. ScriptWithOptions {
  1914. /// The script to execute.
  1915. script: String,
  1916. /// The current working directory.
  1917. cwd: Option<String>,
  1918. /// Whether `tauri dev` should wait for the command to finish or not. Defaults to `false`.
  1919. #[serde(default)]
  1920. wait: bool,
  1921. },
  1922. }
  1923. /// Describes a shell command to be executed when a CLI hook is triggered.
  1924. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1925. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1926. #[serde(rename_all = "camelCase", untagged)]
  1927. pub enum HookCommand {
  1928. /// Run the given script with the default options.
  1929. Script(String),
  1930. /// Run the given script with custom options.
  1931. ScriptWithOptions {
  1932. /// The script to execute.
  1933. script: String,
  1934. /// The current working directory.
  1935. cwd: Option<String>,
  1936. },
  1937. }
  1938. /// The Build configuration object.
  1939. ///
  1940. /// See more: <https://tauri.app/v1/api/config#buildconfig>
  1941. #[skip_serializing_none]
  1942. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize, Default)]
  1943. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1944. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1945. pub struct BuildConfig {
  1946. /// The binary used to build and run the application.
  1947. pub runner: Option<String>,
  1948. /// The URL to load in development.
  1949. ///
  1950. /// This is usually an URL to a dev server, which serves your application assets with hot-reload and HMR.
  1951. /// Most modern JavaScript bundlers like [vite](https://vitejs.dev/guide/) provides a way to start a dev server by default.
  1952. ///
  1953. /// If you don't have a dev server or don't want to use one, ignore this option and use [`frontendDist`](BuildConfig::frontend_dist)
  1954. /// and point to a web assets directory, and Tauri CLI will run its built-in dev server and provide a simple hot-reload experience.
  1955. #[serde(alias = "dev-url")]
  1956. pub dev_url: Option<Url>,
  1957. /// The path to the application assets (usually the `dist` folder of your javascript bundler)
  1958. /// or a URL that could be either a custom protocol registered in the tauri app (for example: `myprotocol://`)
  1959. /// or a remote URL (for example: `https://site.com/app`).
  1960. ///
  1961. /// When a path relative to the configuration file is provided,
  1962. /// it is read recursively and all files are embedded in the application binary.
  1963. /// Tauri then looks for an `index.html` and serves it as the default entry point for your application.
  1964. ///
  1965. /// You can also provide a list of paths to be embedded, which allows granular control over what files are added to the binary.
  1966. /// In this case, all files are added to the root and you must reference it that way in your HTML files.
  1967. ///
  1968. /// When a URL is provided, the application won't have bundled assets
  1969. /// and the application will load that URL by default.
  1970. #[serde(alias = "frontend-dist")]
  1971. pub frontend_dist: Option<FrontendDist>,
  1972. /// A shell command to run before `tauri dev` kicks in.
  1973. ///
  1974. /// The TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG environment variables are set if you perform conditional compilation.
  1975. #[serde(alias = "before-dev-command")]
  1976. pub before_dev_command: Option<BeforeDevCommand>,
  1977. /// A shell command to run before `tauri build` kicks in.
  1978. ///
  1979. /// The TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG environment variables are set if you perform conditional compilation.
  1980. #[serde(alias = "before-build-command")]
  1981. pub before_build_command: Option<HookCommand>,
  1982. /// A shell command to run before the bundling phase in `tauri build` kicks in.
  1983. ///
  1984. /// The TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG environment variables are set if you perform conditional compilation.
  1985. #[serde(alias = "before-bundle-command")]
  1986. pub before_bundle_command: Option<HookCommand>,
  1987. /// Features passed to `cargo` commands.
  1988. pub features: Option<Vec<String>>,
  1989. }
  1990. #[derive(Debug, PartialEq, Eq)]
  1991. struct PackageVersion(String);
  1992. impl<'d> serde::Deserialize<'d> for PackageVersion {
  1993. fn deserialize<D: Deserializer<'d>>(deserializer: D) -> Result<Self, D::Error> {
  1994. struct PackageVersionVisitor;
  1995. impl<'d> Visitor<'d> for PackageVersionVisitor {
  1996. type Value = PackageVersion;
  1997. fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
  1998. write!(
  1999. formatter,
  2000. "a semver string or a path to a package.json file"
  2001. )
  2002. }
  2003. fn visit_str<E: DeError>(self, value: &str) -> Result<PackageVersion, E> {
  2004. let path = PathBuf::from(value);
  2005. if path.exists() {
  2006. let json_str = read_to_string(&path)
  2007. .map_err(|e| DeError::custom(format!("failed to read version JSON file: {e}")))?;
  2008. let package_json: serde_json::Value = serde_json::from_str(&json_str)
  2009. .map_err(|e| DeError::custom(format!("failed to read version JSON file: {e}")))?;
  2010. if let Some(obj) = package_json.as_object() {
  2011. let version = obj
  2012. .get("version")
  2013. .ok_or_else(|| DeError::custom("JSON must contain a `version` field"))?
  2014. .as_str()
  2015. .ok_or_else(|| {
  2016. DeError::custom(format!("`{} > version` must be a string", path.display()))
  2017. })?;
  2018. Ok(PackageVersion(
  2019. Version::from_str(version)
  2020. .map_err(|_| DeError::custom("`package > version` must be a semver string"))?
  2021. .to_string(),
  2022. ))
  2023. } else {
  2024. Err(DeError::custom(
  2025. "`package > version` value is not a path to a JSON object",
  2026. ))
  2027. }
  2028. } else {
  2029. Ok(PackageVersion(
  2030. Version::from_str(value)
  2031. .map_err(|_| DeError::custom("`package > version` must be a semver string"))?
  2032. .to_string(),
  2033. ))
  2034. }
  2035. }
  2036. }
  2037. deserializer.deserialize_string(PackageVersionVisitor {})
  2038. }
  2039. }
  2040. fn version_deserializer<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
  2041. where
  2042. D: Deserializer<'de>,
  2043. {
  2044. Option::<PackageVersion>::deserialize(deserializer).map(|v| v.map(|v| v.0))
  2045. }
  2046. /// The Tauri configuration object.
  2047. /// It is read from a file where you can define your frontend assets,
  2048. /// configure the bundler and define a tray icon.
  2049. ///
  2050. /// The configuration file is generated by the
  2051. /// [`tauri init`](https://tauri.app/v1/api/cli#init) command that lives in
  2052. /// your Tauri application source directory (src-tauri).
  2053. ///
  2054. /// Once generated, you may modify it at will to customize your Tauri application.
  2055. ///
  2056. /// ## File Formats
  2057. ///
  2058. /// By default, the configuration is defined as a JSON file named `tauri.conf.json`.
  2059. ///
  2060. /// Tauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively.
  2061. /// The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`.
  2062. /// The TOML file name is `Tauri.toml`.
  2063. ///
  2064. /// ## Platform-Specific Configuration
  2065. ///
  2066. /// In addition to the default configuration file, Tauri can
  2067. /// read a platform-specific configuration from `tauri.linux.conf.json`,
  2068. /// `tauri.windows.conf.json`, `tauri.macos.conf.json`, `tauri.android.conf.json` and `tauri.ios.conf.json`
  2069. /// (or `Tauri.linux.toml`, `Tauri.windows.toml`, `Tauri.macos.toml`, `Tauri.android.toml` and `Tauri.ios.toml` if the `Tauri.toml` format is used),
  2070. /// which gets merged with the main configuration object.
  2071. ///
  2072. /// ## Configuration Structure
  2073. ///
  2074. /// The configuration is composed of the following objects:
  2075. ///
  2076. /// - [`app`](#appconfig): The Tauri configuration
  2077. /// - [`build`](#buildconfig): The build configuration
  2078. /// - [`bundle`](#bundleconfig): The bundle configurations
  2079. /// - [`plugins`](#pluginconfig): The plugins configuration
  2080. ///
  2081. /// Example tauri.config.json file:
  2082. ///
  2083. /// ```json
  2084. /// {
  2085. /// "productName": "tauri-app",
  2086. /// "version": "0.1.0",
  2087. /// "build": {
  2088. /// "beforeBuildCommand": "",
  2089. /// "beforeDevCommand": "",
  2090. /// "devUrl": "../dist",
  2091. /// "frontendDist": "../dist"
  2092. /// },
  2093. /// "app": {
  2094. /// "security": {
  2095. /// "csp": null
  2096. /// },
  2097. /// "windows": [
  2098. /// {
  2099. /// "fullscreen": false,
  2100. /// "height": 600,
  2101. /// "resizable": true,
  2102. /// "title": "Tauri App",
  2103. /// "width": 800
  2104. /// }
  2105. /// ]
  2106. /// },
  2107. /// "bundle": {},
  2108. /// "plugins": {}
  2109. /// }
  2110. /// ```
  2111. #[skip_serializing_none]
  2112. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  2113. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2114. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2115. pub struct Config {
  2116. /// The JSON schema for the Tauri config.
  2117. #[serde(rename = "$schema")]
  2118. pub schema: Option<String>,
  2119. /// App name.
  2120. #[serde(alias = "product-name")]
  2121. #[cfg_attr(feature = "schema", validate(regex(pattern = "^[^/\\:*?\"<>|]+$")))]
  2122. pub product_name: Option<String>,
  2123. /// App main binary filename. Defaults to the name of your cargo crate.
  2124. #[serde(alias = "main-binary-name")]
  2125. pub main_binary_name: Option<String>,
  2126. /// App version. It is a semver version number or a path to a `package.json` file containing the `version` field. If removed the version number from `Cargo.toml` is used.
  2127. ///
  2128. /// By default version 1.0 is used on Android.
  2129. #[serde(deserialize_with = "version_deserializer", default)]
  2130. pub version: Option<String>,
  2131. /// The application identifier in reverse domain name notation (e.g. `com.tauri.example`).
  2132. /// This string must be unique across applications since it is used in system configurations like
  2133. /// the bundle ID and path to the webview data directory.
  2134. /// This string must contain only alphanumeric characters (A-Z, a-z, and 0-9), hyphens (-),
  2135. /// and periods (.).
  2136. pub identifier: String,
  2137. /// The App configuration.
  2138. #[serde(default)]
  2139. pub app: AppConfig,
  2140. /// The build configuration.
  2141. #[serde(default = "default_build")]
  2142. pub build: BuildConfig,
  2143. /// The bundler configuration.
  2144. #[serde(default)]
  2145. pub bundle: BundleConfig,
  2146. /// The plugins config.
  2147. #[serde(default)]
  2148. pub plugins: PluginConfig,
  2149. }
  2150. /// The plugin configs holds a HashMap mapping a plugin name to its configuration object.
  2151. ///
  2152. /// See more: <https://tauri.app/v1/api/config#pluginconfig>
  2153. #[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)]
  2154. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2155. pub struct PluginConfig(pub HashMap<String, JsonValue>);
  2156. fn default_build() -> BuildConfig {
  2157. BuildConfig {
  2158. runner: None,
  2159. dev_url: None,
  2160. frontend_dist: None,
  2161. before_dev_command: None,
  2162. before_build_command: None,
  2163. before_bundle_command: None,
  2164. features: None,
  2165. }
  2166. }
  2167. /// Implement `ToTokens` for all config structs, allowing a literal `Config` to be built.
  2168. ///
  2169. /// This allows for a build script to output the values in a `Config` to a `TokenStream`, which can
  2170. /// then be consumed by another crate. Useful for passing a config to both the build script and the
  2171. /// application using tauri while only parsing it once (in the build script).
  2172. #[cfg(feature = "build")]
  2173. mod build {
  2174. use super::*;
  2175. use crate::{literal_struct, tokens::*};
  2176. use proc_macro2::TokenStream;
  2177. use quote::{quote, ToTokens, TokenStreamExt};
  2178. use std::convert::identity;
  2179. impl ToTokens for WebviewUrl {
  2180. fn to_tokens(&self, tokens: &mut TokenStream) {
  2181. let prefix = quote! { ::tauri::utils::config::WebviewUrl };
  2182. tokens.append_all(match self {
  2183. Self::App(path) => {
  2184. let path = path_buf_lit(path);
  2185. quote! { #prefix::App(#path) }
  2186. }
  2187. Self::External(url) => {
  2188. let url = url_lit(url);
  2189. quote! { #prefix::External(#url) }
  2190. }
  2191. Self::CustomProtocol(url) => {
  2192. let url = url_lit(url);
  2193. quote! { #prefix::CustomProtocol(#url) }
  2194. }
  2195. })
  2196. }
  2197. }
  2198. impl ToTokens for crate::Theme {
  2199. fn to_tokens(&self, tokens: &mut TokenStream) {
  2200. let prefix = quote! { ::tauri::utils::Theme };
  2201. tokens.append_all(match self {
  2202. Self::Light => quote! { #prefix::Light },
  2203. Self::Dark => quote! { #prefix::Dark },
  2204. })
  2205. }
  2206. }
  2207. impl ToTokens for Color {
  2208. fn to_tokens(&self, tokens: &mut TokenStream) {
  2209. let Color(r, g, b, a) = self;
  2210. tokens.append_all(quote! {::tauri::utils::config::Color(#r,#g,#b,#a)});
  2211. }
  2212. }
  2213. impl ToTokens for WindowEffectsConfig {
  2214. fn to_tokens(&self, tokens: &mut TokenStream) {
  2215. let effects = vec_lit(self.effects.clone(), |d| d);
  2216. let state = opt_lit(self.state.as_ref());
  2217. let radius = opt_lit(self.radius.as_ref());
  2218. let color = opt_lit(self.color.as_ref());
  2219. literal_struct!(
  2220. tokens,
  2221. ::tauri::utils::config::WindowEffectsConfig,
  2222. effects,
  2223. state,
  2224. radius,
  2225. color
  2226. )
  2227. }
  2228. }
  2229. impl ToTokens for crate::TitleBarStyle {
  2230. fn to_tokens(&self, tokens: &mut TokenStream) {
  2231. let prefix = quote! { ::tauri::utils::TitleBarStyle };
  2232. tokens.append_all(match self {
  2233. Self::Visible => quote! { #prefix::Visible },
  2234. Self::Transparent => quote! { #prefix::Transparent },
  2235. Self::Overlay => quote! { #prefix::Overlay },
  2236. })
  2237. }
  2238. }
  2239. impl ToTokens for crate::WindowEffect {
  2240. fn to_tokens(&self, tokens: &mut TokenStream) {
  2241. let prefix = quote! { ::tauri::utils::WindowEffect };
  2242. #[allow(deprecated)]
  2243. tokens.append_all(match self {
  2244. WindowEffect::AppearanceBased => quote! { #prefix::AppearanceBased},
  2245. WindowEffect::Light => quote! { #prefix::Light},
  2246. WindowEffect::Dark => quote! { #prefix::Dark},
  2247. WindowEffect::MediumLight => quote! { #prefix::MediumLight},
  2248. WindowEffect::UltraDark => quote! { #prefix::UltraDark},
  2249. WindowEffect::Titlebar => quote! { #prefix::Titlebar},
  2250. WindowEffect::Selection => quote! { #prefix::Selection},
  2251. WindowEffect::Menu => quote! { #prefix::Menu},
  2252. WindowEffect::Popover => quote! { #prefix::Popover},
  2253. WindowEffect::Sidebar => quote! { #prefix::Sidebar},
  2254. WindowEffect::HeaderView => quote! { #prefix::HeaderView},
  2255. WindowEffect::Sheet => quote! { #prefix::Sheet},
  2256. WindowEffect::WindowBackground => quote! { #prefix::WindowBackground},
  2257. WindowEffect::HudWindow => quote! { #prefix::HudWindow},
  2258. WindowEffect::FullScreenUI => quote! { #prefix::FullScreenUI},
  2259. WindowEffect::Tooltip => quote! { #prefix::Tooltip},
  2260. WindowEffect::ContentBackground => quote! { #prefix::ContentBackground},
  2261. WindowEffect::UnderWindowBackground => quote! { #prefix::UnderWindowBackground},
  2262. WindowEffect::UnderPageBackground => quote! { #prefix::UnderPageBackground},
  2263. WindowEffect::Mica => quote! { #prefix::Mica},
  2264. WindowEffect::MicaDark => quote! { #prefix::MicaDark},
  2265. WindowEffect::MicaLight => quote! { #prefix::MicaLight},
  2266. WindowEffect::Blur => quote! { #prefix::Blur},
  2267. WindowEffect::Acrylic => quote! { #prefix::Acrylic},
  2268. WindowEffect::Tabbed => quote! { #prefix::Tabbed },
  2269. WindowEffect::TabbedDark => quote! { #prefix::TabbedDark },
  2270. WindowEffect::TabbedLight => quote! { #prefix::TabbedLight },
  2271. })
  2272. }
  2273. }
  2274. impl ToTokens for crate::WindowEffectState {
  2275. fn to_tokens(&self, tokens: &mut TokenStream) {
  2276. let prefix = quote! { ::tauri::utils::WindowEffectState };
  2277. #[allow(deprecated)]
  2278. tokens.append_all(match self {
  2279. WindowEffectState::Active => quote! { #prefix::Active},
  2280. WindowEffectState::FollowsWindowActiveState => quote! { #prefix::FollowsWindowActiveState},
  2281. WindowEffectState::Inactive => quote! { #prefix::Inactive},
  2282. })
  2283. }
  2284. }
  2285. impl ToTokens for WindowConfig {
  2286. fn to_tokens(&self, tokens: &mut TokenStream) {
  2287. let label = str_lit(&self.label);
  2288. let create = &self.create;
  2289. let url = &self.url;
  2290. let user_agent = opt_str_lit(self.user_agent.as_ref());
  2291. let drag_drop_enabled = self.drag_drop_enabled;
  2292. let center = self.center;
  2293. let x = opt_lit(self.x.as_ref());
  2294. let y = opt_lit(self.y.as_ref());
  2295. let width = self.width;
  2296. let height = self.height;
  2297. let min_width = opt_lit(self.min_width.as_ref());
  2298. let min_height = opt_lit(self.min_height.as_ref());
  2299. let max_width = opt_lit(self.max_width.as_ref());
  2300. let max_height = opt_lit(self.max_height.as_ref());
  2301. let resizable = self.resizable;
  2302. let maximizable = self.maximizable;
  2303. let minimizable = self.minimizable;
  2304. let closable = self.closable;
  2305. let title = str_lit(&self.title);
  2306. let proxy_url = opt_lit(self.proxy_url.as_ref().map(url_lit).as_ref());
  2307. let fullscreen = self.fullscreen;
  2308. let focus = self.focus;
  2309. let transparent = self.transparent;
  2310. let maximized = self.maximized;
  2311. let visible = self.visible;
  2312. let decorations = self.decorations;
  2313. let always_on_bottom = self.always_on_bottom;
  2314. let always_on_top = self.always_on_top;
  2315. let visible_on_all_workspaces = self.visible_on_all_workspaces;
  2316. let content_protected = self.content_protected;
  2317. let skip_taskbar = self.skip_taskbar;
  2318. let theme = opt_lit(self.theme.as_ref());
  2319. let title_bar_style = &self.title_bar_style;
  2320. let hidden_title = self.hidden_title;
  2321. let accept_first_mouse = self.accept_first_mouse;
  2322. let tabbing_identifier = opt_str_lit(self.tabbing_identifier.as_ref());
  2323. let additional_browser_args = opt_str_lit(self.additional_browser_args.as_ref());
  2324. let shadow = self.shadow;
  2325. let window_effects = opt_lit(self.window_effects.as_ref());
  2326. let incognito = self.incognito;
  2327. let parent = opt_str_lit(self.parent.as_ref());
  2328. let zoom_hotkeys_enabled = self.zoom_hotkeys_enabled;
  2329. literal_struct!(
  2330. tokens,
  2331. ::tauri::utils::config::WindowConfig,
  2332. label,
  2333. url,
  2334. create,
  2335. user_agent,
  2336. drag_drop_enabled,
  2337. center,
  2338. x,
  2339. y,
  2340. width,
  2341. height,
  2342. min_width,
  2343. min_height,
  2344. max_width,
  2345. max_height,
  2346. resizable,
  2347. maximizable,
  2348. minimizable,
  2349. closable,
  2350. title,
  2351. proxy_url,
  2352. fullscreen,
  2353. focus,
  2354. transparent,
  2355. maximized,
  2356. visible,
  2357. decorations,
  2358. always_on_bottom,
  2359. always_on_top,
  2360. visible_on_all_workspaces,
  2361. content_protected,
  2362. skip_taskbar,
  2363. theme,
  2364. title_bar_style,
  2365. hidden_title,
  2366. accept_first_mouse,
  2367. tabbing_identifier,
  2368. additional_browser_args,
  2369. shadow,
  2370. window_effects,
  2371. incognito,
  2372. parent,
  2373. zoom_hotkeys_enabled
  2374. );
  2375. }
  2376. }
  2377. impl ToTokens for PatternKind {
  2378. fn to_tokens(&self, tokens: &mut TokenStream) {
  2379. let prefix = quote! { ::tauri::utils::config::PatternKind };
  2380. tokens.append_all(match self {
  2381. Self::Brownfield => quote! { #prefix::Brownfield },
  2382. #[cfg(not(feature = "isolation"))]
  2383. Self::Isolation { dir: _ } => quote! { #prefix::Brownfield },
  2384. #[cfg(feature = "isolation")]
  2385. Self::Isolation { dir } => {
  2386. let dir = path_buf_lit(dir);
  2387. quote! { #prefix::Isolation { dir: #dir } }
  2388. }
  2389. })
  2390. }
  2391. }
  2392. impl ToTokens for WebviewInstallMode {
  2393. fn to_tokens(&self, tokens: &mut TokenStream) {
  2394. let prefix = quote! { ::tauri::utils::config::WebviewInstallMode };
  2395. tokens.append_all(match self {
  2396. Self::Skip => quote! { #prefix::Skip },
  2397. Self::DownloadBootstrapper { silent } => {
  2398. quote! { #prefix::DownloadBootstrapper { silent: #silent } }
  2399. }
  2400. Self::EmbedBootstrapper { silent } => {
  2401. quote! { #prefix::EmbedBootstrapper { silent: #silent } }
  2402. }
  2403. Self::OfflineInstaller { silent } => {
  2404. quote! { #prefix::OfflineInstaller { silent: #silent } }
  2405. }
  2406. Self::FixedRuntime { path } => {
  2407. let path = path_buf_lit(path);
  2408. quote! { #prefix::FixedRuntime { path: #path } }
  2409. }
  2410. })
  2411. }
  2412. }
  2413. impl ToTokens for WindowsConfig {
  2414. fn to_tokens(&self, tokens: &mut TokenStream) {
  2415. let webview_install_mode = &self.webview_install_mode;
  2416. tokens.append_all(quote! { ::tauri::utils::config::WindowsConfig {
  2417. webview_install_mode: #webview_install_mode,
  2418. ..Default::default()
  2419. }})
  2420. }
  2421. }
  2422. impl ToTokens for BundleConfig {
  2423. fn to_tokens(&self, tokens: &mut TokenStream) {
  2424. let publisher = quote!(None);
  2425. let homepage = quote!(None);
  2426. let icon = vec_lit(&self.icon, str_lit);
  2427. let active = self.active;
  2428. let targets = quote!(Default::default());
  2429. let create_updater_artifacts = quote!(Default::default());
  2430. let resources = quote!(None);
  2431. let copyright = quote!(None);
  2432. let category = quote!(None);
  2433. let file_associations = quote!(None);
  2434. let short_description = quote!(None);
  2435. let long_description = quote!(None);
  2436. let use_local_tools_dir = self.use_local_tools_dir;
  2437. let external_bin = opt_vec_lit(self.external_bin.as_ref(), str_lit);
  2438. let windows = &self.windows;
  2439. let license = opt_str_lit(self.license.as_ref());
  2440. let license_file = opt_lit(self.license_file.as_ref().map(path_buf_lit).as_ref());
  2441. let linux = quote!(Default::default());
  2442. let macos = quote!(Default::default());
  2443. let ios = quote!(Default::default());
  2444. let android = quote!(Default::default());
  2445. literal_struct!(
  2446. tokens,
  2447. ::tauri::utils::config::BundleConfig,
  2448. active,
  2449. publisher,
  2450. homepage,
  2451. icon,
  2452. targets,
  2453. create_updater_artifacts,
  2454. resources,
  2455. copyright,
  2456. category,
  2457. license,
  2458. license_file,
  2459. file_associations,
  2460. short_description,
  2461. long_description,
  2462. use_local_tools_dir,
  2463. external_bin,
  2464. windows,
  2465. linux,
  2466. macos,
  2467. ios,
  2468. android
  2469. );
  2470. }
  2471. }
  2472. impl ToTokens for FrontendDist {
  2473. fn to_tokens(&self, tokens: &mut TokenStream) {
  2474. let prefix = quote! { ::tauri::utils::config::FrontendDist };
  2475. tokens.append_all(match self {
  2476. Self::Url(url) => {
  2477. let url = url_lit(url);
  2478. quote! { #prefix::Url(#url) }
  2479. }
  2480. Self::Directory(path) => {
  2481. let path = path_buf_lit(path);
  2482. quote! { #prefix::Directory(#path) }
  2483. }
  2484. Self::Files(files) => {
  2485. let files = vec_lit(files, path_buf_lit);
  2486. quote! { #prefix::Files(#files) }
  2487. }
  2488. })
  2489. }
  2490. }
  2491. impl ToTokens for BuildConfig {
  2492. fn to_tokens(&self, tokens: &mut TokenStream) {
  2493. let dev_url = opt_lit(self.dev_url.as_ref().map(url_lit).as_ref());
  2494. let frontend_dist = opt_lit(self.frontend_dist.as_ref());
  2495. let runner = quote!(None);
  2496. let before_dev_command = quote!(None);
  2497. let before_build_command = quote!(None);
  2498. let before_bundle_command = quote!(None);
  2499. let features = quote!(None);
  2500. literal_struct!(
  2501. tokens,
  2502. ::tauri::utils::config::BuildConfig,
  2503. runner,
  2504. dev_url,
  2505. frontend_dist,
  2506. before_dev_command,
  2507. before_build_command,
  2508. before_bundle_command,
  2509. features
  2510. );
  2511. }
  2512. }
  2513. impl ToTokens for CspDirectiveSources {
  2514. fn to_tokens(&self, tokens: &mut TokenStream) {
  2515. let prefix = quote! { ::tauri::utils::config::CspDirectiveSources };
  2516. tokens.append_all(match self {
  2517. Self::Inline(sources) => {
  2518. let sources = sources.as_str();
  2519. quote!(#prefix::Inline(#sources.into()))
  2520. }
  2521. Self::List(list) => {
  2522. let list = vec_lit(list, str_lit);
  2523. quote!(#prefix::List(#list))
  2524. }
  2525. })
  2526. }
  2527. }
  2528. impl ToTokens for Csp {
  2529. fn to_tokens(&self, tokens: &mut TokenStream) {
  2530. let prefix = quote! { ::tauri::utils::config::Csp };
  2531. tokens.append_all(match self {
  2532. Self::Policy(policy) => {
  2533. let policy = policy.as_str();
  2534. quote!(#prefix::Policy(#policy.into()))
  2535. }
  2536. Self::DirectiveMap(list) => {
  2537. let map = map_lit(
  2538. quote! { ::std::collections::HashMap },
  2539. list,
  2540. str_lit,
  2541. identity,
  2542. );
  2543. quote!(#prefix::DirectiveMap(#map))
  2544. }
  2545. })
  2546. }
  2547. }
  2548. impl ToTokens for DisabledCspModificationKind {
  2549. fn to_tokens(&self, tokens: &mut TokenStream) {
  2550. let prefix = quote! { ::tauri::utils::config::DisabledCspModificationKind };
  2551. tokens.append_all(match self {
  2552. Self::Flag(flag) => {
  2553. quote! { #prefix::Flag(#flag) }
  2554. }
  2555. Self::List(directives) => {
  2556. let directives = vec_lit(directives, str_lit);
  2557. quote! { #prefix::List(#directives) }
  2558. }
  2559. });
  2560. }
  2561. }
  2562. impl ToTokens for CapabilityEntry {
  2563. fn to_tokens(&self, tokens: &mut TokenStream) {
  2564. let prefix = quote! { ::tauri::utils::config::CapabilityEntry };
  2565. tokens.append_all(match self {
  2566. Self::Inlined(capability) => {
  2567. quote! { #prefix::Inlined(#capability) }
  2568. }
  2569. Self::Reference(id) => {
  2570. let id = str_lit(id);
  2571. quote! { #prefix::Reference(#id) }
  2572. }
  2573. });
  2574. }
  2575. }
  2576. impl ToTokens for SecurityConfig {
  2577. fn to_tokens(&self, tokens: &mut TokenStream) {
  2578. let csp = opt_lit(self.csp.as_ref());
  2579. let dev_csp = opt_lit(self.dev_csp.as_ref());
  2580. let freeze_prototype = self.freeze_prototype;
  2581. let dangerous_disable_asset_csp_modification = &self.dangerous_disable_asset_csp_modification;
  2582. let asset_protocol = &self.asset_protocol;
  2583. let pattern = &self.pattern;
  2584. let capabilities = vec_lit(&self.capabilities, identity);
  2585. literal_struct!(
  2586. tokens,
  2587. ::tauri::utils::config::SecurityConfig,
  2588. csp,
  2589. dev_csp,
  2590. freeze_prototype,
  2591. dangerous_disable_asset_csp_modification,
  2592. asset_protocol,
  2593. pattern,
  2594. capabilities
  2595. );
  2596. }
  2597. }
  2598. impl ToTokens for TrayIconConfig {
  2599. fn to_tokens(&self, tokens: &mut TokenStream) {
  2600. let id = opt_str_lit(self.id.as_ref());
  2601. let icon_as_template = self.icon_as_template;
  2602. let menu_on_left_click = self.menu_on_left_click;
  2603. let icon_path = path_buf_lit(&self.icon_path);
  2604. let title = opt_str_lit(self.title.as_ref());
  2605. let tooltip = opt_str_lit(self.tooltip.as_ref());
  2606. literal_struct!(
  2607. tokens,
  2608. ::tauri::utils::config::TrayIconConfig,
  2609. id,
  2610. icon_path,
  2611. icon_as_template,
  2612. menu_on_left_click,
  2613. title,
  2614. tooltip
  2615. );
  2616. }
  2617. }
  2618. impl ToTokens for FsScope {
  2619. fn to_tokens(&self, tokens: &mut TokenStream) {
  2620. let prefix = quote! { ::tauri::utils::config::FsScope };
  2621. tokens.append_all(match self {
  2622. Self::AllowedPaths(allow) => {
  2623. let allowed_paths = vec_lit(allow, path_buf_lit);
  2624. quote! { #prefix::AllowedPaths(#allowed_paths) }
  2625. }
  2626. Self::Scope { allow, deny , require_literal_leading_dot} => {
  2627. let allow = vec_lit(allow, path_buf_lit);
  2628. let deny = vec_lit(deny, path_buf_lit);
  2629. let require_literal_leading_dot = opt_lit(require_literal_leading_dot.as_ref());
  2630. quote! { #prefix::Scope { allow: #allow, deny: #deny, require_literal_leading_dot: #require_literal_leading_dot } }
  2631. }
  2632. });
  2633. }
  2634. }
  2635. impl ToTokens for AssetProtocolConfig {
  2636. fn to_tokens(&self, tokens: &mut TokenStream) {
  2637. let scope = &self.scope;
  2638. tokens.append_all(quote! { ::tauri::utils::config::AssetProtocolConfig { scope: #scope, ..Default::default() } })
  2639. }
  2640. }
  2641. impl ToTokens for AppConfig {
  2642. fn to_tokens(&self, tokens: &mut TokenStream) {
  2643. let windows = vec_lit(&self.windows, identity);
  2644. let security = &self.security;
  2645. let tray_icon = opt_lit(self.tray_icon.as_ref());
  2646. let macos_private_api = self.macos_private_api;
  2647. let with_global_tauri = self.with_global_tauri;
  2648. let enable_gtk_app_id = self.enable_gtk_app_id;
  2649. literal_struct!(
  2650. tokens,
  2651. ::tauri::utils::config::AppConfig,
  2652. windows,
  2653. security,
  2654. tray_icon,
  2655. macos_private_api,
  2656. with_global_tauri,
  2657. enable_gtk_app_id
  2658. );
  2659. }
  2660. }
  2661. impl ToTokens for PluginConfig {
  2662. fn to_tokens(&self, tokens: &mut TokenStream) {
  2663. let config = map_lit(
  2664. quote! { ::std::collections::HashMap },
  2665. &self.0,
  2666. str_lit,
  2667. json_value_lit,
  2668. );
  2669. tokens.append_all(quote! { ::tauri::utils::config::PluginConfig(#config) })
  2670. }
  2671. }
  2672. impl ToTokens for Config {
  2673. fn to_tokens(&self, tokens: &mut TokenStream) {
  2674. let schema = quote!(None);
  2675. let product_name = opt_str_lit(self.product_name.as_ref());
  2676. let main_binary_name = opt_str_lit(self.main_binary_name.as_ref());
  2677. let version = opt_str_lit(self.version.as_ref());
  2678. let identifier = str_lit(&self.identifier);
  2679. let app = &self.app;
  2680. let build = &self.build;
  2681. let bundle = &self.bundle;
  2682. let plugins = &self.plugins;
  2683. literal_struct!(
  2684. tokens,
  2685. ::tauri::utils::config::Config,
  2686. schema,
  2687. product_name,
  2688. main_binary_name,
  2689. version,
  2690. identifier,
  2691. app,
  2692. build,
  2693. bundle,
  2694. plugins
  2695. );
  2696. }
  2697. }
  2698. }
  2699. #[cfg(test)]
  2700. mod test {
  2701. use super::*;
  2702. // TODO: create a test that compares a config to a json config
  2703. #[test]
  2704. // test all of the default functions
  2705. fn test_defaults() {
  2706. // get default app config
  2707. let a_config = AppConfig::default();
  2708. // get default build config
  2709. let b_config = BuildConfig::default();
  2710. // get default window
  2711. let d_windows: Vec<WindowConfig> = vec![];
  2712. // get default bundle
  2713. let d_bundle = BundleConfig::default();
  2714. // create a tauri config.
  2715. let app = AppConfig {
  2716. windows: vec![],
  2717. security: SecurityConfig {
  2718. csp: None,
  2719. dev_csp: None,
  2720. freeze_prototype: false,
  2721. dangerous_disable_asset_csp_modification: DisabledCspModificationKind::Flag(false),
  2722. asset_protocol: AssetProtocolConfig::default(),
  2723. pattern: Default::default(),
  2724. capabilities: Vec::new(),
  2725. },
  2726. tray_icon: None,
  2727. macos_private_api: false,
  2728. with_global_tauri: false,
  2729. enable_gtk_app_id: false,
  2730. };
  2731. // create a build config
  2732. let build = BuildConfig {
  2733. runner: None,
  2734. dev_url: None,
  2735. frontend_dist: None,
  2736. before_dev_command: None,
  2737. before_build_command: None,
  2738. before_bundle_command: None,
  2739. features: None,
  2740. };
  2741. // create a bundle config
  2742. let bundle = BundleConfig {
  2743. active: false,
  2744. targets: Default::default(),
  2745. create_updater_artifacts: Default::default(),
  2746. publisher: None,
  2747. homepage: None,
  2748. icon: Vec::new(),
  2749. resources: None,
  2750. copyright: None,
  2751. category: None,
  2752. file_associations: None,
  2753. short_description: None,
  2754. long_description: None,
  2755. use_local_tools_dir: false,
  2756. license: None,
  2757. license_file: None,
  2758. linux: Default::default(),
  2759. macos: Default::default(),
  2760. external_bin: None,
  2761. windows: Default::default(),
  2762. ios: Default::default(),
  2763. android: Default::default(),
  2764. };
  2765. // test the configs
  2766. assert_eq!(a_config, app);
  2767. assert_eq!(b_config, build);
  2768. assert_eq!(d_bundle, bundle);
  2769. assert_eq!(d_windows, app.windows);
  2770. }
  2771. }