From 9f00f888220580f72ae12b39adb1ea36053c2c78 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Wed, 17 May 2023 21:12:46 -0300 Subject: [PATCH] refactor: move fs-watch to fs --- .changes/config.json | 9 - Cargo.lock | 19 +- README.md | 32 ++-- plugins/fs-watch/.gitignore | 1 - plugins/fs-watch/Cargo.toml | 19 -- plugins/fs-watch/LICENSE.spdx | 20 -- plugins/fs-watch/LICENSE_APACHE-2.0 | 177 ------------------ plugins/fs-watch/LICENSE_MIT | 21 --- plugins/fs-watch/README.md | 82 -------- plugins/fs-watch/banner.png | Bin 43432 -> 0 bytes plugins/fs-watch/guest-js/index.ts | 135 ------------- plugins/fs-watch/package.json | 33 ---- plugins/fs-watch/rollup.config.mjs | 11 -- plugins/fs-watch/tsconfig.json | 1 - plugins/fs/Cargo.toml | 5 + plugins/fs/src/error.rs | 4 + plugins/fs/src/lib.rs | 12 +- .../src/lib.rs => fs/src/watcher.rs} | 45 +---- plugins/http/README.md | 2 +- plugins/mirrors.txt | 1 - pnpm-lock.yaml | 16 +- 21 files changed, 51 insertions(+), 594 deletions(-) delete mode 100644 plugins/fs-watch/.gitignore delete mode 100644 plugins/fs-watch/Cargo.toml delete mode 100644 plugins/fs-watch/LICENSE.spdx delete mode 100644 plugins/fs-watch/LICENSE_APACHE-2.0 delete mode 100644 plugins/fs-watch/LICENSE_MIT delete mode 100644 plugins/fs-watch/README.md delete mode 100644 plugins/fs-watch/banner.png delete mode 100644 plugins/fs-watch/guest-js/index.ts delete mode 100644 plugins/fs-watch/package.json delete mode 100644 plugins/fs-watch/rollup.config.mjs delete mode 120000 plugins/fs-watch/tsconfig.json rename plugins/{fs-watch/src/lib.rs => fs/src/watcher.rs} (72%) diff --git a/.changes/config.json b/.changes/config.json index 5792535f..f74e1a5f 100644 --- a/.changes/config.json +++ b/.changes/config.json @@ -88,15 +88,6 @@ "manager": "javascript-disabled" }, - "fs-watch": { - "path": "./plugins/fs-watch", - "manager": "rust-disabled" - }, - "fs-watch-js": { - "path": "./plugins/fs-watch", - "manager": "javascript-disabled" - }, - "global-shortcut": { "path": "./plugins/global-shortcut", "manager": "rust-disabled" diff --git a/Cargo.lock b/Cargo.lock index 266a3c38..7162dcc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3100,9 +3100,9 @@ dependencies = [ [[package]] name = "notify" -version = "5.1.0" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9" +checksum = "729f63e1ca555a43fe3efa4f3efdf4801c479da85b432242a7b726f353c88486" dependencies = [ "bitflags 1.3.2", "crossbeam-channel", @@ -3114,7 +3114,7 @@ dependencies = [ "mio", "serde", "walkdir", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -5150,23 +5150,12 @@ version = "0.0.0" dependencies = [ "anyhow", "glob", - "serde", - "tauri", - "thiserror", - "uuid", -] - -[[package]] -name = "tauri-plugin-fs-watch" -version = "0.0.0" -dependencies = [ - "log", "notify", "notify-debouncer-mini", "serde", - "serde_json", "tauri", "thiserror", + "uuid", ] [[package]] diff --git a/README.md b/README.md index edeb0ac5..1fdcf447 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,19 @@ ## Plugins Found Here -| | | Win | Mac | Lin | iOS | And | -| ------------------------------------------ | --------------------------------------------------------- | --- | --- | --- | --- | --- | -| [authenticator](plugins/authenticator) | Interface with hardware security keys. | ✅ | ✅ | ✅ | ? | ? | -| [autostart](plugins/autostart) | Automatically launch your app at system startup. | ✅ | ✅ | ✅ | ? | ? | -| [fs-extra](plugins/fs-extra) | File system methods that aren't included in the core API. | ✅ | ✅ | ✅ | ? | ? | -| [fs-watch](plugins/fs-watch) | Watch the filesystem for changes. | ✅ | ✅ | ✅ | ? | ? | -| [localhost](plugins/localhost) | Use a localhost server in production apps. | ✅ | ✅ | ✅ | ? | ? | -| [log](plugins/log) | Configurable logging. | ✅ | ✅ | ✅ | ✅ | ✅ | -| [persisted-scope](plugins/persisted-scope) | Persist runtime scope changes on the filesystem. | ✅ | ✅ | ✅ | ? | ? | -| [positioner](plugins/positioner) | Move windows to common locations. | ✅ | ✅ | ✅ | ? | ? | -| [single-instance](plugins/single-instance) | Ensure a single instance of your tauri app is running. | ✅ | ? | ✅ | ? | ? | -| [sql](plugins/sql) | Interface with SQL databases. | ✅ | ✅ | ✅ | ? | ? | -| [store](plugins/store) | Persistent key value storage. | ✅ | ✅ | ✅ | ? | ? | -| [stronghold](plugins/stronghold) | Encrypted, secure database. | ✅ | ✅ | ✅ | ? | ? | -| [upload](plugins/upload) | Tauri plugin for file uploads through HTTP. | ✅ | ✅ | ✅ | ? | ? | -| [websocket](plugins/websocket) | Open a WebSocket connection using a Rust client in JS. | ✅ | ✅ | ✅ | ? | ? | -| [window-state](plugins/window-state) | Persist window sizes and positions. | ✅ | ✅ | ✅ | ? | ? | +| | | Win | Mac | Lin | iOS | And | +| ------------------------------------------ | ------------------------------------------------------ | --- | --- | --- | --- | --- | +| [authenticator](plugins/authenticator) | Interface with hardware security keys. | ✅ | ✅ | ✅ | ? | ? | +| [autostart](plugins/autostart) | Automatically launch your app at system startup. | ✅ | ✅ | ✅ | ? | ? | +| [localhost](plugins/localhost) | Use a localhost server in production apps. | ✅ | ✅ | ✅ | ? | ? | +| [log](plugins/log) | Configurable logging. | ✅ | ✅ | ✅ | ✅ | ✅ | +| [persisted-scope](plugins/persisted-scope) | Persist runtime scope changes on the filesystem. | ✅ | ✅ | ✅ | ? | ? | +| [positioner](plugins/positioner) | Move windows to common locations. | ✅ | ✅ | ✅ | ? | ? | +| [single-instance](plugins/single-instance) | Ensure a single instance of your tauri app is running. | ✅ | ? | ✅ | ? | ? | +| [sql](plugins/sql) | Interface with SQL databases. | ✅ | ✅ | ✅ | ? | ? | +| [store](plugins/store) | Persistent key value storage. | ✅ | ✅ | ✅ | ? | ? | +| [stronghold](plugins/stronghold) | Encrypted, secure database. | ✅ | ✅ | ✅ | ? | ? | +| [upload](plugins/upload) | Tauri plugin for file uploads through HTTP. | ✅ | ✅ | ✅ | ? | ? | +| [websocket](plugins/websocket) | Open a WebSocket connection using a Rust client in JS. | ✅ | ✅ | ✅ | ? | ? | +| [window-state](plugins/window-state) | Persist window sizes and positions. | ✅ | ✅ | ✅ | ? | ? | _This repo and all plugins require a Rust version of at least **1.65**_ diff --git a/plugins/fs-watch/.gitignore b/plugins/fs-watch/.gitignore deleted file mode 100644 index b512c09d..00000000 --- a/plugins/fs-watch/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules \ No newline at end of file diff --git a/plugins/fs-watch/Cargo.toml b/plugins/fs-watch/Cargo.toml deleted file mode 100644 index 8431bae0..00000000 --- a/plugins/fs-watch/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "tauri-plugin-fs-watch" -version = "0.0.0" -description = "Watch files and directories for changes." -authors.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 - -[dependencies] -serde.workspace = true -serde_json.workspace = true -tauri.workspace = true -log.workspace = true -thiserror.workspace = true -notify = { version = "5" , features = ["serde"] } -notify-debouncer-mini = { version = "0.2.1" , features = ["serde"] } diff --git a/plugins/fs-watch/LICENSE.spdx b/plugins/fs-watch/LICENSE.spdx deleted file mode 100644 index cdd0df5a..00000000 --- a/plugins/fs-watch/LICENSE.spdx +++ /dev/null @@ -1,20 +0,0 @@ -SPDXVersion: SPDX-2.1 -DataLicense: CC0-1.0 -PackageName: tauri -DataFormat: SPDXRef-1 -PackageSupplier: Organization: The Tauri Programme in the Commons Conservancy -PackageHomePage: https://tauri.app -PackageLicenseDeclared: Apache-2.0 -PackageLicenseDeclared: MIT -PackageCopyrightText: 2019-2022, The Tauri Programme in the Commons Conservancy -PackageSummary: Tauri is a rust project that enables developers to make secure -and small desktop applications using a web frontend. - -PackageComment: The package includes the following libraries; see -Relationship information. - -Created: 2019-05-20T09:00:00Z -PackageDownloadLocation: git://github.com/tauri-apps/tauri -PackageDownloadLocation: git+https://github.com/tauri-apps/tauri.git -PackageDownloadLocation: git+ssh://github.com/tauri-apps/tauri.git -Creator: Person: Daniel Thompson-Yvetot \ No newline at end of file diff --git a/plugins/fs-watch/LICENSE_APACHE-2.0 b/plugins/fs-watch/LICENSE_APACHE-2.0 deleted file mode 100644 index 4947287f..00000000 --- a/plugins/fs-watch/LICENSE_APACHE-2.0 +++ /dev/null @@ -1,177 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/plugins/fs-watch/LICENSE_MIT b/plugins/fs-watch/LICENSE_MIT deleted file mode 100644 index 4d754725..00000000 --- a/plugins/fs-watch/LICENSE_MIT +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 - Present Tauri Apps Contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/plugins/fs-watch/README.md b/plugins/fs-watch/README.md deleted file mode 100644 index 63a154c8..00000000 --- a/plugins/fs-watch/README.md +++ /dev/null @@ -1,82 +0,0 @@ -![plugin-fs-watch](banner.png) - -Watch files and directories for changes using [notify](https://github.com/notify-rs/notify). - -## Install - -_This plugin requires a Rust version of at least **1.65**_ - -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 = "v2" } -``` - -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#v2 -# or -npm add https://github.com/tauri-apps/tauri-plugin-fs-watch#v2 -# or -yarn add https://github.com/tauri-apps/tauri-plugin-fs-watch#v2 -``` - -## 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-apps/plugin-fs-watch"; - -// can also watch an array of paths -const stopWatching = await watch( - "/path/to/something", - (event) => { - const { type, payload } = event; - }, - { recursive: true } -); - -const stopRawWatcher = await watchImmediate( - ["/path/a", "/path/b"], - (event) => { - const { path, operation, cookie } = event; - }, - {} -); -``` - -## Contributing - -PRs accepted. Please make sure to read the Contributing Guide before making a pull request. - -## License - -Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy. - -MIT or MIT/Apache 2.0 where applicable. diff --git a/plugins/fs-watch/banner.png b/plugins/fs-watch/banner.png deleted file mode 100644 index 6e77fe16b1896e8f42209a1d2d79ec4ba97a387e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43432 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 ASO5S3 diff --git a/plugins/fs-watch/guest-js/index.ts b/plugins/fs-watch/guest-js/index.ts deleted file mode 100644 index 2aa58b0c..00000000 --- a/plugins/fs-watch/guest-js/index.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { invoke, transformCallback } from "@tauri-apps/api/tauri"; - -export interface WatchOptions { - recursive?: boolean; -} - -export interface DebouncedWatchOptions extends WatchOptions { - delayMs?: number; -} - -export type RawEvent = { - type: RawEventKind; - paths: string[]; - attrs: unknown; -}; - -type RawEventKind = - | "any " - | { - access?: unknown; - } - | { - create?: unknown; - } - | { - modify?: unknown; - } - | { - remove?: unknown; - } - | "other"; - -export type DebouncedEvent = - | { kind: "any"; path: string } - | { kind: "AnyContinous"; path: string }; - -async function unwatch(id: number): Promise { - await invoke("plugin:fs-watch|unwatch", { id }); -} - -// TODO: use channel from @tauri-apps/api on v2 -class Channel { - id: number; - // @ts-expect-error field used by the IPC serializer - private readonly __TAURI_CHANNEL_MARKER__ = true; - #onmessage: (response: T) => void = () => { - // no-op - }; - - constructor() { - this.id = transformCallback((response: T) => { - this.#onmessage(response); - }); - } - - set onmessage(handler: (response: T) => void) { - this.#onmessage = handler; - } - - get onmessage(): (response: T) => void { - return this.#onmessage; - } - - toJSON(): string { - return `__CHANNEL__:${this.id}`; - } -} - -export async function watch( - paths: string | string[], - cb: (event: DebouncedEvent) => void, - options: DebouncedWatchOptions = {} -): Promise<() => void> { - const opts = { - recursive: false, - delayMs: 2000, - ...options, - }; - let watchPaths; - if (typeof paths === "string") { - watchPaths = [paths]; - } else { - watchPaths = paths; - } - - const id = window.crypto.getRandomValues(new Uint32Array(1))[0]; - - const onEvent = new Channel(); - onEvent.onmessage = cb; - - await invoke("plugin:fs-watch|watch", { - id, - paths: watchPaths, - options: opts, - onEvent, - }); - - return () => { - void unwatch(id); - }; -} - -export async function watchImmediate( - paths: string | string[], - cb: (event: RawEvent) => void, - options: WatchOptions = {} -): Promise<() => void> { - const opts = { - recursive: false, - ...options, - delayMs: null, - }; - let watchPaths; - if (typeof paths === "string") { - watchPaths = [paths]; - } else { - watchPaths = paths; - } - - const id = window.crypto.getRandomValues(new Uint32Array(1))[0]; - - const onEvent = new Channel(); - onEvent.onmessage = cb; - - await invoke("plugin:fs-watch|watch", { - id, - paths: watchPaths, - options: opts, - onEvent, - }); - - return () => { - void unwatch(id); - }; -} diff --git a/plugins/fs-watch/package.json b/plugins/fs-watch/package.json deleted file mode 100644 index e5c0bb7a..00000000 --- a/plugins/fs-watch/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "@tauri-apps/plugin-fs-watch", - "version": "0.0.0", - "description": "Watch files and directories for changes.", - "license": "MIT or APACHE-2.0", - "authors": [ - "Tauri Programme within The Commons Conservancy" - ], - "type": "module", - "browser": "dist-js/index.min.js", - "module": "dist-js/index.mjs", - "types": "dist-js/index.d.ts", - "exports": { - "import": "./dist-js/index.mjs", - "types": "./dist-js/index.d.ts", - "browser": "./dist-js/index.min.js" - }, - "scripts": { - "build": "rollup -c" - }, - "files": [ - "dist-js", - "!dist-js/**/*.map", - "README.md", - "LICENSE" - ], - "devDependencies": { - "tslib": "^2.5.0" - }, - "dependencies": { - "@tauri-apps/api": "^1.2.0" - } -} diff --git a/plugins/fs-watch/rollup.config.mjs b/plugins/fs-watch/rollup.config.mjs deleted file mode 100644 index 6555e98b..00000000 --- a/plugins/fs-watch/rollup.config.mjs +++ /dev/null @@ -1,11 +0,0 @@ -import { readFileSync } from "fs"; - -import { createConfig } from "../../shared/rollup.config.mjs"; - -export default createConfig({ - input: "guest-js/index.ts", - pkg: JSON.parse( - readFileSync(new URL("./package.json", import.meta.url), "utf8") - ), - external: [/^@tauri-apps\/api/], -}); diff --git a/plugins/fs-watch/tsconfig.json b/plugins/fs-watch/tsconfig.json deleted file mode 120000 index 7cd38da8..00000000 --- a/plugins/fs-watch/tsconfig.json +++ /dev/null @@ -1 +0,0 @@ -../../shared/tsconfig.json \ No newline at end of file diff --git a/plugins/fs/Cargo.toml b/plugins/fs/Cargo.toml index bb3980b6..9ec49e97 100644 --- a/plugins/fs/Cargo.toml +++ b/plugins/fs/Cargo.toml @@ -16,3 +16,8 @@ thiserror.workspace = true anyhow = "1" uuid = { version = "1", features = ["v4"] } glob = "0.3" +notify = { version = "5", optional = true, features = ["serde"] } +notify-debouncer-mini = { version = "0.2.1", optional = true, features = ["serde"] } + +[features] +watch = ["notify", "notify-debouncer-mini"] diff --git a/plugins/fs/src/error.rs b/plugins/fs/src/error.rs index 9af56db3..e627b458 100644 --- a/plugins/fs/src/error.rs +++ b/plugins/fs/src/error.rs @@ -13,6 +13,10 @@ pub enum Error { /// Invalid glob pattern. #[error("invalid glob pattern: {0}")] GlobPattern(#[from] glob::PatternError), + /// Watcher error. + #[cfg(feature = "watch")] + #[error(transparent)] + Watch(#[from] notify::Error), } impl Serialize for Error { diff --git a/plugins/fs/src/lib.rs b/plugins/fs/src/lib.rs index 737189d5..023d04e6 100644 --- a/plugins/fs/src/lib.rs +++ b/plugins/fs/src/lib.rs @@ -12,6 +12,8 @@ mod commands; mod config; mod error; mod scope; +#[cfg(feature = "watch")] +mod watcher; pub use config::Config; pub use error::Error; @@ -47,7 +49,11 @@ pub fn init() -> TauriPlugin> { commands::remove_file, commands::rename_file, commands::exists, - commands::metadata + commands::metadata, + #[cfg(feature = "watch")] + watcher::watch, + #[cfg(feature = "watch")] + watcher::unwatch ]) .setup(|app: &tauri::AppHandle, api| { let default_scope = FsScope::default(); @@ -58,6 +64,10 @@ pub fn init() -> TauriPlugin> { .map(|c| &c.scope) .unwrap_or(&default_scope), )?); + + #[cfg(feature = "watch")] + app.manage(watcher::WatcherCollection::default()); + Ok(()) }) .on_event(|app, event| { diff --git a/plugins/fs-watch/src/lib.rs b/plugins/fs/src/watcher.rs similarity index 72% rename from plugins/fs-watch/src/lib.rs rename to plugins/fs/src/watcher.rs index d0a9f783..79cb34a2 100644 --- a/plugins/fs-watch/src/lib.rs +++ b/plugins/fs/src/watcher.rs @@ -1,12 +1,9 @@ use notify::{Config, Event, RecommendedWatcher, RecursiveMode, Watcher}; use notify_debouncer_mini::{new_debouncer, DebounceEventResult, Debouncer}; -use serde::{ser::Serializer, Deserialize, Serialize}; -use tauri::{ - api::ipc::Channel, - command, - plugin::{Builder as PluginBuilder, TauriPlugin}, - Manager, Runtime, State, -}; +use serde::Deserialize; +use tauri::{api::ipc::Channel, command, Runtime, State}; + +use crate::Result; use std::{ collections::HashMap, @@ -19,26 +16,10 @@ use std::{ time::Duration, }; -type Result = std::result::Result; type Id = u32; -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error(transparent)] - Watch(#[from] notify::Error), -} - -impl Serialize for Error { - fn serialize(&self, serializer: S) -> std::result::Result - where - S: Serializer, - { - serializer.serialize_str(self.to_string().as_ref()) - } -} - #[derive(Default)] -struct WatcherCollection(Mutex)>>); +pub struct WatcherCollection(Mutex)>>); enum WatcherKind { Debouncer(Debouncer), @@ -69,13 +50,13 @@ fn watch_debounced(on_event: Channel, rx: Receiver, recursive: bool, } #[command] -async fn watch( +pub async fn watch( watchers: State<'_, WatcherCollection>, id: Id, paths: Vec, @@ -113,7 +94,7 @@ async fn watch( } #[command] -async fn unwatch(watchers: State<'_, WatcherCollection>, id: Id) -> Result<()> { +pub async fn unwatch(watchers: State<'_, WatcherCollection>, id: Id) -> Result<()> { if let Some((watcher, paths)) = watchers.0.lock().unwrap().remove(&id) { match watcher { WatcherKind::Debouncer(mut debouncer) => { @@ -130,13 +111,3 @@ async fn unwatch(watchers: State<'_, WatcherCollection>, id: Id) -> Result<()> { } Ok(()) } - -pub fn init() -> TauriPlugin { - PluginBuilder::new("fs-watch") - .invoke_handler(tauri::generate_handler![watch, unwatch]) - .setup(|app, _api| { - app.manage(WatcherCollection::default()); - Ok(()) - }) - .build() -} diff --git a/plugins/http/README.md b/plugins/http/README.md index de55e8dd..729cedfa 100644 --- a/plugins/http/README.md +++ b/plugins/http/README.md @@ -18,7 +18,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file: ```toml [dependencies] -tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } +tauri-plugin-http = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } ``` You can install the JavaScript Guest bindings using your preferred JavaScript package manager: diff --git a/plugins/mirrors.txt b/plugins/mirrors.txt index c785da72..c441d95e 100644 --- a/plugins/mirrors.txt +++ b/plugins/mirrors.txt @@ -4,7 +4,6 @@ cli clipboard dialog fs -fs-watch global-shortcut http localhost diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 15858968..dceddd2f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -58,9 +58,6 @@ importers: '@tauri-apps/cli': specifier: 2.0.0-alpha.8 version: 2.0.0-alpha.8 - '@zerodevx/svelte-json-view': - specifier: 0.2.1 - version: 0.2.1 '@tauri-apps/plugin-app': specifier: 0.0.0 version: link:../../plugins/app @@ -100,6 +97,9 @@ importers: '@tauri-apps/plugin-window': specifier: 0.0.0 version: link:../../plugins/window + '@zerodevx/svelte-json-view': + specifier: 0.2.1 + version: 0.2.1 devDependencies: '@iconify-json/codicon': specifier: ^1.1.10 @@ -193,16 +193,6 @@ importers: specifier: ^2.4.1 version: 2.4.1 - plugins/fs-watch: - dependencies: - '@tauri-apps/api': - specifier: ^1.2.0 - version: 1.2.0 - devDependencies: - tslib: - specifier: ^2.5.0 - version: 2.5.0 - plugins/global-shortcut: dependencies: '@tauri-apps/api':