diff --git a/.changes/config-$schema.md b/.changes/config-$schema.md new file mode 100644 index 000000000..ac8f87a5a --- /dev/null +++ b/.changes/config-$schema.md @@ -0,0 +1,7 @@ +--- +"tauri-utils": patch +"cli.rs": patch +"cli.js": patch +--- + +Added `$schema` support to `tauri.conf.json`. diff --git a/core/tauri-utils/src/config.rs b/core/tauri-utils/src/config.rs index ad5263c88..809df6ca0 100644 --- a/core/tauri-utils/src/config.rs +++ b/core/tauri-utils/src/config.rs @@ -2125,6 +2125,9 @@ impl PackageConfig { #[cfg_attr(feature = "schema", derive(JsonSchema))] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct Config { + /// The JSON schema for the Tauri config. + #[serde(rename = "$schema")] + pub schema: Option, /// Package settings. #[serde(default)] pub package: PackageConfig, @@ -2887,12 +2890,13 @@ mod build { impl ToTokens for Config { fn to_tokens(&self, tokens: &mut TokenStream) { + let schema = quote!(None); let package = &self.package; let tauri = &self.tauri; let build = &self.build; let plugins = &self.plugins; - literal_struct!(tokens, Config, package, tauri, build, plugins); + literal_struct!(tokens, Config, schema, package, tauri, build, plugins); } } } diff --git a/core/tauri/src/test/mod.rs b/core/tauri/src/test/mod.rs index 7f95994bf..7bfb71332 100644 --- a/core/tauri/src/test/mod.rs +++ b/core/tauri/src/test/mod.rs @@ -42,6 +42,7 @@ pub fn noop_assets() -> NoopAsset { pub fn mock_context(assets: A) -> crate::Context { crate::Context { config: Config { + schema: None, package: Default::default(), tauri: TauriConfig { pattern: PatternKind::Brownfield, diff --git a/core/tauri/test/fixture/src-tauri/tauri.conf.json b/core/tauri/test/fixture/src-tauri/tauri.conf.json index f5ecf03b2..77d42b93e 100644 --- a/core/tauri/test/fixture/src-tauri/tauri.conf.json +++ b/core/tauri/test/fixture/src-tauri/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../../../../tooling/cli/schema.json", "build": { "distDir": "../dist", "devPath": "http://localhost:4000" diff --git a/core/tests/app-updater/tauri.conf.json b/core/tests/app-updater/tauri.conf.json index b650d8a99..28406899b 100644 --- a/core/tests/app-updater/tauri.conf.json +++ b/core/tests/app-updater/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../../tooling/cli/schema.json", "build": { "distDir": [], "devPath": [] diff --git a/examples/api/src-tauri/tauri.conf.json b/examples/api/src-tauri/tauri.conf.json index b73f21e06..a66ec59d1 100644 --- a/examples/api/src-tauri/tauri.conf.json +++ b/examples/api/src-tauri/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../../tooling/cli/schema.json", "build": { "distDir": "../dist", "devPath": "http://localhost:5000", diff --git a/examples/commands/tauri.conf.json b/examples/commands/tauri.conf.json index 7164c83c6..52d95b2a3 100644 --- a/examples/commands/tauri.conf.json +++ b/examples/commands/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../tooling/cli/schema.json", "build": { "distDir": ["index.html"], "devPath": ["index.html"], diff --git a/examples/helloworld/tauri.conf.json b/examples/helloworld/tauri.conf.json index 09bc55c96..1c6d8fead 100644 --- a/examples/helloworld/tauri.conf.json +++ b/examples/helloworld/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../tooling/cli/schema.json", "build": { "distDir": ["index.html"], "devPath": ["index.html"], diff --git a/examples/isolation/tauri.conf.json b/examples/isolation/tauri.conf.json index f15807dab..f39361272 100644 --- a/examples/isolation/tauri.conf.json +++ b/examples/isolation/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../tooling/cli/schema.json", "package": { "productName": "isolation", "version": "0.1.0" diff --git a/examples/multiwindow/tauri.conf.json b/examples/multiwindow/tauri.conf.json index 03a1ae881..07fd1a95e 100644 --- a/examples/multiwindow/tauri.conf.json +++ b/examples/multiwindow/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../tooling/cli/schema.json", "build": { "distDir": ["index.html"], "devPath": ["index.html"], diff --git a/examples/navigation/tauri.conf.json b/examples/navigation/tauri.conf.json index 0a64be7ae..6d12ede16 100644 --- a/examples/navigation/tauri.conf.json +++ b/examples/navigation/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../tooling/cli/schema.json", "build": { "distDir": "public", "devPath": "public", diff --git a/examples/parent-window/tauri.conf.json b/examples/parent-window/tauri.conf.json index 6b22828b9..a9191425c 100644 --- a/examples/parent-window/tauri.conf.json +++ b/examples/parent-window/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../tooling/cli/schema.json", "build": { "distDir": ["index.html"], "devPath": ["index.html"], diff --git a/examples/resources/src-tauri/tauri.conf.json b/examples/resources/src-tauri/tauri.conf.json index d10e4513e..5033d4a5b 100644 --- a/examples/resources/src-tauri/tauri.conf.json +++ b/examples/resources/src-tauri/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../../tooling/cli/schema.json", "build": { "distDir": ["../index.html"], "devPath": ["../index.html"], diff --git a/examples/sidecar/src-tauri/tauri.conf.json b/examples/sidecar/src-tauri/tauri.conf.json index b90046e50..09e869b76 100644 --- a/examples/sidecar/src-tauri/tauri.conf.json +++ b/examples/sidecar/src-tauri/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../../tooling/cli/schema.json", "build": { "distDir": ["../index.html"], "devPath": ["../index.html"], diff --git a/examples/splashscreen/tauri.conf.json b/examples/splashscreen/tauri.conf.json index f2326a3a9..04b335d3e 100644 --- a/examples/splashscreen/tauri.conf.json +++ b/examples/splashscreen/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../tooling/cli/schema.json", "build": { "distDir": "dist", "devPath": "dist", diff --git a/examples/state/tauri.conf.json b/examples/state/tauri.conf.json index 7164c83c6..52d95b2a3 100644 --- a/examples/state/tauri.conf.json +++ b/examples/state/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../tooling/cli/schema.json", "build": { "distDir": ["index.html"], "devPath": ["index.html"], diff --git a/examples/streaming/tauri.conf.json b/examples/streaming/tauri.conf.json index 4a85ce235..3e1a220a3 100644 --- a/examples/streaming/tauri.conf.json +++ b/examples/streaming/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../tooling/cli/schema.json", "build": { "distDir": ["index.html"], "devPath": ["index.html"], diff --git a/examples/tauri-dynamic-lib/src-tauri/tauri.conf.json b/examples/tauri-dynamic-lib/src-tauri/tauri.conf.json index 3e71fd3fc..576ac26c0 100644 --- a/examples/tauri-dynamic-lib/src-tauri/tauri.conf.json +++ b/examples/tauri-dynamic-lib/src-tauri/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../../tooling/cli/schema.json", "build": { "distDir": ["src/index.html"], "devPath": ["src/index.html"], diff --git a/examples/updater/src-tauri/tauri.conf.json b/examples/updater/src-tauri/tauri.conf.json index 37d18442e..e9c8bd2b4 100644 --- a/examples/updater/src-tauri/tauri.conf.json +++ b/examples/updater/src-tauri/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../../tooling/cli/schema.json", "build": { "distDir": ["../index.html"], "devPath": ["../index.html"], diff --git a/tooling/bench/tests/cpu_intensive/src-tauri/tauri.conf.json b/tooling/bench/tests/cpu_intensive/src-tauri/tauri.conf.json index 1cf73adc7..62777c527 100644 --- a/tooling/bench/tests/cpu_intensive/src-tauri/tauri.conf.json +++ b/tooling/bench/tests/cpu_intensive/src-tauri/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../../../../tooling/cli/schema.json", "build": { "distDir": "../public", "devPath": "../public", diff --git a/tooling/bench/tests/files_transfer/src-tauri/tauri.conf.json b/tooling/bench/tests/files_transfer/src-tauri/tauri.conf.json index 1666be376..045b8c481 100644 --- a/tooling/bench/tests/files_transfer/src-tauri/tauri.conf.json +++ b/tooling/bench/tests/files_transfer/src-tauri/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../../../../tooling/cli/schema.json", "build": { "distDir": "../public", "devPath": "../public", diff --git a/tooling/bench/tests/helloworld/src-tauri/tauri.conf.json b/tooling/bench/tests/helloworld/src-tauri/tauri.conf.json index 1cf73adc7..62777c527 100644 --- a/tooling/bench/tests/helloworld/src-tauri/tauri.conf.json +++ b/tooling/bench/tests/helloworld/src-tauri/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../../../../tooling/cli/schema.json", "build": { "distDir": "../public", "devPath": "../public", diff --git a/tooling/cli/node/.gitignore b/tooling/cli/node/.gitignore index a56b09701..cc606d37a 100644 --- a/tooling/cli/node/.gitignore +++ b/tooling/cli/node/.gitignore @@ -1,2 +1,3 @@ # Automatically generated -/*.node \ No newline at end of file +/*.node +schema.json diff --git a/tooling/cli/node/package.json b/tooling/cli/node/package.json index 8de030258..7308f7d77 100644 --- a/tooling/cli/node/package.json +++ b/tooling/cli/node/package.json @@ -38,6 +38,7 @@ }, "devDependencies": { "@napi-rs/cli": "2.7.0", + "cross-env": "7.0.3", "cross-spawn": "7.0.3", "fs-extra": "10.1.0", "jest": "28.0.3", @@ -52,9 +53,10 @@ }, "scripts": { "artifacts": "napi artifacts", - "build:release": "napi build --platform --release", - "build": "napi build --platform", + "build:release": "cross-env TARGET=node napi build --platform --release", + "build": "cross-env TARGET=node napi build --platform", "prepublishOnly": "napi prepublish -t npm", + "prepack": "cp ../schema.json .", "test": "jest --runInBand --forceExit --no-cache", "version": "napi version", "tauri": "node ./tauri.js", diff --git a/tooling/cli/node/test/jest/fixtures/app/src-tauri/tauri.conf.json b/tooling/cli/node/test/jest/fixtures/app/src-tauri/tauri.conf.json index ca1fe4e6a..230b663ca 100644 --- a/tooling/cli/node/test/jest/fixtures/app/src-tauri/tauri.conf.json +++ b/tooling/cli/node/test/jest/fixtures/app/src-tauri/tauri.conf.json @@ -1,4 +1,5 @@ { + "$schema": "../../../../../../../../tooling/cli/schema.json", "build": { "devPath": "../dist", "distDir": "../dist", diff --git a/tooling/cli/node/yarn.lock b/tooling/cli/node/yarn.lock index eb8ab6e9c..39401d1d8 100644 --- a/tooling/cli/node/yarn.lock +++ b/tooling/cli/node/yarn.lock @@ -1041,7 +1041,14 @@ convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" -cross-spawn@7.0.3, cross-spawn@^7.0.3: +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + +cross-spawn@7.0.3, cross-spawn@^7.0.1, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== diff --git a/tooling/cli/schema.json b/tooling/cli/schema.json index d0fcb4584..573eac891 100644 --- a/tooling/cli/schema.json +++ b/tooling/cli/schema.json @@ -4,6 +4,13 @@ "description": "The config type mapped to `tauri.conf.json`.", "type": "object", "properties": { + "$schema": { + "description": "The JSON schema for the Tauri config.", + "type": [ + "string", + "null" + ] + }, "build": { "description": "The build configuration.", "default": { diff --git a/tooling/cli/src/init.rs b/tooling/cli/src/init.rs index 231f2ae36..1238fd0c7 100644 --- a/tooling/cli/src/init.rs +++ b/tooling/cli/src/init.rs @@ -27,6 +27,7 @@ use include_dir::{include_dir, Dir}; use serde::Deserialize; const TEMPLATE_DIR: Dir<'_> = include_dir!("templates/app"); +const TAURI_CONF_TEMPLATE: &str = include_str!("../templates/tauri.conf.json"); #[derive(Debug, Parser)] #[clap(about = "Initializes a Tauri project")] @@ -185,6 +186,56 @@ pub fn command(mut options: Options) -> Result<()> { to_json(options.window_title.unwrap_or_else(|| "Tauri".to_string())), ); + let mut config = serde_json::from_str( + &handlebars + .render_template(TAURI_CONF_TEMPLATE, &data) + .expect("Failed to render tauri.conf.json template"), + ) + .unwrap(); + if crate::TARGET == Some("node") { + let mut dir = current_dir().expect("failed to read cwd"); + let mut count = 0; + let mut cli_node_module_path = None; + let cli_path = "node_modules/@tauri-apps/cli"; + + // only go up three folders max + while count <= 2 { + let test_path = dir.join(cli_path); + if test_path.exists() { + let mut node_module_path = PathBuf::from(".."); + for _ in 0..count { + node_module_path.push(".."); + } + node_module_path.push(cli_path); + node_module_path.push("schema.json"); + cli_node_module_path.replace(node_module_path); + break; + } + count += 1; + match dir.parent() { + Some(parent) => { + dir = parent.to_path_buf(); + } + None => break, + } + } + + if let Some(cli_node_module_path) = cli_node_module_path { + let mut map = serde_json::Map::default(); + map.insert( + "$schema".into(), + serde_json::Value::String(cli_node_module_path.display().to_string()), + ); + let merge_config = serde_json::Value::Object(map); + json_patch::merge(&mut config, &merge_config); + } + } + + data.insert( + "tauri_config", + to_json(serde_json::to_string_pretty(&config).unwrap()), + ); + template::render(&handlebars, &data, &TEMPLATE_DIR, &options.directory) .with_context(|| "failed to render Tauri template")?; } diff --git a/tooling/cli/src/lib.rs b/tooling/cli/src/lib.rs index 8c894b2d1..7007a6792 100644 --- a/tooling/cli/src/lib.rs +++ b/tooling/cli/src/lib.rs @@ -17,6 +17,8 @@ use clap::{FromArgMatches, IntoApp, Parser, Subcommand}; use std::ffi::OsString; +const TARGET: Option<&str> = option_env!("TARGET"); + pub(crate) trait CommandExt { fn pipe(&mut self) -> Result<&mut Self>; } diff --git a/tooling/cli/templates/app/src-tauri/tauri.conf.json b/tooling/cli/templates/app/src-tauri/tauri.conf.json index 79829f625..9cc5eb7ca 100644 --- a/tooling/cli/templates/app/src-tauri/tauri.conf.json +++ b/tooling/cli/templates/app/src-tauri/tauri.conf.json @@ -1,65 +1 @@ -{ - "package": { - "productName": "{{ app_name }}", - "version": "0.1.0" - }, - "build": { - "distDir": "{{ dist_dir }}", - "devPath": "{{ dev_path }}", - "beforeDevCommand": "", - "beforeBuildCommand": "" - }, - "tauri": { - "bundle": { - "active": true, - "targets": "all", - "identifier": "com.tauri.dev", - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "resources": [], - "externalBin": [], - "copyright": "", - "category": "DeveloperTool", - "shortDescription": "", - "longDescription": "", - "deb": { - "depends": [] - }, - "macOS": { - "frameworks": [], - "exceptionDomain": "", - "signingIdentity": null, - "providerShortName": null, - "entitlements": null - }, - "windows": { - "certificateThumbprint": null, - "digestAlgorithm": "sha256", - "timestampUrl": "" - } - }, - "updater": { - "active": false - }, - "allowlist": { - "all": true - }, - "windows": [ - { - "title": "{{ window_title }}", - "width": 800, - "height": 600, - "resizable": true, - "fullscreen": false - } - ], - "security": { - "csp": null - } - } -} +{{{ tauri_config }}} diff --git a/tooling/cli/templates/tauri.conf.json b/tooling/cli/templates/tauri.conf.json new file mode 100644 index 000000000..79829f625 --- /dev/null +++ b/tooling/cli/templates/tauri.conf.json @@ -0,0 +1,65 @@ +{ + "package": { + "productName": "{{ app_name }}", + "version": "0.1.0" + }, + "build": { + "distDir": "{{ dist_dir }}", + "devPath": "{{ dev_path }}", + "beforeDevCommand": "", + "beforeBuildCommand": "" + }, + "tauri": { + "bundle": { + "active": true, + "targets": "all", + "identifier": "com.tauri.dev", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "resources": [], + "externalBin": [], + "copyright": "", + "category": "DeveloperTool", + "shortDescription": "", + "longDescription": "", + "deb": { + "depends": [] + }, + "macOS": { + "frameworks": [], + "exceptionDomain": "", + "signingIdentity": null, + "providerShortName": null, + "entitlements": null + }, + "windows": { + "certificateThumbprint": null, + "digestAlgorithm": "sha256", + "timestampUrl": "" + } + }, + "updater": { + "active": false + }, + "allowlist": { + "all": true + }, + "windows": [ + { + "title": "{{ window_title }}", + "width": 800, + "height": 600, + "resizable": true, + "fullscreen": false + } + ], + "security": { + "csp": null + } + } +}