diff --git a/.gitignore b/.gitignore index 4f9a09c..9863270 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ package-lock.json .vscode/settings.json yarn.lock +/.tauri /target Cargo.lock node_modules/ -webview-dist \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 5519f02..0ff3b31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,4 +41,4 @@ ## 0.2.0 * BREAKING CHANGE: replaced the `init` function with a `Builder` struct, see README for example usage -* Ability to set custom hosts for self hosted servers \ No newline at end of file +* Ability to set custom hosts for self hosted servers diff --git a/Cargo.toml b/Cargo.toml index 4178f4b..a207e16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,23 +3,26 @@ name = "tauri-plugin-aptabase" version = "0.5.1" license = "MIT" description = "Tauri Plugin for Aptabase: Open Source, Privacy-First and Simple Analytics for Mobile, Desktop and Web Apps" -authors = [ "Guilherme Oenning" ] +authors = ["Guilherme Oenning"] edition = "2021" -rust-version = "1.59" +rust-version = "1.70" readme = "README.md" repository = "https://github.com/aptabase/tauri-plugin-aptabase" -exclude = ["/examples", "/webview-dist", "/webview-src", "node_modules"] +exclude = ["/examples", "/webview-dist", "/webview-src", "/node_modules"] +links = "tauri-plugin-aptabase" [dependencies] -tauri = { version = "1", features = ["os-api"] } -tokio = "1" -futures = "0" -serde = "1.0" -serde_json = "1.0" -thiserror = "1.0" -reqwest = { version = "0.11", features = ["json"] } -time = { version = "0.3", features = ["formatting"]} -os_info = "3" -uuid = "1" -rand = "0.8" -log = "0.4" +tauri = "2.2.5" +tokio = "1.43.0" +futures = "0.3.31" +serde = "1.0.217" +serde_json = "1.0.138" +reqwest = { version = "0.12.12", features = ["json"] } +time = { version = "0.3.37", features = ["formatting"] } +os_info = "3.9.2" +rand = "0.9.0" +log = "0.4.25" +sys-locale = "0.3.2" + +[build-dependencies] +tauri-plugin = { version = "2.0.4", features = ["build"] } diff --git a/README.md b/README.md index d2d79a7..d0d96ac 100644 --- a/README.md +++ b/README.md @@ -12,22 +12,20 @@ Install the Core plugin by adding the following to your `Cargo.toml` file: ```toml [dependencies] -tauri-plugin-aptabase = "0.4" +tauri-plugin-aptabase = { git = "https://github.com/aptabase/tauri-plugin-aptabase", branch = "v2" } ``` You can install the JavaScript Guest bindings using your preferred JavaScript package manager ```bash -npm add @aptabase/tauri +npm add https://github.com/aptabase/tauri-plugin-aptabase#v2 ``` -> This plugin is only compatible with Tauri v1. To use it on a Tauri v2 app, [follow the instructions on our v2 branch](https://github.com/aptabase/tauri-plugin-aptabase/blob/v2). - ## Usage First, you need to get your `App Key` from Aptabase, you can find it in the `Instructions` menu on the left side menu. -Then you need to register the core plugin with Tauri: +Then register the plugin with Tauri: `src-tauri/src/main.rs` @@ -40,11 +38,12 @@ fn main() { } ``` +And finally add `aptabase:allow-track-event` to your list Access Control List. + You can then start sending events from Rust by importing the `tauri_plugin_aptabase::EventTracker` trait and calling the `track_event` method on `App`, `AppHandle` or `Window`. As an example, you can add `app_started` and `app_exited` events like this: - ```rust use tauri_plugin_aptabase::EventTracker; @@ -83,3 +82,35 @@ A few important notes: - Because of this, it's generally recommended to at least track an event at startup 3. You do not need to await for the `trackEvent` function, it'll run in the background. 3. Only strings and numbers values are allowed on custom properties + +## Providing the APTABASE_KEY via .env + +It's possible to load the APTABASE_KEY from a .env file at compile time using the `dotenvy_macro` crate. The `.env` file needs to be +in the `src-tauri` directory for the `dotevny_macro` crate to find it properly. + +Add the `use` declaration to where you are building the tauri app (likely `lib.rs` for Tauri v2), and then call it where you would put the key. + +```rust +use tauri_plugin_aptabase::EventTracker; +use dotenvy_macro::dotenv; + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +/// This function sets up and runs a Rust application using the Tauri framework, with various plugins +/// and event handlers. +pub fn run() { + tauri::Builder::default() + .build(tauri::generate_context!()) + .plugin(tauri_plugin_aptabase::Builder::new(dotenv!("APTABASE_KEY")).build()) + .expect("Error when building tauri app") + .run(|handler, event| match event { + tauri::RunEvent::Exit { .. } => { + handler.track_event("app_exited", None); + handler.flush_events_blocking(); + } + tauri::RunEvent::Ready { .. } => { + handler.track_event("app_started", None); + } + _ => {} + }); +} +``` diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..b6b7b1a --- /dev/null +++ b/build.rs @@ -0,0 +1,5 @@ +const COMMANDS: &[&str] = &["track_event"]; + +fn main() { + tauri_plugin::Builder::new(COMMANDS).build(); +} diff --git a/examples/helloworld/README.md b/examples/helloworld/README.md deleted file mode 100644 index 102e366..0000000 --- a/examples/helloworld/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Tauri + React + Typescript - -This template should help get you started developing with Tauri, React and Typescript in Vite. - -## Recommended IDE Setup - -- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) diff --git a/examples/helloworld/index.html b/examples/helloworld/index.html index 194012b..fad1c5d 100644 --- a/examples/helloworld/index.html +++ b/examples/helloworld/index.html @@ -4,11 +4,11 @@ - Tauri + React + TS + Tauri + Svelte -
- +
+ diff --git a/examples/helloworld/jsconfig.json b/examples/helloworld/jsconfig.json new file mode 100644 index 0000000..ee5e92f --- /dev/null +++ b/examples/helloworld/jsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "moduleResolution": "Node", + "target": "ESNext", + "module": "ESNext", + /** + * svelte-preprocess cannot figure out whether you have + * a value or a type, so tell TypeScript to enforce using + * `import type` instead of `import` for Types. + */ + "importsNotUsedAsValues": "error", + "isolatedModules": true, + "resolveJsonModule": true, + /** + * To have warnings / errors of the Svelte compiler at the + * correct position, enable source maps by default. + */ + "sourceMap": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + /** + * Typecheck JS in `.svelte` and `.js` files by default. + * Disable this if you'd like to use dynamic types. + */ + "checkJs": true + }, + /** + * Use global.d.ts instead of compilerOptions.types + * to avoid limiting type declarations. + */ + "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/examples/helloworld/package.json b/examples/helloworld/package.json index 79a4231..2c6fd20 100644 --- a/examples/helloworld/package.json +++ b/examples/helloworld/package.json @@ -11,18 +11,14 @@ "tauri": "tauri" }, "dependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0", - "@tauri-apps/api": "^1.2.0", + "@tauri-apps/api": "^2.1.1", "@aptabase/tauri": "file:../../" }, "devDependencies": { - "@types/node": "^18.7.10", - "@types/react": "^18.0.15", - "@types/react-dom": "^18.0.6", - "@vitejs/plugin-react": "^3.0.0", - "typescript": "^4.6.4", - "vite": "^4.0.0", - "@tauri-apps/cli": "^1.2.2" + "@sveltejs/vite-plugin-svelte": "^1.0.1", + "internal-ip": "^7.0.0", + "svelte": "^3.49.0", + "vite": "^3.0.2", + "@tauri-apps/cli": "^2.1.0" } } diff --git a/examples/helloworld/public/svelte.svg b/examples/helloworld/public/svelte.svg new file mode 100644 index 0000000..c5e0848 --- /dev/null +++ b/examples/helloworld/public/svelte.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/helloworld/src-tauri/Cargo.toml b/examples/helloworld/src-tauri/Cargo.toml index 2293d41..619e34e 100644 --- a/examples/helloworld/src-tauri/Cargo.toml +++ b/examples/helloworld/src-tauri/Cargo.toml @@ -1,28 +1,29 @@ [package] -name = "helloworld" +name = "tauri-app" version = "0.0.0" description = "A Tauri App" authors = ["you"] license = "" repository = "" edition = "2021" +rust-version = "1.70" + +[lib] +name = "tauri_app_lib" +crate-type = ["staticlib", "cdylib", "rlib"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] -tauri-build = { version = "1.4", features = [] } +tauri-build = { version = "2.0", default-features = false, features = [] } [dependencies] +tauri = { version = "2.1", features = [] } +tauri-plugin-aptabase = { path = "../../../" } serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.4", features = ["shell-open"] } -tauri-plugin-aptabase = { path = "../../../" } -tauri-plugin-log = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" } [features] -# by default Tauri runs in production mode -# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL -default = ["custom-protocol"] -# this feature is used used for production builds where `devPath` points to the filesystem -# DO NOT remove this +# this feature is used for production builds or when `devUrl` points to the filesystem +# DO NOT REMOVE!! custom-protocol = ["tauri/custom-protocol"] diff --git a/examples/helloworld/src-tauri/capabilities/desktop.json b/examples/helloworld/src-tauri/capabilities/desktop.json new file mode 100644 index 0000000..8182109 --- /dev/null +++ b/examples/helloworld/src-tauri/capabilities/desktop.json @@ -0,0 +1,8 @@ +{ + "identifier": "main-capability", + "description": "Capability for the main window", + "windows": ["main"], + "permissions": [ + "aptabase:allow-track-event" + ] + } \ No newline at end of file diff --git a/examples/helloworld/src-tauri/gen/schemas/capabilities.json b/examples/helloworld/src-tauri/gen/schemas/capabilities.json new file mode 100644 index 0000000..ab8512e --- /dev/null +++ b/examples/helloworld/src-tauri/gen/schemas/capabilities.json @@ -0,0 +1 @@ +{"main-capability":{"identifier":"main-capability","description":"Capability for the main window","context":"local","windows":["main"],"permissions":["aptabase:allow-track-event"],"platforms":["linux","macOS","windows","android","iOS"]}} \ No newline at end of file diff --git a/examples/helloworld/src-tauri/gen/schemas/desktop-schema.json b/examples/helloworld/src-tauri/gen/schemas/desktop-schema.json new file mode 100644 index 0000000..e42d396 --- /dev/null +++ b/examples/helloworld/src-tauri/gen/schemas/desktop-schema.json @@ -0,0 +1 @@ +{schema_str} \ No newline at end of file diff --git a/examples/helloworld/src-tauri/gen/schemas/macOS-schema.json b/examples/helloworld/src-tauri/gen/schemas/macOS-schema.json new file mode 100644 index 0000000..e42d396 --- /dev/null +++ b/examples/helloworld/src-tauri/gen/schemas/macOS-schema.json @@ -0,0 +1 @@ +{schema_str} \ No newline at end of file diff --git a/examples/helloworld/src-tauri/gen/schemas/plugin-manifests.json b/examples/helloworld/src-tauri/gen/schemas/plugin-manifests.json new file mode 100644 index 0000000..fc6adbe --- /dev/null +++ b/examples/helloworld/src-tauri/gen/schemas/plugin-manifests.json @@ -0,0 +1 @@ +{"app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version"]},"permissions":{"allow-app-hide":{"version":null,"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]},"scope":{}},"allow-app-show":{"version":null,"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]},"scope":{}},"allow-name":{"version":null,"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]},"scope":{}},"allow-tauri-version":{"version":null,"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]},"scope":{}},"allow-version":{"version":null,"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]},"scope":{}},"deny-app-hide":{"version":null,"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]},"scope":{}},"deny-app-show":{"version":null,"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]},"scope":{}},"deny-name":{"version":null,"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]},"scope":{}},"deny-tauri-version":{"version":null,"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]},"scope":{}},"deny-version":{"version":null,"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]},"scope":{}}},"permission_sets":{},"global_scope_schema":null},"aptabase":{"default_permission":null,"permissions":{"allow-track-event":{"version":null,"identifier":"allow-track-event","description":"Enables the track_event command without any pre-configured scope.","commands":{"allow":["track_event"],"deny":[]},"scope":{}},"deny-track-event":{"version":null,"identifier":"deny-track-event","description":"Denies the track_event command without any pre-configured scope.","commands":{"allow":[],"deny":["track_event"]},"scope":{}}},"permission_sets":{},"global_scope_schema":null},"event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"version":null,"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]},"scope":{}},"allow-emit-to":{"version":null,"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]},"scope":{}},"allow-listen":{"version":null,"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]},"scope":{}},"allow-unlisten":{"version":null,"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]},"scope":{}},"deny-emit":{"version":null,"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]},"scope":{}},"deny-emit-to":{"version":null,"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]},"scope":{}},"deny-listen":{"version":null,"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]},"scope":{}},"deny-unlisten":{"version":null,"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]},"scope":{}}},"permission_sets":{},"global_scope_schema":null},"menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":[]},"permissions":{"allow-append":{"version":null,"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]},"scope":{}},"allow-create-default":{"version":null,"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]},"scope":{}},"allow-get":{"version":null,"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]},"scope":{}},"allow-insert":{"version":null,"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]},"scope":{}},"allow-is-checked":{"version":null,"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]},"scope":{}},"allow-is-enabled":{"version":null,"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]},"scope":{}},"allow-items":{"version":null,"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]},"scope":{}},"allow-new":{"version":null,"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]},"scope":{}},"allow-popup":{"version":null,"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]},"scope":{}},"allow-prepend":{"version":null,"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]},"scope":{}},"allow-remove":{"version":null,"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]},"scope":{}},"allow-remove-at":{"version":null,"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]},"scope":{}},"allow-set-accelerator":{"version":null,"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]},"scope":{}},"allow-set-as-app-menu":{"version":null,"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]},"scope":{}},"allow-set-as-help-menu-for-nsapp":{"version":null,"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]},"scope":{}},"allow-set-as-window-menu":{"version":null,"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]},"scope":{}},"allow-set-as-windows-menu-for-nsapp":{"version":null,"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]},"scope":{}},"allow-set-checked":{"version":null,"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]},"scope":{}},"allow-set-enabled":{"version":null,"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]},"scope":{}},"allow-set-icon":{"version":null,"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]},"scope":{}},"allow-set-text":{"version":null,"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]},"scope":{}},"allow-text":{"version":null,"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]},"scope":{}},"deny-append":{"version":null,"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]},"scope":{}},"deny-create-default":{"version":null,"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]},"scope":{}},"deny-get":{"version":null,"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]},"scope":{}},"deny-insert":{"version":null,"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]},"scope":{}},"deny-is-checked":{"version":null,"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]},"scope":{}},"deny-is-enabled":{"version":null,"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]},"scope":{}},"deny-items":{"version":null,"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]},"scope":{}},"deny-new":{"version":null,"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]},"scope":{}},"deny-popup":{"version":null,"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]},"scope":{}},"deny-prepend":{"version":null,"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]},"scope":{}},"deny-remove":{"version":null,"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]},"scope":{}},"deny-remove-at":{"version":null,"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]},"scope":{}},"deny-set-accelerator":{"version":null,"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]},"scope":{}},"deny-set-as-app-menu":{"version":null,"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]},"scope":{}},"deny-set-as-help-menu-for-nsapp":{"version":null,"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]},"scope":{}},"deny-set-as-window-menu":{"version":null,"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]},"scope":{}},"deny-set-as-windows-menu-for-nsapp":{"version":null,"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]},"scope":{}},"deny-set-checked":{"version":null,"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]},"scope":{}},"deny-set-enabled":{"version":null,"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]},"scope":{}},"deny-set-icon":{"version":null,"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]},"scope":{}},"deny-set-text":{"version":null,"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]},"scope":{}},"deny-text":{"version":null,"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]},"scope":{}}},"permission_sets":{},"global_scope_schema":null},"path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"version":null,"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]},"scope":{}},"allow-dirname":{"version":null,"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]},"scope":{}},"allow-extname":{"version":null,"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]},"scope":{}},"allow-is-absolute":{"version":null,"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]},"scope":{}},"allow-join":{"version":null,"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]},"scope":{}},"allow-normalize":{"version":null,"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]},"scope":{}},"allow-resolve":{"version":null,"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]},"scope":{}},"allow-resolve-directory":{"version":null,"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]},"scope":{}},"deny-basename":{"version":null,"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]},"scope":{}},"deny-dirname":{"version":null,"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]},"scope":{}},"deny-extname":{"version":null,"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]},"scope":{}},"deny-is-absolute":{"version":null,"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]},"scope":{}},"deny-join":{"version":null,"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]},"scope":{}},"deny-normalize":{"version":null,"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]},"scope":{}},"deny-resolve":{"version":null,"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]},"scope":{}},"deny-resolve-directory":{"version":null,"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]},"scope":{}}},"permission_sets":{},"global_scope_schema":null},"resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-close"]},"permissions":{"allow-close":{"version":null,"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]},"scope":{}},"deny-close":{"version":null,"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]},"scope":{}}},"permission_sets":{},"global_scope_schema":null},"tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":[]},"permissions":{"allow-new":{"version":null,"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]},"scope":{}},"allow-set-icon":{"version":null,"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]},"scope":{}},"allow-set-icon-as-template":{"version":null,"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]},"scope":{}},"allow-set-menu":{"version":null,"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]},"scope":{}},"allow-set-show-menu-on-left-click":{"version":null,"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]},"scope":{}},"allow-set-temp-dir-path":{"version":null,"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]},"scope":{}},"allow-set-title":{"version":null,"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]},"scope":{}},"allow-set-tooltip":{"version":null,"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]},"scope":{}},"allow-set-visible":{"version":null,"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]},"scope":{}},"deny-new":{"version":null,"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]},"scope":{}},"deny-set-icon":{"version":null,"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]},"scope":{}},"deny-set-icon-as-template":{"version":null,"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]},"scope":{}},"deny-set-menu":{"version":null,"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]},"scope":{}},"deny-set-show-menu-on-left-click":{"version":null,"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]},"scope":{}},"deny-set-temp-dir-path":{"version":null,"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]},"scope":{}},"deny-set-title":{"version":null,"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]},"scope":{}},"deny-set-tooltip":{"version":null,"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]},"scope":{}},"deny-set-visible":{"version":null,"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]},"scope":{}}},"permission_sets":{},"global_scope_schema":null},"webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-create-webview":{"version":null,"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]},"scope":{}},"allow-create-webview-window":{"version":null,"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]},"scope":{}},"allow-internal-toggle-devtools":{"version":null,"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]},"scope":{}},"allow-print":{"version":null,"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]},"scope":{}},"allow-set-webview-focus":{"version":null,"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]},"scope":{}},"allow-set-webview-position":{"version":null,"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]},"scope":{}},"allow-set-webview-size":{"version":null,"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]},"scope":{}},"allow-webview-close":{"version":null,"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]},"scope":{}},"allow-webview-position":{"version":null,"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]},"scope":{}},"allow-webview-size":{"version":null,"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]},"scope":{}},"deny-create-webview":{"version":null,"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]},"scope":{}},"deny-create-webview-window":{"version":null,"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]},"scope":{}},"deny-internal-toggle-devtools":{"version":null,"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]},"scope":{}},"deny-print":{"version":null,"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]},"scope":{}},"deny-set-webview-focus":{"version":null,"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]},"scope":{}},"deny-set-webview-position":{"version":null,"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]},"scope":{}},"deny-set-webview-size":{"version":null,"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]},"scope":{}},"deny-webview-close":{"version":null,"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]},"scope":{}},"deny-webview-position":{"version":null,"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]},"scope":{}},"deny-webview-size":{"version":null,"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]},"scope":{}}},"permission_sets":{},"global_scope_schema":null},"window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-title","allow-current-monitor","allow-primary-monitor","allow-available-monitors","allow-theme","allow-internal-toggle-maximize","allow-internal-on-mousemove","allow-internal-on-mousedown"]},"permissions":{"allow-available-monitors":{"version":null,"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]},"scope":{}},"allow-center":{"version":null,"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]},"scope":{}},"allow-close":{"version":null,"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]},"scope":{}},"allow-create":{"version":null,"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]},"scope":{}},"allow-current-monitor":{"version":null,"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]},"scope":{}},"allow-destroy":{"version":null,"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]},"scope":{}},"allow-hide":{"version":null,"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]},"scope":{}},"allow-inner-position":{"version":null,"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]},"scope":{}},"allow-inner-size":{"version":null,"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]},"scope":{}},"allow-internal-on-mousedown":{"version":null,"identifier":"allow-internal-on-mousedown","description":"Enables the internal_on_mousedown command without any pre-configured scope.","commands":{"allow":["internal_on_mousedown"],"deny":[]},"scope":{}},"allow-internal-on-mousemove":{"version":null,"identifier":"allow-internal-on-mousemove","description":"Enables the internal_on_mousemove command without any pre-configured scope.","commands":{"allow":["internal_on_mousemove"],"deny":[]},"scope":{}},"allow-internal-toggle-maximize":{"version":null,"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]},"scope":{}},"allow-is-closable":{"version":null,"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]},"scope":{}},"allow-is-decorated":{"version":null,"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]},"scope":{}},"allow-is-focused":{"version":null,"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]},"scope":{}},"allow-is-fullscreen":{"version":null,"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]},"scope":{}},"allow-is-maximizable":{"version":null,"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]},"scope":{}},"allow-is-maximized":{"version":null,"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]},"scope":{}},"allow-is-minimizable":{"version":null,"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]},"scope":{}},"allow-is-minimized":{"version":null,"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]},"scope":{}},"allow-is-resizable":{"version":null,"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]},"scope":{}},"allow-is-visible":{"version":null,"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]},"scope":{}},"allow-maximize":{"version":null,"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]},"scope":{}},"allow-minimize":{"version":null,"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]},"scope":{}},"allow-outer-position":{"version":null,"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]},"scope":{}},"allow-outer-size":{"version":null,"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]},"scope":{}},"allow-primary-monitor":{"version":null,"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]},"scope":{}},"allow-request-user-attention":{"version":null,"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]},"scope":{}},"allow-scale-factor":{"version":null,"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]},"scope":{}},"allow-set-always-on-bottom":{"version":null,"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]},"scope":{}},"allow-set-always-on-top":{"version":null,"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]},"scope":{}},"allow-set-closable":{"version":null,"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]},"scope":{}},"allow-set-content-protected":{"version":null,"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]},"scope":{}},"allow-set-cursor-grab":{"version":null,"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]},"scope":{}},"allow-set-cursor-icon":{"version":null,"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]},"scope":{}},"allow-set-cursor-position":{"version":null,"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]},"scope":{}},"allow-set-cursor-visible":{"version":null,"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]},"scope":{}},"allow-set-decorations":{"version":null,"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]},"scope":{}},"allow-set-effects":{"version":null,"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]},"scope":{}},"allow-set-focus":{"version":null,"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]},"scope":{}},"allow-set-fullscreen":{"version":null,"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]},"scope":{}},"allow-set-icon":{"version":null,"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]},"scope":{}},"allow-set-ignore-cursor-events":{"version":null,"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]},"scope":{}},"allow-set-max-size":{"version":null,"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]},"scope":{}},"allow-set-maximizable":{"version":null,"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]},"scope":{}},"allow-set-min-size":{"version":null,"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]},"scope":{}},"allow-set-minimizable":{"version":null,"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]},"scope":{}},"allow-set-position":{"version":null,"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]},"scope":{}},"allow-set-progress-bar":{"version":null,"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]},"scope":{}},"allow-set-resizable":{"version":null,"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]},"scope":{}},"allow-set-shadow":{"version":null,"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]},"scope":{}},"allow-set-size":{"version":null,"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]},"scope":{}},"allow-set-skip-taskbar":{"version":null,"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]},"scope":{}},"allow-set-title":{"version":null,"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]},"scope":{}},"allow-set-visible-on-all-workspaces":{"version":null,"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]},"scope":{}},"allow-show":{"version":null,"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]},"scope":{}},"allow-start-dragging":{"version":null,"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]},"scope":{}},"allow-theme":{"version":null,"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]},"scope":{}},"allow-title":{"version":null,"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]},"scope":{}},"allow-toggle-maximize":{"version":null,"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]},"scope":{}},"allow-unmaximize":{"version":null,"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]},"scope":{}},"allow-unminimize":{"version":null,"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]},"scope":{}},"deny-available-monitors":{"version":null,"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]},"scope":{}},"deny-center":{"version":null,"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]},"scope":{}},"deny-close":{"version":null,"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]},"scope":{}},"deny-create":{"version":null,"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]},"scope":{}},"deny-current-monitor":{"version":null,"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]},"scope":{}},"deny-destroy":{"version":null,"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]},"scope":{}},"deny-hide":{"version":null,"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]},"scope":{}},"deny-inner-position":{"version":null,"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]},"scope":{}},"deny-inner-size":{"version":null,"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]},"scope":{}},"deny-internal-on-mousedown":{"version":null,"identifier":"deny-internal-on-mousedown","description":"Denies the internal_on_mousedown command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_on_mousedown"]},"scope":{}},"deny-internal-on-mousemove":{"version":null,"identifier":"deny-internal-on-mousemove","description":"Denies the internal_on_mousemove command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_on_mousemove"]},"scope":{}},"deny-internal-toggle-maximize":{"version":null,"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]},"scope":{}},"deny-is-closable":{"version":null,"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]},"scope":{}},"deny-is-decorated":{"version":null,"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]},"scope":{}},"deny-is-focused":{"version":null,"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]},"scope":{}},"deny-is-fullscreen":{"version":null,"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]},"scope":{}},"deny-is-maximizable":{"version":null,"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]},"scope":{}},"deny-is-maximized":{"version":null,"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]},"scope":{}},"deny-is-minimizable":{"version":null,"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]},"scope":{}},"deny-is-minimized":{"version":null,"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]},"scope":{}},"deny-is-resizable":{"version":null,"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]},"scope":{}},"deny-is-visible":{"version":null,"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]},"scope":{}},"deny-maximize":{"version":null,"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]},"scope":{}},"deny-minimize":{"version":null,"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]},"scope":{}},"deny-outer-position":{"version":null,"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]},"scope":{}},"deny-outer-size":{"version":null,"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]},"scope":{}},"deny-primary-monitor":{"version":null,"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]},"scope":{}},"deny-request-user-attention":{"version":null,"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]},"scope":{}},"deny-scale-factor":{"version":null,"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]},"scope":{}},"deny-set-always-on-bottom":{"version":null,"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]},"scope":{}},"deny-set-always-on-top":{"version":null,"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]},"scope":{}},"deny-set-closable":{"version":null,"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]},"scope":{}},"deny-set-content-protected":{"version":null,"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]},"scope":{}},"deny-set-cursor-grab":{"version":null,"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]},"scope":{}},"deny-set-cursor-icon":{"version":null,"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]},"scope":{}},"deny-set-cursor-position":{"version":null,"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]},"scope":{}},"deny-set-cursor-visible":{"version":null,"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]},"scope":{}},"deny-set-decorations":{"version":null,"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]},"scope":{}},"deny-set-effects":{"version":null,"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]},"scope":{}},"deny-set-focus":{"version":null,"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]},"scope":{}},"deny-set-fullscreen":{"version":null,"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]},"scope":{}},"deny-set-icon":{"version":null,"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]},"scope":{}},"deny-set-ignore-cursor-events":{"version":null,"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]},"scope":{}},"deny-set-max-size":{"version":null,"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]},"scope":{}},"deny-set-maximizable":{"version":null,"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]},"scope":{}},"deny-set-min-size":{"version":null,"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]},"scope":{}},"deny-set-minimizable":{"version":null,"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]},"scope":{}},"deny-set-position":{"version":null,"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]},"scope":{}},"deny-set-progress-bar":{"version":null,"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]},"scope":{}},"deny-set-resizable":{"version":null,"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]},"scope":{}},"deny-set-shadow":{"version":null,"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]},"scope":{}},"deny-set-size":{"version":null,"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]},"scope":{}},"deny-set-skip-taskbar":{"version":null,"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]},"scope":{}},"deny-set-title":{"version":null,"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]},"scope":{}},"deny-set-visible-on-all-workspaces":{"version":null,"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]},"scope":{}},"deny-show":{"version":null,"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]},"scope":{}},"deny-start-dragging":{"version":null,"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]},"scope":{}},"deny-theme":{"version":null,"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]},"scope":{}},"deny-title":{"version":null,"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]},"scope":{}},"deny-toggle-maximize":{"version":null,"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]},"scope":{}},"deny-unmaximize":{"version":null,"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]},"scope":{}},"deny-unminimize":{"version":null,"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]},"scope":{}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file diff --git a/examples/helloworld/src-tauri/icons/128x128.png b/examples/helloworld/src-tauri/icons/128x128.png index 6be5e50..77e7d23 100644 Binary files a/examples/helloworld/src-tauri/icons/128x128.png and b/examples/helloworld/src-tauri/icons/128x128.png differ diff --git a/examples/helloworld/src-tauri/icons/128x128@2x.png b/examples/helloworld/src-tauri/icons/128x128@2x.png index e81bece..0f7976f 100644 Binary files a/examples/helloworld/src-tauri/icons/128x128@2x.png and b/examples/helloworld/src-tauri/icons/128x128@2x.png differ diff --git a/examples/helloworld/src-tauri/icons/32x32.png b/examples/helloworld/src-tauri/icons/32x32.png index a437dd5..98fda06 100644 Binary files a/examples/helloworld/src-tauri/icons/32x32.png and b/examples/helloworld/src-tauri/icons/32x32.png differ diff --git a/examples/helloworld/src-tauri/icons/Square107x107Logo.png b/examples/helloworld/src-tauri/icons/Square107x107Logo.png deleted file mode 100644 index 0ca4f27..0000000 Binary files a/examples/helloworld/src-tauri/icons/Square107x107Logo.png and /dev/null differ diff --git a/examples/helloworld/src-tauri/icons/Square142x142Logo.png b/examples/helloworld/src-tauri/icons/Square142x142Logo.png deleted file mode 100644 index b81f820..0000000 Binary files a/examples/helloworld/src-tauri/icons/Square142x142Logo.png and /dev/null differ diff --git a/examples/helloworld/src-tauri/icons/Square150x150Logo.png b/examples/helloworld/src-tauri/icons/Square150x150Logo.png deleted file mode 100644 index 624c7bf..0000000 Binary files a/examples/helloworld/src-tauri/icons/Square150x150Logo.png and /dev/null differ diff --git a/examples/helloworld/src-tauri/icons/Square284x284Logo.png b/examples/helloworld/src-tauri/icons/Square284x284Logo.png deleted file mode 100644 index c021d2b..0000000 Binary files a/examples/helloworld/src-tauri/icons/Square284x284Logo.png and /dev/null differ diff --git a/examples/helloworld/src-tauri/icons/Square30x30Logo.png b/examples/helloworld/src-tauri/icons/Square30x30Logo.png deleted file mode 100644 index 6219700..0000000 Binary files a/examples/helloworld/src-tauri/icons/Square30x30Logo.png and /dev/null differ diff --git a/examples/helloworld/src-tauri/icons/Square310x310Logo.png b/examples/helloworld/src-tauri/icons/Square310x310Logo.png deleted file mode 100644 index f9bc048..0000000 Binary files a/examples/helloworld/src-tauri/icons/Square310x310Logo.png and /dev/null differ diff --git a/examples/helloworld/src-tauri/icons/Square44x44Logo.png b/examples/helloworld/src-tauri/icons/Square44x44Logo.png deleted file mode 100644 index d5fbfb2..0000000 Binary files a/examples/helloworld/src-tauri/icons/Square44x44Logo.png and /dev/null differ diff --git a/examples/helloworld/src-tauri/icons/Square71x71Logo.png b/examples/helloworld/src-tauri/icons/Square71x71Logo.png deleted file mode 100644 index 63440d7..0000000 Binary files a/examples/helloworld/src-tauri/icons/Square71x71Logo.png and /dev/null differ diff --git a/examples/helloworld/src-tauri/icons/Square89x89Logo.png b/examples/helloworld/src-tauri/icons/Square89x89Logo.png deleted file mode 100644 index f3f705a..0000000 Binary files a/examples/helloworld/src-tauri/icons/Square89x89Logo.png and /dev/null differ diff --git a/examples/helloworld/src-tauri/icons/StoreLogo.png b/examples/helloworld/src-tauri/icons/StoreLogo.png deleted file mode 100644 index 4556388..0000000 Binary files a/examples/helloworld/src-tauri/icons/StoreLogo.png and /dev/null differ diff --git a/examples/helloworld/src-tauri/icons/icon.icns b/examples/helloworld/src-tauri/icons/icon.icns index 12a5bce..29d6685 100644 Binary files a/examples/helloworld/src-tauri/icons/icon.icns and b/examples/helloworld/src-tauri/icons/icon.icns differ diff --git a/examples/helloworld/src-tauri/icons/icon.ico b/examples/helloworld/src-tauri/icons/icon.ico index b3636e4..06c23c8 100644 Binary files a/examples/helloworld/src-tauri/icons/icon.ico and b/examples/helloworld/src-tauri/icons/icon.ico differ diff --git a/examples/helloworld/src-tauri/icons/icon.png b/examples/helloworld/src-tauri/icons/icon.png index e1cd261..d1756ce 100644 Binary files a/examples/helloworld/src-tauri/icons/icon.png and b/examples/helloworld/src-tauri/icons/icon.png differ diff --git a/examples/helloworld/src-tauri/src/lib.rs b/examples/helloworld/src-tauri/src/lib.rs new file mode 100644 index 0000000..f520eb8 --- /dev/null +++ b/examples/helloworld/src-tauri/src/lib.rs @@ -0,0 +1,26 @@ +use serde_json::json; + +#[tauri::command] +fn greet(name: &str) -> String { + format!("Hello, {}! You've been greeted from Rust!", name) +} + +#[tauri::command] +fn this_will_panic() { + panic!("I told you!"); +} + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +pub fn run() { + tauri::Builder::default() + .invoke_handler(tauri::generate_handler![greet, this_will_panic]) + .plugin(tauri_plugin_aptabase::Builder::new("A-US-0928558097").with_panic_hook(Box::new(|client, info, msg| { + let location = info.location().map(|loc| format!("{}:{}:{}", loc.file(), loc.line(), loc.column())).unwrap_or_else(|| "".to_string()); + + client.track_event("panic", Some(json!({ + "info": format!("{} ({})", msg, location), + }))); + })).build()) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} diff --git a/examples/helloworld/src-tauri/src/main.rs b/examples/helloworld/src-tauri/src/main.rs index 5b1292d..455963e 100644 --- a/examples/helloworld/src-tauri/src/main.rs +++ b/examples/helloworld/src-tauri/src/main.rs @@ -1,43 +1,6 @@ -#![cfg_attr( - all(not(debug_assertions), target_os = "windows"), - windows_subsystem = "windows" -)] - -use tauri_plugin_log::LogTarget; -use tauri_plugin_aptabase::EventTracker; -use serde_json::json; - -#[tauri::command] -fn this_will_panic() { - panic!("I told you!"); -} +// Prevents additional console window on Windows in release, DO NOT REMOVE!! +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { - tauri::Builder::default() - .invoke_handler(tauri::generate_handler![this_will_panic]) - .plugin(tauri_plugin_aptabase::Builder::new("A-DEV-0000000000").with_panic_hook(Box::new(|client, info, msg| { - let location = info.location().map(|loc| format!("{}:{}:{}", loc.file(), loc.line(), loc.column())).unwrap_or_else(|| "".to_string()); - - client.track_event("panic", Some(json!({ - "info": format!("{} ({})", msg, location), - }))); - })).build()) - .plugin(tauri_plugin_log::Builder::default().targets([ - LogTarget::LogDir, - LogTarget::Stdout, - LogTarget::Webview, - ]).build()) - .setup(|app| { - app.track_event("app_started", None); - Ok(()) - }) - .build(tauri::generate_context!()) - .expect("error while running tauri application") - .run(|handler, event| match event { - tauri::RunEvent::Exit { .. } => { - handler.track_event("app_exit", None); - handler.flush_events_blocking(); - } - _ => {} - }) + tauri_app_lib::run(); } diff --git a/examples/helloworld/src-tauri/tauri.conf.json b/examples/helloworld/src-tauri/tauri.conf.json index b78cc60..b028d19 100644 --- a/examples/helloworld/src-tauri/tauri.conf.json +++ b/examples/helloworld/src-tauri/tauri.conf.json @@ -1,70 +1,37 @@ { + "productName": "tauri-app", + "version": "0.0.0", + "identifier": "com.tauri.dev", "build": { "beforeDevCommand": "npm run dev:vite", "beforeBuildCommand": "npm run build", - "devPath": "http://localhost:1420", - "distDir": "../dist", - "withGlobalTauri": false + "devUrl": "http://localhost:1420", + "frontendDist": "../dist" }, - "package": { - "productName": "helloworld", - "version": "0.0.0" - }, - "tauri": { - "allowlist": { - "all": false, - "shell": { - "all": false, - "open": true - } - }, - "bundle": { - "active": true, - "category": "DeveloperTool", - "copyright": "", - "deb": { - "depends": [] - }, - "externalBin": [], - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "identifier": "com.aptabase.HelloWorldTauri", - "longDescription": "", - "macOS": { - "entitlements": null, - "exceptionDomain": "", - "frameworks": [], - "providerShortName": null, - "signingIdentity": null - }, - "resources": [], - "shortDescription": "", - "targets": "all", - "windows": { - "certificateThumbprint": null, - "digestAlgorithm": "sha256", - "timestampUrl": "" - } - }, + "app": { + "withGlobalTauri": false, "security": { "csp": null }, - "updater": { - "active": false - }, "windows": [ { "fullscreen": false, "height": 600, "resizable": true, - "title": "Tauri + Aptabase", + "title": "tauri-app", "width": 800 } ] + }, + "bundle": { + "active": true, + "targets": "all", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ] } } diff --git a/examples/helloworld/src/App.css b/examples/helloworld/src/App.css deleted file mode 100644 index a89ebd1..0000000 --- a/examples/helloworld/src/App.css +++ /dev/null @@ -1,7 +0,0 @@ -.logo.vite:hover { - filter: drop-shadow(0 0 2em #747bff); -} - -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafb); -} diff --git a/examples/helloworld/src/App.svelte b/examples/helloworld/src/App.svelte new file mode 100644 index 0000000..126b4a4 --- /dev/null +++ b/examples/helloworld/src/App.svelte @@ -0,0 +1,47 @@ + + +
+

Welcome to Tauri!

+ +
+ + + + + + + + + +
+ +

+ Click on the Tauri, Vite, and Svelte logos to learn more. +

+ +
+ +
+ +
+ +
+ +
+ + diff --git a/examples/helloworld/src/App.tsx b/examples/helloworld/src/App.tsx deleted file mode 100644 index a20447d..0000000 --- a/examples/helloworld/src/App.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import reactLogo from "./assets/react.svg"; -import { trackEvent } from '@aptabase/tauri' -import "./App.css"; -import { invoke } from "@tauri-apps/api"; - -function App() { - function clickVite() { - trackEvent("logo_click", { "logo": "vite", count: 1 }) - } - - function clickTauri() { - trackEvent("logo_click", { "logo": "tauri", count: 1 }) - } - - function clickReact() { - trackEvent("logo_click", { "logo": "react", count: 1 }) - } - - function panic() { - invoke("this_will_panic") - } - - return ( -
-

Welcome to Tauri + Aptabase Example!

- -
- - - -
- -

Click on the Tauri, Vite, and React logos to trigger an event.

- -
- -
-
- ); -} - -export default App; diff --git a/examples/helloworld/src/assets/react.svg b/examples/helloworld/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/examples/helloworld/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/examples/helloworld/src/lib/Greet.svelte b/examples/helloworld/src/lib/Greet.svelte new file mode 100644 index 0000000..91b9989 --- /dev/null +++ b/examples/helloworld/src/lib/Greet.svelte @@ -0,0 +1,24 @@ + + +
+
+ + +
+

{greetMsg}

+
+ diff --git a/examples/helloworld/src/main.js b/examples/helloworld/src/main.js new file mode 100644 index 0000000..6b4e1a9 --- /dev/null +++ b/examples/helloworld/src/main.js @@ -0,0 +1,8 @@ +import "./style.css"; +import App from "./App.svelte"; + +const app = new App({ + target: document.getElementById("app"), +}); + +export default app; diff --git a/examples/helloworld/src/main.tsx b/examples/helloworld/src/main.tsx deleted file mode 100644 index 7d6d78e..0000000 --- a/examples/helloworld/src/main.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; -import App from "./App"; -import "./style.css"; - -ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( - - - -); diff --git a/examples/helloworld/src/vite-env.d.ts b/examples/helloworld/src/vite-env.d.ts index 11f02fe..4078e74 100644 --- a/examples/helloworld/src/vite-env.d.ts +++ b/examples/helloworld/src/vite-env.d.ts @@ -1 +1,2 @@ +/// /// diff --git a/examples/helloworld/tsconfig.json b/examples/helloworld/tsconfig.json deleted file mode 100644 index 3d0a51a..0000000 --- a/examples/helloworld/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "allowJs": false, - "skipLibCheck": true, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "module": "ESNext", - "moduleResolution": "Node", - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx" - }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }] -} diff --git a/examples/helloworld/tsconfig.node.json b/examples/helloworld/tsconfig.node.json deleted file mode 100644 index 9d31e2a..0000000 --- a/examples/helloworld/tsconfig.node.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "composite": true, - "module": "ESNext", - "moduleResolution": "Node", - "allowSyntheticDefaultImports": true - }, - "include": ["vite.config.ts"] -} diff --git a/examples/helloworld/vite.config.js b/examples/helloworld/vite.config.js new file mode 100644 index 0000000..4e1a260 --- /dev/null +++ b/examples/helloworld/vite.config.js @@ -0,0 +1,25 @@ +import { defineConfig } from "vite"; +import { svelte } from "@sveltejs/vite-plugin-svelte"; +import { internalIpV4Sync } from 'internal-ip' + +const mobile = !!/android|ios/.exec(process.env.TAURI_ENV_PLATFORM); + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [svelte()], + + // Vite optons tailored for Tauri development and only applied in `tauri dev` or `tauri build` + // prevent vite from obscuring rust errors + clearScreen: false, + // tauri expects a fixed port, fail if that port is not available + server: { + host: mobile ? "0.0.0.0" : false, + port: 1420, + strictPort: true, + hmr: mobile ? { + protocol: 'ws', + host: internalIpV4Sync(), + port: 1421 + } : undefined, + }, +}) diff --git a/examples/helloworld/vite.config.ts b/examples/helloworld/vite.config.ts deleted file mode 100644 index ee4440d..0000000 --- a/examples/helloworld/vite.config.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react()], - - // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` - // prevent vite from obscuring rust errors - clearScreen: false, - // tauri expects a fixed port, fail if that port is not available - server: { - port: 1420, - strictPort: true, - }, - // to make use of `TAURI_DEBUG` and other env variables - // https://tauri.studio/v1/api/config#buildconfig.beforedevcommand - envPrefix: ["VITE_", "TAURI_"], - build: { - // Tauri supports es2021 - target: process.env.TAURI_PLATFORM == "windows" ? "chrome105" : "safari13", - // don't minify for debug builds - minify: !process.env.TAURI_DEBUG ? "esbuild" : false, - // produce sourcemaps for debug builds - sourcemap: !!process.env.TAURI_DEBUG, - }, -}); diff --git a/package.json b/package.json index 72d4e14..2c16439 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "@aptabase/tauri", "version": "0.4.2", "private": false, + "type": "module", "description": "Tauri Plugin for Aptabase: Open Source, Privacy-First and Simple Analytics for Mobile, Desktop and Web Apps", "author": "Guilherme Oenning", "browser": "webview-dist/index.js", @@ -18,8 +19,8 @@ "scripts": { "build": "rollup -c ./webview-src/rollup.config.js", "watch": "rollup -c ./webview-src/rollup.config.js -w", - "prepublishOnly": "yarn build", - "pretest": "yarn build" + "prepublishOnly": "npm run build", + "pretest": "npm run build" }, "files": [ "README.md", @@ -28,15 +29,14 @@ "package.json" ], "devDependencies": { - "@rollup/plugin-node-resolve": "15.0.1", - "@rollup/plugin-typescript": "11.0.0", - "rollup": "2.78.0", - "rollup-plugin-terser": "7.0.2", - "typescript": "5.0.2", - "tslib": "2.5.0", - "@tauri-apps/api": "1.2.0" + "@rollup/plugin-node-resolve": "^15.3.0", + "@rollup/plugin-typescript": "^12.1.1", + "@rollup/plugin-terser": "^0.4.4", + "rollup": "^4.27.4", + "typescript": "^5.7.2" }, "dependencies": { - "@tauri-apps/api": "^1.0.0" + "@tauri-apps/api": "^2.1.1", + "tslib": "^2.8.1" } } diff --git a/permissions/autogenerated/commands/track_event.toml b/permissions/autogenerated/commands/track_event.toml new file mode 100644 index 0000000..02d667d --- /dev/null +++ b/permissions/autogenerated/commands/track_event.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-track-event" +description = "Enables the track_event command without any pre-configured scope." +commands.allow = ["track_event"] + +[[permission]] +identifier = "deny-track-event" +description = "Denies the track_event command without any pre-configured scope." +commands.deny = ["track_event"] diff --git a/permissions/autogenerated/reference.md b/permissions/autogenerated/reference.md new file mode 100644 index 0000000..3c0486b --- /dev/null +++ b/permissions/autogenerated/reference.md @@ -0,0 +1,36 @@ + +## Permission Table + + + + + + + + + + + + + + + + + +
IdentifierDescription
+ +`aptabase:allow-track-event` + + + +Enables the track_event command without any pre-configured scope. + +
+ +`aptabase:deny-track-event` + + + +Denies the track_event command without any pre-configured scope. + +
diff --git a/permissions/schemas/schema.json b/permissions/schemas/schema.json new file mode 100644 index 0000000..f13b11b --- /dev/null +++ b/permissions/schemas/schema.json @@ -0,0 +1,310 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "PermissionFile", + "description": "Permission file that can define a default permission, a set of permissions or a list of inlined permissions.", + "type": "object", + "properties": { + "default": { + "description": "The default permission set for the plugin", + "anyOf": [ + { + "$ref": "#/definitions/DefaultPermission" + }, + { + "type": "null" + } + ] + }, + "set": { + "description": "A list of permissions sets defined", + "type": "array", + "items": { + "$ref": "#/definitions/PermissionSet" + } + }, + "permission": { + "description": "A list of inlined permissions", + "default": [], + "type": "array", + "items": { + "$ref": "#/definitions/Permission" + } + } + }, + "definitions": { + "DefaultPermission": { + "description": "The default permission set of the plugin.\n\nWorks similarly to a permission with the \"default\" identifier.", + "type": "object", + "required": [ + "permissions" + ], + "properties": { + "version": { + "description": "The version of the permission.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 1.0 + }, + "description": { + "description": "Human-readable description of what the permission does. Tauri convention is to use

headings in markdown content for Tauri documentation generation purposes.", + "type": [ + "string", + "null" + ] + }, + "permissions": { + "description": "All permissions this set contains.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "PermissionSet": { + "description": "A set of direct permissions grouped together under a new name.", + "type": "object", + "required": [ + "description", + "identifier", + "permissions" + ], + "properties": { + "identifier": { + "description": "A unique identifier for the permission.", + "type": "string" + }, + "description": { + "description": "Human-readable description of what the permission does.", + "type": "string" + }, + "permissions": { + "description": "All permissions this set contains.", + "type": "array", + "items": { + "$ref": "#/definitions/PermissionKind" + } + } + } + }, + "Permission": { + "description": "Descriptions of explicit privileges of commands.\n\nIt can enable commands to be accessible in the frontend of the application.\n\nIf the scope is defined it can be used to fine grain control the access of individual or multiple commands.", + "type": "object", + "required": [ + "identifier" + ], + "properties": { + "version": { + "description": "The version of the permission.", + "type": [ + "integer", + "null" + ], + "format": "uint64", + "minimum": 1.0 + }, + "identifier": { + "description": "A unique identifier for the permission.", + "type": "string" + }, + "description": { + "description": "Human-readable description of what the permission does. Tauri internal convention is to use

headings in markdown content for Tauri documentation generation purposes.", + "type": [ + "string", + "null" + ] + }, + "commands": { + "description": "Allowed or denied commands when using this permission.", + "default": { + "allow": [], + "deny": [] + }, + "allOf": [ + { + "$ref": "#/definitions/Commands" + } + ] + }, + "scope": { + "description": "Allowed or denied scoped when using this permission.", + "allOf": [ + { + "$ref": "#/definitions/Scopes" + } + ] + }, + "platforms": { + "description": "Target platforms this permission applies. By default all platforms are affected by this permission.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Target" + } + } + } + }, + "Commands": { + "description": "Allowed and denied commands inside a permission.\n\nIf two commands clash inside of `allow` and `deny`, it should be denied by default.", + "type": "object", + "properties": { + "allow": { + "description": "Allowed command.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + }, + "deny": { + "description": "Denied command, which takes priority.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "Scopes": { + "description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```", + "type": "object", + "properties": { + "allow": { + "description": "Data that defines what is allowed by the scope.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Value" + } + }, + "deny": { + "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Value" + } + } + } + }, + "Value": { + "description": "All supported ACL values.", + "anyOf": [ + { + "description": "Represents a null JSON value.", + "type": "null" + }, + { + "description": "Represents a [`bool`].", + "type": "boolean" + }, + { + "description": "Represents a valid ACL [`Number`].", + "allOf": [ + { + "$ref": "#/definitions/Number" + } + ] + }, + { + "description": "Represents a [`String`].", + "type": "string" + }, + { + "description": "Represents a list of other [`Value`]s.", + "type": "array", + "items": { + "$ref": "#/definitions/Value" + } + }, + { + "description": "Represents a map of [`String`] keys to [`Value`]s.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/Value" + } + } + ] + }, + "Number": { + "description": "A valid ACL number.", + "anyOf": [ + { + "description": "Represents an [`i64`].", + "type": "integer", + "format": "int64" + }, + { + "description": "Represents a [`f64`].", + "type": "number", + "format": "double" + } + ] + }, + "Target": { + "description": "Platform target.", + "oneOf": [ + { + "description": "MacOS.", + "type": "string", + "enum": [ + "macOS" + ] + }, + { + "description": "Windows.", + "type": "string", + "enum": [ + "windows" + ] + }, + { + "description": "Linux.", + "type": "string", + "enum": [ + "linux" + ] + }, + { + "description": "Android.", + "type": "string", + "enum": [ + "android" + ] + }, + { + "description": "iOS.", + "type": "string", + "enum": [ + "iOS" + ] + } + ] + }, + "PermissionKind": { + "type": "string", + "oneOf": [ + { + "description": "Enables the track_event command without any pre-configured scope.", + "type": "string", + "const": "allow-track-event" + }, + { + "description": "Denies the track_event command without any pre-configured scope.", + "type": "string", + "const": "deny-track-event" + } + ] + } + } +} \ No newline at end of file diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..43d4840 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +newline_style = "Unix" diff --git a/src/client.rs b/src/client.rs index 5f3f2a7..da9d905 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,12 +1,16 @@ -use std::time::{SystemTime, UNIX_EPOCH}; use rand::Rng; use serde_json::{json, Value}; -use std::{sync::{Arc, Mutex as SyncMutex}, time::Duration}; +use std::time::{SystemTime, UNIX_EPOCH}; +use std::{ + sync::{Arc, Mutex as SyncMutex}, + time::Duration, +}; use time::{format_description::well_known::Rfc3339, OffsetDateTime}; use crate::{ config::Config, - sys::{self, SystemProperties}, dispatcher::EventDispatcher, + dispatcher::EventDispatcher, + sys::{self, SystemProperties}, }; static SESSION_TIMEOUT: Duration = Duration::from_secs(4 * 60 * 60); @@ -17,12 +21,12 @@ fn new_session_id() -> String { .expect("time went backwards") .as_secs(); - let mut rng = rand::thread_rng(); - let random: u64 = rng.gen_range(0..=99999999); + let mut rng = rand::rng(); + let random: u64 = rng.random_range(0..=99999999); let id = epoch_in_seconds * 100_000_000 + random; - return id.to_string(); + id.to_string() } /// A tracking session. @@ -34,7 +38,7 @@ pub struct TrackingSession { impl TrackingSession { fn new() -> Self { - TrackingSession { + Self { id: new_session_id(), last_touch_ts: OffsetDateTime::now_utc(), } @@ -51,7 +55,6 @@ pub struct AptabaseClient { } impl AptabaseClient { - /// Creates a new Aptabase client. pub fn new(config: &Config, app_version: String) -> Self { let sys_info = sys::get_info(); @@ -59,7 +62,7 @@ impl AptabaseClient { let is_enabled = !config.app_key.is_empty(); let dispatcher = Arc::new(EventDispatcher::new(config, &sys_info)); - AptabaseClient { + Self { is_enabled, dispatcher, session: SyncMutex::new(TrackingSession::new()), @@ -67,12 +70,12 @@ impl AptabaseClient { sys_info, } } - + /// Starts the event dispatcher loop. pub(crate) fn start_polling(&self, interval: Duration) { let dispatcher = self.dispatcher.clone(); - tauri::async_runtime::spawn(async move { + tokio::spawn(async move { loop { tokio::time::sleep(interval).await; dispatcher.flush().await; @@ -90,13 +93,23 @@ impl AptabaseClient { } else { session.last_touch_ts = now; } - return session.id.clone(); + + session.id.clone() } /// Enqueues an event to be sent to the server. - pub fn track_event(&self, name: &str, props: Option) { + pub fn track_event(&self, name: &str, props: Option) -> Result<(), String> { if !self.is_enabled { - return; + return Ok(()); + } + + if let Some(props) = &props { + if !matches!(props, Value::Object(_)) { + return Err( + "props must be `None` or the `Object` variation of `serde_json::Value`" + .to_owned(), + ); + } } let ev = json!({ @@ -117,6 +130,8 @@ impl AptabaseClient { }); self.dispatcher.enqueue(ev); + + Ok(()) } /// Flushes the event queue. @@ -126,7 +141,7 @@ impl AptabaseClient { /// Flushes the event queue, blocking the current thread. pub fn flush_blocking(&self) { - tauri::async_runtime::block_on(async { + futures::executor::block_on(async { self.flush().await; }); } diff --git a/src/commands.rs b/src/commands.rs index 0755c35..21839a9 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1,14 +1,14 @@ -use std::sync::Arc; use serde_json::Value; +use std::sync::Arc; use tauri::{command, State}; use crate::client::AptabaseClient; #[command] pub fn track_event( - client: State<'_, Arc>, - name: &str, - props: Option, -) { - client.track_event(name, props); -} \ No newline at end of file + client: State<'_, Arc>, + name: &str, + props: Option, +) -> Result<(), String> { + client.track_event(name, props) +} diff --git a/src/config.rs b/src/config.rs index 1b78d87..1985f11 100644 --- a/src/config.rs +++ b/src/config.rs @@ -22,13 +22,16 @@ static DEFAULT_FLUSH_INTERVAL: Duration = Duration::from_secs(60); #[cfg(debug_assertions)] static DEFAULT_FLUSH_INTERVAL: Duration = Duration::from_secs(2); -const VALID_REGIONS: &'static [&'static str] = &["US", "EU", "DEV", "SH"]; +const VALID_REGIONS: &[&str] = &["US", "EU", "DEV", "SH"]; impl Config { pub fn new(app_key: String, opts: InitOptions) -> Self { let parts = app_key.split("-").collect::>(); if parts.len() != 3 || !VALID_REGIONS.contains(&parts[1]) { - debug!("The Aptabase App Key '{}' is invalid. Tracking will be disabled.", app_key); + debug!( + "The Aptabase App Key '{}' is invalid. Tracking will be disabled.", + app_key + ); return Config::default(); } @@ -43,24 +46,24 @@ impl Config { debug!("Host parameter must be defined when using Self-Hosted App Key. Tracking will be disabled."); return Config::default(); } - }, + } _ => return Config::default(), }; - Config { + Self { app_key, ingest_api_url: format!("{}/api/v0/events", base_url).parse().unwrap(), - flush_interval: opts.flush_interval.clone().unwrap_or(DEFAULT_FLUSH_INTERVAL) + flush_interval: opts.flush_interval.unwrap_or(DEFAULT_FLUSH_INTERVAL), } } } impl Default for Config { fn default() -> Self { - return Config { + Self { app_key: String::new(), ingest_api_url: Url::parse(LOCAL).unwrap(), flush_interval: DEFAULT_FLUSH_INTERVAL, - }; + } } } diff --git a/src/dispatcher.rs b/src/dispatcher.rs index 76698cb..b4885a4 100644 --- a/src/dispatcher.rs +++ b/src/dispatcher.rs @@ -1,8 +1,16 @@ -use std::{collections::VecDeque, time::Duration, cmp::min, sync::{Arc, RwLock}}; +use std::{ + cmp::min, + collections::VecDeque, + sync::{Arc, RwLock}, + time::Duration, +}; use log::{debug, trace}; -use reqwest::{header::{HeaderMap, HeaderValue}, Url}; -use serde_json::{Value, json}; +use reqwest::{ + header::{HeaderMap, HeaderValue}, + Url, +}; +use serde_json::{json, Value}; use crate::{config::Config, sys::SystemProperties}; @@ -22,17 +30,20 @@ impl EventDispatcher { headers.insert("App-Key", app_key_header); headers.insert("Content-Type", HeaderValue::from_static("application/json")); - let user_agent = format!("{}/{} {}/{} {}", sys.os_name, sys.os_version, sys.engine_name, sys.engine_version, sys.locale); + let user_agent = format!( + "{}/{} {}/{} {}", + sys.os_name, sys.os_version, sys.engine_name, sys.engine_version, sys.locale + ); let http_client = reqwest::Client::builder() .timeout(HTTP_REQUEST_TIMEOUT) .default_headers(headers) .user_agent(user_agent) .build() .expect("could not build http client"); - + let queue = Arc::new(RwLock::new(VecDeque::new())); - EventDispatcher { + Self { url: config.ingest_api_url.clone(), queue, http_client, @@ -40,7 +51,7 @@ impl EventDispatcher { } pub fn is_empty(&self) -> bool { - let queue = self.queue.read().expect("could not lock queue for reading"); + let queue = self.queue.read().expect("could not lock queue for reading"); queue.is_empty() } @@ -54,7 +65,7 @@ impl EventDispatcher { queue.extend(events); } - fn dequeue_many(&self, max: usize) -> Vec { + fn dequeue_many(&self, max: usize) -> Vec { let mut queue = self.queue.write().expect("could not lock queue"); if queue.is_empty() { return Vec::new(); @@ -79,26 +90,29 @@ impl EventDispatcher { } trace!("preparing {} events to send", events_to_send.len()); - + let body = json!(events_to_send); - let response = self.http_client.post(self.url.clone()).json(&body).send().await; + let response = self + .http_client + .post(self.url.clone()) + .json(&body) + .send() + .await; match response { - Ok(response) => { - match response.status().is_success() { - true => { - trace!("sent {} tracking events", events_to_send.len()); - }, - false => { - debug!( - "failed to track_event with status code {}", - response.status() - ); - if response.status().is_server_error() { - failed_items.extend(events_to_send); - } + Ok(response) => match response.status().is_success() { + true => { + trace!("sent {} tracking events", events_to_send.len()); + } + false => { + debug!( + "failed to track_event with status code {}", + response.status() + ); + if response.status().is_server_error() { + failed_items.extend(events_to_send); } } - } + }, Err(err) => { failed_items.extend(events_to_send); debug!("failed to track_event: {}", err.to_string()); diff --git a/src/lib.rs b/src/lib.rs index 51cea4d..a2b747c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,150 +1,144 @@ -mod config; mod client; mod commands; -mod sys; +mod config; mod dispatcher; +mod sys; -use std::{sync::Arc, panic::PanicInfo, time::Duration, thread::sleep}; +use std::{panic::PanicInfo, sync::Arc, time::Duration}; +use client::AptabaseClient; use config::Config; use serde_json::Value; -use client::AptabaseClient; use tauri::{ - plugin::{TauriPlugin, self}, - Runtime, Manager, App, AppHandle, Window, RunEvent, + plugin::{self, TauriPlugin}, + App, AppHandle, Manager, RunEvent, Runtime, Window, }; #[derive(Default, Debug, Clone)] pub struct InitOptions { - pub host: Option, - pub flush_interval: Option, + pub host: Option, + pub flush_interval: Option, } - /// The Aptabase Plugin builder pub struct Builder { - app_key: String, - panic_hook: Option, - options: InitOptions + app_key: String, + panic_hook: Option, + options: InitOptions, } pub type PanicHook = - Box, String) + 'static + Sync + Send>; + Box, String) + 'static + Sync + Send>; fn get_panic_message(info: &PanicInfo) -> String { - let payload = info.payload(); - if let Some(s) = payload.downcast_ref::<&str>() { - return s.to_string(); - } else if let Some(s) = payload.downcast_ref::() { - return s.to_string(); - } - - return format!("{:?}", payload); + let payload = info.payload(); + if let Some(s) = payload.downcast_ref::<&str>() { + return s.to_string(); + } else if let Some(s) = payload.downcast_ref::() { + return s.to_string(); + } + + format!("{:?}", payload) } impl Builder { /// Creates a new builder. pub fn new(app_key: &str) -> Self { - Builder { - app_key: app_key.into(), - panic_hook: None, - options: Default::default() - } + Self { + app_key: app_key.into(), + panic_hook: None, + options: Default::default(), + } } - /// Sets custom topions to use for the Aptabase client. + /// Sets custom options to use for the Aptabase client. pub fn with_options(mut self, opts: InitOptions) -> Self { - self.options = opts; - self + self.options = opts; + self } /// Sets a custom panic hook. pub fn with_panic_hook(mut self, hook: PanicHook) -> Self { - self.panic_hook = Some(hook); - self + self.panic_hook = Some(hook); + self } /// Builds and initializes the plugin pub fn build(self) -> TauriPlugin { - plugin::Builder::new("aptabase") - .invoke_handler(tauri::generate_handler![ - commands::track_event - ]) - .setup(|app| { - let cfg = Config::new(self.app_key, self.options); - let app_version = app.package_info().version.to_string(); - let client = Arc::new(AptabaseClient::new(&cfg, app_version)); - - client.start_polling(cfg.flush_interval); - - if let Some(hook) = self.panic_hook { - let default_panic = std::panic::take_hook(); - let hook_client = client.clone(); - std::panic::set_hook(Box::new(move |info| { - let msg = get_panic_message(info); - hook(&hook_client, info, msg); - - let _ = hook_client.flush(); - sleep(std::time::Duration::from_secs(2)); - - default_panic(info); - })); - } - - app.manage(client); - Ok(()) - }) - .on_event(move |app, event| { - if let RunEvent::Exit = event { - let client = app.state::>(); - client.flush_blocking(); - } - }) - .build() + plugin::Builder::new("aptabase") + .invoke_handler(tauri::generate_handler![commands::track_event]) + .setup(|app, _api| { + let cfg = Config::new(self.app_key, self.options); + let app_version = app.package_info().version.to_string(); + let client = Arc::new(AptabaseClient::new(&cfg, app_version)); + + client.start_polling(cfg.flush_interval); + + if let Some(hook) = self.panic_hook { + let default_panic = std::panic::take_hook(); + let hook_client = client.clone(); + std::panic::set_hook(Box::new(move |info| { + let msg = get_panic_message(info); + hook(&hook_client, info, msg); + hook_client.flush_blocking(); + default_panic(info); + })); + } + + app.manage(client); + Ok(()) + }) + .on_event(move |app, event| { + if let RunEvent::Exit = event { + let client = app.state::>(); + client.flush_blocking(); + } + }) + .build() } } /// Trait implemented by Tauri handlers pub trait EventTracker { - /// Enqueues an event to be sent to the server. - fn track_event(&self, name: &str, props: Option); + /// Enqueues an event to be sent to the server. + fn track_event(&self, name: &str, props: Option) -> Result<(), String>; - /// Flushes the event queue, blocking the current thread. - fn flush_events_blocking(&self); + /// Flushes the event queue, blocking the current thread. + fn flush_events_blocking(&self); } impl EventTracker for App { - fn track_event(&self, name: &str, props: Option) { - let client = self.state::>(); - client.track_event(name, props); + fn track_event(&self, name: &str, props: Option) -> Result<(), String> { + let client = self.state::>(); + client.track_event(name, props) } fn flush_events_blocking(&self) { - let client = self.state::>(); - client.flush_blocking(); + let client = self.state::>(); + client.flush_blocking(); } } impl EventTracker for AppHandle { - fn track_event(&self, name: &str, props: Option) { - let client = self.state::>(); - client.track_event(name, props); + fn track_event(&self, name: &str, props: Option) -> Result<(), String> { + let client = self.state::>(); + client.track_event(name, props) } fn flush_events_blocking(&self) { - let client = self.state::>(); - client.flush_blocking(); + let client = self.state::>(); + client.flush_blocking(); } } impl EventTracker for Window { - fn track_event(&self, name: &str, props: Option) { - let client = self.state::>(); - client.track_event(name, props); + fn track_event(&self, name: &str, props: Option) -> Result<(), String> { + let client = self.state::>(); + client.track_event(name, props) } fn flush_events_blocking(&self) { - let client = self.state::>(); - client.flush_blocking(); + let client = self.state::>(); + client.flush_blocking(); } -} \ No newline at end of file +} diff --git a/src/sys.rs b/src/sys.rs index 6dafa4b..ad13467 100644 --- a/src/sys.rs +++ b/src/sys.rs @@ -1,4 +1,4 @@ -use tauri::{api::os::locale, webview_version}; +use tauri::webview_version; #[cfg(target_os = "linux")] static ENGINE_NAME: &str = "WebKitGTK"; @@ -9,7 +9,6 @@ static ENGINE_NAME: &str = "WebKit"; #[cfg(target_os = "windows")] static ENGINE_NAME: &str = "WebView2"; - #[cfg(debug_assertions)] static IS_DEBUG: bool = true; @@ -27,12 +26,13 @@ pub struct SystemProperties { pub fn get_info() -> SystemProperties { let info = os_info::get(); - let locale = locale().unwrap_or_default(); + let locale = sys_locale::get_locale().unwrap_or_default(); let engine_version = webview_version().unwrap_or_default(); let os_name = match info.os_type() { os_info::Type::Macos => "macOS".to_string(), os_info::Type::Windows => "Windows".to_string(), + _ if std::env::var("container").is_ok() => "Flatpak".to_string(), _ => info.os_type().to_string(), }; diff --git a/webview-dist/index.d.ts b/webview-dist/index.d.ts new file mode 100644 index 0000000..dab0a4e --- /dev/null +++ b/webview-dist/index.d.ts @@ -0,0 +1,5 @@ +type Props = { + [key: string]: string | number; +}; +export declare function trackEvent(name: string, props?: Props): Promise; +export {}; diff --git a/webview-dist/index.js b/webview-dist/index.js new file mode 100644 index 0000000..5f0290a --- /dev/null +++ b/webview-dist/index.js @@ -0,0 +1 @@ +function n(n,e,r,t){return new(r||(r=Promise))((function(o,u){function i(n){try{p(t.next(n))}catch(n){u(n)}}function c(n){try{p(t.throw(n))}catch(n){u(n)}}function p(n){var e;n.done?o(n.value):(e=n.value,e instanceof r?e:new r((function(n){n(e)}))).then(i,c)}p((t=t.apply(n,e||[])).next())}))}function e(e,r){return n(this,void 0,void 0,(function*(){yield async function(n,e={},r){return window.__TAURI_INTERNALS__.invoke(n,e,r)}("plugin:aptabase|track_event",{name:e,props:r})}))}"function"==typeof SuppressedError&&SuppressedError,"function"==typeof SuppressedError&&SuppressedError;export{e as trackEvent}; diff --git a/webview-src/index.ts b/webview-src/index.ts index 5bfec07..f98960f 100644 --- a/webview-src/index.ts +++ b/webview-src/index.ts @@ -1,9 +1,9 @@ -import { invoke } from '@tauri-apps/api' +import { invoke } from '@tauri-apps/api/core' type Props = { - [key: string]: string | number -} + [key: string]: string | number; +}; export async function trackEvent(name: string, props?: Props): Promise { - await invoke('plugin:aptabase|track_event', { name, props }) -} \ No newline at end of file + await invoke('plugin:aptabase|track_event', { name, props }); +} diff --git a/webview-src/rollup.config.js b/webview-src/rollup.config.js index a9038e2..bf8450c 100644 --- a/webview-src/rollup.config.js +++ b/webview-src/rollup.config.js @@ -1,6 +1,6 @@ import { nodeResolve } from '@rollup/plugin-node-resolve' -import { terser } from 'rollup-plugin-terser' import typescript from '@rollup/plugin-typescript' +import terser from '@rollup/plugin-terser' export default { input: './webview-src/index.ts', @@ -10,9 +10,6 @@ export default { format: 'es', exports: 'auto' }, - external: [ - "@tauri-apps/api" - ], plugins: [ nodeResolve(), terser(), diff --git a/webview-src/tsconfig.json b/webview-src/tsconfig.json index a120087..816d015 100644 --- a/webview-src/tsconfig.json +++ b/webview-src/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "ES5", + "target": "ES2015", "strict": true, "allowJs": true, "esModuleInterop": true,