config.rs 99 KB

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