Merge branch 'v2' into feat/notification-mobile

pull/340/head
Lucas Nogueira 2 years ago
commit 6910342d34
No known key found for this signature in database
GPG Key ID: FFEA6C72E73482F1

@ -3,12 +3,12 @@
"pkgManagers": {
"javascript": {
"version": true,
"getPublishedVersion": "pnpm view ${ pkgFile.pkg.name } version",
"getPublishedVersion": "node ../../.scripts/covector/package-latest-version.js npm ${ pkgFile.pkg.name } ${ pkgFile.pkg.version }",
"publish": ["pnpm build", "pnpm publish --access public --no-git-checks"]
},
"rust": {
"version": true,
"getPublishedVersion": "cargo search ${ pkgFile.pkg.package.name } --limit 1 | sed -nE 's/^[^\"]*\"//; s/\".*//1p' -",
"getPublishedVersion": "node ../../.scripts/covector/package-latest-version.js cargo ${ pkgFile.pkg.package.name } ${ pkgFile.pkg.package.version }",
"publish": [
{
"command": "cargo package --no-verify",

@ -1,3 +1,4 @@
target
node_modules
dist
dist-js

@ -6,7 +6,8 @@
"extends": [
"prettier",
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
"plugin:@typescript-eslint/recommended",
"plugin:security/recommended"
],
"overrides": [],
"parser": "@typescript-eslint/parser",

@ -6,14 +6,16 @@ on:
- cron: "0 0 * * *"
push:
branches:
- dev
- v1
- v2
paths:
- ".github/workflows/audit-javascript.yml"
- "**/pnpm-lock.yaml"
- "**/package.json"
pull_request:
branches:
- dev
- v1
- v2
paths:
- ".github/workflows/audit-javascript.yml"
- "**/pnpm-lock.yaml"

@ -6,14 +6,16 @@ on:
- cron: "0 0 * * *"
push:
branches:
- dev
- v1
- v2
paths:
- ".github/workflows/audit-rust.yml"
- "**/Cargo.lock"
- "**/Cargo.toml"
pull_request:
branches:
- dev
- v1
- v2
paths:
- ".github/workflows/audit-rust.yml"
- "**/Cargo.lock"

@ -3,7 +3,7 @@ name: version or publish
on:
push:
branches:
- dev
- v1
jobs:
version-or-publish:

@ -3,7 +3,8 @@ name: Lint JavaScript
on:
push:
branches:
- dev
- v1
- v2
paths:
- ".github/workflows/lint-javascript.yml"
- "plugins/*/guest-js/**"
@ -13,7 +14,8 @@ on:
- "**/package.json"
pull_request:
branches:
- dev
- v1
- v2
paths:
- ".github/workflows/lint-javascript.yml"
- "plugins/*/guest-js/**"

@ -3,14 +3,16 @@ name: Lint Rust
on:
push:
branches:
- dev
- v1
- v2
paths:
- ".github/workflows/lint-rust.yml"
- "plugins/*/src/**"
- "**/Cargo.toml"
pull_request:
branches:
- dev
- v1
- v2
paths:
- ".github/workflows/lint-rust.yml"
- "plugins/*/src/**"
@ -32,7 +34,7 @@ jobs:
- name: install webkit2gtk and libudev for [authenticator]
run: |
sudo apt-get update
sudo apt-get install -y webkit2gtk-4.0 libudev-dev
sudo apt-get install -y libwebkit2gtk-4.0-dev libwebkit2gtk-4.1-dev libudev-dev
- name: Install clippy with stable toolchain
uses: dtolnay/rust-toolchain@stable

@ -3,7 +3,8 @@ name: Check MSRV
on:
push:
branches:
- dev
- v1
- v2
paths:
- ".github/workflows/msrv-check.yml"
- "plugins/*/src/**"
@ -11,7 +12,8 @@ on:
- "**/Cargo.lock"
pull_request:
branches:
- dev
- v1
- v2
paths:
- ".github/workflows/msrv-check.yml"
- "plugins/*/src/**"
@ -34,7 +36,7 @@ jobs:
- name: install webkit2gtk and libudev for [authenticator]
run: |
sudo apt-get update
sudo apt-get install -y webkit2gtk-4.0 libudev-dev
sudo apt-get install -y libwebkit2gtk-4.0-dev libwebkit2gtk-4.1-dev libudev-dev
- uses: dtolnay/rust-toolchain@1.64.0

@ -4,8 +4,8 @@ on:
workflow_dispatch:
push:
branches:
- dev
- next
- v1
- v2
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}

@ -0,0 +1,56 @@
#!/usr/bin/env node
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
/*
This script is solely intended to be run as part of the `covector publish` step to
check the latest version of a crate, considering the current minor version.
*/
const https = require("https");
const kind = process.argv[2];
const packageName = process.argv[3];
const packageVersion = process.argv[4];
const target = packageVersion.substring(0, packageVersion.lastIndexOf("."));
let url = null;
switch (kind) {
case "cargo":
url = `https://crates.io/api/v1/crates/${packageName}`;
break;
case "npm":
url = `https://registry.npmjs.org/${packageName}`;
break;
default:
throw new Error("unexpected kind " + kind);
}
const options = {
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"User-Agent": "tauri (https://github.com/tauri-apps/tauri)",
},
};
https.get(url, options, (response) => {
let chunks = [];
response.on("data", function (chunk) {
chunks.push(chunk);
});
response.on("end", function () {
const data = JSON.parse(chunks.join(""));
if (kind === "cargo") {
const versions = data.versions.filter((v) => v.num.startsWith(target));
console.log(versions.length ? versions[0].num : "0.0.0");
} else if (kind === "npm") {
const versions = Object.keys(data.versions).filter((v) =>
v.startsWith(target)
);
console.log(versions[versions.length - 1] || "0.0.0");
}
});
});

@ -21,6 +21,7 @@
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-n": "^15.7.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-security": "^1.7.1",
"prettier": "^2.8.7",
"rollup": "^3.20.4",
"typescript": "^5.0.4"

@ -20,7 +20,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
[dependencies]
tauri-plugin-authenticator = "0.1"
# or through git
tauri-plugin-authenticator = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-authenticator = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -28,11 +28,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-authenticator#next
pnpm add https://github.com/tauri-apps/tauri-plugin-authenticator#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-authenticator#next
npm add https://github.com/tauri-apps/tauri-plugin-authenticator#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-authenticator#next
yarn add https://github.com/tauri-apps/tauri-plugin-authenticator#v2
```
## Usage
@ -53,7 +53,7 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { Authenticator } from 'tauri-plugin-authenticator-api';
import { Authenticator } from "tauri-plugin-authenticator-api";
const auth = new Authenticator();
auth.init(); // initialize transports
@ -63,16 +63,21 @@ const arr = new Uint32Array(32);
window.crypto.getRandomValues(arr);
const b64 = btoa(String.fromCharCode.apply(null, arr));
// web-safe base64
const challenge = b64.replace(/\+/g, '-').replace(/\//g, '_');
const challenge = b64.replace(/\+/g, "-").replace(/\//g, "_");
const domain = 'https://tauri.app';
const domain = "https://tauri.app";
// attempt to register with the security key
const json = await auth.register(challenge, domain);
const registerResult = JSON.parse(json);
// verify te registration was successfull
const r2 = await auth.verifyRegistration(challenge, app, registerResult.registerData, registerResult.clientData);
const r2 = await auth.verifyRegistration(
challenge,
app,
registerResult.registerData,
registerResult.clientData
);
const j2 = JSON.parse(r2);
// sign some data
@ -80,10 +85,17 @@ const json = await auth.sign(challenge, app, keyHandle);
const signData = JSON.parse(json);
// verify the signature again
const counter = await auth.verifySignature(challenge, app, signData.signData, clientData, keyHandle, pubkey);
const counter = await auth.verifySignature(
challenge,
app,
signData.signData,
clientData,
keyHandle,
pubkey
);
if (counter && counter > 0) {
console.log('SUCCESS!');
console.log("SUCCESS!");
}
```

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-autostart#next
pnpm add https://github.com/tauri-apps/tauri-plugin-autostart#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-autostart#next
npm add https://github.com/tauri-apps/tauri-plugin-autostart#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-autostart#next
yarn add https://github.com/tauri-apps/tauri-plugin-autostart#v2
```
## Usage
@ -53,7 +53,7 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { enable, isEnabled, disable } from 'tauri-plugin-autostart-api';
import { enable, isEnabled, disable } from "tauri-plugin-autostart-api";
await enable();

@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-cli#next
pnpm add https://github.com/tauri-apps/tauri-plugin-cli#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-cli#next
npm add https://github.com/tauri-apps/tauri-plugin-cli#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-cli#next
yarn add https://github.com/tauri-apps/tauri-plugin-cli#v2
```
## Usage

@ -8,7 +8,7 @@
* @module
*/
import { invoke } from '@tauri-apps/api/tauri';
import { invoke } from "@tauri-apps/api/tauri";
/**
* @since 1.0.0
@ -19,27 +19,27 @@ interface ArgMatch {
* boolean if flag
* string[] or null if takes multiple values
*/
value: string | boolean | string[] | null
value: string | boolean | string[] | null;
/**
* Number of occurrences
*/
occurrences: number
occurrences: number;
}
/**
* @since 1.0.0
*/
interface SubcommandMatch {
name: string
matches: CliMatches
name: string;
matches: CliMatches;
}
/**
* @since 1.0.0
*/
interface CliMatches {
args: Record<string, ArgMatch>
subcommand: SubcommandMatch | null
args: Record<string, ArgMatch>;
subcommand: SubcommandMatch | null;
}
/**
@ -64,9 +64,9 @@ interface CliMatches {
* @since 1.0.0
*/
async function getMatches(): Promise<CliMatches> {
return await invoke('plugin:cli|cli_matches');
return await invoke("plugin:cli|cli_matches");
}
export type { ArgMatch, SubcommandMatch, CliMatches }
export type { ArgMatch, SubcommandMatch, CliMatches };
export { getMatches }
export { getMatches };

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-clipboard = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-clipboard = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-clipboard#next
pnpm add https://github.com/tauri-apps/tauri-plugin-clipboard#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-clipboard#next
npm add https://github.com/tauri-apps/tauri-plugin-clipboard#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-clipboard#next
yarn add https://github.com/tauri-apps/tauri-plugin-clipboard#v2
```
## Usage

@ -24,14 +24,14 @@
* @module
*/
import { invoke } from '@tauri-apps/api/tauri'
import { invoke } from "@tauri-apps/api/tauri";
interface Clip<K, T> {
kind: K
options: T
kind: K;
options: T;
}
type ClipResponse = Clip<'PlainText', string>
type ClipResponse = Clip<"PlainText", string>;
/**
* Writes plain text to the clipboard.
@ -46,16 +46,19 @@ type ClipResponse = Clip<'PlainText', string>
*
* @since 1.0.0.
*/
async function writeText(text: string, opts?: { label?: string }): Promise<void> {
return invoke('plugin:clipboard|write', {
async function writeText(
text: string,
opts?: { label?: string }
): Promise<void> {
return invoke("plugin:clipboard|write", {
data: {
kind: 'PlainText',
kind: "PlainText",
options: {
label: opts?.label,
text
}
}
})
text,
},
},
});
}
/**
@ -68,8 +71,8 @@ async function writeText(text: string, opts?: { label?: string }): Promise<void>
* @since 1.0.0.
*/
async function readText(): Promise<string> {
const kind: ClipResponse = await invoke('plugin:clipboard|read')
return kind.options
const kind: ClipResponse = await invoke("plugin:clipboard|read");
return kind.options;
}
export { writeText, readText }
export { writeText, readText };

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-dialog-api = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-dialog-api = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:

@ -4,7 +4,11 @@ import { internalIpV4 } from "internal-ip";
// https://vitejs.dev/config/
export default defineConfig(async () => {
const host = process.env.TAURI_PLATFORM === 'android' || process.env.TAURI_PLATFORM === 'ios' ? (await internalIpV4()) : 'localhost'
const host =
process.env.TAURI_PLATFORM === "android" ||
process.env.TAURI_PLATFORM === "ios"
? await internalIpV4()
: "localhost";
return {
plugins: [svelte()],
@ -13,17 +17,17 @@ export default defineConfig(async () => {
clearScreen: false,
// tauri expects a fixed port, fail if that port is not available
server: {
host: '0.0.0.0',
host: "0.0.0.0",
port: 5173,
strictPort: true,
hmr: {
protocol: 'ws',
protocol: "ws",
host,
port: 5183
port: 5183,
},
fs: {
allow: ['.', '../../tooling/api/dist']
}
allow: [".", "../../tooling/api/dist"],
},
},
// to make use of `TAURI_DEBUG` and other env variables
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
@ -36,5 +40,5 @@ export default defineConfig(async () => {
// produce sourcemaps for debug builds
sourcemap: !!process.env.TAURI_DEBUG,
},
}
};
});

@ -2,18 +2,18 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import { invoke } from '@tauri-apps/api/tauri'
import { invoke } from "@tauri-apps/api/tauri";
interface FileResponse {
base64Data?: string
duration?: number
height?: number
width?: number
mimeType?: string
modifiedAt?: number
name?: string
path: string
size: number
base64Data?: string;
duration?: number;
height?: number;
width?: number;
mimeType?: string;
modifiedAt?: number;
name?: string;
path: string;
size: number;
}
/**
@ -23,7 +23,7 @@ interface FileResponse {
*/
interface DialogFilter {
/** Filter name. */
name: string
name: string;
/**
* Extensions to filter, without a `.` prefix.
* @example
@ -31,7 +31,7 @@ interface DialogFilter {
* extensions: ['svg', 'png']
* ```
*/
extensions: string[]
extensions: string[];
}
/**
@ -41,20 +41,20 @@ interface DialogFilter {
*/
interface OpenDialogOptions {
/** The title of the dialog window. */
title?: string
title?: string;
/** The filters of the dialog. */
filters?: DialogFilter[]
filters?: DialogFilter[];
/** Initial directory or file path. */
defaultPath?: string
defaultPath?: string;
/** Whether the dialog allows multiple selection or not. */
multiple?: boolean
multiple?: boolean;
/** Whether the dialog is a directory selection or not. */
directory?: boolean
directory?: boolean;
/**
* If `directory` is true, indicates that it will be read recursively later.
* Defines whether subdirectories will be allowed on the scope or not.
*/
recursive?: boolean
recursive?: boolean;
}
/**
@ -64,15 +64,15 @@ interface OpenDialogOptions {
*/
interface SaveDialogOptions {
/** The title of the dialog window. */
title?: string
title?: string;
/** The filters of the dialog. */
filters?: DialogFilter[]
filters?: DialogFilter[];
/**
* Initial directory or file path.
* If it's a directory path, the dialog interface will change to that folder.
* If it's not an existing directory, the file name will be set to the dialog's file name input and the dialog will be set to the parent folder.
*/
defaultPath?: string
defaultPath?: string;
}
/**
@ -80,36 +80,36 @@ interface SaveDialogOptions {
*/
interface MessageDialogOptions {
/** The title of the dialog. Defaults to the app name. */
title?: string
title?: string;
/** The type of the dialog. Defaults to `info`. */
type?: 'info' | 'warning' | 'error'
type?: "info" | "warning" | "error";
/** The label of the confirm button. */
okLabel?: string
okLabel?: string;
}
interface ConfirmDialogOptions {
/** The title of the dialog. Defaults to the app name. */
title?: string
title?: string;
/** The type of the dialog. Defaults to `info`. */
type?: 'info' | 'warning' | 'error'
type?: "info" | "warning" | "error";
/** The label of the confirm button. */
okLabel?: string
okLabel?: string;
/** The label of the cancel button. */
cancelLabel?: string
cancelLabel?: string;
}
async function open(
options?: OpenDialogOptions & { multiple?: false, directory?: false }
): Promise<null | FileResponse>
options?: OpenDialogOptions & { multiple?: false; directory?: false }
): Promise<null | FileResponse>;
async function open(
options?: OpenDialogOptions & { multiple?: true, directory?: false }
): Promise<null | FileResponse[]>
options?: OpenDialogOptions & { multiple?: true; directory?: false }
): Promise<null | FileResponse[]>;
async function open(
options?: OpenDialogOptions & { multiple?: false, directory?: true }
): Promise<null | string>
options?: OpenDialogOptions & { multiple?: false; directory?: true }
): Promise<null | string>;
async function open(
options?: OpenDialogOptions & { multiple?: true, directory?: true }
): Promise<null | string[]>
options?: OpenDialogOptions & { multiple?: true; directory?: true }
): Promise<null | string[]>;
/**
* Open a file/directory selection dialog.
*
@ -165,11 +165,11 @@ async function open(
async function open(
options: OpenDialogOptions = {}
): Promise<null | string | string[] | FileResponse | FileResponse[]> {
if (typeof options === 'object') {
Object.freeze(options)
if (typeof options === "object") {
Object.freeze(options);
}
return invoke('plugin:dialog|open', { options })
return invoke("plugin:dialog|open", { options });
}
/**
@ -197,11 +197,11 @@ async function open(
* @since 1.0.0
*/
async function save(options: SaveDialogOptions = {}): Promise<string | null> {
if (typeof options === 'object') {
Object.freeze(options)
if (typeof options === "object") {
Object.freeze(options);
}
return invoke('plugin:dialog|save', { options })
return invoke("plugin:dialog|save", { options });
}
/**
@ -225,13 +225,13 @@ async function message(
message: string,
options?: string | MessageDialogOptions
): Promise<void> {
const opts = typeof options === 'string' ? { title: options } : options
return invoke('plugin:dialog|message', {
const opts = typeof options === "string" ? { title: options } : options;
return invoke("plugin:dialog|message", {
message: message.toString(),
title: opts?.title?.toString(),
type_: opts?.type,
okButtonLabel: opts?.okLabel?.toString()
})
okButtonLabel: opts?.okLabel?.toString(),
});
}
/**
@ -254,14 +254,14 @@ async function ask(
message: string,
options?: string | ConfirmDialogOptions
): Promise<boolean> {
const opts = typeof options === 'string' ? { title: options } : options
return invoke('plugin:dialog|ask', {
const opts = typeof options === "string" ? { title: options } : options;
return invoke("plugin:dialog|ask", {
message: message.toString(),
title: opts?.title?.toString(),
type_: opts?.type,
okButtonLabel: opts?.okLabel?.toString() ?? 'Yes',
cancelButtonLabel: opts?.cancelLabel?.toString() ?? 'No',
})
okButtonLabel: opts?.okLabel?.toString() ?? "Yes",
cancelButtonLabel: opts?.cancelLabel?.toString() ?? "No",
});
}
/**
@ -284,14 +284,14 @@ async function confirm(
message: string,
options?: string | ConfirmDialogOptions
): Promise<boolean> {
const opts = typeof options === 'string' ? { title: options } : options
return invoke('plugin:dialog|confirm', {
const opts = typeof options === "string" ? { title: options } : options;
return invoke("plugin:dialog|confirm", {
message: message.toString(),
title: opts?.title?.toString(),
type_: opts?.type,
okButtonLabel: opts?.okLabel?.toString() ?? 'Ok',
cancelButtonLabel: opts?.cancelLabel?.toString() ?? 'Cancel',
})
okButtonLabel: opts?.okLabel?.toString() ?? "Ok",
cancelButtonLabel: opts?.cancelLabel?.toString() ?? "Cancel",
});
}
export type {
@ -299,7 +299,7 @@ export type {
OpenDialogOptions,
SaveDialogOptions,
MessageDialogOptions,
ConfirmDialogOptions
}
ConfirmDialogOptions,
};
export { open, save, message, ask, confirm }
export { open, save, message, ask, confirm };

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-fs-watch = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-fs-watch = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-fs-watch#next
pnpm add https://github.com/tauri-apps/tauri-plugin-fs-watch#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-fs-watch#next
npm add https://github.com/tauri-apps/tauri-plugin-fs-watch#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-fs-watch#next
yarn add https://github.com/tauri-apps/tauri-plugin-fs-watch#v2
```
## Usage
@ -51,16 +51,24 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { watch, watchImmediate } from 'tauri-plugin-fs-watch-api';
import { watch, watchImmediate } from "tauri-plugin-fs-watch-api";
// can also watch an array of paths
const stopWatching = await watch('/path/to/something', { recursive: true }, (event) => {
const stopWatching = await watch(
"/path/to/something",
(event) => {
const { type, payload } = event;
});
},
{ recursive: true }
);
const stopRawWatcher = await watchImmediate(['/path/a', '/path/b'], {}, (event) => {
const stopRawWatcher = await watchImmediate(
["/path/a", "/path/b"],
(event) => {
const { path, operation, cookie } = event;
});
},
{}
);
```
## Contributing

@ -44,8 +44,8 @@ async function unwatch(id: number): Promise<void> {
export async function watch(
paths: string | string[],
options: DebouncedWatchOptions,
cb: (event: DebouncedEvent) => void
cb: (event: DebouncedEvent) => void,
options: DebouncedWatchOptions = {}
): Promise<UnlistenFn> {
const opts = {
recursive: false,
@ -82,8 +82,8 @@ export async function watch(
export async function watchImmediate(
paths: string | string[],
options: WatchOptions,
cb: (event: RawEvent) => void
cb: (event: RawEvent) => void,
options: WatchOptions = {}
): Promise<UnlistenFn> {
const opts = {
recursive: false,

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-fs = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-fs = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-fs#next
pnpm add https://github.com/tauri-apps/tauri-plugin-fs#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-fs#next
npm add https://github.com/tauri-apps/tauri-plugin-fs#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-fs#next
yarn add https://github.com/tauri-apps/tauri-plugin-fs#v2
```
## Usage
@ -51,9 +51,9 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { metadata } from 'tauri-plugin-fs-api';
import { metadata } from "tauri-plugin-fs-api";
await metadata('/path/to/file');
await metadata("/path/to/file");
```
## Contributing

@ -210,14 +210,14 @@ enum BaseDirectory {
Font,
Home,
Runtime,
Template
Template,
}
/**
* @since 1.0.0
*/
interface FsOptions {
dir?: BaseDirectory
dir?: BaseDirectory;
// note that adding fields here needs a change in the writeBinaryFile check
}
@ -225,8 +225,8 @@ interface FsOptions {
* @since 1.0.0
*/
interface FsDirOptions {
dir?: BaseDirectory
recursive?: boolean
dir?: BaseDirectory;
recursive?: boolean;
}
/**
@ -236,12 +236,12 @@ interface FsDirOptions {
*/
interface FsTextFileOption {
/** Path to the file to write. */
path: string
path: string;
/** The UTF-8 string to write to the file. */
contents: string
contents: string;
}
type BinaryFileContents = Iterable<number> | ArrayLike<number> | ArrayBuffer
type BinaryFileContents = Iterable<number> | ArrayLike<number> | ArrayBuffer;
/**
* Options object used to write a binary data to a file.
@ -250,23 +250,23 @@ type BinaryFileContents = Iterable<number> | ArrayLike<number> | ArrayBuffer
*/
interface FsBinaryFileOption {
/** Path to the file to write. */
path: string
path: string;
/** The byte array contents. */
contents: BinaryFileContents
contents: BinaryFileContents;
}
/**
* @since 1.0.0
*/
interface FileEntry {
path: string
path: string;
/**
* Name of the directory/file
* can be null if the path terminates with `..`
*/
name?: string
name?: string;
/** Children of this entry if it's a directory; null otherwise */
children?: FileEntry[]
children?: FileEntry[];
}
/**
@ -286,8 +286,8 @@ async function readTextFile(
): Promise<string> {
return await invoke("plugin:fs|read_text_file", {
path: filePath,
options
})
options,
});
}
/**
@ -307,10 +307,10 @@ async function readBinaryFile(
): Promise<Uint8Array> {
const arr = await invoke<number[]>("plugin:fs|read_file", {
path: filePath,
options
})
options,
});
return Uint8Array.from(arr)
return Uint8Array.from(arr);
}
/**
@ -328,7 +328,7 @@ async function writeTextFile(
path: string,
contents: string,
options?: FsOptions
): Promise<void>
): Promise<void>;
/**
* Writes a UTF-8 text file.
@ -345,7 +345,7 @@ async function writeTextFile(
async function writeTextFile(
file: FsTextFileOption,
options?: FsOptions
): Promise<void>
): Promise<void>;
/**
* Writes a UTF-8 text file.
@ -359,33 +359,33 @@ async function writeTextFile(
contents?: string | FsOptions,
options?: FsOptions
): Promise<void> {
if (typeof options === 'object') {
Object.freeze(options)
if (typeof options === "object") {
Object.freeze(options);
}
if (typeof path === 'object') {
Object.freeze(path)
if (typeof path === "object") {
Object.freeze(path);
}
const file: FsTextFileOption = { path: '', contents: '' }
let fileOptions: FsOptions | undefined = options
if (typeof path === 'string') {
file.path = path
const file: FsTextFileOption = { path: "", contents: "" };
let fileOptions: FsOptions | undefined = options;
if (typeof path === "string") {
file.path = path;
} else {
file.path = path.path
file.contents = path.contents
file.path = path.path;
file.contents = path.contents;
}
if (typeof contents === 'string') {
file.contents = contents ?? ''
if (typeof contents === "string") {
file.contents = contents ?? "";
} else {
fileOptions = contents
fileOptions = contents;
}
return await invoke("plugin:fs|write_file", {
path: file.path,
contents: Array.from(new TextEncoder().encode(file.contents)),
options: fileOptions
})
options: fileOptions,
});
}
/**
@ -406,7 +406,7 @@ async function writeBinaryFile(
path: string,
contents: BinaryFileContents,
options?: FsOptions
): Promise<void>
): Promise<void>;
/**
* Writes a byte array content to a file.
@ -426,7 +426,7 @@ async function writeBinaryFile(
async function writeBinaryFile(
file: FsBinaryFileOption,
options?: FsOptions
): Promise<void>
): Promise<void>;
/**
* Writes a byte array content to a file.
@ -440,27 +440,27 @@ async function writeBinaryFile(
contents?: BinaryFileContents | FsOptions,
options?: FsOptions
): Promise<void> {
if (typeof options === 'object') {
Object.freeze(options)
if (typeof options === "object") {
Object.freeze(options);
}
if (typeof path === 'object') {
Object.freeze(path)
if (typeof path === "object") {
Object.freeze(path);
}
const file: FsBinaryFileOption = { path: '', contents: [] }
let fileOptions: FsOptions | undefined = options
if (typeof path === 'string') {
file.path = path
const file: FsBinaryFileOption = { path: "", contents: [] };
let fileOptions: FsOptions | undefined = options;
if (typeof path === "string") {
file.path = path;
} else {
file.path = path.path
file.contents = path.contents
file.path = path.path;
file.contents = path.contents;
}
if (contents && 'dir' in contents) {
fileOptions = contents
} else if (typeof path === 'string') {
if (contents && "dir" in contents) {
fileOptions = contents;
} else if (typeof path === "string") {
// @ts-expect-error in this case `contents` is always a BinaryFileContents
file.contents = contents ?? []
file.contents = contents ?? [];
}
return await invoke("plugin:fs|write_binary_file", {
@ -470,8 +470,8 @@ async function writeBinaryFile(
? new Uint8Array(file.contents)
: file.contents
),
options: fileOptions
})
options: fileOptions,
});
}
/**
@ -500,8 +500,8 @@ async function readDir(
): Promise<FileEntry[]> {
return await invoke("plugin:fs|read_dir", {
path: dir,
options
})
options,
});
}
/**
@ -525,8 +525,8 @@ async function createDir(
): Promise<void> {
return await invoke("plugin:fs|create_dir", {
path: dir,
options
})
options,
});
}
/**
@ -549,8 +549,8 @@ async function removeDir(
): Promise<void> {
return await invoke("plugin:fs|remove_dir", {
path: dir,
options
})
options,
});
}
/**
@ -574,8 +574,8 @@ async function copyFile(
return await invoke("plugin:fs|copy_file", {
source,
destination,
options
})
options,
});
}
/**
@ -597,8 +597,8 @@ async function removeFile(
): Promise<void> {
return await invoke("plugin:fs|remove_file", {
path: file,
options
})
options,
});
}
/**
@ -622,9 +622,8 @@ async function renameFile(
return await invoke("plugin:fs|rename_file", {
oldPath,
newPath,
options
})
options,
});
}
/**
@ -670,7 +669,7 @@ export type {
FileEntry,
Permissions,
Metadata,
}
};
export {
BaseDirectory,
@ -687,5 +686,5 @@ export {
removeFile,
renameFile,
exists,
metadata
}
metadata,
};

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-shortcut = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-shortcut = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-shortcut#next
pnpm add https://github.com/tauri-apps/tauri-plugin-shortcut#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-shortcut#next
npm add https://github.com/tauri-apps/tauri-plugin-shortcut#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-shortcut#next
yarn add https://github.com/tauri-apps/tauri-plugin-shortcut#v2
```
## Usage

@ -21,9 +21,9 @@
* @module
*/
import { invoke, transformCallback } from '@tauri-apps/api/tauri'
import { invoke, transformCallback } from "@tauri-apps/api/tauri";
export type ShortcutHandler = (shortcut: string) => void
export type ShortcutHandler = (shortcut: string) => void;
/**
* Register a global shortcut.
@ -44,10 +44,10 @@ async function register(
shortcut: string,
handler: ShortcutHandler
): Promise<void> {
return await invoke('plugin:globalShortcut|register', {
return await invoke("plugin:globalShortcut|register", {
shortcut,
handler: transformCallback(handler)
})
handler: transformCallback(handler),
});
}
/**
@ -69,10 +69,10 @@ async function registerAll(
shortcuts: string[],
handler: ShortcutHandler
): Promise<void> {
return await invoke('plugin:globalShortcut|register_all', {
return await invoke("plugin:globalShortcut|register_all", {
shortcuts,
handler: transformCallback(handler)
})
handler: transformCallback(handler),
});
}
/**
@ -91,9 +91,9 @@ async function registerAll(
* @since 1.0.0
*/
async function isRegistered(shortcut: string): Promise<boolean> {
return await invoke('plugin:globalShortcut|is_registered', {
shortcut
})
return await invoke("plugin:globalShortcut|is_registered", {
shortcut,
});
}
/**
@ -109,9 +109,9 @@ async function isRegistered(shortcut: string): Promise<boolean> {
* @since 1.0.0
*/
async function unregister(shortcut: string): Promise<void> {
return await invoke('plugin:globalShortcut|unregister', {
shortcut
})
return await invoke("plugin:globalShortcut|unregister", {
shortcut,
});
}
/**
@ -125,7 +125,7 @@ async function unregister(shortcut: string): Promise<void> {
* @since 1.0.0
*/
async function unregisterAll(): Promise<void> {
return await invoke('plugin:globalShortcut|unregister_all')
return await invoke("plugin:globalShortcut|unregister_all");
}
export { register, registerAll, isRegistered, unregister, unregisterAll }
export { register, registerAll, isRegistered, unregister, unregisterAll };

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-http = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-http#next
pnpm add https://github.com/tauri-apps/tauri-plugin-http#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-http#next
npm add https://github.com/tauri-apps/tauri-plugin-http#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-http#next
yarn add https://github.com/tauri-apps/tauri-plugin-http#v2
```
## Usage

@ -41,14 +41,14 @@
* @module
*/
import { invoke } from '@tauri-apps/api/tauri'
import { invoke } from "@tauri-apps/api/tauri";
/**
* @since 1.0.0
*/
interface Duration {
secs: number
nanos: number
secs: number;
nanos: number;
}
/**
@ -59,8 +59,8 @@ interface ClientOptions {
* Defines the maximum number of redirects the client should follow.
* If set to 0, no redirects will be followed.
*/
maxRedirections?: number
connectTimeout?: number | Duration
maxRedirections?: number;
connectTimeout?: number | Duration;
}
/**
@ -69,19 +69,19 @@ interface ClientOptions {
enum ResponseType {
JSON = 1,
Text = 2,
Binary = 3
Binary = 3,
}
/**
* @since 1.0.0
*/
interface FilePart<T> {
file: string | T
mime?: string
fileName?: string
file: string | T;
mime?: string;
fileName?: string;
}
type Part = string | Uint8Array | FilePart<Uint8Array>
type Part = string | Uint8Array | FilePart<Uint8Array>;
/**
* The body object to be used on POST and PUT requests.
@ -89,13 +89,13 @@ type Part = string | Uint8Array | FilePart<Uint8Array>
* @since 1.0.0
*/
class Body {
type: string
payload: unknown
type: string;
payload: unknown;
/** @ignore */
private constructor(type: string, payload: unknown) {
this.type = type
this.payload = payload
this.type = type;
this.payload = payload;
}
/**
@ -130,39 +130,39 @@ class Body {
* @returns The body object ready to be used on the POST and PUT requests.
*/
static form(data: Record<string, Part> | FormData): Body {
const form: Record<string, string | number[] | FilePart<number[]>> = {}
const form: Record<string, string | number[] | FilePart<number[]>> = {};
const append = (
key: string,
v: string | Uint8Array | FilePart<Uint8Array> | File
): void => {
if (v !== null) {
let r
if (typeof v === 'string') {
r = v
let r;
if (typeof v === "string") {
r = v;
} else if (v instanceof Uint8Array || Array.isArray(v)) {
r = Array.from(v)
r = Array.from(v);
} else if (v instanceof File) {
r = { file: v.name, mime: v.type, fileName: v.name }
} else if (typeof v.file === 'string') {
r = { file: v.file, mime: v.mime, fileName: v.fileName }
r = { file: v.name, mime: v.type, fileName: v.name };
} else if (typeof v.file === "string") {
r = { file: v.file, mime: v.mime, fileName: v.fileName };
} else {
r = { file: Array.from(v.file), mime: v.mime, fileName: v.fileName }
}
form[String(key)] = r
r = { file: Array.from(v.file), mime: v.mime, fileName: v.fileName };
}
form[String(key)] = r;
}
};
if (data instanceof FormData) {
for (const [key, value] of data) {
append(key, value)
append(key, value);
}
} else {
for (const [key, value] of Object.entries(data)) {
append(key, value)
append(key, value);
}
}
return new Body('Form', form)
return new Body("Form", form);
}
/**
@ -181,7 +181,7 @@ class Body {
* @returns The body object ready to be used on the POST and PUT requests.
*/
static json<K extends string | number | symbol, V>(data: Record<K, V>): Body {
return new Body('Json', data)
return new Body("Json", data);
}
/**
@ -197,7 +197,7 @@ class Body {
* @returns The body object ready to be used on the POST and PUT requests.
*/
static text(value: string): Body {
return new Body('Text', value)
return new Body("Text", value);
}
/**
@ -217,23 +217,23 @@ class Body {
): Body {
// stringifying Uint8Array doesn't return an array of numbers, so we create one here
return new Body(
'Bytes',
"Bytes",
Array.from(bytes instanceof ArrayBuffer ? new Uint8Array(bytes) : bytes)
)
);
}
}
/** The request HTTP verb. */
type HttpVerb =
| 'GET'
| 'POST'
| 'PUT'
| 'DELETE'
| 'PATCH'
| 'HEAD'
| 'OPTIONS'
| 'CONNECT'
| 'TRACE'
| "GET"
| "POST"
| "PUT"
| "DELETE"
| "PATCH"
| "HEAD"
| "OPTIONS"
| "CONNECT"
| "TRACE";
/**
* Options object sent to the backend.
@ -241,27 +241,27 @@ type HttpVerb =
* @since 1.0.0
*/
interface HttpOptions {
method: HttpVerb
url: string
headers?: Record<string, unknown>
query?: Record<string, unknown>
body?: Body
timeout?: number | Duration
responseType?: ResponseType
method: HttpVerb;
url: string;
headers?: Record<string, unknown>;
query?: Record<string, unknown>;
body?: Body;
timeout?: number | Duration;
responseType?: ResponseType;
}
/** Request options. */
type RequestOptions = Omit<HttpOptions, 'method' | 'url'>
type RequestOptions = Omit<HttpOptions, "method" | "url">;
/** Options for the `fetch` API. */
type FetchOptions = Omit<HttpOptions, 'url'>
type FetchOptions = Omit<HttpOptions, "url">;
/** @ignore */
interface IResponse<T> {
url: string
status: number
headers: Record<string, string>
rawHeaders: Record<string, string[]>
data: T
url: string;
status: number;
headers: Record<string, string>;
rawHeaders: Record<string, string[]>;
data: T;
}
/**
@ -271,26 +271,26 @@ interface IResponse<T> {
* */
class Response<T> {
/** The request URL. */
url: string
url: string;
/** The response status code. */
status: number
status: number;
/** A boolean indicating whether the response was successful (status in the range 200299) or not. */
ok: boolean
ok: boolean;
/** The response headers. */
headers: Record<string, string>
headers: Record<string, string>;
/** The response raw headers. */
rawHeaders: Record<string, string[]>
rawHeaders: Record<string, string[]>;
/** The response data. */
data: T
data: T;
/** @ignore */
constructor(response: IResponse<T>) {
this.url = response.url
this.status = response.status
this.ok = this.status >= 200 && this.status < 300
this.headers = response.headers
this.rawHeaders = response.rawHeaders
this.data = response.data
this.url = response.url;
this.status = response.status;
this.ok = this.status >= 200 && this.status < 300;
this.headers = response.headers;
this.rawHeaders = response.rawHeaders;
this.data = response.data;
}
}
@ -298,10 +298,10 @@ class Response<T> {
* @since 1.0.0
*/
class Client {
id: number
id: number;
/** @ignore */
constructor(id: number) {
this.id = id
this.id = id;
}
/**
@ -314,9 +314,9 @@ class Client {
* ```
*/
async drop(): Promise<void> {
return invoke('plugin:http|drop_client', {
client: this.id
})
return invoke("plugin:http|drop_client", {
client: this.id,
});
}
/**
@ -333,34 +333,34 @@ class Client {
*/
async request<T>(options: HttpOptions): Promise<Response<T>> {
const jsonResponse =
!options.responseType || options.responseType === ResponseType.JSON
!options.responseType || options.responseType === ResponseType.JSON;
if (jsonResponse) {
options.responseType = ResponseType.Text
options.responseType = ResponseType.Text;
}
return invoke<IResponse<T>>('plugin:http|request', {
client: this.id,
options
return invoke<IResponse<T>>("plugin:http|request", {
clientId: this.id,
options,
}).then((res) => {
const response = new Response(res)
const response = new Response(res);
if (jsonResponse) {
/* eslint-disable */
try {
response.data = JSON.parse(response.data as string)
response.data = JSON.parse(response.data as string);
} catch (e) {
if (response.ok && (response.data as unknown as string) === '') {
response.data = {} as T
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
return response;
}
return response
})
return response;
});
}
/**
@ -378,10 +378,10 @@ class Client {
*/
async get<T>(url: string, options?: RequestOptions): Promise<Response<T>> {
return this.request({
method: 'GET',
method: "GET",
url,
...options
})
...options,
});
}
/**
@ -406,11 +406,11 @@ class Client {
options?: RequestOptions
): Promise<Response<T>> {
return this.request({
method: 'POST',
method: "POST",
url,
body,
...options
})
...options,
});
}
/**
@ -436,11 +436,11 @@ class Client {
options?: RequestOptions
): Promise<Response<T>> {
return this.request({
method: 'PUT',
method: "PUT",
url,
body,
...options
})
...options,
});
}
/**
@ -456,10 +456,10 @@ class Client {
*/
async patch<T>(url: string, options?: RequestOptions): Promise<Response<T>> {
return this.request({
method: 'PATCH',
method: "PATCH",
url,
...options
})
...options,
});
}
/**
@ -473,10 +473,10 @@ class Client {
*/
async delete<T>(url: string, options?: RequestOptions): Promise<Response<T>> {
return this.request({
method: 'DELETE',
method: "DELETE",
url,
...options
})
...options,
});
}
}
@ -495,13 +495,13 @@ class Client {
* @since 1.0.0
*/
async function getClient(options?: ClientOptions): Promise<Client> {
return invoke<number>('plugin:http|create_client', {
options
}).then((id) => new Client(id))
return invoke<number>("plugin:http|create_client", {
options,
}).then((id) => new Client(id));
}
/** @internal */
let defaultClient: Client | null = null
let defaultClient: Client | null = null;
/**
* Perform an HTTP request using the default client.
@ -519,13 +519,13 @@ async function fetch<T>(
options?: FetchOptions
): Promise<Response<T>> {
if (defaultClient === null) {
defaultClient = await getClient()
defaultClient = await getClient();
}
return defaultClient.request({
url,
method: options?.method ?? 'GET',
...options
})
method: options?.method ?? "GET",
...options,
});
}
export type {
@ -535,7 +535,15 @@ export type {
HttpVerb,
HttpOptions,
RequestOptions,
FetchOptions
}
export { getClient, fetch, Body, Client, Response, ResponseType, type FilePart }
FetchOptions,
};
export {
getClient,
fetch,
Body,
Client,
Response,
ResponseType,
type FilePart,
};

@ -20,7 +20,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-localhost = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-localhost = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
portpicker = "0.1" # used in the example to pick a random free port
```

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-log = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-log = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-log#next
pnpm add https://github.com/tauri-apps/tauri-plugin-log#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-log#next
npm add https://github.com/tauri-apps/tauri-plugin-log#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-log#next
yarn add https://github.com/tauri-apps/tauri-plugin-log#v2
```
## Usage
@ -57,14 +57,14 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { trace, info, error, attachConsole } from 'tauri-plugin-log-api';
import { trace, info, error, attachConsole } from "tauri-plugin-log-api";
// with LogTarget::Webview enabled this function will print logs to the browser console
const detach = await attachConsole();
trace('Trace');
info('Info');
error('Error');
trace("Trace");
info("Info");
error("Error");
// detach the browser console from the log stream
detach();

@ -52,10 +52,15 @@ async function log(
const { file, line, ...keyValues } = options ?? {};
let location = filtered?.[0]?.filter((v) => v.length > 0).join("@");
if (location === "Error") {
location = "webview::unknown";
}
await invoke("plugin:log|log", {
level,
message,
location: filtered?.[0]?.filter((v) => v.length > 0).join("@"),
location,
file,
line,
keyValues,
@ -184,7 +189,8 @@ export async function attachConsole(): Promise<UnlistenFn> {
// Strip ANSI escape codes
const message = payload.message.replace(
// eslint-disable-next-line no-control-regex
// TODO: Investigate security/detect-unsafe-regex
// eslint-disable-next-line no-control-regex, security/detect-unsafe-regex
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
""
);

@ -178,8 +178,8 @@ fn log(
let location = location.unwrap_or("webview");
let mut builder = RecordBuilder::new();
builder
.target(location)
.level(level.into())
.target(location)
.file(file)
.line(line);
@ -251,8 +251,8 @@ impl Builder {
out.finish(format_args!(
"{}[{}][{}] {}",
timezone_strategy.get_now().format(&format).unwrap(),
record.target(),
record.level(),
record.target(),
message
))
});
@ -311,8 +311,8 @@ impl Builder {
out.finish(format_args!(
"{}[{}][{}] {}",
timezone_strategy.get_now().format(&format).unwrap(),
record.target(),
colors.color(record.level()),
record.target(),
message
))
})

@ -298,7 +298,7 @@ interface Channel {
}
/** Possible permission values. */
type Permission = 'granted' | 'denied' | 'default'
type Permission = "granted" | "denied" | "default";
/**
* Checks if the permission to send notifications is granted.
@ -311,10 +311,10 @@ type Permission = 'granted' | 'denied' | 'default'
* @since 1.0.0
*/
async function isPermissionGranted(): Promise<boolean> {
if (window.Notification.permission !== 'default') {
return Promise.resolve(window.Notification.permission === 'granted')
if (window.Notification.permission !== "default") {
return Promise.resolve(window.Notification.permission === "granted");
}
return invoke('plugin:notification|is_permission_granted')
return invoke("plugin:notification|is_permission_granted");
}
/**
@ -334,7 +334,7 @@ async function isPermissionGranted(): Promise<boolean> {
* @since 1.0.0
*/
async function requestPermission(): Promise<Permission> {
return window.Notification.requestPermission()
return window.Notification.requestPermission();
}
/**
@ -356,12 +356,12 @@ async function requestPermission(): Promise<Permission> {
* @since 1.0.0
*/
function sendNotification(options: Options | string): void {
if (typeof options === 'string') {
if (typeof options === "string") {
// eslint-disable-next-line no-new
new window.Notification(options)
new window.Notification(options);
} else {
// eslint-disable-next-line no-new
new window.Notification(options.title, options)
new window.Notification(options.title, options);
}
}

@ -1,71 +1,71 @@
(function () {
let permissionSettable = false
let permissionValue = 'default'
let permissionSettable = false;
let permissionValue = "default";
function isPermissionGranted() {
if (window.Notification.permission !== 'default') {
return Promise.resolve(window.Notification.permission === 'granted')
if (window.Notification.permission !== "default") {
return Promise.resolve(window.Notification.permission === "granted");
}
return __TAURI__.invoke('plugin:notification|is_permission_granted')
return window.__TAURI__.invoke("plugin:notification|is_permission_granted");
}
function setNotificationPermission(value) {
permissionSettable = true
permissionSettable = true;
// @ts-expect-error we can actually set this value on the webview
window.Notification.permission = value
permissionSettable = false
window.Notification.permission = value;
permissionSettable = false;
}
function requestPermission() {
return __TAURI__.invoke('plugin:notification|request_permission')
return window.__TAURI__
.invoke("plugin:notification|request_permission")
.then(function (permission) {
setNotificationPermission(permission)
return permission
})
setNotificationPermission(permission);
return permission;
});
}
function sendNotification(options) {
if (typeof options === 'object') {
Object.freeze(options)
if (typeof options === "object") {
Object.freeze(options);
}
return __TAURI__.invoke('plugin:notification|notify', {
options: typeof options === 'string'
return window.__TAURI__.invoke("plugin:notification|notify", {
options:
typeof options === "string"
? {
title: options
title: options,
}
: options
})
: options,
});
}
// @ts-expect-error unfortunately we can't implement the whole type, so we overwrite it with our own version
window.Notification = function (title, options) {
const opts = options || {}
sendNotification(
Object.assign(opts, { title })
)
}
const opts = options || {};
sendNotification(Object.assign(opts, { title }));
};
window.Notification.requestPermission = requestPermission
window.Notification.requestPermission = requestPermission;
Object.defineProperty(window.Notification, 'permission', {
Object.defineProperty(window.Notification, "permission", {
enumerable: true,
get: function () {
return permissionValue
return permissionValue;
},
set: function (v) {
if (!permissionSettable) {
throw new Error('Readonly property')
}
permissionValue = v
throw new Error("Readonly property");
}
})
permissionValue = v;
},
});
isPermissionGranted().then(function (response) {
if (response === null) {
setNotificationPermission('default')
setNotificationPermission("default");
} else {
setNotificationPermission(response ? 'granted' : 'denied')
setNotificationPermission(response ? "granted" : "denied");
}
})
})()
});
})();

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-persisted-scope = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-persisted-scope = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
## Usage

@ -22,7 +22,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
[dependencies]
tauri-plugin-positioner = "1.0"
# or through git
tauri-plugin-positioner = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-positioner = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -30,21 +30,21 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add tauri-plugin-positioner
pnpm add tauri-plugin-positioner-api
# or
npm add tauri-plugin-positioner
npm add tauri-plugin-positioner-api
# or
yarn add tauri-plugin-positioner
yarn add tauri-plugin-positioner-api
```
Or through git:
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-positioner#next
pnpm add https://github.com/tauri-apps/tauri-plugin-positioner#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-positioner#next
npm add https://github.com/tauri-apps/tauri-plugin-positioner#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-positioner#next
yarn add https://github.com/tauri-apps/tauri-plugin-positioner#v2
```
## Usage
@ -69,7 +69,7 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { move_window, Position } from 'tauri-plugin-positioner-api';
import { move_window, Position } from "tauri-plugin-positioner-api";
move_window(Position.TopRight);
```

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-shell = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-shell = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-shell#next
pnpm add https://github.com/tauri-apps/tauri-plugin-shell#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-shell#next
npm add https://github.com/tauri-apps/tauri-plugin-shell#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-shell#next
yarn add https://github.com/tauri-apps/tauri-plugin-shell#v2
```
## Usage

@ -75,27 +75,27 @@
* @module
*/
import { invoke, transformCallback } from '@tauri-apps/api/tauri'
import { invoke, transformCallback } from "@tauri-apps/api/tauri";
/**
* @since 1.0.0
*/
interface SpawnOptions {
/** Current working directory. */
cwd?: string
cwd?: string;
/** Environment variables. set to `null` to clear the process env. */
env?: Record<string, string>
env?: Record<string, string>;
/**
* Character encoding for stdout/stderr
*
* @since 1.1.0
* */
encoding?: string
encoding?: string;
}
/** @ignore */
interface InternalSpawnOptions extends SpawnOptions {
sidecar?: boolean
sidecar?: boolean;
}
/**
@ -103,13 +103,13 @@ interface InternalSpawnOptions extends SpawnOptions {
*/
interface ChildProcess<O extends IOPayload> {
/** Exit code of the process. `null` if the process was terminated by a signal on Unix. */
code: number | null
code: number | null;
/** If the process was terminated by a signal, represents that signal. */
signal: number | null
signal: number | null;
/** The data that the process wrote to `stdout`. */
stdout: O
stdout: O;
/** The data that the process wrote to `stderr`. */
stderr: O
stderr: O;
}
/**
@ -128,26 +128,27 @@ async function execute<O extends IOPayload>(
args: string | string[] = [],
options?: InternalSpawnOptions
): Promise<number> {
if (typeof args === 'object') {
Object.freeze(args)
if (typeof args === "object") {
Object.freeze(args);
}
return invoke<number>('plugin:shell|execute', {
return invoke<number>("plugin:shell|execute", {
program,
args,
options,
onEventFn: transformCallback(onEvent)
})
onEventFn: transformCallback(onEvent),
});
}
/**
* @since 1.0.0
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
class EventEmitter<E extends Record<string, any>> {
/** @ignore */
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
private eventListeners: Record<keyof E, Array<(arg: any) => void>> =
Object.create(null)
Object.create(null);
/**
* Alias for `emitter.on(eventName, listener)`.
@ -158,7 +159,7 @@ class EventEmitter<E extends Record<string, any>> {
eventName: N,
listener: (arg: E[typeof eventName]) => void
): this {
return this.on(eventName, listener)
return this.on(eventName, listener);
}
/**
@ -170,7 +171,7 @@ class EventEmitter<E extends Record<string, any>> {
eventName: N,
listener: (arg: E[typeof eventName]) => void
): this {
return this.off(eventName, listener)
return this.off(eventName, listener);
}
/**
@ -189,12 +190,12 @@ class EventEmitter<E extends Record<string, any>> {
): this {
if (eventName in this.eventListeners) {
// eslint-disable-next-line security/detect-object-injection
this.eventListeners[eventName].push(listener)
this.eventListeners[eventName].push(listener);
} else {
// eslint-disable-next-line security/detect-object-injection
this.eventListeners[eventName] = [listener]
this.eventListeners[eventName] = [listener];
}
return this
return this;
}
/**
@ -210,11 +211,11 @@ class EventEmitter<E extends Record<string, any>> {
listener: (arg: E[typeof eventName]) => void
): this {
const wrapper = (arg: E[typeof eventName]): void => {
this.removeListener(eventName, wrapper)
this.removeListener(eventName, wrapper);
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
listener(arg)
}
return this.addListener(eventName, wrapper)
listener(arg);
};
return this.addListener(eventName, wrapper);
}
/**
@ -231,9 +232,9 @@ class EventEmitter<E extends Record<string, any>> {
// eslint-disable-next-line security/detect-object-injection
this.eventListeners[eventName] = this.eventListeners[eventName].filter(
(l) => l !== listener
)
);
}
return this
return this;
}
/**
@ -246,12 +247,12 @@ class EventEmitter<E extends Record<string, any>> {
removeAllListeners<N extends keyof E>(event?: N): this {
if (event) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete,security/detect-object-injection
delete this.eventListeners[event]
delete this.eventListeners[event];
} else {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
this.eventListeners = Object.create(null)
this.eventListeners = Object.create(null);
}
return this
return this;
}
/**
@ -264,12 +265,12 @@ class EventEmitter<E extends Record<string, any>> {
emit<N extends keyof E>(eventName: N, arg: E[typeof eventName]): boolean {
if (eventName in this.eventListeners) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,security/detect-object-injection
const listeners = this.eventListeners[eventName]
const listeners = this.eventListeners[eventName];
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
for (const listener of listeners) listener(arg)
return true
for (const listener of listeners) listener(arg);
return true;
}
return false
return false;
}
/**
@ -280,8 +281,8 @@ class EventEmitter<E extends Record<string, any>> {
listenerCount<N extends keyof E>(eventName: N): number {
if (eventName in this.eventListeners)
// eslint-disable-next-line security/detect-object-injection
return this.eventListeners[eventName].length
return 0
return this.eventListeners[eventName].length;
return 0;
}
/**
@ -300,12 +301,12 @@ class EventEmitter<E extends Record<string, any>> {
): this {
if (eventName in this.eventListeners) {
// eslint-disable-next-line security/detect-object-injection
this.eventListeners[eventName].unshift(listener)
this.eventListeners[eventName].unshift(listener);
} else {
// eslint-disable-next-line security/detect-object-injection
this.eventListeners[eventName] = [listener]
this.eventListeners[eventName] = [listener];
}
return this
return this;
}
/**
@ -320,12 +321,13 @@ class EventEmitter<E extends Record<string, any>> {
eventName: N,
listener: (arg: E[typeof eventName]) => void
): this {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const wrapper = (arg: any): void => {
this.removeListener(eventName, wrapper)
this.removeListener(eventName, wrapper);
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
listener(arg)
}
return this.prependListener(eventName, wrapper)
listener(arg);
};
return this.prependListener(eventName, wrapper);
}
}
@ -334,10 +336,10 @@ class EventEmitter<E extends Record<string, any>> {
*/
class Child {
/** The child process `pid`. */
pid: number
pid: number;
constructor(pid: number) {
this.pid = pid
this.pid = pid;
}
/**
@ -356,11 +358,11 @@ class Child {
* @returns A promise indicating the success or failure of the operation.
*/
async write(data: IOPayload): Promise<void> {
return invoke('plugin:shell|stdin_write', {
return invoke("plugin:shell|stdin_write", {
pid: this.pid,
// correctly serialize Uint8Arrays
buffer: typeof data === 'string' ? data : Array.from(data)
})
buffer: typeof data === "string" ? data : Array.from(data),
});
}
/**
@ -369,20 +371,20 @@ class Child {
* @returns A promise indicating the success or failure of the operation.
*/
async kill(): Promise<void> {
return invoke('plugin:shell|kill', {
cmd: 'killChild',
pid: this.pid
})
return invoke("plugin:shell|kill", {
cmd: "killChild",
pid: this.pid,
});
}
}
interface CommandEvents {
close: TerminatedPayload
error: string
close: TerminatedPayload;
error: string;
}
interface OutputEvents<O extends IOPayload> {
data: O
data: O;
}
/**
@ -408,15 +410,15 @@ interface OutputEvents<O extends IOPayload> {
*/
class Command<O extends IOPayload> extends EventEmitter<CommandEvents> {
/** @ignore Program to execute. */
private readonly program: string
private readonly program: string;
/** @ignore Program arguments */
private readonly args: string[]
private readonly args: string[];
/** @ignore Spawn options. */
private readonly options: InternalSpawnOptions
private readonly options: InternalSpawnOptions;
/** Event emitter for the `stdout`. Emits the `data` event. */
readonly stdout = new EventEmitter<OutputEvents<O>>()
readonly stdout = new EventEmitter<OutputEvents<O>>();
/** Event emitter for the `stderr`. Emits the `data` event. */
readonly stderr = new EventEmitter<OutputEvents<O>>()
readonly stderr = new EventEmitter<OutputEvents<O>>();
/**
* @ignore
@ -432,23 +434,23 @@ class Command<O extends IOPayload> extends EventEmitter<CommandEvents> {
args: string | string[] = [],
options?: SpawnOptions
) {
super()
this.program = program
this.args = typeof args === 'string' ? [args] : args
this.options = options ?? {}
super();
this.program = program;
this.args = typeof args === "string" ? [args] : args;
this.options = options ?? {};
}
static create(program: string, args?: string | string[]): Command<string>
static create(program: string, args?: string | string[]): Command<string>;
static create(
program: string,
args?: string | string[],
options?: SpawnOptions & { encoding: 'raw' }
): Command<Uint8Array>
options?: SpawnOptions & { encoding: "raw" }
): Command<Uint8Array>;
static create(
program: string,
args?: string | string[],
options?: SpawnOptions
): Command<string>
): Command<string>;
/**
* Creates a command to execute the given program.
@ -467,20 +469,20 @@ class Command<O extends IOPayload> extends EventEmitter<CommandEvents> {
args: string | string[] = [],
options?: SpawnOptions
): Command<O> {
return new Command(program, args, options)
return new Command(program, args, options);
}
static sidecar(program: string, args?: string | string[]): Command<string>
static sidecar(program: string, args?: string | string[]): Command<string>;
static sidecar(
program: string,
args?: string | string[],
options?: SpawnOptions & { encoding: 'raw' }
): Command<Uint8Array>
options?: SpawnOptions & { encoding: "raw" }
): Command<Uint8Array>;
static sidecar(
program: string,
args?: string | string[],
options?: SpawnOptions
): Command<string>
): Command<string>;
/**
* Creates a command to execute the given sidecar program.
@ -499,9 +501,9 @@ class Command<O extends IOPayload> extends EventEmitter<CommandEvents> {
args: string | string[] = [],
options?: SpawnOptions
): Command<O> {
const instance = new Command<O>(program, args, options)
instance.options.sidecar = true
return instance
const instance = new Command<O>(program, args, options);
instance.options.sidecar = true;
return instance;
}
/**
@ -513,24 +515,24 @@ class Command<O extends IOPayload> extends EventEmitter<CommandEvents> {
return execute<O>(
(event) => {
switch (event.event) {
case 'Error':
this.emit('error', event.payload)
break
case 'Terminated':
this.emit('close', event.payload)
break
case 'Stdout':
this.stdout.emit('data', event.payload)
break
case 'Stderr':
this.stderr.emit('data', event.payload)
break
case "Error":
this.emit("error", event.payload);
break;
case "Terminated":
this.emit("close", event.payload);
break;
case "Stdout":
this.stdout.emit("data", event.payload);
break;
case "Stderr":
this.stderr.emit("data", event.payload);
break;
}
},
this.program,
this.args,
this.options
).then((pid) => new Child(pid))
).then((pid) => new Child(pid));
}
/**
@ -549,38 +551,38 @@ class Command<O extends IOPayload> extends EventEmitter<CommandEvents> {
*/
async execute(): Promise<ChildProcess<O>> {
return new Promise((resolve, reject) => {
this.on('error', reject)
const stdout: O[] = []
const stderr: O[] = []
this.stdout.on('data', (line: O) => {
stdout.push(line)
})
this.stderr.on('data', (line: O) => {
stderr.push(line)
})
this.on('close', (payload: TerminatedPayload) => {
this.on("error", reject);
const stdout: O[] = [];
const stderr: O[] = [];
this.stdout.on("data", (line: O) => {
stdout.push(line);
});
this.stderr.on("data", (line: O) => {
stderr.push(line);
});
this.on("close", (payload: TerminatedPayload) => {
resolve({
code: payload.code,
signal: payload.signal,
stdout: this.collectOutput(stdout) as O,
stderr: this.collectOutput(stderr) as O
})
})
stderr: this.collectOutput(stderr) as O,
});
});
this.spawn().catch(reject)
})
this.spawn().catch(reject);
});
}
/** @ignore */
private collectOutput(events: O[]): string | Uint8Array {
if (this.options.encoding === 'raw') {
if (this.options.encoding === "raw") {
return events.reduce<Uint8Array>((p, c) => {
return new Uint8Array([...p, ...(c as Uint8Array), 10])
}, new Uint8Array())
return new Uint8Array([...p, ...(c as Uint8Array), 10]);
}, new Uint8Array());
} else {
return events.join('\n')
return events.join("\n");
}
}
}
@ -589,8 +591,8 @@ class Command<O extends IOPayload> extends EventEmitter<CommandEvents> {
* Describes the event message received from the command.
*/
interface Event<T, V> {
event: T
payload: V
event: T;
payload: V;
}
/**
@ -598,20 +600,20 @@ interface Event<T, V> {
*/
interface TerminatedPayload {
/** Exit code of the process. `null` if the process was terminated by a signal on Unix. */
code: number | null
code: number | null;
/** If the process was terminated by a signal, represents that signal. */
signal: number | null
signal: number | null;
}
/** Event payload type */
type IOPayload = string | Uint8Array
type IOPayload = string | Uint8Array;
/** Events emitted by the child process. */
type CommandEvent<O extends IOPayload> =
| Event<'Stdout', O>
| Event<'Stderr', O>
| Event<'Terminated', TerminatedPayload>
| Event<'Error', string>
| Event<"Stdout", O>
| Event<"Stderr", O>
| Event<"Terminated", TerminatedPayload>
| Event<"Error", string>;
/**
* Opens a path or URL with the system's default app,
@ -640,18 +642,18 @@ type CommandEvent<O extends IOPayload> =
* @since 1.0.0
*/
async function open(path: string, openWith?: string): Promise<void> {
return invoke('plugin:shell|open', {
return invoke("plugin:shell|open", {
path,
with: openWith
})
with: openWith,
});
}
export { Command, Child, EventEmitter, open }
export { Command, Child, EventEmitter, open };
export type {
IOPayload,
CommandEvents,
TerminatedPayload,
OutputEvents,
ChildProcess,
SpawnOptions
}
SpawnOptions,
};

@ -480,7 +480,7 @@ mod tests {
#[test]
fn test_cmd_output_output() {
let cmd = Command::new("cat").args(["test/api/test.txt"]);
let output = cmd.output().unwrap();
let output = tauri::async_runtime::block_on(cmd.output()).unwrap();
assert_eq!(String::from_utf8(output.stderr).unwrap(), "");
assert_eq!(
@ -493,7 +493,7 @@ mod tests {
#[test]
fn test_cmd_output_output_fail() {
let cmd = Command::new("cat").args(["test/api/"]);
let output = cmd.output().unwrap();
let output = tauri::async_runtime::block_on(cmd.output()).unwrap();
assert_eq!(String::from_utf8(output.stdout).unwrap(), "");
assert_eq!(

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
## Usage

@ -19,7 +19,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies.tauri-plugin-sql]
git = "https://github.com/tauri-apps/plugins-workspace"
branch = "next"
branch = "v2"
features = ["sqlite"] # or "postgres", or "mysql"
```
@ -28,11 +28,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-sql#next
pnpm add https://github.com/tauri-apps/tauri-plugin-sql#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-sql#next
npm add https://github.com/tauri-apps/tauri-plugin-sql#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-sql#next
yarn add https://github.com/tauri-apps/tauri-plugin-sql#v2
```
## Usage
@ -53,16 +53,16 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import Database from 'tauri-plugin-sql-api';
import Database from "tauri-plugin-sql-api";
// sqlite. The path is relative to `tauri::api::path::BaseDirectory::App`.
const db = await Database.load('sqlite:test.db');
const db = await Database.load("sqlite:test.db");
// mysql
const db = await Database.load('mysql://user:pass@host/database');
const db = await Database.load("mysql://user:pass@host/database");
// postgres
const db = await Database.load('postgres://postgres:password@localhost/test');
const db = await Database.load("postgres://postgres:password@localhost/test");
await db.execute('INSERT INTO ...');
await db.execute("INSERT INTO ...");
```
## Contributing

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-store#next
pnpm add https://github.com/tauri-apps/tauri-plugin-store#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-store#next
npm add https://github.com/tauri-apps/tauri-plugin-store#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-store#next
yarn add https://github.com/tauri-apps/tauri-plugin-store#v2
```
## Usage
@ -51,13 +51,13 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { Store } from 'tauri-plugin-store-api';
import { Store } from "tauri-plugin-store-api";
const store = new Store('.settings.dat');
const store = new Store(".settings.dat");
await store.set('some-key', { value: 5 });
await store.set("some-key", { value: 5 });
const val = await store.get('some-key');
const val = await store.get("some-key");
assert(val, { value: 5 });
await store.save(); // this manually saves the store, otherwise the store is only saved when your app is closed

@ -175,8 +175,9 @@ pub struct Store<R: Runtime> {
impl<R: Runtime> Store<R> {
/// Update the store from the on-disk state
pub fn load<R: Runtime>(&mut self, app: &AppHandle<R>) -> Result<(), Error> {
let app_dir = app
pub fn load(&mut self) -> Result<(), Error> {
let app_dir = self
.app
.path()
.app_data_dir()
.expect("failed to resolve app dir");
@ -191,8 +192,9 @@ impl<R: Runtime> Store<R> {
}
/// Saves the store to disk
pub fn save<R: Runtime>(&self, app: &AppHandle<R>) -> Result<(), Error> {
let app_dir = app
pub fn save(&self) -> Result<(), Error> {
let app_dir = self
.app
.path()
.app_data_dir()
.expect("failed to resolve app dir");

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-stronghold = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-stronghold = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-stronghold#next
pnpm add https://github.com/tauri-apps/tauri-plugin-stronghold#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-stronghold#next
npm add https://github.com/tauri-apps/tauri-plugin-stronghold#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-stronghold#next
yarn add https://github.com/tauri-apps/tauri-plugin-stronghold#v2
```
## Usage
@ -55,7 +55,7 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { Stronghold, Location } from 'tauri-plugin-stronghold-api';
import { Stronghold, Location } from "tauri-plugin-stronghold-api";
// TODO
```

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-upload = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-upload = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-upload#next
pnpm add https://github.com/tauri-apps/tauri-plugin-upload#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-upload#next
npm add https://github.com/tauri-apps/tauri-plugin-upload#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-upload#next
yarn add https://github.com/tauri-apps/tauri-plugin-upload#v2
```
## Usage

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-websocket = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-websocket = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-websocket#next
pnpm add https://github.com/tauri-apps/tauri-plugin-websocket#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-websocket#next
npm add https://github.com/tauri-apps/tauri-plugin-websocket#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-websocket#next
yarn add https://github.com/tauri-apps/tauri-plugin-websocket#v2
```
## Usage
@ -51,11 +51,11 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { WebSocket } from 'tauri-plugin-websocket-api';
import { WebSocket } from "tauri-plugin-websocket-api";
const ws = await WebSocket.connect('wss://example.com');
const ws = await WebSocket.connect("wss://example.com");
await ws.send('Hello World');
await ws.send("Hello World");
await ws.disconnect();
```

@ -79,15 +79,14 @@ enum WebSocketMessage {
}
#[tauri::command]
fn connect<R: Runtime>(
async fn connect<R: Runtime>(
window: Window<R>,
url: String,
callback_function: CallbackFn,
config: Option<ConnectionConfig>,
) -> Result<Id> {
let id = rand::random();
let (ws_stream, _) =
tauri::async_runtime::block_on(connect_async_with_config(url, config.map(Into::into)))?;
let (ws_stream, _) = connect_async_with_config(url, config.map(Into::into)).await?;
tauri::async_runtime::spawn(async move {
let (write, read) = ws_stream.split();

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "next" }
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
@ -26,11 +26,11 @@ You can install the JavaScript Guest bindings using your preferred JavaScript pa
> Note: Since most JavaScript package managers are unable to install packages from git monorepos we provide read-only mirrors of each plugin. This makes installation option 2 more ergonomic to use.
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-window-state#next
pnpm add https://github.com/tauri-apps/tauri-plugin-window-state#v2
# or
npm add https://github.com/tauri-apps/tauri-plugin-window-state#next
npm add https://github.com/tauri-apps/tauri-plugin-window-state#v2
# or
yarn add https://github.com/tauri-apps/tauri-plugin-window-state#next
yarn add https://github.com/tauri-apps/tauri-plugin-window-state#v2
```
## Usage
@ -62,7 +62,7 @@ app.save_window_state(StateFlags::all()); // will save the state of all open win
or through Javascript
```javascript
import { saveWindowState, StateFlags } from 'tauri-plugin-window-state-api';
import { saveWindowState, StateFlags } from "tauri-plugin-window-state-api";
saveWindowState(StateFlags.ALL);
```
@ -79,7 +79,7 @@ window.restore_state(StateFlags::all()); // will restore the windows state from
or through Javascript
```javascript
import { restoreStateCurrent, StateFlags } from 'tauri-plugin-window-state-api';
import { restoreStateCurrent, StateFlags } from "tauri-plugin-window-state-api";
restoreStateCurrent(StateFlags.ALL);
```

@ -37,6 +37,9 @@ importers:
eslint-plugin-promise:
specifier: ^6.1.1
version: 6.1.1(eslint@8.39.0)
eslint-plugin-security:
specifier: ^1.7.1
version: 1.7.1
prettier:
specifier: ^2.8.7
version: 2.8.8
@ -1758,6 +1761,12 @@ packages:
eslint: 8.39.0
dev: true
/eslint-plugin-security@1.7.1:
resolution: {integrity: sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==}
dependencies:
safe-regex: 2.1.1
dev: true
/eslint-scope@5.1.1:
resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
engines: {node: '>=8.0.0'}
@ -2686,6 +2695,11 @@ packages:
picomatch: 2.3.1
dev: true
/regexp-tree@0.1.27:
resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==}
hasBin: true
dev: true
/regexp.prototype.flags@1.4.3:
resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==}
engines: {node: '>= 0.4'}
@ -2774,6 +2788,12 @@ packages:
is-regex: 1.1.4
dev: true
/safe-regex@2.1.1:
resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==}
dependencies:
regexp-tree: 0.1.27
dev: true
/sander@0.5.1:
resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==}
dependencies:

@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
<!-- plugin here --> = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
<!-- plugin here --> = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:

Loading…
Cancel
Save