Эх сурвалжийг харах

feat(cli.rs): add `init plugin` command, bootstraps a plugin project (#2669)

Lucas Fernandes Nogueira 3 жил өмнө
parent
commit
ac8e69a98c
98 өөрчлөгдсөн 1615 нэмэгдсэн , 96 устгасан
  1. 5 0
      .changes/plugin-command.md
  2. 80 25
      docs/api/cli.md
  3. 9 7
      docs/usage/guides/plugin.md
  4. 1 3
      tooling/cli.rs/Cargo.toml
  5. 25 1
      tooling/cli.rs/src/cli.yml
  6. 11 0
      tooling/cli.rs/src/helpers/mod.rs
  7. 44 0
      tooling/cli.rs/src/helpers/template.rs
  8. 8 59
      tooling/cli.rs/src/init.rs
  9. 34 1
      tooling/cli.rs/src/main.rs
  10. 120 0
      tooling/cli.rs/src/plugin.rs
  11. 0 0
      tooling/cli.rs/templates/app/src-tauri/.gitignore
  12. 0 0
      tooling/cli.rs/templates/app/src-tauri/Cargo.crate-manifest
  13. 0 0
      tooling/cli.rs/templates/app/src-tauri/build.rs
  14. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/128x128.png
  15. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/128x128@2x.png
  16. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/32x32.png
  17. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/Square107x107Logo.png
  18. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/Square142x142Logo.png
  19. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/Square150x150Logo.png
  20. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/Square284x284Logo.png
  21. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/Square30x30Logo.png
  22. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/Square310x310Logo.png
  23. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/Square44x44Logo.png
  24. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/Square71x71Logo.png
  25. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/Square89x89Logo.png
  26. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/StoreLogo.png
  27. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/icon.icns
  28. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/icon.ico
  29. 0 0
      tooling/cli.rs/templates/app/src-tauri/icons/icon.png
  30. 0 0
      tooling/cli.rs/templates/app/src-tauri/rustfmt.toml
  31. 0 0
      tooling/cli.rs/templates/app/src-tauri/src/main.rs
  32. 0 0
      tooling/cli.rs/templates/app/src-tauri/tauri.conf.json
  33. 16 0
      tooling/cli.rs/templates/plugin/backend/.changes/config.json
  34. 16 0
      tooling/cli.rs/templates/plugin/backend/.changes/readme.md
  35. 28 0
      tooling/cli.rs/templates/plugin/backend/.github/workflows/audit.yml
  36. 17 0
      tooling/cli.rs/templates/plugin/backend/.github/workflows/covector-status.yml
  37. 39 0
      tooling/cli.rs/templates/plugin/backend/.github/workflows/covector-version-or-publish.yml
  38. 32 0
      tooling/cli.rs/templates/plugin/backend/.github/workflows/format.yml
  39. 37 0
      tooling/cli.rs/templates/plugin/backend/.github/workflows/lint.yml
  40. 82 0
      tooling/cli.rs/templates/plugin/backend/.github/workflows/test.yml
  41. 2 0
      tooling/cli.rs/templates/plugin/backend/.gitignore
  42. 9 0
      tooling/cli.rs/templates/plugin/backend/Cargo.crate-manifest
  43. 1 0
      tooling/cli.rs/templates/plugin/backend/README.md
  44. 1 0
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/.gitignore
  45. 14 0
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/package.json
  46. 9 0
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/public/index.html
  47. 4 0
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/.gitignore
  48. 20 0
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/Cargo.crate-manifest
  49. 3 0
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/build.rs
  50. BIN
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/icons/128x128.png
  51. BIN
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/icons/128x128@2x.png
  52. BIN
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/icons/32x32.png
  53. BIN
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/icons/icon.icns
  54. BIN
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/icons/icon.ico
  55. BIN
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/icons/icon.png
  56. 14 0
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/rustfmt.toml
  57. 11 0
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/src/main.rs
  58. 65 0
      tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/tauri.conf.json
  59. 10 0
      tooling/cli.rs/templates/plugin/backend/src/lib.rs
  60. 16 0
      tooling/cli.rs/templates/plugin/with-api/.changes/config.json
  61. 16 0
      tooling/cli.rs/templates/plugin/with-api/.changes/readme.md
  62. 28 0
      tooling/cli.rs/templates/plugin/with-api/.github/workflows/audit.yml
  63. 37 0
      tooling/cli.rs/templates/plugin/with-api/.github/workflows/clippy.yml
  64. 39 0
      tooling/cli.rs/templates/plugin/with-api/.github/workflows/covector-version-or-publish.yml
  65. 32 0
      tooling/cli.rs/templates/plugin/with-api/.github/workflows/format.yml
  66. 82 0
      tooling/cli.rs/templates/plugin/with-api/.github/workflows/test.yml
  67. 13 0
      tooling/cli.rs/templates/plugin/with-api/.gitignore
  68. 13 0
      tooling/cli.rs/templates/plugin/with-api/Cargo.crate-manifest
  69. 1 0
      tooling/cli.rs/templates/plugin/with-api/README.md
  70. 3 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/.gitignore
  71. 32 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/package.json
  72. BIN
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/public/favicon.png
  73. 63 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/public/global.css
  74. 20 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/public/index.html
  75. 83 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/rollup.config.js
  76. 10 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/.gitignore
  77. 20 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/Cargo.crate-manifest
  78. 3 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/build.rs
  79. BIN
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/icons/128x128.png
  80. BIN
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/icons/128x128@2x.png
  81. BIN
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/icons/32x32.png
  82. BIN
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/icons/icon.icns
  83. BIN
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/icons/icon.ico
  84. BIN
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/icons/icon.png
  85. 13 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/rustfmt.toml
  86. 12 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/src/main.rs
  87. 53 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/tauri.conf.json
  88. 17 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src/App.svelte
  89. 8 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src/main.ts
  90. 6 0
      tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/tsconfig.json
  91. 26 0
      tooling/cli.rs/templates/plugin/with-api/package.json
  92. 65 0
      tooling/cli.rs/templates/plugin/with-api/src/lib.rs
  93. 1 0
      tooling/cli.rs/templates/plugin/with-api/webview-dist/index.d.ts
  94. 28 0
      tooling/cli.rs/templates/plugin/with-api/webview-dist/index.js
  95. 66 0
      tooling/cli.rs/templates/plugin/with-api/webview-src/.gitignore
  96. 5 0
      tooling/cli.rs/templates/plugin/with-api/webview-src/index.ts
  97. 21 0
      tooling/cli.rs/templates/plugin/with-api/webview-src/rollup.config.js
  98. 16 0
      tooling/cli.rs/templates/plugin/with-api/webview-src/tsconfig.json

+ 5 - 0
.changes/plugin-command.md

@@ -0,0 +1,5 @@
+---
+"cli.rs": patch
+---
+
+Added `$ tauri init plugin` command, which initializes a Tauri plugin.

+ 80 - 25
docs/api/cli.md

@@ -29,17 +29,50 @@ This command is pretty helpful when you need to have a quick overview of your ap
 <Command name="init" />
 
 ```
-  Description
-    Inits the Tauri template. If Tauri cannot find the src-tauri/tauri.conf.json
-    it will create one.
-  Usage
-    $ tauri init
-  Options
-    --help, -h        Displays this message
-    --force, -f       Force init to overwrite [conf|template|all]
-    --log, -l         Logging [boolean]
-    --directory, -d   Set target directory for init
-    --tauriPath, -t   Path of the Tauri project to use (relative to the cwd)
+Initializes a Tauri project
+
+USAGE:
+    cargo tauri init [FLAGS] [OPTIONS] [SUBCOMMAND]
+
+FLAGS:
+        --ci         Skip prompting for values
+    -f, --force      Force init to overwrite the src-tauri folder
+    -h, --help       Print help information
+    -l, --log        Enables logging
+    -V, --version    Print version information
+
+OPTIONS:
+    -A, --app-name <app-name>            Name of your Tauri application
+    -d, --directory <directory>          Set target directory for init
+    -D, --dist-dir <dist-dir>            Web assets location, relative to <project-dir>/src-tauri
+    -P, --dev-path <dev-path>            Url of your dev server
+    -t, --tauri-path <tauri-path>        Path of the Tauri project to use (relative to the cwd)
+    -W, --window-title <window-title>    Window title of your Tauri application
+
+SUBCOMMANDS:
+    help      Print this message or the help of the given subcommand(s)
+    plugin    Initialize a Tauri plugin.
+```
+
+### `init plugin`
+
+<Command name="init plugin" />
+
+```
+Initializes a Tauri plugin project.
+
+USAGE:
+    cargo tauri init plugin [FLAGS] [OPTIONS] --name <name>
+
+FLAGS:
+    -a, --api        Initializes a Tauri plugin with TypeScript API.
+    -h, --help       Print help information
+    -V, --version    Print version information
+
+OPTIONS:
+    -d, --directory <directory>      Set target directory for init
+    -n, --name <name>                Name of your Tauri plugin
+    -t, --tauri-path <tauri-path>    Path of the Tauri project to use (relative to the cwd)
 ```
 
 ## `dev`
@@ -47,12 +80,25 @@ This command is pretty helpful when you need to have a quick overview of your ap
 <Command name="dev" />
 
 ```
-  Description
-    Tauri dev.
-  Usage
-    $ tauri dev
-  Options
-    --help, -h     Displays this message
+Tauri dev.
+
+USAGE:
+    cargo tauri dev [FLAGS] [OPTIONS] [--] [args]...
+
+ARGS:
+    <args>...    Args passed to the binary
+
+FLAGS:
+    -e, --exit-on-panic    Exit on panic
+    -h, --help             Print help information
+        --release          Run the code in release mode
+    -V, --version          Print version information
+
+OPTIONS:
+    -c, --config <config>           config JSON to merge with tauri.conf.json
+    -f, --features <features>...    list of cargo features to activate
+    -r, --runner <runner>           binary to use to run the application
+    -t, --target <target>...        target triple to build against
 ```
 
 This command will open the WebView in development mode. It makes use of the `build.devPath` property from your `src-tauri/tauri.conf.json` file.
@@ -83,13 +129,23 @@ If you're not using `build.beforeDevCommand`, make sure your `build.devPath` is
 <Command name="build" />
 
 ```
-  Description
-    Tauri build.
-  Usage
-    $ tauri build
-  Options
-    --help, -h     Displays this message
-    --debug, -d    Build a tauri app with debugging
+Tauri build.
+
+USAGE:
+    cargo tauri build [FLAGS] [OPTIONS]
+
+FLAGS:
+    -d, --debug      Builds with the debug flag
+    -h, --help       Print help information
+    -v, --verbose    Enables verbose logging
+    -V, --version    Print version information
+
+OPTIONS:
+    -b, --bundle <bundle>...        list of bundles to package
+    -c, --config <config>           config JSON to merge with tauri.conf.json
+    -f, --features <features>...    list of cargo features to activate
+    -r, --runner <runner>           binary to use to build the application
+    -t, --target <target>...        target triple to build against
 ```
 
 This command will bundle your application, either in production mode or debug mode if you used the `--debug` flag. It makes use of the `build.distDir` property from your `src-tauri/tauri.conf.json` file.
@@ -133,4 +189,3 @@ This command will show the current version of Tauri.
 ## CLI usage
 
 See more about the usage through this [complete guide](/docs/usage/development/integration).
-

+ 9 - 7
docs/usage/guides/plugin.md

@@ -5,9 +5,8 @@ title: Write Tauri Plugins
 import Alert from '@theme/Alert'
 
 <Alert title="Note" icon="info-alt">
-Tauri will soon offer Plugin starter kits so the process of writing a Plugin crate will be simplified.
-
-For now it's recommended to follow the [official Tauri plugins](#official-tauri-plugins).
+The Tauri CLI can bootstrap a Plugin project with the `$ tauri init plugin --name your-plugin-name` command.
+It setups the recommended folder structure, optionally adding a TypeScript API wrapper with the `--api` flag.
 </Alert>
 
 Plugins allow you to hook into the Tauri application lifecycle and introduce new commands.
@@ -94,7 +93,10 @@ fn main() {
 
 ## Official Tauri Plugins
 
-- [Stronghold (WIP)](https://github.com/tauri-apps/tauri-plugin-stronghold)
-- [Authenticator (WIP)](https://github.com/tauri-apps/tauri-plugin-authenticator)
-- [Logging (WIP)](https://github.com/tauri-apps/tauri-plugin-log)
-- [SQL (WIP)](https://github.com/tauri-apps/tauri-plugin-sql)
+- [Stronghold](https://github.com/tauri-apps/tauri-plugin-stronghold)
+- [Authenticator](https://github.com/tauri-apps/tauri-plugin-authenticator)
+- [Logging](https://github.com/tauri-apps/tauri-plugin-log)
+- [SQL](https://github.com/tauri-apps/tauri-plugin-sql)
+- [WebSocket](https://github.com/tauri-apps/tauri-plugin-websocket)
+- [Restoring window state](https://github.com/tauri-apps/tauri-plugin-window-state)
+- [Store](https://github.com/tauri-apps/tauri-plugin-store)

+ 1 - 3
tooling/cli.rs/Cargo.toml

@@ -47,14 +47,12 @@ unicode-width = "0.1"
 tempfile = "3"
 zeroize = "1.4"
 glob = "0.3"
+heck = "0.3"
 
 [target."cfg(windows)".dependencies]
 winapi = { version = "0.3", features = [ "winbase", "winuser", "consoleapi", "processenv", "wincon" ] }
 encode_unicode = "0.3"
 
-[target."cfg(target_os = \"linux\")".dependencies]
-heck = "0.3"
-
 [target."cfg(target_os = \"linux\")".build-dependencies]
 heck = "0.3"
 

+ 25 - 1
tooling/cli.rs/src/cli.yml

@@ -128,7 +128,7 @@ subcommands:
   - info:
       about: Shows information about Tauri dependencies
   - init:
-      about: Initializes a Tauri project
+      about: Initializes a Tauri project.
       args:
           - ci:
               long: ci
@@ -171,3 +171,27 @@ subcommands:
               long: dev-path
               about: Url of your dev server
               takes_value: true
+      subcommands:
+        - plugin:
+            about: Initializes a Tauri plugin project.
+            args:
+                - name:
+                    short: n
+                    long: name
+                    about: Name of your Tauri plugin
+                    takes_value: true
+                    required: true
+                - directory:
+                    short: d
+                    long: directory
+                    about: Set target directory for init
+                    takes_value: true
+                - tauri-path:
+                    short: t
+                    long: tauri-path
+                    about: Path of the Tauri project to use (relative to the cwd)
+                    takes_value: true
+                - api:
+                    short: a
+                    long: api
+                    about: Initializes a Tauri plugin with TypeScript API.

+ 11 - 0
tooling/cli.rs/src/helpers/mod.rs

@@ -7,6 +7,7 @@ pub mod config;
 pub mod framework;
 mod logger;
 pub mod manifest;
+pub mod template;
 pub mod updater_signature;
 
 pub use logger::Logger;
@@ -14,6 +15,7 @@ pub use logger::Logger;
 use std::{
   collections::HashMap,
   io::{BufRead, BufReader},
+  path::{Path, PathBuf},
   process::{Command, Stdio},
 };
 
@@ -55,3 +57,12 @@ pub fn command_env() -> HashMap<String, String> {
 
   map
 }
+
+pub fn resolve_tauri_path<P: AsRef<Path>>(path: P, crate_name: &str) -> PathBuf {
+  let path = path.as_ref();
+  if path.is_absolute() {
+    path.join(crate_name)
+  } else {
+    PathBuf::from("..").join(path).join(crate_name)
+  }
+}

+ 44 - 0
tooling/cli.rs/src/helpers/template.rs

@@ -0,0 +1,44 @@
+// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-License-Identifier: MIT
+
+use std::{
+  collections::BTreeMap,
+  fs::{create_dir_all, File},
+  io::Write,
+  path::Path,
+};
+
+use handlebars::Handlebars;
+use include_dir::Dir;
+
+pub fn render<P: AsRef<Path>>(
+  handlebars: &Handlebars,
+  data: &BTreeMap<&str, serde_json::Value>,
+  dir: &Dir,
+  out_dir: P,
+) -> crate::Result<()> {
+  create_dir_all(out_dir.as_ref().join(dir.path()))?;
+  for file in dir.files() {
+    let mut file_path = file.path().to_path_buf();
+    // cargo for some reason ignores the /templates folder packaging when it has a Cargo.toml file inside
+    // so we rename the extension to `.crate-manifest`
+    if let Some(extension) = file_path.extension() {
+      if extension == "crate-manifest" {
+        file_path.set_extension("toml");
+      }
+    }
+    let mut output_file = File::create(out_dir.as_ref().join(file_path))?;
+    if let Some(utf8) = file.contents_utf8() {
+      handlebars
+        .render_template_to_write(utf8, &data, &mut output_file)
+        .expect("Failed to render template");
+    } else {
+      output_file.write_all(file.contents())?;
+    }
+  }
+  for dir in dir.dirs() {
+    render(handlebars, data, dir, out_dir.as_ref())?;
+  }
+  Ok(())
+}

+ 8 - 59
tooling/cli.rs/src/init.rs

@@ -2,28 +2,17 @@
 // SPDX-License-Identifier: Apache-2.0
 // SPDX-License-Identifier: MIT
 
-use std::{
-  collections::BTreeMap,
-  env::current_dir,
-  fs::{create_dir_all, remove_dir_all, File},
-  io::Write,
-  path::{Path, PathBuf},
-};
+use std::{collections::BTreeMap, env::current_dir, fs::remove_dir_all, path::PathBuf};
 
-use crate::helpers::Logger;
+use crate::{
+  helpers::{resolve_tauri_path, template, Logger},
+  VersionMetadata,
+};
 use anyhow::Context;
 use handlebars::{to_json, Handlebars};
 use include_dir::{include_dir, Dir};
-use serde::Deserialize;
 
-const TEMPLATE_DIR: Dir = include_dir!("templates");
-
-#[derive(Deserialize)]
-struct VersionMetadata {
-  tauri: String,
-  #[serde(rename = "tauri-build")]
-  tauri_build: String,
-}
+const TEMPLATE_DIR: Dir = include_dir!("templates/app");
 
 pub struct Init {
   force: bool,
@@ -95,7 +84,7 @@ impl Init {
     let metadata = serde_json::from_str::<VersionMetadata>(include_str!("../metadata.json"))?;
     if template_target_path.exists() && !self.force {
       logger.warn(format!(
-        "Tauri dir ({:?}) not empty. Run `init --force template` to overwrite.",
+        "Tauri dir ({:?}) not empty. Run `init --force` to overwrite.",
         template_target_path
       ));
     } else {
@@ -144,50 +133,10 @@ impl Init {
         to_json(self.window_title.unwrap_or_else(|| "Tauri".to_string())),
       );
 
-      render_template(&handlebars, &data, &TEMPLATE_DIR, &self.directory)
+      template::render(&handlebars, &data, &TEMPLATE_DIR, &self.directory)
         .with_context(|| "failed to render Tauri template")?;
     }
 
     Ok(())
   }
 }
-
-fn render_template<P: AsRef<Path>>(
-  handlebars: &Handlebars,
-  data: &BTreeMap<&str, serde_json::Value>,
-  dir: &Dir,
-  out_dir: P,
-) -> crate::Result<()> {
-  create_dir_all(out_dir.as_ref().join(dir.path()))?;
-  for file in dir.files() {
-    let mut file_path = file.path().to_path_buf();
-    // cargo for some reason ignores the /templates folder packaging when it has a Cargo.toml file inside
-    // so we rename the extension to `.crate-manifest`
-    if let Some(extension) = file_path.extension() {
-      if extension == "crate-manifest" {
-        file_path.set_extension("toml");
-      }
-    }
-    let mut output_file = File::create(out_dir.as_ref().join(file_path))?;
-    if let Some(utf8) = file.contents_utf8() {
-      handlebars
-        .render_template_to_write(utf8, &data, &mut output_file)
-        .expect("Failed to render template");
-    } else {
-      output_file.write_all(file.contents())?;
-    }
-  }
-  for dir in dir.dirs() {
-    render_template(handlebars, data, dir, out_dir.as_ref())?;
-  }
-  Ok(())
-}
-
-fn resolve_tauri_path<P: AsRef<Path>>(path: P, crate_name: &str) -> PathBuf {
-  let path = path.as_ref();
-  if path.is_absolute() {
-    path.join(crate_name)
-  } else {
-    PathBuf::from("..").join(path).join(crate_name)
-  }
-}

+ 34 - 1
tooling/cli.rs/src/main.rs

@@ -13,6 +13,7 @@ mod helpers;
 mod info;
 mod init;
 mod interface;
+mod plugin;
 mod sign;
 
 // temporary fork from https://github.com/mitsuhiko/console until 0.14.1+ release
@@ -26,6 +27,13 @@ use helpers::framework::{infer_from_package_json as infer_framework, Framework};
 
 use std::{env::current_dir, fs::read_to_string, path::PathBuf};
 
+#[derive(Deserialize)]
+pub struct VersionMetadata {
+  tauri: String,
+  #[serde(rename = "tauri-build")]
+  tauri_build: String,
+}
+
 #[derive(Deserialize)]
 struct PackageJson {
   name: Option<String>,
@@ -56,6 +64,27 @@ macro_rules! value_or_prompt {
   }};
 }
 
+fn plugin_command(matches: &ArgMatches) -> Result<()> {
+  let api = matches.is_present("api");
+  let plugin_name = matches.value_of("name").expect("name is required");
+  let directory = matches.value_of("directory");
+  let tauri_path = matches.value_of("tauri-path");
+
+  let mut plugin_runner = plugin::Plugin::new().plugin_name(plugin_name.to_string());
+
+  if api {
+    plugin_runner = plugin_runner.api();
+  }
+  if let Some(directory) = directory {
+    plugin_runner = plugin_runner.directory(directory);
+  }
+  if let Some(tauri_path) = tauri_path {
+    plugin_runner = plugin_runner.tauri_path(tauri_path);
+  }
+
+  plugin_runner.run()
+}
+
 fn init_command(matches: &ArgMatches) -> Result<()> {
   let force = matches.is_present("force");
   let directory = matches.value_of("directory");
@@ -270,7 +299,11 @@ fn main() -> Result<()> {
   let matches = app.get_matches();
 
   if let Some(matches) = matches.subcommand_matches("init") {
-    init_command(matches)?;
+    if let Some(matches) = matches.subcommand_matches("plugin") {
+      plugin_command(matches)?;
+    } else {
+      init_command(matches)?;
+    }
   } else if let Some(matches) = matches.subcommand_matches("dev") {
     dev_command(matches)?;
   } else if let Some(matches) = matches.subcommand_matches("build") {

+ 120 - 0
tooling/cli.rs/src/plugin.rs

@@ -0,0 +1,120 @@
+// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-License-Identifier: MIT
+
+use crate::{
+  helpers::{resolve_tauri_path, template, Logger},
+  VersionMetadata,
+};
+use anyhow::Context;
+use handlebars::{to_json, Handlebars};
+use heck::{KebabCase, SnakeCase};
+use include_dir::{include_dir, Dir};
+
+use std::{collections::BTreeMap, env::current_dir, fs::remove_dir_all, path::PathBuf};
+
+const BACKEND_PLUGIN_DIR: Dir = include_dir!("templates/plugin/backend");
+const API_PLUGIN_DIR: Dir = include_dir!("templates/plugin/with-api");
+
+pub struct Plugin {
+  plugin_name: String,
+  api: bool,
+  directory: PathBuf,
+  tauri_path: Option<PathBuf>,
+}
+
+impl Default for Plugin {
+  fn default() -> Self {
+    Self {
+      plugin_name: "".into(),
+      api: false,
+      directory: current_dir().expect("failed to read cwd"),
+      tauri_path: None,
+    }
+  }
+}
+
+impl Plugin {
+  pub fn new() -> Self {
+    Default::default()
+  }
+
+  pub fn plugin_name(mut self, plugin_name: String) -> Self {
+    self.plugin_name = plugin_name;
+    self
+  }
+
+  pub fn api(mut self) -> Self {
+    self.api = true;
+    self
+  }
+
+  pub fn directory(mut self, directory: impl Into<PathBuf>) -> Self {
+    self.directory = directory.into();
+    self
+  }
+
+  pub fn tauri_path(mut self, tauri_path: impl Into<PathBuf>) -> Self {
+    self.tauri_path = Some(tauri_path.into());
+    self
+  }
+
+  pub fn run(self) -> crate::Result<()> {
+    let logger = Logger::new("tauri:init:plugin");
+    let template_target_path = self.directory.join(&format!(
+      "tauri-plugin-{}",
+      self.plugin_name.to_kebab_case()
+    ));
+    let metadata = serde_json::from_str::<VersionMetadata>(include_str!("../metadata.json"))?;
+    if template_target_path.exists() {
+      logger.warn(format!(
+        "Plugin dir ({:?}) not empty.",
+        template_target_path
+      ));
+    } else {
+      let (tauri_dep, tauri_build_dep) = if let Some(tauri_path) = self.tauri_path {
+        (
+          format!(
+            "{{  path = {:?} }}",
+            resolve_tauri_path(&tauri_path, "core/tauri")
+          ),
+          format!(
+            "{{  path = {:?} }}",
+            resolve_tauri_path(&tauri_path, "core/tauri-build")
+          ),
+        )
+      } else {
+        (
+          format!(r#"{{ version = "{}" }}"#, metadata.tauri),
+          format!(r#"{{ version = "{}" }}"#, metadata.tauri_build),
+        )
+      };
+
+      let _ = remove_dir_all(&template_target_path);
+      let handlebars = Handlebars::new();
+
+      let mut data = BTreeMap::new();
+      data.insert("plugin_name_original", to_json(&self.plugin_name));
+      data.insert("plugin_name", to_json(self.plugin_name.to_kebab_case()));
+      data.insert(
+        "plugin_name_snake_case",
+        to_json(self.plugin_name.to_snake_case()),
+      );
+      data.insert("tauri_dep", to_json(tauri_dep));
+      data.insert("tauri_build_dep", to_json(tauri_build_dep));
+
+      template::render(
+        &handlebars,
+        &data,
+        if self.api {
+          &API_PLUGIN_DIR
+        } else {
+          &BACKEND_PLUGIN_DIR
+        },
+        &template_target_path,
+      )
+      .with_context(|| "failed to render Tauri template")?;
+    }
+    Ok(())
+  }
+}

+ 0 - 0
tooling/cli.rs/templates/src-tauri/.gitignore → tooling/cli.rs/templates/app/src-tauri/.gitignore


+ 0 - 0
tooling/cli.rs/templates/src-tauri/Cargo.crate-manifest → tooling/cli.rs/templates/app/src-tauri/Cargo.crate-manifest


+ 0 - 0
tooling/cli.rs/templates/src-tauri/build.rs → tooling/cli.rs/templates/app/src-tauri/build.rs


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/128x128.png → tooling/cli.rs/templates/app/src-tauri/icons/128x128.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/128x128@2x.png → tooling/cli.rs/templates/app/src-tauri/icons/128x128@2x.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/32x32.png → tooling/cli.rs/templates/app/src-tauri/icons/32x32.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/Square107x107Logo.png → tooling/cli.rs/templates/app/src-tauri/icons/Square107x107Logo.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/Square142x142Logo.png → tooling/cli.rs/templates/app/src-tauri/icons/Square142x142Logo.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/Square150x150Logo.png → tooling/cli.rs/templates/app/src-tauri/icons/Square150x150Logo.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/Square284x284Logo.png → tooling/cli.rs/templates/app/src-tauri/icons/Square284x284Logo.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/Square30x30Logo.png → tooling/cli.rs/templates/app/src-tauri/icons/Square30x30Logo.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/Square310x310Logo.png → tooling/cli.rs/templates/app/src-tauri/icons/Square310x310Logo.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/Square44x44Logo.png → tooling/cli.rs/templates/app/src-tauri/icons/Square44x44Logo.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/Square71x71Logo.png → tooling/cli.rs/templates/app/src-tauri/icons/Square71x71Logo.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/Square89x89Logo.png → tooling/cli.rs/templates/app/src-tauri/icons/Square89x89Logo.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/StoreLogo.png → tooling/cli.rs/templates/app/src-tauri/icons/StoreLogo.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/icon.icns → tooling/cli.rs/templates/app/src-tauri/icons/icon.icns


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/icon.ico → tooling/cli.rs/templates/app/src-tauri/icons/icon.ico


+ 0 - 0
tooling/cli.rs/templates/src-tauri/icons/icon.png → tooling/cli.rs/templates/app/src-tauri/icons/icon.png


+ 0 - 0
tooling/cli.rs/templates/src-tauri/rustfmt.toml → tooling/cli.rs/templates/app/src-tauri/rustfmt.toml


+ 0 - 0
tooling/cli.rs/templates/src-tauri/src/main.rs → tooling/cli.rs/templates/app/src-tauri/src/main.rs


+ 0 - 0
tooling/cli.rs/templates/src-tauri/tauri.conf.json → tooling/cli.rs/templates/app/src-tauri/tauri.conf.json


+ 16 - 0
tooling/cli.rs/templates/plugin/backend/.changes/config.json

@@ -0,0 +1,16 @@
+{
+  "gitSiteUrl": "https://www.github.com/your-org/tauri-plugin-{{ plugin_name }}/",
+  "pkgManagers": {
+    "rust": {
+      "version": true,
+      "publish": true,
+      "getPublishedVersion": "cargo search ${ pkg.pkg } --limit 1 | sed -nE 's/^[^\"]*\"//; s/\".*//1p' -"
+    }
+  },
+  "packages": {
+    "tauri-plugin-{{ plugin_name }}": {
+      "path": ".",
+      "manager": "rust"
+    }
+  }
+}

+ 16 - 0
tooling/cli.rs/templates/plugin/backend/.changes/readme.md

@@ -0,0 +1,16 @@
+# Changes
+##### via https://github.com/jbolda/covector
+
+As you create PRs and make changes that require a version bump, please add a new markdown file in this folder. You do not note the version *number*, but rather the type of bump that you expect: major, minor, or patch. The filename is not important, as long as it is a `.md`, but we recommend it represents the overall change for our sanity.
+
+When you select the version bump required, you do *not* need to consider depedencies. Only note the package with the actual change, and any packages that depend on that package will be bumped automatically in the process.
+
+Use the following format:
+```md
+---
+"tauri-plugin-{{ plugin_name }}": minor
+---
+
+Change summary goes here
+
+```

+ 28 - 0
tooling/cli.rs/templates/plugin/backend/.github/workflows/audit.yml

@@ -0,0 +1,28 @@
+{{{{raw}}}}
+name: Audit
+
+on:
+  schedule:
+    - cron: '0 0 * * *'
+  push:
+    branches:
+      - main
+    paths:
+      - "**/Cargo.lock"
+      - "**/Cargo.toml"
+  pull_request:
+    branches:
+      - main
+    paths:
+      - "**/Cargo.lock"
+      - "**/Cargo.toml"
+
+jobs:
+  audit:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/audit-check@v1
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+{{{{/raw}}}}

+ 17 - 0
tooling/cli.rs/templates/plugin/backend/.github/workflows/covector-status.yml

@@ -0,0 +1,17 @@
+{{{{raw}}}}
+name: covector status
+on: [pull_request]
+
+jobs:
+  covector:
+    runs-on: ubuntu-latest
+
+    steps:
+      - uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
+      - name: covector status
+        uses: jbolda/covector/packages/action@covector-v0
+        with:
+          command: 'status'
+{{{{/raw}}}}

+ 39 - 0
tooling/cli.rs/templates/plugin/backend/.github/workflows/covector-version-or-publish.yml

@@ -0,0 +1,39 @@
+{{{{raw}}}}
+name: covector version or publish
+on:
+  push:
+    branches:
+    - dev
+
+jobs:
+  covector:
+    runs-on: ubuntu-latest
+
+    steps:
+      - uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
+      - uses: actions/setup-node@v1
+        with:
+          node-version: 12
+          registry-url: 'https://registry.npmjs.org'
+      - name: git config
+        run: |
+          git config --global user.name "${{ github.event.pusher.name }}"
+          git config --global user.email "${{ github.event.pusher.email }}"
+      - name: covector version-or-publish
+        uses: jbolda/covector/packages/action@covector-v0
+        id: covector
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          command: 'version-or-publish'
+          createRelease: true
+      - name: create pull request
+        id: cpr
+        uses: tauri-apps/create-pull-request@v2.8.0
+        with:
+          title: "Publish New Versions"
+          labels: "version updates"
+          branch: "release"
+          body: ${{ steps.covector.outputs.change }}
+{{{{/raw}}}}

+ 32 - 0
tooling/cli.rs/templates/plugin/backend/.github/workflows/format.yml

@@ -0,0 +1,32 @@
+{{{{raw}}}}
+name: Format
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+      - dev
+
+jobs:
+  format:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install rustfmt with nightly toolchain
+      uses: actions-rs/toolchain@v1
+      with:
+          profile: minimal
+          toolchain: nightly
+          override: true
+          components: rustfmt
+    - uses: actions-rs/cargo@v1
+      with:
+        command: fmt
+        args: --manifest-path=Cargo.toml --all -- --check
+{{{{/raw}}}}

+ 37 - 0
tooling/cli.rs/templates/plugin/backend/.github/workflows/lint.yml

@@ -0,0 +1,37 @@
+{{{{raw}}}}
+name: Clippy
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+      - dev
+
+jobs:
+  clippy:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+
+    steps:
+      - uses: actions/checkout@v2
+      - name: install webkit2gtk
+        run: |
+          sudo apt-get update
+          sudo apt-get install -y webkit2gtk-4.0
+      - name: Install clippy with stable toolchain
+        uses: actions-rs/toolchain@v1
+        with:
+            profile: minimal
+            toolchain: stable
+            override: true
+            components: clippy
+      - uses: actions-rs/clippy-check@v1
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          args: --manifest-path=Cargo.toml --all-targets --all-features -- -D warnings
+          name: clippy
+{{{{/raw}}}}

+ 82 - 0
tooling/cli.rs/templates/plugin/backend/.github/workflows/test.yml

@@ -0,0 +1,82 @@
+{{{{raw}}}}
+name: Test
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+      - dev
+    paths-ignore:
+      - 'webview-src/**'
+      - 'webview-dist/**'
+      - 'examples/**'
+
+jobs:
+  build-and-test:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ubuntu-latest, macos-latest, windows-latest]
+
+    steps:
+    - uses: actions/checkout@v2
+
+    - name: Install stable toolchain
+      uses: actions-rs/toolchain@v1
+      with:
+        toolchain: stable
+        override: true
+    
+    - name: Install gtk on Ubuntu
+      if: matrix.os == 'ubuntu-latest'
+      run: |
+        sudo apt-get update
+        sudo apt-get install -y webkit2gtk-4.0
+    - name: Get current date
+      if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
+      run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
+
+    - name: Get current date
+      if: matrix.os == 'windows-latest'
+      run: echo "CURRENT_DATE=$(Get-Date -Format "yyyy-MM-dd")" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
+
+    - name: Cache cargo registry
+      uses: actions/cache@v2
+      with:
+        path: ~/.cargo/registry
+        # Add date to the cache to keep it up to date
+        key: ${{ matrix.os }}-${{ matrix.rust }}-cargo-registry-${{ hashFiles('**/Cargo.toml') }}-${{ env.CURRENT_DATE }}
+        # Restore from outdated cache for speed
+        restore-keys: |
+          ${{ matrix.os }}-${{ matrix.rust }}-cargo-registry-${{ hashFiles('**/Cargo.toml') }}
+
+    - name: Cache cargo index
+      uses: actions/cache@v2
+      with:
+        path: ~/.cargo/git
+        # Add date to the cache to keep it up to date
+        key: ${{ matrix.os }}-${{ matrix.rust }}-cargo-index-${{ hashFiles('**/Cargo.toml') }}-${{ env.CURRENT_DATE }}
+        # Restore from outdated cache for speed
+        restore-keys: |
+          ${{ matrix.os }}-${{ matrix.rust }}-cargo-index-${{ hashFiles('**/Cargo.toml') }}
+
+    - name: Cache cargo target
+      uses: actions/cache@v2
+      with:
+        path: ${{ matrix.project}}/target
+        # Add date to the cache to keep it up to date
+        key: ${{ matrix.os }}-${{ matrix.rust }}-cargo-build-target-${{ hashFiles('**/Cargo.toml') }}-${{ env.CURRENT_DATE }}
+        # Restore from outdated cache for speed
+        restore-keys: |
+          ${{ matrix.os }}-${{ matrix.rust }}-cargo-build-target-${{ hashFiles('**/Cargo.toml') }}
+
+    - name: Run tests 
+      uses: actions-rs/cargo@v1
+      with:
+        command: test
+        args: --manifest-path=Cargo.toml --release
+{{{{/raw}}}}

+ 2 - 0
tooling/cli.rs/templates/plugin/backend/.gitignore

@@ -0,0 +1,2 @@
+/target
+/Cargo.lock

+ 9 - 0
tooling/cli.rs/templates/plugin/backend/Cargo.crate-manifest

@@ -0,0 +1,9 @@
+[package]
+name = "tauri-plugin-{{ plugin_name }}"
+version = "0.1.0"
+authors = [ "You" ]
+description = ""
+edition = "2018"
+
+[dependencies]
+tauri = {{{  tauri_dep  }}}

+ 1 - 0
tooling/cli.rs/templates/plugin/backend/README.md

@@ -0,0 +1 @@
+# Tauri Plugin {{ plugin_name_original }}

+ 1 - 0
tooling/cli.rs/templates/plugin/backend/examples/vanilla/.gitignore

@@ -0,0 +1 @@
+node_modules/

+ 14 - 0
tooling/cli.rs/templates/plugin/backend/examples/vanilla/package.json

@@ -0,0 +1,14 @@
+{
+  "name": "app",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "MIT",
+  "dependencies": {
+    "@tauri-apps/cli": "^1.0.0-beta.10"
+  }
+}

+ 9 - 0
tooling/cli.rs/templates/plugin/backend/examples/vanilla/public/index.html

@@ -0,0 +1,9 @@
+<html>
+
+<body>
+  <div>
+    Plugin example
+  </div>
+</body>
+
+</html>

+ 4 - 0
tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/.gitignore

@@ -0,0 +1,4 @@
+# Generated by Cargo
+# will have compiled files and executables
+/target/
+WixTools

+ 20 - 0
tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/Cargo.crate-manifest

@@ -0,0 +1,20 @@
+[package]
+name = "app"
+version = "0.1.0"
+description = "A Tauri App"
+authors = [ "You" ]
+repository = ""
+edition = "2018"
+
+[dependencies]
+serde_json = "1.0"
+serde = { version = "1.0", features = [ "derive" ] }
+tauri = {{{  tauri_dep  }}}
+tauri-plugin-{{ plugin_name }} = { path = "../../../" }
+
+[build-dependencies]
+tauri-build = {{{  tauri_build_dep  }}}
+
+[features]
+default = [ "custom-protocol" ]
+custom-protocol = [ "tauri/custom-protocol" ]

+ 3 - 0
tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/build.rs

@@ -0,0 +1,3 @@
+fn main() {
+  tauri_build::build()
+}

BIN
tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/icons/128x128.png


BIN
tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/icons/128x128@2x.png


BIN
tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/icons/32x32.png


BIN
tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/icons/icon.icns


BIN
tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/icons/icon.ico


BIN
tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/icons/icon.png


+ 14 - 0
tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/rustfmt.toml

@@ -0,0 +1,14 @@
+max_width = 100
+hard_tabs = false
+tab_spaces = 2
+newline_style = "Auto"
+use_small_heuristics = "Default"
+reorder_imports = true
+reorder_modules = true
+remove_nested_parens = true
+edition = "2018"
+merge_derives = true
+use_try_shorthand = false
+use_field_init_shorthand = false
+force_explicit_abi = true
+imports_granularity = "Crate"

+ 11 - 0
tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/src/main.rs

@@ -0,0 +1,11 @@
+#![cfg_attr(
+  all(not(debug_assertions), target_os = "windows"),
+  windows_subsystem = "windows"
+)]
+
+fn main() {
+  tauri::Builder::default()
+    .plugin(tauri_plugin_{{ plugin_name_snake_case }}::YourPlugin::default())
+    .run(tauri::generate_context!())
+    .expect("error while running tauri application");
+}

+ 65 - 0
tooling/cli.rs/templates/plugin/backend/examples/vanilla/src-tauri/tauri.conf.json

@@ -0,0 +1,65 @@
+{
+  "package": {
+    "productName": "app",
+    "version": "0.1.0"
+  },
+  "build": {
+    "distDir": "../public",
+    "devPath": "../public"
+  },
+  "tauri": {
+    "bundle": {
+      "active": true,
+      "targets": "all",
+      "identifier": "com.tauri.{{ plugin_name }}",
+      "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": [],
+        "useBootstrapper": false
+      },
+      "macOS": {
+        "frameworks": [],
+        "minimumSystemVersion": "",
+        "useBootstrapper": false,
+        "exceptionDomain": "",
+        "signingIdentity": null,
+        "entitlements": null
+      },
+      "windows": {
+        "certificateThumbprint": null,
+        "digestAlgorithm": "sha256",
+        "timestampUrl": ""
+      }
+    },
+    "updater": {
+      "active": false
+    },
+    "allowlist": {
+      "all": true
+    },
+    "windows": [
+      {
+        "title": "app",
+        "width": 800,
+        "height": 600,
+        "resizable": true,
+        "fullscreen": false
+      }
+    ],
+    "security": {
+      "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'"
+    }
+  }
+}

+ 10 - 0
tooling/cli.rs/templates/plugin/backend/src/lib.rs

@@ -0,0 +1,10 @@
+use tauri::{plugin::Plugin, Runtime};
+
+#[derive(Default)]
+pub struct YourPlugin {}
+
+impl<R: Runtime> Plugin<R> for YourPlugin {
+  fn name(&self) -> &'static str {
+    "{{ plugin_name }}"
+  }
+}

+ 16 - 0
tooling/cli.rs/templates/plugin/with-api/.changes/config.json

@@ -0,0 +1,16 @@
+{
+  "gitSiteUrl": "https://www.github.com/your-org/tauri-plugin-{{ plugin_name }}/",
+  "pkgManagers": {
+    "rust": {
+      "version": true,
+      "publish": true,
+      "getPublishedVersion": "cargo search ${ pkg.pkg } --limit 1 | sed -nE 's/^[^\"]*\"//; s/\".*//1p' -"
+    }
+  },
+  "packages": {
+    "tauri-plugin-{{ plugin_name }}": {
+      "path": ".",
+      "manager": "rust"
+    }
+  }
+}

+ 16 - 0
tooling/cli.rs/templates/plugin/with-api/.changes/readme.md

@@ -0,0 +1,16 @@
+# Changes
+##### via https://github.com/jbolda/covector
+
+As you create PRs and make changes that require a version bump, please add a new markdown file in this folder. You do not note the version *number*, but rather the type of bump that you expect: major, minor, or patch. The filename is not important, as long as it is a `.md`, but we recommend it represents the overall change for our sanity.
+
+When you select the version bump required, you do *not* need to consider depedencies. Only note the package with the actual change, and any packages that depend on that package will be bumped automatically in the process.
+
+Use the following format:
+```md
+---
+"tauri-plugin-{{ plugin_name }}": minor
+---
+
+Change summary goes here
+
+```

+ 28 - 0
tooling/cli.rs/templates/plugin/with-api/.github/workflows/audit.yml

@@ -0,0 +1,28 @@
+{{{{raw}}}}
+name: Audit
+
+on:
+  schedule:
+    - cron: '0 0 * * *'
+  push:
+    branches:
+      - main
+    paths:
+      - "**/Cargo.lock"
+      - "**/Cargo.toml"
+  pull_request:
+    branches:
+      - main
+    paths:
+      - "**/Cargo.lock"
+      - "**/Cargo.toml"
+
+jobs:
+  audit:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - uses: actions-rs/audit-check@v1
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+{{{{/raw}}}}

+ 37 - 0
tooling/cli.rs/templates/plugin/with-api/.github/workflows/clippy.yml

@@ -0,0 +1,37 @@
+{{{{raw}}}}
+name: Clippy
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+      - dev
+
+jobs:
+  clippy:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+
+    steps:
+      - uses: actions/checkout@v2
+      - name: install webkit2gtk
+        run: |
+          sudo apt-get update
+          sudo apt-get install -y webkit2gtk-4.0
+      - name: Install clippy with stable toolchain
+        uses: actions-rs/toolchain@v1
+        with:
+            profile: minimal
+            toolchain: stable
+            override: true
+            components: clippy
+      - uses: actions-rs/clippy-check@v1
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          args: --manifest-path=Cargo.toml --all-targets --all-features -- -D warnings
+          name: clippy
+{{{{/raw}}}}

+ 39 - 0
tooling/cli.rs/templates/plugin/with-api/.github/workflows/covector-version-or-publish.yml

@@ -0,0 +1,39 @@
+{{{{raw}}}}
+name: covector version or publish
+on:
+  push:
+    branches:
+    - dev
+
+jobs:
+  covector:
+    runs-on: ubuntu-latest
+
+    steps:
+      - uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
+      - uses: actions/setup-node@v1
+        with:
+          node-version: 12
+          registry-url: 'https://registry.npmjs.org'
+      - name: git config
+        run: |
+          git config --global user.name "${{ github.event.pusher.name }}"
+          git config --global user.email "${{ github.event.pusher.email }}"
+      - name: covector version-or-publish
+        uses: jbolda/covector/packages/action@covector-v0
+        id: covector
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          command: 'version-or-publish'
+          createRelease: true
+      - name: create pull request
+        id: cpr
+        uses: tauri-apps/create-pull-request@v2.8.0
+        with:
+          title: "Publish New Versions"
+          labels: "version updates"
+          branch: "release"
+          body: ${{ steps.covector.outputs.change }}
+{{{{/raw}}}}

+ 32 - 0
tooling/cli.rs/templates/plugin/with-api/.github/workflows/format.yml

@@ -0,0 +1,32 @@
+{{{{raw}}}}
+name: Format
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+      - dev
+
+jobs:
+  format:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install rustfmt with nightly toolchain
+      uses: actions-rs/toolchain@v1
+      with:
+          profile: minimal
+          toolchain: nightly
+          override: true
+          components: rustfmt
+    - uses: actions-rs/cargo@v1
+      with:
+        command: fmt
+        args: --manifest-path=Cargo.toml --all -- --check
+{{{{/raw}}}}

+ 82 - 0
tooling/cli.rs/templates/plugin/with-api/.github/workflows/test.yml

@@ -0,0 +1,82 @@
+{{{{raw}}}}
+name: Test
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+      - dev
+    paths-ignore:
+      - 'webview-src/**'
+      - 'webview-dist/**'
+      - 'examples/**'
+
+jobs:
+  build-and-test:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ubuntu-latest, macos-latest, windows-latest]
+
+    steps:
+    - uses: actions/checkout@v2
+
+    - name: Install stable toolchain
+      uses: actions-rs/toolchain@v1
+      with:
+        toolchain: stable
+        override: true
+    
+    - name: Install gtk on Ubuntu
+      if: matrix.os == 'ubuntu-latest'
+      run: |
+        sudo apt-get update
+        sudo apt-get install -y webkit2gtk-4.0
+    - name: Get current date
+      if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest'
+      run: echo "CURRENT_DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
+
+    - name: Get current date
+      if: matrix.os == 'windows-latest'
+      run: echo "CURRENT_DATE=$(Get-Date -Format "yyyy-MM-dd")" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
+
+    - name: Cache cargo registry
+      uses: actions/cache@v2
+      with:
+        path: ~/.cargo/registry
+        # Add date to the cache to keep it up to date
+        key: ${{ matrix.os }}-${{ matrix.rust }}-cargo-registry-${{ hashFiles('**/Cargo.toml') }}-${{ env.CURRENT_DATE }}
+        # Restore from outdated cache for speed
+        restore-keys: |
+          ${{ matrix.os }}-${{ matrix.rust }}-cargo-registry-${{ hashFiles('**/Cargo.toml') }}
+
+    - name: Cache cargo index
+      uses: actions/cache@v2
+      with:
+        path: ~/.cargo/git
+        # Add date to the cache to keep it up to date
+        key: ${{ matrix.os }}-${{ matrix.rust }}-cargo-index-${{ hashFiles('**/Cargo.toml') }}-${{ env.CURRENT_DATE }}
+        # Restore from outdated cache for speed
+        restore-keys: |
+          ${{ matrix.os }}-${{ matrix.rust }}-cargo-index-${{ hashFiles('**/Cargo.toml') }}
+
+    - name: Cache cargo target
+      uses: actions/cache@v2
+      with:
+        path: ${{ matrix.project}}/target
+        # Add date to the cache to keep it up to date
+        key: ${{ matrix.os }}-${{ matrix.rust }}-cargo-build-target-${{ hashFiles('**/Cargo.toml') }}-${{ env.CURRENT_DATE }}
+        # Restore from outdated cache for speed
+        restore-keys: |
+          ${{ matrix.os }}-${{ matrix.rust }}-cargo-build-target-${{ hashFiles('**/Cargo.toml') }}
+
+    - name: Run tests 
+      uses: actions-rs/cargo@v1
+      with:
+        command: test
+        args: --manifest-path=Cargo.toml --release
+{{{{/raw}}}}

+ 13 - 0
tooling/cli.rs/templates/plugin/with-api/.gitignore

@@ -0,0 +1,13 @@
+/.vs
+.DS_Store
+.Thumbs.db
+*.sublime*
+.idea/
+debug.log
+package-lock.json
+.vscode/settings.json
+yarn.lock
+
+/target
+Cargo.lock
+node_modules/

+ 13 - 0
tooling/cli.rs/templates/plugin/with-api/Cargo.crate-manifest

@@ -0,0 +1,13 @@
+[package]
+name = "tauri-plugin-{{ plugin_name }}"
+version = "0.0.0"
+authors = [ "You" ]
+description = ""
+edition = "2018"
+exclude = ["/examples", "/webview-dist", "/webview-src", "node_modules"]
+
+[dependencies]
+tauri = {{{  tauri_dep }}}
+serde = "1.0"
+serde_json = "1.0"
+thiserror = "1.0"

+ 1 - 0
tooling/cli.rs/templates/plugin/with-api/README.md

@@ -0,0 +1 @@
+# Tauri Plugin {{ plugin_name_original }}

+ 3 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/.gitignore

@@ -0,0 +1,3 @@
+node_modules/
+public/build/
+public/index.tauri.html

+ 32 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/package.json

@@ -0,0 +1,32 @@
+{
+  "name": "svelte-app",
+  "version": "1.0.0",
+  "scripts": {
+    "build": "rollup -c",
+    "dev": "rollup -c -w",
+    "start": "sirv public",
+    "validate": "svelte-check",
+    "tauri": "tauri"
+  },
+  "devDependencies": {
+    "@rollup/plugin-commonjs": "^18.0.0",
+    "@rollup/plugin-node-resolve": "^11.2.0",
+    "@rollup/plugin-typescript": "^8.2.0",
+    "@tauri-apps/cli": "^1.0.0-beta.0",
+    "@tsconfig/svelte": "^1.0.0",
+    "rollup": "^2.45",
+    "rollup-plugin-css-only": "^3.1.0",
+    "rollup-plugin-livereload": "^2.0.0",
+    "rollup-plugin-svelte": "^7.0.0",
+    "rollup-plugin-terser": "^7.0.0",
+    "svelte": "^3.0.0",
+    "svelte-check": "^1.0.0",
+    "svelte-preprocess": "^4.0.0",
+    "tslib": "^2.0.0",
+    "typescript": "^3.9.3"
+  },
+  "dependencies": {
+    "sirv-cli": "^1.0.0",
+    "tauri-plugin-{{ plugin_name }}-api": "link:../../"
+  }
+}

BIN
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/public/favicon.png


+ 63 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/public/global.css

@@ -0,0 +1,63 @@
+html, body {
+	position: relative;
+	width: 100%;
+	height: 100%;
+}
+
+body {
+	color: #333;
+	margin: 0;
+	padding: 8px;
+	box-sizing: border-box;
+	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
+}
+
+a {
+	color: rgb(0,100,200);
+	text-decoration: none;
+}
+
+a:hover {
+	text-decoration: underline;
+}
+
+a:visited {
+	color: rgb(0,80,160);
+}
+
+label {
+	display: block;
+}
+
+input, button, select, textarea {
+	font-family: inherit;
+	font-size: inherit;
+	-webkit-padding: 0.4em 0;
+	padding: 0.4em;
+	margin: 0 0 0.5em 0;
+	box-sizing: border-box;
+	border: 1px solid #ccc;
+	border-radius: 2px;
+}
+
+input:disabled {
+	color: #ccc;
+}
+
+button {
+	color: #333;
+	background-color: #f4f4f4;
+	outline: none;
+}
+
+button:disabled {
+	color: #999;
+}
+
+button:not(:disabled):active {
+	background-color: #ddd;
+}
+
+button:focus {
+	border-color: #666;
+}

+ 20 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/public/index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+	<meta charset='utf-8'>
+	<meta name='viewport' content='width=device-width,initial-scale=1'>
+
+	<title>Svelte app</title>
+
+	<link rel='icon' type='image/png' href='favicon.png'>
+	<link rel='stylesheet' href='global.css'>
+	<link rel='stylesheet' href='build/bundle.css'>
+
+	<script defer src='build/bundle.js'></script>
+</head>
+
+<body>
+</body>
+
+</html>

+ 83 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/rollup.config.js

@@ -0,0 +1,83 @@
+import svelte from 'rollup-plugin-svelte';
+import commonjs from '@rollup/plugin-commonjs';
+import resolve from '@rollup/plugin-node-resolve';
+import livereload from 'rollup-plugin-livereload';
+import { terser } from 'rollup-plugin-terser';
+import sveltePreprocess from 'svelte-preprocess';
+import typescript from '@rollup/plugin-typescript';
+import css from 'rollup-plugin-css-only';
+
+const production = !process.env.ROLLUP_WATCH;
+
+function serve() {
+	let server;
+
+	function toExit() {
+		if (server) server.kill(0);
+	}
+
+	return {
+		writeBundle() {
+			if (server) return;
+			server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
+				stdio: ['ignore', 'inherit', 'inherit'],
+				shell: true
+			});
+
+			process.on('SIGTERM', toExit);
+			process.on('exit', toExit);
+		}
+	};
+}
+
+export default {
+	input: 'src/main.ts',
+	output: {
+		sourcemap: true,
+		format: 'iife',
+		name: 'app',
+		file: 'public/build/bundle.js'
+	},
+	plugins: [
+		svelte({
+			preprocess: sveltePreprocess(),
+			compilerOptions: {
+				// enable run-time checks when not in production
+				dev: !production
+			}
+		}),
+		// we'll extract any component CSS out into
+		// a separate file - better for performance
+		css({ output: 'bundle.css' }),
+
+		// If you have external dependencies installed from
+		// npm, you'll most likely need these plugins. In
+		// some cases you'll need additional configuration -
+		// consult the documentation for details:
+		// https://github.com/rollup/plugins/tree/master/packages/commonjs
+		resolve({
+			browser: true,
+			dedupe: ['svelte']
+		}),
+		commonjs(),
+		typescript({
+			sourceMap: !production,
+			inlineSources: !production
+		}),
+
+		// In dev mode, call `npm run start` once
+		// the bundle has been generated
+		!production && serve(),
+
+		// Watch the `public` directory and refresh the
+		// browser on changes when not in production
+		!production && livereload('public'),
+
+		// If we're building for production (npm run build
+		// instead of npm run dev), minify
+		production && terser()
+	],
+	watch: {
+		clearScreen: false
+	}
+};

+ 10 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/.gitignore

@@ -0,0 +1,10 @@
+# Generated by Cargo
+# will have compiled files and executables
+/target/
+WixTools
+
+# These are backup files generated by rustfmt
+**/*.rs.bk
+
+config.json
+bundle.json

+ 20 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/Cargo.crate-manifest

@@ -0,0 +1,20 @@
+[package]
+name = "app"
+version = "0.1.0"
+description = "A Tauri App"
+authors = [ "You" ]
+repository = ""
+edition = "2018"
+
+[dependencies]
+serde_json = "1.0"
+serde = { version = "1.0", features = [ "derive" ] }
+tauri = {{{  tauri_dep  }}}
+tauri-plugin-{{ plugin_name }} = { path = "../../../" }
+
+[build-dependencies]
+tauri-build = {{{  tauri_build_dep  }}}
+
+[features]
+default = [ "custom-protocol" ]
+custom-protocol = [ "tauri/custom-protocol" ]

+ 3 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/build.rs

@@ -0,0 +1,3 @@
+fn main() {
+  tauri_build::build()
+}

BIN
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/icons/128x128.png


BIN
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/icons/128x128@2x.png


BIN
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/icons/32x32.png


BIN
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/icons/icon.icns


BIN
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/icons/icon.ico


BIN
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/icons/icon.png


+ 13 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/rustfmt.toml

@@ -0,0 +1,13 @@
+max_width = 100
+hard_tabs = false
+tab_spaces = 2
+newline_style = "Auto"
+use_small_heuristics = "Default"
+reorder_imports = true
+reorder_modules = true
+remove_nested_parens = true
+edition = "2018"
+merge_derives = true
+use_try_shorthand = false
+use_field_init_shorthand = false
+force_explicit_abi = true

+ 12 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/src/main.rs

@@ -0,0 +1,12 @@
+#![cfg_attr(
+  all(not(debug_assertions), target_os = "windows"),
+  windows_subsystem = "windows"
+)]
+
+
+fn main() {
+  tauri::Builder::default()
+    .plugin(tauri_plugin_{{ plugin_name_snake_case }}::YourPlugin::default())
+    .run(tauri::generate_context!())
+    .expect("failed to run app");
+}

+ 53 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src-tauri/tauri.conf.json

@@ -0,0 +1,53 @@
+{
+  "build": {
+    "distDir": "../public",
+    "devPath": "http://localhost:5000",
+    "beforeDevCommand": "yarn dev",
+    "beforeBuildCommand": "yarn build"
+  },
+  "tauri": {
+    "bundle": {
+      "active": true,
+      "targets": "all",
+      "identifier": "com.tauri.{{ plugin_name }}",
+      "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": [],
+        "useBootstrapper": false
+      },
+      "macOS": {
+        "frameworks": [],
+        "minimumSystemVersion": "",
+        "useBootstrapper": false,
+        "exceptionDomain": ""
+      }
+    },
+    "allowlist": {
+      "all": true
+    },
+    "windows": [
+      {
+        "title": "Tauri App",
+        "width": 800,
+        "height": 600,
+        "resizable": true,
+        "fullscreen": false
+      }
+    ],
+    "security": {
+      "csp": "default-src blob: data: filesystem: ws: http: https: 'unsafe-eval' 'unsafe-inline'"
+    }
+  }
+}

+ 17 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src/App.svelte

@@ -0,0 +1,17 @@
+<script lang="ts">
+	import { execute } from 'tauri-plugin-{{ plugin_name }}-api'
+
+	let response = ''
+
+	function updateResponse(returnValue) {
+		response += (typeof returnValue === 'string' ? returnValue : JSON.stringify(returnValue)) + '<br>'
+	}
+
+	function _execute() {
+		execute().then(updateResponse).catch(updateResponse)
+	}
+</script>
+
+<div>
+	<button on:click="{_execute}">Execute</button>
+</div>

+ 8 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/src/main.ts

@@ -0,0 +1,8 @@
+import App from './App.svelte';
+
+const app = new App({
+	target: document.body,
+	props: {}
+});
+
+export default app;

+ 6 - 0
tooling/cli.rs/templates/plugin/with-api/examples/svelte-app/tsconfig.json

@@ -0,0 +1,6 @@
+{
+  "extends": "@tsconfig/svelte/tsconfig.json",
+
+  "include": ["src/**/*"],
+  "exclude": ["node_modules/*", "__sapper__/*", "public/*"]
+}

+ 26 - 0
tooling/cli.rs/templates/plugin/with-api/package.json

@@ -0,0 +1,26 @@
+{
+  "name": "tauri-plugin-{{ plugin_name }}-api",
+  "version": "0.1.0",
+  "authors": [
+    "You"
+  ],
+  "description": "",
+  "browser": "webview-dist/index.js",
+  "main": "webview-dist/index.js",
+  "scripts": {
+    "build": "rollup -c ./webview-src/rollup.config.js",
+    "prepublishOnly": "yarn build",
+    "pretest": "yarn build"
+  },
+  "devDependencies": {
+    "@rollup/plugin-node-resolve": "^11.1.0",
+    "@rollup/plugin-typescript": "^8.1.0",
+    "rollup": "^2.38.0",
+    "rollup-plugin-terser": "^7.0.2",
+    "typescript": "^4.1.3"
+  },
+  "dependencies": {
+    "@tauri-apps/api": "1.0.0-beta.8",
+    "tslib": "^2.1.0"
+  }
+}

+ 65 - 0
tooling/cli.rs/templates/plugin/with-api/src/lib.rs

@@ -0,0 +1,65 @@
+use serde::{ser::Serializer, Serialize};
+use serde_json::Value as JsonValue;
+use tauri::{command, plugin::Plugin, AppHandle, Invoke, Manager, Runtime, State, Window};
+
+use std::{collections::HashMap, sync::Mutex};
+
+type Result<T> = std::result::Result<T, Error>;
+
+#[derive(Debug, thiserror::Error)]
+pub enum Error {
+  #[error(transparent)]
+  Io(#[from] std::io::Error),
+}
+
+impl Serialize for Error {
+  fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
+  where
+    S: Serializer,
+  {
+    match self {
+      Self::Io(error) => serializer.serialize_str(error.to_string().as_ref()),
+    }
+  }
+}
+
+#[derive(Default)]
+struct MyState(Mutex<HashMap<String, String>>);
+
+#[command]
+async fn execute<R: Runtime>(
+  _app: AppHandle<R>,
+  _window: Window<R>,
+  state: State<'_, MyState>,
+) -> Result<String> {
+  state.0.lock().unwrap().insert("key".into(), "value".into());
+  Ok("success".to_string())
+}
+
+/// Tauri plugin.
+pub struct YourPlugin<R: Runtime> {
+  invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync>,
+}
+
+impl<R: Runtime> Default for YourPlugin<R> {
+  fn default() -> Self {
+    Self {
+      invoke_handler: Box::new(tauri::generate_handler![execute]),
+    }
+  }
+}
+
+impl<R: Runtime> Plugin<R> for YourPlugin<R> {
+  fn name(&self) -> &'static str {
+    "{{ plugin_name }}"
+  }
+
+  fn initialize(&mut self, app: &AppHandle<R>, _config: JsonValue) -> tauri::plugin::Result<()> {
+    app.manage(MyState::default());
+    Ok(())
+  }
+
+  fn extend_api(&mut self, message: Invoke<R>) {
+    (self.invoke_handler)(message)
+  }
+}

+ 1 - 0
tooling/cli.rs/templates/plugin/with-api/webview-dist/index.d.ts

@@ -0,0 +1 @@
+export declare function execute(): Promise<void>;

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 28 - 0
tooling/cli.rs/templates/plugin/with-api/webview-dist/index.js


+ 66 - 0
tooling/cli.rs/templates/plugin/with-api/webview-src/.gitignore

@@ -0,0 +1,66 @@
+# Build output
+/dist
+/api
+
+
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# nyc test coverage
+.nyc_output
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# Typescript v1 declaration files
+typings/
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+
+/.vs
+.DS_Store
+.Thumbs.db
+*.sublime*
+.idea/
+debug.log
+package-lock.json
+.vscode/settings.json

+ 5 - 0
tooling/cli.rs/templates/plugin/with-api/webview-src/index.ts

@@ -0,0 +1,5 @@
+import { invoke } from '@tauri-apps/api/tauri'
+
+export async function execute() {
+  await invoke('plugin:{{ plugin_name }}|execute')
+}

+ 21 - 0
tooling/cli.rs/templates/plugin/with-api/webview-src/rollup.config.js

@@ -0,0 +1,21 @@
+import { nodeResolve } from '@rollup/plugin-node-resolve'
+import { terser } from 'rollup-plugin-terser'
+import typescript from '@rollup/plugin-typescript'
+
+export default {
+	input: './webview-src/index.ts',
+	output: {
+		dir: './webview-dist',
+		entryFileNames: '[name].js',
+		format: 'es',
+		exports: 'auto'
+	},
+	plugins: [
+    nodeResolve(),
+		terser(),
+		typescript({
+			tsconfig: './webview-src/tsconfig.json',
+			moduleResolution: 'node'
+		})
+	]
+}

+ 16 - 0
tooling/cli.rs/templates/plugin/with-api/webview-src/tsconfig.json

@@ -0,0 +1,16 @@
+{
+  "compilerOptions": {
+    "target": "ES5",
+    "strict": true,
+    "allowJs": true,
+    "esModuleInterop": true,
+    "baseUrl": ".",
+    "paths": {
+      "types": ["@types"]
+    },
+    "declaration": true,
+    "declarationDir": "../webview-dist",
+    "rootDir": "./"
+  },
+  "include": ["./"]
+}

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно