From 39f27ef55da1b926c3c926c8170c7f35c3a2a2b4 Mon Sep 17 00:00:00 2001 From: Maurice Date: Sat, 4 Jul 2026 14:44:24 +0200 Subject: [PATCH] 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 ` 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 `, the invocation that actually resolves. --- .github/workflows/publish-plugin-sdk.yml | 30 ++++++++++++++++++++++++ plugin-sdk/LICENSE | 21 +++++++++++++++++ plugin-sdk/README.md | 12 +++++----- plugin-sdk/package.json | 14 ++++++++--- plugin-sdk/src/cli/trek-plugin.ts | 10 ++++++-- wiki/Plugin-Development.md | 2 +- wiki/Plugin-Permissions.md | 2 +- wiki/Plugin-Publishing.md | 22 ++++++++--------- wiki/Plugins.md | 2 +- 9 files changed, 90 insertions(+), 25 deletions(-) create mode 100644 .github/workflows/publish-plugin-sdk.yml create mode 100644 plugin-sdk/LICENSE diff --git a/.github/workflows/publish-plugin-sdk.yml b/.github/workflows/publish-plugin-sdk.yml new file mode 100644 index 000000000..5d2e2393c --- /dev/null +++ b/.github/workflows/publish-plugin-sdk.yml @@ -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 }} diff --git a/plugin-sdk/LICENSE b/plugin-sdk/LICENSE new file mode 100644 index 000000000..7f40f0bf4 --- /dev/null +++ b/plugin-sdk/LICENSE @@ -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. diff --git a/plugin-sdk/README.md b/plugin-sdk/README.md index 342975044..f51b781e3 100644 --- a/plugin-sdk/README.md +++ b/plugin-sdk/README.md @@ -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/.json`. diff --git a/plugin-sdk/package.json b/plugin-sdk/package.json index dc98a63ce..998ae6711 100644 --- a/plugin-sdk/package.json +++ b/plugin-sdk/package.json @@ -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", diff --git a/plugin-sdk/src/cli/trek-plugin.ts b/plugin-sdk/src/cli/trek-plugin.ts index 8a2cab05f..4d0c1b7dd 100644 --- a/plugin-sdk/src/cli/trek-plugin.ts +++ b/plugin-sdk/src/cli/trek-plugin.ts @@ -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 [...]'); + console.error('usage: trek-plugin [...]'); process.exit(2); } } catch (e) { diff --git a/wiki/Plugin-Development.md b/wiki/Plugin-Development.md index 6437a424f..25c59ff3d 100644 --- a/wiki/Plugin-Development.md +++ b/wiki/Plugin-Development.md @@ -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 ``` diff --git a/wiki/Plugin-Permissions.md b/wiki/Plugin-Permissions.md index 3e3af0a8f..a56815b16 100644 --- a/wiki/Plugin-Permissions.md +++ b/wiki/Plugin-Permissions.md @@ -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 `. The full submission +size, or commit sha. Run it with `npx trek-plugin-sdk `. The full submission flow is in [[Publishing a Plugin|Plugin-Publishing]]. | Command | What it does | diff --git a/wiki/Plugin-Publishing.md b/wiki/Plugin-Publishing.md index 193a06713..028e2f5a2 100644 --- a/wiki/Plugin-Publishing.md +++ b/wiki/Plugin-Publishing.md @@ -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-`). `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 ``` diff --git a/wiki/Plugins.md b/wiki/Plugins.md index 1a20d26bd..7e7a14e0a 100644 --- a/wiki/Plugins.md +++ b/wiki/Plugins.md @@ -151,7 +151,7 @@ registry entry, so you never hand-compute a SHA-256 or hand-write registry JSON: | `trek-plugin entry --repo --tag [--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 --tag ` | 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