mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-10-16 23:00:54 +02:00
chore: add AGENTS.md (#3680)
* chore: add AGENTS.md * Apply batched suggestions from code review [skip ci] Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com> * simplify --------- Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
This commit is contained in:
1 parent
dff0dd4b23
commit
8efe845612
2 files changed
+150
-1
No files matched your search
@@ -0,0 +1,150 @@
|
||||
# AGENTS.md
|
||||
|
||||
Instructions for coding agents working in this repository. The contributor guide is [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md).
|
||||
|
||||
## Overview
|
||||
|
||||
This repo holds the official [Tauri](https://tauri.app) plugins. Each directory in `plugins/` is one plugin, published as:
|
||||
|
||||
- the Rust crate `tauri-plugin-<name>` on crates.io, and
|
||||
- the npm package `@tauri-apps/plugin-<name>`, its JavaScript bindings for the webview, at the **same version** as the crate.
|
||||
|
||||
Some plugins are Rust-only and have no npm package.
|
||||
|
||||
Each Tauri major version has a branch here (`v1`, `v2`, …) with the plugins compatible with it. PRs go to the default branch. Don't port changes between them unless asked.
|
||||
|
||||
## Layout
|
||||
|
||||
```text
|
||||
plugins/<name>/
|
||||
build.rs lists the plugin's commands and generates its permissions
|
||||
src/lib.rs init()/Builder, plus a `<Name>Ext` trait on AppHandle & co.
|
||||
src/commands.rs #[tauri::command] handlers
|
||||
src/desktop.rs, mobile.rs platform implementations; mobile.rs calls into Kotlin/Swift
|
||||
src/error.rs thiserror Error, serialized to JS as its message string
|
||||
src/models.rs serde types shared with JS and native code
|
||||
permissions/*.toml hand-written permission sets, including default.toml
|
||||
permissions/autogenerated/ generated
|
||||
permissions/schemas/ generated
|
||||
guest-js/index.ts JS API: thin wrappers around invoke('plugin:<name>|<command>')
|
||||
api-iife.js generated: the window.__TAURI__.<name> global (withGlobalTauri)
|
||||
android/, ios/ native plugin code (Kotlin library, Swift package)
|
||||
examples/ small per-plugin example apps
|
||||
examples/api/ Svelte app that registers every plugin; the manual test bed
|
||||
packages/api-e2e/ WebdriverIO e2e suite driven against examples/api
|
||||
shared/rollup.config.js the rollup config every plugin builds with (createConfig)
|
||||
shared/template/ skeleton for a new plugin ({{ placeholders }}, not compiled)
|
||||
.changes/ covector change files
|
||||
.scripts/ci/ scripts CI runs; they work locally too
|
||||
```
|
||||
|
||||
## Build, lint, test
|
||||
|
||||
Run everything from the repo root.
|
||||
|
||||
```sh
|
||||
pnpm install
|
||||
pnpm build # every plugin: dist-js/, api-iife.js, src/init-iife.js
|
||||
pnpm --filter @tauri-apps/plugin-<name> build # one plugin
|
||||
```
|
||||
|
||||
Run `pnpm build` before `pnpm lint`, `pnpm ts:check`, the example app or the e2e suite, because they read the plugins from `dist-js/`.
|
||||
|
||||
Rust checks run per crate. CI runs them for every plugin a change affects, on Windows, Linux and macOS, and builds for iOS and Android:
|
||||
|
||||
```sh
|
||||
cargo clippy -p tauri-plugin-<name> --all-targets -- -D warnings
|
||||
cargo clippy -p tauri-plugin-<name> --all-targets --all-features -- -D warnings
|
||||
cargo test -p tauri-plugin-<name> --all-targets --all-features
|
||||
cargo test -p tauri-plugin-<name> --doc
|
||||
```
|
||||
|
||||
Some plugins have mutually exclusive features (check `[features]` in their `Cargo.toml`) and don't build with `--all-features`. Drop that flag for them.
|
||||
|
||||
Formatting and JS checks. CI fails if any of them would change a file or report an error:
|
||||
|
||||
```sh
|
||||
cargo fmt --all
|
||||
taplo fmt # TOML
|
||||
pnpm format # prettier: TS, JS, JSON, Markdown, YAML
|
||||
pnpm lint # eslint with type-aware rules
|
||||
pnpm ts:check
|
||||
```
|
||||
|
||||
To try a change by hand, run `pnpm example:api:dev`. It starts `examples/api` against the local plugins.
|
||||
|
||||
The e2e suite runs with `pnpm test:api-e2e` (`test:api-e2e:android` and `test:api-e2e:ios` for mobile). Its prerequisites, environment variables and how to add a spec are in [packages/api-e2e/README.md](packages/api-e2e/README.md).
|
||||
|
||||
## Generated files
|
||||
|
||||
Don't edit these by hand. Regenerate them and commit the result together with the change that caused it.
|
||||
|
||||
| Files | Regenerated by |
|
||||
| ------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
|
||||
| `plugins/*/api-iife.js`, `plugins/*/src/init-iife.js` | `pnpm build`. CI fails if the build leaves a diff. |
|
||||
| `plugins/*/permissions/autogenerated/**`, `plugins/*/permissions/schemas/schema.json` | the plugin's `build.rs`, on any `cargo check` or build of it |
|
||||
| `CHANGELOG.md` files, package versions, the `version` of path dependencies | covector, at release time. Don't bump versions in a PR. |
|
||||
|
||||
Also leave `dist-js/` alone, along with the git-ignored `.tauri/` directories under `plugins/*/` and `plugins/*/android/`. The build copies Tauri's mobile API into those.
|
||||
|
||||
## Adding or changing a command
|
||||
|
||||
These places must agree:
|
||||
|
||||
1. `src/commands.rs`: write the `#[tauri::command]`, returning `crate::Result<T>`.
|
||||
2. `src/lib.rs`: register it in `tauri::generate_handler![…]` on every platform where the JS API exposes it. If it can't work on a platform, register it anyway and return an error there. An unregistered command reaches JS as an opaque "command not found".
|
||||
3. `build.rs`: add it to `COMMANDS`, which generates its `allow-…` and `deny-…` permissions. Without them, apps can't grant it. When you remove a command, also delete its file from `permissions/autogenerated/commands/`, because the build doesn't remove stale ones.
|
||||
4. `permissions/default.toml`: add it only if every app should get it without opting in. Defaults are deliberately narrow.
|
||||
5. `guest-js/index.ts`: call `invoke('plugin:<name>|<command_name>', { … })`. JS passes the command's snake_case parameters as camelCase keys (`file_path` becomes `filePath`), and serde structs use `#[serde(rename_all = "camelCase")]`. Give exported functions TSDoc with an `@example`, and set `@since` to the version the change will ship in.
|
||||
6. Mobile: `mobile.rs` forwards with `run_mobile_plugin("<methodName>", args)` to the Kotlin `@Command` or Swift `@objc` method of that name.
|
||||
7. Example app: if it should use the command, grant it in `examples/api/src-tauri/capabilities/` and cover it in `packages/api-e2e`.
|
||||
8. Run `cargo check -p tauri-plugin-<name>` and `pnpm build`, then commit the regenerated files.
|
||||
|
||||
## Change files
|
||||
|
||||
A change to a published crate or npm package needs a [covector](https://github.com/jbolda/covector) change file in `.changes/`. Changes that only touch CI, tests, examples or docs don't. Here is a real one, `.changes/fix-fs-read-lines-error.md`:
|
||||
|
||||
```md
|
||||
---
|
||||
fs: patch
|
||||
fs-js: patch
|
||||
---
|
||||
|
||||
Fixed `readTextFileLines` yielding empty lines forever when reading fails (e.g. on a directory). The read error is now reported: the iterator rejects and the file is closed.
|
||||
```
|
||||
|
||||
- The keys are package names from `.changes/config.json`. `<plugin>` is the crate and `<plugin>-js` is the npm package.
|
||||
- **List both with the same bump, even when only the Rust side or only the JS side changed.** Their versions are kept identical. Rust-only plugins have no `-js` entry.
|
||||
- The bump is `patch`, `minor` or `major`. Plugins that depend on the changed one (`dialog` on `fs`, for example) are bumped automatically, so don't list them.
|
||||
- The body becomes the changelog entry. Write it for the plugin's users: what changed, and what they must update.
|
||||
- Check the file with `node .scripts/ci/check-change-files.js .changes/<file>.md`.
|
||||
|
||||
## Rules and gotchas
|
||||
|
||||
- **License header:** new `.rs`, `.ts`, `.js`, `.kt`, `.swift` and `.yml` files must start with these lines (with `#` comments in YAML). Keep the year range exactly as written:
|
||||
|
||||
```text
|
||||
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
```
|
||||
|
||||
Check new files with `node .scripts/ci/check-license-header.js <files>`. Without arguments, it also reports the git-ignored `.tauri/` copies, which you can ignore.
|
||||
|
||||
- **MSRV:** the tests run on exactly on MSRV configured in Cargo.toml (clippy runs on stable). Don't use newer std APIs, and check with `cargo +<version> check -p tauri-plugin-<name>` where <version> is the current MSRV for the plugin.
|
||||
- **tauri features:** the workspace depends on `tauri` with `default-features = false`. A plugin that needs a tauri feature, such as `wry` on iOS, enables it in its own `Cargo.toml`. Build plugins with `-p`: a workspace-wide build unifies features with `examples/api`, which hides a missing one.
|
||||
- **Platform cfgs:** use the `desktop` and `mobile` cfgs that `tauri-plugin`'s build script sets, and `target_os` for single platforms. Desktop-only dependencies go in the long `cfg(any(target_os = "macos", windows, target_os = "linux", …))` target table that the existing manifests use.
|
||||
- **docs.rs:** a plugin with mobile code must detect docs.rs in its `build.rs` with `std::env::var_os("DOCS_RS")`, as `plugins/dialog/build.rs` does. `cfg!(docsrs)` is never set for build scripts, and `shared/template/build.rs` still has that old form.
|
||||
- **Dependencies:** shared ones come from `[workspace.dependencies]` (`serde = { workspace = true }`). A plugin that depends on another uses a path plus a version (`tauri-plugin-fs = { path = "../fs", version = "2.6.0" }`).
|
||||
- **Updates:** Renovate handles routine dependency updates, so don't run a blanket `cargo update` or `pnpm update`. Unrelated lockfile changes make CI build and test every plugin.
|
||||
- **New npm versions:** pnpm won't install versions published less than 3 days ago (`minimumReleaseAge`). Ask before adding an exception to `pnpm-workspace.yaml`.
|
||||
- **Platform support:** when a plugin gains or loses a platform, update `[package.metadata.platforms.support]` in its `Cargo.toml`, the table in its README and the table in the root README.
|
||||
- **Mirrors:** plugins listed in `plugins/mirrors.txt` are pushed to read-only `tauri-apps/tauri-plugin-<name>` repositories. Make changes here, not in the mirrors.
|
||||
- **Security:** report vulnerabilities privately, as [SECURITY.md](SECURITY.md) describes. Never put them in a public issue or PR.
|
||||
|
||||
## Commits and pull requests
|
||||
|
||||
- Use conventional-commit titles scoped to the plugin: `fix(fs): …`, `feat(notification): …`, `chore(deps): …`, `ci: …`, `docs(log): …`. When the change fixes an issue, end the title with `(fix #1234)`.
|
||||
- Commits must be signed, so don't bypass signing. PRs are squash-merged, so intermediate commits are fine.
|
||||
- A new feature needs a convincing reason, ideally an issue the maintainers accepted. Link it in the PR.
|
||||
- [AI tool policy](.github/CONTRIBUTING.md#ai-tool-policy): the person submitting is responsible for everything an agent wrote, and replies to review comments must not be AI-written (translations excepted). PRs that ignore this are closed as `ai-slop`. Before handing work over, run the checks above and say plainly what you tested and on which platforms. Don't draft or post replies to review comments.
|
||||
@@ -3,7 +3,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// @ts-nocheck
|
||||
// This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually.
|
||||
|
||||
/** user-defined commands **/
|
||||
|
||||
|
||||
Reference in new issue
Block a user