Questa guida è per gli autori di plugin sandboxed scritti contro la forma precedente di definePlugin(). Affronta i breaking change in ordine. Nessuno cambia il comportamento di hooks o route a runtime; cambiano come il plugin viene dichiarato, compilato e pubblicato.
Per l’elenco completo delle modifiche in ogni pacchetto, vedi la relativa voce nella pagina dei release.
Breaking change
Rinominato: @emdash-cms/registry-cli ora è @emdash-cms/plugin-cli
I release precedenti distribuivano la CLI come @emdash-cms/registry-cli, con un binario emdash-registry.
Il pacchetto ora è @emdash-cms/plugin-cli e il binario è emdash-plugin. Il pacchetto precedente non viene più pubblicato.
Cosa devo fare?
Sostituisci la dipendenza:
pnpm remove @emdash-cms/registry-cli
pnpm add -D @emdash-cms/plugin-cli
Sostituisci emdash-registry con emdash-plugin ovunque lo chiami. Ogni sottocomando mantiene il nome (bundle, publish, login, whoami, switch, validate), e vengono aggiunti init, build e dev. Vedi The plugin CLI.
Rinominato: i nomi delle capability usano l’ortografia resource-first
I manifest precedenti usavano nomi di capability come read:content e network:fetch. Il manifest di authoring accetta solo i nomi attuali, anche se il runtime normalizza ancora i nomi legacy nei bundle già pubblicati durante la finestra di compatibilità.
Cosa devo fare?
Sostituisci ogni nome legacy nel manifest:
| Nome precedente | Nome attuale |
|---|---|
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 |
Usa network:request con un elenco allowedHosts non vuoto. Usa network:request:unrestricted con un elenco vuoto solo quando un operatore sceglie la destinazione a runtime. Capabilities and security spiega i permessi e le regole di rete attuali.
Modificato: i plugin sandboxed usano un’annotazione esplicita SandboxedPlugin
I release precedenti avvolgevano hooks e route del plugin in definePlugin() importato da emdash, con i parametri di ogni handler annotati a mano.
Un plugin sandboxed assegna la sua definizione a una costante tipizzata SandboxedPlugin e esporta quella costante come default. Importa il tipo da emdash/plugin con import type; il bundler elimina quell’import. Lo stesso sottopercorso esporta anche gli helper runtime leggeri pluginRoute() e pluginResponse(). TypeScript inferisce event e ctx di ogni handler dal nome dell’hook o della route, quindi i parametri dell’handler non richiedono annotazioni. L’annotazione esplicita mantiene anche le dichiarazioni generate portabili sotto layout isolati del package manager.
Cosa devo fare?
Apporta quattro modifiche al file sorgente del plugin. Sostituisci l’import:
import { definePlugin, type ContentHookEvent, type PluginContext } from "emdash";
import type { SandboxedPlugin } from "emdash/plugin";
Sostituisci il wrapper definePlugin() con una costante tipizzata esplicitamente:
export default definePlugin({ /* hooks, routes */ });
const plugin: SandboxedPlugin = { /* hooks, routes */ };
export default plugin;
Rimuovi le annotazioni di parametro da ogni handler:
handler: async (event: ContentHookEvent, ctx: PluginContext) => {
handler: async (event, ctx) => {
Il risultato è un oggetto esportato di default:
import type { SandboxedPlugin } from "emdash/plugin";
const plugin: SandboxedPlugin = {
hooks: {
"content:beforeSave": {
handler: async (event, ctx) => {
return event.content;
},
},
},
};
export default plugin;
Per nominare un tipo di evento in una funzione helper, importalo da emdash/plugin:
import type { ContentHookEvent, PluginContext } from "emdash/plugin";
L’event di un handler è sempre il tipo canonico per quell’hook. Annotare un handler con un’interfaccia più stretta non supera più il type-check. Valida a runtime qualsiasi campo da cui dipendi con un controllo typeof o un guard, che è l’approccio corretto per dati provenienti dall’esterno del sistema di tipi.
Modificato: un plugin è un src/plugin.ts più emdash-plugin.jsonc
I release precedenti dividevano un plugin in due file: src/index.ts restituiva un PluginDescriptor (id, version, capabilities, storage, entrypoint), e src/sandbox-entry.ts conteneva hooks e route.
Un plugin è ora un file runtime, src/plugin.ts (hooks e route), e un manifest modificato a mano, emdash-plugin.jsonc (identità e contratto di fiducia). I campi entrypoint e format sono spariti; la build li collega.
Cosa devo fare?
Sposta hooks e route in src/plugin.ts usando la forma sopra. Sposta i metadati del descriptor in emdash-plugin.jsonc accanto a package.json. L’id del descriptor diventa lo slug del manifest; capabilities, allowedHosts e storage mantengono la forma; version viene letto da package.json, quindi omettilo.
L’esempio seguente mostra l’equivalente in manifest di un descriptor che dichiarava una collection di 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"] } }
}
Vedi The plugin manifest per ogni campo, e Publisher pinning per il campo publisher.
In package.json, punta l’export "./sandbox" al file runtime compilato:
"./sandbox": "./dist/sandbox-entry.mjs"
"./sandbox": "./dist/plugin.mjs"
Aggiungi il manifest a files così viene distribuito con il pacchetto:
"files": ["dist"]
"files": ["dist", "emdash-plugin.jsonc"]
Modificato: compilare con emdash-plugin build
I release precedenti compilavano i due file sorgente con uno script tsdown scritto a mano.
emdash-plugin build legge emdash-plugin.jsonc e src/plugin.ts e emette gli artefatti dist/. emdash-plugin dev osserva e ricompila.
Cosa devo fare?
Sostituisci lo script di build e aggiungi uno script di watch:
"scripts": {
"build": "tsdown src/index.ts src/sandbox-entry.ts --format esm --dts --clean"
"build": "emdash-plugin build",
"dev": "emdash-plugin dev"
}
Poi valida e compila:
emdash-plugin validate
emdash-plugin build
Rimosso: export di tipi e funzioni in formato standard da emdash
I release precedenti esportavano StandardPluginDefinition, StandardHookHandler, StandardHookEntry, StandardRouteHandler, StandardRouteEntry e la funzione isStandardPluginDefinition da emdash.
Sono rimossi. Erano alias di supporto per la forma precedente di definePlugin.
Cosa devo fare?
Usa SandboxedPlugin da emdash/plugin per lo stesso scopo. La definizione esportata di un plugin sandboxed è già tipizzata dalla sua annotazione SandboxedPlugin, quindi non c’è un sostituto per isStandardPluginDefinition; identifica un plugin dalla sua struttura ({ hooks?, routes? }) se ti serve.
Rinominato: gli handle del sandbox-runner usano SandboxedPluginInstance
Questo riguarda solo gli autori di un SandboxRunner personalizzato, come @emdash-cms/cloudflare. La maggior parte degli autori di plugin può saltarlo.
Il tipo orientato all’autore SandboxedPlugin è disponibile dal punto di ingresso di authoring emdash/plugin. L’handle runtime restituito da SandboxRunner.load è esportato da emdash come SandboxedPluginInstance.
Cosa devo fare?
Se importi SandboxedPlugin da emdash per tipizzare un sandbox runner o tenere handle di plugin a runtime, cambia l’import in SandboxedPluginInstance:
import type { SandboxedPlugin } from "emdash";
import type { SandboxedPluginInstance } from "emdash";
Informa i tuoi utenti
I siti che installano il tuo plugin devono anche cambiare l’import. Indirizzali alla nuova forma: togli le parentesi graffe e il ().
import { helloPlugin } from "@my-org/plugin-hello";
import hello from "@my-org/plugin-hello";
export default defineConfig({
integrations: [
emdash({
sandboxed: [helloPlugin()],
sandboxed: [hello],
}),
],
});
Se il tuo plugin accettava configurazione tramite la sua factory, sposta quella configurazione in una pagina di impostazioni di amministrazione e leggila da ctx.settings. I descriptor dei plugin sandboxed sono oggetti plain e non possono ricevere opzioni del costruttore. Vedi Settings.
Verificare il plugin migrato
Esegui i test del plugin, valida il manifest di authoring ed esegui i controlli completi di build e bundle:
pnpm test
pnpm exec emdash-plugin validate
pnpm exec emdash-plugin build
pnpm exec emdash-plugin bundle --validate-only
Poi installa il pacchetto locale in un sito di sviluppo ed esercita ogni hook e route migrati. La build può confermare nomi e forme, ma non può confermare che una route restituisca i dati previsti o che un hook preservi correttamente il contenuto.