config_definition.rs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. use schemars::JsonSchema;
  2. use serde::{Deserialize, Serialize};
  3. use serde_json::Value as JsonValue;
  4. use std::{collections::HashMap, path::PathBuf};
  5. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  6. #[serde(untagged)]
  7. pub enum BundleTarget {
  8. All(Vec<String>),
  9. One(String),
  10. }
  11. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  12. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  13. pub struct DebConfig {
  14. pub depends: Option<Vec<String>>,
  15. #[serde(default)]
  16. pub use_bootstrapper: bool,
  17. }
  18. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  19. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  20. pub struct OsxConfig {
  21. pub frameworks: Option<Vec<String>>,
  22. pub minimum_system_version: Option<String>,
  23. pub exception_domain: Option<String>,
  24. pub license: Option<String>,
  25. #[serde(default)]
  26. pub use_bootstrapper: bool,
  27. }
  28. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  29. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  30. pub struct BundleConfig {
  31. /// Whether we should build your app with tauri-bundler or plain `cargo build`
  32. pub active: bool,
  33. /// The bundle targets, currently supports ["deb", "osx", "msi", "appimage", "dmg"] or "all"
  34. pub targets: Option<BundleTarget>,
  35. pub name: Option<String>,
  36. /// The app's identifier
  37. pub identifier: Option<String>,
  38. /// The app's icons
  39. pub icon: Option<Vec<String>>,
  40. pub version: Option<String>,
  41. /// App resources to bundle.
  42. /// Each resource is a path to a file or directory.
  43. /// Glob patterns are supported.
  44. pub resources: Option<Vec<String>>,
  45. pub copyright: Option<String>,
  46. pub category: Option<String>,
  47. pub short_description: Option<String>,
  48. pub long_description: Option<String>,
  49. pub script: Option<PathBuf>,
  50. #[serde(default)]
  51. pub deb: DebConfig,
  52. #[serde(default)]
  53. pub osx: OsxConfig,
  54. pub external_bin: Option<Vec<String>>,
  55. }
  56. /// A CLI argument definition
  57. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  58. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  59. pub struct CliArg {
  60. /// The short version of the argument, without the preceding -.
  61. ///
  62. /// NOTE: Any leading - characters will be stripped, and only the first non - character will be used as the short version.
  63. pub short: Option<char>,
  64. /// The unique argument name
  65. pub name: String,
  66. /// The argument description which will be shown on the help information.
  67. /// Typically, this is a short (one line) description of the arg.
  68. pub description: Option<String>,
  69. /// The argument long description which will be shown on the help information.
  70. /// Typically this a more detailed (multi-line) message that describes the argument.
  71. pub long_description: Option<String>,
  72. /// Specifies that the argument takes a value at run time.
  73. ///
  74. /// NOTE: values for arguments may be specified in any of the following methods
  75. /// - Using a space such as -o value or --option value
  76. /// - Using an equals and no space such as -o=value or --option=value
  77. /// - Use a short and no space such as -ovalue
  78. pub takes_value: Option<bool>,
  79. /// Specifies that the argument may appear more than once.
  80. ///
  81. /// - For flags, this results in the number of occurrences of the flag being recorded.
  82. /// For example -ddd or -d -d -d would count as three occurrences.
  83. /// - For options there is a distinct difference in multiple occurrences vs multiple values.
  84. /// For example, --opt val1 val2 is one occurrence, but two values. Whereas --opt val1 --opt val2 is two occurrences.
  85. pub multiple: Option<bool>,
  86. /// specifies that the argument may appear more than once.
  87. pub multiple_occurrences: Option<bool>,
  88. ///
  89. pub number_of_values: Option<u64>,
  90. /// Specifies a list of possible values for this argument.
  91. /// At runtime, the CLI verifies that only one of the specified values was used, or fails with an error message.
  92. pub possible_values: Option<Vec<String>>,
  93. /// Specifies the minimum number of values for this argument.
  94. /// For example, if you had a -f <file> argument where you wanted at least 2 'files',
  95. /// you would set `minValues: 2`, and this argument would be satisfied if the user provided, 2 or more values.
  96. pub min_values: Option<u64>,
  97. /// Specifies the maximum number of values are for this argument.
  98. /// For example, if you had a -f <file> argument where you wanted up to 3 'files',
  99. /// you would set .max_values(3), and this argument would be satisfied if the user provided, 1, 2, or 3 values.
  100. pub max_values: Option<u64>,
  101. /// Sets whether or not the argument is required by default.
  102. ///
  103. /// - Required by default means it is required, when no other conflicting rules have been evaluated
  104. /// - Conflicting rules take precedence over being required.
  105. pub required: Option<bool>,
  106. /// Sets an arg that override this arg's required setting
  107. /// i.e. this arg will be required unless this other argument is present.
  108. pub required_unless_present: Option<String>,
  109. /// Sets args that override this arg's required setting
  110. /// i.e. this arg will be required unless all these other arguments are present.
  111. pub required_unless_present_all: Option<Vec<String>>,
  112. /// Sets args that override this arg's required setting
  113. /// i.e. this arg will be required unless at least one of these other arguments are present.
  114. pub required_unless_present_any: Option<Vec<String>>,
  115. /// Sets a conflicting argument by name
  116. /// i.e. when using this argument, the following argument can't be present and vice versa.
  117. pub conflicts_with: Option<String>,
  118. /// The same as conflictsWith but allows specifying multiple two-way conflicts per argument.
  119. pub conflicts_with_all: Option<Vec<String>>,
  120. /// Tets an argument by name that is required when this one is present
  121. /// i.e. when using this argument, the following argument must be present.
  122. pub requires: Option<String>,
  123. /// Sts multiple arguments by names that are required when this one is present
  124. /// i.e. when using this argument, the following arguments must be present.
  125. pub requires_all: Option<Vec<String>>,
  126. /// Allows a conditional requirement with the signature [arg, value]
  127. /// the requirement will only become valid if `arg`'s value equals `${value}`.
  128. pub requires_if: Option<Vec<String>>,
  129. /// Allows specifying that an argument is required conditionally with the signature [arg, value]
  130. /// the requirement will only become valid if the `arg`'s value equals `${value}`.
  131. pub required_if_eq: Option<Vec<String>>,
  132. /// Requires that options use the --option=val syntax
  133. /// i.e. an equals between the option and associated value.
  134. pub require_equals: Option<bool>,
  135. /// The positional argument index, starting at 1.
  136. ///
  137. /// The index refers to position according to other positional argument.
  138. /// It does not define position in the argument list as a whole. When utilized with multiple=true,
  139. /// only the last positional argument may be defined as multiple (i.e. the one with the highest index).
  140. pub index: Option<u64>,
  141. }
  142. /// describes a CLI configuration
  143. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  144. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  145. pub struct CliConfig {
  146. /// command description which will be shown on the help information
  147. description: Option<String>,
  148. /// command long description which will be shown on the help information
  149. long_description: Option<String>,
  150. /// adds additional help information to be displayed in addition to auto-generated help
  151. /// this information is displayed before the auto-generated help information.
  152. /// this is often used for header information
  153. before_help: Option<String>,
  154. /// adds additional help information to be displayed in addition to auto-generated help
  155. /// this information is displayed after the auto-generated help information
  156. /// this is often used to describe how to use the arguments, or caveats to be noted.
  157. after_help: Option<String>,
  158. /// list of args for the command
  159. args: Option<Vec<CliArg>>,
  160. /// list of subcommands of this command.
  161. ///
  162. /// subcommands are effectively sub-apps, because they can contain their own arguments, subcommands, usage, etc.
  163. /// they also function just like the app command, in that they get their own auto generated help and usage
  164. subcommands: Option<HashMap<String, CliConfig>>,
  165. }
  166. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  167. #[serde(untagged)]
  168. pub enum Port {
  169. /// Port with a numeric value.
  170. Value(u16),
  171. /// Random port.
  172. Random,
  173. }
  174. /// The embeddedServer configuration object.
  175. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  176. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  177. pub struct EmbeddedServerConfig {
  178. /// The embedded server host.
  179. pub host: Option<String>,
  180. /// The embedded server port.
  181. /// If it's `random`, we'll generate one at runtime.
  182. pub port: Option<Port>,
  183. /// The base path of the embedded server.
  184. /// The path should always start and end in a forward slash, which the deserializer will ensure
  185. pub public_path: Option<String>,
  186. }
  187. /// The window configuration object.
  188. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  189. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  190. pub struct WindowConfig {
  191. /// The window identifier.
  192. pub label: Option<String>,
  193. /// The window webview URL.
  194. pub url: Option<String>,
  195. /// The horizontal position of the window's top left corner
  196. pub x: Option<f64>,
  197. /// The vertical position of the window's top left corner
  198. pub y: Option<f64>,
  199. /// The window width.
  200. pub width: Option<f64>,
  201. /// The window height.
  202. pub height: Option<f64>,
  203. /// The min window width.
  204. pub min_width: Option<f64>,
  205. /// The min window height.
  206. pub min_height: Option<f64>,
  207. /// The max window width.
  208. pub max_width: Option<f64>,
  209. /// The max window height.
  210. pub max_height: Option<f64>,
  211. /// Whether the window is resizable or not.
  212. #[serde(default)]
  213. pub resizable: bool,
  214. /// The window title.
  215. pub title: Option<String>,
  216. /// Whether the window starts as fullscreen or not.
  217. #[serde(default)]
  218. pub fullscreen: bool,
  219. /// Whether the window is transparent or not.
  220. #[serde(default)]
  221. pub transparent: bool,
  222. /// Whether the window is maximized or not.
  223. #[serde(default)]
  224. pub maximized: bool,
  225. /// Whether the window is visible or not.
  226. #[serde(default)]
  227. pub visible: bool,
  228. /// Whether the window should have borders and bars.
  229. #[serde(default)]
  230. pub decorations: bool,
  231. /// Whether the window should always be on top of other windows.
  232. #[serde(default)]
  233. pub always_on_top: bool,
  234. }
  235. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  236. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  237. pub struct SecurityConfig {
  238. csp: Option<String>,
  239. }
  240. trait Allowlist {
  241. fn to_features(&self) -> Vec<&str>;
  242. }
  243. macro_rules! check_feature {
  244. ($self:ident, $features:ident, $flag:ident, $feature_name: expr) => {
  245. if $self.$flag {
  246. $features.push($feature_name)
  247. }
  248. };
  249. }
  250. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  251. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  252. struct FsAllowlistConfig {
  253. #[serde(default)]
  254. all: bool,
  255. #[serde(default)]
  256. read_text_file: bool,
  257. #[serde(default)]
  258. read_binary_file: bool,
  259. #[serde(default)]
  260. write_file: bool,
  261. #[serde(default)]
  262. write_binary_file: bool,
  263. #[serde(default)]
  264. read_dir: bool,
  265. #[serde(default)]
  266. copy_file: bool,
  267. #[serde(default)]
  268. create_dir: bool,
  269. #[serde(default)]
  270. remove_dir: bool,
  271. #[serde(default)]
  272. remove_file: bool,
  273. #[serde(default)]
  274. rename_file: bool,
  275. #[serde(default)]
  276. path: bool,
  277. }
  278. impl Allowlist for FsAllowlistConfig {
  279. fn to_features(&self) -> Vec<&str> {
  280. if self.all {
  281. vec!["fs-all"]
  282. } else {
  283. let mut features = Vec::new();
  284. check_feature!(self, features, read_text_file, "fs-read-text-file");
  285. check_feature!(self, features, read_binary_file, "fs-read-binary-file");
  286. check_feature!(self, features, write_file, "fs-write-file");
  287. check_feature!(self, features, write_binary_file, "fs-write-binary-file");
  288. check_feature!(self, features, read_dir, "fs-read-dir");
  289. check_feature!(self, features, copy_file, "fs-copy-file");
  290. check_feature!(self, features, create_dir, "fs-create-dir");
  291. check_feature!(self, features, remove_dir, "fs-remove-dir");
  292. check_feature!(self, features, remove_file, "fs-remove-file");
  293. check_feature!(self, features, rename_file, "fs-rename-file");
  294. check_feature!(self, features, path, "fs-path");
  295. features
  296. }
  297. }
  298. }
  299. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  300. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  301. struct WindowAllowlistConfig {
  302. #[serde(default)]
  303. all: bool,
  304. #[serde(default)]
  305. create: bool,
  306. }
  307. impl Allowlist for WindowAllowlistConfig {
  308. fn to_features(&self) -> Vec<&str> {
  309. if self.all {
  310. vec!["window-all"]
  311. } else {
  312. let mut features = Vec::new();
  313. check_feature!(self, features, create, "window-create");
  314. features
  315. }
  316. }
  317. }
  318. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  319. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  320. struct ShellAllowlistConfig {
  321. #[serde(default)]
  322. all: bool,
  323. #[serde(default)]
  324. execute: bool,
  325. #[serde(default)]
  326. open: bool,
  327. }
  328. impl Allowlist for ShellAllowlistConfig {
  329. fn to_features(&self) -> Vec<&str> {
  330. if self.all {
  331. vec!["shell-all"]
  332. } else {
  333. let mut features = Vec::new();
  334. check_feature!(self, features, execute, "shell-execute");
  335. check_feature!(self, features, open, "shell-open");
  336. features
  337. }
  338. }
  339. }
  340. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  341. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  342. struct DialogAllowlistConfig {
  343. #[serde(default)]
  344. all: bool,
  345. #[serde(default)]
  346. open: bool,
  347. #[serde(default)]
  348. save: bool,
  349. }
  350. impl Allowlist for DialogAllowlistConfig {
  351. fn to_features(&self) -> Vec<&str> {
  352. if self.all {
  353. vec!["dialog-all"]
  354. } else {
  355. let mut features = Vec::new();
  356. check_feature!(self, features, open, "dialog-open");
  357. check_feature!(self, features, save, "dialog-save");
  358. features
  359. }
  360. }
  361. }
  362. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  363. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  364. struct HttpAllowlistConfig {
  365. #[serde(default)]
  366. all: bool,
  367. #[serde(default)]
  368. request: bool,
  369. }
  370. impl Allowlist for HttpAllowlistConfig {
  371. fn to_features(&self) -> Vec<&str> {
  372. if self.all {
  373. vec!["http-all"]
  374. } else {
  375. let mut features = Vec::new();
  376. check_feature!(self, features, request, "http-request");
  377. features
  378. }
  379. }
  380. }
  381. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  382. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  383. struct NotificationAllowlistConfig {
  384. #[serde(default)]
  385. all: bool,
  386. }
  387. impl Allowlist for NotificationAllowlistConfig {
  388. fn to_features(&self) -> Vec<&str> {
  389. if self.all {
  390. vec!["notification-all"]
  391. } else {
  392. vec![]
  393. }
  394. }
  395. }
  396. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  397. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  398. struct GlobalShortcutAllowlistConfig {
  399. #[serde(default)]
  400. all: bool,
  401. }
  402. impl Allowlist for GlobalShortcutAllowlistConfig {
  403. fn to_features(&self) -> Vec<&str> {
  404. if self.all {
  405. vec!["global-shortcut-all"]
  406. } else {
  407. vec![]
  408. }
  409. }
  410. }
  411. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  412. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  413. struct AllowlistConfig {
  414. #[serde(default)]
  415. all: bool,
  416. #[serde(default)]
  417. fs: FsAllowlistConfig,
  418. #[serde(default)]
  419. window: WindowAllowlistConfig,
  420. #[serde(default)]
  421. shell: ShellAllowlistConfig,
  422. #[serde(default)]
  423. dialog: DialogAllowlistConfig,
  424. #[serde(default)]
  425. http: HttpAllowlistConfig,
  426. #[serde(default)]
  427. notification: NotificationAllowlistConfig,
  428. #[serde(default)]
  429. global_shortcut: GlobalShortcutAllowlistConfig,
  430. }
  431. impl Allowlist for AllowlistConfig {
  432. fn to_features(&self) -> Vec<&str> {
  433. if self.all {
  434. vec!["api-all"]
  435. } else {
  436. let mut features = Vec::new();
  437. features.extend(self.fs.to_features());
  438. features.extend(self.window.to_features());
  439. features.extend(self.shell.to_features());
  440. features.extend(self.dialog.to_features());
  441. features.extend(self.http.to_features());
  442. features.extend(self.notification.to_features());
  443. features.extend(self.global_shortcut.to_features());
  444. features
  445. }
  446. }
  447. }
  448. /// The Tauri configuration object.
  449. #[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  450. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  451. pub struct TauriConfig {
  452. /// The windows configuration.
  453. #[serde(default)]
  454. pub windows: Vec<WindowConfig>,
  455. /// The CLI configuration.
  456. pub cli: Option<CliConfig>,
  457. #[serde(default)]
  458. pub embedded_server: EmbeddedServerConfig,
  459. /// The bundler configuration.
  460. #[serde(default)]
  461. pub bundle: BundleConfig,
  462. #[serde(default)]
  463. allowlist: AllowlistConfig,
  464. pub security: Option<SecurityConfig>,
  465. }
  466. impl TauriConfig {
  467. #[allow(dead_code)]
  468. pub fn features(&self) -> Vec<&str> {
  469. self.allowlist.to_features()
  470. }
  471. }
  472. /// The Build configuration object.
  473. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  474. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  475. pub struct BuildConfig {
  476. /// the app's dev server URL, or the path to the directory containing an index.html file
  477. #[serde(default = "default_dev_path")]
  478. pub dev_path: String,
  479. /// the path to the app's dist dir. This path must contain your index.html file.
  480. #[serde(default = "default_dist_dir")]
  481. pub dist_dir: String,
  482. /// a shell command to run before `tauri dev` kicks in
  483. pub before_dev_command: Option<String>,
  484. /// a shell command to run before `tauri build` kicks in
  485. pub before_build_command: Option<String>,
  486. /// Whether we should inject the Tauri API on `window.__TAURI__` or not.
  487. #[serde(default)]
  488. pub with_global_tauri: bool,
  489. }
  490. fn default_dev_path() -> String {
  491. "".to_string()
  492. }
  493. fn default_dist_dir() -> String {
  494. "../dist".to_string()
  495. }
  496. type JsonObject = HashMap<String, JsonValue>;
  497. /// The tauri.conf.json mapper.
  498. #[derive(Debug, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
  499. #[serde(rename_all = "camelCase", deny_unknown_fields)]
  500. pub struct Config {
  501. /// The Tauri configuration.
  502. #[serde(default)]
  503. pub tauri: TauriConfig,
  504. /// The build configuration.
  505. #[serde(default = "default_build")]
  506. pub build: BuildConfig,
  507. /// The plugins config.
  508. #[serde(default)]
  509. pub plugins: HashMap<String, JsonObject>,
  510. }
  511. fn default_build() -> BuildConfig {
  512. BuildConfig {
  513. dev_path: default_dev_path(),
  514. dist_dir: default_dist_dir(),
  515. before_dev_command: None,
  516. before_build_command: None,
  517. with_global_tauri: false,
  518. }
  519. }