Merge branch 'dev' into monitor-data

pull/48/head
amrbashir 3 years ago
commit adfb011a94
No known key found for this signature in database
GPG Key ID: BBD7A47A2003FF33

@ -0,0 +1,5 @@
# Order is important; the last matching pattern takes the most precedence.
* @tauri-apps/plugin-maintainers
# Currently CI/CD for plugins are in heavy flux, and the plugin team manages it themselves.
# .github @tauri-apps/wg-devops

@ -93,12 +93,12 @@ while read -r PLUGIN_NAME; do
echo "Failed to find a branch to branch from, just creating an empty one." echo "Failed to find a branch to branch from, just creating an empty one."
FORCE_COMMIT=--allow-empty FORCE_COMMIT=--allow-empty
fi fi
git add -Af git add -A
echo "::endgroup::" echo "::endgroup::"
if [[ -n "$FORCE_COMMIT" || -n "$(git status --porcelain)" ]]; then if [[ -n "$FORCE_COMMIT" || -n "$(git status --porcelain)" ]]; then
echo "Committing to $PLUGIN_NAME" echo "Committing to $PLUGIN_NAME"
if git commit --quiet $FORCE_COMMIT --author="${COMMIT_ORIGINAL_AUTHOR}" -m "${COMMIT_MESSAGE}" && if git commit $FORCE_COMMIT --author="${COMMIT_ORIGINAL_AUTHOR}" -m "${COMMIT_MESSAGE}" &&
{ [[ -z "$CI" ]] || git push origin "$BRANCH"; } # Only do the actual push from the GitHub Action { [[ -z "$CI" ]] || git push origin "$BRANCH"; } # Only do the actual push from the GitHub Action
then then
# echo "$BUILD_BASE/changes.diff" # echo "$BUILD_BASE/changes.diff"

@ -6,14 +6,14 @@ on:
- dev - dev
paths: paths:
- ".github/workflows/lint-rust.yml" - ".github/workflows/lint-rust.yml"
- "plugins/src/**" - "plugins/*/src/**"
- "**/Cargo.toml" - "**/Cargo.toml"
pull_request: pull_request:
branches: branches:
- dev - dev
paths: paths:
- ".github/workflows/lint-rust.yml" - ".github/workflows/lint-rust.yml"
- "plugins/src/**" - "plugins/*/src/**"
- "**/Cargo.toml" - "**/Cargo.toml"
concurrency: concurrency:
@ -28,42 +28,30 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: install webkit2gtk
- name: install webkit2gtk and libudev for [authenticator]
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y webkit2gtk-4.0 sudo apt-get install -y webkit2gtk-4.0 libudev-dev
- name: install libudev for [authenticator]
run: |
sudo apt-get install -y libudev-dev
- name: Install clippy with stable toolchain - name: Install clippy with stable toolchain
uses: actions-rs/toolchain@v1 uses: dtolnay/rust-toolchain@stable
with: with:
profile: minimal
toolchain: stable
override: true
components: clippy components: clippy
- uses: Swatinem/rust-cache@v1
- uses: actions-rs/clippy-check@v1 - uses: Swatinem/rust-cache@v2
with:
token: ${{ secrets.GITHUB_TOKEN }} - name: clippy
args: --workspace --exclude 'tauri-plugin-sql' --all-targets --all-features -- -D warnings run: cargo clippy --workspace --exclude 'tauri-plugin-sql' --all-targets --all-features -- -D warnings
name: clippy
- uses: actions-rs/clippy-check@v1 - name: clippy sql:sqlite
with: run: cargo clippy --package 'tauri-plugin-sql' --all-targets --features sqlite -- -D warnings
token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --package 'tauri-plugin-sql' --all-targets --features sqlite -- -D warnings - name: clippy sql:mysql
name: clippy sql:sqlite run: cargo clippy --package 'tauri-plugin-sql' --all-targets --features mysql -- -D warnings
- uses: actions-rs/clippy-check@v1
with: - name: clippy sql:postgres
token: ${{ secrets.GITHUB_TOKEN }} run: cargo clippy --package 'tauri-plugin-sql' --all-targets --features postgres -- -D warnings
args: --workspace --package 'tauri-plugin-sql' --all-targets --features mysql -- -D warnings
name: clippy sql:mysql
- uses: actions-rs/clippy-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --workspace --package 'tauri-plugin-sql' --all-targets --features postgres -- -D warnings
name: clippy sql:postgres
fmt: fmt:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -72,14 +60,11 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install rustfmt with nightly toolchain - name: Install rustfmt with nightly toolchain
uses: actions-rs/toolchain@v1 uses: dtolnay/rust-toolchain@nightly
with: with:
profile: minimal
toolchain: nightly
override: true
components: rustfmt components: rustfmt
- uses: actions-rs/cargo@v1
with: - name: Check formatting
command: fmt run: cargo fmt --all -- --check
args: --all -- --check

@ -33,5 +33,5 @@ jobs:
- name: Sync - name: Sync
run: .github/sync-to-mirrors.sh run: .github/sync-to-mirrors.sh
env: env:
BUILD_BASE: ./plugins BUILD_BASE: ${{ github.workspace }}/plugins
API_TOKEN_GITHUB: ${{ secrets.ORG_TAURI_BOT_PAT }} API_TOKEN_GITHUB: ${{ secrets.ORG_TAURI_BOT_PAT }}

@ -1,3 +1,5 @@
target target
node_modules node_modules
dist dist
pnpm-lock.yaml
Cargo.lock

42
Cargo.lock generated

@ -157,12 +157,12 @@ dependencies = [
[[package]] [[package]]
name = "auto-launch" name = "auto-launch"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "642d13324da4df30a472026356a7fd24845d4a8038e5c47ed99c62074b526fa5" checksum = "5904a4d734f0235edf29aab320a14899f3e090446e594ff96508a6215f76f89c"
dependencies = [ dependencies = [
"anyhow",
"dirs", "dirs",
"thiserror",
"winreg", "winreg",
] ]
@ -2540,9 +2540,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.16.0" version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]] [[package]]
name = "opaque-debug" name = "opaque-debug"
@ -3527,17 +3527,6 @@ dependencies = [
"stable_deref_trait", "stable_deref_trait",
] ]
[[package]]
name = "sha-1"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
dependencies = [
"cfg-if 1.0.0",
"cpufeatures 0.2.5",
"digest 0.10.6",
]
[[package]] [[package]]
name = "sha1" name = "sha1"
version = "0.10.5" version = "0.10.5"
@ -4467,15 +4456,14 @@ dependencies = [
[[package]] [[package]]
name = "tiny_http" name = "tiny_http"
version = "0.11.0" version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0d6ef4e10d23c1efb862eecad25c5054429a71958b4eeef85eb5e7170b477ca" checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82"
dependencies = [ dependencies = [
"ascii", "ascii",
"chunked_transfer", "chunked_transfer",
"httpdate",
"log", "log",
"time 0.3.17",
"url",
] ]
[[package]] [[package]]
@ -4495,9 +4483,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.23.0" version = "1.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46" checksum = "1d9f76183f91ecfb55e1d7d5602bd1d979e38a3a522fe900241cf195624d67ae"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"bytes 1.3.0", "bytes 1.3.0",
@ -4544,9 +4532,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-tungstenite" name = "tokio-tungstenite"
version = "0.17.2" version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"log", "log",
@ -4664,9 +4652,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]] [[package]]
name = "tungstenite" name = "tungstenite"
version = "0.17.3" version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
dependencies = [ dependencies = [
"base64 0.13.1", "base64 0.13.1",
"byteorder", "byteorder",
@ -4676,7 +4664,7 @@ dependencies = [
"log", "log",
"native-tls", "native-tls",
"rand 0.8.5", "rand 0.8.5",
"sha-1", "sha1",
"thiserror", "thiserror",
"url", "url",
"utf-8", "utf-8",

@ -12,4 +12,5 @@ thiserror = "1"
[workspace.package] [workspace.package]
edition = "2021" edition = "2021"
authors = [ "Tauri Programme within The Commons Conservancy" ] authors = [ "Tauri Programme within The Commons Conservancy" ]
license = "Apache-2.0 OR MIT" license = "Apache-2.0 OR MIT"
rust-version = "1.59"

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-authenticator" name = "tauri-plugin-authenticator"
version = "0.1.0" version = "0.1.0"
edition.workspace = true description = "Use hardware security-keys in your Tauri App."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -14,7 +16,7 @@ tauri.workspace = true
log.workspace = true log.workspace = true
thiserror.workspace = true thiserror.workspace = true
authenticator = "0.3.1" authenticator = "0.3.1"
once_cell = "1.9" once_cell = "1"
sha2 = "0.10" sha2 = "0.10"
base64 = { version = "^0.13" } base64 = { version = "^0.13" }
u2f = "0.2" u2f = "0.2"

@ -1,17 +1,100 @@
![plugin-authenticator](banner.png) ![plugin-authenticator](banner.png)
<!-- description --> Use hardware security-keys in your Tauri App.
## Install ## Install
There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-authenticator = "0.1"
# or through git
tauri-plugin-authenticator = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
``` ```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> 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
# or
npm add https://github.com/tauri-apps/tauri-plugin-authenticator
# or
yarn add https://github.com/tauri-apps/tauri-plugin-authenticator
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_authenticator::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { Authenticator } from "tauri-plugin-authenticator-api";
const auth = new Authenticator();
auth.init(); // initialize transports
// generate a 32-bytes long random challenge
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 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 j2 = JSON.parse(r2);
// sign some data
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
);
if (counter && counter > 0) {
console.log("SUCCESS!");
}
``` ```
## Contributing ## Contributing
@ -20,6 +103,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -2,7 +2,7 @@ import { invoke } from "@tauri-apps/api/tauri";
export class Authenticator { export class Authenticator {
async init(): Promise<void> { async init(): Promise<void> {
return await invoke("plugin:authenticator|init"); return await invoke("plugin:authenticator|init_auth");
} }
async register(challenge: string, application: string): Promise<string> { async register(challenge: string, application: string): Promise<string> {

@ -1,6 +1,7 @@
{ {
"name": "tauri-plugin-authenticator-api", "name": "tauri-plugin-authenticator-api",
"version": "0.0.0", "version": "0.0.0",
"description": "Use hardware security-keys in your Tauri App.",
"license": "MIT or APACHE-2.0", "license": "MIT or APACHE-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"

@ -75,8 +75,8 @@ pub fn register(application: String, timeout: u64, challenge: String) -> crate::
let (key_handle, public_key) = let (key_handle, public_key) =
_u2f_get_key_handle_and_public_key_from_register_response(&register_data).unwrap(); _u2f_get_key_handle_and_public_key_from_register_response(&register_data).unwrap();
let key_handle_base64 = encode_config(&key_handle, URL_SAFE_NO_PAD); let key_handle_base64 = encode_config(key_handle, URL_SAFE_NO_PAD);
let public_key_base64 = encode_config(&public_key, URL_SAFE_NO_PAD); let public_key_base64 = encode_config(public_key, URL_SAFE_NO_PAD);
let register_data_base64 = encode_config(&register_data, URL_SAFE_NO_PAD); let register_data_base64 = encode_config(&register_data, URL_SAFE_NO_PAD);
println!("Key Handle: {}", &key_handle_base64); println!("Key Handle: {}", &key_handle_base64);
println!("Public Key: {}", &public_key_base64); println!("Public Key: {}", &public_key_base64);
@ -108,7 +108,7 @@ pub fn sign(
challenge: String, challenge: String,
key_handle: String, key_handle: String,
) -> crate::Result<String> { ) -> crate::Result<String> {
let credential = match decode_config(&key_handle, URL_SAFE_NO_PAD) { let credential = match decode_config(key_handle, URL_SAFE_NO_PAD) {
Ok(v) => v, Ok(v) => v,
Err(e) => { Err(e) => {
return Err(e.into()); return Err(e.into());
@ -152,7 +152,7 @@ pub fn sign(
let (_, handle_used, sign_data, device_info) = sign_result.unwrap(); let (_, handle_used, sign_data, device_info) = sign_result.unwrap();
let sig = encode_config(&sign_data, URL_SAFE_NO_PAD); let sig = encode_config(sign_data, URL_SAFE_NO_PAD);
println!("Sign result: {}", sig); println!("Sign result: {}", sig);
println!( println!(

@ -6,13 +6,16 @@ mod auth;
mod error; mod error;
mod u2f; mod u2f;
use tauri::{plugin::Plugin, Invoke, Runtime}; use tauri::{
plugin::{Builder as PluginBuilder, TauriPlugin},
Runtime,
};
pub use error::Error; pub use error::Error;
type Result<T> = std::result::Result<T, Error>; type Result<T> = std::result::Result<T, Error>;
#[tauri::command] #[tauri::command]
fn init() { fn init_auth() {
auth::init_usb(); auth::init_usb();
} }
@ -60,30 +63,14 @@ fn verify_signature(
) )
} }
pub struct TauriAuthenticator<R: Runtime> { pub fn init<R: Runtime>() -> TauriPlugin<R> {
invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync>, PluginBuilder::new("authenticator")
} .invoke_handler(tauri::generate_handler![
init_auth,
impl<R: Runtime> Default for TauriAuthenticator<R> { register,
fn default() -> Self { verify_registration,
Self { sign,
invoke_handler: Box::new(tauri::generate_handler![ verify_signature
init, ])
register, .build()
verify_registration,
sign,
verify_signature
]),
}
}
}
impl<R: Runtime> Plugin<R> for TauriAuthenticator<R> {
fn name(&self) -> &'static str {
"authenticator"
}
fn extend_api(&mut self, invoke: Invoke<R>) {
(self.invoke_handler)(invoke)
}
} }

@ -15,7 +15,7 @@ static VERSION: &str = "U2F_V2";
pub fn make_challenge(app_id: &str, challenge_bytes: Vec<u8>) -> Challenge { pub fn make_challenge(app_id: &str, challenge_bytes: Vec<u8>) -> Challenge {
let utc: DateTime<Utc> = Utc::now(); let utc: DateTime<Utc> = Utc::now();
Challenge { Challenge {
challenge: encode_config(&challenge_bytes, URL_SAFE_NO_PAD), challenge: encode_config(challenge_bytes, URL_SAFE_NO_PAD),
timestamp: format!("{:?}", utc), timestamp: format!("{:?}", utc),
app_id: app_id.to_string(), app_id: app_id.to_string(),
} }
@ -35,10 +35,10 @@ pub fn verify_registration(
register_data: String, register_data: String,
client_data: String, client_data: String,
) -> crate::Result<String> { ) -> crate::Result<String> {
let challenge_bytes = decode_config(&challenge, URL_SAFE_NO_PAD)?; let challenge_bytes = decode_config(challenge, URL_SAFE_NO_PAD)?;
let challenge = make_challenge(&app_id, challenge_bytes); let challenge = make_challenge(&app_id, challenge_bytes);
let client_data_bytes: Vec<u8> = client_data.as_bytes().into(); let client_data_bytes: Vec<u8> = client_data.as_bytes().into();
let client_data_base64 = encode_config(&client_data_bytes, URL_SAFE_NO_PAD); let client_data_base64 = encode_config(client_data_bytes, URL_SAFE_NO_PAD);
let client = U2f::new(app_id); let client = U2f::new(app_id);
match client.register_response( match client.register_response(
challenge, challenge,
@ -74,12 +74,12 @@ pub fn verify_signature(
key_handle: String, key_handle: String,
pub_key: String, pub_key: String,
) -> crate::Result<u32> { ) -> crate::Result<u32> {
let challenge_bytes = decode_config(&challenge, URL_SAFE_NO_PAD)?; let challenge_bytes = decode_config(challenge, URL_SAFE_NO_PAD)?;
let chal = make_challenge(&app_id, challenge_bytes); let chal = make_challenge(&app_id, challenge_bytes);
let client_data_bytes: Vec<u8> = client_data.as_bytes().into(); let client_data_bytes: Vec<u8> = client_data.as_bytes().into();
let client_data_base64 = encode_config(&client_data_bytes, URL_SAFE_NO_PAD); let client_data_base64 = encode_config(client_data_bytes, URL_SAFE_NO_PAD);
let key_handle_bytes = decode_config(&key_handle, URL_SAFE_NO_PAD)?; let key_handle_bytes = decode_config(&key_handle, URL_SAFE_NO_PAD)?;
let pubkey_bytes = decode_config(&pub_key, URL_SAFE_NO_PAD)?; let pubkey_bytes = decode_config(pub_key, URL_SAFE_NO_PAD)?;
let client = U2f::new(app_id); let client = U2f::new(app_id);
let mut _counter: u32 = 0; let mut _counter: u32 = 0;
match client.sign_response( match client.sign_response(

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-autostart" name = "tauri-plugin-autostart"
version = "0.1.0" version = "0.1.0"
edition.workspace = true description = "Automatically launch your application at startup."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -13,4 +15,4 @@ serde_json.workspace = true
tauri.workspace = true tauri.workspace = true
log.workspace = true log.workspace = true
thiserror.workspace = true thiserror.workspace = true
auto-launch = "0.3" auto-launch = "0.4"

@ -1,17 +1,61 @@
![plugin-autostart](banner.png) ![plugin-autostart](banner.png)
<!-- description --> Automatically launch your application at startup. Supports Windows, Mac (via AppleScript or Launch Agent), and Linux.
## Install ## Install
There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
``` ```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> 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
# or
npm add https://github.com/tauri-apps/tauri-plugin-autostart
# or
yarn add https://github.com/tauri-apps/tauri-plugin-autostart
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_autostart::init(MacosLauncher::LaunchAgent, Some(vec!["--flag1", "--flag2"]) /* arbitrary number of args to pass to your app */))
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { enable, isEnabled, disable } from "tauri-plugin-autostart-api";
await enable();
console.log(`registered for autostart? ${await isEnabled()}`);
disable();
``` ```
## Contributing ## Contributing
@ -20,6 +64,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-fs-extra" name = "tauri-plugin-fs-extra"
version = "0.1.0" version = "0.1.0"
edition.workspace = true description = "Additional file system methods not included in the core API."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -1,17 +1,57 @@
![plugin-fs-extra](banner.png) ![tauri-plugin-fs-extra](banner.png)
<!-- description --> Additional file system methods not included in the core API.
## Install ## Install
There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
``` ```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> 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-extra
# or
npm add https://github.com/tauri-apps/tauri-plugin-fs-extra
# or
yarn add https://github.com/tauri-apps/tauri-plugin-fs-extra
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_fs_extra::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { metadata } from "tauri-plugin-fs-extra-api";
await metadata("/path/to/file");
``` ```
## Contributing ## Contributing
@ -20,6 +60,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -1,6 +1,7 @@
{ {
"name": "tauri-plugin-fs-extra-api", "name": "tauri-plugin-fs-extra-api",
"version": "0.0.0", "version": "0.0.0",
"description": "Additional file system methods not included in the core API.",
"license": "MIT or APACHE-2.0", "license": "MIT or APACHE-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"

@ -3,7 +3,11 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
use serde::{ser::Serializer, Serialize}; use serde::{ser::Serializer, Serialize};
use tauri::{command, plugin::Plugin, Invoke, Runtime}; use tauri::{
command,
plugin::{Builder as PluginBuilder, TauriPlugin},
Runtime,
};
use std::{ use std::{
path::PathBuf, path::PathBuf,
@ -121,25 +125,8 @@ async fn exists(path: PathBuf) -> bool {
path.exists() path.exists()
} }
/// Tauri plugin. pub fn init<R: Runtime>() -> TauriPlugin<R> {
pub struct FsExtra<R: Runtime> { PluginBuilder::new("fs-extra")
invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync>, .invoke_handler(tauri::generate_handler![exists, metadata])
} .build()
impl<R: Runtime> Default for FsExtra<R> {
fn default() -> Self {
Self {
invoke_handler: Box::new(tauri::generate_handler![exists, metadata]),
}
}
}
impl<R: Runtime> Plugin<R> for FsExtra<R> {
fn name(&self) -> &'static str {
"fs-extra"
}
fn extend_api(&mut self, message: Invoke<R>) {
(self.invoke_handler)(message)
}
} }

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-fs-watch" name = "tauri-plugin-fs-watch"
version = "0.1.0" version = "0.1.0"
edition.workspace = true description = "Watch files and directories for changes."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -1,17 +1,72 @@
![plugin-fs-watch](banner.png) ![plugin-fs-watch](banner.png)
<!-- description --> Watch files and directories for changes using [notify](https://github.com/notify-rs/notify).
## Install ## Install
There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-fs-watch = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
``` ```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> 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
# or
npm add https://github.com/tauri-apps/tauri-plugin-fs-watch
# or
yarn add https://github.com/tauri-apps/tauri-plugin-fs-watch
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_fs_watch::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
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 { type, payload } = event;
}
);
const stopRawWatcher = await watchImmediate(
["/path/a", "/path/b"],
{},
(event) => {
const { path, operation, cookie } = event;
}
);
``` ```
## Contributing ## Contributing
@ -20,6 +75,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -1,6 +1,7 @@
{ {
"name": "tauri-plugin-fs-watch-api", "name": "tauri-plugin-fs-watch-api",
"version": "0.0.0", "version": "0.0.0",
"description": "Watch files and directories for changes.",
"license": "MIT or APACHE-2.0", "license": "MIT or APACHE-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"

@ -3,8 +3,11 @@ use notify::{
Watcher as _, Watcher as _,
}; };
use serde::{ser::Serializer, Deserialize, Serialize}; use serde::{ser::Serializer, Deserialize, Serialize};
use serde_json::Value as JsonValue; use tauri::{
use tauri::{command, plugin::Plugin, AppHandle, Invoke, Manager, Runtime, State, Window}; command,
plugin::{Builder as PluginBuilder, TauriPlugin},
Manager, Runtime, State, Window,
};
use std::{ use std::{
collections::HashMap, collections::HashMap,
@ -160,30 +163,12 @@ async fn unwatch(watchers: State<'_, WatcherCollection>, id: Id) -> Result<()> {
Ok(()) Ok(())
} }
/// Tauri plugin. pub fn init<R: Runtime>() -> TauriPlugin<R> {
pub struct Watcher<R: Runtime> { PluginBuilder::new("fs-watch")
invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync>, .invoke_handler(tauri::generate_handler![watch, unwatch])
} .setup(|app| {
app.manage(WatcherCollection::default());
impl<R: Runtime> Default for Watcher<R> { Ok(())
fn default() -> Self { })
Self { .build()
invoke_handler: Box::new(tauri::generate_handler![watch, unwatch]),
}
}
}
impl<R: Runtime> Plugin<R> for Watcher<R> {
fn name(&self) -> &'static str {
"fs-watch"
}
fn initialize(&mut self, app: &AppHandle<R>, _config: JsonValue) -> tauri::plugin::Result<()> {
app.manage(WatcherCollection::default());
Ok(())
}
fn extend_api(&mut self, message: Invoke<R>) {
(self.invoke_handler)(message)
}
} }

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-localhost" name = "tauri-plugin-localhost"
version = "0.1.0" version = "0.1.0"
edition.workspace = true description = "Expose your apps assets through a localhost server instead of the default custom protocol."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -13,5 +15,5 @@ serde_json.workspace = true
tauri.workspace = true tauri.workspace = true
log.workspace = true log.workspace = true
thiserror.workspace = true thiserror.workspace = true
tiny_http = "0.11" tiny_http = "0.12"
http = "0.2" http = "0.2"

@ -1,17 +1,57 @@
![plugin-localhost](banner.png) ![plugin-localhost](banner.png)
<!-- description --> Expose your apps assets through a localhost server instead of the default custom protocol.
> Note: This plugins brings considerable security risks and you should only use it if you know what your are doing. If in doubt, use the default custom protocol implementation.
## Install ## Install
``` There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-localhost = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
portpicker = "0.1" # used in the example to pick a random free port
``` ```
## Usage ## Usage
``` First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
use tauri::{utils::config::AppUrl, window::WindowBuilder, WindowUrl};
fn main() {
let port = portpicker::pick_unused_port().expect("failed to find unused port");
let mut context = tauri::generate_context!();
let url = format!("http://localhost:{}", port).parse().unwrap();
let window_url = WindowUrl::External(url);
// rewrite the config so the IPC is enabled on this URL
context.config_mut().build.dist_dir = AppUrl::Url(window_url.clone());
context.config_mut().build.dev_path = AppUrl::Url(window_url.clone());
tauri::Builder::default()
.plugin(tauri_plugin_localhost::Builder::new(port).build())
.setup(move |app| {
WindowBuilder::new(app, "main".to_string(), window_url)
.title("Localhost Example")
.build()?;
Ok(())
})
.run(context)
.expect("error while running tauri application");
}
``` ```
## Contributing ## Contributing
@ -20,6 +60,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-log" name = "tauri-plugin-log"
version = "0.1.0" version = "0.1.0"
edition.workspace = true description = "Configurable logging for your Tauri app."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -1,25 +1,88 @@
![plugin-log](banner.png) ![plugin-log](banner.png)
<!-- description --> Configurable logging for your Tauri app.
## Install ## Install
There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-log = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
``` ```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> 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
# or
npm add https://github.com/tauri-apps/tauri-plugin-log
# or
yarn add https://github.com/tauri-apps/tauri-plugin-log
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
use tauri_plugin_log::{LogTarget};
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_log::Builder::default().targets([
LogTarget::LogDir,
LogTarget::Stdout,
LogTarget::Webview,
]).build())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
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");
// detach the browser console from the log stream
detach();
``` ```
To log from rust code, add the log crate to your `Cargo.toml`:
```toml
[dependencies]
log = "^0.4"
```
Now, you can use the macros provided by the log crate to log messages from your backend. See the [docs](https://docs.rs/log/latest) for more details.
## Contributing ## Contributing
PRs accepted. Please make sure to read the Contributing Guide before making a pull request. PRs accepted. Please make sure to read the Contributing Guide before making a pull request.
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -1,6 +1,7 @@
{ {
"name": "tauri-plugin-log-api", "name": "tauri-plugin-log-api",
"version": "0.0.0", "version": "0.0.0",
"description": "Configurable logging for your Tauri app.",
"license": "MIT or APACHE-2.0", "license": "MIT or APACHE-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"

@ -142,14 +142,14 @@ fn log(
logger().log(&builder.args(format_args!("{message}")).build()); logger().log(&builder.args(format_args!("{message}")).build());
} }
pub struct LoggerBuilder { pub struct Builder {
dispatch: fern::Dispatch, dispatch: fern::Dispatch,
rotation_strategy: RotationStrategy, rotation_strategy: RotationStrategy,
max_file_size: u128, max_file_size: u128,
targets: Vec<LogTarget>, targets: Vec<LogTarget>,
} }
impl Default for LoggerBuilder { impl Default for Builder {
fn default() -> Self { fn default() -> Self {
let format = let format =
time::format_description::parse("[[[year]-[month]-[day]][[[hour]:[minute]:[second]]") time::format_description::parse("[[[year]-[month]-[day]][[[hour]:[minute]:[second]]")
@ -172,7 +172,7 @@ impl Default for LoggerBuilder {
} }
} }
impl LoggerBuilder { impl Builder {
pub fn new() -> Self { pub fn new() -> Self {
Default::default() Default::default()
} }

@ -1 +1,14 @@
authenticator
autostart
fs-extra
fs-watch
localhost
log
persisted-scope
positioner
sql
store
stronghold
upload
websocket websocket
window-state

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-persisted-scope" name = "tauri-plugin-persisted-scope"
version = "0.1.0" version = "0.1.0"
edition.workspace = true description = "Save filesystem and asset scopes and restore them when the app is reopened."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -1,25 +1,47 @@
![plugin-persisted-scope](banner.png) ![plugin-persisted-scope](banner.png)
<!-- description --> Save filesystem and asset scopes and restore them when the app is reopened.
## Install ## Install
``` There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-persisted-scope = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
``` ```
## Usage ## Usage
``` First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_persisted_scope::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards the plugin will automatically save and restore filesystem and asset scopes.
## Contributing ## Contributing
PRs accepted. Please make sure to read the Contributing Guide before making a pull request. PRs accepted. Please make sure to read the Contributing Guide before making a pull request.
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -54,15 +54,15 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
.map_err(Error::from) .map_err(Error::from)
.and_then(|scope| bincode::deserialize(&scope).map_err(Into::into)) .and_then(|scope| bincode::deserialize(&scope).map_err(Into::into))
.unwrap_or_default(); .unwrap_or_default();
for allowed in scope.allowed_paths { for allowed in &scope.allowed_paths {
// allows the path as is // allows the path as is
let _ = fs_scope.allow_file(&allowed); let _ = fs_scope.allow_file(allowed);
#[cfg(feature = "protocol-asset")] #[cfg(feature = "protocol-asset")]
let _ = asset_protocol_scope.allow_file(allowed); let _ = asset_protocol_scope.allow_file(allowed);
} }
for forbidden in scope.forbidden_patterns { for forbidden in &scope.forbidden_patterns {
// forbid the path as is // forbid the path as is
let _ = fs_scope.forbid_file(&forbidden); let _ = fs_scope.forbid_file(forbidden);
#[cfg(feature = "protocol-asset")] #[cfg(feature = "protocol-asset")]
let _ = asset_protocol_scope.forbid_file(forbidden); let _ = asset_protocol_scope.forbid_file(forbidden);
} }

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-positioner" name = "tauri-plugin-positioner"
version = "0.2.7" version = "0.2.7"
edition.workspace = true description = "Position your windows at well-known locations."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -1,17 +1,84 @@
![plugin-positioner](banner.png) ![plugin-positioner](banner.png)
<!-- description --> Position your windows at well-known locations.
This plugin is a port of [electron-positioner](https://github.com/jenslind/electron-positioner) for Tauri.
## Install ## Install
There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-positioner = "1.0"
# or through git
tauri-plugin-positioner = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> 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
# or
npm add tauri-plugin-positioner
# or
yarn add tauri-plugin-positioner
``` ```
Or through git:
```sh
pnpm add https://github.com/tauri-apps/tauri-plugin-positioner
# or
npm add https://github.com/tauri-apps/tauri-plugin-positioner
# or
yarn add https://github.com/tauri-apps/tauri-plugin-positioner
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_positioner::init())
// This is required to get tray-relative positions to work
.on_system_tray_event(|app, event| {
tauri_plugin_positioner::on_tray_event(app, &event);
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { move_window, Position } from "tauri-plugin-positioner-api";
move_window(Position.TopRight);
```
If you only intend on moving the window from rust code, you can import the Window trait extension instead of registering the plugin:
```rust
use tauri_plugin_positioner::{WindowExt, Position};
let mut win = app.get_window("main").unwrap();
let _ = win.move_window(Position::TopRight);
``` ```
## Contributing ## Contributing
@ -20,6 +87,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2021 - Jonas Kruckenberg. 2021 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -1,6 +1,7 @@
{ {
"name": "tauri-plugin-positioner-api", "name": "tauri-plugin-positioner-api",
"version": "0.0.0", "version": "0.0.0",
"description": "Position your windows at well-known locations.",
"license": "MIT or APACHE-2.0", "license": "MIT or APACHE-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-sql" name = "tauri-plugin-sql"
version = "0.1.0" version = "0.1.0"
edition.workspace = true description = "Interface with SQL databases."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -1,17 +1,66 @@
![plugin-sql](banner.png) ![plugin-sql](banner.png)
<!-- description --> Interface with SQL databases through [sqlx](https://github.com/launchbadge/sqlx). It supports the `sqlite`, `mysql` and `postgres` drivers, enabled by a Cargo feature.
## Install ## Install
There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies.tauri-plugin-sql]
git = "https://github.com/tauri-apps/plugins-workspace"
branch = "dev"
features = ["sqlite"] # or "postgres", or "mysql"
``` ```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> 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
# or
npm add https://github.com/tauri-apps/tauri-plugin-sql
# or
yarn add https://github.com/tauri-apps/tauri-plugin-sql
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_sql::Builder::default())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
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");
// mysql
const db = await Database.load("mysql://user:pass@host/database");
// postgres
const db = await Database.load("postgres://postgres:password@localhost/test");
await db.execute("INSERT INTO ...");
``` ```
## Contributing ## Contributing
@ -20,6 +69,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -1,6 +1,7 @@
{ {
"name": "tauri-plugin-sql-api", "name": "tauri-plugin-sql-api",
"version": "0.0.0", "version": "0.0.0",
"description": "Interface with SQL databases",
"license": "MIT or APACHE-2.0", "license": "MIT or APACHE-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"

@ -14,8 +14,8 @@ use sqlx::{
}; };
use tauri::{ use tauri::{
command, command,
plugin::{Plugin, Result as PluginResult}, plugin::{Builder as PluginBuilder, TauriPlugin},
AppHandle, Invoke, Manager, RunEvent, Runtime, State, AppHandle, Manager, RunEvent, Runtime, State,
}; };
use tokio::sync::Mutex; use tokio::sync::Mutex;
@ -92,7 +92,7 @@ struct DbInstances(Mutex<HashMap<String, Pool<Db>>>);
struct Migrations(Mutex<HashMap<String, MigrationList>>); struct Migrations(Mutex<HashMap<String, MigrationList>>);
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
struct PluginConfig { pub struct PluginConfig {
#[serde(default)] #[serde(default)]
preload: Vec<String>, preload: Vec<String>,
} }
@ -300,88 +300,69 @@ async fn select(
Ok(values) Ok(values)
} }
/// Tauri SQL plugin. /// Tauri SQL plugin builder.
pub struct TauriSql<R: Runtime> { pub struct Builder {
migrations: Option<HashMap<String, MigrationList>>, migrations: Option<HashMap<String, MigrationList>>,
invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync>,
} }
impl<R: Runtime> Default for TauriSql<R> { impl Builder {
fn default() -> Self {
Self {
migrations: Some(Default::default()),
invoke_handler: Box::new(tauri::generate_handler![load, execute, select, close]),
}
}
}
impl<R: Runtime> TauriSql<R> {
/// Add migrations to a database. /// Add migrations to a database.
#[must_use] #[must_use]
pub fn add_migrations(mut self, db_url: &str, migrations: Vec<Migration>) -> Self { pub fn add_migrations(mut self, db_url: &str, migrations: Vec<Migration>) -> Self {
self.migrations self.migrations
.as_mut() .get_or_insert(Default::default())
.unwrap()
.insert(db_url.to_string(), MigrationList(migrations)); .insert(db_url.to_string(), MigrationList(migrations));
self self
} }
}
impl<R: Runtime> Plugin<R> for TauriSql<R> {
fn name(&self) -> &'static str {
"sql"
}
fn initialize(&mut self, app: &AppHandle<R>, config: serde_json::Value) -> PluginResult<()> {
tauri::async_runtime::block_on(async move {
let config: PluginConfig = if config.is_null() {
Default::default()
} else {
serde_json::from_value(config)?
};
#[cfg(feature = "sqlite")] pub fn build<R: Runtime>(mut self) -> TauriPlugin<R, Option<PluginConfig>> {
create_dir_all(app_path(app)).expect("problems creating App directory!"); PluginBuilder::new("sql")
.invoke_handler(tauri::generate_handler![load, execute, select, close])
.setup_with_config(|app, config: Option<PluginConfig>| {
let config = config.unwrap_or_default();
let instances = DbInstances::default();
let mut lock = instances.0.lock().await;
for db in config.preload {
#[cfg(feature = "sqlite")] #[cfg(feature = "sqlite")]
let fqdb = path_mapper(app_path(app), &db); create_dir_all(app_path(app)).expect("problems creating App directory!");
#[cfg(not(feature = "sqlite"))]
let fqdb = db.clone(); tauri::async_runtime::block_on(async move {
let instances = DbInstances::default();
if !Db::database_exists(&fqdb).await.unwrap_or(false) { let mut lock = instances.0.lock().await;
Db::create_database(&fqdb).await?; for db in config.preload {
} #[cfg(feature = "sqlite")]
let pool = Pool::connect(&fqdb).await?; let fqdb = path_mapper(app_path(app), &db);
#[cfg(not(feature = "sqlite"))]
if let Some(migrations) = self.migrations.as_mut().unwrap().remove(&db) { let fqdb = db.clone();
let migrator = Migrator::new(migrations).await?;
migrator.run(&pool).await?; if !Db::database_exists(&fqdb).await.unwrap_or(false) {
} Db::create_database(&fqdb).await?;
lock.insert(db, pool); }
} let pool = Pool::connect(&fqdb).await?;
drop(lock);
app.manage(instances);
app.manage(Migrations(Mutex::new(self.migrations.take().unwrap())));
Ok(())
})
}
fn extend_api(&mut self, message: Invoke<R>) {
(self.invoke_handler)(message)
}
fn on_event(&mut self, app: &AppHandle<R>, event: &RunEvent) { if let Some(migrations) = self.migrations.as_mut().unwrap().remove(&db) {
if let RunEvent::Exit = event { let migrator = Migrator::new(migrations).await?;
tauri::async_runtime::block_on(async move { migrator.run(&pool).await?;
let instances = &*app.state::<DbInstances>(); }
let instances = instances.0.lock().await; lock.insert(db, pool);
for value in instances.values() { }
value.close().await; drop(lock);
app.manage(instances);
app.manage(Migrations(Mutex::new(self.migrations.take().unwrap())));
Ok(())
})
})
.on_event(|app, event| {
if let RunEvent::Exit = event {
tauri::async_runtime::block_on(async move {
let instances = &*app.state::<DbInstances>();
let instances = instances.0.lock().await;
for value in instances.values() {
value.close().await;
}
});
} }
}); })
} .build()
} }
} }

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-store" name = "tauri-plugin-store"
version = "0.1.0" version = "0.1.0"
edition.workspace = true description = "Simple, persistent key-value store."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -1,17 +1,62 @@
![plugin-store](banner.png) ![plugin-store](banner.png)
<!-- description --> Simple, persistent key-value store.
## Install ## Install
There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
``` ```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> 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
# or
npm add https://github.com/tauri-apps/tauri-plugin-store
# or
yarn add https://github.com/tauri-apps/tauri-plugin-store
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_store::Builder::default().build())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { Store } from "tauri-plugin-store-api";
const store = new Store(".settings.dat");
await store.set("some-key", { value: 5 });
const val = await store.get("some-key");
assert(val, { value: 5 });
``` ```
## Contributing ## Contributing
@ -20,6 +65,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -1,6 +1,7 @@
{ {
"name": "tauri-plugin-store-api", "name": "tauri-plugin-store-api",
"version": "0.0.0", "version": "0.0.0",
"description": "Simple, persistent key-value store.",
"license": "MIT or APACHE-2.0", "license": "MIT or APACHE-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"

@ -244,12 +244,12 @@ async fn save<R: Runtime>(
} }
#[derive(Default)] #[derive(Default)]
pub struct PluginBuilder { pub struct Builder {
stores: HashMap<PathBuf, Store>, stores: HashMap<PathBuf, Store>,
frozen: bool, frozen: bool,
} }
impl PluginBuilder { impl Builder {
/// Registers a store with the plugin. /// Registers a store with the plugin.
/// ///
/// # Examples /// # Examples

@ -176,7 +176,7 @@ impl Store {
.expect("failed to resolve app dir"); .expect("failed to resolve app dir");
let store_path = app_dir.join(&self.path); let store_path = app_dir.join(&self.path);
let bytes = read(&store_path)?; let bytes = read(store_path)?;
self.cache = (self.deserialize)(&bytes).map_err(Error::Deserialize)?; self.cache = (self.deserialize)(&bytes).map_err(Error::Deserialize)?;

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-stronghold" name = "tauri-plugin-stronghold"
version = "0.1.0" version = "0.1.0"
edition.workspace = true description = "Store secrets and keys using the IOTA Stronghold encrypted database."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -1,17 +1,61 @@
![plugin-stronghold](banner.png) ![plugin-stronghold](banner.png)
<!-- description --> Store secrets and keys using the [IOTA Stronghold](https://github.com/iotaledger/stronghold.rs) encrypted database and secure runtime.
## Install ## Install
There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-stronghold = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
``` ```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> 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
# or
npm add https://github.com/tauri-apps/tauri-plugin-stronghold
# or
yarn add https://github.com/tauri-apps/tauri-plugin-stronghold
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_stronghold::Builder::new(|password| {
// TODO: hash the password here with e.g. argon2, blake2b or any other secure algorithm
todo!()
})
.build())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { Stronghold, Location } from "tauri-plugin-stronghold-api";
// TODO
``` ```
## Contributing ## Contributing
@ -20,6 +64,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -1,6 +1,7 @@
{ {
"name": "tauri-plugin-stronghold-api", "name": "tauri-plugin-stronghold-api",
"version": "0.0.0", "version": "0.0.0",
"description": "Store secrets and keys using the IOTA Stronghold encrypted database.",
"license": "MIT or APACHE-2.0", "license": "MIT or APACHE-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-upload" name = "tauri-plugin-upload"
version = "0.1.0" version = "0.1.0"
edition.workspace = true description = "Upload files from disk to a remote server over HTTP."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -13,7 +15,7 @@ serde_json.workspace = true
tauri.workspace = true tauri.workspace = true
log.workspace = true log.workspace = true
thiserror.workspace = true thiserror.workspace = true
tokio = { version = "1.17", features = [ "fs" ] } tokio = { version = "1", features = [ "fs" ] }
tokio-util = { version = "0.7", features = [ "codec" ] } tokio-util = { version = "0.7", features = [ "codec" ] }
reqwest = { version = "0.11", features = [ "json", "stream" ] } reqwest = { version = "0.11", features = [ "json", "stream" ] }
futures = "0.3" futures = "0.3"

@ -1,17 +1,62 @@
![plugin-upload](banner.png) ![plugin-upload](banner.png)
<!-- description --> Upload files from disk to a remote server over HTTP.
## Install ## Install
There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-upload = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
``` ```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> 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
# or
npm add https://github.com/tauri-apps/tauri-plugin-upload
# or
yarn add https://github.com/tauri-apps/tauri-plugin-upload
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_upload::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { upload } from 'tauri-plugin-upload-api'
upload(
'https://example.com/file-upload'
'./path/to/my/file.txt'
(progress, total) => console.log(`Downloaded ${progress} of ${total} bytes`) // a callback that will be called with the upload progress
{ 'ContentType': 'text/plain' } // optional headers to send with the request
)
``` ```
## Contributing ## Contributing
@ -20,6 +65,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -1,6 +1,7 @@
{ {
"name": "tauri-plugin-upload-api", "name": "tauri-plugin-upload-api",
"version": "0.0.0", "version": "0.0.0",
"description": "Upload files from disk to a remote server over HTTP.",
"license": "MIT or APACHE-2.0", "license": "MIT or APACHE-2.0",
"authors": [ "authors": [
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"

@ -4,7 +4,11 @@
use futures::TryStreamExt; use futures::TryStreamExt;
use serde::{ser::Serializer, Serialize}; use serde::{ser::Serializer, Serialize};
use tauri::{command, plugin::Plugin, Invoke, Runtime, Window}; use tauri::{
command,
plugin::{Builder as PluginBuilder, TauriPlugin},
Runtime, Window,
};
use tokio::fs::File; use tokio::fs::File;
use tokio_util::codec::{BytesCodec, FramedRead}; use tokio_util::codec::{BytesCodec, FramedRead};
@ -82,25 +86,8 @@ fn file_to_body<R: Runtime>(id: u32, window: Window<R>, file: File) -> reqwest::
)) ))
} }
/// Tauri plugin. pub fn init<R: Runtime>() -> TauriPlugin<R> {
pub struct Upload<R: Runtime> { PluginBuilder::new("upload")
invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync>, .invoke_handler(tauri::generate_handler![upload])
} .build()
impl<R: Runtime> Default for Upload<R> {
fn default() -> Self {
Self {
invoke_handler: Box::new(tauri::generate_handler![upload]),
}
}
}
impl<R: Runtime> Plugin<R> for Upload<R> {
fn name(&self) -> &'static str {
"upload"
}
fn extend_api(&mut self, message: Invoke<R>) {
(self.invoke_handler)(message)
}
} }

@ -1,9 +1,10 @@
[package] [package]
name = "tauri-plugin-websocket" name = "tauri-plugin-websocket"
version = "0.1.0" version = "0.1.0"
edition.workspace = true
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -15,5 +16,5 @@ log.workspace = true
thiserror.workspace = true thiserror.workspace = true
rand = "0.8" rand = "0.8"
futures-util = "0.3" futures-util = "0.3"
tokio = { version = "1.17", features = ["net", "sync"] } tokio = { version = "1", features = ["net", "sync"] }
tokio-tungstenite = { version = "0.17", features = ["native-tls"] } tokio-tungstenite = { version = "0.18", features = ["native-tls"] }

@ -4,14 +4,58 @@
## Install ## Install
There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-websocket = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
``` ```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> 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
# or
npm add https://github.com/tauri-apps/tauri-plugin-websocket
# or
yarn add https://github.com/tauri-apps/tauri-plugin-websocket
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_websocket::init())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
import { WebSocket } from "tauri-plugin-websocket-api";
const ws = await WebSocket.connect("wss://example.com");
await ws.send("Hello World");
await ws.disconnect();
``` ```
## Contributing ## Contributing
@ -20,6 +64,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -1,10 +1,9 @@
use futures_util::{stream::SplitSink, SinkExt, StreamExt}; use futures_util::{stream::SplitSink, SinkExt, StreamExt};
use serde::{ser::Serializer, Deserialize, Serialize}; use serde::{ser::Serializer, Deserialize, Serialize};
use serde_json::Value as JsonValue;
use tauri::{ use tauri::{
api::ipc::{format_callback, CallbackFn}, api::ipc::{format_callback, CallbackFn},
plugin::Plugin, plugin::{Builder as PluginBuilder, TauriPlugin},
AppHandle, Invoke, Manager, Runtime, State, Window, Manager, Runtime, State, Window,
}; };
use tokio::{net::TcpStream, sync::Mutex}; use tokio::{net::TcpStream, sync::Mutex};
use tokio_tungstenite::{ use tokio_tungstenite::{
@ -161,29 +160,12 @@ async fn send(
} }
} }
pub struct TauriWebsocket<R: Runtime> { pub fn init<R: Runtime>() -> TauriPlugin<R> {
invoke_handler: Box<dyn Fn(Invoke<R>) + Send + Sync>, PluginBuilder::new("websocket")
} .invoke_handler(tauri::generate_handler![connect, send])
.setup(|app| {
impl<R: Runtime> Default for TauriWebsocket<R> { app.manage(ConnectionManager::default());
fn default() -> Self { Ok(())
Self { })
invoke_handler: Box::new(tauri::generate_handler![connect, send]), .build()
}
}
}
impl<R: Runtime> Plugin<R> for TauriWebsocket<R> {
fn name(&self) -> &'static str {
"websocket"
}
fn initialize(&mut self, app: &AppHandle<R>, _config: JsonValue) -> tauri::plugin::Result<()> {
app.manage(ConnectionManager::default());
Ok(())
}
fn extend_api(&mut self, invoke: Invoke<R>) {
(self.invoke_handler)(invoke)
}
} }

@ -1,9 +1,11 @@
[package] [package]
name = "tauri-plugin-window-state" name = "tauri-plugin-window-state"
version = "0.1.0" version = "0.1.0"
edition.workspace = true description = "Save window positions and sizse and restore them when the app is reopened."
authors.workspace = true authors.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true
rust-version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

@ -1,17 +1,57 @@
![plugin-window-state](banner.png) ![plugin-window-state](banner.png)
<!-- description --> Save window positions and sizse and restore them when the app is reopened.
## Install ## Install
``` There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_window_state::Builder::default().build())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all windows will remember their state when the app is being closed and will restore to their previous state on the next launch.
Optionally you can also tell the plugin to save the state of all open window to disk my using the `save_window_state()` method exposed by the `AppHandleExt` trait:
```rust
use tauri_plugin_window_state::AppHandleExt;
// `tauri::AppHandle` now has the following additional method
app.save_window_state(); // will save the state of all open windows to disk
```
To manually restore a windows state from disk you can call the `restore_state()` method exposed by the `WindowExt` trait:
```rust
use tauri_plugin_window_state::{WindowExt, ShowMode};
// all `Window` types now have the following additional method
window.restore_state(ShowMode::LastSaved); // will restore the windows state from disk
``` ```
## Contributing ## Contributing
@ -20,6 +60,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -0,0 +1,4 @@
{
"extends": ["config:base"],
"enabledManagers": ["cargo", "npm"]
}

@ -1,17 +1,55 @@
<img src=".github/banner.png" alt="{{name}}" /> ![{{plugin name}}](banner.jpg)
<!-- description --> <!-- description -->
## Install ## Install
There are three general methods of installation that we can recommend.
1. Use crates.io and npm (easiest, and requires you to trust that our publishing pipeline worked)
2. Pull sources directly from Github using git tags / revision hashes (most secure)
3. Git submodule install this repo in your tauri project and then use file protocol to ingest the source (most secure, but inconvenient to use)
Install the Core plugin by adding the following to your `Cargo.toml` file:
`src-tauri/Cargo.toml`
```toml
[dependencies]
<!-- plugin here --> = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
``` ```
You can install the JavaScript Guest bindings using your preferred JavaScript package manager:
> 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 <!-- plugin here -->
# or
npm add <!-- plugin here -->
# or
yarn add <!-- plugin here -->
``` ```
## Usage ## Usage
First you need to register the core plugin with Tauri:
`src-tauri/src/main.rs`
```rust
fn main() {
tauri::Builder::default()
.plugin(<!-- plugin here -->)
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
``` ```
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
``` ```
## Contributing ## Contributing
@ -20,6 +58,6 @@ PRs accepted. Please make sure to read the Contributing Guide before making a pu
## License ## License
Code: (c) 2015 - 2021 - The Tauri Programme within The Commons Conservancy. Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
MIT or MIT/Apache 2.0 where applicable. MIT or MIT/Apache 2.0 where applicable.

@ -1 +0,0 @@
../../../shared/tsconfig.json

@ -6,13 +6,13 @@
"Tauri Programme within The Commons Conservancy" "Tauri Programme within The Commons Conservancy"
], ],
"type": "module", "type": "module",
"browser": "dist/index.min.js", "browser": "guest-js/dist/index.min.js",
"module": "dist/index.mjs", "module": "guest-js/dist/index.mjs",
"types": "dist/index.d.ts", "types": "guest-js/dist/index.d.ts",
"exports": { "exports": {
"import": "./dist/index.mjs", "import": "./guest-js/dist/index.mjs",
"types": "./dist/index.d.ts", "types": "./guest-js/dist/index.d.ts",
"browser": "./dist/index.min.js" "browser": "./guest-js/dist/index.min.js"
}, },
"scripts": { "scripts": {
"build": "rollup -c" "build": "rollup -c"

@ -1,8 +1,9 @@
import { readFileSync } from "fs"; import { readFileSync } from "fs";
import { createConfig } from "../../../shared/rollup.config.mjs"; import { createConfig } from "../rollup.config.mjs";
export default createConfig({ export default createConfig({
input: "guest-js/index.ts",
pkg: JSON.parse( pkg: JSON.parse(
readFileSync(new URL("./package.json", import.meta.url), "utf8") readFileSync(new URL("./package.json", import.meta.url), "utf8")
), ),

@ -0,0 +1 @@
../tsconfig.json
Loading…
Cancel
Save