@outl/plugin-sdk 0.8.0-beta.131 → 0.8.0-beta.134
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -0
- package/package.json +5 -1
package/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# @outl/plugin-sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for authoring [outl](https://outl.app) plugins.
|
|
4
|
+
|
|
5
|
+
**Types + one helper, nothing else.** Zero runtime dependencies. The SDK never talks to Tauri, the filesystem, or the network — the real `PluginContext` is injected by the outl runtime (a Boa JS engine in the Rust `outl-plugins` crate) when it calls your plugin's `activate(ctx)`.
|
|
6
|
+
|
|
7
|
+
Documentation: **<https://outl.app/docs/query#plugin-sdk-api-outlquery>**
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install @outl/plugin-sdk
|
|
13
|
+
# or
|
|
14
|
+
bun add @outl/plugin-sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { definePlugin } from "@outl/plugin-sdk";
|
|
21
|
+
|
|
22
|
+
export default definePlugin({
|
|
23
|
+
activate(ctx) {
|
|
24
|
+
ctx.commands.register("say-hi", () => ctx.ui.notify("hi from my plugin"));
|
|
25
|
+
|
|
26
|
+
// React to every op applied to the log (needs the `read-op-log` permission).
|
|
27
|
+
ctx.ops.onOp((op) => {
|
|
28
|
+
if (op.actor?.startsWith("plugin:")) return; // ignore your own writes
|
|
29
|
+
ctx.log.info(`op ${op.kind} on ${op.node}`);
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
All plugin **metadata** — id, version, permissions, `contributes` — lives in `plugin.json`, never in code. `definePlugin` carries **behavior only**, so there's exactly one source of truth per fact.
|
|
36
|
+
|
|
37
|
+
## Mental model
|
|
38
|
+
|
|
39
|
+
You think in **blocks and ops**, never in pixels, CRDT internals, or `.md` files. Every mutation you trigger (`ctx.blocks.move`, `ctx.blocks.edit`, …) becomes a host call routed through `outl-actions` → `Workspace::apply` → the op log, stamped `plugin:<id>@<device>`. The op log stays the single source of truth; the SDK is just a typed door to it.
|
|
40
|
+
|
|
41
|
+
Blocks execute **describe → apply**: reads (`query` / `get`) see a snapshot from the start of the turn, and writes are buffered and applied by the host *after* your handler returns. A block you `edit`/`create` this turn is **not** visible to a later `query` in the same turn — collect what you need first, then mutate.
|
|
42
|
+
|
|
43
|
+
## The `ctx` surface
|
|
44
|
+
|
|
45
|
+
Each namespace is gated by a permission declared in `plugin.json`; calling into one you didn't request rejects at the host boundary.
|
|
46
|
+
|
|
47
|
+
| Namespace | What it does | Permission |
|
|
48
|
+
|-----------|--------------|------------|
|
|
49
|
+
| `ctx.blocks` | Query, get, edit, create, move, toggle TODO, delete, `appendTree` | `read-page` / `write-page` / `submit-op` |
|
|
50
|
+
| `ctx.page` | List, create, `appendTree` (seed a fresh page's first blocks) | `read-page` / `write-page` |
|
|
51
|
+
| `ctx.template` | List and instantiate structural templates | `read-page` / `write-page` |
|
|
52
|
+
| `ctx.ops` | `onOp` hook fired for every applied op (local + synced) | `read-op-log` |
|
|
53
|
+
| `ctx.commands` | Register slash-menu / keybinding handlers | — (declared in `plugin.json`) |
|
|
54
|
+
| `ctx.config` | Read the user's validated config for this plugin | — |
|
|
55
|
+
| `ctx.storage` | Per-plugin local key/value store (**does not sync**) | `storage:local` |
|
|
56
|
+
| `ctx.secrets` | Read this plugin's secrets from the OS keychain | `secrets` |
|
|
57
|
+
| `ctx.net` | `fetch` with a required `timeoutMs` | `network:<domain>` |
|
|
58
|
+
| `ctx.content` | Register a code-fence transformer for a language | `content-transformer:*` |
|
|
59
|
+
| `ctx.sync` | Register a sync transport (ship/receive op JSONL) | `sync-transport` |
|
|
60
|
+
| `ctx.ui` | `notify` toast; `render` sandboxed HTML overlay (GUI only) | — / `ui-render` |
|
|
61
|
+
| `ctx.log` | Structured logging into the client's plugin log | — |
|
|
62
|
+
|
|
63
|
+
## Structured query — `outl.query`
|
|
64
|
+
|
|
65
|
+
The workspace query engine is also exposed as a structured API. Pass a plain object instead of the DSL string; both paths converge on the same engine:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const tasks = outl.query({ status: "todo", tag: "ops", sort: "page", limit: 50 });
|
|
69
|
+
for (const t of tasks) {
|
|
70
|
+
console.log(`${t.status === "done" ? "[x]" : "[ ]"} ${t.text} — (${t.page})`);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Full field and result-shape reference: <https://outl.app/docs/query#plugin-sdk-api-outlquery>.
|
|
75
|
+
|
|
76
|
+
## Links
|
|
77
|
+
|
|
78
|
+
- Plugin API reference: <https://outl.app/docs/plugin-api>
|
|
79
|
+
- Plugin architecture: <https://outl.app/docs/plugin-architecture>
|
|
80
|
+
- Tutorial: <https://outl.app/docs/plugin-tutorial>
|
|
81
|
+
- Source: <https://github.com/avelino/outl>
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@outl/plugin-sdk",
|
|
3
|
-
"version": "0.8.0-beta.
|
|
3
|
+
"version": "0.8.0-beta.134",
|
|
4
4
|
"description": "TypeScript SDK for authoring outl plugins. Types-only contract — the host implementation is injected by the outl runtime (Boa/Rust) at load time.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"homepage": "https://outl.app/docs/query#plugin-sdk-api-outlquery",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/avelino/outl/issues"
|
|
9
|
+
},
|
|
6
10
|
"type": "module",
|
|
7
11
|
"main": "./src/index.ts",
|
|
8
12
|
"module": "./src/index.ts",
|