Este guia é para autores de plugins sandboxed escritos contra a forma anterior de definePlugin(). Percorra as alterações incompatíveis em ordem. Nenhuma muda o comportamento dos hooks ou rotas em runtime; mudam como o plugin é declarado, construído e publicado.
Para a lista completa de alterações em cada pacote, consulte a entrada na página de releases.
Alterações incompatíveis
Renomeado: @emdash-cms/registry-cli agora é @emdash-cms/plugin-cli
Releases anteriores distribuíam a CLI como @emdash-cms/registry-cli, com um binário emdash-registry.
O pacote agora é @emdash-cms/plugin-cli e o binário é emdash-plugin. O pacote antigo não é mais publicado.
O que devo fazer?
Substitua a dependência:
pnpm remove @emdash-cms/registry-cli
pnpm add -D @emdash-cms/plugin-cli
Substitua emdash-registry por emdash-plugin em todos os lugares onde o chamar. Cada subcomando mantém o nome (bundle, publish, login, whoami, switch, validate), e init, build e dev são adicionados. Veja The plugin CLI.
Renomeado: nomes de capabilities usam ortografia resource-first
Manifestos anteriores usavam nomes de capability como read:content e network:fetch. O manifesto de authoring aceita apenas os nomes atuais, embora o runtime ainda normalize nomes legacy em bundles já publicados durante a janela de compatibilidade.
O que devo fazer?
Substitua cada nome legacy no manifesto:
| Nome anterior | Nome atual |
|---|---|
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 |
Use network:request com uma lista allowedHosts não vazia. Use network:request:unrestricted com uma lista vazia somente quando um operador escolher o destino em runtime. Capabilities and security explica as permissões e regras de rede atuais.
Alterado: plugins sandboxed usam uma anotação explícita SandboxedPlugin
Releases anteriores envolviam os hooks e rotas do plugin em definePlugin() importado de emdash, com os parâmetros de cada handler anotados à mão.
Um plugin sandboxed atribui sua definição a uma constante tipada como SandboxedPlugin e exporta essa constante como default. Importe o tipo de emdash/plugin com import type; o bundler apaga essa importação. O mesmo subcaminho também exporta os helpers de runtime leves pluginRoute() e pluginResponse(). O TypeScript infere o event e o ctx de cada handler a partir do nome do hook ou rota, portanto os parâmetros do handler não precisam de anotações. A anotação explícita também mantém declarações geradas portáteis sob layouts isolados do gerenciador de pacotes.
O que devo fazer?
Faça quatro alterações no arquivo-fonte do plugin. Substitua a importação:
import { definePlugin, type ContentHookEvent, type PluginContext } from "emdash";
import type { SandboxedPlugin } from "emdash/plugin";
Substitua o wrapper definePlugin() por uma constante tipada explicitamente:
export default definePlugin({ /* hooks, routes */ });
const plugin: SandboxedPlugin = { /* hooks, routes */ };
export default plugin;
Remova as anotações de parâmetro de cada handler:
handler: async (event: ContentHookEvent, ctx: PluginContext) => {
handler: async (event, ctx) => {
O resultado é um objeto exportado por padrão:
import type { SandboxedPlugin } from "emdash/plugin";
const plugin: SandboxedPlugin = {
hooks: {
"content:beforeSave": {
handler: async (event, ctx) => {
return event.content;
},
},
},
};
export default plugin;
Para nomear um tipo de evento em uma função auxiliar, importe-o de emdash/plugin:
import type { ContentHookEvent, PluginContext } from "emdash/plugin";
O event de um handler é sempre o tipo canônico daquele hook. Anotar um handler com uma interface mais estreita não passa mais no type-check. Valide em runtime quaisquer campos de que dependa com uma verificação typeof ou um guard, a abordagem correta para dados que vêm de fora do sistema de tipos.
Alterado: um plugin é um src/plugin.ts mais emdash-plugin.jsonc
Releases anteriores dividiam um plugin em dois arquivos: src/index.ts retornava um PluginDescriptor (id, version, capabilities, storage, entrypoint), e src/sandbox-entry.ts continha os hooks e rotas.
Um plugin agora é um arquivo de runtime, src/plugin.ts (hooks e rotas), e um manifesto editado à mão, emdash-plugin.jsonc (identidade e o contrato de confiança). Os campos entrypoint e format sumiram; o build os conecta.
O que devo fazer?
Mova os hooks e rotas para src/plugin.ts usando a forma acima. Mova os metadados do descriptor para emdash-plugin.jsonc ao lado de package.json. O id do descriptor vira o slug do manifesto; capabilities, allowedHosts e storage mantêm a forma; version é lida de package.json, então omita.
O exemplo a seguir mostra o equivalente em manifesto de um descriptor que declarava uma collection de storage:
{
"$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"] } }
}
Veja The plugin manifest para cada campo, e Publisher pinning para o campo publisher.
Em package.json, aponte o export "./sandbox" para o arquivo de runtime construído:
"./sandbox": "./dist/sandbox-entry.mjs"
"./sandbox": "./dist/plugin.mjs"
Adicione o manifesto a files para que seja distribuído com o pacote:
"files": ["dist"]
"files": ["dist", "emdash-plugin.jsonc"]
Alterado: construir com emdash-plugin build
Releases anteriores construíam os dois arquivos-fonte com um script tsdown escrito à mão.
emdash-plugin build lê emdash-plugin.jsonc e src/plugin.ts e emite os artefatos dist/. emdash-plugin dev observa e reconstrói.
O que devo fazer?
Substitua o script de build e adicione um script de watch:
"scripts": {
"build": "tsdown src/index.ts src/sandbox-entry.ts --format esm --dts --clean"
"build": "emdash-plugin build",
"dev": "emdash-plugin dev"
}
Em seguida, valide e construa:
emdash-plugin validate
emdash-plugin build
Removido: exports de tipos e funções de formato padrão de emdash
Releases anteriores exportavam StandardPluginDefinition, StandardHookHandler, StandardHookEntry, StandardRouteHandler, StandardRouteEntry e a função isStandardPluginDefinition de emdash.
Eles foram removidos. Eram aliases auxiliares para a forma anterior de definePlugin.
O que devo fazer?
Use SandboxedPlugin de emdash/plugin para o mesmo propósito. A definição exportada de um plugin sandboxed já é tipada pela anotação SandboxedPlugin, então não há substituto para isStandardPluginDefinition; identifique um plugin pela estrutura ({ hooks?, routes? }) se precisar.
Renomeado: handles do sandbox-runner usam SandboxedPluginInstance
Isso afeta apenas autores de um SandboxRunner personalizado, como @emdash-cms/cloudflare. A maioria dos autores de plugins pode pular.
O tipo voltado ao autor SandboxedPlugin está disponível no ponto de entrada de authoring emdash/plugin. O handle de runtime retornado por SandboxRunner.load é exportado de emdash como SandboxedPluginInstance.
O que devo fazer?
Se você importa SandboxedPlugin de emdash para tipar um sandbox runner ou manter handles de plugins em runtime, mude a importação para SandboxedPluginInstance:
import type { SandboxedPlugin } from "emdash";
import type { SandboxedPluginInstance } from "emdash";
Informe seus usuários
Sites que instalam seu plugin também precisam mudar a importação. Aponte-os para a nova forma: remova as chaves e o ().
import { helloPlugin } from "@my-org/plugin-hello";
import hello from "@my-org/plugin-hello";
export default defineConfig({
integrations: [
emdash({
sandboxed: [helloPlugin()],
sandboxed: [hello],
}),
],
});
Se seu plugin aceitava configuração pela factory, mova essa configuração para uma página de configurações de administração e leia de ctx.settings. Descriptors de plugins sandboxed são objetos plain e não podem receber opções de construtor. Veja Settings.
Verificar o plugin migrado
Execute os testes do plugin, valide o manifesto de authoring e execute as verificações completas de build e bundle:
pnpm test
pnpm exec emdash-plugin validate
pnpm exec emdash-plugin build
pnpm exec emdash-plugin bundle --validate-only
Em seguida, instale o pacote local em um site de desenvolvimento e exercite cada hook e rota migrados. O build pode confirmar nomes e formas, mas não pode confirmar que uma rota retorna os dados pretendidos ou que um hook preserva o conteúdo corretamente.