chore(plugin-sdk): make it npm-publishable so npx resolves for authors

The docs told authors to run `npx create-trek-plugin` / `npx trek-plugin`,
but nothing published under those names, so npx couldn't resolve them.

- Ship one package, `trek-plugin-sdk`, with a bin that matches the package
  name (`trek-plugin-sdk`) so `npx trek-plugin-sdk <command>` resolves with
  zero install. The dispatcher gained a `create` subcommand, so every step
  (create/validate/pack/entry/release) runs through that one entry point.
  The short `trek-plugin` / `create-trek-plugin` bins still work once
  installed.
- Package hardening for publish: repository+directory (monorepo subdir),
  homepage/bugs/author/engines, publishConfig public, a prepublishOnly that
  builds + tests, and a LICENSE file.
- A publish workflow: pushing a `plugin-sdk-v*` tag builds and publishes with
  the NPM_TOKEN repo secret.
- Docs (SDK README + the four wiki pages) now use `npx trek-plugin-sdk <cmd>`,
  the invocation that actually resolves.
This commit is contained in:
Maurice
2026-07-04 14:44:24 +02:00
parent ab0a67aa4c
commit b647de9813
9 changed files with 90 additions and 25 deletions
+30
View File
@@ -0,0 +1,30 @@
name: Publish plugin-sdk to npm
# Publishes trek-plugin-sdk when a tag like `plugin-sdk-v1.2.0` is pushed.
# One-time setup: add an npm automation token as the repo secret NPM_TOKEN.
# The package's prepublishOnly hook builds + tests before publishing.
on:
push:
tags:
- 'plugin-sdk-v*'
permissions:
contents: read
jobs:
publish:
runs-on: ubuntu-latest
defaults:
run:
working-directory: plugin-sdk
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 mauriceboe
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.
+6 -6
View File
@@ -5,10 +5,10 @@ The SDK for building [TREK](https://github.com/mauriceboe/TREK) plugins.
## Scaffold a plugin
```bash
npx create-trek-plugin my-plugin --type integration|page|widget
npx trek-plugin-sdk create my-plugin --type integration|page|widget
cd my-plugin
# build server/index.js, fill in the README
npx trek-plugin validate .
npx trek-plugin-sdk validate .
```
## Write a plugin
@@ -51,14 +51,14 @@ The SDK does the fiddly parts (zipping, hashing, sizing, writing the registry
entry) so you don't compute anything by hand:
```bash
npx trek-plugin validate # manifest + layout OK?
npx trek-plugin pack # -> plugin.zip, prints sha256 + size
npx trek-plugin-sdk validate # manifest + layout OK?
npx trek-plugin-sdk pack # -> plugin.zip, prints sha256 + size
gh release create v1.0.0 plugin.zip # attach the artifact to your tag
npx trek-plugin entry --repo you/repo --tag v1.0.0
npx trek-plugin-sdk entry --repo you/repo --tag v1.0.0
# -> the ready-to-PR registry entry JSON
```
Or in one step: `npx trek-plugin release --repo you/repo --tag v1.0.0` packs,
Or in one step: `npx trek-plugin-sdk release --repo you/repo --tag v1.0.0` packs,
creates the GitHub release, and prints the entry. Then paste the entry into a PR
against [TREK-Plugins](https://github.com/mauriceboe/TREK-Plugins) as
`registry/plugins/<id>.json`.
+11 -3
View File
@@ -4,6 +4,12 @@
"description": "SDK for building TREK plugins: types, definePlugin, a mock host, manifest validation, and the create-trek-plugin / trek-plugin CLIs.",
"type": "module",
"license": "MIT",
"author": "mauriceboe",
"homepage": "https://github.com/mauriceboe/TREK/wiki/Plugin-Development",
"repository": { "type": "git", "url": "git+https://github.com/mauriceboe/TREK.git", "directory": "plugin-sdk" },
"bugs": { "url": "https://github.com/mauriceboe/TREK/issues" },
"engines": { "node": ">=18" },
"publishConfig": { "access": "public" },
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
@@ -11,14 +17,16 @@
"./testing": { "types": "./dist/mock-host.d.ts", "import": "./dist/mock-host.js" }
},
"bin": {
"create-trek-plugin": "./dist/cli/create.js",
"trek-plugin": "./dist/cli/trek-plugin.js"
"trek-plugin-sdk": "./dist/cli/trek-plugin.js",
"trek-plugin": "./dist/cli/trek-plugin.js",
"create-trek-plugin": "./dist/cli/create.js"
},
"files": ["dist"],
"scripts": {
"build": "tsc -p tsconfig.json",
"typecheck": "tsc -p tsconfig.json --noEmit",
"test": "vitest run"
"test": "vitest run",
"prepublishOnly": "npm run build && npm test"
},
"devDependencies": {
"@types/node": "^22.0.0",
+8 -2
View File
@@ -17,6 +17,7 @@ import { execFileSync } from 'node:child_process';
import { validatePluginDir } from './validate.js';
import { packPluginDir } from './pack.js';
import { buildEntry } from './entry.js';
import { scaffold } from './create.js';
const [cmd, ...args] = process.argv.slice(2);
@@ -41,7 +42,12 @@ function fail(msg: string): never {
const { flags, pos } = parse(args);
try {
if (cmd === 'validate') {
if (cmd === 'create') {
const name = pos[0];
if (!name) fail('create needs a plugin name, e.g. `create my-plugin --type widget`');
scaffold(name, flags.type || 'integration', process.cwd());
console.log(`Created ${name}/ — build server/index.js, add docs/screenshot.png, fill in the README, then \`trek-plugin validate ${name}\`.`);
} else if (cmd === 'validate') {
const r = validatePluginDir(pos[0] || '.');
for (const w of r.warnings) console.warn('warning: ' + w);
if (!r.ok) { for (const e of r.errors) console.error('error: ' + e); process.exit(1); }
@@ -84,7 +90,7 @@ try {
console.error('\nRegistry entry (add as registry/plugins/' + entry.id + '.json in a TREK-Plugins PR):\n');
process.stdout.write(JSON.stringify(entry, null, 2) + '\n');
} else {
console.error('usage: trek-plugin <validate|pack|entry|release> [...]');
console.error('usage: trek-plugin <create|validate|pack|entry|release> [...]');
process.exit(2);
}
} catch (e) {
+1 -1
View File
@@ -9,7 +9,7 @@ child process** and reaches it only over RPC; the browser part runs in a
## Scaffold
```bash
npx create-trek-plugin my-plugin --type integration|page|widget
npx trek-plugin-sdk create my-plugin --type integration|page|widget
cd my-plugin
```
+1 -1
View File
@@ -72,7 +72,7 @@ is refused if it resolves to a loopback / private / link-local / metadata addres
The `trek-plugin-sdk` package ships a `trek-plugin` CLI that builds the release
artifact and the registry entry for you, so you never hand-compute a sha256,
size, or commit sha. Run it with `npx trek-plugin <command>`. The full submission
size, or commit sha. Run it with `npx trek-plugin-sdk <command>`. The full submission
flow is in [[Publishing a Plugin|Plugin-Publishing]].
| Command | What it does |
+11 -11
View File
@@ -11,10 +11,10 @@ the mechanical work — you rarely hand-type a hash, size, commit, or JSON field
## The short version
```bash
npx trek-plugin validate . # manifest + layout sanity
npx trek-plugin pack . # build plugin.zip, print sha256 + size
npx trek-plugin-sdk validate . # manifest + layout sanity
npx trek-plugin-sdk pack . # build plugin.zip, print sha256 + size
gh release create v1.0.0 plugin.zip --repo you/trek-plugin-flight-tracker
npx trek-plugin entry --repo you/trek-plugin-flight-tracker --tag v1.0.0 \
npx trek-plugin-sdk entry --repo you/trek-plugin-flight-tracker --tag v1.0.0 \
--out registry/plugins/flight-tracker.json # the ready-to-PR entry
```
@@ -28,7 +28,7 @@ Put your plugin in a **public GitHub repo** (convention: `trek-plugin-<id>`).
`create-trek-plugin` scaffolds the layout:
```bash
npx create-trek-plugin flight-tracker --type widget # integration | page | widget
npx trek-plugin-sdk create flight-tracker --type widget # integration | page | widget
```
A publishable plugin has, at the repo root:
@@ -42,7 +42,7 @@ A publishable plugin has, at the repo root:
## 2. Validate
```bash
npx trek-plugin validate .
npx trek-plugin-sdk validate .
```
`validate` runs the manifest checks plus a light layout/README sanity pass:
@@ -56,9 +56,9 @@ CI run but doesn't replace it.
## 3. Pack
```bash
npx trek-plugin pack . # writes ./plugin.zip
npx trek-plugin pack . --out dist.zip # custom output path
npx trek-plugin pack . --json # machine-readable result
npx trek-plugin-sdk pack . # writes ./plugin.zip
npx trek-plugin-sdk pack . --out dist.zip # custom output path
npx trek-plugin-sdk pack . --json # machine-readable result
```
`pack` validates first, then builds `plugin.zip` in the installer's exact layout
@@ -89,7 +89,7 @@ they aren't the installer layout and their bytes aren't stable.
## 5. Generate the registry entry
```bash
npx trek-plugin entry \
npx trek-plugin-sdk entry \
--repo you/trek-plugin-flight-tracker \
--tag v1.0.0 \
--out registry/plugins/flight-tracker.json
@@ -106,7 +106,7 @@ to name a differently-named release asset, `--merge` for updates (below), and
### One-shot: `release`
```bash
npx trek-plugin release . --repo you/trek-plugin-flight-tracker --tag v1.0.0
npx trek-plugin-sdk release . --repo you/trek-plugin-flight-tracker --tag v1.0.0
```
`release` does **pack → `gh release create` → entry** in one go and prints the
@@ -211,7 +211,7 @@ Bump `version` in the manifest, re-`pack`, cut a new `vX.Y.Z` release, then fold
the new version onto your existing entry with `--merge`:
```bash
npx trek-plugin entry --repo you/trek-plugin-flight-tracker --tag v1.1.0 \
npx trek-plugin-sdk entry --repo you/trek-plugin-flight-tracker --tag v1.1.0 \
--merge registry/plugins/flight-tracker.json \
--out registry/plugins/flight-tracker.json
```
+1 -1
View File
@@ -151,7 +151,7 @@ registry entry, so you never hand-compute a SHA-256 or hand-write registry JSON:
| `trek-plugin entry --repo <o/n> --tag <vX> [--zip z] [--merge entry.json] [--out f]` | Emits the registry entry — `commitSha`, `downloadUrl`, `sha256`, `size` and `minTrekVersion` (derived from the manifest `trek` range) all filled in. `--merge` prepends the new version onto an existing entry for updates. |
| `trek-plugin release [dir] --repo <o/n> --tag <vX>` | The one-shot: `pack` → create the GitHub release → print the entry. |
Run them via `npx trek-plugin …`. See [[Plugin Development|Plugin-Development]]
Run them via `npx trek-plugin-sdk …`. See [[Plugin Development|Plugin-Development]]
for the SDK and manifest, and [[Publishing a Plugin|Plugin-Publishing]] for the
registry PR flow. Publishing no longer reserves any namespaces — any unique slug
is fine — but an `id` stays bound to the GitHub owner who first registered it, so