Les plugins natifs sont des paquets npm installés dans le projet hôte et enregistrés dans astro.config.mjs. Le paquet a besoin d’une entrée serveur construite pour son descripteur et createPlugin(). S’il livre aussi des composants React ou Astro, exportez-les comme entrypoints source séparés pour que l’hôte puisse les compiler pour le bon environnement.
Disposition du paquet
La disposition suivante sépare le runtime serveur du code source navigateur et Astro :
plugin-activity/
├── src/
│ ├── index.ts
│ ├── admin/
│ │ ├── index.tsx
│ │ └── ActivityPage.tsx
│ └── astro/
│ ├── index.ts
│ └── ActivityBlock.astro
├── dist/
│ ├── index.mjs
│ └── index.d.mts
├── package.json
├── tsconfig.json
└── README.md
dist/ est généré. Conservez src/admin/ et src/astro/ dans le tarball publié car le build Vite et Astro de l’hôte doit traiter ces entrypoints.
Exports du paquet
Le package.json suivant construit l’entrée serveur et publie les trois entrypoints :
{
"name": "@example/plugin-activity",
"version": "0.1.0",
"type": "module",
"main": "./dist/index.mjs",
"exports": {
".": {
"types": "./dist/index.d.mts",
"import": "./dist/index.mjs"
},
"./admin": "./src/admin/index.tsx",
"./astro": "./src/astro/index.ts"
},
"files": ["dist", "src/admin", "src/astro"],
"scripts": {
"build": "tsdown src/index.ts --format esm --dts --clean",
"dev": "tsdown src/index.ts --format esm --dts --watch",
"typecheck": "tsc --noEmit",
"prepublishOnly": "pnpm typecheck && pnpm build"
},
"peerDependencies": {
"@cloudflare/kumo": "*",
"@emdash-cms/admin": "*",
"@lingui/core": "*",
"@lingui/react": "*",
"@tanstack/react-query": "*",
"astro": ">=6.0.0-beta.0",
"emdash": "*",
"react": "^18.0.0 || ^19.0.0"
},
"devDependencies": {
"@types/react": "^19.0.0",
"tsdown": "^0.20.0",
"typescript": "^5.9.0"
},
"keywords": ["emdash", "emdash-plugin"],
"license": "MIT"
}
Retirez ./admin, src/admin et les peer dependencies réservées à l’admin lorsque le plugin n’a pas d’UI React de confiance. Retirez ./astro, src/astro et le peer astro lorsqu’il n’a pas de renderiseur Portable Text. Ajoutez une peer dependency pour chaque bibliothèque appartenant à l’hôte importée par un entrypoint source exporté ; cela empêche une seconde instance de React, Kumo, Lingui ou React Query d’entrer dans le bundle d’administration.
Les entrypoints ont des consommateurs différents :
| Export | Requis lorsque | Consommateur |
|---|---|---|
. | Toujours | La configuration Astro importe la factory du descripteur ; EmDash importe le createPlugin() nommé au runtime. |
./admin | adminEntry est défini | Le build navigateur de l’hôte importe les maps de composants React. |
./astro | componentsEntry est défini | Le build Astro de l’hôte importe blockComponents. |
Les spécificateurs de module dans le descripteur et le runtime doivent correspondre à ces exports :
export function activityPlugin(): PluginDescriptor {
return {
id: "plugin-activity",
version: "0.1.0",
format: "native",
entrypoint: "@example/plugin-activity",
adminEntry: "@example/plugin-activity/admin",
componentsEntry: "@example/plugin-activity/astro",
};
}
export function createPlugin() {
return definePlugin({
id: "plugin-activity",
version: "0.1.0",
admin: {
entry: "@example/plugin-activity/admin",
},
});
}
Gardez synchronisées la version du paquet npm, la version du descripteur et la version de definePlugin(). La version affichée à un administrateur du site vient de la définition du plugin, pas automatiquement de package.json.
Identité et version du plugin
definePlugin() accepte soit un ID sans scope contenant des lettres minuscules, des chiffres et des tirets, soit un ID scopé de la forme @scope/name. Utilisez un ID sans scope en kebab-case pour un plugin de site car l’ID occupe aussi un segment de chemin dans /_emdash/api/plugins/<plugin-id>/<route>.
Les valeurs suivantes montrent les formes acceptées et la séparation recommandée entre l’ID du plugin et le nom du paquet npm :
id: "plugin-activity"; // Recommandé : valide dans les URL de routes du plugin
id: "@example/plugin-activity"; // Accepté par definePlugin(), mais pas un segment d’URL
entrypoint: "@example/plugin-activity"; // Le paquet npm peut rester scopé
Les versions doivent commencer par une séquence sémantique major.minor.patch. Utilisez une version sémantique complète pour le descripteur et le runtime :
version: "1.0.0"; // Valide
version: "1.2.3-beta.1"; // Prerelease valide
version: "1.0"; // Invalide : version de correctif manquante
Configuration TypeScript
Le scaffold natif crée un tsconfig.json adapté. Si le plugin ajoute du code source React et Astro après le scaffolding, incluez les deux environnements JSX :
{
"compilerOptions": {
"target": "ES2022",
"module": "preserve",
"moduleResolution": "bundler",
"strict": true,
"declaration": true,
"outDir": "./dist",
"rootDir": "./src",
"jsx": "react-jsx",
"types": ["astro/client"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Exécutez pnpm typecheck contre les entrypoints source avant d’empaqueter. Le script build ne compile que src/index.ts ; l’hôte compile le code source admin et Astro exporté lorsqu’il consomme le paquet.
Inspecter le paquet
Testez le contenu exact du tarball avant de publier. Les commandes ci-dessous supposent qu’un site jetable nommé my-emdash-site se trouve à côté du répertoire du plugin.
-
Construisez et vérifiez les types du paquet.
pnpm typecheck pnpm build -
Créez le tarball npm et examinez la liste de fichiers imprimée par npm.
npm packPour le paquet d’exemple, npm crée
example-plugin-activity-0.1.0.tgz. -
Confirmez que la sortie contient
dist/index.mjs,dist/index.d.mtset chaque fichier source atteignable depuis les modules exportés./adminet./astro. -
Installez le tarball produit dans le site EmDash jetable.
cd ../my-emdash-site pnpm add ../plugin-activity/example-plugin-activity-0.1.0.tgz -
Importez et enregistrez la factory du descripteur dans le
astro.config.mjsdu site jetable, en suivant Créer et enregistrer le paquet. Puis construisez le site hôte.pnpm buildOuvrez chaque surface d’administration du plugin et rendez chaque bloc Portable Text contribué. Enregistrer avant le build permet à Astro de résoudre les exports
./adminet./astrodu tarball ; un test de paquet serveur seul ne peut pas détecter un fichier source navigateur ou.astromanquant.
Contenu du README
Donnez à un opérateur assez d’informations pour installer et évaluer le paquet sans lire son code source. Incluez :
- une description en une phrase et la version EmDash prise en charge
- la commande d’installation et l’enregistrement complet dans
astro.config.mjs - la frontière de confiance native et pourquoi le plugin a besoin d’une exécution native
- chaque capability déclarée et hôte autorisé, avec la fonctionnalité qui l’utilise
- les paramètres et leurs valeurs par défaut
- les composants de mise en page requis, tels que
EmDashBodyEndpour un fragment body-end - les étapes de mise à niveau pour les changements qui exigent une action de l’opérateur
Ne décrivez pas les déclarations de capability comme une frontière d’isolation. Elles contrôlent les API ctx, mais le code natif peut toujours utiliser les imports, variables d’environnement et appels réseau directs disponibles pour le processus hôte.
Publier sur npm
Publiez après que le test du tarball a réussi :
npm publish --access public
La première publication publique d’un paquet scopé a besoin de --access public. Utilisez le versionnement sémantique pour les releases ultérieures. Traitez les changements aux options du constructeur, données stockées, changements d’hôte requis, exports du paquet ou exigences de confiance du plugin comme des décisions de compatibilité. Si une mise à niveau exige une nouvelle capability ou un hôte autorisé, signalez-le dans les notes de release même si les installations natives n’ont pas d’invite de consentement aux capabilities.
Installer depuis npm
Un opérateur installe le paquet publié dans le site EmDash :
pnpm add @example/plugin-activity
Importez et enregistrez ensuite sa factory de descripteur dans astro.config.mjs comme montré dans Créer et enregistrer le paquet. Installer la dépendance seule n’active pas le plugin ; modifier la configuration Astro et déployer le site termine l’installation.
Développer contre un site hôte
Construisez le plugin en mode watch :
pnpm dev
Installez le répertoire local depuis le site hôte :
pnpm add ../plugin-activity
Enregistrez la factory du descripteur du plugin dans astro.config.mjs, puis démarrez le serveur de développement de l’hôte. Redémarrez le serveur après avoir modifié les métadonnées du descripteur ou les exports du paquet. Si une dépendance fichier du gestionnaire de paquets copie les fichiers au lieu de les lier dans votre configuration, réinstallez-la après reconstruction ; une dépendance workspace ou pnpm link garde le paquet local connecté pendant le développement.
Frontière du registre
Les paquets natifs ne peuvent pas être publiés dans le registre EmDash. Les plugins du registre utilisent le format de paquet sandboxed, le flux de release signé et le flux de consentement d’installation. Si le plugin n’a plus besoin de code d’administration React, de renderiseurs Astro, de fragments de confiance ou d’une autre dépendance in-process, convertissez-le au format sandboxed avant de publier via le registre.