mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 05:26:47 +00:00
cf9be554ac
Round out the author experience so the loop is create -> dev -> release/submit without hand-work or a round-trip through registry review. - `dev`: run a plugin locally with a real request loop and hot reload — no full TREK. Injects a ctx that enforces the manifest's granted permissions (an ungranted call throws, so you catch a missing grant), backs db:own with a real SQLite file (node:sqlite), serves routes under /api and page/widget UI at /ui, and reloads on save. Dependency-free (node:http + built-ins). - `preflight`: run the registry CI checks locally over the network (tag->commit, manifest parity, artifact sha256/size, native scan, README quality gate) so a green run predicts a green CI. - `submit`: fork TREK-Plugins, branch off current main, write/merge the entry, push, and open the PR — the last manual publishing step, automated. - `keygen`/`sign` + `--sign` on entry/release/submit: dependency-free Ed25519 author signatures over the artifact bytes, verified 1:1 against the server's TOFU check. Fills authorPublicKey + signature and guards against a key change. - `create` gains an interactive wizard (id/type/author/permissions) and flags. - README + Development/Publishing/Permissions wikis document the new flow. 24 tests pass (sign round-trips through a server-shaped verifier; zip reader; scaffold options; entry signing + key-change guard).
128 lines
5.1 KiB
Markdown
128 lines
5.1 KiB
Markdown
# trek-plugin-sdk
|
|
|
|
The SDK for building [TREK](https://github.com/mauriceboe/TREK) plugins.
|
|
|
|
## Scaffold a plugin
|
|
|
|
```bash
|
|
npx trek-plugin-sdk create # interactive wizard (id, type, permissions)
|
|
npx trek-plugin-sdk create my-plugin --type widget # or non-interactive
|
|
cd my-plugin
|
|
```
|
|
|
|
## Develop with a live reload loop
|
|
|
|
`dev` runs your plugin locally — no full TREK needed. It injects a `ctx` that
|
|
enforces exactly the permissions your manifest grants (an ungranted call throws
|
|
`PERMISSION_DENIED`, so you catch missing grants), backs `db:own` with a real
|
|
SQLite file, serves your routes and your page/widget UI, and reloads on save.
|
|
|
|
```bash
|
|
npx trek-plugin-sdk dev # http://localhost:4317 — dashboard, routes, UI
|
|
```
|
|
|
|
Hit a route as an unauthenticated request with `?_anon=1`. Drop a
|
|
`dev-fixtures.json` (trips, users, config) next to your manifest to feed
|
|
`ctx.trips` / `ctx.users`.
|
|
|
|
## Write a plugin
|
|
|
|
```js
|
|
const { definePlugin } = require('trek-plugin-sdk')
|
|
|
|
module.exports = definePlugin({
|
|
async onLoad(ctx) {
|
|
await ctx.db.migrate('001', 'CREATE TABLE cache (k TEXT PRIMARY KEY, v TEXT)')
|
|
},
|
|
routes: [
|
|
{ method: 'GET', path: '/status', auth: true, async handler(req, ctx) {
|
|
return { status: 200, headers: { 'content-type': 'application/json' }, body: '{"ok":true}' }
|
|
}},
|
|
],
|
|
})
|
|
```
|
|
|
|
Your plugin runs in an **isolated child process**. `ctx` is the only way to reach
|
|
TREK, and it grants exactly the permissions your `trek-plugin.json` declares — an
|
|
ungranted call throws `PERMISSION_DENIED`.
|
|
|
|
## Test without a running TREK
|
|
|
|
```js
|
|
import { createMockHost } from 'trek-plugin-sdk/testing'
|
|
|
|
const { ctx, broadcasts } = createMockHost({
|
|
grants: ['db:read:trips', 'ws:broadcast:trip'],
|
|
trips: { 1: { members: [42], data: { id: 1, name: 'Japan' } } },
|
|
})
|
|
// the mock enforces the SAME permission model, so you can prove your plugin
|
|
// degrades gracefully when a permission is missing.
|
|
```
|
|
|
|
## Publish
|
|
|
|
The SDK does the fiddly parts (zipping, hashing, sizing, writing the registry
|
|
entry, opening the PR) so you don't compute anything by hand. The short path:
|
|
|
|
```bash
|
|
git tag v1.0.0 && git push --tags
|
|
npx trek-plugin-sdk release --repo you/repo --tag v1.0.0 # pack -> GitHub release -> entry
|
|
npx trek-plugin-sdk submit --repo you/repo --tag v1.0.0 # opens the registry PR for you
|
|
```
|
|
|
|
`submit` forks [TREK-Plugins](https://github.com/mauriceboe/TREK-Plugins),
|
|
branches off the current main, writes (or merges into) `registry/plugins/<id>.json`,
|
|
and opens the PR — the last manual step is gone. Prefer to paste it yourself?
|
|
`entry` just prints the JSON.
|
|
|
|
**Check before you submit** — run the exact registry CI checks locally so you
|
|
don't round-trip through review:
|
|
|
|
```bash
|
|
npx trek-plugin-sdk preflight --repo you/repo --tag v1.0.0
|
|
# verifies the tag→commit, manifest parity, artifact sha256/size, native scan,
|
|
# and the README quality gate — over the network, against your pushed release.
|
|
```
|
|
|
|
**Updating** a listed plugin: bump `version`, tag, and re-run `submit` — it
|
|
detects the existing entry and prepends the new version, newest-first.
|
|
|
|
### Sign your releases (optional, recommended)
|
|
|
|
Give your plugin a stable identity. TREK pins your key on first install
|
|
(trust-on-first-use); afterwards an unsigned or wrong-key update is refused.
|
|
|
|
```bash
|
|
npx trek-plugin-sdk keygen # once — writes ~/.trek-plugin/signing.key
|
|
npx trek-plugin-sdk release --repo you/repo --tag v1.1.0 --sign
|
|
npx trek-plugin-sdk submit --repo you/repo --tag v1.1.0 --sign
|
|
```
|
|
|
|
Signing is dependency-free Ed25519 over the artifact bytes. **Back up the key** —
|
|
losing it means you can't ship signed updates.
|
|
|
|
## Exports
|
|
|
|
- `definePlugin(def)` + all the plugin types (`PluginContext`, `PluginRoute`, `PluginJob`, `PhotoProvider`, `CalendarSource`).
|
|
- `PLUGIN_API_VERSION` — embed as `apiVersion` in your manifest.
|
|
- `validateManifest(json)` — the manifest rules the server loader uses.
|
|
- `createMockHost(opts)` (from `trek-plugin-sdk/testing`).
|
|
|
|
## Commands
|
|
|
|
Run any of these with `npx trek-plugin-sdk <command>` (or the short `trek-plugin`
|
|
bin if you install the package):
|
|
|
|
- `create [name] [--type t] [--interactive]` — scaffold a plugin; a wizard if you omit the name.
|
|
- `dev [dir] [--port 4317]` — run locally with a real request loop, SQLite `db:own`, and hot reload.
|
|
- `validate [dir]` — manifest + layout checks (a subset of registry CI, offline).
|
|
- `pack [dir] [--out plugin.zip] [--json]` — build the artifact, print `sha256` + `size`.
|
|
- `keygen [--key file]` — create an Ed25519 signing key.
|
|
- `sign [zip] [--key file]` — print a signature + public key for an artifact.
|
|
- `entry --repo o/n --tag vX [--merge f] [--sign [key]] [--out f]` — emit the registry entry JSON.
|
|
- `preflight --repo o/n --tag vX` (or `--entry f`) — run the registry CI checks locally, over the network.
|
|
- `submit --repo o/n --tag vX [--sign [key]] [--draft]` — open the registry PR for you.
|
|
- `release [dir] --repo o/n --tag vX [--sign [key]] [--merge f]` — pack → GitHub release → entry, in one go.
|
|
|
|
The SDK tooling in this repo is MIT. Your plugin is your own code under your own license.
|