config.rs 84 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611
  1. // Copyright 2019-2021 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 serde::{
  16. de::{Deserializer, Error as DeError, Visitor},
  17. Deserialize, Serialize,
  18. };
  19. use serde_json::Value as JsonValue;
  20. use serde_with::skip_serializing_none;
  21. use url::Url;
  22. use std::{collections::HashMap, fmt, fs::read_to_string, path::PathBuf};
  23. /// Items to help with parsing content into a [`Config`].
  24. pub mod parse;
  25. pub use self::parse::parse;
  26. /// An URL to open on a Tauri webview window.
  27. #[derive(PartialEq, Debug, Clone, Deserialize, Serialize)]
  28. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  29. #[serde(untagged)]
  30. #[non_exhaustive]
  31. pub enum WindowUrl {
  32. /// An external URL.
  33. External(Url),
  34. /// An app URL.
  35. App(PathBuf),
  36. }
  37. impl fmt::Display for WindowUrl {
  38. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  39. match self {
  40. Self::External(url) => write!(f, "{}", url),
  41. Self::App(path) => write!(f, "{}", path.display()),
  42. }
  43. }
  44. }
  45. impl Default for WindowUrl {
  46. fn default() -> Self {
  47. Self::App("index.html".into())
  48. }
  49. }
  50. /// Targets to bundle.
  51. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  52. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  53. #[serde(untagged)]
  54. pub enum BundleTarget {
  55. /// A list of bundle targets.
  56. All(Vec<String>),
  57. /// A single bundle target.
  58. One(String),
  59. }
  60. impl BundleTarget {
  61. /// Gets the bundle targets as a [`Vec`].
  62. #[allow(dead_code)]
  63. pub fn to_vec(&self) -> Vec<String> {
  64. match self {
  65. Self::All(list) => list.clone(),
  66. Self::One(i) => vec![i.clone()],
  67. }
  68. }
  69. }
  70. /// Configuration for Debian (.deb) bundles.
  71. #[skip_serializing_none]
  72. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  73. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  74. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  75. pub struct DebConfig {
  76. /// The list of deb dependencies your application relies on.
  77. pub depends: Option<Vec<String>>,
  78. /// Enable the boostrapper script.
  79. #[serde(default)]
  80. pub use_bootstrapper: bool,
  81. /// The files to include on the package.
  82. #[serde(default)]
  83. pub files: HashMap<PathBuf, PathBuf>,
  84. }
  85. /// Configuration for the macOS bundles.
  86. #[skip_serializing_none]
  87. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  88. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  89. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  90. pub struct MacConfig {
  91. /// A list of strings indicating any macOS X frameworks that need to be bundled with the application.
  92. ///
  93. /// 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.
  94. pub frameworks: Option<Vec<String>>,
  95. /// A version string indicating the minimum macOS X version that the bundled application supports.
  96. pub minimum_system_version: Option<String>,
  97. /// Allows your application to communicate with the outside world.
  98. /// It should be a lowercase, without port and protocol domain name.
  99. pub exception_domain: Option<String>,
  100. /// The path to the license file to add to the DMG bundle.
  101. pub license: Option<String>,
  102. /// Enable the boostrapper script.
  103. #[serde(default)]
  104. pub use_bootstrapper: bool,
  105. /// Identity to use for code signing.
  106. pub signing_identity: Option<String>,
  107. /// Provider short name for notarization.
  108. pub provider_short_name: Option<String>,
  109. /// Path to the entitlements file.
  110. pub entitlements: Option<String>,
  111. }
  112. /// Configuration for a target language for the WiX build.
  113. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  114. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  115. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  116. pub struct WixLanguageConfig {
  117. /// The path to a locale (`.wxl`) file. See <https://wixtoolset.org/documentation/manual/v3/howtos/ui_and_localization/build_a_localized_version.html>.
  118. pub locale_path: Option<String>,
  119. }
  120. /// The languages to build using WiX.
  121. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  122. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  123. #[serde(untagged)]
  124. pub enum WixLanguage {
  125. /// A single language to build, without configuration.
  126. One(String),
  127. /// A list of languages to build, without configuration.
  128. List(Vec<String>),
  129. /// A map of languages and its configuration.
  130. Localized(HashMap<String, WixLanguageConfig>),
  131. }
  132. impl Default for WixLanguage {
  133. fn default() -> Self {
  134. Self::One("en-US".into())
  135. }
  136. }
  137. /// Configuration for the MSI bundle using WiX.
  138. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  139. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  140. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  141. pub struct WixConfig {
  142. /// The installer languages to build. See <https://docs.microsoft.com/en-us/windows/win32/msi/localizing-the-error-and-actiontext-tables>.
  143. #[serde(default)]
  144. pub language: WixLanguage,
  145. /// A custom .wxs template to use.
  146. pub template: Option<PathBuf>,
  147. /// A list of paths to .wxs files with WiX fragments to use.
  148. #[serde(default)]
  149. pub fragment_paths: Vec<PathBuf>,
  150. /// The ComponentGroup element ids you want to reference from the fragments.
  151. #[serde(default)]
  152. pub component_group_refs: Vec<String>,
  153. /// The Component element ids you want to reference from the fragments.
  154. #[serde(default)]
  155. pub component_refs: Vec<String>,
  156. /// The FeatureGroup element ids you want to reference from the fragments.
  157. #[serde(default)]
  158. pub feature_group_refs: Vec<String>,
  159. /// The Feature element ids you want to reference from the fragments.
  160. #[serde(default)]
  161. pub feature_refs: Vec<String>,
  162. /// The Merge element ids you want to reference from the fragments.
  163. #[serde(default)]
  164. pub merge_refs: Vec<String>,
  165. /// Disables the Webview2 runtime installation after app install.
  166. #[serde(default)]
  167. pub skip_webview_install: bool,
  168. /// The path to the license file to render on the installer.
  169. ///
  170. /// Must be an RTF file, so if a different extension is provided, we convert it to the RTF format.
  171. pub license: Option<PathBuf>,
  172. /// Create an elevated update task within Windows Task Scheduler.
  173. #[serde(default)]
  174. pub enable_elevated_update_task: bool,
  175. /// Path to a bitmap file to use as the installation user interface banner.
  176. /// This bitmap will appear at the top of all but the first page of the installer.
  177. ///
  178. /// The required dimensions are 493px × 58px.
  179. pub banner_path: Option<PathBuf>,
  180. /// Path to a bitmap file to use on the installation user interface dialogs.
  181. /// It is used on the welcome and completion dialogs.
  182. /// The required dimensions are 493px × 312px.
  183. pub dialog_image_path: Option<PathBuf>,
  184. }
  185. /// Windows bundler configuration.
  186. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  187. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  188. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  189. pub struct WindowsConfig {
  190. /// Specifies the file digest algorithm to use for creating file signatures.
  191. /// Required for code signing. SHA-256 is recommended.
  192. pub digest_algorithm: Option<String>,
  193. /// Specifies the SHA1 hash of the signing certificate.
  194. pub certificate_thumbprint: Option<String>,
  195. /// Server to use during timestamping.
  196. pub timestamp_url: Option<String>,
  197. /// Path to the webview fixed runtime to use.
  198. ///
  199. /// The fixed version can be downloaded [on the official website](https://developer.microsoft.com/en-us/microsoft-edge/webview2/#download-section).
  200. /// The `.cab` file must be extracted to a folder and this folder path must be defined on this field.
  201. pub webview_fixed_runtime_path: Option<PathBuf>,
  202. /// Configuration for the MSI generated with WiX.
  203. pub wix: Option<WixConfig>,
  204. }
  205. /// Configuration for tauri-bundler.
  206. #[skip_serializing_none]
  207. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  208. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  209. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  210. pub struct BundleConfig {
  211. /// Whether we should build your app with tauri-bundler or plain `cargo build`
  212. #[serde(default)]
  213. pub active: bool,
  214. /// The bundle targets, currently supports ["deb", "app", "msi", "appimage", "dmg"] or "all"
  215. pub targets: Option<BundleTarget>,
  216. /// The app's identifier
  217. pub identifier: String,
  218. /// The app's icons
  219. #[serde(default)]
  220. pub icon: Vec<String>,
  221. /// App resources to bundle.
  222. /// Each resource is a path to a file or directory.
  223. /// Glob patterns are supported.
  224. pub resources: Option<Vec<String>>,
  225. /// A copyright string associated with your application.
  226. pub copyright: Option<String>,
  227. /// The application kind.
  228. pub category: Option<String>,
  229. /// A short description of your application.
  230. pub short_description: Option<String>,
  231. /// A longer, multi-line description of the application.
  232. pub long_description: Option<String>,
  233. /// Configuration for the Debian bundle.
  234. #[serde(default)]
  235. pub deb: DebConfig,
  236. /// Configuration for the macOS bundles.
  237. #[serde(rename = "macOS", default)]
  238. pub macos: MacConfig,
  239. /// A list of—either absolute or relative—paths to binaries to embed with your application.
  240. ///
  241. /// Note that Tauri will look for system-specific binaries following the pattern "binary-name{-target-triple}{.system-extension}".
  242. ///
  243. /// E.g. for the external binary "my-binary", Tauri looks for:
  244. ///
  245. /// - "my-binary-x86_64-pc-windows-msvc.exe" for Windows
  246. /// - "my-binary-x86_64-apple-darwin" for macOS
  247. /// - "my-binary-x86_64-unknown-linux-gnu" for Linux
  248. ///
  249. /// so don't forget to provide binaries for all targeted platforms.
  250. pub external_bin: Option<Vec<String>>,
  251. /// Configuration for the Windows bundle.
  252. #[serde(default)]
  253. pub windows: WindowsConfig,
  254. }
  255. /// A CLI argument definition.
  256. #[skip_serializing_none]
  257. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  258. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  259. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  260. pub struct CliArg {
  261. /// The short version of the argument, without the preceding -.
  262. ///
  263. /// NOTE: Any leading - characters will be stripped, and only the first non - character will be used as the short version.
  264. pub short: Option<char>,
  265. /// The unique argument name
  266. pub name: String,
  267. /// The argument description which will be shown on the help information.
  268. /// Typically, this is a short (one line) description of the arg.
  269. pub description: Option<String>,
  270. /// The argument long description which will be shown on the help information.
  271. /// Typically this a more detailed (multi-line) message that describes the argument.
  272. pub long_description: Option<String>,
  273. /// Specifies that the argument takes a value at run time.
  274. ///
  275. /// NOTE: values for arguments may be specified in any of the following methods
  276. /// - Using a space such as -o value or --option value
  277. /// - Using an equals and no space such as -o=value or --option=value
  278. /// - Use a short and no space such as -ovalue
  279. pub takes_value: Option<bool>,
  280. /// Specifies that the argument may have an unknown number of multiple values. Without any other settings, this argument may appear only once.
  281. ///
  282. /// For example, --opt val1 val2 is allowed, but --opt val1 val2 --opt val3 is not.
  283. ///
  284. /// NOTE: Setting this requires `takes_value` to be set to true.
  285. pub multiple: Option<bool>,
  286. /// Specifies that the argument may appear more than once.
  287. /// 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.
  288. /// 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)
  289. ///
  290. /// For example, --opt val1 --opt val2 is allowed, but --opt val1 val2 is not.
  291. pub multiple_occurrences: Option<bool>,
  292. /// Specifies how many values are required to satisfy this argument. For example, if you had a
  293. /// `-f <file>` argument where you wanted exactly 3 'files' you would set
  294. /// `number_of_values = 3`, and this argument wouldn't be satisfied unless the user provided
  295. /// 3 and only 3 values.
  296. ///
  297. /// **NOTE:** Does *not* require `multiple_occurrences = true` to be set. Setting
  298. /// `multiple_occurrences = true` would allow `-f <file> <file> <file> -f <file> <file> <file>` where
  299. /// as *not* setting it would only allow one occurrence of this argument.
  300. ///
  301. /// **NOTE:** implicitly sets `takes_value = true` and `multiple_values = true`.
  302. pub number_of_values: Option<usize>,
  303. /// Specifies a list of possible values for this argument.
  304. /// At runtime, the CLI verifies that only one of the specified values was used, or fails with an error message.
  305. pub possible_values: Option<Vec<String>>,
  306. /// Specifies the minimum number of values for this argument.
  307. /// For example, if you had a -f <file> argument where you wanted at least 2 'files',
  308. /// you would set `minValues: 2`, and this argument would be satisfied if the user provided, 2 or more values.
  309. pub min_values: Option<usize>,
  310. /// Specifies the maximum number of values are for this argument.
  311. /// For example, if you had a -f <file> argument where you wanted up to 3 'files',
  312. /// you would set .max_values(3), and this argument would be satisfied if the user provided, 1, 2, or 3 values.
  313. pub max_values: Option<usize>,
  314. /// Sets whether or not the argument is required by default.
  315. ///
  316. /// - Required by default means it is required, when no other conflicting rules have been evaluated
  317. /// - Conflicting rules take precedence over being required.
  318. pub required: Option<bool>,
  319. /// Sets an arg that override this arg's required setting
  320. /// i.e. this arg will be required unless this other argument is present.
  321. pub required_unless_present: Option<String>,
  322. /// Sets args that override this arg's required setting
  323. /// i.e. this arg will be required unless all these other arguments are present.
  324. pub required_unless_present_all: Option<Vec<String>>,
  325. /// Sets args that override this arg's required setting
  326. /// i.e. this arg will be required unless at least one of these other arguments are present.
  327. pub required_unless_present_any: Option<Vec<String>>,
  328. /// Sets a conflicting argument by name
  329. /// i.e. when using this argument, the following argument can't be present and vice versa.
  330. pub conflicts_with: Option<String>,
  331. /// The same as conflictsWith but allows specifying multiple two-way conflicts per argument.
  332. pub conflicts_with_all: Option<Vec<String>>,
  333. /// Tets an argument by name that is required when this one is present
  334. /// i.e. when using this argument, the following argument must be present.
  335. pub requires: Option<String>,
  336. /// Sts multiple arguments by names that are required when this one is present
  337. /// i.e. when using this argument, the following arguments must be present.
  338. pub requires_all: Option<Vec<String>>,
  339. /// Allows a conditional requirement with the signature [arg, value]
  340. /// the requirement will only become valid if `arg`'s value equals `${value}`.
  341. pub requires_if: Option<Vec<String>>,
  342. /// Allows specifying that an argument is required conditionally with the signature [arg, value]
  343. /// the requirement will only become valid if the `arg`'s value equals `${value}`.
  344. pub required_if_eq: Option<Vec<String>>,
  345. /// Requires that options use the --option=val syntax
  346. /// i.e. an equals between the option and associated value.
  347. pub require_equals: Option<bool>,
  348. /// The positional argument index, starting at 1.
  349. ///
  350. /// The index refers to position according to other positional argument.
  351. /// It does not define position in the argument list as a whole. When utilized with multiple=true,
  352. /// only the last positional argument may be defined as multiple (i.e. the one with the highest index).
  353. pub index: Option<usize>,
  354. }
  355. /// describes a CLI configuration
  356. #[skip_serializing_none]
  357. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  358. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  359. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  360. pub struct CliConfig {
  361. /// Command description which will be shown on the help information.
  362. pub description: Option<String>,
  363. /// Command long description which will be shown on the help information.
  364. pub long_description: Option<String>,
  365. /// Adds additional help information to be displayed in addition to auto-generated help.
  366. /// This information is displayed before the auto-generated help information.
  367. /// This is often used for header information.
  368. pub before_help: Option<String>,
  369. /// Adds additional help information to be displayed in addition to auto-generated help.
  370. /// This information is displayed after the auto-generated help information.
  371. /// This is often used to describe how to use the arguments, or caveats to be noted.
  372. pub after_help: Option<String>,
  373. /// List of arguments for the command
  374. pub args: Option<Vec<CliArg>>,
  375. /// List of subcommands of this command
  376. pub subcommands: Option<HashMap<String, CliConfig>>,
  377. }
  378. impl CliConfig {
  379. /// List of arguments for the command
  380. pub fn args(&self) -> Option<&Vec<CliArg>> {
  381. self.args.as_ref()
  382. }
  383. /// List of subcommands of this command
  384. pub fn subcommands(&self) -> Option<&HashMap<String, CliConfig>> {
  385. self.subcommands.as_ref()
  386. }
  387. /// Command description which will be shown on the help information.
  388. pub fn description(&self) -> Option<&String> {
  389. self.description.as_ref()
  390. }
  391. /// Command long description which will be shown on the help information.
  392. pub fn long_description(&self) -> Option<&String> {
  393. self.description.as_ref()
  394. }
  395. /// Adds additional help information to be displayed in addition to auto-generated help.
  396. /// This information is displayed before the auto-generated help information.
  397. /// This is often used for header information.
  398. pub fn before_help(&self) -> Option<&String> {
  399. self.before_help.as_ref()
  400. }
  401. /// Adds additional help information to be displayed in addition to auto-generated help.
  402. /// This information is displayed after the auto-generated help information.
  403. /// This is often used to describe how to use the arguments, or caveats to be noted.
  404. pub fn after_help(&self) -> Option<&String> {
  405. self.after_help.as_ref()
  406. }
  407. }
  408. /// The window configuration object.
  409. #[skip_serializing_none]
  410. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  411. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  412. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  413. pub struct WindowConfig {
  414. /// The window identifier. It must be alphanumeric.
  415. #[serde(default = "default_window_label")]
  416. pub label: String,
  417. /// The window webview URL.
  418. #[serde(default)]
  419. pub url: WindowUrl,
  420. /// Whether the file drop is enabled or not on the webview. By default it is enabled.
  421. ///
  422. /// Disabling it is required to use drag and drop on the frontend on Windows.
  423. #[serde(default = "default_file_drop_enabled")]
  424. pub file_drop_enabled: bool,
  425. /// Whether or not the window starts centered or not.
  426. #[serde(default)]
  427. pub center: bool,
  428. /// The horizontal position of the window's top left corner
  429. pub x: Option<f64>,
  430. /// The vertical position of the window's top left corner
  431. pub y: Option<f64>,
  432. /// The window width.
  433. #[serde(default = "default_width")]
  434. pub width: f64,
  435. /// The window height.
  436. #[serde(default = "default_height")]
  437. pub height: f64,
  438. /// The min window width.
  439. pub min_width: Option<f64>,
  440. /// The min window height.
  441. pub min_height: Option<f64>,
  442. /// The max window width.
  443. pub max_width: Option<f64>,
  444. /// The max window height.
  445. pub max_height: Option<f64>,
  446. /// Whether the window is resizable or not.
  447. #[serde(default = "default_resizable")]
  448. pub resizable: bool,
  449. /// The window title.
  450. #[serde(default = "default_title")]
  451. pub title: String,
  452. /// Whether the window starts as fullscreen or not.
  453. #[serde(default)]
  454. pub fullscreen: bool,
  455. /// Whether the window will be initially hidden or focused.
  456. #[serde(default = "default_focus")]
  457. pub focus: bool,
  458. /// Whether the window is transparent or not.
  459. ///
  460. /// Note that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri.conf.json > tauri > macosPrivateApi`.
  461. /// WARNING: Using private APIs on `macOS` prevents your application from being accepted for the `App Store`.
  462. #[serde(default)]
  463. pub transparent: bool,
  464. /// Whether the window is maximized or not.
  465. #[serde(default)]
  466. pub maximized: bool,
  467. /// Whether the window is visible or not.
  468. #[serde(default = "default_visible")]
  469. pub visible: bool,
  470. /// Whether the window should have borders and bars.
  471. #[serde(default = "default_decorations")]
  472. pub decorations: bool,
  473. /// Whether the window should always be on top of other windows.
  474. #[serde(default)]
  475. pub always_on_top: bool,
  476. /// Whether or not the window icon should be added to the taskbar.
  477. #[serde(default)]
  478. pub skip_taskbar: bool,
  479. }
  480. impl Default for WindowConfig {
  481. fn default() -> Self {
  482. Self {
  483. label: default_window_label(),
  484. url: WindowUrl::default(),
  485. file_drop_enabled: default_file_drop_enabled(),
  486. center: false,
  487. x: None,
  488. y: None,
  489. width: default_width(),
  490. height: default_height(),
  491. min_width: None,
  492. min_height: None,
  493. max_width: None,
  494. max_height: None,
  495. resizable: default_resizable(),
  496. title: default_title(),
  497. fullscreen: false,
  498. focus: false,
  499. transparent: false,
  500. maximized: false,
  501. visible: default_visible(),
  502. decorations: default_decorations(),
  503. always_on_top: false,
  504. skip_taskbar: false,
  505. }
  506. }
  507. }
  508. fn default_window_label() -> String {
  509. "main".to_string()
  510. }
  511. fn default_width() -> f64 {
  512. 800f64
  513. }
  514. fn default_height() -> f64 {
  515. 600f64
  516. }
  517. fn default_resizable() -> bool {
  518. true
  519. }
  520. fn default_title() -> String {
  521. "Tauri App".to_string()
  522. }
  523. fn default_focus() -> bool {
  524. true
  525. }
  526. fn default_visible() -> bool {
  527. true
  528. }
  529. fn default_decorations() -> bool {
  530. true
  531. }
  532. fn default_file_drop_enabled() -> bool {
  533. true
  534. }
  535. /// Security configuration.
  536. #[skip_serializing_none]
  537. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  538. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  539. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  540. pub struct SecurityConfig {
  541. /// The Content Security Policy that will be injected on all HTML files on the built application.
  542. /// If [`dev_csp`](SecurityConfig.dev_csp) is not specified, this value is also injected on dev.
  543. ///
  544. /// This is a really important part of the configuration since it helps you ensure your WebView is secured.
  545. /// See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>.
  546. pub csp: Option<String>,
  547. /// The Content Security Policy that will be injected on all HTML files on development.
  548. ///
  549. /// This is a really important part of the configuration since it helps you ensure your WebView is secured.
  550. /// See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>.
  551. pub dev_csp: Option<String>,
  552. /// Freeze the `Object.prototype` when using the custom protocol.
  553. #[serde(default = "default_freeze_prototype")]
  554. pub freeze_prototype: bool,
  555. }
  556. impl Default for SecurityConfig {
  557. fn default() -> Self {
  558. Self {
  559. csp: None,
  560. dev_csp: None,
  561. freeze_prototype: default_freeze_prototype(),
  562. }
  563. }
  564. }
  565. fn default_freeze_prototype() -> bool {
  566. true
  567. }
  568. /// Defines an allowlist type.
  569. pub trait Allowlist {
  570. /// Returns all features associated with the allowlist struct.
  571. fn all_features() -> Vec<&'static str>;
  572. /// Returns the tauri features enabled on this allowlist.
  573. fn to_features(&self) -> Vec<&'static str>;
  574. }
  575. macro_rules! check_feature {
  576. ($self:ident, $features:ident, $flag:ident, $feature_name: expr) => {
  577. if $self.$flag {
  578. $features.push($feature_name)
  579. }
  580. };
  581. }
  582. /// Filesystem scope definition.
  583. /// It is a list of glob patterns that restrict the API access from the webview.
  584. ///
  585. /// Each pattern can start with a variable that resolves to a system base directory.
  586. /// The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`,
  587. /// `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`,
  588. /// `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$CWD`.
  589. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  590. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  591. pub struct FsAllowlistScope(pub Vec<PathBuf>);
  592. /// Allowlist for the file system APIs.
  593. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  594. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  595. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  596. pub struct FsAllowlistConfig {
  597. /// The access scope for the filesystem APIs.
  598. #[serde(default)]
  599. pub scope: FsAllowlistScope,
  600. /// Use this flag to enable all file system API features.
  601. #[serde(default)]
  602. pub all: bool,
  603. /// Read file from local filesystem.
  604. #[serde(default)]
  605. pub read_file: bool,
  606. /// Write file to local filesystem.
  607. #[serde(default)]
  608. pub write_file: bool,
  609. /// Read directory from local filesystem.
  610. #[serde(default)]
  611. pub read_dir: bool,
  612. /// Copy file from local filesystem.
  613. #[serde(default)]
  614. pub copy_file: bool,
  615. /// Create directory from local filesystem.
  616. #[serde(default)]
  617. pub create_dir: bool,
  618. /// Remove directory from local filesystem.
  619. #[serde(default)]
  620. pub remove_dir: bool,
  621. /// Remove file from local filesystem.
  622. #[serde(default)]
  623. pub remove_file: bool,
  624. /// Rename file from local filesystem.
  625. #[serde(default)]
  626. pub rename_file: bool,
  627. }
  628. impl Allowlist for FsAllowlistConfig {
  629. fn all_features() -> Vec<&'static str> {
  630. let allowlist = Self {
  631. scope: Default::default(),
  632. all: false,
  633. read_file: true,
  634. write_file: true,
  635. read_dir: true,
  636. copy_file: true,
  637. create_dir: true,
  638. remove_dir: true,
  639. remove_file: true,
  640. rename_file: true,
  641. };
  642. let mut features = allowlist.to_features();
  643. features.push("fs-all");
  644. features
  645. }
  646. fn to_features(&self) -> Vec<&'static str> {
  647. if self.all {
  648. vec!["fs-all"]
  649. } else {
  650. let mut features = Vec::new();
  651. check_feature!(self, features, read_file, "fs-read-file");
  652. check_feature!(self, features, write_file, "fs-write-file");
  653. check_feature!(self, features, read_dir, "fs-read-dir");
  654. check_feature!(self, features, copy_file, "fs-copy-file");
  655. check_feature!(self, features, create_dir, "fs-create-dir");
  656. check_feature!(self, features, remove_dir, "fs-remove-dir");
  657. check_feature!(self, features, remove_file, "fs-remove-file");
  658. check_feature!(self, features, rename_file, "fs-rename-file");
  659. features
  660. }
  661. }
  662. }
  663. /// Allowlist for the window APIs.
  664. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  665. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  666. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  667. pub struct WindowAllowlistConfig {
  668. /// Use this flag to enable all window API features.
  669. #[serde(default)]
  670. pub all: bool,
  671. /// Allows dynamic window creation.
  672. #[serde(default)]
  673. pub create: bool,
  674. /// Allows centering the window.
  675. #[serde(default)]
  676. pub center: bool,
  677. /// Allows requesting user attention on the window.
  678. #[serde(default)]
  679. pub request_user_attention: bool,
  680. /// Allows setting the resizable flag of the window.
  681. #[serde(default)]
  682. pub set_resizable: bool,
  683. /// Allows changing the window title.
  684. #[serde(default)]
  685. pub set_title: bool,
  686. /// Allows maximizing the window.
  687. #[serde(default)]
  688. pub maximize: bool,
  689. /// Allows unmaximizing the window.
  690. #[serde(default)]
  691. pub unmaximize: bool,
  692. /// Allows minimizing the window.
  693. #[serde(default)]
  694. pub minimize: bool,
  695. /// Allows unminimizing the window.
  696. #[serde(default)]
  697. pub unminimize: bool,
  698. /// Allows showing the window.
  699. #[serde(default)]
  700. pub show: bool,
  701. /// Allows hiding the window.
  702. #[serde(default)]
  703. pub hide: bool,
  704. /// Allows closing the window.
  705. #[serde(default)]
  706. pub close: bool,
  707. /// Allows setting the decorations flag of the window.
  708. #[serde(default)]
  709. pub set_decorations: bool,
  710. /// Allows setting the always_on_top flag of the window.
  711. #[serde(default)]
  712. pub set_always_on_top: bool,
  713. /// Allows setting the window size.
  714. #[serde(default)]
  715. pub set_size: bool,
  716. /// Allows setting the window minimum size.
  717. #[serde(default)]
  718. pub set_min_size: bool,
  719. /// Allows setting the window maximum size.
  720. #[serde(default)]
  721. pub set_max_size: bool,
  722. /// Allows changing the position of the window.
  723. #[serde(default)]
  724. pub set_position: bool,
  725. /// Allows setting the fullscreen flag of the window.
  726. #[serde(default)]
  727. pub set_fullscreen: bool,
  728. /// Allows focusing the window.
  729. #[serde(default)]
  730. pub set_focus: bool,
  731. /// Allows changing the window icon.
  732. #[serde(default)]
  733. pub set_icon: bool,
  734. /// Allows setting the skip_taskbar flag of the window.
  735. #[serde(default)]
  736. pub set_skip_taskbar: bool,
  737. /// Allows start dragging on the window.
  738. #[serde(default)]
  739. pub start_dragging: bool,
  740. /// Allows opening the system dialog to print the window content.
  741. #[serde(default)]
  742. pub print: bool,
  743. }
  744. impl Allowlist for WindowAllowlistConfig {
  745. fn all_features() -> Vec<&'static str> {
  746. let allowlist = Self {
  747. all: false,
  748. create: true,
  749. center: true,
  750. request_user_attention: true,
  751. set_resizable: true,
  752. set_title: true,
  753. maximize: true,
  754. unmaximize: true,
  755. minimize: true,
  756. unminimize: true,
  757. show: true,
  758. hide: true,
  759. close: true,
  760. set_decorations: true,
  761. set_always_on_top: true,
  762. set_size: true,
  763. set_min_size: true,
  764. set_max_size: true,
  765. set_position: true,
  766. set_fullscreen: true,
  767. set_focus: true,
  768. set_icon: true,
  769. set_skip_taskbar: true,
  770. start_dragging: true,
  771. print: true,
  772. };
  773. let mut features = allowlist.to_features();
  774. features.push("window-all");
  775. features
  776. }
  777. fn to_features(&self) -> Vec<&'static str> {
  778. if self.all {
  779. vec!["window-all"]
  780. } else {
  781. let mut features = Vec::new();
  782. check_feature!(self, features, create, "window-create");
  783. check_feature!(self, features, center, "window-center");
  784. check_feature!(
  785. self,
  786. features,
  787. request_user_attention,
  788. "window-request-user-attention"
  789. );
  790. check_feature!(self, features, set_resizable, "window-set-resizable");
  791. check_feature!(self, features, set_title, "window-set-title");
  792. check_feature!(self, features, maximize, "window-maximize");
  793. check_feature!(self, features, unmaximize, "window-unmaximize");
  794. check_feature!(self, features, minimize, "window-minimize");
  795. check_feature!(self, features, unminimize, "window-unminimize");
  796. check_feature!(self, features, show, "window-show");
  797. check_feature!(self, features, hide, "window-hide");
  798. check_feature!(self, features, close, "window-close");
  799. check_feature!(self, features, set_decorations, "window-set-decorations");
  800. check_feature!(
  801. self,
  802. features,
  803. set_always_on_top,
  804. "window-set-always-on-top"
  805. );
  806. check_feature!(self, features, set_size, "window-set-size");
  807. check_feature!(self, features, set_min_size, "window-set-min-size");
  808. check_feature!(self, features, set_max_size, "window-set-max-size");
  809. check_feature!(self, features, set_position, "window-set-position");
  810. check_feature!(self, features, set_fullscreen, "window-set-fullscreen");
  811. check_feature!(self, features, set_focus, "window-set-focus");
  812. check_feature!(self, features, set_icon, "window-set-icon");
  813. check_feature!(self, features, set_skip_taskbar, "window-set-skip-taskbar");
  814. check_feature!(self, features, start_dragging, "window-start-dragging");
  815. check_feature!(self, features, print, "window-print");
  816. features
  817. }
  818. }
  819. }
  820. /// A command allowed to be executed by the webview API.
  821. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  822. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  823. pub struct ShellAllowedCommand {
  824. /// The name for this allowed shell command configuration.
  825. ///
  826. /// This name will be used inside of the webview API to call this command along with
  827. /// any specified arguments.
  828. pub name: String,
  829. /// The command name.
  830. /// It can start with a variable that resolves to a system base directory.
  831. /// The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`,
  832. /// `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`,
  833. /// `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$CWD`.
  834. #[serde(rename = "cmd")]
  835. pub command: PathBuf,
  836. /// The allowed arguments for the command execution.
  837. #[serde(default)]
  838. pub args: ShellAllowedArgs,
  839. /// If this command is a sidecar command.
  840. #[serde(default)]
  841. pub sidecar: bool,
  842. }
  843. /// A set of command arguments allowed to be executed by the webview API.
  844. ///
  845. /// A value of `true` will allow any arguments to be passed to the command. `false` will disable all
  846. /// arguments. A list of [`ShellAllowedArg`] will set those arguments as the only valid arguments to
  847. /// be passed to the attached command configuration.
  848. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  849. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  850. #[serde(untagged, deny_unknown_fields)]
  851. #[non_exhaustive]
  852. pub enum ShellAllowedArgs {
  853. /// Use a simple boolean to allow all or disable all arguments to this command configuration.
  854. Flag(bool),
  855. /// A specific set of [`ShellAllowedArg`] that are valid to call for the command configuration.
  856. List(Vec<ShellAllowedArg>),
  857. }
  858. impl Default for ShellAllowedArgs {
  859. fn default() -> Self {
  860. Self::Flag(false)
  861. }
  862. }
  863. /// A command argument allowed to be executed by the webview API.
  864. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  865. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  866. #[serde(untagged, deny_unknown_fields)]
  867. #[non_exhaustive]
  868. pub enum ShellAllowedArg {
  869. /// A non-configurable argument that is passed to the command in the order it was specified.
  870. Fixed(String),
  871. /// A variable that is set while calling the command from the webview API.
  872. ///
  873. Var {
  874. /// [regex] validator to require passed values to conform to an expected input.
  875. ///
  876. /// This will require the argument value passed to this variable to match the `validator` regex
  877. /// before it will be executed.
  878. ///
  879. /// [regex]: https://docs.rs/regex/latest/regex/#syntax
  880. #[serde(default)]
  881. validator: String,
  882. },
  883. }
  884. /// Shell scope definition.
  885. /// It is a list of command names and associated CLI arguments that restrict the API access from the webview.
  886. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  887. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  888. pub struct ShellAllowlistScope(pub Vec<ShellAllowedCommand>);
  889. /// Defines the `shell > open` api scope.
  890. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  891. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  892. #[serde(untagged, deny_unknown_fields)]
  893. #[non_exhaustive]
  894. pub enum ShellAllowlistOpen {
  895. /// If the shell open API should be enabled.
  896. ///
  897. /// If enabled, the default validation regex (`^https?://`) is used.
  898. Flag(bool),
  899. /// Enable the shell open API, with a custom regex that the opened path must match against.
  900. ///
  901. /// If using a custom regex to support a non-http(s) schema, care should be used to prevent values
  902. /// that allow flag-like strings to pass validation. e.g. `--enable-debugging`, `-i`, `/R`.
  903. Validate(String),
  904. }
  905. impl Default for ShellAllowlistOpen {
  906. fn default() -> Self {
  907. Self::Flag(false)
  908. }
  909. }
  910. /// Allowlist for the shell APIs.
  911. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  912. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  913. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  914. pub struct ShellAllowlistConfig {
  915. /// Access scope for the binary execution APIs.
  916. /// Sidecars are automatically enabled.
  917. #[serde(default)]
  918. pub scope: ShellAllowlistScope,
  919. /// Use this flag to enable all shell API features.
  920. #[serde(default)]
  921. pub all: bool,
  922. /// Enable binary execution.
  923. #[serde(default)]
  924. pub execute: bool,
  925. /// Enable sidecar execution, allowing the JavaScript layer to spawn a sidecar command,
  926. /// an executable that is shipped with the application.
  927. /// For more information see <https://tauri.studio/en/docs/usage/guides/bundler/sidecar>.
  928. #[serde(default)]
  929. pub sidecar: bool,
  930. /// Open URL with the user's default application.
  931. #[serde(default)]
  932. pub open: ShellAllowlistOpen,
  933. }
  934. impl Allowlist for ShellAllowlistConfig {
  935. fn all_features() -> Vec<&'static str> {
  936. let allowlist = Self {
  937. scope: Default::default(),
  938. all: false,
  939. execute: true,
  940. sidecar: true,
  941. open: ShellAllowlistOpen::Flag(true),
  942. };
  943. let mut features = allowlist.to_features();
  944. features.push("shell-all");
  945. features
  946. }
  947. fn to_features(&self) -> Vec<&'static str> {
  948. if self.all {
  949. vec!["shell-all"]
  950. } else {
  951. let mut features = Vec::new();
  952. check_feature!(self, features, execute, "shell-execute");
  953. check_feature!(self, features, sidecar, "shell-sidecar");
  954. if !matches!(self.open, ShellAllowlistOpen::Flag(false)) {
  955. features.push("shell-open")
  956. }
  957. features
  958. }
  959. }
  960. }
  961. /// Allowlist for the dialog APIs.
  962. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  963. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  964. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  965. pub struct DialogAllowlistConfig {
  966. /// Use this flag to enable all dialog API features.
  967. #[serde(default)]
  968. pub all: bool,
  969. /// Allows the API to open a dialog window to pick files.
  970. #[serde(default)]
  971. pub open: bool,
  972. /// Allows the API to open a dialog window to pick where to save files.
  973. #[serde(default)]
  974. pub save: bool,
  975. /// Allows the API to show a message dialog window.
  976. #[serde(default)]
  977. pub message: bool,
  978. /// Allows the API to show a dialog window with Yes/No buttons.
  979. #[serde(default)]
  980. pub ask: bool,
  981. /// Allows the API to show a dialog window with Ok/Cancel buttons.
  982. #[serde(default)]
  983. pub confirm: bool,
  984. }
  985. impl Allowlist for DialogAllowlistConfig {
  986. fn all_features() -> Vec<&'static str> {
  987. let allowlist = Self {
  988. all: false,
  989. open: true,
  990. save: true,
  991. message: true,
  992. ask: true,
  993. confirm: true,
  994. };
  995. let mut features = allowlist.to_features();
  996. features.push("dialog-all");
  997. features
  998. }
  999. fn to_features(&self) -> Vec<&'static str> {
  1000. if self.all {
  1001. vec!["dialog-all"]
  1002. } else {
  1003. let mut features = Vec::new();
  1004. check_feature!(self, features, open, "dialog-open");
  1005. check_feature!(self, features, save, "dialog-save");
  1006. check_feature!(self, features, message, "dialog-message");
  1007. check_feature!(self, features, ask, "dialog-ask");
  1008. check_feature!(self, features, confirm, "dialog-confirm");
  1009. features
  1010. }
  1011. }
  1012. }
  1013. /// HTTP API scope definition.
  1014. /// It is a list of URLs that can be accessed by the webview when using the HTTP APIs.
  1015. /// The URL path is matched against the request URL using a glob pattern.
  1016. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1017. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1018. pub struct HttpAllowlistScope(pub Vec<Url>);
  1019. /// Allowlist for the HTTP APIs.
  1020. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1021. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1022. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1023. pub struct HttpAllowlistConfig {
  1024. /// The access scope for the HTTP APIs.
  1025. #[serde(default)]
  1026. pub scope: HttpAllowlistScope,
  1027. /// Use this flag to enable all HTTP API features.
  1028. #[serde(default)]
  1029. pub all: bool,
  1030. /// Allows making HTTP requests.
  1031. #[serde(default)]
  1032. pub request: bool,
  1033. }
  1034. impl Allowlist for HttpAllowlistConfig {
  1035. fn all_features() -> Vec<&'static str> {
  1036. let allowlist = Self {
  1037. scope: Default::default(),
  1038. all: false,
  1039. request: true,
  1040. };
  1041. let mut features = allowlist.to_features();
  1042. features.push("http-all");
  1043. features
  1044. }
  1045. fn to_features(&self) -> Vec<&'static str> {
  1046. if self.all {
  1047. vec!["http-all"]
  1048. } else {
  1049. let mut features = Vec::new();
  1050. check_feature!(self, features, request, "http-request");
  1051. features
  1052. }
  1053. }
  1054. }
  1055. /// Allowlist for the notification APIs.
  1056. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1057. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1058. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1059. pub struct NotificationAllowlistConfig {
  1060. /// Use this flag to enable all notification API features.
  1061. #[serde(default)]
  1062. pub all: bool,
  1063. }
  1064. impl Allowlist for NotificationAllowlistConfig {
  1065. fn all_features() -> Vec<&'static str> {
  1066. let allowlist = Self { all: false };
  1067. let mut features = allowlist.to_features();
  1068. features.push("notification-all");
  1069. features
  1070. }
  1071. fn to_features(&self) -> Vec<&'static str> {
  1072. if self.all {
  1073. vec!["notification-all"]
  1074. } else {
  1075. vec![]
  1076. }
  1077. }
  1078. }
  1079. /// Allowlist for the global shortcut APIs.
  1080. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1081. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1082. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1083. pub struct GlobalShortcutAllowlistConfig {
  1084. /// Use this flag to enable all global shortcut API features.
  1085. #[serde(default)]
  1086. pub all: bool,
  1087. }
  1088. impl Allowlist for GlobalShortcutAllowlistConfig {
  1089. fn all_features() -> Vec<&'static str> {
  1090. let allowlist = Self { all: false };
  1091. let mut features = allowlist.to_features();
  1092. features.push("global-shortcut-all");
  1093. features
  1094. }
  1095. fn to_features(&self) -> Vec<&'static str> {
  1096. if self.all {
  1097. vec!["global-shortcut-all"]
  1098. } else {
  1099. vec![]
  1100. }
  1101. }
  1102. }
  1103. /// Allowlist for the OS APIs.
  1104. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1105. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1106. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1107. pub struct OsAllowlistConfig {
  1108. /// Use this flag to enable all OS API features.
  1109. #[serde(default)]
  1110. pub all: bool,
  1111. }
  1112. impl Allowlist for OsAllowlistConfig {
  1113. fn all_features() -> Vec<&'static str> {
  1114. let allowlist = Self { all: false };
  1115. let mut features = allowlist.to_features();
  1116. features.push("os-all");
  1117. features
  1118. }
  1119. fn to_features(&self) -> Vec<&'static str> {
  1120. if self.all {
  1121. vec!["os-all"]
  1122. } else {
  1123. vec![]
  1124. }
  1125. }
  1126. }
  1127. /// Allowlist for the path APIs.
  1128. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1129. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1130. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1131. pub struct PathAllowlistConfig {
  1132. /// Use this flag to enable all path API features.
  1133. #[serde(default)]
  1134. pub all: bool,
  1135. }
  1136. impl Allowlist for PathAllowlistConfig {
  1137. fn all_features() -> Vec<&'static str> {
  1138. let allowlist = Self { all: false };
  1139. let mut features = allowlist.to_features();
  1140. features.push("path-all");
  1141. features
  1142. }
  1143. fn to_features(&self) -> Vec<&'static str> {
  1144. if self.all {
  1145. vec!["path-all"]
  1146. } else {
  1147. vec![]
  1148. }
  1149. }
  1150. }
  1151. /// Allowlist for the custom protocols.
  1152. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1153. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1154. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1155. pub struct ProtocolAllowlistConfig {
  1156. /// The access scope for the asset protocol.
  1157. #[serde(default)]
  1158. pub asset_scope: FsAllowlistScope,
  1159. /// Use this flag to enable all custom protocols.
  1160. #[serde(default)]
  1161. pub all: bool,
  1162. /// Enables the asset protocol.
  1163. #[serde(default)]
  1164. pub asset: bool,
  1165. }
  1166. impl Allowlist for ProtocolAllowlistConfig {
  1167. fn all_features() -> Vec<&'static str> {
  1168. let allowlist = Self {
  1169. asset_scope: Default::default(),
  1170. all: false,
  1171. asset: true,
  1172. };
  1173. let mut features = allowlist.to_features();
  1174. features.push("protocol-all");
  1175. features
  1176. }
  1177. fn to_features(&self) -> Vec<&'static str> {
  1178. if self.all {
  1179. vec!["protocol-all"]
  1180. } else {
  1181. let mut features = Vec::new();
  1182. check_feature!(self, features, asset, "protocol-asset");
  1183. features
  1184. }
  1185. }
  1186. }
  1187. /// Allowlist for the process APIs.
  1188. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1189. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1190. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1191. pub struct ProcessAllowlistConfig {
  1192. /// Use this flag to enable all process APIs.
  1193. #[serde(default)]
  1194. pub all: bool,
  1195. /// Enables the relaunch API.
  1196. #[serde(default)]
  1197. pub relaunch: bool,
  1198. /// Dangerous option that allows macOS to relaunch even if the binary contains a symlink.
  1199. ///
  1200. /// This is due to macOS having less symlink protection. Highly recommended to not set this flag
  1201. /// unless you have a very specific reason too, and understand the implications of it.
  1202. #[serde(default)]
  1203. pub relaunch_dangerous_allow_symlink_macos: bool,
  1204. /// Enables the exit API.
  1205. #[serde(default)]
  1206. pub exit: bool,
  1207. }
  1208. impl Allowlist for ProcessAllowlistConfig {
  1209. fn all_features() -> Vec<&'static str> {
  1210. let allowlist = Self {
  1211. all: false,
  1212. relaunch: true,
  1213. relaunch_dangerous_allow_symlink_macos: false,
  1214. exit: true,
  1215. };
  1216. let mut features = allowlist.to_features();
  1217. features.push("process-all");
  1218. features
  1219. }
  1220. fn to_features(&self) -> Vec<&'static str> {
  1221. if self.all {
  1222. vec!["process-all"]
  1223. } else {
  1224. let mut features = Vec::new();
  1225. check_feature!(self, features, relaunch, "process-relaunch");
  1226. check_feature!(
  1227. self,
  1228. features,
  1229. relaunch_dangerous_allow_symlink_macos,
  1230. "process-relaunch-dangerous-allow-symlink-macos"
  1231. );
  1232. check_feature!(self, features, exit, "process-exit");
  1233. features
  1234. }
  1235. }
  1236. }
  1237. /// Allowlist for the clipboard APIs.
  1238. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1239. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1240. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1241. pub struct ClipboardAllowlistConfig {
  1242. /// Use this flag to enable all clipboard APIs.
  1243. #[serde(default)]
  1244. pub all: bool,
  1245. /// Enables the clipboard's `writeText` API.
  1246. #[serde(default)]
  1247. pub write_text: bool,
  1248. /// Enables the clipboard's `readText` API.
  1249. #[serde(default)]
  1250. pub read_text: bool,
  1251. }
  1252. impl Allowlist for ClipboardAllowlistConfig {
  1253. fn all_features() -> Vec<&'static str> {
  1254. let allowlist = Self {
  1255. all: false,
  1256. write_text: true,
  1257. read_text: true,
  1258. };
  1259. let mut features = allowlist.to_features();
  1260. features.push("clipboard-all");
  1261. features
  1262. }
  1263. fn to_features(&self) -> Vec<&'static str> {
  1264. if self.all {
  1265. vec!["clipboard-all"]
  1266. } else {
  1267. let mut features = Vec::new();
  1268. check_feature!(self, features, write_text, "clipboard-write-text");
  1269. check_feature!(self, features, read_text, "clipboard-read-text");
  1270. features
  1271. }
  1272. }
  1273. }
  1274. /// Allowlist configuration.
  1275. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1276. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1277. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1278. pub struct AllowlistConfig {
  1279. /// Use this flag to enable all API features.
  1280. #[serde(default)]
  1281. pub all: bool,
  1282. /// File system API allowlist.
  1283. #[serde(default)]
  1284. pub fs: FsAllowlistConfig,
  1285. /// Window API allowlist.
  1286. #[serde(default)]
  1287. pub window: WindowAllowlistConfig,
  1288. /// Shell API allowlist.
  1289. #[serde(default)]
  1290. pub shell: ShellAllowlistConfig,
  1291. /// Dialog API allowlist.
  1292. #[serde(default)]
  1293. pub dialog: DialogAllowlistConfig,
  1294. /// HTTP API allowlist.
  1295. #[serde(default)]
  1296. pub http: HttpAllowlistConfig,
  1297. /// Notification API allowlist.
  1298. #[serde(default)]
  1299. pub notification: NotificationAllowlistConfig,
  1300. /// Global shortcut API allowlist.
  1301. #[serde(default)]
  1302. pub global_shortcut: GlobalShortcutAllowlistConfig,
  1303. /// OS allowlist.
  1304. #[serde(default)]
  1305. pub os: OsAllowlistConfig,
  1306. /// Path API allowlist.
  1307. #[serde(default)]
  1308. pub path: PathAllowlistConfig,
  1309. /// Custom protocol allowlist.
  1310. #[serde(default)]
  1311. pub protocol: ProtocolAllowlistConfig,
  1312. /// Process API allowlist.
  1313. #[serde(default)]
  1314. pub process: ProcessAllowlistConfig,
  1315. /// Clipboard APIs allowlist.
  1316. #[serde(default)]
  1317. pub clipboard: ClipboardAllowlistConfig,
  1318. }
  1319. impl Allowlist for AllowlistConfig {
  1320. fn all_features() -> Vec<&'static str> {
  1321. let mut features = vec!["api-all"];
  1322. features.extend(FsAllowlistConfig::all_features());
  1323. features.extend(WindowAllowlistConfig::all_features());
  1324. features.extend(ShellAllowlistConfig::all_features());
  1325. features.extend(DialogAllowlistConfig::all_features());
  1326. features.extend(HttpAllowlistConfig::all_features());
  1327. features.extend(NotificationAllowlistConfig::all_features());
  1328. features.extend(GlobalShortcutAllowlistConfig::all_features());
  1329. features.extend(OsAllowlistConfig::all_features());
  1330. features.extend(PathAllowlistConfig::all_features());
  1331. features.extend(ProtocolAllowlistConfig::all_features());
  1332. features.extend(ProcessAllowlistConfig::all_features());
  1333. features.extend(ClipboardAllowlistConfig::all_features());
  1334. features
  1335. }
  1336. fn to_features(&self) -> Vec<&'static str> {
  1337. if self.all {
  1338. vec!["api-all"]
  1339. } else {
  1340. let mut features = Vec::new();
  1341. features.extend(self.fs.to_features());
  1342. features.extend(self.window.to_features());
  1343. features.extend(self.shell.to_features());
  1344. features.extend(self.dialog.to_features());
  1345. features.extend(self.http.to_features());
  1346. features.extend(self.notification.to_features());
  1347. features.extend(self.global_shortcut.to_features());
  1348. features.extend(self.os.to_features());
  1349. features.extend(self.path.to_features());
  1350. features.extend(self.protocol.to_features());
  1351. features.extend(self.process.to_features());
  1352. features.extend(self.clipboard.to_features());
  1353. features
  1354. }
  1355. }
  1356. }
  1357. /// The application pattern.
  1358. #[skip_serializing_none]
  1359. #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
  1360. #[serde(rename_all = "lowercase", tag = "use", content = "options")]
  1361. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1362. pub enum PatternKind {
  1363. /// Brownfield pattern.
  1364. Brownfield,
  1365. /// Isolation pattern. Recommended for security purposes.
  1366. #[cfg(feature = "isolation")]
  1367. Isolation {
  1368. /// The dir containing the index.html file that contains the secure isolation application.
  1369. dir: PathBuf,
  1370. },
  1371. }
  1372. impl Default for PatternKind {
  1373. fn default() -> Self {
  1374. Self::Brownfield
  1375. }
  1376. }
  1377. /// The Tauri configuration object.
  1378. #[skip_serializing_none]
  1379. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  1380. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1381. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1382. pub struct TauriConfig {
  1383. /// The pattern to use.
  1384. #[serde(default)]
  1385. pub pattern: PatternKind,
  1386. /// The windows configuration.
  1387. #[serde(default)]
  1388. pub windows: Vec<WindowConfig>,
  1389. /// The CLI configuration.
  1390. pub cli: Option<CliConfig>,
  1391. /// The bundler configuration.
  1392. #[serde(default)]
  1393. pub bundle: BundleConfig,
  1394. /// The allowlist configuration.
  1395. #[serde(default)]
  1396. pub allowlist: AllowlistConfig,
  1397. /// Security configuration.
  1398. #[serde(default)]
  1399. pub security: SecurityConfig,
  1400. /// The updater configuration.
  1401. #[serde(default)]
  1402. pub updater: UpdaterConfig,
  1403. /// Configuration for app system tray.
  1404. pub system_tray: Option<SystemTrayConfig>,
  1405. /// MacOS private API configuration. Enables the transparent background API and sets the `fullScreenEnabled` preference to `true`.
  1406. #[serde(rename = "macOSPrivateApi", default)]
  1407. pub macos_private_api: bool,
  1408. }
  1409. impl Default for TauriConfig {
  1410. fn default() -> Self {
  1411. Self {
  1412. pattern: Default::default(),
  1413. windows: Default::default(),
  1414. cli: None,
  1415. bundle: BundleConfig::default(),
  1416. allowlist: AllowlistConfig::default(),
  1417. security: SecurityConfig::default(),
  1418. updater: UpdaterConfig::default(),
  1419. system_tray: None,
  1420. macos_private_api: false,
  1421. }
  1422. }
  1423. }
  1424. impl TauriConfig {
  1425. /// Returns all Cargo features.
  1426. #[allow(dead_code)]
  1427. pub fn all_features() -> Vec<&'static str> {
  1428. let mut features = AllowlistConfig::all_features();
  1429. features.extend(vec![
  1430. "cli",
  1431. "updater",
  1432. "system-tray",
  1433. "macos-private-api",
  1434. "isolation",
  1435. ]);
  1436. features
  1437. }
  1438. /// Returns the enabled Cargo features.
  1439. #[allow(dead_code)]
  1440. pub fn features(&self) -> Vec<&str> {
  1441. let mut features = self.allowlist.to_features();
  1442. if self.cli.is_some() {
  1443. features.push("cli");
  1444. }
  1445. if self.updater.active {
  1446. features.push("updater");
  1447. }
  1448. if self.system_tray.is_some() {
  1449. features.push("system-tray");
  1450. }
  1451. if self.macos_private_api {
  1452. features.push("macos-private-api");
  1453. }
  1454. #[cfg(feature = "isolation")]
  1455. if let PatternKind::Isolation { .. } = self.pattern {
  1456. features.push("isolation");
  1457. }
  1458. features.sort_unstable();
  1459. features
  1460. }
  1461. }
  1462. /// A URL to an updater server.
  1463. ///
  1464. /// The URL must use the `https` scheme on production.
  1465. #[skip_serializing_none]
  1466. #[derive(Debug, PartialEq, Clone, Serialize)]
  1467. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1468. pub struct UpdaterEndpoint(pub Url);
  1469. impl std::fmt::Display for UpdaterEndpoint {
  1470. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  1471. write!(f, "{}", self.0)
  1472. }
  1473. }
  1474. impl<'de> Deserialize<'de> for UpdaterEndpoint {
  1475. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  1476. where
  1477. D: Deserializer<'de>,
  1478. {
  1479. let url = Url::deserialize(deserializer)?;
  1480. #[cfg(all(not(debug_assertions), not(feature = "schema")))]
  1481. {
  1482. if url.scheme() != "https" {
  1483. return Err(serde::de::Error::custom(
  1484. "The configured updater endpoint must use the `https` protocol.",
  1485. ));
  1486. }
  1487. }
  1488. Ok(Self(url))
  1489. }
  1490. }
  1491. /// The Updater configuration object.
  1492. #[skip_serializing_none]
  1493. #[derive(Debug, PartialEq, Clone, Serialize)]
  1494. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1495. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1496. pub struct UpdaterConfig {
  1497. /// Whether the updater is active or not.
  1498. #[serde(default)]
  1499. pub active: bool,
  1500. /// Display built-in dialog or use event system if disabled.
  1501. #[serde(default = "default_dialog")]
  1502. pub dialog: bool,
  1503. /// The updater endpoints. TLS is enforced on production.
  1504. pub endpoints: Option<Vec<UpdaterEndpoint>>,
  1505. /// Signature public key.
  1506. #[serde(default)] // use default just so the schema doesn't flag it as required
  1507. pub pubkey: String,
  1508. }
  1509. impl<'de> Deserialize<'de> for UpdaterConfig {
  1510. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  1511. where
  1512. D: Deserializer<'de>,
  1513. {
  1514. #[derive(Deserialize)]
  1515. struct InnerUpdaterConfig {
  1516. #[serde(default)]
  1517. active: bool,
  1518. #[serde(default = "default_dialog")]
  1519. dialog: bool,
  1520. endpoints: Option<Vec<UpdaterEndpoint>>,
  1521. pubkey: Option<String>,
  1522. }
  1523. let config = InnerUpdaterConfig::deserialize(deserializer)?;
  1524. if config.active && config.pubkey.is_none() {
  1525. return Err(DeError::custom(
  1526. "The updater `pubkey` configuration is required.",
  1527. ));
  1528. }
  1529. Ok(UpdaterConfig {
  1530. active: config.active,
  1531. dialog: config.dialog,
  1532. endpoints: config.endpoints,
  1533. pubkey: config.pubkey.unwrap_or_default(),
  1534. })
  1535. }
  1536. }
  1537. impl Default for UpdaterConfig {
  1538. fn default() -> Self {
  1539. Self {
  1540. active: false,
  1541. dialog: default_dialog(),
  1542. endpoints: None,
  1543. pubkey: "".into(),
  1544. }
  1545. }
  1546. }
  1547. /// Configuration for application system tray icon.
  1548. #[skip_serializing_none]
  1549. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1550. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1551. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1552. pub struct SystemTrayConfig {
  1553. /// Path to the icon to use on the system tray.
  1554. ///
  1555. /// It is forced to be a `.png` file on Linux and macOS, and a `.ico` file on Windows.
  1556. pub icon_path: PathBuf,
  1557. /// 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.
  1558. #[serde(default)]
  1559. pub icon_as_template: bool,
  1560. }
  1561. // We enable the unnecessary_wraps because we need
  1562. // to use an Option for dialog otherwise the CLI schema will mark
  1563. // the dialog as a required field which is not as we default it to true.
  1564. fn default_dialog() -> bool {
  1565. true
  1566. }
  1567. /// The `dev_path` and `dist_dir` options.
  1568. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  1569. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1570. #[serde(untagged, deny_unknown_fields)]
  1571. #[non_exhaustive]
  1572. pub enum AppUrl {
  1573. /// The app's external URL, or the path to the directory containing the app assets.
  1574. Url(WindowUrl),
  1575. /// An array of files to embed on the app.
  1576. Files(Vec<PathBuf>),
  1577. }
  1578. impl std::fmt::Display for AppUrl {
  1579. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  1580. match self {
  1581. Self::Url(url) => write!(f, "{}", url),
  1582. Self::Files(files) => write!(f, "{}", serde_json::to_string(files).unwrap()),
  1583. }
  1584. }
  1585. }
  1586. /// The Build configuration object.
  1587. #[skip_serializing_none]
  1588. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
  1589. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1590. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1591. pub struct BuildConfig {
  1592. /// The binary used to build and run the application.
  1593. pub runner: Option<String>,
  1594. /// The path or URL to use on development.
  1595. #[serde(default = "default_dev_path")]
  1596. pub dev_path: AppUrl,
  1597. /// The path to the app's dist dir. This path must contain your index.html file.
  1598. #[serde(default = "default_dist_dir")]
  1599. pub dist_dir: AppUrl,
  1600. /// A shell command to run before `tauri dev` kicks in.
  1601. ///
  1602. /// 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.
  1603. pub before_dev_command: Option<String>,
  1604. /// A shell command to run before `tauri build` kicks in.
  1605. ///
  1606. /// 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.
  1607. pub before_build_command: Option<String>,
  1608. /// Features passed to `cargo` commands.
  1609. pub features: Option<Vec<String>>,
  1610. /// Whether we should inject the Tauri API on `window.__TAURI__` or not.
  1611. #[serde(default)]
  1612. pub with_global_tauri: bool,
  1613. }
  1614. impl Default for BuildConfig {
  1615. fn default() -> Self {
  1616. Self {
  1617. runner: None,
  1618. dev_path: default_dev_path(),
  1619. dist_dir: default_dist_dir(),
  1620. before_dev_command: None,
  1621. before_build_command: None,
  1622. features: None,
  1623. with_global_tauri: false,
  1624. }
  1625. }
  1626. }
  1627. fn default_dev_path() -> AppUrl {
  1628. AppUrl::Url(WindowUrl::External(
  1629. Url::parse("http://localhost:8080").unwrap(),
  1630. ))
  1631. }
  1632. fn default_dist_dir() -> AppUrl {
  1633. AppUrl::Url(WindowUrl::App("../dist".into()))
  1634. }
  1635. #[derive(Debug, PartialEq)]
  1636. struct PackageVersion(String);
  1637. impl<'d> serde::Deserialize<'d> for PackageVersion {
  1638. fn deserialize<D: Deserializer<'d>>(deserializer: D) -> Result<PackageVersion, D::Error> {
  1639. struct PackageVersionVisitor;
  1640. impl<'d> Visitor<'d> for PackageVersionVisitor {
  1641. type Value = PackageVersion;
  1642. fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
  1643. write!(
  1644. formatter,
  1645. "a semver string or a path to a package.json file"
  1646. )
  1647. }
  1648. fn visit_str<E: DeError>(self, value: &str) -> Result<PackageVersion, E> {
  1649. let path = PathBuf::from(value);
  1650. if path.exists() {
  1651. let json_str = read_to_string(&path)
  1652. .map_err(|e| DeError::custom(format!("failed to read version JSON file: {}", e)))?;
  1653. let package_json: serde_json::Value = serde_json::from_str(&json_str)
  1654. .map_err(|e| DeError::custom(format!("failed to read version JSON file: {}", e)))?;
  1655. if let Some(obj) = package_json.as_object() {
  1656. let version = obj
  1657. .get("version")
  1658. .ok_or_else(|| DeError::custom("JSON must contain a `version` field"))?
  1659. .as_str()
  1660. .ok_or_else(|| DeError::custom("`version` must be a string"))?;
  1661. Ok(PackageVersion(version.into()))
  1662. } else {
  1663. Err(DeError::custom("value is not a path to a JSON object"))
  1664. }
  1665. } else {
  1666. Ok(PackageVersion(value.into()))
  1667. }
  1668. }
  1669. }
  1670. deserializer.deserialize_string(PackageVersionVisitor {})
  1671. }
  1672. }
  1673. /// The package configuration.
  1674. #[derive(Debug, Clone, Default, PartialEq, Deserialize, Serialize)]
  1675. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1676. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1677. pub struct PackageConfig {
  1678. /// App name.
  1679. pub product_name: Option<String>,
  1680. /// App version. It is a semver version number or a path to a `package.json` file contaning the `version` field.
  1681. #[serde(deserialize_with = "version_deserializer", default)]
  1682. pub version: Option<String>,
  1683. }
  1684. fn version_deserializer<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
  1685. where
  1686. D: Deserializer<'de>,
  1687. {
  1688. Option::<PackageVersion>::deserialize(deserializer).map(|v| v.map(|v| v.0))
  1689. }
  1690. impl PackageConfig {
  1691. /// The binary name.
  1692. #[allow(dead_code)]
  1693. pub fn binary_name(&self) -> Option<String> {
  1694. #[cfg(target_os = "linux")]
  1695. {
  1696. self.product_name.as_ref().map(|n| n.to_kebab_case())
  1697. }
  1698. #[cfg(not(target_os = "linux"))]
  1699. {
  1700. self.product_name.clone()
  1701. }
  1702. }
  1703. }
  1704. /// The config type mapped to `tauri.conf.json`.
  1705. #[skip_serializing_none]
  1706. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
  1707. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1708. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  1709. pub struct Config {
  1710. /// Package settings.
  1711. #[serde(default)]
  1712. pub package: PackageConfig,
  1713. /// The Tauri configuration.
  1714. #[serde(default)]
  1715. pub tauri: TauriConfig,
  1716. /// The build configuration.
  1717. #[serde(default = "default_build")]
  1718. pub build: BuildConfig,
  1719. /// The plugins config.
  1720. #[serde(default)]
  1721. pub plugins: PluginConfig,
  1722. }
  1723. /// The plugin configs holds a HashMap mapping a plugin name to its configuration object.
  1724. #[derive(Debug, Clone, Default, PartialEq, Deserialize, Serialize)]
  1725. #[cfg_attr(feature = "schema", derive(JsonSchema))]
  1726. pub struct PluginConfig(pub HashMap<String, JsonValue>);
  1727. fn default_build() -> BuildConfig {
  1728. BuildConfig {
  1729. runner: None,
  1730. dev_path: default_dev_path(),
  1731. dist_dir: default_dist_dir(),
  1732. before_dev_command: None,
  1733. before_build_command: None,
  1734. features: None,
  1735. with_global_tauri: false,
  1736. }
  1737. }
  1738. /// Implement `ToTokens` for all config structs, allowing a literal `Config` to be built.
  1739. ///
  1740. /// This allows for a build script to output the values in a `Config` to a `TokenStream`, which can
  1741. /// then be consumed by another crate. Useful for passing a config to both the build script and the
  1742. /// application using tauri while only parsing it once (in the build script).
  1743. #[cfg(feature = "build")]
  1744. mod build {
  1745. use std::{convert::identity, path::Path};
  1746. use proc_macro2::TokenStream;
  1747. use quote::{quote, ToTokens, TokenStreamExt};
  1748. use super::*;
  1749. use serde_json::Value as JsonValue;
  1750. /// Create a `String` constructor `TokenStream`.
  1751. ///
  1752. /// e.g. `"Hello World" -> String::from("Hello World").
  1753. /// This takes a `&String` to reduce casting all the `&String` -> `&str` manually.
  1754. fn str_lit(s: impl AsRef<str>) -> TokenStream {
  1755. let s = s.as_ref();
  1756. quote! { #s.into() }
  1757. }
  1758. /// Create an `Option` constructor `TokenStream`.
  1759. fn opt_lit(item: Option<&impl ToTokens>) -> TokenStream {
  1760. match item {
  1761. None => quote! { ::core::option::Option::None },
  1762. Some(item) => quote! { ::core::option::Option::Some(#item) },
  1763. }
  1764. }
  1765. /// Helper function to combine an `opt_lit` with `str_lit`.
  1766. fn opt_str_lit(item: Option<impl AsRef<str>>) -> TokenStream {
  1767. opt_lit(item.map(str_lit).as_ref())
  1768. }
  1769. /// Helper function to combine an `opt_lit` with a list of `str_lit`
  1770. fn opt_vec_str_lit(item: Option<impl IntoIterator<Item = impl AsRef<str>>>) -> TokenStream {
  1771. opt_lit(item.map(|list| vec_lit(list, str_lit)).as_ref())
  1772. }
  1773. /// Create a `Vec` constructor, mapping items with a function that spits out `TokenStream`s.
  1774. fn vec_lit<Raw, Tokens>(
  1775. list: impl IntoIterator<Item = Raw>,
  1776. map: impl Fn(Raw) -> Tokens,
  1777. ) -> TokenStream
  1778. where
  1779. Tokens: ToTokens,
  1780. {
  1781. let items = list.into_iter().map(map);
  1782. quote! { vec![#(#items),*] }
  1783. }
  1784. /// Create a `PathBuf` constructor `TokenStream`.
  1785. ///
  1786. /// e.g. `"Hello World" -> String::from("Hello World").
  1787. fn path_buf_lit(s: impl AsRef<Path>) -> TokenStream {
  1788. let s = s.as_ref().to_string_lossy().into_owned();
  1789. quote! { ::std::path::PathBuf::from(#s) }
  1790. }
  1791. /// Creates a `Url` constructor `TokenStream`.
  1792. fn url_lit(url: &Url) -> TokenStream {
  1793. let url = url.as_str();
  1794. quote! { #url.parse().unwrap() }
  1795. }
  1796. /// Create a map constructor, mapping keys and values with other `TokenStream`s.
  1797. ///
  1798. /// This function is pretty generic because the types of keys AND values get transformed.
  1799. fn map_lit<Map, Key, Value, TokenStreamKey, TokenStreamValue, FuncKey, FuncValue>(
  1800. map_type: TokenStream,
  1801. map: Map,
  1802. map_key: FuncKey,
  1803. map_value: FuncValue,
  1804. ) -> TokenStream
  1805. where
  1806. <Map as IntoIterator>::IntoIter: ExactSizeIterator,
  1807. Map: IntoIterator<Item = (Key, Value)>,
  1808. TokenStreamKey: ToTokens,
  1809. TokenStreamValue: ToTokens,
  1810. FuncKey: Fn(Key) -> TokenStreamKey,
  1811. FuncValue: Fn(Value) -> TokenStreamValue,
  1812. {
  1813. let ident = quote::format_ident!("map");
  1814. let map = map.into_iter();
  1815. if map.len() > 0 {
  1816. let items = map.map(|(key, value)| {
  1817. let key = map_key(key);
  1818. let value = map_value(value);
  1819. quote! { #ident.insert(#key, #value); }
  1820. });
  1821. quote! {{
  1822. let mut #ident = #map_type::new();
  1823. #(#items)*
  1824. #ident
  1825. }}
  1826. } else {
  1827. quote! { #map_type::new() }
  1828. }
  1829. }
  1830. /// Create a `serde_json::Value` variant `TokenStream` for a number
  1831. fn json_value_number_lit(num: &serde_json::Number) -> TokenStream {
  1832. // See https://docs.rs/serde_json/1/serde_json/struct.Number.html for guarantees
  1833. let prefix = quote! { ::serde_json::Value };
  1834. if num.is_u64() {
  1835. // guaranteed u64
  1836. let num = num.as_u64().unwrap();
  1837. quote! { #prefix::Number(#num.into()) }
  1838. } else if num.is_i64() {
  1839. // guaranteed i64
  1840. let num = num.as_i64().unwrap();
  1841. quote! { #prefix::Number(#num.into()) }
  1842. } else if num.is_f64() {
  1843. // guaranteed f64
  1844. let num = num.as_f64().unwrap();
  1845. quote! { #prefix::Number(#num.into()) }
  1846. } else {
  1847. // invalid number
  1848. quote! { #prefix::Null }
  1849. }
  1850. }
  1851. /// Create a `serde_json::Value` constructor `TokenStream`
  1852. fn json_value_lit(jv: &JsonValue) -> TokenStream {
  1853. let prefix = quote! { ::serde_json::Value };
  1854. match jv {
  1855. JsonValue::Null => quote! { #prefix::Null },
  1856. JsonValue::Bool(bool) => quote! { #prefix::Bool(#bool) },
  1857. JsonValue::Number(number) => json_value_number_lit(number),
  1858. JsonValue::String(str) => {
  1859. let s = str_lit(str);
  1860. quote! { #prefix::String(#s) }
  1861. }
  1862. JsonValue::Array(vec) => {
  1863. let items = vec.iter().map(json_value_lit);
  1864. quote! { #prefix::Array(vec![#(#items),*]) }
  1865. }
  1866. JsonValue::Object(map) => {
  1867. let map = map_lit(quote! { ::serde_json::Map }, map, str_lit, json_value_lit);
  1868. quote! { #prefix::Object(#map) }
  1869. }
  1870. }
  1871. }
  1872. /// Write a `TokenStream` of the `$struct`'s fields to the `$tokens`.
  1873. ///
  1874. /// All fields must represent a binding of the same name that implements `ToTokens`.
  1875. macro_rules! literal_struct {
  1876. ($tokens:ident, $struct:ident, $($field:ident),+) => {
  1877. $tokens.append_all(quote! {
  1878. ::tauri::utils::config::$struct {
  1879. $($field: #$field),+
  1880. }
  1881. });
  1882. };
  1883. }
  1884. impl ToTokens for WindowUrl {
  1885. fn to_tokens(&self, tokens: &mut TokenStream) {
  1886. let prefix = quote! { ::tauri::utils::config::WindowUrl };
  1887. tokens.append_all(match self {
  1888. Self::App(path) => {
  1889. let path = path_buf_lit(&path);
  1890. quote! { #prefix::App(#path) }
  1891. }
  1892. Self::External(url) => {
  1893. let url = url_lit(url);
  1894. quote! { #prefix::External(#url) }
  1895. }
  1896. })
  1897. }
  1898. }
  1899. impl ToTokens for WindowConfig {
  1900. fn to_tokens(&self, tokens: &mut TokenStream) {
  1901. let label = str_lit(&self.label);
  1902. let url = &self.url;
  1903. let file_drop_enabled = self.file_drop_enabled;
  1904. let center = self.center;
  1905. let x = opt_lit(self.x.as_ref());
  1906. let y = opt_lit(self.y.as_ref());
  1907. let width = self.width;
  1908. let height = self.height;
  1909. let min_width = opt_lit(self.min_width.as_ref());
  1910. let min_height = opt_lit(self.min_height.as_ref());
  1911. let max_width = opt_lit(self.max_width.as_ref());
  1912. let max_height = opt_lit(self.max_height.as_ref());
  1913. let resizable = self.resizable;
  1914. let title = str_lit(&self.title);
  1915. let fullscreen = self.fullscreen;
  1916. let focus = self.focus;
  1917. let transparent = self.transparent;
  1918. let maximized = self.maximized;
  1919. let visible = self.visible;
  1920. let decorations = self.decorations;
  1921. let always_on_top = self.always_on_top;
  1922. let skip_taskbar = self.skip_taskbar;
  1923. literal_struct!(
  1924. tokens,
  1925. WindowConfig,
  1926. label,
  1927. url,
  1928. file_drop_enabled,
  1929. center,
  1930. x,
  1931. y,
  1932. width,
  1933. height,
  1934. min_width,
  1935. min_height,
  1936. max_width,
  1937. max_height,
  1938. resizable,
  1939. title,
  1940. fullscreen,
  1941. focus,
  1942. transparent,
  1943. maximized,
  1944. visible,
  1945. decorations,
  1946. always_on_top,
  1947. skip_taskbar
  1948. );
  1949. }
  1950. }
  1951. impl ToTokens for CliArg {
  1952. fn to_tokens(&self, tokens: &mut TokenStream) {
  1953. let short = opt_lit(self.short.as_ref());
  1954. let name = str_lit(&self.name);
  1955. let description = opt_str_lit(self.description.as_ref());
  1956. let long_description = opt_str_lit(self.long_description.as_ref());
  1957. let takes_value = opt_lit(self.takes_value.as_ref());
  1958. let multiple = opt_lit(self.multiple.as_ref());
  1959. let multiple_occurrences = opt_lit(self.multiple_occurrences.as_ref());
  1960. let number_of_values = opt_lit(self.number_of_values.as_ref());
  1961. let possible_values = opt_vec_str_lit(self.possible_values.as_ref());
  1962. let min_values = opt_lit(self.min_values.as_ref());
  1963. let max_values = opt_lit(self.max_values.as_ref());
  1964. let required = opt_lit(self.required.as_ref());
  1965. let required_unless_present = opt_str_lit(self.required_unless_present.as_ref());
  1966. let required_unless_present_all = opt_vec_str_lit(self.required_unless_present_all.as_ref());
  1967. let required_unless_present_any = opt_vec_str_lit(self.required_unless_present_any.as_ref());
  1968. let conflicts_with = opt_str_lit(self.conflicts_with.as_ref());
  1969. let conflicts_with_all = opt_vec_str_lit(self.conflicts_with_all.as_ref());
  1970. let requires = opt_str_lit(self.requires.as_ref());
  1971. let requires_all = opt_vec_str_lit(self.requires_all.as_ref());
  1972. let requires_if = opt_vec_str_lit(self.requires_if.as_ref());
  1973. let required_if_eq = opt_vec_str_lit(self.required_if_eq.as_ref());
  1974. let require_equals = opt_lit(self.require_equals.as_ref());
  1975. let index = opt_lit(self.index.as_ref());
  1976. literal_struct!(
  1977. tokens,
  1978. CliArg,
  1979. short,
  1980. name,
  1981. description,
  1982. long_description,
  1983. takes_value,
  1984. multiple,
  1985. multiple_occurrences,
  1986. number_of_values,
  1987. possible_values,
  1988. min_values,
  1989. max_values,
  1990. required,
  1991. required_unless_present,
  1992. required_unless_present_all,
  1993. required_unless_present_any,
  1994. conflicts_with,
  1995. conflicts_with_all,
  1996. requires,
  1997. requires_all,
  1998. requires_if,
  1999. required_if_eq,
  2000. require_equals,
  2001. index
  2002. );
  2003. }
  2004. }
  2005. impl ToTokens for CliConfig {
  2006. fn to_tokens(&self, tokens: &mut TokenStream) {
  2007. let description = opt_str_lit(self.description.as_ref());
  2008. let long_description = opt_str_lit(self.long_description.as_ref());
  2009. let before_help = opt_str_lit(self.before_help.as_ref());
  2010. let after_help = opt_str_lit(self.after_help.as_ref());
  2011. let args = {
  2012. let args = self.args.as_ref().map(|args| {
  2013. let arg = args.iter().map(|a| quote! { #a });
  2014. quote! { vec![#(#arg),*] }
  2015. });
  2016. opt_lit(args.as_ref())
  2017. };
  2018. let subcommands = opt_lit(
  2019. self
  2020. .subcommands
  2021. .as_ref()
  2022. .map(|map| {
  2023. map_lit(
  2024. quote! { ::std::collections::HashMap },
  2025. map,
  2026. str_lit,
  2027. identity,
  2028. )
  2029. })
  2030. .as_ref(),
  2031. );
  2032. literal_struct!(
  2033. tokens,
  2034. CliConfig,
  2035. description,
  2036. long_description,
  2037. before_help,
  2038. after_help,
  2039. args,
  2040. subcommands
  2041. );
  2042. }
  2043. }
  2044. impl ToTokens for PatternKind {
  2045. fn to_tokens(&self, tokens: &mut TokenStream) {
  2046. let prefix = quote! { ::tauri::utils::config::PatternKind };
  2047. tokens.append_all(match self {
  2048. Self::Brownfield => quote! { #prefix::Brownfield },
  2049. #[cfg(feature = "isolation")]
  2050. Self::Isolation { dir } => {
  2051. let dir = path_buf_lit(dir);
  2052. quote! { #prefix::Isolation { dir: #dir } }
  2053. }
  2054. })
  2055. }
  2056. }
  2057. impl ToTokens for WindowsConfig {
  2058. fn to_tokens(&self, tokens: &mut TokenStream) {
  2059. let webview_fixed_runtime_path = opt_lit(
  2060. self
  2061. .webview_fixed_runtime_path
  2062. .as_ref()
  2063. .map(path_buf_lit)
  2064. .as_ref(),
  2065. );
  2066. tokens.append_all(quote! { ::tauri::utils::config::WindowsConfig {
  2067. webview_fixed_runtime_path: #webview_fixed_runtime_path,
  2068. ..Default::default()
  2069. }})
  2070. }
  2071. }
  2072. impl ToTokens for BundleConfig {
  2073. fn to_tokens(&self, tokens: &mut TokenStream) {
  2074. let identifier = str_lit(&self.identifier);
  2075. let icon = vec_lit(&self.icon, str_lit);
  2076. let active = self.active;
  2077. let targets = quote!(None);
  2078. let resources = quote!(None);
  2079. let copyright = quote!(None);
  2080. let category = quote!(None);
  2081. let short_description = quote!(None);
  2082. let long_description = quote!(None);
  2083. let deb = quote!(Default::default());
  2084. let macos = quote!(Default::default());
  2085. let external_bin = opt_vec_str_lit(self.external_bin.as_ref());
  2086. let windows = &self.windows;
  2087. literal_struct!(
  2088. tokens,
  2089. BundleConfig,
  2090. active,
  2091. identifier,
  2092. icon,
  2093. targets,
  2094. resources,
  2095. copyright,
  2096. category,
  2097. short_description,
  2098. long_description,
  2099. deb,
  2100. macos,
  2101. external_bin,
  2102. windows
  2103. );
  2104. }
  2105. }
  2106. impl ToTokens for AppUrl {
  2107. fn to_tokens(&self, tokens: &mut TokenStream) {
  2108. let prefix = quote! { ::tauri::utils::config::AppUrl };
  2109. tokens.append_all(match self {
  2110. Self::Url(url) => {
  2111. quote! { #prefix::Url(#url) }
  2112. }
  2113. Self::Files(files) => {
  2114. let files = vec_lit(files, path_buf_lit);
  2115. quote! { #prefix::Files(#files) }
  2116. }
  2117. })
  2118. }
  2119. }
  2120. impl ToTokens for BuildConfig {
  2121. fn to_tokens(&self, tokens: &mut TokenStream) {
  2122. let dev_path = &self.dev_path;
  2123. let dist_dir = &self.dist_dir;
  2124. let with_global_tauri = self.with_global_tauri;
  2125. let runner = quote!(None);
  2126. let before_dev_command = quote!(None);
  2127. let before_build_command = quote!(None);
  2128. let features = quote!(None);
  2129. literal_struct!(
  2130. tokens,
  2131. BuildConfig,
  2132. runner,
  2133. dev_path,
  2134. dist_dir,
  2135. with_global_tauri,
  2136. before_dev_command,
  2137. before_build_command,
  2138. features
  2139. );
  2140. }
  2141. }
  2142. impl ToTokens for UpdaterConfig {
  2143. fn to_tokens(&self, tokens: &mut TokenStream) {
  2144. let active = self.active;
  2145. let dialog = self.dialog;
  2146. let pubkey = str_lit(&self.pubkey);
  2147. let endpoints = opt_lit(
  2148. self
  2149. .endpoints
  2150. .as_ref()
  2151. .map(|list| {
  2152. vec_lit(list, |url| {
  2153. let url = url.0.as_str();
  2154. quote! { ::tauri::utils::config::UpdaterEndpoint(#url.parse().unwrap()) }
  2155. })
  2156. })
  2157. .as_ref(),
  2158. );
  2159. literal_struct!(tokens, UpdaterConfig, active, dialog, pubkey, endpoints);
  2160. }
  2161. }
  2162. impl ToTokens for SecurityConfig {
  2163. fn to_tokens(&self, tokens: &mut TokenStream) {
  2164. let csp = opt_str_lit(self.csp.as_ref());
  2165. let dev_csp = opt_str_lit(self.dev_csp.as_ref());
  2166. let freeze_prototype = self.freeze_prototype;
  2167. literal_struct!(tokens, SecurityConfig, csp, dev_csp, freeze_prototype);
  2168. }
  2169. }
  2170. impl ToTokens for SystemTrayConfig {
  2171. fn to_tokens(&self, tokens: &mut TokenStream) {
  2172. let icon_as_template = self.icon_as_template;
  2173. let icon_path = path_buf_lit(&self.icon_path);
  2174. literal_struct!(tokens, SystemTrayConfig, icon_path, icon_as_template);
  2175. }
  2176. }
  2177. impl ToTokens for FsAllowlistScope {
  2178. fn to_tokens(&self, tokens: &mut TokenStream) {
  2179. let allowed_paths = vec_lit(&self.0, path_buf_lit);
  2180. tokens.append_all(quote! { ::tauri::utils::config::FsAllowlistScope(#allowed_paths) })
  2181. }
  2182. }
  2183. impl ToTokens for FsAllowlistConfig {
  2184. fn to_tokens(&self, tokens: &mut TokenStream) {
  2185. let scope = &self.scope;
  2186. tokens.append_all(quote! { ::tauri::utils::config::FsAllowlistConfig { scope: #scope, ..Default::default() } })
  2187. }
  2188. }
  2189. impl ToTokens for ProtocolAllowlistConfig {
  2190. fn to_tokens(&self, tokens: &mut TokenStream) {
  2191. let asset_scope = &self.asset_scope;
  2192. tokens.append_all(quote! { ::tauri::utils::config::ProtocolAllowlistConfig { asset_scope: #asset_scope, ..Default::default() } })
  2193. }
  2194. }
  2195. impl ToTokens for HttpAllowlistScope {
  2196. fn to_tokens(&self, tokens: &mut TokenStream) {
  2197. let allowed_urls = vec_lit(&self.0, url_lit);
  2198. tokens.append_all(quote! { ::tauri::utils::config::HttpAllowlistScope(#allowed_urls) })
  2199. }
  2200. }
  2201. impl ToTokens for HttpAllowlistConfig {
  2202. fn to_tokens(&self, tokens: &mut TokenStream) {
  2203. let scope = &self.scope;
  2204. tokens.append_all(quote! { ::tauri::utils::config::HttpAllowlistConfig { scope: #scope, ..Default::default() } })
  2205. }
  2206. }
  2207. impl ToTokens for ShellAllowedCommand {
  2208. fn to_tokens(&self, tokens: &mut TokenStream) {
  2209. let name = str_lit(&self.name);
  2210. let command = path_buf_lit(&self.command);
  2211. let args = &self.args;
  2212. let sidecar = &self.sidecar;
  2213. literal_struct!(tokens, ShellAllowedCommand, name, command, args, sidecar);
  2214. }
  2215. }
  2216. impl ToTokens for ShellAllowedArgs {
  2217. fn to_tokens(&self, tokens: &mut TokenStream) {
  2218. let prefix = quote! { ::tauri::utils::config::ShellAllowedArgs };
  2219. tokens.append_all(match self {
  2220. Self::Flag(flag) => quote!(#prefix::Flag(#flag)),
  2221. Self::List(list) => {
  2222. let list = vec_lit(list, identity);
  2223. quote!(#prefix::List(#list))
  2224. }
  2225. })
  2226. }
  2227. }
  2228. impl ToTokens for ShellAllowedArg {
  2229. fn to_tokens(&self, tokens: &mut TokenStream) {
  2230. let prefix = quote! { ::tauri::utils::config::ShellAllowedArg };
  2231. tokens.append_all(match self {
  2232. Self::Fixed(fixed) => {
  2233. let fixed = str_lit(fixed);
  2234. quote!(#prefix::Fixed(#fixed))
  2235. }
  2236. Self::Var { validator } => {
  2237. let validator = str_lit(validator);
  2238. quote!(#prefix::Var { validator: #validator })
  2239. }
  2240. })
  2241. }
  2242. }
  2243. impl ToTokens for ShellAllowlistOpen {
  2244. fn to_tokens(&self, tokens: &mut TokenStream) {
  2245. let prefix = quote! { ::tauri::utils::config::ShellAllowlistOpen };
  2246. tokens.append_all(match self {
  2247. Self::Flag(flag) => quote!(#prefix::Flag(#flag)),
  2248. Self::Validate(regex) => quote!(#prefix::Validate(#regex)),
  2249. })
  2250. }
  2251. }
  2252. impl ToTokens for ShellAllowlistScope {
  2253. fn to_tokens(&self, tokens: &mut TokenStream) {
  2254. let allowed_commands = vec_lit(&self.0, identity);
  2255. tokens.append_all(quote! { ::tauri::utils::config::ShellAllowlistScope(#allowed_commands) })
  2256. }
  2257. }
  2258. impl ToTokens for ShellAllowlistConfig {
  2259. fn to_tokens(&self, tokens: &mut TokenStream) {
  2260. let scope = &self.scope;
  2261. tokens.append_all(quote! { ::tauri::utils::config::ShellAllowlistConfig { scope: #scope, ..Default::default() } })
  2262. }
  2263. }
  2264. impl ToTokens for AllowlistConfig {
  2265. fn to_tokens(&self, tokens: &mut TokenStream) {
  2266. let fs = &self.fs;
  2267. let protocol = &self.protocol;
  2268. let http = &self.http;
  2269. let shell = &self.shell;
  2270. tokens.append_all(
  2271. quote! { ::tauri::utils::config::AllowlistConfig { fs: #fs, protocol: #protocol, http: #http, shell: #shell, ..Default::default() } },
  2272. )
  2273. }
  2274. }
  2275. impl ToTokens for TauriConfig {
  2276. fn to_tokens(&self, tokens: &mut TokenStream) {
  2277. let pattern = &self.pattern;
  2278. let windows = vec_lit(&self.windows, identity);
  2279. let cli = opt_lit(self.cli.as_ref());
  2280. let bundle = &self.bundle;
  2281. let updater = &self.updater;
  2282. let security = &self.security;
  2283. let system_tray = opt_lit(self.system_tray.as_ref());
  2284. let allowlist = &self.allowlist;
  2285. let macos_private_api = self.macos_private_api;
  2286. literal_struct!(
  2287. tokens,
  2288. TauriConfig,
  2289. pattern,
  2290. windows,
  2291. cli,
  2292. bundle,
  2293. updater,
  2294. security,
  2295. system_tray,
  2296. allowlist,
  2297. macos_private_api
  2298. );
  2299. }
  2300. }
  2301. impl ToTokens for PluginConfig {
  2302. fn to_tokens(&self, tokens: &mut TokenStream) {
  2303. let config = map_lit(
  2304. quote! { ::std::collections::HashMap },
  2305. &self.0,
  2306. str_lit,
  2307. json_value_lit,
  2308. );
  2309. tokens.append_all(quote! { ::tauri::utils::config::PluginConfig(#config) })
  2310. }
  2311. }
  2312. impl ToTokens for PackageConfig {
  2313. fn to_tokens(&self, tokens: &mut TokenStream) {
  2314. let product_name = opt_str_lit(self.product_name.as_ref());
  2315. let version = opt_str_lit(self.version.as_ref());
  2316. literal_struct!(tokens, PackageConfig, product_name, version);
  2317. }
  2318. }
  2319. impl ToTokens for Config {
  2320. fn to_tokens(&self, tokens: &mut TokenStream) {
  2321. let package = &self.package;
  2322. let tauri = &self.tauri;
  2323. let build = &self.build;
  2324. let plugins = &self.plugins;
  2325. literal_struct!(tokens, Config, package, tauri, build, plugins);
  2326. }
  2327. }
  2328. }
  2329. #[cfg(test)]
  2330. mod test {
  2331. use super::*;
  2332. // TODO: create a test that compares a config to a json config
  2333. #[test]
  2334. // test all of the default functions
  2335. fn test_defaults() {
  2336. // get default tauri config
  2337. let t_config = TauriConfig::default();
  2338. // get default build config
  2339. let b_config = BuildConfig::default();
  2340. // get default dev path
  2341. let d_path = default_dev_path();
  2342. // get default window
  2343. let d_windows: Vec<WindowConfig> = vec![];
  2344. // get default bundle
  2345. let d_bundle = BundleConfig::default();
  2346. // get default updater
  2347. let d_updater = UpdaterConfig::default();
  2348. // create a tauri config.
  2349. let tauri = TauriConfig {
  2350. pattern: Default::default(),
  2351. windows: vec![],
  2352. bundle: BundleConfig {
  2353. active: false,
  2354. targets: None,
  2355. identifier: String::from(""),
  2356. icon: Vec::new(),
  2357. resources: None,
  2358. copyright: None,
  2359. category: None,
  2360. short_description: None,
  2361. long_description: None,
  2362. deb: Default::default(),
  2363. macos: Default::default(),
  2364. external_bin: None,
  2365. windows: Default::default(),
  2366. },
  2367. cli: None,
  2368. updater: UpdaterConfig {
  2369. active: false,
  2370. dialog: true,
  2371. pubkey: "".into(),
  2372. endpoints: None,
  2373. },
  2374. security: SecurityConfig {
  2375. csp: None,
  2376. dev_csp: None,
  2377. freeze_prototype: true,
  2378. },
  2379. allowlist: AllowlistConfig::default(),
  2380. system_tray: None,
  2381. macos_private_api: false,
  2382. };
  2383. // create a build config
  2384. let build = BuildConfig {
  2385. runner: None,
  2386. dev_path: AppUrl::Url(WindowUrl::External(
  2387. Url::parse("http://localhost:8080").unwrap(),
  2388. )),
  2389. dist_dir: AppUrl::Url(WindowUrl::App("../dist".into())),
  2390. before_dev_command: None,
  2391. before_build_command: None,
  2392. features: None,
  2393. with_global_tauri: false,
  2394. };
  2395. // test the configs
  2396. assert_eq!(t_config, tauri);
  2397. assert_eq!(b_config, build);
  2398. assert_eq!(d_bundle, tauri.bundle);
  2399. assert_eq!(d_updater, tauri.updater);
  2400. assert_eq!(
  2401. d_path,
  2402. AppUrl::Url(WindowUrl::External(
  2403. Url::parse("http://localhost:8080").unwrap()
  2404. ))
  2405. );
  2406. assert_eq!(d_windows, tauri.windows);
  2407. }
  2408. }