Aller au contenu

Vue d'ensemble du système de plugins

Le système de plugins d’EmDash vous permet d’étendre le CMS sans modifier le code principal. Les plugins peuvent s’accrocher aux événements du cycle de vie du contenu, stocker leurs propres données, exposer des paramètres aux administrateurs et ajouter une interface utilisateur personnalisée au panneau d’administration.

Les plugins EmDash sont des transformateurs de configuration, et non des applications séparées. Ils s’exécutent dans le même processus que votre site Astro et interagissent via des interfaces bien définies.

Principes clés :

  • Déclaratif — Les hooks, le stockage et les routes sont déclarés au moment de la définition, et non enregistrés dynamiquement
  • Type-safe — Prise en charge complète de TypeScript avec des objets de contexte typés
  • Prêt pour le sandboxing — APIs conçues pour une exécution isolée sur Cloudflare Workers
  • Basé sur les capacités — Les plugins déclarent ce dont ils ont besoin ; l’environnement d’exécution applique l’accès

S'accrocher aux événements

Exécuter du code avant ou après l’enregistrement du contenu, les téléchargements de médias et les événements du cycle de vie des plugins.

Stocker des données

Persister des données spécifiques au plugin dans des collections indexées sans écrire de migrations de base de données.

Exposer des paramètres

Déclarer un schéma de paramètres et obtenir une interface d’administration générée automatiquement pour la configuration.

Ajouter des pages d'administration

Créer des pages d’administration personnalisées et des widgets de tableau de bord avec des composants React.

Créer des routes API

Exposer des points de terminaison pour l’interface d’administration de votre plugin ou des intégrations externes.

Effectuer des requêtes HTTP

Appeler des APIs externes avec des restrictions d’hôte déclarées pour la sécurité.

Chaque plugin est créé avec definePlugin() :

import { definePlugin } from "emdash";
export default definePlugin({
id: "my-plugin",
version: "1.0.0",
// Quelles APIs le plugin doit pouvoir utiliser
capabilities: ["read:content", "network:fetch"],
// Hôtes vers lesquels le plugin peut effectuer des requêtes HTTP
allowedHosts: ["api.example.com"],
// Collections de stockage persistant
storage: {
entries: {
indexes: ["userId", "createdAt"],
},
},
// Gestionnaires d'événements
hooks: {
"content:afterSave": async (event, ctx) => {
ctx.log.info("Content saved", { id: event.content.id });
},
},
// Points de terminaison de l'API REST
routes: {
status: {
handler: async (ctx) => ({ ok: true }),
},
},
// Configuration de l'interface d'administration
admin: {
settingsSchema: {
apiKey: { type: "secret", label: "API Key" },
},
pages: [{ path: "/dashboard", label: "Dashboard" }],
widgets: [{ id: "status", size: "half" }],
},
});

Chaque hook et gestionnaire de route reçoit un objet PluginContext avec accès à :

PropriétéDescriptionDisponibilité
ctx.storageCollections de documents du pluginToujours (si déclaré)
ctx.kvStockage clé-valeur pour les paramètres et l’étatToujours
ctx.contentLire/écrire le contenu du siteAvec read:content ou write:content
ctx.mediaLire/écrire les fichiers multimédiasAvec read:media ou write:media
ctx.httpClient HTTP pour les requêtes externesAvec network:fetch
ctx.logJournal structuré (debug, info, warn, error)Toujours
ctx.pluginMétadonnées du plugin (id, version)Toujours
ctx.siteInformations du site : name, url, localeToujours
ctx.url()Générer des URLs absolues à partir de cheminsToujours
ctx.usersLire les infos utilisateur : get(), getByEmail(), list()Avec read:users
ctx.cronPlanifier des tâches : schedule(), cancel(), list()Toujours
ctx.emailEnvoyer un email : send()Avec email:send + fournisseur configuré

La forme du contexte est identique pour tous les hooks et routes. Les propriétés conditionnées par les capacités ne sont présentes que lorsque le plugin déclare la capacité requise.

Les capacités déterminent quelles APIs sont disponibles dans le contexte du plugin :

CapacitéAccorde l’accès à
read:contentctx.content.get(), ctx.content.list()
write:contentctx.content.create(), ctx.content.update(), ctx.content.delete()
read:mediactx.media.get(), ctx.media.list()
write:mediactx.media.getUploadUrl(), ctx.media.upload(), ctx.media.delete()
network:fetchctx.http.fetch() (restreint à allowedHosts)
network:fetch:anyctx.http.fetch() (sans restriction — pour les URLs configurées par l’utilisateur)
read:usersctx.users.get(), ctx.users.getByEmail(), ctx.users.list()
email:sendctx.email.send() (nécessite un plugin fournisseur)
email:provideEnregistrer le hook exclusif email:deliver (transporteur)
email:interceptEnregistrer les hooks email:beforeSend / email:afterSend
page:injectEnregistrer les hooks page:metadata / page:fragments

Enregistrez les plugins dans votre configuration Astro :

typescript title="astro.config.mjs"
import { defineConfig } from "astro/config";
import { emdash } from "emdash/astro";
import seoPlugin from "@emdash-cms/plugin-seo";
import auditLogPlugin from "@emdash-cms/plugin-audit-log";
export default defineConfig({
integrations: [
emdash({
plugins: [seoPlugin({ generateSitemap: true }), auditLogPlugin({ retentionDays: 90 })],
}),
],
});

Les plugins sont résolus au moment de la construction. L’ordre est important pour les hooks de même priorité—les plugins placés plus tôt dans le tableau s’exécutent en premier.

EmDash prend en charge deux modes d’exécution de plugin :

ModeDescriptionPlateforme
TrustedLes plugins s’exécutent en processus avec un accès completToutes
SandboxedLes plugins s’exécutent dans des workers V8 isolésCloudflare uniquement

En mode de confiance (par défaut), les capacités sont documentaires—les plugins peuvent accéder à tout. En mode isolé, les capacités sont appliquées au niveau de l’exécution.