プラグインCLIへの移行
このページで分かること
- CLIのパッケージ名の変更(
@emdash-cms/registry-cliから@emdash-cms/plugin-cliへ)と、権限名の変更(read:contentからcontent:readなど) SandboxedPlugin型の注釈、src/plugin.tsとemdash-plugin.jsoncの2ファイルの構成、emdash-plugin buildによるビルドへの変更- 削除された型、サンドボックスランナーの作者向けの変更、利用者への案内、移行後の確認
このページの目次
このガイドは、以前の definePlugin() の形で書かれたサンドボックス型プラグインの作者向けです。破壊的変更を順番に進めます。どの変更も、フックやルートの実行時の動作は変えません。変わるのは、プラグインの宣言、ビルド、公開の方法です。
各パッケージの変更の一覧は、リリースページにあるそのパッケージの項目を参照してください。
破壊的変更
名前の変更:@emdash-cms/registry-cli から @emdash-cms/plugin-cli へ
以前のリリースでは、CLIは @emdash-cms/registry-cli として提供され、実行ファイルは emdash-registry でした。
現在のパッケージは @emdash-cms/plugin-cli で、実行ファイルは emdash-plugin です。古いパッケージは公開されなくなりました。
対応方法
依存パッケージを置き換えます。
pnpm remove @emdash-cms/registry-cli
pnpm add -D @emdash-cms/plugin-cli
emdash-registry を呼び出しているすべての箇所を emdash-plugin に置き換えます。サブコマンドの名前(bundle、publish、login、whoami、switch、validate)はすべてそのままで、init、build、dev が追加されています。プラグインCLIを参照してください。
名前の変更:リソースを先に書く権限名
以前のマニフェストでは、read:content や network:fetch のような権限名を使っていました。作成時のマニフェストは現在の名前だけを受け付けます。ただし、互換期間中は、公開済みのバンドルにある古い名前をランタイムが引き続き正規化します。
対応方法
マニフェストにある古い名前をすべて置き換えます。
| 以前の名前 | 現在の名前 |
|---|---|
network:fetch |
network:request |
network:fetch:any |
network:request:unrestricted |
read:content |
content:read |
write:content |
content:write |
read:media |
media:read |
write:media |
media:write |
read:users |
users:read |
email:provide |
hooks.email-transport:register |
email:intercept |
hooks.email-events:register |
page:inject |
hooks.page-fragments:register |
network:request は、空でない allowedHosts の一覧と組み合わせて使います。network:request:unrestricted は、運営者が実行時に送信先を選ぶ場合にだけ、空の一覧と組み合わせて使います。現在の権限とネットワークの規則は、権限(Capabilities)とセキュリティで説明しています。
やさしい解説
生成AIに聞くと、read:content のような古い権限名や、@emdash-cms/registry-cli という古いパッケージ名を使ったコードが返ってくることがあります。これはこのページで説明している変更より前の書き方です。現在は content:read のように「対象:操作」の順で書き、CLIは @emdash-cms/plugin-cli(コマンド名は emdash-plugin)を使います。
変更:サンドボックス型プラグインでの明示的な SandboxedPlugin の注釈
以前のリリースでは、emdash からインポートした definePlugin() でプラグインのフックとルートを包み、各ハンドラーの引数には手作業で型注釈を付けていました。
サンドボックス型プラグインは、定義を SandboxedPlugin 型の定数に代入し、その定数をデフォルトエクスポートします。この型は emdash/plugin から取得します。emdash/plugin は型専用のエントリーポイントで、バンドラーが消去します。TypeScriptは、フックやルートの名前から各ハンドラーの event と ctx を推論するため、ハンドラーの引数に注釈は不要です。明示的な注釈があることで、パッケージマネージャーが分離されたレイアウトを使う場合でも、生成される型宣言の移植性が保たれます。
対応方法
プラグインのソースファイルに4つの変更を加えます。インポートを置き換えます。
import { definePlugin, type ContentHookEvent, type PluginContext } from "emdash";
import type { SandboxedPlugin } from "emdash/plugin";
definePlugin() による包み込みを、型を明示した定数に置き換えます。
export default definePlugin({ /* hooks, routes */ });
const plugin: SandboxedPlugin = { /* hooks, routes */ };
export default plugin;
すべてのハンドラーから引数の注釈を取り除きます。
handler: async (event: ContentHookEvent, ctx: PluginContext) => {
handler: async (event, ctx) => {
結果は、デフォルトエクスポートされた1つのオブジェクトになります。
import type { SandboxedPlugin } from "emdash/plugin";
const plugin: SandboxedPlugin = {
hooks: {
"content:beforeSave": {
handler: async (event, ctx) => {
return event.content;
},
},
},
};
export default plugin;
ヘルパー関数でイベントの型名を使うには、emdash/plugin からインポートします。
import type { ContentHookEvent, PluginContext } from "emdash/plugin";
ハンドラーの event は、常にそのフックの正規の型になります。より狭いインターフェースでハンドラーに注釈を付けると、型チェックが通らなくなりました。依存するフィールドは、実行時に typeof による確認やガードで検証します。これは、型システムの外から来るデータに対する正しい方法です。
変更:1つの src/plugin.ts と emdash-plugin.jsonc によるプラグインの構成
以前のリリースでは、プラグインを2つのファイルに分けていました。src/index.ts が PluginDescriptor(ID、バージョン、権限、ストレージ、エントリーポイント)を返し、src/sandbox-entry.ts がフックとルートを持っていました。
現在のプラグインは、1つの実行時のファイル src/plugin.ts(フックとルート)と、手で編集する1つのマニフェスト emdash-plugin.jsonc(IDと信頼に関する取り決め)で構成します。entrypoint と format のフィールドはなくなりました。これらはビルドが設定します。
対応方法
上記の形を使って、フックとルートを src/plugin.ts に移します。ディスクリプターのメタデータは、package.json の隣にある emdash-plugin.jsonc に移します。ディスクリプターの id はマニフェストの slug になります。capabilities、allowedHosts、storage は同じ形のままです。version は package.json から読み取られるため、書きません。
次の例は、ストレージのコレクションを1つ宣言していたディスクリプターを、マニフェストに置き換えたものです。
{
"$schema": "./node_modules/@emdash-cms/plugin-cli/schemas/emdash-plugin.schema.json",
"slug": "plugin-hello",
"publisher": "did:plc:abc123def456",
"license": "MIT",
"author": { "name": "Jane Doe", "url": "https://example.com" },
"security": { "email": "security@example.com" },
"capabilities": [],
"allowedHosts": [],
"storage": { "events": { "indexes": ["timestamp"] } }
}
すべてのフィールドはプラグインのマニフェストを、publisher フィールドについては公開者の固定を参照してください。
package.json では、"./sandbox" のエクスポートを、ビルドされた実行時のファイルに向けます。
"./sandbox": "./dist/sandbox-entry.mjs"
"./sandbox": "./dist/plugin.mjs"
マニフェストがパッケージに含まれるように、files に追加します。
"files": ["dist"]
"files": ["dist", "emdash-plugin.jsonc"]
変更:emdash-plugin build によるビルド
以前のリリースでは、手書きの tsdown のスクリプトで2つのソースファイルをビルドしていました。
emdash-plugin build は、emdash-plugin.jsonc と src/plugin.ts を読み取り、dist/ に成果物を出力します。emdash-plugin dev は変更を監視して再ビルドします。
対応方法
ビルドのスクリプトを置き換え、監視用のスクリプトを追加します。
"scripts": {
"build": "tsdown src/index.ts src/sandbox-entry.ts --format esm --dts --clean"
"build": "emdash-plugin build",
"dev": "emdash-plugin dev"
}
そのあと、検証してビルドします。
emdash-plugin validate
emdash-plugin build
削除:emdash からの標準形式の型と関数のエクスポート
以前のリリースでは、emdash から StandardPluginDefinition、StandardHookHandler、StandardHookEntry、StandardRouteHandler、StandardRouteEntry と、関数 isStandardPluginDefinition をエクスポートしていました。
これらは削除されました。以前の definePlugin の形のための補助的な別名でした。
対応方法
同じ目的には、emdash/plugin の SandboxedPlugin を使います。サンドボックス型プラグインがエクスポートする定義は、SandboxedPlugin の注釈によってすでに型が付いているため、isStandardPluginDefinition の代わりになるものはありません。必要な場合は、構造({ hooks?, routes? })でプラグインを識別します。
名前の変更:サンドボックスランナーのハンドルでの SandboxedPluginInstance の使用
この変更が影響するのは、@emdash-cms/cloudflare のような独自の SandboxRunner の作者だけです。ほとんどのプラグインの作者は読み飛ばして構いません。
作者向けの SandboxedPlugin 型は、型専用の emdash/plugin エントリーポイントからだけ利用できます。SandboxRunner.load が返す実行時のハンドルは、emdash から SandboxedPluginInstance としてエクスポートされています。
対応方法
サンドボックスランナーの型付けや、実行時のプラグインのハンドルを保持するために emdash から SandboxedPlugin をインポートしている場合は、インポートを SandboxedPluginInstance に変更します。
import type { SandboxedPlugin } from "emdash";
import type { SandboxedPluginInstance } from "emdash";
利用者への案内
プラグインをインストールしているサイトも、インポートを変更する必要があります。利用者に新しい形を案内します。波括弧と () を取り除きます。
import { helloPlugin } from "@my-org/plugin-hello";
import hello from "@my-org/plugin-hello";
export default defineConfig({
integrations: [
emdash({
sandboxed: [helloPlugin()],
sandboxed: [hello],
}),
],
});
プラグインがファクトリーを通じて設定を受け取っていた場合は、その設定を管理画面の設定ページに移し、ctx.kv から読み取ります。サンドボックス型プラグインのディスクリプターは単純なオブジェクトで、コンストラクターのオプションを受け取れません。設定を参照してください。
移行したプラグインの確認
プラグインのテストを実行し、作成時のマニフェストを検証して、ビルドとバンドルの確認をすべて実行します。
pnpm test
pnpm exec emdash-plugin validate
pnpm exec emdash-plugin build
pnpm exec emdash-plugin bundle --validate-only
そのあと、ローカルのパッケージを開発用のサイトにインストールし、移行したフックとルートを1つずつ動かします。ビルドで確認できるのはフックとルートの名前と形だけです。ルートが意図したデータを返すことや、フックがコンテンツを正しく保つことまでは確認できません。