Ce guide s’adresse aux auteurs de plugins sandboxed écrits contre l’ancienne forme definePlugin(). Parcourez les changements incompatibles dans l’ordre. Aucun ne change le comportement de vos hooks ou routes à l’exécution ; ils changent la façon dont le plugin est déclaré, construit et publié.
Pour la liste complète des changements dans chaque paquet, consultez son entrée sur la page des releases.
Changements incompatibles
Renommé : @emdash-cms/registry-cli est maintenant @emdash-cms/plugin-cli
Les versions antérieures livraient la CLI sous @emdash-cms/registry-cli, avec un binaire emdash-registry.
Le paquet est maintenant @emdash-cms/plugin-cli et le binaire est emdash-plugin. L’ancien paquet n’est plus publié.
Que dois-je faire ?
Remplacez la dépendance :
pnpm remove @emdash-cms/registry-cli
pnpm add -D @emdash-cms/plugin-cli
Remplacez emdash-registry par emdash-plugin partout où vous l’appelez. Chaque sous-commande conserve son nom (bundle, publish, login, whoami, switch, validate), et init, build et dev sont ajoutés. Voir The plugin CLI.
Renommé : les noms de capabilities utilisent l’orthographe resource-first
Les manifests antérieurs utilisaient des noms de capability tels que read:content et network:fetch. Le manifest d’authoring n’accepte que les noms actuels, bien que le runtime normalise encore les noms legacy dans les bundles déjà publiés pendant la fenêtre de compatibilité.
Que dois-je faire ?
Remplacez chaque nom legacy dans le manifest :
| Nom antérieur | Nom actuel |
|---|---|
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 |
Utilisez network:request avec une liste allowedHosts non vide. Utilisez network:request:unrestricted avec une liste vide uniquement lorsqu’un opérateur choisit la destination à l’exécution. Capabilities and security explique les permissions et règles réseau actuelles.
Modifié : les plugins sandboxed utilisent une annotation explicite SandboxedPlugin
Les versions antérieures enveloppaient les hooks et routes du plugin dans definePlugin() importé depuis emdash, avec les paramètres de chaque handler annotés à la main.
Un plugin sandboxed assigne sa définition à une constante typée SandboxedPlugin et exporte cette constante en default. Importez le type depuis emdash/plugin avec import type ; le bundler efface cet import. Le même sous-chemin exporte aussi les helpers runtime légers pluginRoute() et pluginResponse(). TypeScript infère le event et le ctx de chaque handler à partir du nom du hook ou de la route, donc les paramètres du handler n’ont pas besoin d’annotations. L’annotation explicite maintient aussi les déclarations générées portables sous des layouts isolés du gestionnaire de paquets.
Que dois-je faire ?
Faites quatre changements dans le fichier source du plugin. Remplacez l’import :
import { definePlugin, type ContentHookEvent, type PluginContext } from "emdash";
import type { SandboxedPlugin } from "emdash/plugin";
Remplacez le wrapper definePlugin() par une constante explicitement typée :
export default definePlugin({ /* hooks, routes */ });
const plugin: SandboxedPlugin = { /* hooks, routes */ };
export default plugin;
Supprimez les annotations de paramètres de chaque handler :
handler: async (event: ContentHookEvent, ctx: PluginContext) => {
handler: async (event, ctx) => {
Le résultat est un objet exporté par défaut :
import type { SandboxedPlugin } from "emdash/plugin";
const plugin: SandboxedPlugin = {
hooks: {
"content:beforeSave": {
handler: async (event, ctx) => {
return event.content;
},
},
},
};
export default plugin;
Pour nommer un type d’événement dans une fonction auxiliaire, importez-le depuis emdash/plugin :
import type { ContentHookEvent, PluginContext } from "emdash/plugin";
Le event d’un handler est toujours le type canonique pour ce hook. Annoter un handler avec une interface plus étroite ne passe plus le type-check. Validez à l’exécution tout champ dont vous dépendez avec un contrôle typeof ou un guard, ce qui est l’approche correcte pour des données provenant de l’extérieur du système de types.
Modifié : un plugin est un src/plugin.ts plus emdash-plugin.jsonc
Les versions antérieures divisaient un plugin en deux fichiers : src/index.ts renvoyait un PluginDescriptor (id, version, capabilities, storage, entrypoint), et src/sandbox-entry.ts contenait les hooks et routes.
Un plugin est maintenant un fichier runtime, src/plugin.ts (hooks et routes), et un manifest édité à la main, emdash-plugin.jsonc (identité et le contrat de confiance). Les champs entrypoint et format ont disparu ; le build les câble.
Que dois-je faire ?
Déplacez les hooks et routes dans src/plugin.ts selon la forme ci-dessus. Déplacez les métadonnées du descripteur dans emdash-plugin.jsonc à côté de package.json. L’id du descripteur devient le slug du manifest ; capabilities, allowedHosts et storage conservent leur forme ; version est lue depuis package.json, donc omettez-la.
L’exemple suivant montre l’équivalent manifest d’un descripteur qui déclarait une collection 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"] } }
}
Voir The plugin manifest pour chaque champ, et Publisher pinning pour le champ publisher.
Dans package.json, pointez l’export "./sandbox" vers le fichier runtime construit :
"./sandbox": "./dist/sandbox-entry.mjs"
"./sandbox": "./dist/plugin.mjs"
Ajoutez le manifest à files pour qu’il soit livré avec le paquet :
"files": ["dist"]
"files": ["dist", "emdash-plugin.jsonc"]
Modifié : construire avec emdash-plugin build
Les versions antérieures construisaient les deux fichiers source avec un script tsdown écrit à la main.
emdash-plugin build lit emdash-plugin.jsonc et src/plugin.ts et émet les artefacts dist/. emdash-plugin dev surveille et reconstruit.
Que dois-je faire ?
Remplacez le script de build et ajoutez un 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"
}
Puis validez et construisez :
emdash-plugin validate
emdash-plugin build
Supprimé : exports de types et fonctions de format standard depuis emdash
Les versions antérieures exportaient StandardPluginDefinition, StandardHookHandler, StandardHookEntry, StandardRouteHandler, StandardRouteEntry et la fonction isStandardPluginDefinition depuis emdash.
Ils sont supprimés. C’étaient des alias d’aide pour l’ancienne forme definePlugin.
Que dois-je faire ?
Utilisez SandboxedPlugin depuis emdash/plugin dans le même but. La définition exportée d’un plugin sandboxed est déjà typée par son annotation SandboxedPlugin, donc il n’y a pas de remplacement pour isStandardPluginDefinition ; identifiez un plugin par sa structure ({ hooks?, routes? }) si besoin.
Renommé : les handles du sandbox-runner utilisent SandboxedPluginInstance
Cela n’affecte que les auteurs d’un SandboxRunner personnalisé, tel que @emdash-cms/cloudflare. La plupart des auteurs de plugins peuvent l’ignorer.
Le type orienté auteur SandboxedPlugin est disponible depuis le point d’entrée d’authoring emdash/plugin. Le handle runtime renvoyé par SandboxRunner.load est exporté depuis emdash en tant que SandboxedPluginInstance.
Que dois-je faire ?
Si vous importez SandboxedPlugin depuis emdash pour typer un sandbox runner ou détenir des handles de plugins runtime, changez l’import en SandboxedPluginInstance :
import type { SandboxedPlugin } from "emdash";
import type { SandboxedPluginInstance } from "emdash";
Informez vos utilisateurs
Les sites qui installent votre plugin doivent aussi changer leur import. Orientez-les vers la nouvelle forme : retirez les accolades et le ().
import { helloPlugin } from "@my-org/plugin-hello";
import hello from "@my-org/plugin-hello";
export default defineConfig({
integrations: [
emdash({
sandboxed: [helloPlugin()],
sandboxed: [hello],
}),
],
});
Si votre plugin acceptait de la configuration via son factory, déplacez cette configuration vers une page de paramètres d’administration et lisez-la depuis ctx.settings. Les descripteurs de plugins sandboxed sont des objets plain et ne peuvent pas recevoir d’options de constructeur. Voir Settings.
Vérifier le plugin migré
Exécutez les tests du plugin, validez le manifest d’authoring et exécutez les contrôles complets de build et de bundle :
pnpm test
pnpm exec emdash-plugin validate
pnpm exec emdash-plugin build
pnpm exec emdash-plugin bundle --validate-only
Puis installez le paquet local dans un site de développement et exercez chaque hook et route migrés. Le build peut confirmer leurs noms et formes, mais ne peut pas confirmer qu’une route renvoie les données prévues ou qu’un hook préserve correctement le contenu.