Panoramica del sistema plugin

In questa pagina

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àDescrizioneDisponibilità
ctx.storageRaccolte di documenti del pluginSempre (se dichiarato)
ctx.kvArchivio chiave-valore per impostazioni e statoSempre
ctx.contentLettura/scrittura contenuto del sitoCon read:content o write:content
ctx.mediaLettura/scrittura file mediaCon read:media o write:media
ctx.httpClient HTTP per richieste esterneCon network:fetch
ctx.logLogger strutturato (debug, info, warn, error)Sempre
ctx.pluginMetadati del plugin (id, version)Sempre
ctx.siteInfo sito: name, url, localeSempre
ctx.url()Generare URL assoluti da percorsiSempre
ctx.usersLeggere info utenti: get(), getByEmail(), list()Con read:users
ctx.cronPianificare attività: schedule(), cancel(), list()Sempre
ctx.emailInviare 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: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() (ristretto a allowedHosts)
network:fetch:anyctx.http.fetch() (senza restrizioni — per URL configurati dall’utente)
read:usersctx.users.get(), ctx.users.getByEmail(), ctx.users.list()
email:sendctx.email.send() (richiede plugin provider)
email:provideRegistrare hook esclusivo email:deliver (provider trasporto)
email:interceptRegistrare hook email:beforeSend / email:afterSend
page:injectRegistrare 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àDescrizionePiattaforma
SandboxedWorker V8 isolati con limiti forzatiSolo Cloudflare
NativoIn-process con accesso completoQualsiasi

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