Il sistema di plugin di EmDash ti consente di estendere il CMS senza modificare il codice principale. I plugin possono agganciarsi agli eventi del ciclo di vita del contenuto, memorizzare i propri dati, esporre impostazioni agli amministratori e aggiungere UI personalizzata al pannello admin.
Filosofia di design
I plugin EmDash sono di due tipi: sandboxed e nativi. I plugin sandboxed vengono eseguiti in worker V8 isolati e possono essere installati dal marketplace con un clic. I plugin nativi vengono eseguiti in-process e sono configurati nel codice.
Preferisci i plugin sandboxed. Possono essere installati, aggiornati e rimossi dall’UI admin senza toccare il codice o ridistribuire. Usa i plugin nativi solo quando hai bisogno di funzionalità che richiedono integrazione al momento del build (pagine admin React, componenti di rendering Portable Text o iniezione di frammenti di pagina).
Principi chiave:
- Sandbox-first — Progetta per il sandbox; usa la modalità nativa solo quando necessario
- Dichiarativo — Hook, storage e route sono dichiarati al momento della definizione, non registrati dinamicamente
- Type-safe — Supporto completo di TypeScript con oggetti di contesto tipizzati
- Basato su capacità — I plugin dichiarano ciò di cui hanno bisogno; il sandbox lo applica
Cosa possono fare i plugin
Agganciarsi agli eventi
Eseguire codice prima o dopo salvataggi di contenuti, caricamenti di media ed eventi del ciclo di vita dei plugin.
Memorizzare dati
Persistere dati specifici del plugin in raccolte indicizzate senza scrivere migrazioni di database.
Esporre impostazioni
Dichiarare uno schema di impostazioni e ottenere un’UI admin auto-generata per la configurazione.
Aggiungere pagine admin
Creare pagine admin personalizzate e widget del dashboard con componenti React.
Creare route API
Esporre endpoint per l’UI admin del tuo plugin o integrazioni esterne.
Effettuare richieste HTTP
Chiamare API esterne con restrizioni di host dichiarate per la sicurezza.
Architettura del plugin
Ogni plugin è creato con definePlugin():
import { definePlugin } from "emdash";
export default definePlugin({
id: "my-plugin",
version: "1.0.0",
// API a cui il plugin necessita di accedere
capabilities: ["read:content", "network:fetch"],
// Host a cui il plugin può effettuare richieste HTTP
allowedHosts: ["api.example.com"],
// Raccolte di storage persistente
storage: {
entries: {
indexes: ["userId", "createdAt"],
},
},
// Gestori di eventi
hooks: {
"content:afterSave": async (event, ctx) => {
ctx.log.info("Content saved", { id: event.content.id });
},
},
// Endpoint REST API
routes: {
status: {
handler: async (ctx) => ({ ok: true }),
},
},
// Configurazione UI admin
admin: {
settingsSchema: {
apiKey: { type: "secret", label: "API Key" },
},
pages: [{ path: "/dashboard", label: "Dashboard" }],
widgets: [{ id: "status", size: "half" }],
},
});
Contesto del plugin
Ogni hook e gestore di route riceve un oggetto PluginContext con accesso a:
| Proprietà | Descrizione | Disponibilità |
|---|---|---|
ctx.storage | Raccolte di documenti del plugin | Sempre (se dichiarato) |
ctx.kv | Archivio chiave-valore per impostazioni e stato | Sempre |
ctx.content | Lettura/scrittura contenuto del sito | Con read:content o write:content |
ctx.media | Lettura/scrittura file media | Con read:media o write:media |
ctx.http | Client HTTP per richieste esterne | Con network:fetch |
ctx.log | Logger strutturato (debug, info, warn, error) | Sempre |
ctx.plugin | Metadati del plugin (id, version) | Sempre |
ctx.site | Info sito: name, url, locale | Sempre |
ctx.url() | Generare URL assoluti da percorsi | Sempre |
ctx.users | Leggere info utenti: get(), getByEmail(), list() | Con read:users |
ctx.cron | Pianificare attività: schedule(), cancel(), list() | Sempre |
ctx.email | Inviare email: send() | Con email:send + provider configurato |
La forma del contesto è identica per tutti gli hook e le route. Le proprietà protette da capacità sono presenti solo quando il plugin dichiara la capacità richiesta.
Capacità
Le capacità determinano quali API sono disponibili nel contesto del plugin:
| Capacità | Concede accesso a |
|---|---|
read:content | ctx.content.get(), ctx.content.list() |
write:content | ctx.content.create(), ctx.content.update(), ctx.content.delete() |
read:media | ctx.media.get(), ctx.media.list() |
write:media | ctx.media.getUploadUrl(), ctx.media.upload(), ctx.media.delete() |
network:fetch | ctx.http.fetch() (ristretto a allowedHosts) |
network:fetch:any | ctx.http.fetch() (senza restrizioni — per URL configurati dall’utente) |
read:users | ctx.users.get(), ctx.users.getByEmail(), ctx.users.list() |
email:send | ctx.email.send() (richiede plugin provider) |
email:provide | Registrare hook esclusivo email:deliver (provider trasporto) |
email:intercept | Registrare hook email:beforeSend / email:afterSend |
page:inject | Registrare hook page:metadata / page:fragments |
Registrazione
Registra i plugin nella tua configurazione Astro:
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 })],
}),
],
});
I plugin vengono risolti al momento del build. L’ordine conta per gli hook con la stessa priorità — i plugin precedenti nell’array vengono eseguiti per primi.
Modalità di esecuzione
EmDash supporta due modalità di esecuzione dei plugin:
| Modalità | Descrizione | Piattaforma |
|---|---|---|
| Sandboxed | Worker V8 isolati con limiti forzati | Solo Cloudflare |
| Nativo | In-process con accesso completo | Qualsiasi |
In modalità sandboxed, le capacità sono applicate a livello di runtime — i plugin possono accedere solo a ciò che dichiarano. In modalità nativa, le capacità sono consultive e i plugin hanno accesso completo al processo.
Prossimi passi
Crea un plugin
Costruisci il tuo primo plugin con storage, hook e UI admin.
Hook disponibili
Esplora tutti gli hook per contenuti, media e ciclo di vita dei plugin.
Storage del plugin
Scopri lo storage e come interrogare i dati dei plugin.
UI admin
Aggiungi pagine admin e widget del dashboard.
Nativo vs. Sandboxed
Confronta le modalità di esecuzione e scegli quella giusta per il tuo plugin.