config.rs 138 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057
  1. // Copyright 2019-2023 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(target_os = "linux")]
  12. use heck::ToKebabCase;
  13. #[cfg(feature = "schema")]
  14. use schemars::JsonSchema;
  15. use semver::Version;
  16. use serde::{
  17. de::{Deserializer, Error as DeError, Visitor},
  18. Deserialize, Serialize, Serializer,
  19. };
  20. use serde_json::Value as JsonValue;
  21. use serde_with::skip_serializing_none;
  22. use url::Url;
  23. use std::{
  24. collections::HashMap,
  25. fmt::{self, Display},
  26. fs::read_to_string,
  27. path::PathBuf,
  28. str::FromStr,
  29. };
  30. /// Items to help with parsing content into a [`Config`].
  31. pub mod parse;
  32. use crate::TitleBarStyle;
  33. pub use self::parse::parse;
  34. fn default_true() -> bool {
  35. true
  36. }
  37. /// An URL to open on a Tauri webview window.
  38. #[derive(PartialEq, Eq, Debug, Clone, Deserialize, Serialize)]
  39. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  40. #[serde(untagged)]
  41. #[non_exhaustive]
  42. pub enum WindowUrl {
  43. /// An external URL.
  44. External(Url),
  45. /// The path portion of an app URL.
  46. /// For instance, to load `tauri://localhost/users/john`,
  47. /// you can simply provide `users/john` in this configuration.
  48. App(PathBuf),
  49. }
  50. impl fmt::Display for WindowUrl {
  51. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  52. match self {
  53. Self::External(url) => write!(f, "{url}"),
  54. Self::App(path) => write!(f, "{}", path.display()),
  55. }
  56. }
  57. }
  58. impl Default for WindowUrl {
  59. fn default() -> Self {
  60. Self::App("index.html".into())
  61. }
  62. }
  63. /// A bundle referenced by tauri-bundler.
  64. #[derive(Debug, PartialEq, Eq, Clone)]
  65. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  66. #[cfg_attr(feature = "schema", schemars(rename_all = "lowercase"))]
  67. pub enum BundleType {
  68. /// The debian bundle (.deb).
  69. Deb,
  70. /// The AppImage bundle (.appimage).
  71. AppImage,
  72. /// The Microsoft Installer bundle (.msi).
  73. Msi,
  74. /// The NSIS bundle (.exe).
  75. Nsis,
  76. /// The macOS application bundle (.app).
  77. App,
  78. /// The Apple Disk Image bundle (.dmg).
  79. Dmg,
  80. /// The Tauri updater bundle.
  81. Updater,
  82. }
  83. impl Display for BundleType {
  84. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  85. write!(
  86. f,
  87. "{}",
  88. match self {
  89. Self::Deb => "deb",
  90. Self::AppImage => "appimage",
  91. Self::Msi => "msi",
  92. Self::Nsis => "nsis",
  93. Self::App => "app",
  94. Self::Dmg => "dmg",
  95. Self::Updater => "updater",
  96. }
  97. )
  98. }
  99. }
  100. impl Serialize for BundleType {
  101. fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
  102. where
  103. S: Serializer,
  104. {
  105. serializer.serialize_str(self.to_string().as_ref())
  106. }
  107. }
  108. impl<'de> Deserialize<'de> for BundleType {
  109. fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
  110. where
  111. D: Deserializer<'de>,
  112. {
  113. let s = String::deserialize(deserializer)?;
  114. match s.to_lowercase().as_str() {
  115. "deb" => Ok(Self::Deb),
  116. "appimage" => Ok(Self::AppImage),
  117. "msi" => Ok(Self::Msi),
  118. "nsis" => Ok(Self::Nsis),
  119. "app" => Ok(Self::App),
  120. "dmg" => Ok(Self::Dmg),
  121. "updater" => Ok(Self::Updater),
  122. _ => Err(DeError::custom(format!("unknown bundle target '{s}'"))),
  123. }
  124. }
  125. }
  126. /// Targets to bundle. Each value is case insensitive.
  127. #[derive(Debug, PartialEq, Eq, Clone)]
  128. pub enum BundleTarget {
  129. /// Bundle all targets.
  130. All,
  131. /// A list of bundle targets.
  132. List(Vec<BundleType>),
  133. /// A single bundle target.
  134. One(BundleType),
  135. }
  136. #[cfg(feature = "schema")]
  137. impl schemars::JsonSchema for BundleTarget {
  138. fn schema_name() -> std::string::String {
  139. "BundleTarget".to_owned()
  140. }
  141. fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
  142. let any_of = vec![
  143. schemars::schema::SchemaObject {
  144. enum_values: Some(vec!["all".into()]),
  145. metadata: Some(Box::new(schemars::schema::Metadata {
  146. description: Some("Bundle all targets.".to_owned()),
  147. ..Default::default()
  148. })),
  149. ..Default::default()
  150. }
  151. .into(),
  152. schemars::_private::apply_metadata(
  153. gen.subschema_for::<Vec<BundleType>>(),
  154. schemars::schema::Metadata {
  155. description: Some("A list of bundle targets.".to_owned()),
  156. ..Default::default()
  157. },
  158. ),
  159. schemars::_private::apply_metadata(
  160. gen.subschema_for::<BundleType>(),
  161. schemars::schema::Metadata {
  162. description: Some("A single bundle target.".to_owned()),
  163. ..Default::default()
  164. },
  165. ),
  166. ];
  167. schemars::schema::SchemaObject {
  168. subschemas: Some(Box::new(schemars::schema::SubschemaValidation {
  169. any_of: Some(any_of),
  170. ..Default::default()
  171. })),
  172. metadata: Some(Box::new(schemars::schema::Metadata {
  173. description: Some("Targets to bundle. Each value is case insensitive.".to_owned()),
  174. ..Default::default()
  175. })),
  176. ..Default::default()
  177. }
  178. .into()
  179. }
  180. }
  181. impl Default for BundleTarget {
  182. fn default() -> Self {
  183. Self::All
  184. }
  185. }
  186. impl Serialize for BundleTarget {
  187. fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
  188. where
  189. S: Serializer,
  190. {
  191. match self {
  192. Self::All => serializer.serialize_str("all"),
  193. Self::List(l) => l.serialize(serializer),
  194. Self::One(t) => serializer.serialize_str(t.to_string().as_ref()),
  195. }
  196. }
  197. }
  198. impl<'de> Deserialize<'de> for BundleTarget {
  199. fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
  200. where
  201. D: Deserializer<'de>,
  202. {
  203. #[derive(Deserialize, Serialize)]
  204. #[serde(untagged)]
  205. pub enum BundleTargetInner {
  206. List(Vec<BundleType>),
  207. One(BundleType),
  208. All(String),
  209. }
  210. match BundleTargetInner::deserialize(deserializer)? {
  211. BundleTargetInner::All(s) if s.to_lowercase() == "all" => Ok(Self::All),
  212. BundleTargetInner::All(t) => Err(DeError::custom(format!("invalid bundle type {t}"))),
  213. BundleTargetInner::List(l) => Ok(Self::List(l)),
  214. BundleTargetInner::One(t) => Ok(Self::One(t)),
  215. }
  216. }
  217. }
  218. impl BundleTarget {
  219. /// Gets the bundle targets as a [`Vec`]. The vector is empty when set to [`BundleTarget::All`].
  220. #[allow(dead_code)]
  221. pub fn to_vec(&self) -> Vec<BundleType> {
  222. match self {
  223. Self::All => vec![],
  224. Self::List(list) => list.clone(),
  225. Self::One(i) => vec![i.clone()],
  226. }
  227. }
  228. }
  229. /// Configuration for AppImage bundles.
  230. ///
  231. /// See more: https://tauri.app/v1/api/config#appimageconfig
  232. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  233. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  234. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  235. pub struct AppImageConfig {
  236. /// Include additional gstreamer dependencies needed for audio and video playback.
  237. /// This increases the bundle size by ~15-35MB depending on your build system.
  238. #[serde(default, alias = "bundle-media-framework")]
  239. pub bundle_media_framework: bool,
  240. }
  241. /// Configuration for Debian (.deb) bundles.
  242. ///
  243. /// See more: https://tauri.app/v1/api/config#debconfig
  244. #[skip_serializing_none]
  245. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  246. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  247. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  248. pub struct DebConfig {
  249. /// The list of deb dependencies your application relies on.
  250. pub depends: Option<Vec<String>>,
  251. /// The files to include on the package.
  252. #[serde(default)]
  253. pub files: HashMap<PathBuf, PathBuf>,
  254. /// Path to a custom desktop file Handlebars template.
  255. ///
  256. /// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
  257. pub desktop_template: Option<PathBuf>,
  258. }
  259. fn de_minimum_system_version<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
  260. where
  261. D: Deserializer<'de>,
  262. {
  263. let version = Option::<String>::deserialize(deserializer)?;
  264. match version {
  265. Some(v) if v.is_empty() => Ok(minimum_system_version()),
  266. e => Ok(e),
  267. }
  268. }
  269. /// Configuration for the macOS bundles.
  270. ///
  271. /// See more: https://tauri.app/v1/api/config#macconfig
  272. #[skip_serializing_none]
  273. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  274. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  275. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  276. pub struct MacConfig {
  277. /// A list of strings indicating any macOS X frameworks that need to be bundled with the application.
  278. ///
  279. /// 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.
  280. pub frameworks: Option<Vec<String>>,
  281. /// A version string indicating the minimum macOS X version that the bundled application supports. Defaults to `10.13`.
  282. ///
  283. /// Setting it to `null` completely removes the `LSMinimumSystemVersion` field on the bundle's `Info.plist`
  284. /// and the `MACOSX_DEPLOYMENT_TARGET` environment variable.
  285. ///
  286. /// An empty string is considered an invalid value so the default value is used.
  287. #[serde(
  288. deserialize_with = "de_minimum_system_version",
  289. default = "minimum_system_version",
  290. alias = "minimum-system-version"
  291. )]
  292. pub minimum_system_version: Option<String>,
  293. /// Allows your application to communicate with the outside world.
  294. /// It should be a lowercase, without port and protocol domain name.
  295. #[serde(alias = "exception-domain")]
  296. pub exception_domain: Option<String>,
  297. /// The path to the license file to add to the DMG bundle.
  298. pub license: Option<String>,
  299. /// Identity to use for code signing.
  300. #[serde(alias = "signing-identity")]
  301. pub signing_identity: Option<String>,
  302. /// Provider short name for notarization.
  303. #[serde(alias = "provider-short-name")]
  304. pub provider_short_name: Option<String>,
  305. /// Path to the entitlements file.
  306. pub entitlements: Option<String>,
  307. }
  308. impl Default for MacConfig {
  309. fn default() -> Self {
  310. Self {
  311. frameworks: None,
  312. minimum_system_version: minimum_system_version(),
  313. exception_domain: None,
  314. license: None,
  315. signing_identity: None,
  316. provider_short_name: None,
  317. entitlements: None,
  318. }
  319. }
  320. }
  321. fn minimum_system_version() -> Option<String> {
  322. Some("10.13".into())
  323. }
  324. /// Configuration for a target language for the WiX build.
  325. ///
  326. /// See more: https://tauri.app/v1/api/config#wixlanguageconfig
  327. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  328. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  329. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  330. pub struct WixLanguageConfig {
  331. /// The path to a locale (`.wxl`) file. See <https://wixtoolset.org/documentation/manual/v3/howtos/ui_and_localization/build_a_localized_version.html>.
  332. #[serde(alias = "locale-path")]
  333. pub locale_path: Option<String>,
  334. }
  335. /// The languages to build using WiX.
  336. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  337. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  338. #[serde(untagged)]
  339. pub enum WixLanguage {
  340. /// A single language to build, without configuration.
  341. One(String),
  342. /// A list of languages to build, without configuration.
  343. List(Vec<String>),
  344. /// A map of languages and its configuration.
  345. Localized(HashMap<String, WixLanguageConfig>),
  346. }
  347. impl Default for WixLanguage {
  348. fn default() -> Self {
  349. Self::One("en-US".into())
  350. }
  351. }
  352. /// Configuration for the MSI bundle using WiX.
  353. ///
  354. /// See more: https://tauri.app/v1/api/config#wixconfig
  355. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  356. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  357. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  358. pub struct WixConfig {
  359. /// The installer languages to build. See <https://docs.microsoft.com/en-us/windows/win32/msi/localizing-the-error-and-actiontext-tables>.
  360. #[serde(default)]
  361. pub language: WixLanguage,
  362. /// A custom .wxs template to use.
  363. pub template: Option<PathBuf>,
  364. /// A list of paths to .wxs files with WiX fragments to use.
  365. #[serde(default, alias = "fragment-paths")]
  366. pub fragment_paths: Vec<PathBuf>,
  367. /// The ComponentGroup element ids you want to reference from the fragments.
  368. #[serde(default, alias = "component-group-refs")]
  369. pub component_group_refs: Vec<String>,
  370. /// The Component element ids you want to reference from the fragments.
  371. #[serde(default, alias = "component-refs")]
  372. pub component_refs: Vec<String>,
  373. /// The FeatureGroup element ids you want to reference from the fragments.
  374. #[serde(default, alias = "feature-group-refs")]
  375. pub feature_group_refs: Vec<String>,
  376. /// The Feature element ids you want to reference from the fragments.
  377. #[serde(default, alias = "feature-refs")]
  378. pub feature_refs: Vec<String>,
  379. /// The Merge element ids you want to reference from the fragments.
  380. #[serde(default, alias = "merge-refs")]
  381. pub merge_refs: Vec<String>,
  382. /// Disables the Webview2 runtime installation after app install.
  383. ///
  384. /// Will be removed in v2, prefer the [`WindowsConfig::webview_install_mode`] option.
  385. #[serde(default, alias = "skip-webview-install")]
  386. pub skip_webview_install: bool,
  387. /// The path to the license file to render on the installer.
  388. ///
  389. /// Must be an RTF file, so if a different extension is provided, we convert it to the RTF format.
  390. pub license: Option<PathBuf>,
  391. /// Create an elevated update task within Windows Task Scheduler.
  392. #[serde(default, alias = "enable-elevated-update-task")]
  393. pub enable_elevated_update_task: bool,
  394. /// Path to a bitmap file to use as the installation user interface banner.
  395. /// This bitmap will appear at the top of all but the first page of the installer.
  396. ///
  397. /// The required dimensions are 493px × 58px.
  398. #[serde(alias = "banner-path")]
  399. pub banner_path: Option<PathBuf>,
  400. /// Path to a bitmap file to use on the installation user interface dialogs.
  401. /// It is used on the welcome and completion dialogs.
  402. /// The required dimensions are 493px × 312px.
  403. #[serde(alias = "dialog-image-path")]
  404. pub dialog_image_path: Option<PathBuf>,
  405. }
  406. /// Compression algorithms used in the NSIS installer.
  407. ///
  408. /// See <https://nsis.sourceforge.io/Reference/SetCompressor>
  409. #[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
  410. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  411. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  412. pub enum NsisCompression {
  413. /// ZLIB uses the deflate algorithm, it is a quick and simple method. With the default compression level it uses about 300 KB of memory.
  414. Zlib,
  415. /// 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.
  416. Bzip2,
  417. /// 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.
  418. Lzma,
  419. }
  420. /// Configuration for the Installer bundle using NSIS.
  421. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  422. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  423. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  424. pub struct NsisConfig {
  425. /// A custom .nsi template to use.
  426. pub template: Option<PathBuf>,
  427. /// The path to the license file to render on the installer.
  428. pub license: Option<PathBuf>,
  429. /// The path to a bitmap file to display on the header of installers pages.
  430. ///
  431. /// The recommended dimensions are 150px x 57px.
  432. #[serde(alias = "header-image")]
  433. pub header_image: Option<PathBuf>,
  434. /// The path to a bitmap file for the Welcome page and the Finish page.
  435. ///
  436. /// The recommended dimensions are 164px x 314px.
  437. #[serde(alias = "sidebar-image")]
  438. pub sidebar_image: Option<PathBuf>,
  439. /// The path to an icon file used as the installer icon.
  440. #[serde(alias = "install-icon")]
  441. pub installer_icon: Option<PathBuf>,
  442. /// Whether the installation will be for all users or just the current user.
  443. #[serde(default, alias = "install-mode")]
  444. pub install_mode: NSISInstallerMode,
  445. /// A list of installer languages.
  446. /// By default the OS language is used. If the OS language is not in the list of languages, the first language will be used.
  447. /// To allow the user to select the language, set `display_language_selector` to `true`.
  448. ///
  449. /// See <https://github.com/kichik/nsis/tree/9465c08046f00ccb6eda985abbdbf52c275c6c4d/Contrib/Language%20files> for the complete list of languages.
  450. pub languages: Option<Vec<String>>,
  451. /// A key-value pair where the key is the language and the
  452. /// value is the path to a custom `.nsh` file that holds the translated text for tauri's custom messages.
  453. ///
  454. /// See <https://github.com/tauri-apps/tauri/blob/dev/tooling/bundler/src/bundle/windows/templates/nsis-languages/English.nsh> for an example `.nsh` file.
  455. ///
  456. /// **Note**: the key must be a valid NSIS language and it must be added to [`NsisConfig`] languages array,
  457. pub custom_language_files: Option<HashMap<String, PathBuf>>,
  458. /// Whether to display a language selector dialog before the installer and uninstaller windows are rendered or not.
  459. /// By default the OS language is selected, with a fallback to the first language in the `languages` array.
  460. #[serde(default, alias = "display-language-selector")]
  461. pub display_language_selector: bool,
  462. /// Set the compression algorithm used to compress files in the installer.
  463. ///
  464. /// See <https://nsis.sourceforge.io/Reference/SetCompressor>
  465. pub compression: Option<NsisCompression>,
  466. }
  467. /// Install Modes for the NSIS installer.
  468. #[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
  469. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  470. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  471. pub enum NSISInstallerMode {
  472. /// Default mode for the installer.
  473. ///
  474. /// Install the app by default in a directory that doesn't require Administrator access.
  475. ///
  476. /// Installer metadata will be saved under the `HKCU` registry path.
  477. CurrentUser,
  478. /// Install the app by default in the `Program Files` folder directory requires Administrator
  479. /// access for the installation.
  480. ///
  481. /// Installer metadata will be saved under the `HKLM` registry path.
  482. PerMachine,
  483. /// Combines both modes and allows the user to choose at install time
  484. /// whether to install for the current user or per machine. Note that this mode
  485. /// will require Administrator access even if the user wants to install it for the current user only.
  486. ///
  487. /// Installer metadata will be saved under the `HKLM` or `HKCU` registry path based on the user's choice.
  488. Both,
  489. }
  490. impl Default for NSISInstallerMode {
  491. fn default() -> Self {
  492. Self::CurrentUser
  493. }
  494. }
  495. /// Install modes for the Webview2 runtime.
  496. /// Note that for the updater bundle [`Self::DownloadBootstrapper`] is used.
  497. ///
  498. /// For more information see <https://tauri.app/v1/guides/building/windows>.
  499. #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
  500. #[serde(tag = "type", rename_all = "camelCase", deny_unknown_fields)]
  501. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  502. pub enum WebviewInstallMode {
  503. /// Do not install the Webview2 as part of the Windows Installer.
  504. Skip,
  505. /// Download the bootstrapper and run it.
  506. /// Requires an internet connection.
  507. /// Results in a smaller installer size, but is not recommended on Windows 7.
  508. DownloadBootstrapper {
  509. /// Instructs the installer to run the bootstrapper in silent mode. Defaults to `true`.
  510. #[serde(default = "default_true")]
  511. silent: bool,
  512. },
  513. /// Embed the bootstrapper and run it.
  514. /// Requires an internet connection.
  515. /// Increases the installer size by around 1.8MB, but offers better support on Windows 7.
  516. EmbedBootstrapper {
  517. /// Instructs the installer to run the bootstrapper in silent mode. Defaults to `true`.
  518. #[serde(default = "default_true")]
  519. silent: bool,
  520. },
  521. /// Embed the offline installer and run it.
  522. /// Does not require an internet connection.
  523. /// Increases the installer size by around 127MB.
  524. OfflineInstaller {
  525. /// Instructs the installer to run the installer in silent mode. Defaults to `true`.
  526. #[serde(default = "default_true")]
  527. silent: bool,
  528. },
  529. /// Embed a fixed webview2 version and use it at runtime.
  530. /// Increases the installer size by around 180MB.
  531. FixedRuntime {
  532. /// The path to the fixed runtime to use.
  533. ///
  534. /// The fixed version can be downloaded [on the official website](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section).
  535. /// The `.cab` file must be extracted to a folder and this folder path must be defined on this field.
  536. path: PathBuf,
  537. },
  538. }
  539. impl Default for WebviewInstallMode {
  540. fn default() -> Self {
  541. Self::DownloadBootstrapper { silent: true }
  542. }
  543. }
  544. /// Windows bundler configuration.
  545. ///
  546. /// See more: https://tauri.app/v1/api/config#windowsconfig
  547. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  548. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  549. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  550. pub struct WindowsConfig {
  551. /// Specifies the file digest algorithm to use for creating file signatures.
  552. /// Required for code signing. SHA-256 is recommended.
  553. #[serde(alias = "digest-algorithm")]
  554. pub digest_algorithm: Option<String>,
  555. /// Specifies the SHA1 hash of the signing certificate.
  556. #[serde(alias = "certificate-thumbprint")]
  557. pub certificate_thumbprint: Option<String>,
  558. /// Server to use during timestamping.
  559. #[serde(alias = "timestamp-url")]
  560. pub timestamp_url: Option<String>,
  561. /// Whether to use Time-Stamp Protocol (TSP, a.k.a. RFC 3161) for the timestamp server. Your code signing provider may
  562. /// use a TSP timestamp server, like e.g. SSL.com does. If so, enable TSP by setting to true.
  563. #[serde(default)]
  564. pub tsp: bool,
  565. /// The installation mode for the Webview2 runtime.
  566. #[serde(default, alias = "webview-install-mode")]
  567. pub webview_install_mode: WebviewInstallMode,
  568. /// Path to the webview fixed runtime to use. Overwrites [`Self::webview_install_mode`] if set.
  569. ///
  570. /// Will be removed in v2, prefer the [`Self::webview_install_mode`] option.
  571. ///
  572. /// The fixed version can be downloaded [on the official website](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section).
  573. /// The `.cab` file must be extracted to a folder and this folder path must be defined on this field.
  574. #[serde(alias = "webview-fixed-runtime-path")]
  575. pub webview_fixed_runtime_path: Option<PathBuf>,
  576. /// Validates a second app installation, blocking the user from installing an older version if set to `false`.
  577. ///
  578. /// 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`.
  579. ///
  580. /// The default value of this flag is `true`.
  581. #[serde(default = "default_true", alias = "allow-downgrades")]
  582. pub allow_downgrades: bool,
  583. /// Configuration for the MSI generated with WiX.
  584. pub wix: Option<WixConfig>,
  585. /// Configuration for the installer generated with NSIS.
  586. pub nsis: Option<NsisConfig>,
  587. }
  588. impl Default for WindowsConfig {
  589. fn default() -> Self {
  590. Self {
  591. digest_algorithm: None,
  592. certificate_thumbprint: None,
  593. timestamp_url: None,
  594. tsp: false,
  595. webview_install_mode: Default::default(),
  596. webview_fixed_runtime_path: None,
  597. allow_downgrades: true,
  598. wix: None,
  599. nsis: None,
  600. }
  601. }
  602. }
  603. /// Definition for bundle resources.
  604. /// Can be either a list of paths to include or a map of source to target paths.
  605. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  606. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  607. #[serde(rename_all = "camelCase", deny_unknown_fields, untagged)]
  608. pub enum BundleResources {
  609. /// A list of paths to include.
  610. List(Vec<String>),
  611. /// A map of source to target paths.
  612. Map(HashMap<String, String>),
  613. }
  614. impl BundleResources {
  615. /// Adds a path to the resource collection.
  616. pub fn push(&mut self, path: impl Into<String>) {
  617. match self {
  618. Self::List(l) => l.push(path.into()),
  619. Self::Map(l) => {
  620. let path = path.into();
  621. l.insert(path.clone(), path);
  622. }
  623. }
  624. }
  625. }
  626. /// Configuration for tauri-bundler.
  627. ///
  628. /// See more: https://tauri.app/v1/api/config#bundleconfig
  629. #[skip_serializing_none]
  630. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  631. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  632. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  633. pub struct BundleConfig {
  634. /// Whether Tauri should bundle your application or just output the executable.
  635. #[serde(default)]
  636. pub active: bool,
  637. /// The bundle targets, currently supports ["deb", "appimage", "nsis", "msi", "app", "dmg", "updater"] or "all".
  638. #[serde(default)]
  639. pub targets: BundleTarget,
  640. /// The application identifier in reverse domain name notation (e.g. `com.tauri.example`).
  641. /// This string must be unique across applications since it is used in system configurations like
  642. /// the bundle ID and path to the webview data directory.
  643. /// This string must contain only alphanumeric characters (A–Z, a–z, and 0–9), hyphens (-),
  644. /// and periods (.).
  645. pub identifier: String,
  646. /// The application's publisher. Defaults to the second element in the identifier string.
  647. /// Currently maps to the Manufacturer property of the Windows Installer.
  648. pub publisher: Option<String>,
  649. /// The app's icons
  650. #[serde(default)]
  651. pub icon: Vec<String>,
  652. /// App resources to bundle.
  653. /// Each resource is a path to a file or directory.
  654. /// Glob patterns are supported.
  655. pub resources: Option<BundleResources>,
  656. /// A copyright string associated with your application.
  657. pub copyright: Option<String>,
  658. /// The application kind.
  659. ///
  660. /// Should be one of the following:
  661. /// 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.
  662. pub category: Option<String>,
  663. /// A short description of your application.
  664. #[serde(alias = "short-description")]
  665. pub short_description: Option<String>,
  666. /// A longer, multi-line description of the application.
  667. #[serde(alias = "long-description")]
  668. pub long_description: Option<String>,
  669. /// Configuration for the AppImage bundle.
  670. #[serde(default)]
  671. pub appimage: AppImageConfig,
  672. /// Configuration for the Debian bundle.
  673. #[serde(default)]
  674. pub deb: DebConfig,
  675. /// Configuration for the macOS bundles.
  676. #[serde(rename = "macOS", default)]
  677. pub macos: MacConfig,
  678. /// A list of—either absolute or relative—paths to binaries to embed with your application.
  679. ///
  680. /// Note that Tauri will look for system-specific binaries following the pattern "binary-name{-target-triple}{.system-extension}".
  681. ///
  682. /// E.g. for the external binary "my-binary", Tauri looks for:
  683. ///
  684. /// - "my-binary-x86_64-pc-windows-msvc.exe" for Windows
  685. /// - "my-binary-x86_64-apple-darwin" for macOS
  686. /// - "my-binary-x86_64-unknown-linux-gnu" for Linux
  687. ///
  688. /// so don't forget to provide binaries for all targeted platforms.
  689. #[serde(alias = "external-bin")]
  690. pub external_bin: Option<Vec<String>>,
  691. /// Configuration for the Windows bundle.
  692. #[serde(default)]
  693. pub windows: WindowsConfig,
  694. }
  695. /// A CLI argument definition.
  696. #[skip_serializing_none]
  697. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  698. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  699. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  700. pub struct CliArg {
  701. /// The short version of the argument, without the preceding -.
  702. ///
  703. /// NOTE: Any leading `-` characters will be stripped, and only the first non-character will be used as the short version.
  704. pub short: Option<char>,
  705. /// The unique argument name
  706. pub name: String,
  707. /// The argument description which will be shown on the help information.
  708. /// Typically, this is a short (one line) description of the arg.
  709. pub description: Option<String>,
  710. /// The argument long description which will be shown on the help information.
  711. /// Typically this a more detailed (multi-line) message that describes the argument.
  712. #[serde(alias = "long-description")]
  713. pub long_description: Option<String>,
  714. /// Specifies that the argument takes a value at run time.
  715. ///
  716. /// NOTE: values for arguments may be specified in any of the following methods
  717. /// - Using a space such as -o value or --option value
  718. /// - Using an equals and no space such as -o=value or --option=value
  719. /// - Use a short and no space such as -ovalue
  720. #[serde(default, alias = "takes-value")]
  721. pub takes_value: bool,
  722. /// Specifies that the argument may have an unknown number of multiple values. Without any other settings, this argument may appear only once.
  723. ///
  724. /// For example, --opt val1 val2 is allowed, but --opt val1 val2 --opt val3 is not.
  725. ///
  726. /// NOTE: Setting this requires `takes_value` to be set to true.
  727. #[serde(default)]
  728. pub multiple: bool,
  729. /// Specifies that the argument may appear more than once.
  730. /// For flags, this results in the number of occurrences of the flag being recorded. For example -ddd or -d -d -d would count as three occurrences.
  731. /// For options or arguments that take a value, this does not affect how many values they can accept. (i.e. only one at a time is allowed)
  732. ///
  733. /// For example, --opt val1 --opt val2 is allowed, but --opt val1 val2 is not.
  734. #[serde(default, alias = "multiple-occurrences")]
  735. pub multiple_occurrences: bool,
  736. /// Specifies how many values are required to satisfy this argument. For example, if you had a
  737. /// `-f <file>` argument where you wanted exactly 3 'files' you would set
  738. /// `number_of_values = 3`, and this argument wouldn't be satisfied unless the user provided
  739. /// 3 and only 3 values.
  740. ///
  741. /// **NOTE:** Does *not* require `multiple_occurrences = true` to be set. Setting
  742. /// `multiple_occurrences = true` would allow `-f <file> <file> <file> -f <file> <file> <file>` where
  743. /// as *not* setting it would only allow one occurrence of this argument.
  744. ///
  745. /// **NOTE:** implicitly sets `takes_value = true` and `multiple_values = true`.
  746. #[serde(alias = "number-of-values")]
  747. pub number_of_values: Option<usize>,
  748. /// Specifies a list of possible values for this argument.
  749. /// At runtime, the CLI verifies that only one of the specified values was used, or fails with an error message.
  750. #[serde(alias = "possible-values")]
  751. pub possible_values: Option<Vec<String>>,
  752. /// Specifies the minimum number of values for this argument.
  753. /// For example, if you had a -f `<file>` argument where you wanted at least 2 'files',
  754. /// you would set `minValues: 2`, and this argument would be satisfied if the user provided, 2 or more values.
  755. #[serde(alias = "min-values")]
  756. pub min_values: Option<usize>,
  757. /// Specifies the maximum number of values are for this argument.
  758. /// For example, if you had a -f `<file>` argument where you wanted up to 3 'files',
  759. /// you would set .max_values(3), and this argument would be satisfied if the user provided, 1, 2, or 3 values.
  760. #[serde(alias = "max-values")]
  761. pub max_values: Option<usize>,
  762. /// Sets whether or not the argument is required by default.
  763. ///
  764. /// - Required by default means it is required, when no other conflicting rules have been evaluated
  765. /// - Conflicting rules take precedence over being required.
  766. #[serde(default)]
  767. pub required: bool,
  768. /// Sets an arg that override this arg's required setting
  769. /// i.e. this arg will be required unless this other argument is present.
  770. #[serde(alias = "required-unless-present")]
  771. pub required_unless_present: Option<String>,
  772. /// Sets args that override this arg's required setting
  773. /// i.e. this arg will be required unless all these other arguments are present.
  774. #[serde(alias = "required-unless-present-all")]
  775. pub required_unless_present_all: Option<Vec<String>>,
  776. /// Sets args that override this arg's required setting
  777. /// i.e. this arg will be required unless at least one of these other arguments are present.
  778. #[serde(alias = "required-unless-present-any")]
  779. pub required_unless_present_any: Option<Vec<String>>,
  780. /// Sets a conflicting argument by name
  781. /// i.e. when using this argument, the following argument can't be present and vice versa.
  782. #[serde(alias = "conflicts-with")]
  783. pub conflicts_with: Option<String>,
  784. /// The same as conflictsWith but allows specifying multiple two-way conflicts per argument.
  785. #[serde(alias = "conflicts-with-all")]
  786. pub conflicts_with_all: Option<Vec<String>>,
  787. /// Tets an argument by name that is required when this one is present
  788. /// i.e. when using this argument, the following argument must be present.
  789. pub requires: Option<String>,
  790. /// Sts multiple arguments by names that are required when this one is present
  791. /// i.e. when using this argument, the following arguments must be present.
  792. #[serde(alias = "requires-all")]
  793. pub requires_all: Option<Vec<String>>,
  794. /// Allows a conditional requirement with the signature [arg, value]
  795. /// the requirement will only become valid if `arg`'s value equals `${value}`.
  796. #[serde(alias = "requires-if")]
  797. pub requires_if: Option<Vec<String>>,
  798. /// Allows specifying that an argument is required conditionally with the signature [arg, value]
  799. /// the requirement will only become valid if the `arg`'s value equals `${value}`.
  800. #[serde(alias = "requires-if-eq")]
  801. pub required_if_eq: Option<Vec<String>>,
  802. /// Requires that options use the --option=val syntax
  803. /// i.e. an equals between the option and associated value.
  804. #[serde(alias = "requires-equals")]
  805. pub require_equals: Option<bool>,
  806. /// The positional argument index, starting at 1.
  807. ///
  808. /// The index refers to position according to other positional argument.
  809. /// It does not define position in the argument list as a whole. When utilized with multiple=true,
  810. /// only the last positional argument may be defined as multiple (i.e. the one with the highest index).
  811. #[cfg_attr(feature = "schema", validate(range(min = 1)))]
  812. pub index: Option<usize>,
  813. }
  814. /// describes a CLI configuration
  815. ///
  816. /// See more: https://tauri.app/v1/api/config#cliconfig
  817. #[skip_serializing_none]
  818. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  819. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  820. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  821. pub struct CliConfig {
  822. /// Command description which will be shown on the help information.
  823. pub description: Option<String>,
  824. /// Command long description which will be shown on the help information.
  825. #[serde(alias = "long-description")]
  826. pub long_description: Option<String>,
  827. /// Adds additional help information to be displayed in addition to auto-generated help.
  828. /// This information is displayed before the auto-generated help information.
  829. /// This is often used for header information.
  830. #[serde(alias = "before-help")]
  831. pub before_help: Option<String>,
  832. /// Adds additional help information to be displayed in addition to auto-generated help.
  833. /// This information is displayed after the auto-generated help information.
  834. /// This is often used to describe how to use the arguments, or caveats to be noted.
  835. #[serde(alias = "after-help")]
  836. pub after_help: Option<String>,
  837. /// List of arguments for the command
  838. pub args: Option<Vec<CliArg>>,
  839. /// List of subcommands of this command
  840. pub subcommands: Option<HashMap<String, CliConfig>>,
  841. }
  842. impl CliConfig {
  843. /// List of arguments for the command
  844. pub fn args(&self) -> Option<&Vec<CliArg>> {
  845. self.args.as_ref()
  846. }
  847. /// List of subcommands of this command
  848. pub fn subcommands(&self) -> Option<&HashMap<String, CliConfig>> {
  849. self.subcommands.as_ref()
  850. }
  851. /// Command description which will be shown on the help information.
  852. pub fn description(&self) -> Option<&String> {
  853. self.description.as_ref()
  854. }
  855. /// Command long description which will be shown on the help information.
  856. pub fn long_description(&self) -> Option<&String> {
  857. self.description.as_ref()
  858. }
  859. /// Adds additional help information to be displayed in addition to auto-generated help.
  860. /// This information is displayed before the auto-generated help information.
  861. /// This is often used for header information.
  862. pub fn before_help(&self) -> Option<&String> {
  863. self.before_help.as_ref()
  864. }
  865. /// Adds additional help information to be displayed in addition to auto-generated help.
  866. /// This information is displayed after the auto-generated help information.
  867. /// This is often used to describe how to use the arguments, or caveats to be noted.
  868. pub fn after_help(&self) -> Option<&String> {
  869. self.after_help.as_ref()
  870. }
  871. }
  872. /// The window configuration object.
  873. ///
  874. /// See more: https://tauri.app/v1/api/config#windowconfig
  875. #[skip_serializing_none]
  876. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  877. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  878. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  879. pub struct WindowConfig {
  880. /// The window identifier. It must be alphanumeric.
  881. #[serde(default = "default_window_label")]
  882. pub label: String,
  883. /// The window webview URL.
  884. #[serde(default)]
  885. pub url: WindowUrl,
  886. /// The user agent for the webview
  887. #[serde(alias = "user-agent")]
  888. pub user_agent: Option<String>,
  889. /// Whether the file drop is enabled or not on the webview. By default it is enabled.
  890. ///
  891. /// Disabling it is required to use drag and drop on the frontend on Windows.
  892. #[serde(default = "default_true", alias = "file-drop-enabled")]
  893. pub file_drop_enabled: bool,
  894. /// Whether or not the window starts centered or not.
  895. #[serde(default)]
  896. pub center: bool,
  897. /// The horizontal position of the window's top left corner
  898. pub x: Option<f64>,
  899. /// The vertical position of the window's top left corner
  900. pub y: Option<f64>,
  901. /// The window width.
  902. #[serde(default = "default_width")]
  903. pub width: f64,
  904. /// The window height.
  905. #[serde(default = "default_height")]
  906. pub height: f64,
  907. /// The min window width.
  908. #[serde(alias = "min-width")]
  909. pub min_width: Option<f64>,
  910. /// The min window height.
  911. #[serde(alias = "min-height")]
  912. pub min_height: Option<f64>,
  913. /// The max window width.
  914. #[serde(alias = "max-width")]
  915. pub max_width: Option<f64>,
  916. /// The max window height.
  917. #[serde(alias = "max-height")]
  918. pub max_height: Option<f64>,
  919. /// Whether the window is resizable or not. When resizable is set to false, native window's maximize button is automatically disabled.
  920. #[serde(default = "default_true")]
  921. pub resizable: bool,
  922. /// Whether the window's native maximize button is enabled or not.
  923. /// If resizable is set to false, this setting is ignored.
  924. ///
  925. /// ## Platform-specific
  926. ///
  927. /// - **macOS:** Disables the "zoom" button in the window titlebar, which is also used to enter fullscreen mode.
  928. /// - **Linux / iOS / Android:** Unsupported.
  929. #[serde(default = "default_true")]
  930. pub maximizable: bool,
  931. /// Whether the window's native minimize button is enabled or not.
  932. ///
  933. /// ## Platform-specific
  934. ///
  935. /// - **Linux / iOS / Android:** Unsupported.
  936. #[serde(default = "default_true")]
  937. pub minimizable: bool,
  938. /// Whether the window's native close button is enabled or not.
  939. ///
  940. /// ## Platform-specific
  941. ///
  942. /// - **Linux:** "GTK+ will do its best to convince the window manager not to show a close button.
  943. /// Depending on the system, this function may not have any effect when called on a window that is already visible"
  944. /// - **iOS / Android:** Unsupported.
  945. #[serde(default = "default_true")]
  946. pub closable: bool,
  947. /// The window title.
  948. #[serde(default = "default_title")]
  949. pub title: String,
  950. /// Whether the window starts as fullscreen or not.
  951. #[serde(default)]
  952. pub fullscreen: bool,
  953. /// Whether the window will be initially focused or not.
  954. #[serde(default = "default_true")]
  955. pub focus: bool,
  956. /// Whether the window is transparent or not.
  957. ///
  958. /// Note that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri > macOSPrivateApi`.
  959. /// WARNING: Using private APIs on `macOS` prevents your application from being accepted to the `App Store`.
  960. #[serde(default)]
  961. pub transparent: bool,
  962. /// Whether the window is maximized or not.
  963. #[serde(default)]
  964. pub maximized: bool,
  965. /// Whether the window is visible or not.
  966. #[serde(default = "default_true")]
  967. pub visible: bool,
  968. /// Whether the window should have borders and bars.
  969. #[serde(default = "default_true")]
  970. pub decorations: bool,
  971. /// Whether the window should always be on top of other windows.
  972. #[serde(default, alias = "always-on-top")]
  973. pub always_on_top: bool,
  974. /// Prevents the window contents from being captured by other apps.
  975. #[serde(default, alias = "content-protected")]
  976. pub content_protected: bool,
  977. /// If `true`, hides the window icon from the taskbar on Windows and Linux.
  978. #[serde(default, alias = "skip-taskbar")]
  979. pub skip_taskbar: bool,
  980. /// The initial window theme. Defaults to the system theme. Only implemented on Windows and macOS 10.14+.
  981. pub theme: Option<crate::Theme>,
  982. /// The style of the macOS title bar.
  983. #[serde(default, alias = "title-bar-style")]
  984. pub title_bar_style: TitleBarStyle,
  985. /// If `true`, sets the window title to be hidden on macOS.
  986. #[serde(default, alias = "hidden-title")]
  987. pub hidden_title: bool,
  988. /// Whether clicking an inactive window also clicks through to the webview on macOS.
  989. #[serde(default, alias = "accept-first-mouse")]
  990. pub accept_first_mouse: bool,
  991. /// Defines the window [tabbing identifier] for macOS.
  992. ///
  993. /// Windows with matching tabbing identifiers will be grouped together.
  994. /// If the tabbing identifier is not set, automatic tabbing will be disabled.
  995. ///
  996. /// [tabbing identifier]: <https://developer.apple.com/documentation/appkit/nswindow/1644704-tabbingidentifier>
  997. #[serde(default, alias = "tabbing-identifier")]
  998. pub tabbing_identifier: Option<String>,
  999. /// Defines additional browser arguments on Windows. By default wry passes `--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection`
  1000. /// so if you use this method, you also need to disable these components by yourself if you want.
  1001. #[serde(default, alias = "additional-browser-args")]
  1002. pub additional_browser_args: Option<String>,
  1003. }
  1004. impl Default for WindowConfig {
  1005. fn default() -> Self {
  1006. Self {
  1007. label: default_window_label(),
  1008. url: WindowUrl::default(),
  1009. user_agent: None,
  1010. file_drop_enabled: true,
  1011. center: false,
  1012. x: None,
  1013. y: None,
  1014. width: default_width(),
  1015. height: default_height(),
  1016. min_width: None,
  1017. min_height: None,
  1018. max_width: None,
  1019. max_height: None,
  1020. resizable: true,
  1021. maximizable: true,
  1022. minimizable: true,
  1023. closable: true,
  1024. title: default_title(),
  1025. fullscreen: false,
  1026. focus: false,
  1027. transparent: false,
  1028. maximized: false,
  1029. visible: true,
  1030. decorations: true,
  1031. always_on_top: false,
  1032. content_protected: false,
  1033. skip_taskbar: false,
  1034. theme: None,
  1035. title_bar_style: Default::default(),
  1036. hidden_title: false,
  1037. accept_first_mouse: false,
  1038. tabbing_identifier: None,
  1039. additional_browser_args: None,
  1040. }
  1041. }
  1042. }
  1043. fn default_window_label() -> String {
  1044. "main".to_string()
  1045. }
  1046. fn default_width() -> f64 {
  1047. 800f64
  1048. }
  1049. fn default_height() -> f64 {
  1050. 600f64
  1051. }
  1052. fn default_title() -> String {
  1053. "Tauri App".to_string()
  1054. }
  1055. /// A Content-Security-Policy directive source list.
  1056. /// See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/Sources#sources>.
  1057. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1058. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1059. #[serde(rename_all = "camelCase", untagged)]
  1060. pub enum CspDirectiveSources {
  1061. /// An inline list of CSP sources. Same as [`Self::List`], but concatenated with a space separator.
  1062. Inline(String),
  1063. /// A list of CSP sources. The collection will be concatenated with a space separator for the CSP string.
  1064. List(Vec<String>),
  1065. }
  1066. impl Default for CspDirectiveSources {
  1067. fn default() -> Self {
  1068. Self::List(Vec::new())
  1069. }
  1070. }
  1071. impl From<CspDirectiveSources> for Vec<String> {
  1072. fn from(sources: CspDirectiveSources) -> Self {
  1073. match sources {
  1074. CspDirectiveSources::Inline(source) => source.split(' ').map(|s| s.to_string()).collect(),
  1075. CspDirectiveSources::List(l) => l,
  1076. }
  1077. }
  1078. }
  1079. impl CspDirectiveSources {
  1080. /// Whether the given source is configured on this directive or not.
  1081. pub fn contains(&self, source: &str) -> bool {
  1082. match self {
  1083. Self::Inline(s) => s.contains(&format!("{source} ")) || s.contains(&format!(" {source}")),
  1084. Self::List(l) => l.contains(&source.into()),
  1085. }
  1086. }
  1087. /// Appends the given source to this directive.
  1088. pub fn push<S: AsRef<str>>(&mut self, source: S) {
  1089. match self {
  1090. Self::Inline(s) => {
  1091. s.push(' ');
  1092. s.push_str(source.as_ref());
  1093. }
  1094. Self::List(l) => {
  1095. l.push(source.as_ref().to_string());
  1096. }
  1097. }
  1098. }
  1099. /// Extends this CSP directive source list with the given array of sources.
  1100. pub fn extend(&mut self, sources: Vec<String>) {
  1101. for s in sources {
  1102. self.push(s);
  1103. }
  1104. }
  1105. }
  1106. /// A Content-Security-Policy definition.
  1107. /// See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>.
  1108. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1109. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1110. #[serde(rename_all = "camelCase", untagged)]
  1111. pub enum Csp {
  1112. /// The entire CSP policy in a single text string.
  1113. Policy(String),
  1114. /// An object mapping a directive with its sources values as a list of strings.
  1115. DirectiveMap(HashMap<String, CspDirectiveSources>),
  1116. }
  1117. impl From<HashMap<String, CspDirectiveSources>> for Csp {
  1118. fn from(map: HashMap<String, CspDirectiveSources>) -> Self {
  1119. Self::DirectiveMap(map)
  1120. }
  1121. }
  1122. impl From<Csp> for HashMap<String, CspDirectiveSources> {
  1123. fn from(csp: Csp) -> Self {
  1124. match csp {
  1125. Csp::Policy(policy) => {
  1126. let mut map = HashMap::new();
  1127. for directive in policy.split(';') {
  1128. let mut tokens = directive.trim().split(' ');
  1129. if let Some(directive) = tokens.next() {
  1130. let sources = tokens.map(|s| s.to_string()).collect::<Vec<String>>();
  1131. map.insert(directive.to_string(), CspDirectiveSources::List(sources));
  1132. }
  1133. }
  1134. map
  1135. }
  1136. Csp::DirectiveMap(m) => m,
  1137. }
  1138. }
  1139. }
  1140. impl Display for Csp {
  1141. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  1142. match self {
  1143. Self::Policy(s) => write!(f, "{s}"),
  1144. Self::DirectiveMap(m) => {
  1145. let len = m.len();
  1146. let mut i = 0;
  1147. for (directive, sources) in m {
  1148. let sources: Vec<String> = sources.clone().into();
  1149. write!(f, "{} {}", directive, sources.join(" "))?;
  1150. i += 1;
  1151. if i != len {
  1152. write!(f, "; ")?;
  1153. }
  1154. }
  1155. Ok(())
  1156. }
  1157. }
  1158. }
  1159. }
  1160. /// The possible values for the `dangerous_disable_asset_csp_modification` config option.
  1161. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1162. #[serde(untagged)]
  1163. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1164. pub enum DisabledCspModificationKind {
  1165. /// If `true`, disables all CSP modification.
  1166. /// `false` is the default value and it configures Tauri to control the CSP.
  1167. Flag(bool),
  1168. /// Disables the given list of CSP directives modifications.
  1169. List(Vec<String>),
  1170. }
  1171. impl DisabledCspModificationKind {
  1172. /// Determines whether the given CSP directive can be modified or not.
  1173. pub fn can_modify(&self, directive: &str) -> bool {
  1174. match self {
  1175. Self::Flag(f) => !f,
  1176. Self::List(l) => !l.contains(&directive.into()),
  1177. }
  1178. }
  1179. }
  1180. impl Default for DisabledCspModificationKind {
  1181. fn default() -> Self {
  1182. Self::Flag(false)
  1183. }
  1184. }
  1185. /// External command access definition.
  1186. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1187. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1188. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1189. pub struct RemoteDomainAccessScope {
  1190. /// The URL scheme to allow. By default, all schemas are allowed.
  1191. pub scheme: Option<String>,
  1192. /// The domain to allow.
  1193. pub domain: String,
  1194. /// The list of window labels this scope applies to.
  1195. pub windows: Vec<String>,
  1196. /// The list of plugins that are allowed in this scope.
  1197. /// The names should be without the `tauri-plugin-` prefix, for example `"store"` for `tauri-plugin-store`.
  1198. #[serde(default)]
  1199. pub plugins: Vec<String>,
  1200. /// Enables access to the Tauri API.
  1201. #[serde(default, rename = "enableTauriAPI", alias = "enable-tauri-api")]
  1202. pub enable_tauri_api: bool,
  1203. }
  1204. /// Security configuration.
  1205. ///
  1206. /// See more: https://tauri.app/v1/api/config#securityconfig
  1207. #[skip_serializing_none]
  1208. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1209. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1210. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1211. pub struct SecurityConfig {
  1212. /// The Content Security Policy that will be injected on all HTML files on the built application.
  1213. /// If [`dev_csp`](#SecurityConfig.devCsp) is not specified, this value is also injected on dev.
  1214. ///
  1215. /// This is a really important part of the configuration since it helps you ensure your WebView is secured.
  1216. /// See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>.
  1217. pub csp: Option<Csp>,
  1218. /// The Content Security Policy that will be injected on all HTML files on development.
  1219. ///
  1220. /// This is a really important part of the configuration since it helps you ensure your WebView is secured.
  1221. /// See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>.
  1222. #[serde(alias = "dev-csp")]
  1223. pub dev_csp: Option<Csp>,
  1224. /// Freeze the `Object.prototype` when using the custom protocol.
  1225. #[serde(default, alias = "freeze-prototype")]
  1226. pub freeze_prototype: bool,
  1227. /// Disables the Tauri-injected CSP sources.
  1228. ///
  1229. /// At compile time, Tauri parses all the frontend assets and changes the Content-Security-Policy
  1230. /// to only allow loading of your own scripts and styles by injecting nonce and hash sources.
  1231. /// This stricts your CSP, which may introduce issues when using along with other flexing sources.
  1232. ///
  1233. /// This configuration option allows both a boolean and a list of strings as value.
  1234. /// A boolean instructs Tauri to disable the injection for all CSP injections,
  1235. /// and a list of strings indicates the CSP directives that Tauri cannot inject.
  1236. ///
  1237. /// **WARNING:** Only disable this if you know what you are doing and have properly configured the CSP.
  1238. /// Your application might be vulnerable to XSS attacks without this Tauri protection.
  1239. #[serde(default, alias = "dangerous-disable-asset-csp-modification")]
  1240. pub dangerous_disable_asset_csp_modification: DisabledCspModificationKind,
  1241. /// Allow external domains to send command to Tauri.
  1242. ///
  1243. /// By default, external domains do not have access to `window.__TAURI__`, which means they cannot
  1244. /// communicate with the commands defined in Rust. This prevents attacks where an externally
  1245. /// loaded malicious or compromised sites could start executing commands on the user's device.
  1246. ///
  1247. /// This configuration allows a set of external domains to have access to the Tauri commands.
  1248. /// When you configure a domain to be allowed to access the IPC, all subpaths are allowed. Subdomains are not allowed.
  1249. ///
  1250. /// **WARNING:** Only use this option if you either have internal checks against malicious
  1251. /// external sites or you can trust the allowed external sites. You application might be
  1252. /// vulnerable to dangerous Tauri command related attacks otherwise.
  1253. #[serde(default, alias = "dangerous-remote-domain-ipc-access")]
  1254. pub dangerous_remote_domain_ipc_access: Vec<RemoteDomainAccessScope>,
  1255. /// Sets whether the custom protocols should use `http://<scheme>.localhost` instead of the default `https://<scheme>.localhost` on Windows.
  1256. ///
  1257. /// **WARNING:** Using a `http` scheme will allow mixed content when trying to fetch `http` endpoints and is therefore less secure but will match the behavior of the `<scheme>://localhost` protocols used on macOS and Linux.
  1258. #[serde(default, alias = "dangerous-use-http-scheme")]
  1259. pub dangerous_use_http_scheme: bool,
  1260. }
  1261. /// Defines an allowlist type.
  1262. pub trait Allowlist {
  1263. /// Returns all features associated with the allowlist struct.
  1264. fn all_features() -> Vec<&'static str>;
  1265. /// Returns the tauri features enabled on this allowlist.
  1266. fn to_features(&self) -> Vec<&'static str>;
  1267. }
  1268. macro_rules! check_feature {
  1269. ($self:ident, $features:ident, $flag:ident, $feature_name: expr) => {
  1270. if $self.$flag {
  1271. $features.push($feature_name)
  1272. }
  1273. };
  1274. }
  1275. /// Filesystem scope definition.
  1276. /// It is a list of glob patterns that restrict the API access from the webview.
  1277. ///
  1278. /// Each pattern can start with a variable that resolves to a system base directory.
  1279. /// The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`,
  1280. /// `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`,
  1281. /// `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`,
  1282. /// `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.
  1283. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1284. #[serde(untagged)]
  1285. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1286. pub enum FsAllowlistScope {
  1287. /// A list of paths that are allowed by this scope.
  1288. AllowedPaths(Vec<PathBuf>),
  1289. /// A complete scope configuration.
  1290. #[serde(rename_all = "camelCase")]
  1291. Scope {
  1292. /// A list of paths that are allowed by this scope.
  1293. #[serde(default)]
  1294. allow: Vec<PathBuf>,
  1295. /// A list of paths that are not allowed by this scope.
  1296. /// This gets precedence over the [`Self::Scope::allow`] list.
  1297. #[serde(default)]
  1298. deny: Vec<PathBuf>,
  1299. /// Whether or not paths that contain components that start with a `.`
  1300. /// will require that `.` appears literally in the pattern; `*`, `?`, `**`,
  1301. /// or `[...]` will not match. This is useful because such files are
  1302. /// conventionally considered hidden on Unix systems and it might be
  1303. /// desirable to skip them when listing files.
  1304. ///
  1305. /// Defaults to `true` on Unix systems and `false` on Windows
  1306. // dotfiles are not supposed to be exposed by default on unix
  1307. #[serde(alias = "require-literal-leading-dot")]
  1308. require_literal_leading_dot: Option<bool>,
  1309. },
  1310. }
  1311. impl Default for FsAllowlistScope {
  1312. fn default() -> Self {
  1313. Self::AllowedPaths(Vec::new())
  1314. }
  1315. }
  1316. impl FsAllowlistScope {
  1317. /// The list of allowed paths.
  1318. pub fn allowed_paths(&self) -> &Vec<PathBuf> {
  1319. match self {
  1320. Self::AllowedPaths(p) => p,
  1321. Self::Scope { allow, .. } => allow,
  1322. }
  1323. }
  1324. /// The list of forbidden paths.
  1325. pub fn forbidden_paths(&self) -> Option<&Vec<PathBuf>> {
  1326. match self {
  1327. Self::AllowedPaths(_) => None,
  1328. Self::Scope { deny, .. } => Some(deny),
  1329. }
  1330. }
  1331. }
  1332. /// Allowlist for the file system APIs.
  1333. ///
  1334. /// See more: https://tauri.app/v1/api/config#fsallowlistconfig
  1335. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1336. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1337. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1338. pub struct FsAllowlistConfig {
  1339. /// The access scope for the filesystem APIs.
  1340. #[serde(default)]
  1341. pub scope: FsAllowlistScope,
  1342. /// Use this flag to enable all file system API features.
  1343. #[serde(default)]
  1344. pub all: bool,
  1345. /// Read file from local filesystem.
  1346. #[serde(default, alias = "read-file")]
  1347. pub read_file: bool,
  1348. /// Write file to local filesystem.
  1349. #[serde(default, alias = "write-file")]
  1350. pub write_file: bool,
  1351. /// Read directory from local filesystem.
  1352. #[serde(default, alias = "read-dir")]
  1353. pub read_dir: bool,
  1354. /// Copy file from local filesystem.
  1355. #[serde(default, alias = "copy-file")]
  1356. pub copy_file: bool,
  1357. /// Create directory from local filesystem.
  1358. #[serde(default, alias = "create-dir")]
  1359. pub create_dir: bool,
  1360. /// Remove directory from local filesystem.
  1361. #[serde(default, alias = "remove-dir")]
  1362. pub remove_dir: bool,
  1363. /// Remove file from local filesystem.
  1364. #[serde(default, alias = "remove-file")]
  1365. pub remove_file: bool,
  1366. /// Rename file from local filesystem.
  1367. #[serde(default, alias = "rename-file")]
  1368. pub rename_file: bool,
  1369. /// Check if path exists on the local filesystem.
  1370. #[serde(default)]
  1371. pub exists: bool,
  1372. }
  1373. impl Allowlist for FsAllowlistConfig {
  1374. fn all_features() -> Vec<&'static str> {
  1375. let allowlist = Self {
  1376. scope: Default::default(),
  1377. all: false,
  1378. read_file: true,
  1379. write_file: true,
  1380. read_dir: true,
  1381. copy_file: true,
  1382. create_dir: true,
  1383. remove_dir: true,
  1384. remove_file: true,
  1385. rename_file: true,
  1386. exists: true,
  1387. };
  1388. let mut features = allowlist.to_features();
  1389. features.push("fs-all");
  1390. features
  1391. }
  1392. fn to_features(&self) -> Vec<&'static str> {
  1393. if self.all {
  1394. vec!["fs-all"]
  1395. } else {
  1396. let mut features = Vec::new();
  1397. check_feature!(self, features, read_file, "fs-read-file");
  1398. check_feature!(self, features, write_file, "fs-write-file");
  1399. check_feature!(self, features, read_dir, "fs-read-dir");
  1400. check_feature!(self, features, copy_file, "fs-copy-file");
  1401. check_feature!(self, features, create_dir, "fs-create-dir");
  1402. check_feature!(self, features, remove_dir, "fs-remove-dir");
  1403. check_feature!(self, features, remove_file, "fs-remove-file");
  1404. check_feature!(self, features, rename_file, "fs-rename-file");
  1405. check_feature!(self, features, exists, "fs-exists");
  1406. features
  1407. }
  1408. }
  1409. }
  1410. /// Allowlist for the window APIs.
  1411. ///
  1412. /// See more: https://tauri.app/v1/api/config#windowallowlistconfig
  1413. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1414. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1415. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1416. pub struct WindowAllowlistConfig {
  1417. /// Use this flag to enable all window API features.
  1418. #[serde(default)]
  1419. pub all: bool,
  1420. /// Allows dynamic window creation.
  1421. #[serde(default)]
  1422. pub create: bool,
  1423. /// Allows centering the window.
  1424. #[serde(default)]
  1425. pub center: bool,
  1426. /// Allows requesting user attention on the window.
  1427. #[serde(default, alias = "request-user-attention")]
  1428. pub request_user_attention: bool,
  1429. /// Allows setting the resizable flag of the window.
  1430. #[serde(default, alias = "set-resizable")]
  1431. pub set_resizable: bool,
  1432. /// Allows setting whether the window's native maximize button is enabled or not.
  1433. #[serde(default, alias = "set-maximizable")]
  1434. pub set_maximizable: bool,
  1435. /// Allows setting whether the window's native minimize button is enabled or not.
  1436. #[serde(default, alias = "set-minimizable")]
  1437. pub set_minimizable: bool,
  1438. /// Allows setting whether the window's native close button is enabled or not.
  1439. #[serde(default, alias = "set-closable")]
  1440. pub set_closable: bool,
  1441. /// Allows changing the window title.
  1442. #[serde(default, alias = "set-title")]
  1443. pub set_title: bool,
  1444. /// Allows maximizing the window.
  1445. #[serde(default)]
  1446. pub maximize: bool,
  1447. /// Allows unmaximizing the window.
  1448. #[serde(default)]
  1449. pub unmaximize: bool,
  1450. /// Allows minimizing the window.
  1451. #[serde(default)]
  1452. pub minimize: bool,
  1453. /// Allows unminimizing the window.
  1454. #[serde(default)]
  1455. pub unminimize: bool,
  1456. /// Allows showing the window.
  1457. #[serde(default)]
  1458. pub show: bool,
  1459. /// Allows hiding the window.
  1460. #[serde(default)]
  1461. pub hide: bool,
  1462. /// Allows closing the window.
  1463. #[serde(default)]
  1464. pub close: bool,
  1465. /// Allows setting the decorations flag of the window.
  1466. #[serde(default, alias = "set-decorations")]
  1467. pub set_decorations: bool,
  1468. /// Allows setting the always_on_top flag of the window.
  1469. #[serde(default, alias = "set-always-on-top")]
  1470. pub set_always_on_top: bool,
  1471. /// Allows preventing the window contents from being captured by other apps.
  1472. #[serde(default, alias = "set-content-protected")]
  1473. pub set_content_protected: bool,
  1474. /// Allows setting the window size.
  1475. #[serde(default, alias = "set-size")]
  1476. pub set_size: bool,
  1477. /// Allows setting the window minimum size.
  1478. #[serde(default, alias = "set-min-size")]
  1479. pub set_min_size: bool,
  1480. /// Allows setting the window maximum size.
  1481. #[serde(default, alias = "set-max-size")]
  1482. pub set_max_size: bool,
  1483. /// Allows changing the position of the window.
  1484. #[serde(default, alias = "set-position")]
  1485. pub set_position: bool,
  1486. /// Allows setting the fullscreen flag of the window.
  1487. #[serde(default, alias = "set-fullscreen")]
  1488. pub set_fullscreen: bool,
  1489. /// Allows focusing the window.
  1490. #[serde(default, alias = "set-focus")]
  1491. pub set_focus: bool,
  1492. /// Allows changing the window icon.
  1493. #[serde(default, alias = "set-icon")]
  1494. pub set_icon: bool,
  1495. /// Allows setting the skip_taskbar flag of the window.
  1496. #[serde(default, alias = "set-skip-taskbar")]
  1497. pub set_skip_taskbar: bool,
  1498. /// Allows grabbing the cursor.
  1499. #[serde(default, alias = "set-cursor-grab")]
  1500. pub set_cursor_grab: bool,
  1501. /// Allows setting the cursor visibility.
  1502. #[serde(default, alias = "set-cursor-visible")]
  1503. pub set_cursor_visible: bool,
  1504. /// Allows changing the cursor icon.
  1505. #[serde(default, alias = "set-cursor-icon")]
  1506. pub set_cursor_icon: bool,
  1507. /// Allows setting the cursor position.
  1508. #[serde(default, alias = "set-cursor-position")]
  1509. pub set_cursor_position: bool,
  1510. /// Allows ignoring cursor events.
  1511. #[serde(default, alias = "set-ignore-cursor-events")]
  1512. pub set_ignore_cursor_events: bool,
  1513. /// Allows start dragging on the window.
  1514. #[serde(default, alias = "start-dragging")]
  1515. pub start_dragging: bool,
  1516. /// Allows opening the system dialog to print the window content.
  1517. #[serde(default)]
  1518. pub print: bool,
  1519. }
  1520. impl Allowlist for WindowAllowlistConfig {
  1521. fn all_features() -> Vec<&'static str> {
  1522. let allowlist = Self {
  1523. all: false,
  1524. create: true,
  1525. center: true,
  1526. request_user_attention: true,
  1527. set_resizable: true,
  1528. set_maximizable: true,
  1529. set_minimizable: true,
  1530. set_closable: true,
  1531. set_title: true,
  1532. maximize: true,
  1533. unmaximize: true,
  1534. minimize: true,
  1535. unminimize: true,
  1536. show: true,
  1537. hide: true,
  1538. close: true,
  1539. set_decorations: true,
  1540. set_always_on_top: true,
  1541. set_content_protected: false,
  1542. set_size: true,
  1543. set_min_size: true,
  1544. set_max_size: true,
  1545. set_position: true,
  1546. set_fullscreen: true,
  1547. set_focus: true,
  1548. set_icon: true,
  1549. set_skip_taskbar: true,
  1550. set_cursor_grab: true,
  1551. set_cursor_visible: true,
  1552. set_cursor_icon: true,
  1553. set_cursor_position: true,
  1554. set_ignore_cursor_events: true,
  1555. start_dragging: true,
  1556. print: true,
  1557. };
  1558. let mut features = allowlist.to_features();
  1559. features.push("window-all");
  1560. features
  1561. }
  1562. fn to_features(&self) -> Vec<&'static str> {
  1563. if self.all {
  1564. vec!["window-all"]
  1565. } else {
  1566. let mut features = Vec::new();
  1567. check_feature!(self, features, create, "window-create");
  1568. check_feature!(self, features, center, "window-center");
  1569. check_feature!(
  1570. self,
  1571. features,
  1572. request_user_attention,
  1573. "window-request-user-attention"
  1574. );
  1575. check_feature!(self, features, set_resizable, "window-set-resizable");
  1576. check_feature!(self, features, set_maximizable, "window-set-maximizable");
  1577. check_feature!(self, features, set_minimizable, "window-set-minimizable");
  1578. check_feature!(self, features, set_closable, "window-set-closable");
  1579. check_feature!(self, features, set_title, "window-set-title");
  1580. check_feature!(self, features, maximize, "window-maximize");
  1581. check_feature!(self, features, unmaximize, "window-unmaximize");
  1582. check_feature!(self, features, minimize, "window-minimize");
  1583. check_feature!(self, features, unminimize, "window-unminimize");
  1584. check_feature!(self, features, show, "window-show");
  1585. check_feature!(self, features, hide, "window-hide");
  1586. check_feature!(self, features, close, "window-close");
  1587. check_feature!(self, features, set_decorations, "window-set-decorations");
  1588. check_feature!(
  1589. self,
  1590. features,
  1591. set_always_on_top,
  1592. "window-set-always-on-top"
  1593. );
  1594. check_feature!(
  1595. self,
  1596. features,
  1597. set_content_protected,
  1598. "window-set-content-protected"
  1599. );
  1600. check_feature!(self, features, set_size, "window-set-size");
  1601. check_feature!(self, features, set_min_size, "window-set-min-size");
  1602. check_feature!(self, features, set_max_size, "window-set-max-size");
  1603. check_feature!(self, features, set_position, "window-set-position");
  1604. check_feature!(self, features, set_fullscreen, "window-set-fullscreen");
  1605. check_feature!(self, features, set_focus, "window-set-focus");
  1606. check_feature!(self, features, set_icon, "window-set-icon");
  1607. check_feature!(self, features, set_skip_taskbar, "window-set-skip-taskbar");
  1608. check_feature!(self, features, set_cursor_grab, "window-set-cursor-grab");
  1609. check_feature!(
  1610. self,
  1611. features,
  1612. set_cursor_visible,
  1613. "window-set-cursor-visible"
  1614. );
  1615. check_feature!(self, features, set_cursor_icon, "window-set-cursor-icon");
  1616. check_feature!(
  1617. self,
  1618. features,
  1619. set_cursor_position,
  1620. "window-set-cursor-position"
  1621. );
  1622. check_feature!(
  1623. self,
  1624. features,
  1625. set_ignore_cursor_events,
  1626. "window-set-ignore-cursor-events"
  1627. );
  1628. check_feature!(self, features, start_dragging, "window-start-dragging");
  1629. check_feature!(self, features, print, "window-print");
  1630. features
  1631. }
  1632. }
  1633. }
  1634. /// A command allowed to be executed by the webview API.
  1635. #[derive(Debug, PartialEq, Eq, Clone, Serialize)]
  1636. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1637. pub struct ShellAllowedCommand {
  1638. /// The name for this allowed shell command configuration.
  1639. ///
  1640. /// This name will be used inside of the webview API to call this command along with
  1641. /// any specified arguments.
  1642. pub name: String,
  1643. /// The command name.
  1644. /// It can start with a variable that resolves to a system base directory.
  1645. /// The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`,
  1646. /// `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`,
  1647. /// `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`,
  1648. /// `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.
  1649. #[serde(rename = "cmd", default)] // use default just so the schema doesn't flag it as required
  1650. pub command: PathBuf,
  1651. /// The allowed arguments for the command execution.
  1652. #[serde(default)]
  1653. pub args: ShellAllowedArgs,
  1654. /// If this command is a sidecar command.
  1655. #[serde(default)]
  1656. pub sidecar: bool,
  1657. }
  1658. impl<'de> Deserialize<'de> for ShellAllowedCommand {
  1659. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  1660. where
  1661. D: Deserializer<'de>,
  1662. {
  1663. #[derive(Deserialize)]
  1664. struct InnerShellAllowedCommand {
  1665. name: String,
  1666. #[serde(rename = "cmd")]
  1667. command: Option<PathBuf>,
  1668. #[serde(default)]
  1669. args: ShellAllowedArgs,
  1670. #[serde(default)]
  1671. sidecar: bool,
  1672. }
  1673. let config = InnerShellAllowedCommand::deserialize(deserializer)?;
  1674. if !config.sidecar && config.command.is_none() {
  1675. return Err(DeError::custom(
  1676. "The shell scope `command` value is required.",
  1677. ));
  1678. }
  1679. Ok(ShellAllowedCommand {
  1680. name: config.name,
  1681. command: config.command.unwrap_or_default(),
  1682. args: config.args,
  1683. sidecar: config.sidecar,
  1684. })
  1685. }
  1686. }
  1687. /// A set of command arguments allowed to be executed by the webview API.
  1688. ///
  1689. /// A value of `true` will allow any arguments to be passed to the command. `false` will disable all
  1690. /// arguments. A list of [`ShellAllowedArg`] will set those arguments as the only valid arguments to
  1691. /// be passed to the attached command configuration.
  1692. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1693. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1694. #[serde(untagged, deny_unknown_fields)]
  1695. #[non_exhaustive]
  1696. pub enum ShellAllowedArgs {
  1697. /// Use a simple boolean to allow all or disable all arguments to this command configuration.
  1698. Flag(bool),
  1699. /// A specific set of [`ShellAllowedArg`] that are valid to call for the command configuration.
  1700. List(Vec<ShellAllowedArg>),
  1701. }
  1702. impl Default for ShellAllowedArgs {
  1703. fn default() -> Self {
  1704. Self::Flag(false)
  1705. }
  1706. }
  1707. /// A command argument allowed to be executed by the webview API.
  1708. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1709. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1710. #[serde(untagged, deny_unknown_fields)]
  1711. #[non_exhaustive]
  1712. pub enum ShellAllowedArg {
  1713. /// A non-configurable argument that is passed to the command in the order it was specified.
  1714. Fixed(String),
  1715. /// A variable that is set while calling the command from the webview API.
  1716. ///
  1717. Var {
  1718. /// [regex] validator to require passed values to conform to an expected input.
  1719. ///
  1720. /// This will require the argument value passed to this variable to match the `validator` regex
  1721. /// before it will be executed.
  1722. ///
  1723. /// [regex]: https://docs.rs/regex/latest/regex/#syntax
  1724. validator: String,
  1725. },
  1726. }
  1727. /// Shell scope definition.
  1728. /// It is a list of command names and associated CLI arguments that restrict the API access from the webview.
  1729. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1730. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1731. pub struct ShellAllowlistScope(pub Vec<ShellAllowedCommand>);
  1732. /// Defines the `shell > open` api scope.
  1733. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1734. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1735. #[serde(untagged, deny_unknown_fields)]
  1736. #[non_exhaustive]
  1737. pub enum ShellAllowlistOpen {
  1738. /// If the shell open API should be enabled.
  1739. ///
  1740. /// If enabled, the default validation regex (`^((mailto:\w+)|(tel:\w+)|(https?://\w+)).+`) is used.
  1741. Flag(bool),
  1742. /// Enable the shell open API, with a custom regex that the opened path must match against.
  1743. ///
  1744. /// If using a custom regex to support a non-http(s) schema, care should be used to prevent values
  1745. /// that allow flag-like strings to pass validation. e.g. `--enable-debugging`, `-i`, `/R`.
  1746. Validate(String),
  1747. }
  1748. impl Default for ShellAllowlistOpen {
  1749. fn default() -> Self {
  1750. Self::Flag(false)
  1751. }
  1752. }
  1753. /// Allowlist for the shell APIs.
  1754. ///
  1755. /// See more: https://tauri.app/v1/api/config#shellallowlistconfig
  1756. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1757. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1758. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1759. pub struct ShellAllowlistConfig {
  1760. /// Access scope for the binary execution APIs.
  1761. /// Sidecars are automatically enabled.
  1762. #[serde(default)]
  1763. pub scope: ShellAllowlistScope,
  1764. /// Use this flag to enable all shell API features.
  1765. #[serde(default)]
  1766. pub all: bool,
  1767. /// Enable binary execution.
  1768. #[serde(default)]
  1769. pub execute: bool,
  1770. /// Enable sidecar execution, allowing the JavaScript layer to spawn a sidecar command,
  1771. /// an executable that is shipped with the application.
  1772. /// For more information see <https://tauri.app/v1/guides/building/sidecar>.
  1773. #[serde(default)]
  1774. pub sidecar: bool,
  1775. /// Open URL with the user's default application.
  1776. #[serde(default)]
  1777. pub open: ShellAllowlistOpen,
  1778. }
  1779. impl Allowlist for ShellAllowlistConfig {
  1780. fn all_features() -> Vec<&'static str> {
  1781. let allowlist = Self {
  1782. scope: Default::default(),
  1783. all: false,
  1784. execute: true,
  1785. sidecar: true,
  1786. open: ShellAllowlistOpen::Flag(true),
  1787. };
  1788. let mut features = allowlist.to_features();
  1789. features.push("shell-all");
  1790. features
  1791. }
  1792. fn to_features(&self) -> Vec<&'static str> {
  1793. if self.all {
  1794. vec!["shell-all"]
  1795. } else {
  1796. let mut features = Vec::new();
  1797. check_feature!(self, features, execute, "shell-execute");
  1798. check_feature!(self, features, sidecar, "shell-sidecar");
  1799. if !matches!(self.open, ShellAllowlistOpen::Flag(false)) {
  1800. features.push("shell-open")
  1801. }
  1802. features
  1803. }
  1804. }
  1805. }
  1806. /// Allowlist for the dialog APIs.
  1807. ///
  1808. /// See more: https://tauri.app/v1/api/config#dialogallowlistconfig
  1809. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1810. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1811. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1812. pub struct DialogAllowlistConfig {
  1813. /// Use this flag to enable all dialog API features.
  1814. #[serde(default)]
  1815. pub all: bool,
  1816. /// Allows the API to open a dialog window to pick files.
  1817. #[serde(default)]
  1818. pub open: bool,
  1819. /// Allows the API to open a dialog window to pick where to save files.
  1820. #[serde(default)]
  1821. pub save: bool,
  1822. /// Allows the API to show a message dialog window.
  1823. #[serde(default)]
  1824. pub message: bool,
  1825. /// Allows the API to show a dialog window with Yes/No buttons.
  1826. #[serde(default)]
  1827. pub ask: bool,
  1828. /// Allows the API to show a dialog window with Ok/Cancel buttons.
  1829. #[serde(default)]
  1830. pub confirm: bool,
  1831. }
  1832. impl Allowlist for DialogAllowlistConfig {
  1833. fn all_features() -> Vec<&'static str> {
  1834. let allowlist = Self {
  1835. all: false,
  1836. open: true,
  1837. save: true,
  1838. message: true,
  1839. ask: true,
  1840. confirm: true,
  1841. };
  1842. let mut features = allowlist.to_features();
  1843. features.push("dialog-all");
  1844. features
  1845. }
  1846. fn to_features(&self) -> Vec<&'static str> {
  1847. if self.all {
  1848. vec!["dialog-all"]
  1849. } else {
  1850. let mut features = Vec::new();
  1851. check_feature!(self, features, open, "dialog-open");
  1852. check_feature!(self, features, save, "dialog-save");
  1853. check_feature!(self, features, message, "dialog-message");
  1854. check_feature!(self, features, ask, "dialog-ask");
  1855. check_feature!(self, features, confirm, "dialog-confirm");
  1856. features
  1857. }
  1858. }
  1859. }
  1860. /// HTTP API scope definition.
  1861. /// It is a list of URLs that can be accessed by the webview when using the HTTP APIs.
  1862. /// The scoped URL is matched against the request URL using a glob pattern.
  1863. ///
  1864. /// Examples:
  1865. /// - "https://*": allows all HTTPS urls
  1866. /// - "https://*.github.com/tauri-apps/tauri": allows any subdomain of "github.com" with the "tauri-apps/api" path
  1867. /// - "https://myapi.service.com/users/*": allows access to any URLs that begins with "https://myapi.service.com/users/"
  1868. #[allow(rustdoc::bare_urls)]
  1869. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1870. // TODO: in v2, parse into a String or a custom type that perserves the
  1871. // glob string because Url type will add a trailing slash
  1872. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1873. pub struct HttpAllowlistScope(pub Vec<Url>);
  1874. /// Allowlist for the HTTP APIs.
  1875. ///
  1876. /// See more: https://tauri.app/v1/api/config#httpallowlistconfig
  1877. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1878. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1879. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1880. pub struct HttpAllowlistConfig {
  1881. /// The access scope for the HTTP APIs.
  1882. #[serde(default)]
  1883. pub scope: HttpAllowlistScope,
  1884. /// Use this flag to enable all HTTP API features.
  1885. #[serde(default)]
  1886. pub all: bool,
  1887. /// Allows making HTTP requests.
  1888. #[serde(default)]
  1889. pub request: bool,
  1890. }
  1891. impl Allowlist for HttpAllowlistConfig {
  1892. fn all_features() -> Vec<&'static str> {
  1893. let allowlist = Self {
  1894. scope: Default::default(),
  1895. all: false,
  1896. request: true,
  1897. };
  1898. let mut features = allowlist.to_features();
  1899. features.push("http-all");
  1900. features
  1901. }
  1902. fn to_features(&self) -> Vec<&'static str> {
  1903. if self.all {
  1904. vec!["http-all"]
  1905. } else {
  1906. let mut features = Vec::new();
  1907. check_feature!(self, features, request, "http-request");
  1908. features
  1909. }
  1910. }
  1911. }
  1912. /// Allowlist for the notification APIs.
  1913. ///
  1914. /// See more: https://tauri.app/v1/api/config#notificationallowlistconfig
  1915. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1916. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1917. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1918. pub struct NotificationAllowlistConfig {
  1919. /// Use this flag to enable all notification API features.
  1920. #[serde(default)]
  1921. pub all: bool,
  1922. }
  1923. impl Allowlist for NotificationAllowlistConfig {
  1924. fn all_features() -> Vec<&'static str> {
  1925. let allowlist = Self { all: false };
  1926. let mut features = allowlist.to_features();
  1927. features.push("notification-all");
  1928. features
  1929. }
  1930. fn to_features(&self) -> Vec<&'static str> {
  1931. if self.all {
  1932. vec!["notification-all"]
  1933. } else {
  1934. vec![]
  1935. }
  1936. }
  1937. }
  1938. /// Allowlist for the global shortcut APIs.
  1939. ///
  1940. /// See more: https://tauri.app/v1/api/config#globalshortcutallowlistconfig
  1941. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1942. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1943. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1944. pub struct GlobalShortcutAllowlistConfig {
  1945. /// Use this flag to enable all global shortcut API features.
  1946. #[serde(default)]
  1947. pub all: bool,
  1948. }
  1949. impl Allowlist for GlobalShortcutAllowlistConfig {
  1950. fn all_features() -> Vec<&'static str> {
  1951. let allowlist = Self { all: false };
  1952. let mut features = allowlist.to_features();
  1953. features.push("global-shortcut-all");
  1954. features
  1955. }
  1956. fn to_features(&self) -> Vec<&'static str> {
  1957. if self.all {
  1958. vec!["global-shortcut-all"]
  1959. } else {
  1960. vec![]
  1961. }
  1962. }
  1963. }
  1964. /// Allowlist for the OS APIs.
  1965. ///
  1966. /// See more: https://tauri.app/v1/api/config#osallowlistconfig
  1967. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1968. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1969. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1970. pub struct OsAllowlistConfig {
  1971. /// Use this flag to enable all OS API features.
  1972. #[serde(default)]
  1973. pub all: bool,
  1974. }
  1975. impl Allowlist for OsAllowlistConfig {
  1976. fn all_features() -> Vec<&'static str> {
  1977. let allowlist = Self { all: false };
  1978. let mut features = allowlist.to_features();
  1979. features.push("os-all");
  1980. features
  1981. }
  1982. fn to_features(&self) -> Vec<&'static str> {
  1983. if self.all {
  1984. vec!["os-all"]
  1985. } else {
  1986. vec![]
  1987. }
  1988. }
  1989. }
  1990. /// Allowlist for the path APIs.
  1991. ///
  1992. /// See more: https://tauri.app/v1/api/config#pathallowlistconfig
  1993. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  1994. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1995. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1996. pub struct PathAllowlistConfig {
  1997. /// Use this flag to enable all path API features.
  1998. #[serde(default)]
  1999. pub all: bool,
  2000. }
  2001. impl Allowlist for PathAllowlistConfig {
  2002. fn all_features() -> Vec<&'static str> {
  2003. let allowlist = Self { all: false };
  2004. let mut features = allowlist.to_features();
  2005. features.push("path-all");
  2006. features
  2007. }
  2008. fn to_features(&self) -> Vec<&'static str> {
  2009. if self.all {
  2010. vec!["path-all"]
  2011. } else {
  2012. vec![]
  2013. }
  2014. }
  2015. }
  2016. /// Allowlist for the custom protocols.
  2017. ///
  2018. /// See more: https://tauri.app/v1/api/config#protocolallowlistconfig
  2019. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  2020. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2021. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2022. pub struct ProtocolAllowlistConfig {
  2023. /// The access scope for the asset protocol.
  2024. #[serde(default, alias = "asset-scope")]
  2025. pub asset_scope: FsAllowlistScope,
  2026. /// Use this flag to enable all custom protocols.
  2027. #[serde(default)]
  2028. pub all: bool,
  2029. /// Enables the asset protocol.
  2030. #[serde(default)]
  2031. pub asset: bool,
  2032. }
  2033. impl Allowlist for ProtocolAllowlistConfig {
  2034. fn all_features() -> Vec<&'static str> {
  2035. let allowlist = Self {
  2036. asset_scope: Default::default(),
  2037. all: false,
  2038. asset: true,
  2039. };
  2040. let mut features = allowlist.to_features();
  2041. features.push("protocol-all");
  2042. features
  2043. }
  2044. fn to_features(&self) -> Vec<&'static str> {
  2045. if self.all {
  2046. vec!["protocol-all"]
  2047. } else {
  2048. let mut features = Vec::new();
  2049. check_feature!(self, features, asset, "protocol-asset");
  2050. features
  2051. }
  2052. }
  2053. }
  2054. /// Allowlist for the process APIs.
  2055. ///
  2056. /// See more: https://tauri.app/v1/api/config#processallowlistconfig
  2057. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  2058. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2059. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2060. pub struct ProcessAllowlistConfig {
  2061. /// Use this flag to enable all process APIs.
  2062. #[serde(default)]
  2063. pub all: bool,
  2064. /// Enables the relaunch API.
  2065. #[serde(default)]
  2066. pub relaunch: bool,
  2067. /// Dangerous option that allows macOS to relaunch even if the binary contains a symlink.
  2068. ///
  2069. /// This is due to macOS having less symlink protection. Highly recommended to not set this flag
  2070. /// unless you have a very specific reason too, and understand the implications of it.
  2071. #[serde(
  2072. default,
  2073. alias = "relaunchDangerousAllowSymlinkMacOS",
  2074. alias = "relaunch-dangerous-allow-symlink-macos"
  2075. )]
  2076. pub relaunch_dangerous_allow_symlink_macos: bool,
  2077. /// Enables the exit API.
  2078. #[serde(default)]
  2079. pub exit: bool,
  2080. }
  2081. impl Allowlist for ProcessAllowlistConfig {
  2082. fn all_features() -> Vec<&'static str> {
  2083. let allowlist = Self {
  2084. all: false,
  2085. relaunch: true,
  2086. relaunch_dangerous_allow_symlink_macos: false,
  2087. exit: true,
  2088. };
  2089. let mut features = allowlist.to_features();
  2090. features.push("process-all");
  2091. features
  2092. }
  2093. fn to_features(&self) -> Vec<&'static str> {
  2094. if self.all {
  2095. vec!["process-all"]
  2096. } else {
  2097. let mut features = Vec::new();
  2098. check_feature!(self, features, relaunch, "process-relaunch");
  2099. check_feature!(
  2100. self,
  2101. features,
  2102. relaunch_dangerous_allow_symlink_macos,
  2103. "process-relaunch-dangerous-allow-symlink-macos"
  2104. );
  2105. check_feature!(self, features, exit, "process-exit");
  2106. features
  2107. }
  2108. }
  2109. }
  2110. /// Allowlist for the clipboard APIs.
  2111. ///
  2112. /// See more: https://tauri.app/v1/api/config#clipboardallowlistconfig
  2113. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  2114. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2115. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2116. pub struct ClipboardAllowlistConfig {
  2117. /// Use this flag to enable all clipboard APIs.
  2118. #[serde(default)]
  2119. pub all: bool,
  2120. /// Enables the clipboard's `writeText` API.
  2121. #[serde(default, alias = "writeText")]
  2122. pub write_text: bool,
  2123. /// Enables the clipboard's `readText` API.
  2124. #[serde(default, alias = "readText")]
  2125. pub read_text: bool,
  2126. }
  2127. impl Allowlist for ClipboardAllowlistConfig {
  2128. fn all_features() -> Vec<&'static str> {
  2129. let allowlist = Self {
  2130. all: false,
  2131. write_text: true,
  2132. read_text: true,
  2133. };
  2134. let mut features = allowlist.to_features();
  2135. features.push("clipboard-all");
  2136. features
  2137. }
  2138. fn to_features(&self) -> Vec<&'static str> {
  2139. if self.all {
  2140. vec!["clipboard-all"]
  2141. } else {
  2142. let mut features = Vec::new();
  2143. check_feature!(self, features, write_text, "clipboard-write-text");
  2144. check_feature!(self, features, read_text, "clipboard-read-text");
  2145. features
  2146. }
  2147. }
  2148. }
  2149. /// Allowlist for the app APIs.
  2150. ///
  2151. /// See more: https://tauri.app/v1/api/config#appallowlistconfig
  2152. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  2153. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2154. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2155. pub struct AppAllowlistConfig {
  2156. /// Use this flag to enable all app APIs.
  2157. #[serde(default)]
  2158. pub all: bool,
  2159. /// Enables the app's `show` API.
  2160. #[serde(default)]
  2161. pub show: bool,
  2162. /// Enables the app's `hide` API.
  2163. #[serde(default)]
  2164. pub hide: bool,
  2165. }
  2166. impl Allowlist for AppAllowlistConfig {
  2167. fn all_features() -> Vec<&'static str> {
  2168. let allowlist = Self {
  2169. all: false,
  2170. show: true,
  2171. hide: true,
  2172. };
  2173. let mut features = allowlist.to_features();
  2174. features.push("app-all");
  2175. features
  2176. }
  2177. fn to_features(&self) -> Vec<&'static str> {
  2178. if self.all {
  2179. vec!["app-all"]
  2180. } else {
  2181. let mut features = Vec::new();
  2182. check_feature!(self, features, show, "app-show");
  2183. check_feature!(self, features, hide, "app-hide");
  2184. features
  2185. }
  2186. }
  2187. }
  2188. /// Allowlist configuration. The allowlist is a translation of the [Cargo allowlist features](https://docs.rs/tauri/latest/tauri/#cargo-allowlist-features).
  2189. ///
  2190. /// # Notes
  2191. ///
  2192. /// - Endpoints that don't have their own allowlist option are enabled by default.
  2193. /// - There is only "opt-in", no "opt-out". Setting an option to `false` has no effect.
  2194. ///
  2195. /// # Examples
  2196. ///
  2197. /// - * [`"app-all": true`](https://tauri.app/v1/api/config/#appallowlistconfig.all) will make the [hide](https://tauri.app/v1/api/js/app#hide) endpoint be available regardless of whether `hide` is set to `false` or `true` in the allowlist.
  2198. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  2199. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2200. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2201. pub struct AllowlistConfig {
  2202. /// Use this flag to enable all API features.
  2203. #[serde(default)]
  2204. pub all: bool,
  2205. /// File system API allowlist.
  2206. #[serde(default)]
  2207. pub fs: FsAllowlistConfig,
  2208. /// Window API allowlist.
  2209. #[serde(default)]
  2210. pub window: WindowAllowlistConfig,
  2211. /// Shell API allowlist.
  2212. #[serde(default)]
  2213. pub shell: ShellAllowlistConfig,
  2214. /// Dialog API allowlist.
  2215. #[serde(default)]
  2216. pub dialog: DialogAllowlistConfig,
  2217. /// HTTP API allowlist.
  2218. #[serde(default)]
  2219. pub http: HttpAllowlistConfig,
  2220. /// Notification API allowlist.
  2221. #[serde(default)]
  2222. pub notification: NotificationAllowlistConfig,
  2223. /// Global shortcut API allowlist.
  2224. #[serde(default, alias = "global-shortcut")]
  2225. pub global_shortcut: GlobalShortcutAllowlistConfig,
  2226. /// OS allowlist.
  2227. #[serde(default)]
  2228. pub os: OsAllowlistConfig,
  2229. /// Path API allowlist.
  2230. #[serde(default)]
  2231. pub path: PathAllowlistConfig,
  2232. /// Custom protocol allowlist.
  2233. #[serde(default)]
  2234. pub protocol: ProtocolAllowlistConfig,
  2235. /// Process API allowlist.
  2236. #[serde(default)]
  2237. pub process: ProcessAllowlistConfig,
  2238. /// Clipboard APIs allowlist.
  2239. #[serde(default)]
  2240. pub clipboard: ClipboardAllowlistConfig,
  2241. /// App APIs allowlist.
  2242. #[serde(default)]
  2243. pub app: AppAllowlistConfig,
  2244. }
  2245. impl Allowlist for AllowlistConfig {
  2246. fn all_features() -> Vec<&'static str> {
  2247. let mut features = vec!["api-all"];
  2248. features.extend(FsAllowlistConfig::all_features());
  2249. features.extend(WindowAllowlistConfig::all_features());
  2250. features.extend(ShellAllowlistConfig::all_features());
  2251. features.extend(DialogAllowlistConfig::all_features());
  2252. features.extend(HttpAllowlistConfig::all_features());
  2253. features.extend(NotificationAllowlistConfig::all_features());
  2254. features.extend(GlobalShortcutAllowlistConfig::all_features());
  2255. features.extend(OsAllowlistConfig::all_features());
  2256. features.extend(PathAllowlistConfig::all_features());
  2257. features.extend(ProtocolAllowlistConfig::all_features());
  2258. features.extend(ProcessAllowlistConfig::all_features());
  2259. features.extend(ClipboardAllowlistConfig::all_features());
  2260. features.extend(AppAllowlistConfig::all_features());
  2261. features
  2262. }
  2263. fn to_features(&self) -> Vec<&'static str> {
  2264. if self.all {
  2265. vec!["api-all"]
  2266. } else {
  2267. let mut features = Vec::new();
  2268. features.extend(self.fs.to_features());
  2269. features.extend(self.window.to_features());
  2270. features.extend(self.shell.to_features());
  2271. features.extend(self.dialog.to_features());
  2272. features.extend(self.http.to_features());
  2273. features.extend(self.notification.to_features());
  2274. features.extend(self.global_shortcut.to_features());
  2275. features.extend(self.os.to_features());
  2276. features.extend(self.path.to_features());
  2277. features.extend(self.protocol.to_features());
  2278. features.extend(self.process.to_features());
  2279. features.extend(self.clipboard.to_features());
  2280. features.extend(self.app.to_features());
  2281. features
  2282. }
  2283. }
  2284. }
  2285. /// The application pattern.
  2286. #[skip_serializing_none]
  2287. #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
  2288. #[serde(rename_all = "lowercase", tag = "use", content = "options")]
  2289. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2290. pub enum PatternKind {
  2291. /// Brownfield pattern.
  2292. Brownfield,
  2293. /// Isolation pattern. Recommended for security purposes.
  2294. Isolation {
  2295. /// The dir containing the index.html file that contains the secure isolation application.
  2296. dir: PathBuf,
  2297. },
  2298. }
  2299. impl Default for PatternKind {
  2300. fn default() -> Self {
  2301. Self::Brownfield
  2302. }
  2303. }
  2304. /// The Tauri configuration object.
  2305. ///
  2306. /// See more: https://tauri.app/v1/api/config#tauriconfig
  2307. #[skip_serializing_none]
  2308. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  2309. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2310. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2311. pub struct TauriConfig {
  2312. /// The pattern to use.
  2313. #[serde(default)]
  2314. pub pattern: PatternKind,
  2315. /// The windows configuration.
  2316. #[serde(default)]
  2317. pub windows: Vec<WindowConfig>,
  2318. /// The CLI configuration.
  2319. pub cli: Option<CliConfig>,
  2320. /// The bundler configuration.
  2321. #[serde(default)]
  2322. pub bundle: BundleConfig,
  2323. /// The allowlist configuration.
  2324. #[serde(default)]
  2325. pub allowlist: AllowlistConfig,
  2326. /// Security configuration.
  2327. #[serde(default)]
  2328. pub security: SecurityConfig,
  2329. /// The updater configuration.
  2330. #[serde(default)]
  2331. pub updater: UpdaterConfig,
  2332. /// Configuration for app system tray.
  2333. #[serde(alias = "system-tray")]
  2334. pub system_tray: Option<SystemTrayConfig>,
  2335. /// MacOS private API configuration. Enables the transparent background API and sets the `fullScreenEnabled` preference to `true`.
  2336. #[serde(rename = "macOSPrivateApi", alias = "macos-private-api", default)]
  2337. pub macos_private_api: bool,
  2338. }
  2339. impl TauriConfig {
  2340. /// Returns all Cargo features.
  2341. pub fn all_features() -> Vec<&'static str> {
  2342. let mut features = AllowlistConfig::all_features();
  2343. features.extend(vec![
  2344. "cli",
  2345. "updater",
  2346. "system-tray",
  2347. "macos-private-api",
  2348. "isolation",
  2349. ]);
  2350. features
  2351. }
  2352. /// Returns the enabled Cargo features.
  2353. pub fn features(&self) -> Vec<&str> {
  2354. let mut features = self.allowlist.to_features();
  2355. if self.cli.is_some() {
  2356. features.push("cli");
  2357. }
  2358. if self.updater.active {
  2359. features.push("updater");
  2360. }
  2361. if self.system_tray.is_some() {
  2362. features.push("system-tray");
  2363. }
  2364. if self.macos_private_api {
  2365. features.push("macos-private-api");
  2366. }
  2367. if let PatternKind::Isolation { .. } = self.pattern {
  2368. features.push("isolation");
  2369. }
  2370. features.sort_unstable();
  2371. features
  2372. }
  2373. }
  2374. /// A URL to an updater server.
  2375. ///
  2376. /// The URL must use the `https` scheme on production.
  2377. #[skip_serializing_none]
  2378. #[derive(Debug, PartialEq, Eq, Clone, Serialize)]
  2379. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2380. pub struct UpdaterEndpoint(pub Url);
  2381. impl std::fmt::Display for UpdaterEndpoint {
  2382. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  2383. write!(f, "{}", self.0)
  2384. }
  2385. }
  2386. impl<'de> Deserialize<'de> for UpdaterEndpoint {
  2387. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  2388. where
  2389. D: Deserializer<'de>,
  2390. {
  2391. let url = Url::deserialize(deserializer)?;
  2392. #[cfg(all(not(debug_assertions), not(feature = "schema")))]
  2393. {
  2394. if url.scheme() != "https" {
  2395. return Err(serde::de::Error::custom(
  2396. "The configured updater endpoint must use the `https` protocol.",
  2397. ));
  2398. }
  2399. }
  2400. Ok(Self(url))
  2401. }
  2402. }
  2403. /// Install modes for the Windows update.
  2404. #[derive(Debug, PartialEq, Eq, Clone)]
  2405. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2406. #[cfg_attr(feature = "schema", schemars(rename_all = "camelCase"))]
  2407. pub enum WindowsUpdateInstallMode {
  2408. /// Specifies there's a basic UI during the installation process, including a final dialog box at the end.
  2409. BasicUi,
  2410. /// The quiet mode means there's no user interaction required.
  2411. /// Requires admin privileges if the installer does.
  2412. Quiet,
  2413. /// Specifies unattended mode, which means the installation only shows a progress bar.
  2414. Passive,
  2415. // to add more modes, we need to check if the updater relaunch makes sense
  2416. // i.e. for a full UI mode, the user can also mark the installer to start the app
  2417. }
  2418. impl WindowsUpdateInstallMode {
  2419. /// Returns the associated `msiexec.exe` arguments.
  2420. pub fn msiexec_args(&self) -> &'static [&'static str] {
  2421. match self {
  2422. Self::BasicUi => &["/qb+"],
  2423. Self::Quiet => &["/quiet"],
  2424. Self::Passive => &["/passive"],
  2425. }
  2426. }
  2427. /// Returns the associated nsis arguments.
  2428. pub fn nsis_args(&self) -> &'static [&'static str] {
  2429. match self {
  2430. Self::Passive => &["/P", "/R"],
  2431. Self::Quiet => &["/S", "/R"],
  2432. _ => &[],
  2433. }
  2434. }
  2435. }
  2436. impl Display for WindowsUpdateInstallMode {
  2437. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  2438. write!(
  2439. f,
  2440. "{}",
  2441. match self {
  2442. Self::BasicUi => "basicUI",
  2443. Self::Quiet => "quiet",
  2444. Self::Passive => "passive",
  2445. }
  2446. )
  2447. }
  2448. }
  2449. impl Default for WindowsUpdateInstallMode {
  2450. fn default() -> Self {
  2451. Self::Passive
  2452. }
  2453. }
  2454. impl Serialize for WindowsUpdateInstallMode {
  2455. fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
  2456. where
  2457. S: Serializer,
  2458. {
  2459. serializer.serialize_str(self.to_string().as_ref())
  2460. }
  2461. }
  2462. impl<'de> Deserialize<'de> for WindowsUpdateInstallMode {
  2463. fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
  2464. where
  2465. D: Deserializer<'de>,
  2466. {
  2467. let s = String::deserialize(deserializer)?;
  2468. match s.to_lowercase().as_str() {
  2469. "basicui" => Ok(Self::BasicUi),
  2470. "quiet" => Ok(Self::Quiet),
  2471. "passive" => Ok(Self::Passive),
  2472. _ => Err(DeError::custom(format!(
  2473. "unknown update install mode '{s}'"
  2474. ))),
  2475. }
  2476. }
  2477. }
  2478. /// The updater configuration for Windows.
  2479. ///
  2480. /// See more: https://tauri.app/v1/api/config#updaterwindowsconfig
  2481. #[skip_serializing_none]
  2482. #[derive(Debug, Default, PartialEq, Eq, Clone, Serialize, Deserialize)]
  2483. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2484. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2485. pub struct UpdaterWindowsConfig {
  2486. /// Additional arguments given to the NSIS or WiX installer.
  2487. #[serde(default, alias = "installer-args")]
  2488. pub installer_args: Vec<String>,
  2489. /// The installation mode for the update on Windows. Defaults to `passive`.
  2490. #[serde(default, alias = "install-mode")]
  2491. pub install_mode: WindowsUpdateInstallMode,
  2492. }
  2493. /// The Updater configuration object.
  2494. ///
  2495. /// See more: https://tauri.app/v1/api/config#updaterconfig
  2496. #[skip_serializing_none]
  2497. #[derive(Debug, PartialEq, Eq, Clone, Serialize)]
  2498. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2499. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2500. pub struct UpdaterConfig {
  2501. /// Whether the updater is active or not.
  2502. #[serde(default)]
  2503. pub active: bool,
  2504. /// Display built-in dialog or use event system if disabled.
  2505. #[serde(default = "default_true")]
  2506. pub dialog: bool,
  2507. /// The updater endpoints. TLS is enforced on production.
  2508. ///
  2509. /// The updater URL can contain the following variables:
  2510. /// - {{current_version}}: The version of the app that is requesting the update
  2511. /// - {{target}}: The operating system name (one of `linux`, `windows` or `darwin`).
  2512. /// - {{arch}}: The architecture of the machine (one of `x86_64`, `i686`, `aarch64` or `armv7`).
  2513. ///
  2514. /// # Examples
  2515. /// - "https://my.cdn.com/latest.json": a raw JSON endpoint that returns the latest version and download links for each platform.
  2516. /// - "https://updates.app.dev/{{target}}?version={{current_version}}&arch={{arch}}": a dedicated API with positional and query string arguments.
  2517. #[allow(rustdoc::bare_urls)]
  2518. pub endpoints: Option<Vec<UpdaterEndpoint>>,
  2519. /// Signature public key.
  2520. #[serde(default)] // use default just so the schema doesn't flag it as required
  2521. pub pubkey: String,
  2522. /// The Windows configuration for the updater.
  2523. #[serde(default)]
  2524. pub windows: UpdaterWindowsConfig,
  2525. }
  2526. impl<'de> Deserialize<'de> for UpdaterConfig {
  2527. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  2528. where
  2529. D: Deserializer<'de>,
  2530. {
  2531. #[derive(Deserialize)]
  2532. struct InnerUpdaterConfig {
  2533. #[serde(default)]
  2534. active: bool,
  2535. #[serde(default = "default_true")]
  2536. dialog: bool,
  2537. endpoints: Option<Vec<UpdaterEndpoint>>,
  2538. pubkey: Option<String>,
  2539. #[serde(default)]
  2540. windows: UpdaterWindowsConfig,
  2541. }
  2542. let config = InnerUpdaterConfig::deserialize(deserializer)?;
  2543. if config.active && config.pubkey.is_none() {
  2544. return Err(DeError::custom(
  2545. "The updater `pubkey` configuration is required.",
  2546. ));
  2547. }
  2548. Ok(UpdaterConfig {
  2549. active: config.active,
  2550. dialog: config.dialog,
  2551. endpoints: config.endpoints,
  2552. pubkey: config.pubkey.unwrap_or_default(),
  2553. windows: config.windows,
  2554. })
  2555. }
  2556. }
  2557. impl Default for UpdaterConfig {
  2558. fn default() -> Self {
  2559. Self {
  2560. active: false,
  2561. dialog: true,
  2562. endpoints: None,
  2563. pubkey: "".into(),
  2564. windows: Default::default(),
  2565. }
  2566. }
  2567. }
  2568. /// Configuration for application system tray icon.
  2569. ///
  2570. /// See more: https://tauri.app/v1/api/config#systemtrayconfig
  2571. #[skip_serializing_none]
  2572. #[derive(Debug, Default, PartialEq, Eq, Clone, Deserialize, Serialize)]
  2573. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2574. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2575. pub struct SystemTrayConfig {
  2576. /// Path to the default icon to use on the system tray.
  2577. #[serde(alias = "icon-path")]
  2578. pub icon_path: PathBuf,
  2579. /// 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.
  2580. #[serde(default, alias = "icon-as-template")]
  2581. pub icon_as_template: bool,
  2582. /// A Boolean value that determines whether the menu should appear when the tray icon receives a left click on macOS.
  2583. #[serde(default = "default_true", alias = "menu-on-left-click")]
  2584. pub menu_on_left_click: bool,
  2585. /// Title for MacOS tray
  2586. pub title: Option<String>,
  2587. }
  2588. /// Defines the URL or assets to embed in the application.
  2589. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  2590. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2591. #[serde(untagged, deny_unknown_fields)]
  2592. #[non_exhaustive]
  2593. pub enum AppUrl {
  2594. /// The app's external URL, or the path to the directory containing the app assets.
  2595. Url(WindowUrl),
  2596. /// An array of files to embed on the app.
  2597. Files(Vec<PathBuf>),
  2598. }
  2599. impl std::fmt::Display for AppUrl {
  2600. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  2601. match self {
  2602. Self::Url(url) => write!(f, "{url}"),
  2603. Self::Files(files) => write!(f, "{}", serde_json::to_string(files).unwrap()),
  2604. }
  2605. }
  2606. }
  2607. /// Describes the shell command to run before `tauri dev`.
  2608. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  2609. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2610. #[serde(rename_all = "camelCase", untagged)]
  2611. pub enum BeforeDevCommand {
  2612. /// Run the given script with the default options.
  2613. Script(String),
  2614. /// Run the given script with custom options.
  2615. ScriptWithOptions {
  2616. /// The script to execute.
  2617. script: String,
  2618. /// The current working directory.
  2619. cwd: Option<String>,
  2620. /// Whether `tauri dev` should wait for the command to finish or not. Defaults to `false`.
  2621. #[serde(default)]
  2622. wait: bool,
  2623. },
  2624. }
  2625. /// Describes a shell command to be executed when a CLI hook is triggered.
  2626. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  2627. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2628. #[serde(rename_all = "camelCase", untagged)]
  2629. pub enum HookCommand {
  2630. /// Run the given script with the default options.
  2631. Script(String),
  2632. /// Run the given script with custom options.
  2633. ScriptWithOptions {
  2634. /// The script to execute.
  2635. script: String,
  2636. /// The current working directory.
  2637. cwd: Option<String>,
  2638. },
  2639. }
  2640. /// The Build configuration object.
  2641. ///
  2642. /// See more: https://tauri.app/v1/api/config#buildconfig
  2643. #[skip_serializing_none]
  2644. #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
  2645. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2646. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2647. pub struct BuildConfig {
  2648. /// The binary used to build and run the application.
  2649. pub runner: Option<String>,
  2650. /// The path to the application assets or URL to load in development.
  2651. ///
  2652. /// This is usually an URL to a dev server, which serves your application assets
  2653. /// with live reloading. Most modern JavaScript bundlers provides a way to start a dev server by default.
  2654. ///
  2655. /// See [vite](https://vitejs.dev/guide/), [Webpack DevServer](https://webpack.js.org/configuration/dev-server/) and [sirv](https://github.com/lukeed/sirv)
  2656. /// for examples on how to set up a dev server.
  2657. #[serde(default = "default_dev_path", alias = "dev-path")]
  2658. pub dev_path: AppUrl,
  2659. /// The path to the application assets or URL to load in production.
  2660. ///
  2661. /// When a path relative to the configuration file is provided,
  2662. /// it is read recursively and all files are embedded in the application binary.
  2663. /// Tauri then looks for an `index.html` file unless you provide a custom window URL.
  2664. ///
  2665. /// You can also provide a list of paths to be embedded, which allows granular control over what files are added to the binary.
  2666. /// In this case, all files are added to the root and you must reference it that way in your HTML files.
  2667. ///
  2668. /// When an URL is provided, the application won't have bundled assets
  2669. /// and the application will load that URL by default.
  2670. #[serde(default = "default_dist_dir", alias = "dist-dir")]
  2671. pub dist_dir: AppUrl,
  2672. /// A shell command to run before `tauri dev` kicks in.
  2673. ///
  2674. /// The TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.
  2675. #[serde(alias = "before-dev-command")]
  2676. pub before_dev_command: Option<BeforeDevCommand>,
  2677. /// A shell command to run before `tauri build` kicks in.
  2678. ///
  2679. /// The TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.
  2680. #[serde(alias = "before-build-command")]
  2681. pub before_build_command: Option<HookCommand>,
  2682. /// A shell command to run before the bundling phase in `tauri build` kicks in.
  2683. ///
  2684. /// The TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.
  2685. #[serde(alias = "before-bundle-command")]
  2686. pub before_bundle_command: Option<HookCommand>,
  2687. /// Features passed to `cargo` commands.
  2688. pub features: Option<Vec<String>>,
  2689. /// Whether we should inject the Tauri API on `window.__TAURI__` or not.
  2690. #[serde(default, alias = "with-global-tauri")]
  2691. pub with_global_tauri: bool,
  2692. }
  2693. impl Default for BuildConfig {
  2694. fn default() -> Self {
  2695. Self {
  2696. runner: None,
  2697. dev_path: default_dev_path(),
  2698. dist_dir: default_dist_dir(),
  2699. before_dev_command: None,
  2700. before_build_command: None,
  2701. before_bundle_command: None,
  2702. features: None,
  2703. with_global_tauri: false,
  2704. }
  2705. }
  2706. }
  2707. fn default_dev_path() -> AppUrl {
  2708. AppUrl::Url(WindowUrl::External(
  2709. Url::parse("http://localhost:8080").unwrap(),
  2710. ))
  2711. }
  2712. fn default_dist_dir() -> AppUrl {
  2713. AppUrl::Url(WindowUrl::App("../dist".into()))
  2714. }
  2715. #[derive(Debug, PartialEq, Eq)]
  2716. struct PackageVersion(String);
  2717. impl<'d> serde::Deserialize<'d> for PackageVersion {
  2718. fn deserialize<D: Deserializer<'d>>(deserializer: D) -> Result<PackageVersion, D::Error> {
  2719. struct PackageVersionVisitor;
  2720. impl<'d> Visitor<'d> for PackageVersionVisitor {
  2721. type Value = PackageVersion;
  2722. fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
  2723. write!(
  2724. formatter,
  2725. "a semver string or a path to a package.json file"
  2726. )
  2727. }
  2728. fn visit_str<E: DeError>(self, value: &str) -> Result<PackageVersion, E> {
  2729. let path = PathBuf::from(value);
  2730. if path.exists() {
  2731. let json_str = read_to_string(&path)
  2732. .map_err(|e| DeError::custom(format!("failed to read version JSON file: {e}")))?;
  2733. let package_json: serde_json::Value = serde_json::from_str(&json_str)
  2734. .map_err(|e| DeError::custom(format!("failed to read version JSON file: {e}")))?;
  2735. if let Some(obj) = package_json.as_object() {
  2736. let version = obj
  2737. .get("version")
  2738. .ok_or_else(|| DeError::custom("JSON must contain a `version` field"))?
  2739. .as_str()
  2740. .ok_or_else(|| {
  2741. DeError::custom(format!("`{} > version` must be a string", path.display()))
  2742. })?;
  2743. Ok(PackageVersion(
  2744. Version::from_str(version)
  2745. .map_err(|_| DeError::custom("`package > version` must be a semver string"))?
  2746. .to_string(),
  2747. ))
  2748. } else {
  2749. Err(DeError::custom(
  2750. "`package > version` value is not a path to a JSON object",
  2751. ))
  2752. }
  2753. } else {
  2754. Ok(PackageVersion(
  2755. Version::from_str(value)
  2756. .map_err(|_| DeError::custom("`package > version` must be a semver string"))?
  2757. .to_string(),
  2758. ))
  2759. }
  2760. }
  2761. }
  2762. deserializer.deserialize_string(PackageVersionVisitor {})
  2763. }
  2764. }
  2765. /// The package configuration.
  2766. ///
  2767. /// See more: https://tauri.app/v1/api/config#packageconfig
  2768. #[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)]
  2769. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2770. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2771. pub struct PackageConfig {
  2772. /// App name.
  2773. #[serde(alias = "product-name")]
  2774. #[cfg_attr(feature = "schema", validate(regex(pattern = "^[^/\\:*?\"<>|]+$")))]
  2775. pub product_name: Option<String>,
  2776. /// 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.
  2777. #[serde(deserialize_with = "version_deserializer", default)]
  2778. pub version: Option<String>,
  2779. }
  2780. fn version_deserializer<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
  2781. where
  2782. D: Deserializer<'de>,
  2783. {
  2784. Option::<PackageVersion>::deserialize(deserializer).map(|v| v.map(|v| v.0))
  2785. }
  2786. impl PackageConfig {
  2787. /// The binary name.
  2788. #[allow(dead_code)]
  2789. pub fn binary_name(&self) -> Option<String> {
  2790. #[cfg(target_os = "linux")]
  2791. {
  2792. self.product_name.as_ref().map(|n| n.to_kebab_case())
  2793. }
  2794. #[cfg(not(target_os = "linux"))]
  2795. {
  2796. self.product_name.clone()
  2797. }
  2798. }
  2799. }
  2800. /// The Tauri configuration object.
  2801. /// It is read from a file where you can define your frontend assets,
  2802. /// configure the bundler, enable the app updater, define a system tray,
  2803. /// enable APIs via the allowlist and more.
  2804. ///
  2805. /// The configuration file is generated by the
  2806. /// [`tauri init`](https://tauri.app/v1/api/cli#init) command that lives in
  2807. /// your Tauri application source directory (src-tauri).
  2808. ///
  2809. /// Once generated, you may modify it at will to customize your Tauri application.
  2810. ///
  2811. /// ## File Formats
  2812. ///
  2813. /// By default, the configuration is defined as a JSON file named `tauri.conf.json`.
  2814. ///
  2815. /// Tauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively.
  2816. /// The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`.
  2817. /// The TOML file name is `Tauri.toml`.
  2818. ///
  2819. /// ## Platform-Specific Configuration
  2820. ///
  2821. /// In addition to the default configuration file, Tauri can
  2822. /// read a platform-specific configuration from `tauri.linux.conf.json`,
  2823. /// `tauri.windows.conf.json`, and `tauri.macos.conf.json`
  2824. /// (or `Tauri.linux.toml`, `Tauri.windows.toml` and `Tauri.macos.toml` if the `Tauri.toml` format is used),
  2825. /// which gets merged with the main configuration object.
  2826. ///
  2827. /// ## Configuration Structure
  2828. ///
  2829. /// The configuration is composed of the following objects:
  2830. ///
  2831. /// - [`package`](#packageconfig): Package settings
  2832. /// - [`tauri`](#tauriconfig): The Tauri config
  2833. /// - [`build`](#buildconfig): The build configuration
  2834. /// - [`plugins`](#pluginconfig): The plugins config
  2835. ///
  2836. /// ```json title="Example tauri.config.json file"
  2837. /// {
  2838. /// "build": {
  2839. /// "beforeBuildCommand": "",
  2840. /// "beforeDevCommand": "",
  2841. /// "devPath": "../dist",
  2842. /// "distDir": "../dist"
  2843. /// },
  2844. /// "package": {
  2845. /// "productName": "tauri-app",
  2846. /// "version": "0.1.0"
  2847. /// },
  2848. /// "tauri": {
  2849. /// "allowlist": {
  2850. /// "all": true
  2851. /// },
  2852. /// "bundle": {},
  2853. /// "security": {
  2854. /// "csp": null
  2855. /// },
  2856. /// "updater": {
  2857. /// "active": false
  2858. /// },
  2859. /// "windows": [
  2860. /// {
  2861. /// "fullscreen": false,
  2862. /// "height": 600,
  2863. /// "resizable": true,
  2864. /// "title": "Tauri App",
  2865. /// "width": 800
  2866. /// }
  2867. /// ]
  2868. /// }
  2869. /// }
  2870. /// ```
  2871. #[skip_serializing_none]
  2872. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  2873. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2874. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  2875. pub struct Config {
  2876. /// The JSON schema for the Tauri config.
  2877. #[serde(rename = "$schema")]
  2878. pub schema: Option<String>,
  2879. /// Package settings.
  2880. #[serde(default)]
  2881. pub package: PackageConfig,
  2882. /// The Tauri configuration.
  2883. #[serde(default)]
  2884. pub tauri: TauriConfig,
  2885. /// The build configuration.
  2886. #[serde(default = "default_build")]
  2887. pub build: BuildConfig,
  2888. /// The plugins config.
  2889. #[serde(default)]
  2890. pub plugins: PluginConfig,
  2891. }
  2892. /// The plugin configs holds a HashMap mapping a plugin name to its configuration object.
  2893. ///
  2894. /// See more: https://tauri.app/v1/api/config#pluginconfig
  2895. #[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)]
  2896. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  2897. pub struct PluginConfig(pub HashMap<String, JsonValue>);
  2898. fn default_build() -> BuildConfig {
  2899. BuildConfig {
  2900. runner: None,
  2901. dev_path: default_dev_path(),
  2902. dist_dir: default_dist_dir(),
  2903. before_dev_command: None,
  2904. before_build_command: None,
  2905. before_bundle_command: None,
  2906. features: None,
  2907. with_global_tauri: false,
  2908. }
  2909. }
  2910. /// Implement `ToTokens` for all config structs, allowing a literal `Config` to be built.
  2911. ///
  2912. /// This allows for a build script to output the values in a `Config` to a `TokenStream`, which can
  2913. /// then be consumed by another crate. Useful for passing a config to both the build script and the
  2914. /// application using tauri while only parsing it once (in the build script).
  2915. #[cfg(feature = "build")]
  2916. mod build {
  2917. use std::{convert::identity, path::Path};
  2918. use proc_macro2::TokenStream;
  2919. use quote::{quote, ToTokens, TokenStreamExt};
  2920. use super::*;
  2921. use serde_json::Value as JsonValue;
  2922. /// Create a `String` constructor `TokenStream`.
  2923. ///
  2924. /// e.g. `"Hello World" -> String::from("Hello World").
  2925. /// This takes a `&String` to reduce casting all the `&String` -> `&str` manually.
  2926. fn str_lit(s: impl AsRef<str>) -> TokenStream {
  2927. let s = s.as_ref();
  2928. quote! { #s.into() }
  2929. }
  2930. /// Create an `Option` constructor `TokenStream`.
  2931. fn opt_lit(item: Option<&impl ToTokens>) -> TokenStream {
  2932. match item {
  2933. None => quote! { ::core::option::Option::None },
  2934. Some(item) => quote! { ::core::option::Option::Some(#item) },
  2935. }
  2936. }
  2937. /// Helper function to combine an `opt_lit` with `str_lit`.
  2938. fn opt_str_lit(item: Option<impl AsRef<str>>) -> TokenStream {
  2939. opt_lit(item.map(str_lit).as_ref())
  2940. }
  2941. /// Helper function to combine an `opt_lit` with a list of `str_lit`
  2942. fn opt_vec_str_lit(item: Option<impl IntoIterator<Item = impl AsRef<str>>>) -> TokenStream {
  2943. opt_lit(item.map(|list| vec_lit(list, str_lit)).as_ref())
  2944. }
  2945. /// Create a `Vec` constructor, mapping items with a function that spits out `TokenStream`s.
  2946. fn vec_lit<Raw, Tokens>(
  2947. list: impl IntoIterator<Item = Raw>,
  2948. map: impl Fn(Raw) -> Tokens,
  2949. ) -> TokenStream
  2950. where
  2951. Tokens: ToTokens,
  2952. {
  2953. let items = list.into_iter().map(map);
  2954. quote! { vec![#(#items),*] }
  2955. }
  2956. /// Create a `PathBuf` constructor `TokenStream`.
  2957. ///
  2958. /// e.g. `"Hello World" -> String::from("Hello World").
  2959. fn path_buf_lit(s: impl AsRef<Path>) -> TokenStream {
  2960. let s = s.as_ref().to_string_lossy().into_owned();
  2961. quote! { ::std::path::PathBuf::from(#s) }
  2962. }
  2963. /// Creates a `Url` constructor `TokenStream`.
  2964. fn url_lit(url: &Url) -> TokenStream {
  2965. let url = url.as_str();
  2966. quote! { #url.parse().unwrap() }
  2967. }
  2968. /// Create a map constructor, mapping keys and values with other `TokenStream`s.
  2969. ///
  2970. /// This function is pretty generic because the types of keys AND values get transformed.
  2971. fn map_lit<Map, Key, Value, TokenStreamKey, TokenStreamValue, FuncKey, FuncValue>(
  2972. map_type: TokenStream,
  2973. map: Map,
  2974. map_key: FuncKey,
  2975. map_value: FuncValue,
  2976. ) -> TokenStream
  2977. where
  2978. <Map as IntoIterator>::IntoIter: ExactSizeIterator,
  2979. Map: IntoIterator<Item = (Key, Value)>,
  2980. TokenStreamKey: ToTokens,
  2981. TokenStreamValue: ToTokens,
  2982. FuncKey: Fn(Key) -> TokenStreamKey,
  2983. FuncValue: Fn(Value) -> TokenStreamValue,
  2984. {
  2985. let ident = quote::format_ident!("map");
  2986. let map = map.into_iter();
  2987. if map.len() > 0 {
  2988. let items = map.map(|(key, value)| {
  2989. let key = map_key(key);
  2990. let value = map_value(value);
  2991. quote! { #ident.insert(#key, #value); }
  2992. });
  2993. quote! {{
  2994. let mut #ident = #map_type::new();
  2995. #(#items)*
  2996. #ident
  2997. }}
  2998. } else {
  2999. quote! { #map_type::new() }
  3000. }
  3001. }
  3002. /// Create a `serde_json::Value` variant `TokenStream` for a number
  3003. fn json_value_number_lit(num: &serde_json::Number) -> TokenStream {
  3004. // See https://docs.rs/serde_json/1/serde_json/struct.Number.html for guarantees
  3005. let prefix = quote! { ::serde_json::Value };
  3006. if num.is_u64() {
  3007. // guaranteed u64
  3008. let num = num.as_u64().unwrap();
  3009. quote! { #prefix::Number(#num.into()) }
  3010. } else if num.is_i64() {
  3011. // guaranteed i64
  3012. let num = num.as_i64().unwrap();
  3013. quote! { #prefix::Number(#num.into()) }
  3014. } else if num.is_f64() {
  3015. // guaranteed f64
  3016. let num = num.as_f64().unwrap();
  3017. quote! { #prefix::Number(#num.into()) }
  3018. } else {
  3019. // invalid number
  3020. quote! { #prefix::Null }
  3021. }
  3022. }
  3023. /// Create a `serde_json::Value` constructor `TokenStream`
  3024. fn json_value_lit(jv: &JsonValue) -> TokenStream {
  3025. let prefix = quote! { ::serde_json::Value };
  3026. match jv {
  3027. JsonValue::Null => quote! { #prefix::Null },
  3028. JsonValue::Bool(bool) => quote! { #prefix::Bool(#bool) },
  3029. JsonValue::Number(number) => json_value_number_lit(number),
  3030. JsonValue::String(str) => {
  3031. let s = str_lit(str);
  3032. quote! { #prefix::String(#s) }
  3033. }
  3034. JsonValue::Array(vec) => {
  3035. let items = vec.iter().map(json_value_lit);
  3036. quote! { #prefix::Array(vec![#(#items),*]) }
  3037. }
  3038. JsonValue::Object(map) => {
  3039. let map = map_lit(quote! { ::serde_json::Map }, map, str_lit, json_value_lit);
  3040. quote! { #prefix::Object(#map) }
  3041. }
  3042. }
  3043. }
  3044. /// Write a `TokenStream` of the `$struct`'s fields to the `$tokens`.
  3045. ///
  3046. /// All fields must represent a binding of the same name that implements `ToTokens`.
  3047. macro_rules! literal_struct {
  3048. ($tokens:ident, $struct:ident, $($field:ident),+) => {
  3049. $tokens.append_all(quote! {
  3050. ::tauri::utils::config::$struct {
  3051. $($field: #$field),+
  3052. }
  3053. });
  3054. };
  3055. }
  3056. impl ToTokens for WindowUrl {
  3057. fn to_tokens(&self, tokens: &mut TokenStream) {
  3058. let prefix = quote! { ::tauri::utils::config::WindowUrl };
  3059. tokens.append_all(match self {
  3060. Self::App(path) => {
  3061. let path = path_buf_lit(path);
  3062. quote! { #prefix::App(#path) }
  3063. }
  3064. Self::External(url) => {
  3065. let url = url_lit(url);
  3066. quote! { #prefix::External(#url) }
  3067. }
  3068. })
  3069. }
  3070. }
  3071. impl ToTokens for crate::Theme {
  3072. fn to_tokens(&self, tokens: &mut TokenStream) {
  3073. let prefix = quote! { ::tauri::utils::Theme };
  3074. tokens.append_all(match self {
  3075. Self::Light => quote! { #prefix::Light },
  3076. Self::Dark => quote! { #prefix::Dark },
  3077. })
  3078. }
  3079. }
  3080. impl ToTokens for crate::TitleBarStyle {
  3081. fn to_tokens(&self, tokens: &mut TokenStream) {
  3082. let prefix = quote! { ::tauri::utils::TitleBarStyle };
  3083. tokens.append_all(match self {
  3084. Self::Visible => quote! { #prefix::Visible },
  3085. Self::Transparent => quote! { #prefix::Transparent },
  3086. Self::Overlay => quote! { #prefix::Overlay },
  3087. })
  3088. }
  3089. }
  3090. impl ToTokens for WindowConfig {
  3091. fn to_tokens(&self, tokens: &mut TokenStream) {
  3092. let label = str_lit(&self.label);
  3093. let url = &self.url;
  3094. let user_agent = opt_str_lit(self.user_agent.as_ref());
  3095. let file_drop_enabled = self.file_drop_enabled;
  3096. let center = self.center;
  3097. let x = opt_lit(self.x.as_ref());
  3098. let y = opt_lit(self.y.as_ref());
  3099. let width = self.width;
  3100. let height = self.height;
  3101. let min_width = opt_lit(self.min_width.as_ref());
  3102. let min_height = opt_lit(self.min_height.as_ref());
  3103. let max_width = opt_lit(self.max_width.as_ref());
  3104. let max_height = opt_lit(self.max_height.as_ref());
  3105. let resizable = self.resizable;
  3106. let maximizable = self.maximizable;
  3107. let minimizable = self.minimizable;
  3108. let closable = self.closable;
  3109. let title = str_lit(&self.title);
  3110. let fullscreen = self.fullscreen;
  3111. let focus = self.focus;
  3112. let transparent = self.transparent;
  3113. let maximized = self.maximized;
  3114. let visible = self.visible;
  3115. let decorations = self.decorations;
  3116. let always_on_top = self.always_on_top;
  3117. let content_protected = self.content_protected;
  3118. let skip_taskbar = self.skip_taskbar;
  3119. let theme = opt_lit(self.theme.as_ref());
  3120. let title_bar_style = &self.title_bar_style;
  3121. let hidden_title = self.hidden_title;
  3122. let accept_first_mouse = self.accept_first_mouse;
  3123. let tabbing_identifier = opt_str_lit(self.tabbing_identifier.as_ref());
  3124. let additional_browser_args = opt_str_lit(self.additional_browser_args.as_ref());
  3125. literal_struct!(
  3126. tokens,
  3127. WindowConfig,
  3128. label,
  3129. url,
  3130. user_agent,
  3131. file_drop_enabled,
  3132. center,
  3133. x,
  3134. y,
  3135. width,
  3136. height,
  3137. min_width,
  3138. min_height,
  3139. max_width,
  3140. max_height,
  3141. resizable,
  3142. maximizable,
  3143. minimizable,
  3144. closable,
  3145. title,
  3146. fullscreen,
  3147. focus,
  3148. transparent,
  3149. maximized,
  3150. visible,
  3151. decorations,
  3152. always_on_top,
  3153. content_protected,
  3154. skip_taskbar,
  3155. theme,
  3156. title_bar_style,
  3157. hidden_title,
  3158. accept_first_mouse,
  3159. tabbing_identifier,
  3160. additional_browser_args
  3161. );
  3162. }
  3163. }
  3164. impl ToTokens for CliArg {
  3165. fn to_tokens(&self, tokens: &mut TokenStream) {
  3166. let short = opt_lit(self.short.as_ref());
  3167. let name = str_lit(&self.name);
  3168. let description = opt_str_lit(self.description.as_ref());
  3169. let long_description = opt_str_lit(self.long_description.as_ref());
  3170. let takes_value = self.takes_value;
  3171. let multiple = self.multiple;
  3172. let multiple_occurrences = self.multiple_occurrences;
  3173. let number_of_values = opt_lit(self.number_of_values.as_ref());
  3174. let possible_values = opt_vec_str_lit(self.possible_values.as_ref());
  3175. let min_values = opt_lit(self.min_values.as_ref());
  3176. let max_values = opt_lit(self.max_values.as_ref());
  3177. let required = self.required;
  3178. let required_unless_present = opt_str_lit(self.required_unless_present.as_ref());
  3179. let required_unless_present_all = opt_vec_str_lit(self.required_unless_present_all.as_ref());
  3180. let required_unless_present_any = opt_vec_str_lit(self.required_unless_present_any.as_ref());
  3181. let conflicts_with = opt_str_lit(self.conflicts_with.as_ref());
  3182. let conflicts_with_all = opt_vec_str_lit(self.conflicts_with_all.as_ref());
  3183. let requires = opt_str_lit(self.requires.as_ref());
  3184. let requires_all = opt_vec_str_lit(self.requires_all.as_ref());
  3185. let requires_if = opt_vec_str_lit(self.requires_if.as_ref());
  3186. let required_if_eq = opt_vec_str_lit(self.required_if_eq.as_ref());
  3187. let require_equals = opt_lit(self.require_equals.as_ref());
  3188. let index = opt_lit(self.index.as_ref());
  3189. literal_struct!(
  3190. tokens,
  3191. CliArg,
  3192. short,
  3193. name,
  3194. description,
  3195. long_description,
  3196. takes_value,
  3197. multiple,
  3198. multiple_occurrences,
  3199. number_of_values,
  3200. possible_values,
  3201. min_values,
  3202. max_values,
  3203. required,
  3204. required_unless_present,
  3205. required_unless_present_all,
  3206. required_unless_present_any,
  3207. conflicts_with,
  3208. conflicts_with_all,
  3209. requires,
  3210. requires_all,
  3211. requires_if,
  3212. required_if_eq,
  3213. require_equals,
  3214. index
  3215. );
  3216. }
  3217. }
  3218. impl ToTokens for CliConfig {
  3219. fn to_tokens(&self, tokens: &mut TokenStream) {
  3220. let description = opt_str_lit(self.description.as_ref());
  3221. let long_description = opt_str_lit(self.long_description.as_ref());
  3222. let before_help = opt_str_lit(self.before_help.as_ref());
  3223. let after_help = opt_str_lit(self.after_help.as_ref());
  3224. let args = {
  3225. let args = self.args.as_ref().map(|args| {
  3226. let arg = args.iter().map(|a| quote! { #a });
  3227. quote! { vec![#(#arg),*] }
  3228. });
  3229. opt_lit(args.as_ref())
  3230. };
  3231. let subcommands = opt_lit(
  3232. self
  3233. .subcommands
  3234. .as_ref()
  3235. .map(|map| {
  3236. map_lit(
  3237. quote! { ::std::collections::HashMap },
  3238. map,
  3239. str_lit,
  3240. identity,
  3241. )
  3242. })
  3243. .as_ref(),
  3244. );
  3245. literal_struct!(
  3246. tokens,
  3247. CliConfig,
  3248. description,
  3249. long_description,
  3250. before_help,
  3251. after_help,
  3252. args,
  3253. subcommands
  3254. );
  3255. }
  3256. }
  3257. impl ToTokens for PatternKind {
  3258. fn to_tokens(&self, tokens: &mut TokenStream) {
  3259. let prefix = quote! { ::tauri::utils::config::PatternKind };
  3260. tokens.append_all(match self {
  3261. Self::Brownfield => quote! { #prefix::Brownfield },
  3262. #[cfg(not(feature = "isolation"))]
  3263. Self::Isolation { dir: _ } => quote! { #prefix::Brownfield },
  3264. #[cfg(feature = "isolation")]
  3265. Self::Isolation { dir } => {
  3266. let dir = path_buf_lit(dir);
  3267. quote! { #prefix::Isolation { dir: #dir } }
  3268. }
  3269. })
  3270. }
  3271. }
  3272. impl ToTokens for WebviewInstallMode {
  3273. fn to_tokens(&self, tokens: &mut TokenStream) {
  3274. let prefix = quote! { ::tauri::utils::config::WebviewInstallMode };
  3275. tokens.append_all(match self {
  3276. Self::Skip => quote! { #prefix::Skip },
  3277. Self::DownloadBootstrapper { silent } => {
  3278. quote! { #prefix::DownloadBootstrapper { silent: #silent } }
  3279. }
  3280. Self::EmbedBootstrapper { silent } => {
  3281. quote! { #prefix::EmbedBootstrapper { silent: #silent } }
  3282. }
  3283. Self::OfflineInstaller { silent } => {
  3284. quote! { #prefix::OfflineInstaller { silent: #silent } }
  3285. }
  3286. Self::FixedRuntime { path } => {
  3287. let path = path_buf_lit(path);
  3288. quote! { #prefix::FixedRuntime { path: #path } }
  3289. }
  3290. })
  3291. }
  3292. }
  3293. impl ToTokens for WindowsConfig {
  3294. fn to_tokens(&self, tokens: &mut TokenStream) {
  3295. let webview_install_mode = if let Some(fixed_runtime_path) = &self.webview_fixed_runtime_path
  3296. {
  3297. WebviewInstallMode::FixedRuntime {
  3298. path: fixed_runtime_path.clone(),
  3299. }
  3300. } else {
  3301. self.webview_install_mode.clone()
  3302. };
  3303. tokens.append_all(quote! { ::tauri::utils::config::WindowsConfig {
  3304. webview_install_mode: #webview_install_mode,
  3305. ..Default::default()
  3306. }})
  3307. }
  3308. }
  3309. impl ToTokens for BundleConfig {
  3310. fn to_tokens(&self, tokens: &mut TokenStream) {
  3311. let identifier = str_lit(&self.identifier);
  3312. let publisher = quote!(None);
  3313. let icon = vec_lit(&self.icon, str_lit);
  3314. let active = self.active;
  3315. let targets = quote!(Default::default());
  3316. let resources = quote!(None);
  3317. let copyright = quote!(None);
  3318. let category = quote!(None);
  3319. let short_description = quote!(None);
  3320. let long_description = quote!(None);
  3321. let appimage = quote!(Default::default());
  3322. let deb = quote!(Default::default());
  3323. let macos = quote!(Default::default());
  3324. let external_bin = opt_vec_str_lit(self.external_bin.as_ref());
  3325. let windows = &self.windows;
  3326. literal_struct!(
  3327. tokens,
  3328. BundleConfig,
  3329. active,
  3330. identifier,
  3331. publisher,
  3332. icon,
  3333. targets,
  3334. resources,
  3335. copyright,
  3336. category,
  3337. short_description,
  3338. long_description,
  3339. appimage,
  3340. deb,
  3341. macos,
  3342. external_bin,
  3343. windows
  3344. );
  3345. }
  3346. }
  3347. impl ToTokens for AppUrl {
  3348. fn to_tokens(&self, tokens: &mut TokenStream) {
  3349. let prefix = quote! { ::tauri::utils::config::AppUrl };
  3350. tokens.append_all(match self {
  3351. Self::Url(url) => {
  3352. quote! { #prefix::Url(#url) }
  3353. }
  3354. Self::Files(files) => {
  3355. let files = vec_lit(files, path_buf_lit);
  3356. quote! { #prefix::Files(#files) }
  3357. }
  3358. })
  3359. }
  3360. }
  3361. impl ToTokens for BuildConfig {
  3362. fn to_tokens(&self, tokens: &mut TokenStream) {
  3363. let dev_path = &self.dev_path;
  3364. let dist_dir = &self.dist_dir;
  3365. let with_global_tauri = self.with_global_tauri;
  3366. let runner = quote!(None);
  3367. let before_dev_command = quote!(None);
  3368. let before_build_command = quote!(None);
  3369. let before_bundle_command = quote!(None);
  3370. let features = quote!(None);
  3371. literal_struct!(
  3372. tokens,
  3373. BuildConfig,
  3374. runner,
  3375. dev_path,
  3376. dist_dir,
  3377. with_global_tauri,
  3378. before_dev_command,
  3379. before_build_command,
  3380. before_bundle_command,
  3381. features
  3382. );
  3383. }
  3384. }
  3385. impl ToTokens for WindowsUpdateInstallMode {
  3386. fn to_tokens(&self, tokens: &mut TokenStream) {
  3387. let prefix = quote! { ::tauri::utils::config::WindowsUpdateInstallMode };
  3388. tokens.append_all(match self {
  3389. Self::BasicUi => quote! { #prefix::BasicUi },
  3390. Self::Quiet => quote! { #prefix::Quiet },
  3391. Self::Passive => quote! { #prefix::Passive },
  3392. })
  3393. }
  3394. }
  3395. impl ToTokens for UpdaterWindowsConfig {
  3396. fn to_tokens(&self, tokens: &mut TokenStream) {
  3397. let install_mode = &self.install_mode;
  3398. let installer_args = vec_lit(&self.installer_args, str_lit);
  3399. literal_struct!(tokens, UpdaterWindowsConfig, install_mode, installer_args);
  3400. }
  3401. }
  3402. impl ToTokens for UpdaterConfig {
  3403. fn to_tokens(&self, tokens: &mut TokenStream) {
  3404. let active = self.active;
  3405. let dialog = self.dialog;
  3406. let pubkey = str_lit(&self.pubkey);
  3407. let endpoints = opt_lit(
  3408. self
  3409. .endpoints
  3410. .as_ref()
  3411. .map(|list| {
  3412. vec_lit(list, |url| {
  3413. let url = url.0.as_str();
  3414. quote! { ::tauri::utils::config::UpdaterEndpoint(#url.parse().unwrap()) }
  3415. })
  3416. })
  3417. .as_ref(),
  3418. );
  3419. let windows = &self.windows;
  3420. literal_struct!(
  3421. tokens,
  3422. UpdaterConfig,
  3423. active,
  3424. dialog,
  3425. pubkey,
  3426. endpoints,
  3427. windows
  3428. );
  3429. }
  3430. }
  3431. impl ToTokens for CspDirectiveSources {
  3432. fn to_tokens(&self, tokens: &mut TokenStream) {
  3433. let prefix = quote! { ::tauri::utils::config::CspDirectiveSources };
  3434. tokens.append_all(match self {
  3435. Self::Inline(sources) => {
  3436. let sources = sources.as_str();
  3437. quote!(#prefix::Inline(#sources.into()))
  3438. }
  3439. Self::List(list) => {
  3440. let list = vec_lit(list, str_lit);
  3441. quote!(#prefix::List(#list))
  3442. }
  3443. })
  3444. }
  3445. }
  3446. impl ToTokens for Csp {
  3447. fn to_tokens(&self, tokens: &mut TokenStream) {
  3448. let prefix = quote! { ::tauri::utils::config::Csp };
  3449. tokens.append_all(match self {
  3450. Self::Policy(policy) => {
  3451. let policy = policy.as_str();
  3452. quote!(#prefix::Policy(#policy.into()))
  3453. }
  3454. Self::DirectiveMap(list) => {
  3455. let map = map_lit(
  3456. quote! { ::std::collections::HashMap },
  3457. list,
  3458. str_lit,
  3459. identity,
  3460. );
  3461. quote!(#prefix::DirectiveMap(#map))
  3462. }
  3463. })
  3464. }
  3465. }
  3466. impl ToTokens for DisabledCspModificationKind {
  3467. fn to_tokens(&self, tokens: &mut TokenStream) {
  3468. let prefix = quote! { ::tauri::utils::config::DisabledCspModificationKind };
  3469. tokens.append_all(match self {
  3470. Self::Flag(flag) => {
  3471. quote! { #prefix::Flag(#flag) }
  3472. }
  3473. Self::List(directives) => {
  3474. let directives = vec_lit(directives, str_lit);
  3475. quote! { #prefix::List(#directives) }
  3476. }
  3477. });
  3478. }
  3479. }
  3480. impl ToTokens for RemoteDomainAccessScope {
  3481. fn to_tokens(&self, tokens: &mut TokenStream) {
  3482. let scheme = opt_str_lit(self.scheme.as_ref());
  3483. let domain = str_lit(&self.domain);
  3484. let windows = vec_lit(&self.windows, str_lit);
  3485. let plugins = vec_lit(&self.plugins, str_lit);
  3486. let enable_tauri_api = self.enable_tauri_api;
  3487. literal_struct!(
  3488. tokens,
  3489. RemoteDomainAccessScope,
  3490. scheme,
  3491. domain,
  3492. windows,
  3493. plugins,
  3494. enable_tauri_api
  3495. );
  3496. }
  3497. }
  3498. impl ToTokens for SecurityConfig {
  3499. fn to_tokens(&self, tokens: &mut TokenStream) {
  3500. let csp = opt_lit(self.csp.as_ref());
  3501. let dev_csp = opt_lit(self.dev_csp.as_ref());
  3502. let freeze_prototype = self.freeze_prototype;
  3503. let dangerous_disable_asset_csp_modification = &self.dangerous_disable_asset_csp_modification;
  3504. let dangerous_use_http_scheme = &self.dangerous_use_http_scheme;
  3505. let dangerous_remote_domain_ipc_access =
  3506. vec_lit(&self.dangerous_remote_domain_ipc_access, identity);
  3507. literal_struct!(
  3508. tokens,
  3509. SecurityConfig,
  3510. csp,
  3511. dev_csp,
  3512. freeze_prototype,
  3513. dangerous_disable_asset_csp_modification,
  3514. dangerous_remote_domain_ipc_access,
  3515. dangerous_use_http_scheme
  3516. );
  3517. }
  3518. }
  3519. impl ToTokens for SystemTrayConfig {
  3520. fn to_tokens(&self, tokens: &mut TokenStream) {
  3521. let icon_as_template = self.icon_as_template;
  3522. let menu_on_left_click = self.menu_on_left_click;
  3523. let icon_path = path_buf_lit(&self.icon_path);
  3524. let title = opt_str_lit(self.title.as_ref());
  3525. literal_struct!(
  3526. tokens,
  3527. SystemTrayConfig,
  3528. icon_path,
  3529. icon_as_template,
  3530. menu_on_left_click,
  3531. title
  3532. );
  3533. }
  3534. }
  3535. impl ToTokens for FsAllowlistScope {
  3536. fn to_tokens(&self, tokens: &mut TokenStream) {
  3537. let prefix = quote! { ::tauri::utils::config::FsAllowlistScope };
  3538. tokens.append_all(match self {
  3539. Self::AllowedPaths(allow) => {
  3540. let allowed_paths = vec_lit(allow, path_buf_lit);
  3541. quote! { #prefix::AllowedPaths(#allowed_paths) }
  3542. }
  3543. Self::Scope { allow, deny , require_literal_leading_dot} => {
  3544. let allow = vec_lit(allow, path_buf_lit);
  3545. let deny = vec_lit(deny, path_buf_lit);
  3546. let require_literal_leading_dot = opt_lit(require_literal_leading_dot.as_ref());
  3547. quote! { #prefix::Scope { allow: #allow, deny: #deny, require_literal_leading_dot: #require_literal_leading_dot } }
  3548. }
  3549. });
  3550. }
  3551. }
  3552. impl ToTokens for FsAllowlistConfig {
  3553. fn to_tokens(&self, tokens: &mut TokenStream) {
  3554. let scope = &self.scope;
  3555. tokens.append_all(quote! { ::tauri::utils::config::FsAllowlistConfig { scope: #scope, ..Default::default() } })
  3556. }
  3557. }
  3558. impl ToTokens for ProtocolAllowlistConfig {
  3559. fn to_tokens(&self, tokens: &mut TokenStream) {
  3560. let asset_scope = &self.asset_scope;
  3561. tokens.append_all(quote! { ::tauri::utils::config::ProtocolAllowlistConfig { asset_scope: #asset_scope, ..Default::default() } })
  3562. }
  3563. }
  3564. impl ToTokens for HttpAllowlistScope {
  3565. fn to_tokens(&self, tokens: &mut TokenStream) {
  3566. let allowed_urls = vec_lit(&self.0, url_lit);
  3567. tokens.append_all(quote! { ::tauri::utils::config::HttpAllowlistScope(#allowed_urls) })
  3568. }
  3569. }
  3570. impl ToTokens for HttpAllowlistConfig {
  3571. fn to_tokens(&self, tokens: &mut TokenStream) {
  3572. let scope = &self.scope;
  3573. tokens.append_all(quote! { ::tauri::utils::config::HttpAllowlistConfig { scope: #scope, ..Default::default() } })
  3574. }
  3575. }
  3576. impl ToTokens for ShellAllowedCommand {
  3577. fn to_tokens(&self, tokens: &mut TokenStream) {
  3578. let name = str_lit(&self.name);
  3579. let command = path_buf_lit(&self.command);
  3580. let args = &self.args;
  3581. let sidecar = &self.sidecar;
  3582. literal_struct!(tokens, ShellAllowedCommand, name, command, args, sidecar);
  3583. }
  3584. }
  3585. impl ToTokens for ShellAllowedArgs {
  3586. fn to_tokens(&self, tokens: &mut TokenStream) {
  3587. let prefix = quote! { ::tauri::utils::config::ShellAllowedArgs };
  3588. tokens.append_all(match self {
  3589. Self::Flag(flag) => quote!(#prefix::Flag(#flag)),
  3590. Self::List(list) => {
  3591. let list = vec_lit(list, identity);
  3592. quote!(#prefix::List(#list))
  3593. }
  3594. })
  3595. }
  3596. }
  3597. impl ToTokens for ShellAllowedArg {
  3598. fn to_tokens(&self, tokens: &mut TokenStream) {
  3599. let prefix = quote! { ::tauri::utils::config::ShellAllowedArg };
  3600. tokens.append_all(match self {
  3601. Self::Fixed(fixed) => {
  3602. let fixed = str_lit(fixed);
  3603. quote!(#prefix::Fixed(#fixed))
  3604. }
  3605. Self::Var { validator } => {
  3606. let validator = str_lit(validator);
  3607. quote!(#prefix::Var { validator: #validator })
  3608. }
  3609. })
  3610. }
  3611. }
  3612. impl ToTokens for ShellAllowlistOpen {
  3613. fn to_tokens(&self, tokens: &mut TokenStream) {
  3614. let prefix = quote! { ::tauri::utils::config::ShellAllowlistOpen };
  3615. tokens.append_all(match self {
  3616. Self::Flag(flag) => quote!(#prefix::Flag(#flag)),
  3617. Self::Validate(regex) => quote!(#prefix::Validate(#regex)),
  3618. })
  3619. }
  3620. }
  3621. impl ToTokens for ShellAllowlistScope {
  3622. fn to_tokens(&self, tokens: &mut TokenStream) {
  3623. let allowed_commands = vec_lit(&self.0, identity);
  3624. tokens.append_all(quote! { ::tauri::utils::config::ShellAllowlistScope(#allowed_commands) })
  3625. }
  3626. }
  3627. impl ToTokens for ShellAllowlistConfig {
  3628. fn to_tokens(&self, tokens: &mut TokenStream) {
  3629. let scope = &self.scope;
  3630. tokens.append_all(quote! { ::tauri::utils::config::ShellAllowlistConfig { scope: #scope, ..Default::default() } })
  3631. }
  3632. }
  3633. impl ToTokens for AllowlistConfig {
  3634. fn to_tokens(&self, tokens: &mut TokenStream) {
  3635. let fs = &self.fs;
  3636. let protocol = &self.protocol;
  3637. let http = &self.http;
  3638. let shell = &self.shell;
  3639. tokens.append_all(
  3640. quote! { ::tauri::utils::config::AllowlistConfig { fs: #fs, protocol: #protocol, http: #http, shell: #shell, ..Default::default() } },
  3641. )
  3642. }
  3643. }
  3644. impl ToTokens for TauriConfig {
  3645. fn to_tokens(&self, tokens: &mut TokenStream) {
  3646. let pattern = &self.pattern;
  3647. let windows = vec_lit(&self.windows, identity);
  3648. let cli = opt_lit(self.cli.as_ref());
  3649. let bundle = &self.bundle;
  3650. let updater = &self.updater;
  3651. let security = &self.security;
  3652. let system_tray = opt_lit(self.system_tray.as_ref());
  3653. let allowlist = &self.allowlist;
  3654. let macos_private_api = self.macos_private_api;
  3655. literal_struct!(
  3656. tokens,
  3657. TauriConfig,
  3658. pattern,
  3659. windows,
  3660. cli,
  3661. bundle,
  3662. updater,
  3663. security,
  3664. system_tray,
  3665. allowlist,
  3666. macos_private_api
  3667. );
  3668. }
  3669. }
  3670. impl ToTokens for PluginConfig {
  3671. fn to_tokens(&self, tokens: &mut TokenStream) {
  3672. let config = map_lit(
  3673. quote! { ::std::collections::HashMap },
  3674. &self.0,
  3675. str_lit,
  3676. json_value_lit,
  3677. );
  3678. tokens.append_all(quote! { ::tauri::utils::config::PluginConfig(#config) })
  3679. }
  3680. }
  3681. impl ToTokens for PackageConfig {
  3682. fn to_tokens(&self, tokens: &mut TokenStream) {
  3683. let product_name = opt_str_lit(self.product_name.as_ref());
  3684. let version = opt_str_lit(self.version.as_ref());
  3685. literal_struct!(tokens, PackageConfig, product_name, version);
  3686. }
  3687. }
  3688. impl ToTokens for Config {
  3689. fn to_tokens(&self, tokens: &mut TokenStream) {
  3690. let schema = quote!(None);
  3691. let package = &self.package;
  3692. let tauri = &self.tauri;
  3693. let build = &self.build;
  3694. let plugins = &self.plugins;
  3695. literal_struct!(tokens, Config, schema, package, tauri, build, plugins);
  3696. }
  3697. }
  3698. }
  3699. #[cfg(test)]
  3700. mod test {
  3701. use super::*;
  3702. // TODO: create a test that compares a config to a json config
  3703. #[test]
  3704. // test all of the default functions
  3705. fn test_defaults() {
  3706. // get default tauri config
  3707. let t_config = TauriConfig::default();
  3708. // get default build config
  3709. let b_config = BuildConfig::default();
  3710. // get default dev path
  3711. let d_path = default_dev_path();
  3712. // get default window
  3713. let d_windows: Vec<WindowConfig> = vec![];
  3714. // get default bundle
  3715. let d_bundle = BundleConfig::default();
  3716. // get default updater
  3717. let d_updater = UpdaterConfig::default();
  3718. // create a tauri config.
  3719. let tauri = TauriConfig {
  3720. pattern: Default::default(),
  3721. windows: vec![],
  3722. bundle: BundleConfig {
  3723. active: false,
  3724. targets: Default::default(),
  3725. identifier: String::from(""),
  3726. publisher: None,
  3727. icon: Vec::new(),
  3728. resources: None,
  3729. copyright: None,
  3730. category: None,
  3731. short_description: None,
  3732. long_description: None,
  3733. appimage: Default::default(),
  3734. deb: Default::default(),
  3735. macos: Default::default(),
  3736. external_bin: None,
  3737. windows: Default::default(),
  3738. },
  3739. cli: None,
  3740. updater: UpdaterConfig {
  3741. active: false,
  3742. dialog: true,
  3743. pubkey: "".into(),
  3744. endpoints: None,
  3745. windows: Default::default(),
  3746. },
  3747. security: SecurityConfig {
  3748. csp: None,
  3749. dev_csp: None,
  3750. freeze_prototype: false,
  3751. dangerous_disable_asset_csp_modification: DisabledCspModificationKind::Flag(false),
  3752. dangerous_remote_domain_ipc_access: Vec::new(),
  3753. dangerous_use_http_scheme: false,
  3754. },
  3755. allowlist: AllowlistConfig::default(),
  3756. system_tray: None,
  3757. macos_private_api: false,
  3758. };
  3759. // create a build config
  3760. let build = BuildConfig {
  3761. runner: None,
  3762. dev_path: AppUrl::Url(WindowUrl::External(
  3763. Url::parse("http://localhost:8080").unwrap(),
  3764. )),
  3765. dist_dir: AppUrl::Url(WindowUrl::App("../dist".into())),
  3766. before_dev_command: None,
  3767. before_build_command: None,
  3768. before_bundle_command: None,
  3769. features: None,
  3770. with_global_tauri: false,
  3771. };
  3772. // test the configs
  3773. assert_eq!(t_config, tauri);
  3774. assert_eq!(b_config, build);
  3775. assert_eq!(d_bundle, tauri.bundle);
  3776. assert_eq!(d_updater, tauri.updater);
  3777. assert_eq!(
  3778. d_path,
  3779. AppUrl::Url(WindowUrl::External(
  3780. Url::parse("http://localhost:8080").unwrap()
  3781. ))
  3782. );
  3783. assert_eq!(d_windows, tauri.windows);
  3784. }
  3785. }