Este guia é para autores de plugins sandboxed escritos contra a forma anterior de definePlugin(). Trabalhe as mudanças incompatíveis em ordem. Nenhuma delas altera como seus hooks ou rotas se comportam em tempo de execução; elas alteram como o plugin é declarado, construído e publicado.
Para a lista completa de mudanças em cada pacote, consulte o changelog do EmDash.
Mudanças incompatíveis
Renomeado: @emdash-cms/registry-cli agora é @emdash-cms/plugin-cli
Versões 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 você o chama. Cada subcomando mantém seu nome (bundle, publish, login, whoami, switch, validate), e init, build e dev são adicionados. Veja A CLI de plugins.
Alterado: plugins sandboxed são definidos com satisfies SandboxedPlugin
Versões anteriores envolviam os hooks e rotas do plugin em definePlugin() importado de emdash, com os parâmetros de cada manipulador anotados manualmente.
Um plugin sandboxed agora é uma exportação padrão simples anotada com satisfies SandboxedPlugin. O tipo vem de emdash/plugin, um ponto de entrada apenas de tipos que o bundler remove. TypeScript infere event e ctx de cada manipulador a partir do nome do hook ou rota, então os parâmetros do manipulador não precisam de anotações.
O que devo fazer?
Faça quatro mudanças 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 um objeto simples e uma anotação satisfies:
export default definePlugin({ /* hooks, routes */ });
export default { /* hooks, routes */ } satisfies SandboxedPlugin;
Remova as anotações de parâmetros de cada manipulador:
handler: async (event: ContentHookEvent, ctx: PluginContext) => {
handler: async (event, ctx) => {
O resultado é um único objeto exportado por padrão:
import type { SandboxedPlugin } from "emdash/plugin";
export default {
hooks: {
"content:beforeSave": {
handler: async (event, ctx) => {
return event.content;
},
},
},
} satisfies SandboxedPlugin;
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 manipulador é sempre o tipo canônico para esse hook. Anotar um manipulador com uma interface mais restrita não passa mais na verificação de tipos. Valide quaisquer campos dos quais você depende em tempo de execução com uma verificação typeof ou um guard, que é 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
Versões 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 tempo de execução, src/plugin.ts (hooks e rotas), e um manifesto editado manualmente, emdash-plugin.jsonc (identidade e contrato de confiança). Os campos entrypoint e format desapareceram; a construção os conecta.
O que devo fazer?
Mova os hooks e rotas para src/plugin.ts usando a forma acima. Mova os metadados do descritor para emdash-plugin.jsonc ao lado de package.json. O id do descritor se torna o slug do manifesto; capabilities, allowedHosts e storage mantêm sua forma; version é lido de package.json, então omita-o.
O exemplo a seguir mostra o equivalente em manifesto de um descritor que declarava uma coleção de armazenamento:
{
"$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"] } }
}
Veja O manifesto do plugin para todos os campos, e Fixação de publicador para o campo publisher.
Em package.json, aponte a exportação "./sandbox" para o arquivo de tempo de execução 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
Versões anteriores construíam os dois arquivos fonte com um script tsdown escrito manualmente.
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 construção e adicione um script de observação:
"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: exportações de tipos e funções de formato padrão de emdash
Versões anteriores exportavam StandardPluginDefinition, StandardHookHandler, StandardHookEntry, StandardRouteHandler, StandardRouteEntry e a função isStandardPluginDefinition de emdash.
Estes 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 exportação padrão de um plugin sandboxed já é tipada por sua anotação satisfies SandboxedPlugin, então não há substituição para isStandardPluginDefinition; identifique um plugin por sua estrutura ({ hooks?, routes? }) se necessário.
Renomeado: o tipo de tempo de execução SandboxedPlugin agora é SandboxedPluginInstance
Isso afeta apenas autores de um SandboxRunner personalizado, como @emdash-cms/cloudflare. A maioria dos autores de plugins pode pular isso.
SandboxedPlugin de emdash agora se refere à forma fonte orientada ao autor. O handle de tempo de execução retornado por SandboxRunner.load é SandboxedPluginInstance.
O que devo fazer?
Se você importa SandboxedPlugin de emdash para tipar um sandbox runner ou manter handles de plugin de tempo de execução, altere 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 alterar sua importação. Indique a eles a nova forma: remova as chaves e os ().
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 através de sua factory, essa configuração se move para as configurações de plugin da interface de administração. Leia-a em tempo de execução através de ctx.kv ou settings. Veja Configurações.