本指南面向基于之前 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。
变更:沙盒插件使用 satisfies SandboxedPlugin 定义
早期版本将插件的钩子和路由封装在从 emdash 导入的 definePlugin() 中,每个处理程序的参数都需要手动标注类型。
沙盒插件现在是一个用 satisfies SandboxedPlugin 标注的裸默认导出。该类型来自 emdash/plugin,一个纯类型入口点,打包器会将其擦除。TypeScript 从钩子或路由名称推断每个处理程序的 event 和 ctx,因此处理程序参数不需要标注。
我应该怎么做?
对插件的源文件进行四处更改。替换导入:
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.ts 加 emdash-plugin.jsonc
早期版本将插件拆分为两个文件:src/index.ts 返回一个 PluginDescriptor(id、version、capabilities、storage、entrypoint),src/sandbox-entry.ts 包含钩子和路由。
插件现在是一个运行时文件 src/plugin.ts(钩子和路由),加上一个手动编辑的清单 emdash-plugin.jsonc(身份和信任契约)。entrypoint 和 format 字段已移除;构建会自动连接它们。
我应该怎么做?
使用上述形式将钩子和路由移入 src/plugin.ts。将描述符的元数据移入 package.json 旁边的 emdash-plugin.jsonc。描述符 id 变成清单 slug;capabilities、allowedHosts 和 storage 保持其形式;version 从 package.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.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 达到相同目的。沙盒插件的默认导出已经通过其 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],
}),
],
});
如果您的插件之前通过工厂函数接受配置,该配置现在移到管理 UI 的插件设置中。在运行时通过 ctx.kv 或 settings 读取。参见设置。