From b131bc8f7c9eba3b871c999d5c5ccff70bf34540 Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Tue, 23 May 2023 10:20:14 -0700 Subject: [PATCH] feat(plugins): inject API on window.__TAURI__ (#383) --- .eslintignore | 1 + .github/workflows/check-generated-files.yml | 155 +++++++++++++++ .github/workflows/check-license-header.yml | 2 +- .github/workflows/lint-rust.yml | 2 + .github/workflows/test-rust.yml | 2 + .prettierignore | 4 +- .scripts/ci/check-license-header.js | 5 +- .scripts/ci/has-diff.sh | 9 + plugins/app/guest-js/index.ts | 16 +- plugins/app/src/api-iife.js | 1 + plugins/app/src/lib.rs | 1 + plugins/authenticator/guest-js/index.ts | 46 +++-- plugins/authenticator/src/api-iife.js | 1 + plugins/authenticator/src/lib.rs | 1 + plugins/autostart/guest-js/index.ts | 12 +- plugins/autostart/src/api-iife.js | 1 + plugins/autostart/src/lib.rs | 1 + plugins/cli/guest-js/index.ts | 8 +- plugins/cli/src/api-iife.js | 1 + plugins/cli/src/lib.rs | 1 + plugins/clipboard/guest-js/index.ts | 12 +- plugins/clipboard/src/api-iife.js | 1 + plugins/clipboard/src/lib.rs | 1 + plugins/dialog/guest-js/index.ts | 16 +- plugins/dialog/src/api-iife.js | 1 + plugins/dialog/src/lib.rs | 8 +- plugins/fs/guest-js/index.ts | 53 ++--- plugins/fs/src/api-iife.js | 1 + plugins/fs/src/lib.rs | 1 + plugins/global-shortcut/guest-js/index.ts | 23 ++- plugins/global-shortcut/src/api-iife.js | 1 + plugins/global-shortcut/src/lib.rs | 1 + plugins/http/guest-js/index.ts | 58 +++--- plugins/http/src/api-iife.js | 1 + plugins/http/src/lib.rs | 1 + plugins/log/guest-js/index.ts | 9 +- plugins/log/src/api-iife.js | 1 + plugins/log/src/lib.rs | 1 + plugins/notification/src/api-iife.js | 1 + plugins/notification/src/lib.rs | 4 +- plugins/os/guest-js/index.ts | 16 +- plugins/os/src/api-iife.js | 1 + plugins/os/src/lib.rs | 1 + plugins/positioner/guest-js/index.ts | 8 +- plugins/positioner/src/api-iife.js | 1 + plugins/positioner/src/lib.rs | 5 +- plugins/process/guest-js/index.ts | 10 +- plugins/process/src/api-iife.js | 1 + plugins/process/src/lib.rs | 1 + plugins/shell/guest-js/index.ts | 19 +- plugins/shell/src/api-iife.js | 1 + plugins/shell/src/lib.rs | 5 +- plugins/sql/guest-js/index.ts | 27 +-- plugins/sql/src/api-iife.js | 1 + plugins/sql/src/plugin.rs | 1 + plugins/store/guest-js/index.ts | 31 +-- plugins/store/src/api-iife.js | 1 + plugins/store/src/lib.rs | 1 + plugins/stronghold/guest-js/index.ts | 207 +++++++++++--------- plugins/stronghold/src/api-iife.js | 1 + plugins/stronghold/src/lib.rs | 1 + plugins/updater/guest-js/index.ts | 4 +- plugins/updater/src/api-iife.js | 1 + plugins/updater/src/lib.rs | 1 + plugins/upload/src/api-iife.js | 1 + plugins/upload/src/lib.rs | 1 + plugins/websocket/guest-js/index.ts | 23 ++- plugins/websocket/src/api-iife.js | 1 + plugins/websocket/src/lib.rs | 1 + plugins/window-state/guest-js/index.ts | 13 +- plugins/window-state/src/api-iife.js | 1 + plugins/window-state/src/lib.rs | 1 + plugins/window/guest-js/event.ts | 29 ++- plugins/window/guest-js/index.ts | 166 +++++++++------- plugins/window/src/api-iife.js | 1 + plugins/window/src/lib.rs | 12 +- shared/rollup.config.mjs | 29 ++- shared/template/src/lib.rs | 1 + 78 files changed, 754 insertions(+), 337 deletions(-) create mode 100644 .github/workflows/check-generated-files.yml create mode 100755 .scripts/ci/has-diff.sh create mode 100644 plugins/app/src/api-iife.js create mode 100644 plugins/authenticator/src/api-iife.js create mode 100644 plugins/autostart/src/api-iife.js create mode 100644 plugins/cli/src/api-iife.js create mode 100644 plugins/clipboard/src/api-iife.js create mode 100644 plugins/dialog/src/api-iife.js create mode 100644 plugins/fs/src/api-iife.js create mode 100644 plugins/global-shortcut/src/api-iife.js create mode 100644 plugins/http/src/api-iife.js create mode 100644 plugins/log/src/api-iife.js create mode 100644 plugins/notification/src/api-iife.js create mode 100644 plugins/os/src/api-iife.js create mode 100644 plugins/positioner/src/api-iife.js create mode 100644 plugins/process/src/api-iife.js create mode 100644 plugins/shell/src/api-iife.js create mode 100644 plugins/sql/src/api-iife.js create mode 100644 plugins/store/src/api-iife.js create mode 100644 plugins/stronghold/src/api-iife.js create mode 100644 plugins/updater/src/api-iife.js create mode 100644 plugins/upload/src/api-iife.js create mode 100644 plugins/websocket/src/api-iife.js create mode 100644 plugins/window-state/src/api-iife.js create mode 100644 plugins/window/src/api-iife.js diff --git a/.eslintignore b/.eslintignore index 1c120ff5..efef8f77 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,4 @@ target node_modules dist dist-js +api-iife.js \ No newline at end of file diff --git a/.github/workflows/check-generated-files.yml b/.github/workflows/check-generated-files.yml new file mode 100644 index 00000000..86502340 --- /dev/null +++ b/.github/workflows/check-generated-files.yml @@ -0,0 +1,155 @@ +# Copyright 2019-2023 Tauri Programme within The Commons Conservancy +# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: MIT + +name: check generated files + +on: + pull_request: + paths: + - ".github/workflows/check-generated-files.yml" + - "**/guest-js/**" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + changes: + runs-on: ubuntu-latest + outputs: + packages: ${{ steps.filter.outputs.changes }} + steps: + - uses: actions/checkout@v3 + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + app: + - .github/workflows/check-generated-files.yml + - plugins/app/guest-js/** + - plugins/app/src/api-iife.js + authenticator: + - .github/workflows/check-generated-files.yml + - plugins/authenticator/guest-js/** + - plugins/authenticator/src/api-iife.js + autostart: + - .github/workflows/check-generated-files.yml + - plugins/autostart/guest-js/** + - plugins/autostart/src/api-iife.js + cli: + - .github/workflows/check-generated-files.yml + - plugins/cli/guest-js/** + - plugins/cli/src/api-iife.js + clipboard: + - .github/workflows/check-generated-files.yml + - plugins/clipboard/guest-js/** + - plugins/clipboard/src/api-iife.js + dialog: + - .github/workflows/check-generated-files.yml + - plugins/dialog/guest-js/** + - plugins/dialog/src/api-iife.js + fs: + - .github/workflows/check-generated-files.yml + - plugins/fs/guest-js/** + - plugins/fs/src/api-iife.js + global-shortcut: + - .github/workflows/check-generated-files.yml + - plugins/global-shortcut/guest-js/** + - plugins/global-shortcut/src/api-iife.js + http: + - .github/workflows/check-generated-files.yml + - plugins/http/guest-js/** + - plugins/http/src/api-iife.js + log: + - .github/workflows/check-generated-files.yml + - plugins/log/guest-js/** + - plugins/log/src/api-iife.js + notification: + - .github/workflows/check-generated-files.yml + - plugins/notification/guest-js/** + - plugins/notification/src/api-iife.js + os: + - .github/workflows/check-generated-files.yml + - plugins/os/guest-js/** + - plugins/os/src/api-iife.js + positioner: + - .github/workflows/check-generated-files.yml + - plugins/positioner/guest-js/** + - plugins/positioner/src/api-iife.js + process: + - .github/workflows/check-generated-files.yml + - plugins/process/guest-js/** + - plugins/process/src/api-iife.js + shell: + - .github/workflows/check-generated-files.yml + - plugins/shell/guest-js/** + - plugins/shell/src/api-iife.js + sql: + - .github/workflows/check-generated-files.yml + - plugins/sql/guest-js/** + - plugins/sql/src/api-iife.js + store: + - .github/workflows/check-generated-files.yml + - plugins/store/guest-js/** + - plugins/store/src/api-iife.js + stronghold: + - .github/workflows/check-generated-files.yml + - plugins/stronghold/guest-js/** + - plugins/stronghold/src/api-iife.js + updater: + - .github/workflows/check-generated-files.yml + - plugins/updater/guest-js/** + - plugins/updater/src/api-iife.js + upload: + - .github/workflows/check-generated-files.yml + - plugins/upload/guest-js/** + - plugins/upload/src/api-iife.js + websocket: + - .github/workflows/check-generated-files.yml + - plugins/websocket/guest-js/** + - plugins/websocket/src/api-iife.js + window: + - .github/workflows/check-generated-files.yml + - plugins/window/guest-js/** + - plugins/window/src/api-iife.js + window-state: + - .github/workflows/check-generated-files.yml + - plugins/window-state/guest-js/** + - plugins/window-state/src/api-iife.js + + test: + needs: changes + if: ${{ needs.changes.outputs.packages != '[]' && needs.changes.outputs.packages != '' }} + strategy: + fail-fast: false + matrix: + package: ${{ fromJSON(needs.changes.outputs.packages) }} + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Cache pnpm modules + uses: actions/cache@v3 + with: + path: ~/.pnpm-store + key: ${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}- + - uses: actions/setup-node@v3 + with: + node-version: 18 + - uses: pnpm/action-setup@v2 + with: + version: 7.x.x + run_install: true + + - name: build api + working-directory: plugins/${{ matrix.package }} + run: pnpm install && pnpm build + + - name: check diff + run: | + ./.scripts/ci/has-diff.sh diff --git a/.github/workflows/check-license-header.yml b/.github/workflows/check-license-header.yml index 15e9f2cb..011a1780 100644 --- a/.github/workflows/check-license-header.yml +++ b/.github/workflows/check-license-header.yml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: MIT -name: Check generated files +name: check license header on: pull_request: diff --git a/.github/workflows/lint-rust.yml b/.github/workflows/lint-rust.yml index db0a8cfb..77ade591 100644 --- a/.github/workflows/lint-rust.yml +++ b/.github/workflows/lint-rust.yml @@ -12,6 +12,7 @@ on: paths: - ".github/workflows/lint-rust.yml" - "plugins/*/src/**" + - "!plugins/*/src/api-iife.js" - "**/Cargo.toml" pull_request: branches: @@ -20,6 +21,7 @@ on: paths: - ".github/workflows/lint-rust.yml" - "plugins/*/src/**" + - "!plugins/*/src/api-iife.js" - "**/Cargo.toml" concurrency: diff --git a/.github/workflows/test-rust.yml b/.github/workflows/test-rust.yml index e0c49a85..6d4458ee 100644 --- a/.github/workflows/test-rust.yml +++ b/.github/workflows/test-rust.yml @@ -12,6 +12,7 @@ on: paths: - ".github/workflows/test-rust.yml" - "plugins/*/src/**" + - "!plugins/*/src/api-iife.js" - "**/Cargo.toml" - "**/Cargo.lock" pull_request: @@ -21,6 +22,7 @@ on: paths: - ".github/workflows/test-rust.yml" - "plugins/*/src/**" + - "!plugins/*/src/api-iife.js" - "**/Cargo.toml" - "**/Cargo.lock" diff --git a/.prettierignore b/.prettierignore index 7435af0c..af351877 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,8 @@ target node_modules dist +dist-js pnpm-lock.yaml Cargo.lock -.build \ No newline at end of file +.build +api-iife.js \ No newline at end of file diff --git a/.scripts/ci/check-license-header.js b/.scripts/ci/check-license-header.js index 5e629258..d8a64650 100644 --- a/.scripts/ci/check-license-header.js +++ b/.scripts/ci/check-license-header.js @@ -24,7 +24,10 @@ const ignore = [ ]; async function checkFile(file) { - if (extensions.some((e) => file.endsWith(e))) { + if ( + extensions.some((e) => file.endsWith(e)) && + !ignore.some((i) => file.endsWith(i)) + ) { const fileStream = fs.createReadStream(file); const rl = readline.createInterface({ input: fileStream, diff --git a/.scripts/ci/has-diff.sh b/.scripts/ci/has-diff.sh new file mode 100755 index 00000000..dd40c06f --- /dev/null +++ b/.scripts/ci/has-diff.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +if git diff --quiet --ignore-submodules HEAD +then + echo "working directory is clean" +else + echo "found diff" + exit 1 +fi diff --git a/plugins/app/guest-js/index.ts b/plugins/app/guest-js/index.ts index 056f255e..111a7ef7 100644 --- a/plugins/app/guest-js/index.ts +++ b/plugins/app/guest-js/index.ts @@ -8,7 +8,11 @@ * @module */ -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} /** * Gets the application version. @@ -21,7 +25,7 @@ import { invoke } from "@tauri-apps/api/tauri"; * @since 1.0.0 */ async function getVersion(): Promise { - return invoke("plugin:app|version"); + return window.__TAURI_INVOKE__("plugin:app|version"); } /** @@ -35,7 +39,7 @@ async function getVersion(): Promise { * @since 1.0.0 */ async function getName(): Promise { - return invoke("plugin:app|name"); + return window.__TAURI_INVOKE__("plugin:app|name"); } /** @@ -50,7 +54,7 @@ async function getName(): Promise { * @since 1.0.0 */ async function getTauriVersion(): Promise { - return invoke("plugin:app|tauri_version"); + return window.__TAURI_INVOKE__("plugin:app|tauri_version"); } /** @@ -65,7 +69,7 @@ async function getTauriVersion(): Promise { * @since 1.2.0 */ async function show(): Promise { - return invoke("plugin:app|show"); + return window.__TAURI_INVOKE__("plugin:app|show"); } /** @@ -80,7 +84,7 @@ async function show(): Promise { * @since 1.2.0 */ async function hide(): Promise { - return invoke("plugin:app|hide"); + return window.__TAURI_INVOKE__("plugin:app|hide"); } export { getName, getVersion, getTauriVersion, show, hide }; diff --git a/plugins/app/src/api-iife.js b/plugins/app/src/api-iife.js new file mode 100644 index 00000000..a9e45a48 --- /dev/null +++ b/plugins/app/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_APP__=function(_){"use strict";return _.getName=async function(){return window.__TAURI_INVOKE__("plugin:app|name")},_.getTauriVersion=async function(){return window.__TAURI_INVOKE__("plugin:app|tauri_version")},_.getVersion=async function(){return window.__TAURI_INVOKE__("plugin:app|version")},_.hide=async function(){return window.__TAURI_INVOKE__("plugin:app|hide")},_.show=async function(){return window.__TAURI_INVOKE__("plugin:app|show")},_}({});Object.defineProperty(window.__TAURI__,"app",{value:__TAURI_APP__})} diff --git a/plugins/app/src/lib.rs b/plugins/app/src/lib.rs index fc97c050..aa6fb802 100644 --- a/plugins/app/src/lib.rs +++ b/plugins/app/src/lib.rs @@ -11,6 +11,7 @@ mod commands; pub fn init() -> TauriPlugin { Builder::new("app") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![ commands::version, commands::name, diff --git a/plugins/authenticator/guest-js/index.ts b/plugins/authenticator/guest-js/index.ts index f8db2008..c7bb51a1 100644 --- a/plugins/authenticator/guest-js/index.ts +++ b/plugins/authenticator/guest-js/index.ts @@ -2,15 +2,19 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} export class Authenticator { async init(): Promise { - return await invoke("plugin:authenticator|init_auth"); + return await window.__TAURI_INVOKE__("plugin:authenticator|init_auth"); } async register(challenge: string, application: string): Promise { - return await invoke("plugin:authenticator|register", { + return await window.__TAURI_INVOKE__("plugin:authenticator|register", { timeout: 10000, challenge, application, @@ -23,12 +27,15 @@ export class Authenticator { registerData: string, clientData: string ): Promise { - return await invoke("plugin:authenticator|verify_registration", { - challenge, - application, - registerData, - clientData, - }); + return await window.__TAURI_INVOKE__( + "plugin:authenticator|verify_registration", + { + challenge, + application, + registerData, + clientData, + } + ); } async sign( @@ -36,7 +43,7 @@ export class Authenticator { application: string, keyHandle: string ): Promise { - return await invoke("plugin:authenticator|sign", { + return await window.__TAURI_INVOKE__("plugin:authenticator|sign", { timeout: 10000, challenge, application, @@ -52,13 +59,16 @@ export class Authenticator { keyHandle: string, pubkey: string ): Promise { - return await invoke("plugin:authenticator|verify_signature", { - challenge, - application, - signData, - clientData, - keyHandle, - pubkey, - }); + return await window.__TAURI_INVOKE__( + "plugin:authenticator|verify_signature", + { + challenge, + application, + signData, + clientData, + keyHandle, + pubkey, + } + ); } } diff --git a/plugins/authenticator/src/api-iife.js b/plugins/authenticator/src/api-iife.js new file mode 100644 index 00000000..07f75f70 --- /dev/null +++ b/plugins/authenticator/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_AUTHENTICATOR__=function(t){"use strict";return t.Authenticator=class{async init(){return await window.__TAURI_INVOKE__("plugin:authenticator|init_auth")}async register(t,i){return await window.__TAURI_INVOKE__("plugin:authenticator|register",{timeout:1e4,challenge:t,application:i})}async verifyRegistration(t,i,a,n){return await window.__TAURI_INVOKE__("plugin:authenticator|verify_registration",{challenge:t,application:i,registerData:a,clientData:n})}async sign(t,i,a){return await window.__TAURI_INVOKE__("plugin:authenticator|sign",{timeout:1e4,challenge:t,application:i,keyHandle:a})}async verifySignature(t,i,a,n,e,_){return await window.__TAURI_INVOKE__("plugin:authenticator|verify_signature",{challenge:t,application:i,signData:a,clientData:n,keyHandle:e,pubkey:_})}},t}({});Object.defineProperty(window.__TAURI__,"authenticator",{value:__TAURI_AUTHENTICATOR__})} diff --git a/plugins/authenticator/src/lib.rs b/plugins/authenticator/src/lib.rs index b46f44c6..9e6785d0 100644 --- a/plugins/authenticator/src/lib.rs +++ b/plugins/authenticator/src/lib.rs @@ -67,6 +67,7 @@ fn verify_signature( pub fn init() -> TauriPlugin { PluginBuilder::new("authenticator") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![ init_auth, register, diff --git a/plugins/autostart/guest-js/index.ts b/plugins/autostart/guest-js/index.ts index b3100708..66d71a57 100644 --- a/plugins/autostart/guest-js/index.ts +++ b/plugins/autostart/guest-js/index.ts @@ -2,16 +2,20 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} export async function isEnabled(): Promise { - return await invoke("plugin:autostart|is_enabled"); + return await window.__TAURI_INVOKE__("plugin:autostart|is_enabled"); } export async function enable(): Promise { - await invoke("plugin:autostart|enable"); + await window.__TAURI_INVOKE__("plugin:autostart|enable"); } export async function disable(): Promise { - await invoke("plugin:autostart|disable"); + await window.__TAURI_INVOKE__("plugin:autostart|disable"); } diff --git a/plugins/autostart/src/api-iife.js b/plugins/autostart/src/api-iife.js new file mode 100644 index 00000000..468886f4 --- /dev/null +++ b/plugins/autostart/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_AUTOSTART__=function(_){"use strict";return _.disable=async function(){await window.__TAURI_INVOKE__("plugin:autostart|disable")},_.enable=async function(){await window.__TAURI_INVOKE__("plugin:autostart|enable")},_.isEnabled=async function(){return await window.__TAURI_INVOKE__("plugin:autostart|is_enabled")},_}({});Object.defineProperty(window.__TAURI__,"autostart",{value:__TAURI_AUTOSTART__})} diff --git a/plugins/autostart/src/lib.rs b/plugins/autostart/src/lib.rs index 2ecc4609..91c6e4ec 100644 --- a/plugins/autostart/src/lib.rs +++ b/plugins/autostart/src/lib.rs @@ -99,6 +99,7 @@ pub fn init( args: Option>, ) -> TauriPlugin { Builder::new("autostart") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![enable, disable, is_enabled]) .setup(move |app, _api| { let mut builder = AutoLaunchBuilder::new(); diff --git a/plugins/cli/guest-js/index.ts b/plugins/cli/guest-js/index.ts index 49f0cba7..ea6ce67a 100644 --- a/plugins/cli/guest-js/index.ts +++ b/plugins/cli/guest-js/index.ts @@ -8,7 +8,11 @@ * @module */ -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} /** * @since 1.0.0 @@ -64,7 +68,7 @@ interface CliMatches { * @since 1.0.0 */ async function getMatches(): Promise { - return await invoke("plugin:cli|cli_matches"); + return await window.__TAURI_INVOKE__("plugin:cli|cli_matches"); } export type { ArgMatch, SubcommandMatch, CliMatches }; diff --git a/plugins/cli/src/api-iife.js b/plugins/cli/src/api-iife.js new file mode 100644 index 00000000..79da44bb --- /dev/null +++ b/plugins/cli/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_CLI__=function(_){"use strict";return _.getMatches=async function(){return await window.__TAURI_INVOKE__("plugin:cli|cli_matches")},_}({});Object.defineProperty(window.__TAURI__,"cli",{value:__TAURI_CLI__})} diff --git a/plugins/cli/src/lib.rs b/plugins/cli/src/lib.rs index 8243dff3..096b62a2 100644 --- a/plugins/cli/src/lib.rs +++ b/plugins/cli/src/lib.rs @@ -40,6 +40,7 @@ fn cli_matches(_app: AppHandle, cli: State<'_, Cli>) -> Result pub fn init() -> TauriPlugin { Builder::new("cli") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![cli_matches]) .setup(|app, api| { app.manage(Cli(api)); diff --git a/plugins/clipboard/guest-js/index.ts b/plugins/clipboard/guest-js/index.ts index 67f519ee..495371bc 100644 --- a/plugins/clipboard/guest-js/index.ts +++ b/plugins/clipboard/guest-js/index.ts @@ -8,7 +8,11 @@ * @module */ -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} interface Clip { kind: K; @@ -34,7 +38,7 @@ async function writeText( text: string, opts?: { label?: string } ): Promise { - return invoke("plugin:clipboard|write", { + return window.__TAURI_INVOKE__("plugin:clipboard|write", { data: { kind: "PlainText", options: { @@ -55,7 +59,9 @@ async function writeText( * @since 1.0.0. */ async function readText(): Promise { - const kind: ClipResponse = await invoke("plugin:clipboard|read"); + const kind: ClipResponse = await window.__TAURI_INVOKE__( + "plugin:clipboard|read" + ); return kind.options; } diff --git a/plugins/clipboard/src/api-iife.js b/plugins/clipboard/src/api-iife.js new file mode 100644 index 00000000..d04126a5 --- /dev/null +++ b/plugins/clipboard/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_CLIPBOARD__=function(_){"use strict";return _.readText=async function(){return(await window.__TAURI_INVOKE__("plugin:clipboard|read")).options},_.writeText=async function(_,i){return window.__TAURI_INVOKE__("plugin:clipboard|write",{data:{kind:"PlainText",options:{label:null==i?void 0:i.label,text:_}}})},_}({});Object.defineProperty(window.__TAURI__,"clipboard",{value:__TAURI_CLIPBOARD__})} diff --git a/plugins/clipboard/src/lib.rs b/plugins/clipboard/src/lib.rs index a655d93e..7fc05348 100644 --- a/plugins/clipboard/src/lib.rs +++ b/plugins/clipboard/src/lib.rs @@ -39,6 +39,7 @@ impl> crate::ClipboardExt for T { /// Initializes the plugin. pub fn init() -> TauriPlugin { Builder::new("clipboard") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![commands::write, commands::read]) .setup(|app, api| { #[cfg(mobile)] diff --git a/plugins/dialog/guest-js/index.ts b/plugins/dialog/guest-js/index.ts index 3d94a61e..5300b7cc 100644 --- a/plugins/dialog/guest-js/index.ts +++ b/plugins/dialog/guest-js/index.ts @@ -2,7 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} interface FileResponse { base64Data?: string; @@ -169,7 +173,7 @@ async function open( Object.freeze(options); } - return invoke("plugin:dialog|open", { options }); + return window.__TAURI_INVOKE__("plugin:dialog|open", { options }); } /** @@ -201,7 +205,7 @@ async function save(options: SaveDialogOptions = {}): Promise { Object.freeze(options); } - return invoke("plugin:dialog|save", { options }); + return window.__TAURI_INVOKE__("plugin:dialog|save", { options }); } /** @@ -226,7 +230,7 @@ async function message( options?: string | MessageDialogOptions ): Promise { const opts = typeof options === "string" ? { title: options } : options; - return invoke("plugin:dialog|message", { + return window.__TAURI_INVOKE__("plugin:dialog|message", { message: message.toString(), title: opts?.title?.toString(), type_: opts?.type, @@ -255,7 +259,7 @@ async function ask( options?: string | ConfirmDialogOptions ): Promise { const opts = typeof options === "string" ? { title: options } : options; - return invoke("plugin:dialog|ask", { + return window.__TAURI_INVOKE__("plugin:dialog|ask", { message: message.toString(), title: opts?.title?.toString(), type_: opts?.type, @@ -285,7 +289,7 @@ async function confirm( options?: string | ConfirmDialogOptions ): Promise { const opts = typeof options === "string" ? { title: options } : options; - return invoke("plugin:dialog|confirm", { + return window.__TAURI_INVOKE__("plugin:dialog|confirm", { message: message.toString(), title: opts?.title?.toString(), type_: opts?.type, diff --git a/plugins/dialog/src/api-iife.js b/plugins/dialog/src/api-iife.js new file mode 100644 index 00000000..b5a74860 --- /dev/null +++ b/plugins/dialog/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_DIALOG__=function(n){"use strict";return n.ask=async function(n,o){var t,i,l,e,u;const _="string"==typeof o?{title:o}:o;return window.__TAURI_INVOKE__("plugin:dialog|ask",{message:n.toString(),title:null===(t=null==_?void 0:_.title)||void 0===t?void 0:t.toString(),type_:null==_?void 0:_.type,okButtonLabel:null!==(l=null===(i=null==_?void 0:_.okLabel)||void 0===i?void 0:i.toString())&&void 0!==l?l:"Yes",cancelButtonLabel:null!==(u=null===(e=null==_?void 0:_.cancelLabel)||void 0===e?void 0:e.toString())&&void 0!==u?u:"No"})},n.confirm=async function(n,o){var t,i,l,e,u;const _="string"==typeof o?{title:o}:o;return window.__TAURI_INVOKE__("plugin:dialog|confirm",{message:n.toString(),title:null===(t=null==_?void 0:_.title)||void 0===t?void 0:t.toString(),type_:null==_?void 0:_.type,okButtonLabel:null!==(l=null===(i=null==_?void 0:_.okLabel)||void 0===i?void 0:i.toString())&&void 0!==l?l:"Ok",cancelButtonLabel:null!==(u=null===(e=null==_?void 0:_.cancelLabel)||void 0===e?void 0:e.toString())&&void 0!==u?u:"Cancel"})},n.message=async function(n,o){var t,i;const l="string"==typeof o?{title:o}:o;return window.__TAURI_INVOKE__("plugin:dialog|message",{message:n.toString(),title:null===(t=null==l?void 0:l.title)||void 0===t?void 0:t.toString(),type_:null==l?void 0:l.type,okButtonLabel:null===(i=null==l?void 0:l.okLabel)||void 0===i?void 0:i.toString()})},n.open=async function(n={}){return"object"==typeof n&&Object.freeze(n),window.__TAURI_INVOKE__("plugin:dialog|open",{options:n})},n.save=async function(n={}){return"object"==typeof n&&Object.freeze(n),window.__TAURI_INVOKE__("plugin:dialog|save",{options:n})},n}({});Object.defineProperty(window.__TAURI__,"dialog",{value:__TAURI_DIALOG__})} diff --git a/plugins/dialog/src/lib.rs b/plugins/dialog/src/lib.rs index 2c07b591..8353b71c 100644 --- a/plugins/dialog/src/lib.rs +++ b/plugins/dialog/src/lib.rs @@ -75,7 +75,13 @@ pub fn init() -> TauriPlugin { // Dialogs are implemented natively on Android #[cfg(not(target_os = "android"))] { - builder = builder.js_init_script(include_str!("init.js").to_string()); + let mut init_script = include_str!("init.js").to_string(); + init_script.push_str(include_str!("api-iife.js")); + builder = builder.js_init_script(init_script); + } + #[cfg(target_os = "android")] + { + builder = builder.js_init_script(include_str!("api-iife.js").to_string()); } builder diff --git a/plugins/fs/guest-js/index.ts b/plugins/fs/guest-js/index.ts index bd16cd43..2d1ecf37 100644 --- a/plugins/fs/guest-js/index.ts +++ b/plugins/fs/guest-js/index.ts @@ -45,9 +45,14 @@ * @module */ -import { invoke } from "@tauri-apps/api/tauri"; import { BaseDirectory } from "@tauri-apps/api/path"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} + interface Permissions { /** * `true` if these permissions describe a readonly (unwritable) file. @@ -226,7 +231,7 @@ async function readTextFile( filePath: string, options: FsOptions = {} ): Promise { - return await invoke("plugin:fs|read_text_file", { + return await window.__TAURI_INVOKE__("plugin:fs|read_text_file", { path: filePath, options, }); @@ -247,7 +252,7 @@ async function readBinaryFile( filePath: string, options: FsOptions = {} ): Promise { - const arr = await invoke("plugin:fs|read_file", { + const arr = await window.__TAURI_INVOKE__("plugin:fs|read_file", { path: filePath, options, }); @@ -323,7 +328,7 @@ async function writeTextFile( fileOptions = contents; } - return await invoke("plugin:fs|write_file", { + return await window.__TAURI_INVOKE__("plugin:fs|write_file", { path: file.path, contents: Array.from(new TextEncoder().encode(file.contents)), options: fileOptions, @@ -405,7 +410,7 @@ async function writeBinaryFile( file.contents = contents ?? []; } - return await invoke("plugin:fs|write_binary_file", { + return await window.__TAURI_INVOKE__("plugin:fs|write_binary_file", { path: file.path, contents: Array.from( file.contents instanceof ArrayBuffer @@ -440,7 +445,7 @@ async function readDir( dir: string, options: FsDirOptions = {} ): Promise { - return await invoke("plugin:fs|read_dir", { + return await window.__TAURI_INVOKE__("plugin:fs|read_dir", { path: dir, options, }); @@ -465,7 +470,7 @@ async function createDir( dir: string, options: FsDirOptions = {} ): Promise { - return await invoke("plugin:fs|create_dir", { + return await window.__TAURI_INVOKE__("plugin:fs|create_dir", { path: dir, options, }); @@ -489,7 +494,7 @@ async function removeDir( dir: string, options: FsDirOptions = {} ): Promise { - return await invoke("plugin:fs|remove_dir", { + return await window.__TAURI_INVOKE__("plugin:fs|remove_dir", { path: dir, options, }); @@ -513,7 +518,7 @@ async function copyFile( destination: string, options: FsOptions = {} ): Promise { - return await invoke("plugin:fs|copy_file", { + return await window.__TAURI_INVOKE__("plugin:fs|copy_file", { source, destination, options, @@ -537,7 +542,7 @@ async function removeFile( file: string, options: FsOptions = {} ): Promise { - return await invoke("plugin:fs|remove_file", { + return await window.__TAURI_INVOKE__("plugin:fs|remove_file", { path: file, options, }); @@ -561,7 +566,7 @@ async function renameFile( newPath: string, options: FsOptions = {} ): Promise { - return await invoke("plugin:fs|rename_file", { + return await window.__TAURI_INVOKE__("plugin:fs|rename_file", { oldPath, newPath, options, @@ -580,7 +585,7 @@ async function renameFile( * @since 1.0.0 */ async function exists(path: string): Promise { - return await invoke("plugin:fs|exists", { path }); + return await window.__TAURI_INVOKE__("plugin:fs|exists", { path }); } /** @@ -589,17 +594,19 @@ async function exists(path: string): Promise { * @since 1.0.0 */ async function metadata(path: string): Promise { - return await invoke("plugin:fs|metadata", { - path, - }).then((metadata) => { - const { accessedAtMs, createdAtMs, modifiedAtMs, ...data } = metadata; - return { - accessedAt: new Date(accessedAtMs), - createdAt: new Date(createdAtMs), - modifiedAt: new Date(modifiedAtMs), - ...data, - }; - }); + return await window + .__TAURI_INVOKE__("plugin:fs|metadata", { + path, + }) + .then((metadata) => { + const { accessedAtMs, createdAtMs, modifiedAtMs, ...data } = metadata; + return { + accessedAt: new Date(accessedAtMs), + createdAt: new Date(createdAtMs), + modifiedAt: new Date(modifiedAtMs), + ...data, + }; + }); } export type { diff --git a/plugins/fs/src/api-iife.js b/plugins/fs/src/api-iife.js new file mode 100644 index 00000000..c87b63b8 --- /dev/null +++ b/plugins/fs/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_FS__=function(e){"use strict";var t=Object.defineProperty,n=(e,n)=>{for(var r in n)t(e,r,{get:n[r],enumerable:!0})},r=(e,t,n)=>{if(!t.has(e))throw TypeError("Cannot "+n)},i=(e,t,n)=>(r(e,t,"read from private field"),n?n.call(e):t.get(e));function o(e,t=!1){let n=window.crypto.getRandomValues(new Uint32Array(1))[0],r=`_${n}`;return Object.defineProperty(window,r,{value:n=>(t&&Reflect.deleteProperty(window,r),e?.(n)),writable:!1,configurable:!0}),n}n({},{Channel:()=>c,PluginListener:()=>s,addPluginListener:()=>u,convertFileSrc:()=>l,invoke:()=>p,transformCallback:()=>o});var a,c=class{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,((e,t,n)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,n)})(this,a,(()=>{})),this.id=o((e=>{i(this,a).call(this,e)}))}set onmessage(e){((e,t,n,i)=>{r(e,t,"write to private field"),i?i.call(e,n):t.set(e,n)})(this,a,e)}get onmessage(){return i(this,a)}toJSON(){return`__CHANNEL__:${this.id}`}};a=new WeakMap;var s=class{constructor(e,t,n){this.plugin=e,this.event=t,this.channelId=n}async unregister(){return p(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}};async function u(e,t,n){let r=new c;return r.onmessage=n,p(`plugin:${e}|register_listener`,{event:t,handler:r}).then((()=>new s(e,t,r.id)))}async function p(e,t={}){return new Promise(((n,r)=>{let i=o((e=>{n(e),Reflect.deleteProperty(window,`_${a}`)}),!0),a=o((e=>{r(e),Reflect.deleteProperty(window,`_${i}`)}),!0);window.__TAURI_IPC__({cmd:e,callback:i,error:a,...t})}))}function l(e,t="asset"){let n=encodeURIComponent(e);return navigator.userAgent.includes("Windows")?`https://${t}.localhost/${n}`:`${t}://localhost/${n}`}function d(){return navigator.appVersion.includes("Win")}n({},{BaseDirectory:()=>y,appCacheDir:()=>g,appConfigDir:()=>f,appDataDir:()=>h,appLocalDataDir:()=>w,appLogDir:()=>x,audioDir:()=>v,basename:()=>H,cacheDir:()=>m,configDir:()=>A,dataDir:()=>D,delimiter:()=>$,desktopDir:()=>I,dirname:()=>M,documentDir:()=>R,downloadDir:()=>b,executableDir:()=>T,extname:()=>S,fontDir:()=>U,homeDir:()=>E,isAbsolute:()=>W,join:()=>B,localDataDir:()=>O,normalize:()=>z,pictureDir:()=>C,publicDir:()=>N,resolve:()=>k,resolveResource:()=>V,resourceDir:()=>P,runtimeDir:()=>j,sep:()=>L,templateDir:()=>F,videoDir:()=>K});var _,y=((_=y||{})[_.Audio=1]="Audio",_[_.Cache=2]="Cache",_[_.Config=3]="Config",_[_.Data=4]="Data",_[_.LocalData=5]="LocalData",_[_.Document=6]="Document",_[_.Download=7]="Download",_[_.Picture=8]="Picture",_[_.Public=9]="Public",_[_.Video=10]="Video",_[_.Resource=11]="Resource",_[_.Temp=12]="Temp",_[_.AppConfig=13]="AppConfig",_[_.AppData=14]="AppData",_[_.AppLocalData=15]="AppLocalData",_[_.AppCache=16]="AppCache",_[_.AppLog=17]="AppLog",_[_.Desktop=18]="Desktop",_[_.Executable=19]="Executable",_[_.Font=20]="Font",_[_.Home=21]="Home",_[_.Runtime=22]="Runtime",_[_.Template=23]="Template",_);async function f(){return p("plugin:path|resolve_directory",{directory:13})}async function h(){return p("plugin:path|resolve_directory",{directory:14})}async function w(){return p("plugin:path|resolve_directory",{directory:15})}async function g(){return p("plugin:path|resolve_directory",{directory:16})}async function v(){return p("plugin:path|resolve_directory",{directory:1})}async function m(){return p("plugin:path|resolve_directory",{directory:2})}async function A(){return p("plugin:path|resolve_directory",{directory:3})}async function D(){return p("plugin:path|resolve_directory",{directory:4})}async function I(){return p("plugin:path|resolve_directory",{directory:18})}async function R(){return p("plugin:path|resolve_directory",{directory:6})}async function b(){return p("plugin:path|resolve_directory",{directory:7})}async function T(){return p("plugin:path|resolve_directory",{directory:19})}async function U(){return p("plugin:path|resolve_directory",{directory:20})}async function E(){return p("plugin:path|resolve_directory",{directory:21})}async function O(){return p("plugin:path|resolve_directory",{directory:5})}async function C(){return p("plugin:path|resolve_directory",{directory:8})}async function N(){return p("plugin:path|resolve_directory",{directory:9})}async function P(){return p("plugin:path|resolve_directory",{directory:11})}async function V(e){return p("plugin:path|resolve_directory",{directory:11,path:e})}async function j(){return p("plugin:path|resolve_directory",{directory:22})}async function F(){return p("plugin:path|resolve_directory",{directory:23})}async function K(){return p("plugin:path|resolve_directory",{directory:10})}async function x(){return p("plugin:path|resolve_directory",{directory:17})}var L=d()?"\\":"/",$=d()?";":":";async function k(...e){return p("plugin:path|resolve",{paths:e})}async function z(e){return p("plugin:path|normalize",{path:e})}async function B(...e){return p("plugin:path|join",{paths:e})}async function M(e){return p("plugin:path|dirname",{path:e})}async function S(e){return p("plugin:path|extname",{path:e})}async function H(e,t){return p("plugin:path|basename",{path:e,ext:t})}async function W(e){return p("plugin:path|isAbsolute",{path:e})}async function J(e,t,n){"object"==typeof n&&Object.freeze(n),"object"==typeof e&&Object.freeze(e);const r={path:"",contents:""};let i=n;return"string"==typeof e?r.path=e:(r.path=e.path,r.contents=e.contents),"string"==typeof t?r.contents=null!=t?t:"":i=t,await window.__TAURI_INVOKE__("plugin:fs|write_file",{path:r.path,contents:Array.from((new TextEncoder).encode(r.contents)),options:i})}return e.BaseDirectory=y,e.Dir=y,e.copyFile=async function(e,t,n={}){return await window.__TAURI_INVOKE__("plugin:fs|copy_file",{source:e,destination:t,options:n})},e.createDir=async function(e,t={}){return await window.__TAURI_INVOKE__("plugin:fs|create_dir",{path:e,options:t})},e.exists=async function(e){return await window.__TAURI_INVOKE__("plugin:fs|exists",{path:e})},e.metadata=async function(e){return await window.__TAURI_INVOKE__("plugin:fs|metadata",{path:e}).then((e=>{const{accessedAtMs:t,createdAtMs:n,modifiedAtMs:r,...i}=e;return{accessedAt:new Date(t),createdAt:new Date(n),modifiedAt:new Date(r),...i}}))},e.readBinaryFile=async function(e,t={}){const n=await window.__TAURI_INVOKE__("plugin:fs|read_file",{path:e,options:t});return Uint8Array.from(n)},e.readDir=async function(e,t={}){return await window.__TAURI_INVOKE__("plugin:fs|read_dir",{path:e,options:t})},e.readTextFile=async function(e,t={}){return await window.__TAURI_INVOKE__("plugin:fs|read_text_file",{path:e,options:t})},e.removeDir=async function(e,t={}){return await window.__TAURI_INVOKE__("plugin:fs|remove_dir",{path:e,options:t})},e.removeFile=async function(e,t={}){return await window.__TAURI_INVOKE__("plugin:fs|remove_file",{path:e,options:t})},e.renameFile=async function(e,t,n={}){return await window.__TAURI_INVOKE__("plugin:fs|rename_file",{oldPath:e,newPath:t,options:n})},e.writeBinaryFile=async function(e,t,n){"object"==typeof n&&Object.freeze(n),"object"==typeof e&&Object.freeze(e);const r={path:"",contents:[]};let i=n;return"string"==typeof e?r.path=e:(r.path=e.path,r.contents=e.contents),t&&"dir"in t?i=t:"string"==typeof e&&(r.contents=null!=t?t:[]),await window.__TAURI_INVOKE__("plugin:fs|write_binary_file",{path:r.path,contents:Array.from(r.contents instanceof ArrayBuffer?new Uint8Array(r.contents):r.contents),options:i})},e.writeFile=J,e.writeTextFile=J,e}({});Object.defineProperty(window.__TAURI__,"fs",{value:__TAURI_FS__})} diff --git a/plugins/fs/src/lib.rs b/plugins/fs/src/lib.rs index 023d04e6..9156661f 100644 --- a/plugins/fs/src/lib.rs +++ b/plugins/fs/src/lib.rs @@ -38,6 +38,7 @@ impl> FsExt for T { pub fn init() -> TauriPlugin> { PluginBuilder::>::new("fs") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![ commands::read_file, commands::read_text_file, diff --git a/plugins/global-shortcut/guest-js/index.ts b/plugins/global-shortcut/guest-js/index.ts index ea105f25..4c1c02c8 100644 --- a/plugins/global-shortcut/guest-js/index.ts +++ b/plugins/global-shortcut/guest-js/index.ts @@ -8,7 +8,14 @@ * @module */ -import { invoke, transformCallback } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + __TAURI__: { + transformCallback: (cb: (payload: T) => void) => number; + }; + } +} export type ShortcutHandler = (shortcut: string) => void; @@ -31,9 +38,9 @@ async function register( shortcut: string, handler: ShortcutHandler ): Promise { - return await invoke("plugin:globalShortcut|register", { + return await window.__TAURI_INVOKE__("plugin:globalShortcut|register", { shortcut, - handler: transformCallback(handler), + handler: window.__TAURI__.transformCallback(handler), }); } @@ -56,9 +63,9 @@ async function registerAll( shortcuts: string[], handler: ShortcutHandler ): Promise { - return await invoke("plugin:globalShortcut|register_all", { + return await window.__TAURI_INVOKE__("plugin:globalShortcut|register_all", { shortcuts, - handler: transformCallback(handler), + handler: window.__TAURI__.transformCallback(handler), }); } @@ -78,7 +85,7 @@ async function registerAll( * @since 1.0.0 */ async function isRegistered(shortcut: string): Promise { - return await invoke("plugin:globalShortcut|is_registered", { + return await window.__TAURI_INVOKE__("plugin:globalShortcut|is_registered", { shortcut, }); } @@ -96,7 +103,7 @@ async function isRegistered(shortcut: string): Promise { * @since 1.0.0 */ async function unregister(shortcut: string): Promise { - return await invoke("plugin:globalShortcut|unregister", { + return await window.__TAURI_INVOKE__("plugin:globalShortcut|unregister", { shortcut, }); } @@ -112,7 +119,7 @@ async function unregister(shortcut: string): Promise { * @since 1.0.0 */ async function unregisterAll(): Promise { - return await invoke("plugin:globalShortcut|unregister_all"); + return await window.__TAURI_INVOKE__("plugin:globalShortcut|unregister_all"); } export { register, registerAll, isRegistered, unregister, unregisterAll }; diff --git a/plugins/global-shortcut/src/api-iife.js b/plugins/global-shortcut/src/api-iife.js new file mode 100644 index 00000000..542aa04f --- /dev/null +++ b/plugins/global-shortcut/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_GLOBALSHORTCUT__=function(_){"use strict";return _.isRegistered=async function(_){return await window.__TAURI_INVOKE__("plugin:globalShortcut|is_registered",{shortcut:_})},_.register=async function(_,t){return await window.__TAURI_INVOKE__("plugin:globalShortcut|register",{shortcut:_,handler:window.__TAURI__.transformCallback(t)})},_.registerAll=async function(_,t){return await window.__TAURI_INVOKE__("plugin:globalShortcut|register_all",{shortcuts:_,handler:window.__TAURI__.transformCallback(t)})},_.unregister=async function(_){return await window.__TAURI_INVOKE__("plugin:globalShortcut|unregister",{shortcut:_})},_.unregisterAll=async function(){return await window.__TAURI_INVOKE__("plugin:globalShortcut|unregister_all")},_}({});Object.defineProperty(window.__TAURI__,"globalShortcut",{value:__TAURI_GLOBALSHORTCUT__})} diff --git a/plugins/global-shortcut/src/lib.rs b/plugins/global-shortcut/src/lib.rs index 6ac38f45..86fb28dd 100644 --- a/plugins/global-shortcut/src/lib.rs +++ b/plugins/global-shortcut/src/lib.rs @@ -283,6 +283,7 @@ impl Builder { pub fn build(self) -> TauriPlugin { let handler = self.handler; PluginBuilder::new("globalShortcut") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![ register, register_all, diff --git a/plugins/http/guest-js/index.ts b/plugins/http/guest-js/index.ts index f2a8e2b2..9cc07ac1 100644 --- a/plugins/http/guest-js/index.ts +++ b/plugins/http/guest-js/index.ts @@ -24,7 +24,11 @@ * @module */ -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} /** * @since 1.0.0 @@ -297,7 +301,7 @@ class Client { * ``` */ async drop(): Promise { - return invoke("plugin:http|drop_client", { + return window.__TAURI_INVOKE__("plugin:http|drop_client", { client: this.id, }); } @@ -320,30 +324,32 @@ class Client { if (jsonResponse) { options.responseType = ResponseType.Text; } - return invoke>("plugin:http|request", { - clientId: this.id, - options, - }).then((res) => { - const response = new Response(res); - if (jsonResponse) { - /* eslint-disable */ - try { - response.data = JSON.parse(response.data as string); - } catch (e) { - if (response.ok && (response.data as unknown as string) === "") { - response.data = {} as T; - } else if (response.ok) { - throw Error( - `Failed to parse response \`${response.data}\` as JSON: ${e}; + return window + .__TAURI_INVOKE__>("plugin:http|request", { + clientId: this.id, + options, + }) + .then((res) => { + const response = new Response(res); + if (jsonResponse) { + /* eslint-disable */ + try { + response.data = JSON.parse(response.data as string); + } catch (e) { + if (response.ok && (response.data as unknown as string) === "") { + response.data = {} as T; + } else if (response.ok) { + throw Error( + `Failed to parse response \`${response.data}\` as JSON: ${e}; try setting the \`responseType\` option to \`ResponseType.Text\` or \`ResponseType.Binary\` if the API does not return a JSON response.` - ); + ); + } } + /* eslint-enable */ + return response; } - /* eslint-enable */ return response; - } - return response; - }); + }); } /** @@ -478,9 +484,11 @@ class Client { * @since 1.0.0 */ async function getClient(options?: ClientOptions): Promise { - return invoke("plugin:http|create_client", { - options, - }).then((id) => new Client(id)); + return window + .__TAURI_INVOKE__("plugin:http|create_client", { + options, + }) + .then((id) => new Client(id)); } /** @internal */ diff --git a/plugins/http/src/api-iife.js b/plugins/http/src/api-iife.js new file mode 100644 index 00000000..e99aa35b --- /dev/null +++ b/plugins/http/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_HTTP__=function(e){"use strict";var t;e.ResponseType=void 0,(t=e.ResponseType||(e.ResponseType={}))[t.JSON=1]="JSON",t[t.Text=2]="Text",t[t.Binary=3]="Binary";class r{constructor(e,t){this.type=e,this.payload=t}static form(e){const t={},s=(e,r)=>{if(null!==r){let s;s="string"==typeof r?r:r instanceof Uint8Array||Array.isArray(r)?Array.from(r):r instanceof File?{file:r.name,mime:r.type,fileName:r.name}:"string"==typeof r.file?{file:r.file,mime:r.mime,fileName:r.fileName}:{file:Array.from(r.file),mime:r.mime,fileName:r.fileName},t[String(e)]=s}};if(e instanceof FormData)for(const[t,r]of e)s(t,r);else for(const[t,r]of Object.entries(e))s(t,r);return new r("Form",t)}static json(e){return new r("Json",e)}static text(e){return new r("Text",e)}static bytes(e){return new r("Bytes",Array.from(e instanceof ArrayBuffer?new Uint8Array(e):e))}}class s{constructor(e){this.url=e.url,this.status=e.status,this.ok=this.status>=200&&this.status<300,this.headers=e.headers,this.rawHeaders=e.rawHeaders,this.data=e.data}}class n{constructor(e){this.id=e}async drop(){return window.__TAURI_INVOKE__("plugin:http|drop_client",{client:this.id})}async request(t){const r=!t.responseType||t.responseType===e.ResponseType.JSON;return r&&(t.responseType=e.ResponseType.Text),window.__TAURI_INVOKE__("plugin:http|request",{clientId:this.id,options:t}).then((e=>{const t=new s(e);if(r){try{t.data=JSON.parse(t.data)}catch(e){if(t.ok&&""===t.data)t.data={};else if(t.ok)throw Error(`Failed to parse response \`${t.data}\` as JSON: ${e};\n try setting the \`responseType\` option to \`ResponseType.Text\` or \`ResponseType.Binary\` if the API does not return a JSON response.`)}return t}return t}))}async get(e,t){return this.request({method:"GET",url:e,...t})}async post(e,t,r){return this.request({method:"POST",url:e,body:t,...r})}async put(e,t,r){return this.request({method:"PUT",url:e,body:t,...r})}async patch(e,t){return this.request({method:"PATCH",url:e,...t})}async delete(e,t){return this.request({method:"DELETE",url:e,...t})}}async function i(e){return window.__TAURI_INVOKE__("plugin:http|create_client",{options:e}).then((e=>new n(e)))}let o=null;return e.Body=r,e.Client=n,e.Response=s,e.fetch=async function(e,t){var r;return null===o&&(o=await i()),o.request({url:e,method:null!==(r=null==t?void 0:t.method)&&void 0!==r?r:"GET",...t})},e.getClient=i,e}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_HTTP__})} diff --git a/plugins/http/src/lib.rs b/plugins/http/src/lib.rs index afee9b54..d63107cc 100644 --- a/plugins/http/src/lib.rs +++ b/plugins/http/src/lib.rs @@ -41,6 +41,7 @@ impl> HttpExt for T { pub fn init() -> TauriPlugin> { Builder::>::new("http") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![ commands::create_client, commands::drop_client, diff --git a/plugins/log/guest-js/index.ts b/plugins/log/guest-js/index.ts index 54fb6e28..4b3761eb 100644 --- a/plugins/log/guest-js/index.ts +++ b/plugins/log/guest-js/index.ts @@ -2,9 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -import { invoke } from "@tauri-apps/api/tauri"; import { listen, UnlistenFn } from "@tauri-apps/api/event"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} + export type LogOptions = { file?: string; line?: number; @@ -61,7 +66,7 @@ async function log( location = "webview::unknown"; } - await invoke("plugin:log|log", { + await window.__TAURI_INVOKE__("plugin:log|log", { level, message, location, diff --git a/plugins/log/src/api-iife.js b/plugins/log/src/api-iife.js new file mode 100644 index 00000000..7abc7bb7 --- /dev/null +++ b/plugins/log/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_LOG__=function(e){"use strict";var n=Object.defineProperty,t=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})},r=(e,n,t)=>{if(!n.has(e))throw TypeError("Cannot "+t)},a=(e,n,t)=>(r(e,n,"read from private field"),t?t.call(e):n.get(e)),i=(e,n,t,a)=>(r(e,n,"write to private field"),a?a.call(e,t):n.set(e,t),t);function o(e,n=!1){let t=window.crypto.getRandomValues(new Uint32Array(1))[0],r=`_${t}`;return Object.defineProperty(window,r,{value:t=>(n&&Reflect.deleteProperty(window,r),e?.(t)),writable:!1,configurable:!0}),t}t({},{Channel:()=>c,PluginListener:()=>s,addPluginListener:()=>u,convertFileSrc:()=>_,invoke:()=>d,transformCallback:()=>o});var l,c=class{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,((e,n,t)=>{if(n.has(e))throw TypeError("Cannot add the same private member more than once");n instanceof WeakSet?n.add(e):n.set(e,t)})(this,l,(()=>{})),this.id=o((e=>{a(this,l).call(this,e)}))}set onmessage(e){i(this,l,e)}get onmessage(){return a(this,l)}toJSON(){return`__CHANNEL__:${this.id}`}};l=new WeakMap;var s=class{constructor(e,n,t){this.plugin=e,this.event=n,this.channelId=t}async unregister(){return d(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}};async function u(e,n,t){let r=new c;return r.onmessage=t,d(`plugin:${e}|register_listener`,{event:n,handler:r}).then((()=>new s(e,n,r.id)))}async function d(e,n={}){return new Promise(((t,r)=>{let a=o((e=>{t(e),Reflect.deleteProperty(window,`_${i}`)}),!0),i=o((e=>{r(e),Reflect.deleteProperty(window,`_${a}`)}),!0);window.__TAURI_IPC__({cmd:e,callback:a,error:i,...n})}))}function _(e,n="asset"){let t=encodeURIComponent(e);return navigator.userAgent.includes("Windows")?`https://${n}.localhost/${t}`:`${n}://localhost/${t}`}async function w(e,n){await d("plugin:event|unlisten",{event:e,eventId:n})}async function f(e,n,t){return d("plugin:event|listen",{event:e,windowLabel:n,handler:o(t)}).then((n=>async()=>w(e,n)))}t({},{TauriEvent:()=>h,emit:()=>y,listen:()=>E,once:()=>I});var v,g,h=((v=h||{}).WINDOW_RESIZED="tauri://resize",v.WINDOW_MOVED="tauri://move",v.WINDOW_CLOSE_REQUESTED="tauri://close-requested",v.WINDOW_CREATED="tauri://window-created",v.WINDOW_DESTROYED="tauri://destroyed",v.WINDOW_FOCUS="tauri://focus",v.WINDOW_BLUR="tauri://blur",v.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",v.WINDOW_THEME_CHANGED="tauri://theme-changed",v.WINDOW_FILE_DROP="tauri://file-drop",v.WINDOW_FILE_DROP_HOVER="tauri://file-drop-hover",v.WINDOW_FILE_DROP_CANCELLED="tauri://file-drop-cancelled",v.MENU="tauri://menu",v);async function E(e,n){return f(e,null,n)}async function I(e,n){return async function(e,n,t){return f(e,n,(n=>{t(n),w(e,n.id).catch((()=>{}))}))}(e,null,n)}async function y(e,n){return async function(e,n,t){await d("plugin:event|emit",{event:e,windowLabel:n,payload:t})}(e,void 0,n)}async function p(e,n,t){var r,a;const i=null===(r=(new Error).stack)||void 0===r?void 0:r.split("\n").map((e=>e.split("@"))),o=null==i?void 0:i.filter((([e,n])=>e.length>0&&"[native code]"!==n)),{file:l,line:c,...s}=null!=t?t:{};let u=null===(a=null==o?void 0:o[0])||void 0===a?void 0:a.filter((e=>e.length>0)).join("@");"Error"===u&&(u="webview::unknown"),await window.__TAURI_INVOKE__("plugin:log|log",{level:e,message:n,location:u,file:l,line:c,keyValues:s})}return function(e){e[e.Trace=1]="Trace",e[e.Debug=2]="Debug",e[e.Info=3]="Info",e[e.Warn=4]="Warn",e[e.Error=5]="Error"}(g||(g={})),e.attachConsole=async function(){return await E("log://log",(e=>{const n=e.payload,t=n.message.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,"");switch(n.level){case g.Trace:console.log(t);break;case g.Debug:console.debug(t);break;case g.Info:console.info(t);break;case g.Warn:console.warn(t);break;case g.Error:console.error(t);break;default:throw new Error(`unknown log level ${n.level}`)}}))},e.debug=async function(e,n){await p(g.Debug,e,n)},e.error=async function(e,n){await p(g.Error,e,n)},e.info=async function(e,n){await p(g.Info,e,n)},e.trace=async function(e,n){await p(g.Trace,e,n)},e.warn=async function(e,n){await p(g.Warn,e,n)},e}({});Object.defineProperty(window.__TAURI__,"log",{value:__TAURI_LOG__})} diff --git a/plugins/log/src/lib.rs b/plugins/log/src/lib.rs index e8d548c0..05794dd7 100644 --- a/plugins/log/src/lib.rs +++ b/plugins/log/src/lib.rs @@ -389,6 +389,7 @@ impl Builder { pub fn build(mut self) -> TauriPlugin { plugin::Builder::new("log") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![log]) .setup(move |app_handle, _api| { let app_name = &app_handle.package_info().name; diff --git a/plugins/notification/src/api-iife.js b/plugins/notification/src/api-iife.js new file mode 100644 index 00000000..4ef6d877 --- /dev/null +++ b/plugins/notification/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_NOTIFICATION__=function(n){"use strict";var e=Object.defineProperty,i=(n,e,i)=>{if(!e.has(n))throw TypeError("Cannot "+i)},t=(n,e,t)=>(i(n,e,"read from private field"),t?t.call(n):e.get(n)),o=(n,e,t,o)=>(i(n,e,"write to private field"),o?o.call(n,t):e.set(n,t),t);function r(n,e=!1){let i=window.crypto.getRandomValues(new Uint32Array(1))[0],t=`_${i}`;return Object.defineProperty(window,t,{value:i=>(e&&Reflect.deleteProperty(window,t),n?.(i)),writable:!1,configurable:!0}),i}((n,i)=>{for(var t in i)e(n,t,{get:i[t],enumerable:!0})})({},{Channel:()=>a,PluginListener:()=>f,addPluginListener:()=>d,convertFileSrc:()=>p,invoke:()=>_,transformCallback:()=>r});var c,a=class{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,((n,e,i)=>{if(e.has(n))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(n):e.set(n,i)})(this,c,(()=>{})),this.id=r((n=>{t(this,c).call(this,n)}))}set onmessage(n){o(this,c,n)}get onmessage(){return t(this,c)}toJSON(){return`__CHANNEL__:${this.id}`}};c=new WeakMap;var s,l,u,f=class{constructor(n,e,i){this.plugin=n,this.event=e,this.channelId=i}async unregister(){return _(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}};async function d(n,e,i){let t=new a;return t.onmessage=i,_(`plugin:${n}|register_listener`,{event:e,handler:t}).then((()=>new f(n,e,t.id)))}async function _(n,e={}){return new Promise(((i,t)=>{let o=r((n=>{i(n),Reflect.deleteProperty(window,`_${c}`)}),!0),c=r((n=>{t(n),Reflect.deleteProperty(window,`_${o}`)}),!0);window.__TAURI_IPC__({cmd:n,callback:o,error:c,...e})}))}function p(n,e="asset"){let i=encodeURIComponent(n);return navigator.userAgent.includes("Windows")?`https://${e}.localhost/${i}`:`${e}://localhost/${i}`}return function(n){n.Year="Year",n.Month="Month",n.TwoWeeks="TwoWeeks",n.Week="Week",n.Day="Day",n.Hour="Hour",n.Minute="Minute",n.Second="Second"}(s||(s={})),n.Importance=void 0,(l=n.Importance||(n.Importance={}))[l.None=0]="None",l[l.Min=1]="Min",l[l.Low=2]="Low",l[l.Default=3]="Default",l[l.High=4]="High",n.Visibility=void 0,(u=n.Visibility||(n.Visibility={}))[u.Secret=-1]="Secret",u[u.Private=0]="Private",u[u.Public=1]="Public",n.active=async function(){return _("plugin:notification|get_active")},n.cancel=async function(n){return _("plugin:notification|cancel",{notifications:n})},n.cancelAll=async function(){return _("plugin:notification|cancel")},n.channels=async function(){return _("plugin:notification|getActive")},n.createChannel=async function(n){return _("plugin:notification|create_channel",{...n})},n.isPermissionGranted=async function(){return"default"!==window.Notification.permission?Promise.resolve("granted"===window.Notification.permission):_("plugin:notification|is_permission_granted")},n.onAction=async function(n){return d("notification","actionPerformed",n)},n.onNotificationReceived=async function(n){return d("notification","notification",n)},n.pending=async function(){return _("plugin:notification|get_pending")},n.registerActionTypes=async function(n){return _("plugin:notification|register_action_types",{types:n})},n.removeActive=async function(n){return _("plugin:notification|remove_active",{notifications:n})},n.removeAllActive=async function(){return _("plugin:notification|remove_active")},n.removeChannel=async function(n){return _("plugin:notification|delete_channel",{id:n})},n.requestPermission=async function(){return window.Notification.requestPermission()},n.sendNotification=function(n){"string"==typeof n?new window.Notification(n):new window.Notification(n.title,n)},n}({});Object.defineProperty(window.__TAURI__,"notification",{value:__TAURI_NOTIFICATION__})} diff --git a/plugins/notification/src/lib.rs b/plugins/notification/src/lib.rs index 6e566fe2..03f6db09 100644 --- a/plugins/notification/src/lib.rs +++ b/plugins/notification/src/lib.rs @@ -212,13 +212,15 @@ impl> crate::NotificationExt for T { /// Initializes the plugin. pub fn init() -> TauriPlugin { + let mut init_script = include_str!("init.js").to_string(); + init_script.push_str(include_str!("api-iife.js")); Builder::new("notification") .invoke_handler(tauri::generate_handler![ commands::notify, commands::request_permission, commands::is_permission_granted ]) - .js_init_script(include_str!("init.js").into()) + .js_init_script(init_script) .setup(|app, api| { #[cfg(mobile)] let notification = mobile::init(app, api)?; diff --git a/plugins/os/guest-js/index.ts b/plugins/os/guest-js/index.ts index 36c508f1..9bac01cc 100644 --- a/plugins/os/guest-js/index.ts +++ b/plugins/os/guest-js/index.ts @@ -8,7 +8,11 @@ * @module */ -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} type Platform = | "linux" @@ -63,7 +67,7 @@ const EOL = isWindows() ? "\r\n" : "\n"; * */ async function platform(): Promise { - return invoke("plugin:os|platform"); + return window.__TAURI_INVOKE__("plugin:os|platform"); } /** @@ -77,7 +81,7 @@ async function platform(): Promise { * @since 1.0.0 */ async function version(): Promise { - return invoke("plugin:os|version"); + return window.__TAURI_INVOKE__("plugin:os|version"); } /** @@ -91,7 +95,7 @@ async function version(): Promise { * @since 1.0.0 */ async function type(): Promise { - return invoke("plugin:os|kind"); + return window.__TAURI_INVOKE__("plugin:os|kind"); } /** @@ -106,7 +110,7 @@ async function type(): Promise { * @since 1.0.0 */ async function arch(): Promise { - return invoke("plugin:os|arch"); + return window.__TAURI_INVOKE__("plugin:os|arch"); } /** @@ -120,7 +124,7 @@ async function arch(): Promise { * @since 1.0.0 */ async function tempdir(): Promise { - return invoke("plugin:os|tempdir"); + return window.__TAURI_INVOKE__("plugin:os|tempdir"); } export { EOL, platform, version, type, arch, tempdir }; diff --git a/plugins/os/src/api-iife.js b/plugins/os/src/api-iife.js new file mode 100644 index 00000000..8223ce89 --- /dev/null +++ b/plugins/os/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_OS__=function(n){"use strict";const _=navigator.appVersion.includes("Win")?"\r\n":"\n";return n.EOL=_,n.arch=async function(){return window.__TAURI_INVOKE__("plugin:os|arch")},n.platform=async function(){return window.__TAURI_INVOKE__("plugin:os|platform")},n.tempdir=async function(){return window.__TAURI_INVOKE__("plugin:os|tempdir")},n.type=async function(){return window.__TAURI_INVOKE__("plugin:os|kind")},n.version=async function(){return window.__TAURI_INVOKE__("plugin:os|version")},n}({});Object.defineProperty(window.__TAURI__,"os",{value:__TAURI_OS__})} diff --git a/plugins/os/src/lib.rs b/plugins/os/src/lib.rs index 1b51eaea..488107a4 100644 --- a/plugins/os/src/lib.rs +++ b/plugins/os/src/lib.rs @@ -70,6 +70,7 @@ pub fn tempdir() -> PathBuf { pub fn init() -> TauriPlugin { Builder::new("os") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![ commands::platform, commands::version, diff --git a/plugins/positioner/guest-js/index.ts b/plugins/positioner/guest-js/index.ts index 14bad9e9..cf6d0f24 100644 --- a/plugins/positioner/guest-js/index.ts +++ b/plugins/positioner/guest-js/index.ts @@ -3,7 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} /** * Well known window positions. @@ -33,7 +37,7 @@ export enum Position { * @param to The {@link Position} to move to. */ export async function moveWindow(to: Position): Promise { - await invoke("plugin:positioner|move_window", { + await window.__TAURI_INVOKE__("plugin:positioner|move_window", { position: to, }); } diff --git a/plugins/positioner/src/api-iife.js b/plugins/positioner/src/api-iife.js new file mode 100644 index 00000000..47be9b4d --- /dev/null +++ b/plugins/positioner/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_POSITIONER__=function(t){"use strict";var o;return t.Position=void 0,(o=t.Position||(t.Position={}))[o.TopLeft=0]="TopLeft",o[o.TopRight=1]="TopRight",o[o.BottomLeft=2]="BottomLeft",o[o.BottomRight=3]="BottomRight",o[o.TopCenter=4]="TopCenter",o[o.BottomCenter=5]="BottomCenter",o[o.LeftCenter=6]="LeftCenter",o[o.RightCenter=7]="RightCenter",o[o.Center=8]="Center",o[o.TrayLeft=9]="TrayLeft",o[o.TrayBottomLeft=10]="TrayBottomLeft",o[o.TrayRight=11]="TrayRight",o[o.TrayBottomRight=12]="TrayBottomRight",o[o.TrayCenter=13]="TrayCenter",o[o.TrayBottomCenter=14]="TrayBottomCenter",t.moveWindow=async function(t){await window.__TAURI_INVOKE__("plugin:positioner|move_window",{position:t})},t}({});Object.defineProperty(window.__TAURI__,"positioner",{value:__TAURI_POSITIONER__})} diff --git a/plugins/positioner/src/lib.rs b/plugins/positioner/src/lib.rs index fd0140a4..b7f83c41 100644 --- a/plugins/positioner/src/lib.rs +++ b/plugins/positioner/src/lib.rs @@ -62,8 +62,9 @@ async fn move_window(window: tauri::Window, position: Position) - /// The Tauri plugin that exposes [`WindowExt::move_window`] to the webview. pub fn init() -> TauriPlugin { - let plugin = - plugin::Builder::new("positioner").invoke_handler(tauri::generate_handler![move_window]); + let plugin = plugin::Builder::new("positioner") + .js_init_script(include_str!("api-iife.js").to_string()) + .invoke_handler(tauri::generate_handler![move_window]); #[cfg(feature = "system-tray")] let plugin = plugin.setup(|app_handle, _api| { diff --git a/plugins/process/guest-js/index.ts b/plugins/process/guest-js/index.ts index 403dbc92..b66ad837 100644 --- a/plugins/process/guest-js/index.ts +++ b/plugins/process/guest-js/index.ts @@ -7,7 +7,11 @@ * @module */ -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} /** * Exits immediately with the given `exitCode`. @@ -23,7 +27,7 @@ import { invoke } from "@tauri-apps/api/tauri"; * @since 1.0.0 */ async function exit(code = 0): Promise { - return invoke("plugin:process|exit", { code }); + return window.__TAURI_INVOKE__("plugin:process|exit", { code }); } /** @@ -39,7 +43,7 @@ async function exit(code = 0): Promise { * @since 1.0.0 */ async function relaunch(): Promise { - return invoke("plugin:process|restart"); + return window.__TAURI_INVOKE__("plugin:process|restart"); } export { exit, relaunch }; diff --git a/plugins/process/src/api-iife.js b/plugins/process/src/api-iife.js new file mode 100644 index 00000000..89dfd475 --- /dev/null +++ b/plugins/process/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_PROCESS__=function(_){"use strict";return _.exit=async function(_=0){return window.__TAURI_INVOKE__("plugin:process|exit",{code:_})},_.relaunch=async function(){return window.__TAURI_INVOKE__("plugin:process|restart")},_}({});Object.defineProperty(window.__TAURI__,"process",{value:__TAURI_PROCESS__})} diff --git a/plugins/process/src/lib.rs b/plugins/process/src/lib.rs index d3d48cac..d6c327b3 100644 --- a/plugins/process/src/lib.rs +++ b/plugins/process/src/lib.rs @@ -11,6 +11,7 @@ mod commands; pub fn init() -> TauriPlugin { Builder::new("process") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![commands::exit, commands::restart]) .build() } diff --git a/plugins/shell/guest-js/index.ts b/plugins/shell/guest-js/index.ts index 9d5abb21..da964f9d 100644 --- a/plugins/shell/guest-js/index.ts +++ b/plugins/shell/guest-js/index.ts @@ -62,7 +62,14 @@ * @module */ -import { invoke, transformCallback } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + __TAURI__: { + transformCallback: (cb: (payload: T) => void) => number; + }; + } +} /** * @since 1.0.0 @@ -119,11 +126,11 @@ async function execute( Object.freeze(args); } - return invoke("plugin:shell|execute", { + return window.__TAURI_INVOKE__("plugin:shell|execute", { program, args, options, - onEventFn: transformCallback(onEvent), + onEventFn: window.__TAURI__.transformCallback(onEvent), }); } @@ -345,7 +352,7 @@ class Child { * @returns A promise indicating the success or failure of the operation. */ async write(data: IOPayload): Promise { - return invoke("plugin:shell|stdin_write", { + return window.__TAURI_INVOKE__("plugin:shell|stdin_write", { pid: this.pid, // correctly serialize Uint8Arrays buffer: typeof data === "string" ? data : Array.from(data), @@ -358,7 +365,7 @@ class Child { * @returns A promise indicating the success or failure of the operation. */ async kill(): Promise { - return invoke("plugin:shell|kill", { + return window.__TAURI_INVOKE__("plugin:shell|kill", { cmd: "killChild", pid: this.pid, }); @@ -629,7 +636,7 @@ type CommandEvent = * @since 1.0.0 */ async function open(path: string, openWith?: string): Promise { - return invoke("plugin:shell|open", { + return window.__TAURI_INVOKE__("plugin:shell|open", { path, with: openWith, }); diff --git a/plugins/shell/src/api-iife.js b/plugins/shell/src/api-iife.js new file mode 100644 index 00000000..cb6b28ac --- /dev/null +++ b/plugins/shell/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_SHELL__=function(e){"use strict";class t{constructor(){this.eventListeners=Object.create(null)}addListener(e,t){return this.on(e,t)}removeListener(e,t){return this.off(e,t)}on(e,t){return e in this.eventListeners?this.eventListeners[e].push(t):this.eventListeners[e]=[t],this}once(e,t){const s=n=>{this.removeListener(e,s),t(n)};return this.addListener(e,s)}off(e,t){return e in this.eventListeners&&(this.eventListeners[e]=this.eventListeners[e].filter((e=>e!==t))),this}removeAllListeners(e){return e?delete this.eventListeners[e]:this.eventListeners=Object.create(null),this}emit(e,t){if(e in this.eventListeners){const s=this.eventListeners[e];for(const e of s)e(t);return!0}return!1}listenerCount(e){return e in this.eventListeners?this.eventListeners[e].length:0}prependListener(e,t){return e in this.eventListeners?this.eventListeners[e].unshift(t):this.eventListeners[e]=[t],this}prependOnceListener(e,t){const s=n=>{this.removeListener(e,s),t(n)};return this.prependListener(e,s)}}class s{constructor(e){this.pid=e}async write(e){return window.__TAURI_INVOKE__("plugin:shell|stdin_write",{pid:this.pid,buffer:"string"==typeof e?e:Array.from(e)})}async kill(){return window.__TAURI_INVOKE__("plugin:shell|kill",{cmd:"killChild",pid:this.pid})}}class n extends t{constructor(e,s=[],n){super(),this.stdout=new t,this.stderr=new t,this.program=e,this.args="string"==typeof s?[s]:s,this.options=null!=n?n:{}}static create(e,t=[],s){return new n(e,t,s)}static sidecar(e,t=[],s){const r=new n(e,t,s);return r.options.sidecar=!0,r}async spawn(){return async function(e,t,s=[],n){return"object"==typeof s&&Object.freeze(s),window.__TAURI_INVOKE__("plugin:shell|execute",{program:t,args:s,options:n,onEventFn:window.__TAURI__.transformCallback(e)})}((e=>{switch(e.event){case"Error":this.emit("error",e.payload);break;case"Terminated":this.emit("close",e.payload);break;case"Stdout":this.stdout.emit("data",e.payload);break;case"Stderr":this.stderr.emit("data",e.payload)}}),this.program,this.args,this.options).then((e=>new s(e)))}async execute(){return new Promise(((e,t)=>{this.on("error",t);const s=[],n=[];this.stdout.on("data",(e=>{s.push(e)})),this.stderr.on("data",(e=>{n.push(e)})),this.on("close",(t=>{e({code:t.code,signal:t.signal,stdout:this.collectOutput(s),stderr:this.collectOutput(n)})})),this.spawn().catch(t)}))}collectOutput(e){return"raw"===this.options.encoding?e.reduce(((e,t)=>new Uint8Array([...e,...t,10])),new Uint8Array):e.join("\n")}}return e.Child=s,e.Command=n,e.EventEmitter=t,e.open=async function(e,t){return window.__TAURI_INVOKE__("plugin:shell|open",{path:e,with:t})},e}({});Object.defineProperty(window.__TAURI__,"shell",{value:__TAURI_SHELL__})} diff --git a/plugins/shell/src/lib.rs b/plugins/shell/src/lib.rs index 43bf006c..d7637ea5 100644 --- a/plugins/shell/src/lib.rs +++ b/plugins/shell/src/lib.rs @@ -67,8 +67,11 @@ impl> ShellExt for T { } pub fn init() -> TauriPlugin> { + let mut init_script = include_str!("init.js").to_string(); + init_script.push_str(include_str!("api-iife.js")); + Builder::>::new("shell") - .js_init_script(include_str!("init.js").to_string()) + .js_init_script(init_script) .invoke_handler(tauri::generate_handler![ commands::execute, commands::stdin_write, diff --git a/plugins/sql/guest-js/index.ts b/plugins/sql/guest-js/index.ts index 687f6321..24f35ec9 100644 --- a/plugins/sql/guest-js/index.ts +++ b/plugins/sql/guest-js/index.ts @@ -2,7 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} export interface QueryResult { /** The number of rows affected by the query. */ @@ -46,7 +50,7 @@ export default class Database { * ``` */ static async load(path: string): Promise { - const _path = await invoke("plugin:sql|load", { + const _path = await window.__TAURI_INVOKE__("plugin:sql|load", { db: path, }); @@ -87,14 +91,13 @@ export default class Database { * ``` */ async execute(query: string, bindValues?: unknown[]): Promise { - const [rowsAffected, lastInsertId] = await invoke<[number, number]>( - "plugin:sql|execute", - { - db: this.path, - query, - values: bindValues ?? [], - } - ); + const [rowsAffected, lastInsertId] = await window.__TAURI_INVOKE__< + [number, number] + >("plugin:sql|execute", { + db: this.path, + query, + values: bindValues ?? [], + }); return { lastInsertId, @@ -115,7 +118,7 @@ export default class Database { * ``` */ async select(query: string, bindValues?: unknown[]): Promise { - const result = await invoke("plugin:sql|select", { + const result = await window.__TAURI_INVOKE__("plugin:sql|select", { db: this.path, query, values: bindValues ?? [], @@ -136,7 +139,7 @@ export default class Database { * @param db - Optionally state the name of a database if you are managing more than one. Otherwise, all database pools will be in scope. */ async close(db?: string): Promise { - const success = await invoke("plugin:sql|close", { + const success = await window.__TAURI_INVOKE__("plugin:sql|close", { db, }); return success; diff --git a/plugins/sql/src/api-iife.js b/plugins/sql/src/api-iife.js new file mode 100644 index 00000000..e43792cd --- /dev/null +++ b/plugins/sql/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_SQL__=function(){"use strict";class _{constructor(_){this.path=_}static async load(t){const e=await window.__TAURI_INVOKE__("plugin:sql|load",{db:t});return new _(e)}static get(t){return new _(t)}async execute(_,t){const[e,n]=await window.__TAURI_INVOKE__("plugin:sql|execute",{db:this.path,query:_,values:null!=t?t:[]});return{lastInsertId:n,rowsAffected:e}}async select(_,t){return await window.__TAURI_INVOKE__("plugin:sql|select",{db:this.path,query:_,values:null!=t?t:[]})}async close(_){return await window.__TAURI_INVOKE__("plugin:sql|close",{db:_})}}return _}();Object.defineProperty(window.__TAURI__,"sql",{value:__TAURI_SQL__})} diff --git a/plugins/sql/src/plugin.rs b/plugins/sql/src/plugin.rs index 460b2442..8d524345 100644 --- a/plugins/sql/src/plugin.rs +++ b/plugins/sql/src/plugin.rs @@ -280,6 +280,7 @@ impl Builder { pub fn build(mut self) -> TauriPlugin> { PluginBuilder::>::new("sql") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![load, execute, select, close]) .setup(|app, api| { let config = api.config().clone().unwrap_or_default(); diff --git a/plugins/store/guest-js/index.ts b/plugins/store/guest-js/index.ts index 966e371d..49c452ca 100644 --- a/plugins/store/guest-js/index.ts +++ b/plugins/store/guest-js/index.ts @@ -2,9 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -import { invoke } from "@tauri-apps/api/tauri"; import { listen, UnlistenFn } from "@tauri-apps/api/event"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} + interface ChangePayload { path: string; key: string; @@ -28,7 +33,7 @@ export class Store { * @returns */ async set(key: string, value: unknown): Promise { - return await invoke("plugin:store|set", { + return await window.__TAURI_INVOKE__("plugin:store|set", { path: this.path, key, value, @@ -42,7 +47,7 @@ export class Store { * @returns */ async get(key: string): Promise { - return await invoke("plugin:store|get", { + return await window.__TAURI_INVOKE__("plugin:store|get", { path: this.path, key, }); @@ -55,7 +60,7 @@ export class Store { * @returns */ async has(key: string): Promise { - return await invoke("plugin:store|has", { + return await window.__TAURI_INVOKE__("plugin:store|has", { path: this.path, key, }); @@ -68,7 +73,7 @@ export class Store { * @returns */ async delete(key: string): Promise { - return await invoke("plugin:store|delete", { + return await window.__TAURI_INVOKE__("plugin:store|delete", { path: this.path, key, }); @@ -81,7 +86,7 @@ export class Store { * @returns */ async clear(): Promise { - return await invoke("plugin:store|clear", { + return await window.__TAURI_INVOKE__("plugin:store|clear", { path: this.path, }); } @@ -93,7 +98,7 @@ export class Store { * @returns */ async reset(): Promise { - return await invoke("plugin:store|reset", { + return await window.__TAURI_INVOKE__("plugin:store|reset", { path: this.path, }); } @@ -104,7 +109,7 @@ export class Store { * @returns */ async keys(): Promise { - return await invoke("plugin:store|keys", { + return await window.__TAURI_INVOKE__("plugin:store|keys", { path: this.path, }); } @@ -115,7 +120,7 @@ export class Store { * @returns */ async values(): Promise { - return await invoke("plugin:store|values", { + return await window.__TAURI_INVOKE__("plugin:store|values", { path: this.path, }); } @@ -126,7 +131,7 @@ export class Store { * @returns */ async entries(): Promise> { - return await invoke("plugin:store|entries", { + return await window.__TAURI_INVOKE__("plugin:store|entries", { path: this.path, }); } @@ -137,7 +142,7 @@ export class Store { * @returns */ async length(): Promise { - return await invoke("plugin:store|length", { + return await window.__TAURI_INVOKE__("plugin:store|length", { path: this.path, }); } @@ -151,7 +156,7 @@ export class Store { * @returns */ async load(): Promise { - return await invoke("plugin:store|load", { + return await window.__TAURI_INVOKE__("plugin:store|load", { path: this.path, }); } @@ -164,7 +169,7 @@ export class Store { * @returns */ async save(): Promise { - return await invoke("plugin:store|save", { + return await window.__TAURI_INVOKE__("plugin:store|save", { path: this.path, }); } diff --git a/plugins/store/src/api-iife.js b/plugins/store/src/api-iife.js new file mode 100644 index 00000000..df38427d --- /dev/null +++ b/plugins/store/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_STORE__=function(e){"use strict";var t=Object.defineProperty,n=(e,n)=>{for(var a in n)t(e,a,{get:n[a],enumerable:!0})},a=(e,t,n)=>{if(!t.has(e))throw TypeError("Cannot "+n)},r=(e,t,n)=>(a(e,t,"read from private field"),n?n.call(e):t.get(e)),i=(e,t,n,r)=>(a(e,t,"write to private field"),r?r.call(e,n):t.set(e,n),n);function s(e,t=!1){let n=window.crypto.getRandomValues(new Uint32Array(1))[0],a=`_${n}`;return Object.defineProperty(window,a,{value:n=>(t&&Reflect.deleteProperty(window,a),e?.(n)),writable:!1,configurable:!0}),n}n({},{Channel:()=>o,PluginListener:()=>l,addPluginListener:()=>u,convertFileSrc:()=>h,invoke:()=>c,transformCallback:()=>s});var _,o=class{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,((e,t,n)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,n)})(this,_,(()=>{})),this.id=s((e=>{r(this,_).call(this,e)}))}set onmessage(e){i(this,_,e)}get onmessage(){return r(this,_)}toJSON(){return`__CHANNEL__:${this.id}`}};_=new WeakMap;var l=class{constructor(e,t,n){this.plugin=e,this.event=t,this.channelId=n}async unregister(){return c(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}};async function u(e,t,n){let a=new o;return a.onmessage=n,c(`plugin:${e}|register_listener`,{event:t,handler:a}).then((()=>new l(e,t,a.id)))}async function c(e,t={}){return new Promise(((n,a)=>{let r=s((e=>{n(e),Reflect.deleteProperty(window,`_${i}`)}),!0),i=s((e=>{a(e),Reflect.deleteProperty(window,`_${r}`)}),!0);window.__TAURI_IPC__({cmd:e,callback:r,error:i,...t})}))}function h(e,t="asset"){let n=encodeURIComponent(e);return navigator.userAgent.includes("Windows")?`https://${t}.localhost/${n}`:`${t}://localhost/${n}`}async function d(e,t){await c("plugin:event|unlisten",{event:e,eventId:t})}async function p(e,t,n){return c("plugin:event|listen",{event:e,windowLabel:t,handler:s(n)}).then((t=>async()=>d(e,t)))}n({},{TauriEvent:()=>y,emit:()=>E,listen:()=>I,once:()=>g});var w,y=((w=y||{}).WINDOW_RESIZED="tauri://resize",w.WINDOW_MOVED="tauri://move",w.WINDOW_CLOSE_REQUESTED="tauri://close-requested",w.WINDOW_CREATED="tauri://window-created",w.WINDOW_DESTROYED="tauri://destroyed",w.WINDOW_FOCUS="tauri://focus",w.WINDOW_BLUR="tauri://blur",w.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",w.WINDOW_THEME_CHANGED="tauri://theme-changed",w.WINDOW_FILE_DROP="tauri://file-drop",w.WINDOW_FILE_DROP_HOVER="tauri://file-drop-hover",w.WINDOW_FILE_DROP_CANCELLED="tauri://file-drop-cancelled",w.MENU="tauri://menu",w);async function I(e,t){return p(e,null,t)}async function g(e,t){return async function(e,t,n){return p(e,t,(t=>{n(t),d(e,t.id).catch((()=>{}))}))}(e,null,t)}async function E(e,t){return async function(e,t,n){await c("plugin:event|emit",{event:e,windowLabel:t,payload:n})}(e,void 0,t)}return e.Store=class{constructor(e){this.path=e}async set(e,t){return await window.__TAURI_INVOKE__("plugin:store|set",{path:this.path,key:e,value:t})}async get(e){return await window.__TAURI_INVOKE__("plugin:store|get",{path:this.path,key:e})}async has(e){return await window.__TAURI_INVOKE__("plugin:store|has",{path:this.path,key:e})}async delete(e){return await window.__TAURI_INVOKE__("plugin:store|delete",{path:this.path,key:e})}async clear(){return await window.__TAURI_INVOKE__("plugin:store|clear",{path:this.path})}async reset(){return await window.__TAURI_INVOKE__("plugin:store|reset",{path:this.path})}async keys(){return await window.__TAURI_INVOKE__("plugin:store|keys",{path:this.path})}async values(){return await window.__TAURI_INVOKE__("plugin:store|values",{path:this.path})}async entries(){return await window.__TAURI_INVOKE__("plugin:store|entries",{path:this.path})}async length(){return await window.__TAURI_INVOKE__("plugin:store|length",{path:this.path})}async load(){return await window.__TAURI_INVOKE__("plugin:store|load",{path:this.path})}async save(){return await window.__TAURI_INVOKE__("plugin:store|save",{path:this.path})}async onKeyChange(e,t){return await I("store://change",(n=>{n.payload.path===this.path&&n.payload.key===e&&t(n.payload.value)}))}async onChange(e){return await I("store://change",(t=>{t.payload.path===this.path&&e(t.payload.key,t.payload.value)}))}},e}({});Object.defineProperty(window.__TAURI__,"store",{value:__TAURI_STORE__})} diff --git a/plugins/store/src/lib.rs b/plugins/store/src/lib.rs index 968cdc05..1ce2885e 100644 --- a/plugins/store/src/lib.rs +++ b/plugins/store/src/lib.rs @@ -278,6 +278,7 @@ impl Builder { /// ``` pub fn build(mut self) -> TauriPlugin { plugin::Builder::new("store") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![ set, get, has, delete, clear, reset, keys, values, length, entries, load, save ]) diff --git a/plugins/stronghold/guest-js/index.ts b/plugins/stronghold/guest-js/index.ts index 8bd4e894..568a281b 100644 --- a/plugins/stronghold/guest-js/index.ts +++ b/plugins/stronghold/guest-js/index.ts @@ -2,7 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} type BytesDto = string | number[]; export type ClientPath = @@ -131,16 +135,18 @@ class ProcedureExecutor { outputLocation: Location, sizeBytes?: number ): Promise { - return await invoke("plugin:stronghold|execute_procedure", { - ...this.procedureArgs, - procedure: { - type: "SLIP10Generate", - payload: { - output: outputLocation, - sizeBytes, + return await window + .__TAURI_INVOKE__("plugin:stronghold|execute_procedure", { + ...this.procedureArgs, + procedure: { + type: "SLIP10Generate", + payload: { + output: outputLocation, + sizeBytes, + }, }, - }, - }).then((n) => Uint8Array.from(n)); + }) + .then((n) => Uint8Array.from(n)); } /** @@ -158,20 +164,22 @@ class ProcedureExecutor { sourceLocation: Location, outputLocation: Location ): Promise { - return await invoke("plugin:stronghold|execute_procedure", { - ...this.procedureArgs, - procedure: { - type: "SLIP10Derive", - payload: { - chain, - input: { - type: source, - payload: sourceLocation, + return await window + .__TAURI_INVOKE__("plugin:stronghold|execute_procedure", { + ...this.procedureArgs, + procedure: { + type: "SLIP10Derive", + payload: { + chain, + input: { + type: source, + payload: sourceLocation, + }, + output: outputLocation, }, - output: outputLocation, }, - }, - }).then((n) => Uint8Array.from(n)); + }) + .then((n) => Uint8Array.from(n)); } /** @@ -187,17 +195,19 @@ class ProcedureExecutor { outputLocation: Location, passphrase?: string ): Promise { - return await invoke("plugin:stronghold|execute_procedure", { - ...this.procedureArgs, - procedure: { - type: "BIP39Recover", - payload: { - mnemonic, - passphrase, - output: outputLocation, + return await window + .__TAURI_INVOKE__("plugin:stronghold|execute_procedure", { + ...this.procedureArgs, + procedure: { + type: "BIP39Recover", + payload: { + mnemonic, + passphrase, + output: outputLocation, + }, }, - }, - }).then((n) => Uint8Array.from(n)); + }) + .then((n) => Uint8Array.from(n)); } /** @@ -211,16 +221,18 @@ class ProcedureExecutor { outputLocation: Location, passphrase?: string ): Promise { - return await invoke("plugin:stronghold|execute_procedure", { - ...this.procedureArgs, - procedure: { - type: "BIP39Generate", - payload: { - output: outputLocation, - passphrase, + return await window + .__TAURI_INVOKE__("plugin:stronghold|execute_procedure", { + ...this.procedureArgs, + procedure: { + type: "BIP39Generate", + payload: { + output: outputLocation, + passphrase, + }, }, - }, - }).then((n) => Uint8Array.from(n)); + }) + .then((n) => Uint8Array.from(n)); } /** @@ -229,16 +241,18 @@ class ProcedureExecutor { * @returns A promise resolving to the public key hex string. */ async getEd25519PublicKey(privateKeyLocation: Location): Promise { - return await invoke("plugin:stronghold|execute_procedure", { - ...this.procedureArgs, - procedure: { - type: "PublicKey", - payload: { - type: "Ed25519", - privateKey: privateKeyLocation, + return await window + .__TAURI_INVOKE__("plugin:stronghold|execute_procedure", { + ...this.procedureArgs, + procedure: { + type: "PublicKey", + payload: { + type: "Ed25519", + privateKey: privateKeyLocation, + }, }, - }, - }).then((n) => Uint8Array.from(n)); + }) + .then((n) => Uint8Array.from(n)); } /** @@ -251,16 +265,18 @@ class ProcedureExecutor { privateKeyLocation: Location, msg: string ): Promise { - return await invoke("plugin:stronghold|execute_procedure", { - ...this.procedureArgs, - procedure: { - type: "Ed25519Sign", - payload: { - privateKey: privateKeyLocation, - msg, + return await window + .__TAURI_INVOKE__("plugin:stronghold|execute_procedure", { + ...this.procedureArgs, + procedure: { + type: "Ed25519Sign", + payload: { + privateKey: privateKeyLocation, + msg, + }, }, - }, - }).then((n) => Uint8Array.from(n)); + }) + .then((n) => Uint8Array.from(n)); } } @@ -298,11 +314,13 @@ export class Store { } async get(key: StoreKey): Promise { - return await invoke("plugin:stronghold|get_store_record", { - snapshotPath: this.path, - client: this.client, - key: toBytesDto(key), - }).then((v) => Uint8Array.from(v)); + return await window + .__TAURI_INVOKE__("plugin:stronghold|get_store_record", { + snapshotPath: this.path, + client: this.client, + key: toBytesDto(key), + }) + .then((v) => Uint8Array.from(v)); } async insert( @@ -310,24 +328,29 @@ export class Store { value: number[], lifetime?: Duration ): Promise { - return await invoke("plugin:stronghold|save_store_record", { - snapshotPath: this.path, - client: this.client, - key: toBytesDto(key), - value, - lifetime, - }); - } - - async remove(key: StoreKey): Promise { - return await invoke( - "plugin:stronghold|remove_store_record", + return await window.__TAURI_INVOKE__( + "plugin:stronghold|save_store_record", { snapshotPath: this.path, client: this.client, key: toBytesDto(key), + value, + lifetime, } - ).then((v) => (v != null ? Uint8Array.from(v) : null)); + ); + } + + async remove(key: StoreKey): Promise { + return await window + .__TAURI_INVOKE__( + "plugin:stronghold|remove_store_record", + { + snapshotPath: this.path, + client: this.client, + key: toBytesDto(key), + } + ) + .then((v) => (v != null ? Uint8Array.from(v) : null)); } } @@ -362,7 +385,7 @@ export class Vault extends ProcedureExecutor { * @returns */ async insert(recordPath: RecordPath, secret: number[]): Promise { - return await invoke("plugin:stronghold|save_secret", { + return await window.__TAURI_INVOKE__("plugin:stronghold|save_secret", { snapshotPath: this.path, client: this.client, vault: this.name, @@ -378,7 +401,7 @@ export class Vault extends ProcedureExecutor { * @returns */ async remove(location: Location): Promise { - return await invoke("plugin:stronghold|remove_secret", { + return await window.__TAURI_INVOKE__("plugin:stronghold|remove_secret", { snapshotPath: this.path, client: this.client, vault: this.name, @@ -410,7 +433,7 @@ export class Stronghold { * @returns */ private async reload(password: string): Promise { - return await invoke("plugin:stronghold|initialize", { + return await window.__TAURI_INVOKE__("plugin:stronghold|initialize", { snapshotPath: this.path, password, }); @@ -420,23 +443,27 @@ export class Stronghold { * Remove this instance from the cache. */ async unload(): Promise { - return await invoke("plugin:stronghold|destroy", { + return await window.__TAURI_INVOKE__("plugin:stronghold|destroy", { snapshotPath: this.path, }); } async loadClient(client: ClientPath): Promise { - return await invoke("plugin:stronghold|load_client", { - snapshotPath: this.path, - client: toBytesDto(client), - }).then(() => new Client(this.path, client)); + return await window + .__TAURI_INVOKE__("plugin:stronghold|load_client", { + snapshotPath: this.path, + client: toBytesDto(client), + }) + .then(() => new Client(this.path, client)); } async createClient(client: ClientPath): Promise { - return await invoke("plugin:stronghold|create_client", { - snapshotPath: this.path, - client: toBytesDto(client), - }).then(() => new Client(this.path, client)); + return await window + .__TAURI_INVOKE__("plugin:stronghold|create_client", { + snapshotPath: this.path, + client: toBytesDto(client), + }) + .then(() => new Client(this.path, client)); } /** @@ -444,7 +471,7 @@ export class Stronghold { * @returns */ async save(): Promise { - return await invoke("plugin:stronghold|save", { + return await window.__TAURI_INVOKE__("plugin:stronghold|save", { snapshotPath: this.path, }); } diff --git a/plugins/stronghold/src/api-iife.js b/plugins/stronghold/src/api-iife.js new file mode 100644 index 00000000..5fbafd86 --- /dev/null +++ b/plugins/stronghold/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_STRONGHOLD__=function(t){"use strict";function e(t){return"string"==typeof t?t:Array.from(t instanceof ArrayBuffer?new Uint8Array(t):t)}class r{constructor(t,e){this.type=t,this.payload=e}static generic(t,n){return new r("Generic",{vault:e(t),record:e(n)})}static counter(t,n){return new r("Counter",{vault:e(t),counter:n})}}class n{constructor(t){this.procedureArgs=t}async generateSLIP10Seed(t,e){return await window.__TAURI_INVOKE__("plugin:stronghold|execute_procedure",{...this.procedureArgs,procedure:{type:"SLIP10Generate",payload:{output:t,sizeBytes:e}}}).then((t=>Uint8Array.from(t)))}async deriveSLIP10(t,e,r,n){return await window.__TAURI_INVOKE__("plugin:stronghold|execute_procedure",{...this.procedureArgs,procedure:{type:"SLIP10Derive",payload:{chain:t,input:{type:e,payload:r},output:n}}}).then((t=>Uint8Array.from(t)))}async recoverBIP39(t,e,r){return await window.__TAURI_INVOKE__("plugin:stronghold|execute_procedure",{...this.procedureArgs,procedure:{type:"BIP39Recover",payload:{mnemonic:t,passphrase:r,output:e}}}).then((t=>Uint8Array.from(t)))}async generateBIP39(t,e){return await window.__TAURI_INVOKE__("plugin:stronghold|execute_procedure",{...this.procedureArgs,procedure:{type:"BIP39Generate",payload:{output:t,passphrase:e}}}).then((t=>Uint8Array.from(t)))}async getEd25519PublicKey(t){return await window.__TAURI_INVOKE__("plugin:stronghold|execute_procedure",{...this.procedureArgs,procedure:{type:"PublicKey",payload:{type:"Ed25519",privateKey:t}}}).then((t=>Uint8Array.from(t)))}async signEd25519(t,e){return await window.__TAURI_INVOKE__("plugin:stronghold|execute_procedure",{...this.procedureArgs,procedure:{type:"Ed25519Sign",payload:{privateKey:t,msg:e}}}).then((t=>Uint8Array.from(t)))}}class a{constructor(t,r){this.path=t,this.name=e(r)}getVault(t){return new s(this.path,this.name,e(t))}getStore(){return new i(this.path,this.name)}}class i{constructor(t,e){this.path=t,this.client=e}async get(t){return await window.__TAURI_INVOKE__("plugin:stronghold|get_store_record",{snapshotPath:this.path,client:this.client,key:e(t)}).then((t=>Uint8Array.from(t)))}async insert(t,r,n){return await window.__TAURI_INVOKE__("plugin:stronghold|save_store_record",{snapshotPath:this.path,client:this.client,key:e(t),value:r,lifetime:n})}async remove(t){return await window.__TAURI_INVOKE__("plugin:stronghold|remove_store_record",{snapshotPath:this.path,client:this.client,key:e(t)}).then((t=>null!=t?Uint8Array.from(t):null))}}class s extends n{constructor(t,r,n){super({snapshotPath:t,client:r,vault:n}),this.path=t,this.client=e(r),this.name=e(n)}async insert(t,r){return await window.__TAURI_INVOKE__("plugin:stronghold|save_secret",{snapshotPath:this.path,client:this.client,vault:this.name,recordPath:e(t),secret:r})}async remove(t){return await window.__TAURI_INVOKE__("plugin:stronghold|remove_secret",{snapshotPath:this.path,client:this.client,vault:this.name,location:t})}}return t.Client=a,t.Location=r,t.Store=i,t.Stronghold=class{constructor(t,e){this.path=t,this.reload(e)}async reload(t){return await window.__TAURI_INVOKE__("plugin:stronghold|initialize",{snapshotPath:this.path,password:t})}async unload(){return await window.__TAURI_INVOKE__("plugin:stronghold|destroy",{snapshotPath:this.path})}async loadClient(t){return await window.__TAURI_INVOKE__("plugin:stronghold|load_client",{snapshotPath:this.path,client:e(t)}).then((()=>new a(this.path,t)))}async createClient(t){return await window.__TAURI_INVOKE__("plugin:stronghold|create_client",{snapshotPath:this.path,client:e(t)}).then((()=>new a(this.path,t)))}async save(){return await window.__TAURI_INVOKE__("plugin:stronghold|save",{snapshotPath:this.path})}},t.Vault=s,t}({});Object.defineProperty(window.__TAURI__,"stronghold",{value:__TAURI_STRONGHOLD__})} diff --git a/plugins/stronghold/src/lib.rs b/plugins/stronghold/src/lib.rs index 87bedc92..37322cc6 100644 --- a/plugins/stronghold/src/lib.rs +++ b/plugins/stronghold/src/lib.rs @@ -413,6 +413,7 @@ impl Builder { let password_hash_function = self.password_hash_function; PluginBuilder::new("stronghold") + .js_init_script(include_str!("api-iife.js").to_string()) .setup(move |app, _api| { app.manage(StrongholdCollection::default()); app.manage(PasswordHashFunction(password_hash_function)); diff --git a/plugins/updater/guest-js/index.ts b/plugins/updater/guest-js/index.ts index 269b0f18..0124caf8 100644 --- a/plugins/updater/guest-js/index.ts +++ b/plugins/updater/guest-js/index.ts @@ -46,7 +46,9 @@ class Update { if (onEvent != null) { channel.onmessage = onEvent; } - return invoke("plugin:updater|download_and_install", { onEvent: channel }); + return invoke("plugin:updater|download_and_install", { + onEvent: channel, + }); } } diff --git a/plugins/updater/src/api-iife.js b/plugins/updater/src/api-iife.js new file mode 100644 index 00000000..98b55689 --- /dev/null +++ b/plugins/updater/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_UPDATER__=function(e){"use strict";var n=Object.defineProperty,t=(e,n,t)=>{if(!n.has(e))throw TypeError("Cannot "+t)},r=(e,n,r)=>(t(e,n,"read from private field"),r?r.call(e):n.get(e)),i=(e,n,r,i)=>(t(e,n,"write to private field"),i?i.call(e,r):n.set(e,r),r);function a(e,n=!1){let t=window.crypto.getRandomValues(new Uint32Array(1))[0],r=`_${t}`;return Object.defineProperty(window,r,{value:t=>(n&&Reflect.deleteProperty(window,r),e?.(t)),writable:!1,configurable:!0}),t}((e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})})({},{Channel:()=>s,PluginListener:()=>l,addPluginListener:()=>c,convertFileSrc:()=>u,invoke:()=>d,transformCallback:()=>a});var o,s=class{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,((e,n,t)=>{if(n.has(e))throw TypeError("Cannot add the same private member more than once");n instanceof WeakSet?n.add(e):n.set(e,t)})(this,o,(()=>{})),this.id=a((e=>{r(this,o).call(this,e)}))}set onmessage(e){i(this,o,e)}get onmessage(){return r(this,o)}toJSON(){return`__CHANNEL__:${this.id}`}};o=new WeakMap;var l=class{constructor(e,n,t){this.plugin=e,this.event=n,this.channelId=t}async unregister(){return d(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}};async function c(e,n,t){let r=new s;return r.onmessage=t,d(`plugin:${e}|register_listener`,{event:n,handler:r}).then((()=>new l(e,n,r.id)))}async function d(e,n={}){return new Promise(((t,r)=>{let i=a((e=>{t(e),Reflect.deleteProperty(window,`_${o}`)}),!0),o=a((e=>{r(e),Reflect.deleteProperty(window,`_${i}`)}),!0);window.__TAURI_IPC__({cmd:e,callback:i,error:o,...n})}))}function u(e,n="asset"){let t=encodeURIComponent(e);return navigator.userAgent.includes("Windows")?`https://${n}.localhost/${t}`:`${n}://localhost/${t}`}class _{constructor(e){this.response=e}async downloadAndInstall(e){const n=new s;return null!=e&&(n.onmessage=e),d("plugin:updater|download_and_install",{onEvent:n})}}return e.Update=_,e.check=async function(e){return d("plugin:updater|check",{...e}).then((e=>new _(e)))},e}({});Object.defineProperty(window.__TAURI__,"updater",{value:__TAURI_UPDATER__})} diff --git a/plugins/updater/src/lib.rs b/plugins/updater/src/lib.rs index 711fc742..3b511ca4 100644 --- a/plugins/updater/src/lib.rs +++ b/plugins/updater/src/lib.rs @@ -82,6 +82,7 @@ impl Builder { let target = self.target; let installer_args = self.installer_args; PluginBuilder::::new("updater") + .js_init_script(include_str!("api-iife.js").to_string()) .setup(move |app, api| { let mut config = api.config().clone(); if let Some(installer_args) = installer_args { diff --git a/plugins/upload/src/api-iife.js b/plugins/upload/src/api-iife.js new file mode 100644 index 00000000..b42588ae --- /dev/null +++ b/plugins/upload/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_UPLOAD__=function(e){"use strict";var n=Object.defineProperty,t=(e,n,t)=>{if(!n.has(e))throw TypeError("Cannot "+t)},r=(e,n,r)=>(t(e,n,"read from private field"),r?r.call(e):n.get(e)),o=(e,n,r,o)=>(t(e,n,"write to private field"),o?o.call(e,r):n.set(e,r),r);function a(e,n=!1){let t=window.crypto.getRandomValues(new Uint32Array(1))[0],r=`_${t}`;return Object.defineProperty(window,r,{value:t=>(n&&Reflect.deleteProperty(window,r),e?.(t)),writable:!1,configurable:!0}),t}((e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:!0})})({},{Channel:()=>l,PluginListener:()=>s,addPluginListener:()=>d,convertFileSrc:()=>u,invoke:()=>c,transformCallback:()=>a});var i,l=class{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,((e,n,t)=>{if(n.has(e))throw TypeError("Cannot add the same private member more than once");n instanceof WeakSet?n.add(e):n.set(e,t)})(this,i,(()=>{})),this.id=a((e=>{r(this,i).call(this,e)}))}set onmessage(e){o(this,i,e)}get onmessage(){return r(this,i)}toJSON(){return`__CHANNEL__:${this.id}`}};i=new WeakMap;var s=class{constructor(e,n,t){this.plugin=e,this.event=n,this.channelId=t}async unregister(){return c(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}};async function d(e,n,t){let r=new l;return r.onmessage=t,c(`plugin:${e}|register_listener`,{event:n,handler:r}).then((()=>new s(e,n,r.id)))}async function c(e,n={}){return new Promise(((t,r)=>{let o=a((e=>{t(e),Reflect.deleteProperty(window,`_${i}`)}),!0),i=a((e=>{r(e),Reflect.deleteProperty(window,`_${o}`)}),!0);window.__TAURI_IPC__({cmd:e,callback:o,error:i,...n})}))}function u(e,n="asset"){let t=encodeURIComponent(e);return navigator.userAgent.includes("Windows")?`https://${n}.localhost/${t}`:`${n}://localhost/${t}`}async function _(e,n,t,r){const o=new Uint32Array(1);window.crypto.getRandomValues(o);const a=o[0],i=new l;null!=t&&(i.onmessage=t),await c("plugin:upload|upload",{id:a,url:e,filePath:n,headers:null!=r?r:{},onProgress:i})}return e.default=_,e.download=async function(e,n,t,r){const o=new Uint32Array(1);window.crypto.getRandomValues(o);const a=o[0],i=new l;null!=t&&(i.onmessage=t),await c("plugin:upload|download",{id:a,url:e,filePath:n,headers:null!=r?r:{},onProgress:i})},e.upload=_,Object.defineProperty(e,"__esModule",{value:!0}),e}({});Object.defineProperty(window.__TAURI__,"upload",{value:__TAURI_UPLOAD__})} diff --git a/plugins/upload/src/lib.rs b/plugins/upload/src/lib.rs index 0930efd9..698549af 100644 --- a/plugins/upload/src/lib.rs +++ b/plugins/upload/src/lib.rs @@ -115,6 +115,7 @@ fn file_to_body(channel: Channel, file: File) -> reqwest::Body { pub fn init() -> TauriPlugin { PluginBuilder::new("upload") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![download, upload]) .build() } diff --git a/plugins/websocket/guest-js/index.ts b/plugins/websocket/guest-js/index.ts index 5678f7e0..5fd967b4 100644 --- a/plugins/websocket/guest-js/index.ts +++ b/plugins/websocket/guest-js/index.ts @@ -2,7 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -import { invoke, transformCallback } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + __TAURI__: { + transformCallback: (cb: (payload: T) => void) => number; + }; + } +} export interface MessageKind { type: T; @@ -36,11 +43,13 @@ export default class WebSocket { listeners.forEach((l) => l(message)); }; - return await invoke("plugin:websocket|connect", { - url, - callbackFunction: transformCallback(handler), - options, - }).then((id) => new WebSocket(id, listeners)); + return await window + .__TAURI_INVOKE__("plugin:websocket|connect", { + url, + callbackFunction: window.__TAURI__.transformCallback(handler), + options, + }) + .then((id) => new WebSocket(id, listeners)); } addListener(cb: (arg: Message) => void): void { @@ -60,7 +69,7 @@ export default class WebSocket { "invalid `message` type, expected a `{ type: string, data: any }` object, a string or a numeric array" ); } - return await invoke("plugin:websocket|send", { + return await window.__TAURI_INVOKE__("plugin:websocket|send", { id: this.id, message: m, }); diff --git a/plugins/websocket/src/api-iife.js b/plugins/websocket/src/api-iife.js new file mode 100644 index 00000000..cea3c830 --- /dev/null +++ b/plugins/websocket/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_WEBSOCKET__=function(){"use strict";class e{constructor(e,t){this.id=e,this.listeners=t}static async connect(t,n){const i=[];return await window.__TAURI_INVOKE__("plugin:websocket|connect",{url:t,callbackFunction:window.__TAURI__.transformCallback((e=>{i.forEach((t=>t(e)))})),options:n}).then((t=>new e(t,i)))}addListener(e){this.listeners.push(e)}async send(e){let t;if("string"==typeof e)t={type:"Text",data:e};else if("object"==typeof e&&"type"in e)t=e;else{if(!Array.isArray(e))throw new Error("invalid `message` type, expected a `{ type: string, data: any }` object, a string or a numeric array");t={type:"Binary",data:e}}return await window.__TAURI_INVOKE__("plugin:websocket|send",{id:this.id,message:t})}async disconnect(){return await this.send({type:"Close",data:{code:1e3,reason:"Disconnected by client"}})}}return e}();Object.defineProperty(window.__TAURI__,"websocket",{value:__TAURI_WEBSOCKET__})} diff --git a/plugins/websocket/src/lib.rs b/plugins/websocket/src/lib.rs index 66a0a90e..9f2205f6 100644 --- a/plugins/websocket/src/lib.rs +++ b/plugins/websocket/src/lib.rs @@ -165,6 +165,7 @@ async fn send( pub fn init() -> TauriPlugin { PluginBuilder::new("websocket") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![connect, send]) .setup(|app, _api| { app.manage(ConnectionManager::default()); diff --git a/plugins/window-state/guest-js/index.ts b/plugins/window-state/guest-js/index.ts index 4fed384f..706e3cbf 100644 --- a/plugins/window-state/guest-js/index.ts +++ b/plugins/window-state/guest-js/index.ts @@ -2,7 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -import { invoke } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} interface WindowDef { label: string; @@ -31,14 +35,17 @@ export enum StateFlags { * Save the state of all open windows to disk. */ async function saveWindowState(flags: StateFlags) { - invoke("plugin:window-state|save_window_state", { flags }); + window.__TAURI_INVOKE__("plugin:window-state|save_window_state", { flags }); } /** * Restore the state for the specified window from disk. */ async function restoreState(label: string, flags: StateFlags) { - invoke("plugin:window-state|restore_state", { label, flags }); + window.__TAURI_INVOKE__("plugin:window-state|restore_state", { + label, + flags, + }); } /** diff --git a/plugins/window-state/src/api-iife.js b/plugins/window-state/src/api-iife.js new file mode 100644 index 00000000..86c310f8 --- /dev/null +++ b/plugins/window-state/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_WINDOWSTATE__=function(_){"use strict";var t;async function e(_,t){window.__TAURI_INVOKE__("plugin:window-state|restore_state",{label:_,flags:t})}return _.StateFlags=void 0,(t=_.StateFlags||(_.StateFlags={}))[t.SIZE=1]="SIZE",t[t.POSITION=2]="POSITION",t[t.MAXIMIZED=4]="MAXIMIZED",t[t.VISIBLE=8]="VISIBLE",t[t.DECORATIONS=16]="DECORATIONS",t[t.FULLSCREEN=32]="FULLSCREEN",t[t.ALL=63]="ALL",_.restoreState=e,_.restoreStateCurrent=async function(_){e(window.__TAURI_METADATA__.__currentWindow.label,_)},_.saveWindowState=async function(_){window.__TAURI_INVOKE__("plugin:window-state|save_window_state",{flags:_})},_}({});Object.defineProperty(window.__TAURI__,"windowState",{value:__TAURI_WINDOWSTATE__})} diff --git a/plugins/window-state/src/lib.rs b/plugins/window-state/src/lib.rs index 32345fee..28e00b35 100644 --- a/plugins/window-state/src/lib.rs +++ b/plugins/window-state/src/lib.rs @@ -282,6 +282,7 @@ impl Builder { pub fn build(self) -> TauriPlugin { let flags = self.state_flags; PluginBuilder::new("window-state") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![ cmd::save_window_state, cmd::restore_state diff --git a/plugins/window/guest-js/event.ts b/plugins/window/guest-js/event.ts index 798b4fb4..9ff16f1d 100644 --- a/plugins/window/guest-js/event.ts +++ b/plugins/window/guest-js/event.ts @@ -2,7 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -import { invoke, transformCallback } from "@tauri-apps/api/tauri"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + __TAURI__: { + transformCallback: (cb: (payload: T) => void) => number; + }; + } +} export interface Event { /** Event name */ @@ -28,7 +35,7 @@ export type UnlistenFn = () => void; * @returns */ async function _unlisten(event: string, eventId: number): Promise { - await invoke("plugin:event|unlisten", { + await window.__TAURI_INVOKE__("plugin:event|unlisten", { event, eventId, }); @@ -47,7 +54,7 @@ async function emit( windowLabel?: string, payload?: unknown ): Promise { - await invoke("plugin:event|emit", { + await window.__TAURI_INVOKE__("plugin:event|emit", { event, windowLabel, payload, @@ -66,13 +73,15 @@ async function listen( windowLabel: string | null, handler: EventCallback ): Promise { - return invoke("plugin:event|listen", { - event, - windowLabel, - handler: transformCallback(handler), - }).then((eventId) => { - return async () => _unlisten(event, eventId); - }); + return window + .__TAURI_INVOKE__("plugin:event|listen", { + event, + windowLabel, + handler: window.__TAURI__.transformCallback(handler), + }) + .then((eventId) => { + return async () => _unlisten(event, eventId); + }); } /** diff --git a/plugins/window/guest-js/index.ts b/plugins/window/guest-js/index.ts index 038fdc05..2cf7eb8f 100644 --- a/plugins/window/guest-js/index.ts +++ b/plugins/window/guest-js/index.ts @@ -16,7 +16,6 @@ * @module */ -import { invoke } from "@tauri-apps/api/tauri"; import type { Event, EventName, @@ -27,6 +26,12 @@ import { TauriEvent } from "@tauri-apps/api/event"; // TODO: use from @tauri-apps/api v2 import { emit, listen, once } from "./event"; +declare global { + interface Window { + __TAURI_INVOKE__: (cmd: string, args?: unknown) => Promise; + } +} + type Theme = "light" | "dark"; type TitleBarStyle = "visible" | "transparent" | "overlay"; @@ -403,7 +408,7 @@ class WindowManager extends WebviewWindowHandle { * @returns The window's monitor scale factor. * */ async scaleFactor(): Promise { - return invoke("plugin:window|scale_factor", { + return window.__TAURI_INVOKE__("plugin:window|scale_factor", { label: this.label, }); } @@ -419,9 +424,14 @@ class WindowManager extends WebviewWindowHandle { * @returns The window's inner position. * */ async innerPosition(): Promise { - return invoke<{ x: number; y: number }>("plugin:window|inner_position", { - label: this.label, - }).then(({ x, y }) => new PhysicalPosition(x, y)); + return window + .__TAURI_INVOKE__<{ x: number; y: number }>( + "plugin:window|inner_position", + { + label: this.label, + } + ) + .then(({ x, y }) => new PhysicalPosition(x, y)); } /** @@ -435,9 +445,14 @@ class WindowManager extends WebviewWindowHandle { * @returns The window's outer position. * */ async outerPosition(): Promise { - return invoke<{ x: number; y: number }>("plugin:window|outer_position", { - label: this.label, - }).then(({ x, y }) => new PhysicalPosition(x, y)); + return window + .__TAURI_INVOKE__<{ x: number; y: number }>( + "plugin:window|outer_position", + { + label: this.label, + } + ) + .then(({ x, y }) => new PhysicalPosition(x, y)); } /** @@ -452,12 +467,14 @@ class WindowManager extends WebviewWindowHandle { * @returns The window's inner size. */ async innerSize(): Promise { - return invoke<{ width: number; height: number }>( - "plugin:window|inner_size", - { - label: this.label, - } - ).then(({ width, height }) => new PhysicalSize(width, height)); + return window + .__TAURI_INVOKE__<{ width: number; height: number }>( + "plugin:window|inner_size", + { + label: this.label, + } + ) + .then(({ width, height }) => new PhysicalSize(width, height)); } /** @@ -472,12 +489,14 @@ class WindowManager extends WebviewWindowHandle { * @returns The window's outer size. */ async outerSize(): Promise { - return invoke<{ width: number; height: number }>( - "plugin:window|outer_size", - { - label: this.label, - } - ).then(({ width, height }) => new PhysicalSize(width, height)); + return window + .__TAURI_INVOKE__<{ width: number; height: number }>( + "plugin:window|outer_size", + { + label: this.label, + } + ) + .then(({ width, height }) => new PhysicalSize(width, height)); } /** @@ -491,7 +510,7 @@ class WindowManager extends WebviewWindowHandle { * @returns Whether the window is in fullscreen mode or not. * */ async isFullscreen(): Promise { - return invoke("plugin:window|is_fullscreen", { + return window.__TAURI_INVOKE__("plugin:window|is_fullscreen", { label: this.label, }); } @@ -507,7 +526,7 @@ class WindowManager extends WebviewWindowHandle { * @since 1.3.0 * */ async isMinimized(): Promise { - return invoke("plugin:window|is_minimized", { + return window.__TAURI_INVOKE__("plugin:window|is_minimized", { label: this.label, }); } @@ -523,7 +542,7 @@ class WindowManager extends WebviewWindowHandle { * @returns Whether the window is maximized or not. * */ async isMaximized(): Promise { - return invoke("plugin:window|is_maximized", { + return window.__TAURI_INVOKE__("plugin:window|is_maximized", { label: this.label, }); } @@ -539,7 +558,7 @@ class WindowManager extends WebviewWindowHandle { * @returns Whether the window is decorated or not. * */ async isDecorated(): Promise { - return invoke("plugin:window|is_decorated", { + return window.__TAURI_INVOKE__("plugin:window|is_decorated", { label: this.label, }); } @@ -555,7 +574,7 @@ class WindowManager extends WebviewWindowHandle { * @returns Whether the window is resizable or not. * */ async isResizable(): Promise { - return invoke("plugin:window|is_resizable", { + return window.__TAURI_INVOKE__("plugin:window|is_resizable", { label: this.label, }); } @@ -571,7 +590,7 @@ class WindowManager extends WebviewWindowHandle { * @returns Whether the window is visible or not. * */ async isVisible(): Promise { - return invoke("plugin:window|is_visible", { + return window.__TAURI_INVOKE__("plugin:window|is_visible", { label: this.label, }); } @@ -587,7 +606,7 @@ class WindowManager extends WebviewWindowHandle { * @since 1.3.0 * */ async title(): Promise { - return invoke("plugin:window|title", { + return window.__TAURI_INVOKE__("plugin:window|title", { label: this.label, }); } @@ -608,7 +627,7 @@ class WindowManager extends WebviewWindowHandle { * @returns The window theme. * */ async theme(): Promise { - return invoke("plugin:window|theme", { + return window.__TAURI_INVOKE__("plugin:window|theme", { label: this.label, }); } @@ -627,7 +646,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async center(): Promise { - return invoke("plugin:window|center", { + return window.__TAURI_INVOKE__("plugin:window|center", { label: this.label, }); } @@ -665,7 +684,7 @@ class WindowManager extends WebviewWindowHandle { } } - return invoke("plugin:window|request_user_attention", { + return window.__TAURI_INVOKE__("plugin:window|request_user_attention", { label: this.label, value: requestType_, }); @@ -683,7 +702,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async setResizable(resizable: boolean): Promise { - return invoke("plugin:window|set_resizable", { + return window.__TAURI_INVOKE__("plugin:window|set_resizable", { label: this.label, value: resizable, }); @@ -701,7 +720,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async setTitle(title: string): Promise { - return invoke("plugin:window|set_title", { + return window.__TAURI_INVOKE__("plugin:window|set_title", { label: this.label, value: title, }); @@ -718,7 +737,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async maximize(): Promise { - return invoke("plugin:window|maximize", { + return window.__TAURI_INVOKE__("plugin:window|maximize", { label: this.label, }); } @@ -734,7 +753,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async unmaximize(): Promise { - return invoke("plugin:window|unmaximize", { + return window.__TAURI_INVOKE__("plugin:window|unmaximize", { label: this.label, }); } @@ -750,7 +769,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async toggleMaximize(): Promise { - return invoke("plugin:window|toggle_maximize", { + return window.__TAURI_INVOKE__("plugin:window|toggle_maximize", { label: this.label, }); } @@ -766,7 +785,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async minimize(): Promise { - return invoke("plugin:window|minimize", { + return window.__TAURI_INVOKE__("plugin:window|minimize", { label: this.label, }); } @@ -782,7 +801,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async unminimize(): Promise { - return invoke("plugin:window|unminimize", { + return window.__TAURI_INVOKE__("plugin:window|unminimize", { label: this.label, }); } @@ -798,7 +817,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async show(): Promise { - return invoke("plugin:window|show", { + return window.__TAURI_INVOKE__("plugin:window|show", { label: this.label, }); } @@ -814,7 +833,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async hide(): Promise { - return invoke("plugin:window|hide", { + return window.__TAURI_INVOKE__("plugin:window|hide", { label: this.label, }); } @@ -830,7 +849,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async close(): Promise { - return invoke("plugin:window|close", { + return window.__TAURI_INVOKE__("plugin:window|close", { label: this.label, }); } @@ -847,7 +866,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async setDecorations(decorations: boolean): Promise { - return invoke("plugin:window|set_decorations", { + return window.__TAURI_INVOKE__("plugin:window|set_decorations", { label: this.label, value: decorations, }); @@ -875,7 +894,7 @@ class WindowManager extends WebviewWindowHandle { * @since 2.0 */ async setShadow(enable: boolean): Promise { - return invoke("plugin:window|set_shadow", { + return window.__TAURI_INVOKE__("plugin:window|set_shadow", { label: this.label, value: enable, }); @@ -893,7 +912,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async setAlwaysOnTop(alwaysOnTop: boolean): Promise { - return invoke("plugin:window|set_always_on_top", { + return window.__TAURI_INVOKE__("plugin:window|set_always_on_top", { label: this.label, value: alwaysOnTop, }); @@ -912,7 +931,7 @@ class WindowManager extends WebviewWindowHandle { * @since 1.2.0 */ async setContentProtected(protected_: boolean): Promise { - return invoke("plugin:window|set_content_protected", { + return window.__TAURI_INVOKE__("plugin:window|set_content_protected", { label: this.label, value: protected_, }); @@ -936,7 +955,7 @@ class WindowManager extends WebviewWindowHandle { ); } - return invoke("plugin:window|set_size", { + return window.__TAURI_INVOKE__("plugin:window|set_size", { label: this.label, value: { type: size.type, @@ -968,7 +987,7 @@ class WindowManager extends WebviewWindowHandle { ); } - return invoke("plugin:window|set_min_size", { + return window.__TAURI_INVOKE__("plugin:window|set_min_size", { label: this.label, value: size ? { @@ -1002,7 +1021,7 @@ class WindowManager extends WebviewWindowHandle { ); } - return invoke("plugin:window|set_max_size", { + return window.__TAURI_INVOKE__("plugin:window|set_max_size", { label: this.label, value: size ? { @@ -1039,7 +1058,7 @@ class WindowManager extends WebviewWindowHandle { ); } - return invoke("plugin:window|set_position", { + return window.__TAURI_INVOKE__("plugin:window|set_position", { label: this.label, value: { type: position.type, @@ -1063,7 +1082,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async setFullscreen(fullscreen: boolean): Promise { - return invoke("plugin:window|set_fullscreen", { + return window.__TAURI_INVOKE__("plugin:window|set_fullscreen", { label: this.label, value: fullscreen, }); @@ -1080,7 +1099,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async setFocus(): Promise { - return invoke("plugin:window|set_focus", { + return window.__TAURI_INVOKE__("plugin:window|set_focus", { label: this.label, }); } @@ -1104,7 +1123,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async setIcon(icon: string | Uint8Array): Promise { - return invoke("plugin:window|set_icon", { + return window.__TAURI_INVOKE__("plugin:window|set_icon", { label: this.label, value: typeof icon === "string" ? icon : Array.from(icon), }); @@ -1126,7 +1145,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async setSkipTaskbar(skip: boolean): Promise { - return invoke("plugin:window|set_skip_taskbar", { + return window.__TAURI_INVOKE__("plugin:window|set_skip_taskbar", { label: this.label, value: skip, }); @@ -1152,7 +1171,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async setCursorGrab(grab: boolean): Promise { - return invoke("plugin:window|set_cursor_grab", { + return window.__TAURI_INVOKE__("plugin:window|set_cursor_grab", { label: this.label, value: grab, }); @@ -1176,7 +1195,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async setCursorVisible(visible: boolean): Promise { - return invoke("plugin:window|set_cursor_visible", { + return window.__TAURI_INVOKE__("plugin:window|set_cursor_visible", { label: this.label, value: visible, }); @@ -1194,7 +1213,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async setCursorIcon(icon: CursorIcon): Promise { - return invoke("plugin:window|set_cursor_icon", { + return window.__TAURI_INVOKE__("plugin:window|set_cursor_icon", { label: this.label, value: icon, }); @@ -1223,7 +1242,7 @@ class WindowManager extends WebviewWindowHandle { ); } - return invoke("plugin:window|set_cursor_position", { + return window.__TAURI_INVOKE__("plugin:window|set_cursor_position", { label: this.label, value: { type: position.type, @@ -1248,7 +1267,7 @@ class WindowManager extends WebviewWindowHandle { * @returns A promise indicating the success or failure of the operation. */ async setIgnoreCursorEvents(ignore: boolean): Promise { - return invoke("plugin:window|set_ignore_cursor_events", { + return window.__TAURI_INVOKE__("plugin:window|set_ignore_cursor_events", { label: this.label, value: ignore, }); @@ -1265,7 +1284,7 @@ class WindowManager extends WebviewWindowHandle { * @return A promise indicating the success or failure of the operation. */ async startDragging(): Promise { - return invoke("plugin:window|start_dragging", { + return window.__TAURI_INVOKE__("plugin:window|start_dragging", { label: this.label, }); } @@ -1622,12 +1641,13 @@ class WebviewWindow extends WindowManager { super(label); // @ts-expect-error `skip` is not a public API so it is not defined in WindowOptions if (!options?.skip) { - invoke("plugin:window|create", { - options: { - ...options, - label, - }, - }) + window + .__TAURI_INVOKE__("plugin:window|create", { + options: { + ...options, + label, + }, + }) .then(async () => this.emit("tauri://created")) .catch(async (e: string) => this.emit("tauri://error", e)); } @@ -1813,9 +1833,9 @@ function mapPhysicalSize(m: PhysicalSize): PhysicalSize { * @since 1.0.0 */ async function currentMonitor(): Promise { - return invoke("plugin:window|current_monitor").then( - mapMonitor - ); + return window + .__TAURI_INVOKE__("plugin:window|current_monitor") + .then(mapMonitor); } /** @@ -1830,9 +1850,9 @@ async function currentMonitor(): Promise { * @since 1.0.0 */ async function primaryMonitor(): Promise { - return invoke("plugin:window|primary_monitor").then( - mapMonitor - ); + return window + .__TAURI_INVOKE__("plugin:window|primary_monitor") + .then(mapMonitor); } /** @@ -1846,9 +1866,9 @@ async function primaryMonitor(): Promise { * @since 1.0.0 */ async function availableMonitors(): Promise { - return invoke("plugin:window|available_monitors").then( - (ms) => ms.map(mapMonitor) as Monitor[] - ); + return window + .__TAURI_INVOKE__("plugin:window|available_monitors") + .then((ms) => ms.map(mapMonitor) as Monitor[]); } export { diff --git a/plugins/window/src/api-iife.js b/plugins/window/src/api-iife.js new file mode 100644 index 00000000..ffa35ae0 --- /dev/null +++ b/plugins/window/src/api-iife.js @@ -0,0 +1 @@ +if("__TAURI__"in window){var __TAURI_WINDOW__=function(e){"use strict";var n=Object.defineProperty,i=(e,i)=>{for(var t in i)n(e,t,{get:i[t],enumerable:!0})},t=(e,n,i)=>{if(!n.has(e))throw TypeError("Cannot "+i)},l=(e,n,i)=>(t(e,n,"read from private field"),i?i.call(e):n.get(e)),a=(e,n,i,l)=>(t(e,n,"write to private field"),l?l.call(e,i):n.set(e,i),i);function s(e,n=!1){let i=window.crypto.getRandomValues(new Uint32Array(1))[0],t=`_${i}`;return Object.defineProperty(window,t,{value:i=>(n&&Reflect.deleteProperty(window,t),e?.(i)),writable:!1,configurable:!0}),i}i({},{Channel:()=>o,PluginListener:()=>_,addPluginListener:()=>w,convertFileSrc:()=>c,invoke:()=>u,transformCallback:()=>s});var r,o=class{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,((e,n,i)=>{if(n.has(e))throw TypeError("Cannot add the same private member more than once");n instanceof WeakSet?n.add(e):n.set(e,i)})(this,r,(()=>{})),this.id=s((e=>{l(this,r).call(this,e)}))}set onmessage(e){a(this,r,e)}get onmessage(){return l(this,r)}toJSON(){return`__CHANNEL__:${this.id}`}};r=new WeakMap;var _=class{constructor(e,n,i){this.plugin=e,this.event=n,this.channelId=i}async unregister(){return u(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}};async function w(e,n,i){let t=new o;return t.onmessage=i,u(`plugin:${e}|register_listener`,{event:n,handler:t}).then((()=>new _(e,n,t.id)))}async function u(e,n={}){return new Promise(((i,t)=>{let l=s((e=>{i(e),Reflect.deleteProperty(window,`_${a}`)}),!0),a=s((e=>{t(e),Reflect.deleteProperty(window,`_${l}`)}),!0);window.__TAURI_IPC__({cmd:e,callback:l,error:a,...n})}))}function c(e,n="asset"){let i=encodeURIComponent(e);return navigator.userAgent.includes("Windows")?`https://${n}.localhost/${i}`:`${n}://localhost/${i}`}async function d(e,n){await u("plugin:event|unlisten",{event:e,eventId:n})}async function h(e,n,i){return u("plugin:event|listen",{event:e,windowLabel:n,handler:s(i)}).then((n=>async()=>d(e,n)))}i({},{TauriEvent:()=>I,emit:()=>E,listen:()=>b,once:()=>g});var p,y,I=((p=I||{}).WINDOW_RESIZED="tauri://resize",p.WINDOW_MOVED="tauri://move",p.WINDOW_CLOSE_REQUESTED="tauri://close-requested",p.WINDOW_CREATED="tauri://window-created",p.WINDOW_DESTROYED="tauri://destroyed",p.WINDOW_FOCUS="tauri://focus",p.WINDOW_BLUR="tauri://blur",p.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",p.WINDOW_THEME_CHANGED="tauri://theme-changed",p.WINDOW_FILE_DROP="tauri://file-drop",p.WINDOW_FILE_DROP_HOVER="tauri://file-drop-hover",p.WINDOW_FILE_DROP_CANCELLED="tauri://file-drop-cancelled",p.MENU="tauri://menu",p);async function b(e,n){return h(e,null,n)}async function g(e,n){return async function(e,n,i){return h(e,n,(n=>{i(n),d(e,n.id).catch((()=>{}))}))}(e,null,n)}async function E(e,n){return async function(e,n,i){await u("plugin:event|emit",{event:e,windowLabel:n,payload:i})}(e,void 0,n)}async function A(e,n){await window.__TAURI_INVOKE__("plugin:event|unlisten",{event:e,eventId:n})}async function O(e,n,i){return window.__TAURI_INVOKE__("plugin:event|listen",{event:e,windowLabel:n,handler:window.__TAURI__.transformCallback(i)}).then((n=>async()=>A(e,n)))}class T{constructor(e,n){this.type="Logical",this.width=e,this.height=n}}class R{constructor(e,n){this.type="Physical",this.width=e,this.height=n}toLogical(e){return new T(this.width/e,this.height/e)}}class v{constructor(e,n){this.type="Logical",this.x=e,this.y=n}}class N{constructor(e,n){this.type="Physical",this.x=e,this.y=n}toLogical(e){return new v(this.x/e,this.y/e)}}function m(){return window.__TAURI_METADATA__.__windows.map((e=>new V(e.label,{skip:!0})))}e.UserAttentionType=void 0,(y=e.UserAttentionType||(e.UserAttentionType={}))[y.Critical=1]="Critical",y[y.Informational=2]="Informational";const U=["tauri://created","tauri://error"];class f{constructor(e){this.label=e,this.listeners=Object.create(null)}async listen(e,n){return this._handleTauriEvent(e,n)?Promise.resolve((()=>{const i=this.listeners[e];i.splice(i.indexOf(n),1)})):O(e,this.label,n)}async once(e,n){return this._handleTauriEvent(e,n)?Promise.resolve((()=>{const i=this.listeners[e];i.splice(i.indexOf(n),1)})):async function(e,n,i){return O(e,n,(n=>{i(n),A(e,n.id).catch((()=>{}))}))}(e,this.label,n)}async emit(e,n){if(U.includes(e)){for(const i of this.listeners[e]||[])i({event:e,id:-1,windowLabel:this.label,payload:n});return Promise.resolve()}return async function(e,n,i){await window.__TAURI_INVOKE__("plugin:event|emit",{event:e,windowLabel:n,payload:i})}(e,this.label,n)}_handleTauriEvent(e,n){return!!U.includes(e)&&(e in this.listeners?this.listeners[e].push(n):this.listeners[e]=[n],!0)}}class W extends f{async scaleFactor(){return window.__TAURI_INVOKE__("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return window.__TAURI_INVOKE__("plugin:window|inner_position",{label:this.label}).then((({x:e,y:n})=>new N(e,n)))}async outerPosition(){return window.__TAURI_INVOKE__("plugin:window|outer_position",{label:this.label}).then((({x:e,y:n})=>new N(e,n)))}async innerSize(){return window.__TAURI_INVOKE__("plugin:window|inner_size",{label:this.label}).then((({width:e,height:n})=>new R(e,n)))}async outerSize(){return window.__TAURI_INVOKE__("plugin:window|outer_size",{label:this.label}).then((({width:e,height:n})=>new R(e,n)))}async isFullscreen(){return window.__TAURI_INVOKE__("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return window.__TAURI_INVOKE__("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return window.__TAURI_INVOKE__("plugin:window|is_maximized",{label:this.label})}async isDecorated(){return window.__TAURI_INVOKE__("plugin:window|is_decorated",{label:this.label})}async isResizable(){return window.__TAURI_INVOKE__("plugin:window|is_resizable",{label:this.label})}async isVisible(){return window.__TAURI_INVOKE__("plugin:window|is_visible",{label:this.label})}async title(){return window.__TAURI_INVOKE__("plugin:window|title",{label:this.label})}async theme(){return window.__TAURI_INVOKE__("plugin:window|theme",{label:this.label})}async center(){return window.__TAURI_INVOKE__("plugin:window|center",{label:this.label})}async requestUserAttention(n){let i=null;return n&&(i=n===e.UserAttentionType.Critical?{type:"Critical"}:{type:"Informational"}),window.__TAURI_INVOKE__("plugin:window|request_user_attention",{label:this.label,value:i})}async setResizable(e){return window.__TAURI_INVOKE__("plugin:window|set_resizable",{label:this.label,value:e})}async setTitle(e){return window.__TAURI_INVOKE__("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return window.__TAURI_INVOKE__("plugin:window|maximize",{label:this.label})}async unmaximize(){return window.__TAURI_INVOKE__("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return window.__TAURI_INVOKE__("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return window.__TAURI_INVOKE__("plugin:window|minimize",{label:this.label})}async unminimize(){return window.__TAURI_INVOKE__("plugin:window|unminimize",{label:this.label})}async show(){return window.__TAURI_INVOKE__("plugin:window|show",{label:this.label})}async hide(){return window.__TAURI_INVOKE__("plugin:window|hide",{label:this.label})}async close(){return window.__TAURI_INVOKE__("plugin:window|close",{label:this.label})}async setDecorations(e){return window.__TAURI_INVOKE__("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return window.__TAURI_INVOKE__("plugin:window|set_shadow",{label:this.label,value:e})}async setAlwaysOnTop(e){return window.__TAURI_INVOKE__("plugin:window|set_always_on_top",{label:this.label,value:e})}async setContentProtected(e){return window.__TAURI_INVOKE__("plugin:window|set_content_protected",{label:this.label,value:e})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return window.__TAURI_INVOKE__("plugin:window|set_size",{label:this.label,value:{type:e.type,data:{width:e.width,height:e.height}}})}async setMinSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return window.__TAURI_INVOKE__("plugin:window|set_min_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setMaxSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return window.__TAURI_INVOKE__("plugin:window|set_max_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return window.__TAURI_INVOKE__("plugin:window|set_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setFullscreen(e){return window.__TAURI_INVOKE__("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return window.__TAURI_INVOKE__("plugin:window|set_focus",{label:this.label})}async setIcon(e){return window.__TAURI_INVOKE__("plugin:window|set_icon",{label:this.label,value:"string"==typeof e?e:Array.from(e)})}async setSkipTaskbar(e){return window.__TAURI_INVOKE__("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return window.__TAURI_INVOKE__("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return window.__TAURI_INVOKE__("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return window.__TAURI_INVOKE__("plugin:window|set_cursor_icon",{label:this.label,value:e})}async setCursorPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return window.__TAURI_INVOKE__("plugin:window|set_cursor_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setIgnoreCursorEvents(e){return window.__TAURI_INVOKE__("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return window.__TAURI_INVOKE__("plugin:window|start_dragging",{label:this.label})}async onResized(e){return this.listen(I.WINDOW_RESIZED,(n=>{n.payload=C(n.payload),e(n)}))}async onMoved(e){return this.listen(I.WINDOW_MOVED,(n=>{n.payload=P(n.payload),e(n)}))}async onCloseRequested(e){return this.listen(I.WINDOW_CLOSE_REQUESTED,(n=>{const i=new D(n);Promise.resolve(e(i)).then((()=>{if(!i.isPreventDefault())return this.close()}))}))}async onFocusChanged(e){const n=await this.listen(I.WINDOW_FOCUS,(n=>{e({...n,payload:!0})})),i=await this.listen(I.WINDOW_BLUR,(n=>{e({...n,payload:!1})}));return()=>{n(),i()}}async onScaleChanged(e){return this.listen(I.WINDOW_SCALE_FACTOR_CHANGED,e)}async onMenuClicked(e){return this.listen(I.MENU,e)}async onFileDropEvent(e){const n=await this.listen(I.WINDOW_FILE_DROP,(n=>{e({...n,payload:{type:"drop",paths:n.payload}})})),i=await this.listen(I.WINDOW_FILE_DROP_HOVER,(n=>{e({...n,payload:{type:"hover",paths:n.payload}})})),t=await this.listen(I.WINDOW_FILE_DROP_CANCELLED,(n=>{e({...n,payload:{type:"cancel"}})}));return()=>{n(),i(),t()}}async onThemeChanged(e){return this.listen(I.WINDOW_THEME_CHANGED,e)}}class D{constructor(e){this._preventDefault=!1,this.event=e.event,this.windowLabel=e.windowLabel,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}class V extends W{constructor(e,n={}){super(e),(null==n?void 0:n.skip)||window.__TAURI_INVOKE__("plugin:window|create",{options:{...n,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){return m().some((n=>n.label===e))?new V(e,{skip:!0}):null}}function K(e){return null===e?null:{name:e.name,scaleFactor:e.scaleFactor,position:P(e.position),size:C(e.size)}}function P(e){return new N(e.x,e.y)}function C(e){return new R(e.width,e.height)}return e.appWindow=void 0,"__TAURI_METADATA__"in window?e.appWindow=new V(window.__TAURI_METADATA__.__currentWindow.label,{skip:!0}):(console.warn('Could not find "window.__TAURI_METADATA__". The "appWindow" value will reference the "main" window label.\nNote that this is not an issue if running this frontend on a browser instead of a Tauri window.'),e.appWindow=new V("main",{skip:!0})),e.CloseRequestedEvent=D,e.LogicalPosition=v,e.LogicalSize=T,e.PhysicalPosition=N,e.PhysicalSize=R,e.WebviewWindow=V,e.WebviewWindowHandle=f,e.WindowManager=W,e.availableMonitors=async function(){return window.__TAURI_INVOKE__("plugin:window|available_monitors").then((e=>e.map(K)))},e.currentMonitor=async function(){return window.__TAURI_INVOKE__("plugin:window|current_monitor").then(K)},e.getAll=m,e.getCurrent=function(){return new V(window.__TAURI_METADATA__.__currentWindow.label,{skip:!0})},e.primaryMonitor=async function(){return window.__TAURI_INVOKE__("plugin:window|primary_monitor").then(K)},e}({});Object.defineProperty(window.__TAURI__,"window",{value:__TAURI_WINDOW__})} diff --git a/plugins/window/src/lib.rs b/plugins/window/src/lib.rs index e1af0ebd..1efeae15 100644 --- a/plugins/window/src/lib.rs +++ b/plugins/window/src/lib.rs @@ -11,18 +11,20 @@ use tauri::{ mod desktop_commands; pub fn init() -> TauriPlugin { - let mut init_js = String::new(); + let mut init_script = String::new(); // window.print works on Linux/Windows; need to use the API on macOS #[cfg(any(target_os = "macos", target_os = "ios"))] { - init_js.push_str(include_str!("./scripts/print.js")); + init_script.push_str(include_str!("./scripts/print.js")); } - init_js.push_str(include_str!("./scripts/drag.js")); + init_script.push_str(include_str!("./scripts/drag.js")); #[cfg(any(debug_assertions, feature = "devtools"))] - init_js.push_str(include_str!("./scripts/toggle-devtools.js")); + init_script.push_str(include_str!("./scripts/toggle-devtools.js")); + + init_script.push_str(include_str!("api-iife.js")); Builder::new("window") - .js_init_script(init_js) + .js_init_script(init_script) .invoke_handler(|invoke| { #[cfg(desktop)] { diff --git a/shared/rollup.config.mjs b/shared/rollup.config.mjs index 0fec516e..95042f8c 100644 --- a/shared/rollup.config.mjs +++ b/shared/rollup.config.mjs @@ -6,7 +6,7 @@ import { builtinModules } from "module"; import typescript from "@rollup/plugin-typescript"; import resolve from "@rollup/plugin-node-resolve"; -// import terser from "@rollup/plugin-terser"; +import terser from "@rollup/plugin-terser"; /** * Create a base rollup config @@ -15,6 +15,10 @@ import resolve from "@rollup/plugin-node-resolve"; * @returns {import('rollup').RollupOptions} */ export function createConfig({ input = "index.ts", pkg, external = [] }) { + const pluginJsName = pkg.name + .replace("@tauri-apps/plugin-", "") + .replace(/-./g, (x) => x[1].toUpperCase()); + const iifeVarName = `__TAURI_${pluginJsName.toUpperCase()}__`; return [ { input, @@ -51,5 +55,28 @@ export function createConfig({ input = "index.ts", pkg, external = [] }) { typescript({ sourceMap: true }), ], }, + { + input, + output: { + file: "src/api-iife.js", + format: "iife", + name: iifeVarName, + // IIFE is in the format `var ${iifeVarName} = (() => {})()` + // we check if __TAURI__ exists and inject the API object + banner: "if ('__TAURI__' in window) {", + // the last `}` closes the if in the banner + footer: `Object.defineProperty(window.__TAURI__, '${pluginJsName}', { value: ${iifeVarName} }) }`, + }, + // and var is not guaranteed to assign to the global `window` object so we make sure to assign it + plugins: [ + resolve(), + typescript({ + sourceMap: false, + declaration: false, + declarationDir: undefined, + }), + terser(), + ], + }, ]; } diff --git a/shared/template/src/lib.rs b/shared/template/src/lib.rs index 77861b7f..3e0f7618 100644 --- a/shared/template/src/lib.rs +++ b/shared/template/src/lib.rs @@ -39,6 +39,7 @@ impl> crate::{{ plugin_name_pascal_case }}Ext for T /// Initializes the plugin. pub fn init() -> TauriPlugin { Builder::new("{{ plugin_name }}") + .js_init_script(include_str!("api-iife.js").to_string()) .invoke_handler(tauri::generate_handler![commands::execute]) .setup(|app, api| { #[cfg(mobile)]