迁移到插件 CLI

本页内容

本指南适用于基于旧版 definePlugin() 形式编写的沙盒插件作者。按顺序处理这些破坏性变更。它们都不会改变您的钩子或路由在运行时的行为方式;它们改变的是插件的声明、构建和发布方式。

有关每个包中的完整变更列表,请参阅 EmDash 更新日志

破坏性变更

重命名:@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。每个子命令保持其名称(bundlepublishloginwhoamiswitchvalidate),并添加了 initbuilddev。参见插件 CLI

变更:沙盒插件使用 satisfies SandboxedPlugin 定义

早期版本将插件的钩子和路由包装在从 emdash 导入的 definePlugin() 中,每个处理器的参数都需要手动注解。

沙盒插件现在是一个用 satisfies SandboxedPlugin 注解的纯默认导出。类型来自 emdash/plugin,这是一个仅类型的入口点,打包器会将其删除。TypeScript 从钩子或路由名称推断每个处理器的 eventctx,因此处理器参数不需要注解。

我应该怎么做?

对插件的源文件进行四项更改。替换导入:

import { definePlugin, type ContentHookEvent, type PluginContext } from "emdash";
import type { SandboxedPlugin } from "emdash/plugin";

definePlugin() 包装器替换为纯对象和 satisfies 注解:

export default definePlugin({ /* hooks, routes */ });
export default { /* hooks, routes */ } satisfies SandboxedPlugin;

从每个处理器中删除参数注解:

handler: async (event: ContentHookEvent, ctx: PluginContext) => {
handler: async (event, ctx) => {

结果是一个默认导出的对象:

import type { SandboxedPlugin } from "emdash/plugin";

export default {
	hooks: {
		"content:beforeSave": {
			handler: async (event, ctx) => {
				return event.content;
			},
		},
	},
} satisfies SandboxedPlugin;

要在辅助函数中命名事件类型,从 emdash/plugin 导入:

import type { ContentHookEvent, PluginContext } from "emdash/plugin";

处理器的 event 始终是该钩子的规范类型。使用更窄的接口注解处理器不再通过类型检查。使用 typeof 检查或守卫在运行时验证您依赖的任何字段,这是处理来自类型系统外部数据的正确方法。

变更:插件是一个 src/plugin.tsemdash-plugin.jsonc

早期版本将插件拆分为两个文件:src/index.ts 返回一个 PluginDescriptor(id、version、capabilities、storage、entrypoint),src/sandbox-entry.ts 包含钩子和路由。

插件现在是一个运行时文件 src/plugin.ts(钩子和路由)和一个手动编辑的清单 emdash-plugin.jsonc(身份和信任合约)。entrypointformat 字段已消失;构建会连接它们。

我应该怎么做?

使用上述形式将钩子和路由移动到 src/plugin.ts。将描述符的元数据移动到 package.json 旁边的 emdash-plugin.jsonc。描述符 id 变成清单 slugcapabilitiesallowedHostsstorage 保持其形式;versionpackage.json 读取,因此省略它。

以下示例显示了声明一个存储集合的描述符的清单等效项:

{
	"$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": "[email protected]" },

	"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 脚本构建两个源文件。

emdash-plugin build 读取 emdash-plugin.jsoncsrc/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 导出 StandardPluginDefinitionStandardHookHandlerStandardHookEntryStandardRouteHandlerStandardRouteEntry 和函数 isStandardPluginDefinition

这些已被移除。它们是旧版 definePlugin 形式的辅助别名。

我应该怎么做?

使用 emdash/plugin 中的 SandboxedPlugin 实现相同目的。沙盒插件的默认导出已经通过其 satisfies SandboxedPlugin 注解进行了类型化,因此没有 isStandardPluginDefinition 的替代品;如果需要,通过结构({ hooks?, routes? })识别插件。

重命名:运行时 SandboxedPlugin 类型现在是 SandboxedPluginInstance

这仅影响自定义 SandboxRunner 的作者,例如 @emdash-cms/cloudflare。大多数插件作者可以跳过此部分。

emdash 中的 SandboxedPlugin 现在指的是面向作者的源形式。SandboxRunner.load 返回的运行时句柄是 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 或 settings 读取它。参见设置

下一步