迁移到插件 CLI

本页内容

本指南面向基于之前 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。每个子命令保持其名称(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/pluginSandboxedPlugin 达到相同目的。沙盒插件的默认导出已经通过其 satisfies SandboxedPlugin 标注进行了类型化,因此 isStandardPluginDefinition 没有替代品;如果需要,通过其结构({ hooks?, routes? })识别插件。

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

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

来自 emdashSandboxedPlugin 现在指的是面向作者的源形式。由 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 读取。参见设置

接下来阅读