Paramètres des Plugins
Les plugins nécessitent une configuration — clés API, drapeaux de fonctionnalités, préférences d’affichage. EmDash fournit deux mécanismes : un schéma de paramètres pour les options configurables par l’administrateur et un stockage KV pour un accès programmatique.
Schéma de paramètres
Section intitulée « Schéma de paramètres »Déclarez un schéma de paramètres dans admin.settingsSchema pour générer automatiquement une interface d’administration :
import { definePlugin } from "emdash";
export default definePlugin({ id: "seo", version: "1.0.0",
admin: { settingsSchema: { siteTitle: { type: "string", label: "Titre du site", description: "Utilisé dans les balises title et les métadonnées", default: "", }, maxTitleLength: { type: "number", label: "Max Title Length", description: "Characters before truncation", default: 60, min: 30, max: 100, }, generateSitemap: { type: "boolean", label: "Generate Sitemap", description: "Automatically generate sitemap.xml", default: true, }, defaultRobots: { type: "select", label: "Default Robots", options: [ { value: "index,follow", label: "Index & Follow" }, { value: "noindex,follow", label: "No Index, Follow" }, { value: "noindex,nofollow", label: "No Index, No Follow" }, ], default: "index,follow", }, apiKey: { type: "secret", label: "API Key", description: "Encrypted at rest", }, }, },});EmDash génère un formulaire de paramètres dans la section d’administration du plugin. Les utilisateurs modifient les paramètres sans toucher au code.
Types de champs
Section intitulée « Types de champs »Chaîne de caractères
Section intitulée « Chaîne de caractères »Champ de saisie pour des chaînes de caractères sur une ou plusieurs lignes.
siteTitle: { type: "string", label: "Titre du site", description: "Texte d'aide facultatif", default: "Mon site", multiline: false // Définissez sur true pour un textarea}Saisie numérique avec des contraintes min/max optionnelles.
maxItems: { type: "number", label: "Maximum Items", default: 100, min: 1, max: 1000}Interrupteur pour les valeurs vrai/faux.
enabled: { type: "boolean", label: "Enabled", description: "Turn this feature on or off", default: true}Sélection
Section intitulée « Sélection »Menu déroulant pour des options prédéfinies.
theme: { type: "select", label: "Theme", options: [ { value: "light", label: "Light" }, { value: "dark", label: "Dark" }, { value: "auto", label: "System" } ], default: "auto"}Champ chiffré pour les valeurs sensibles comme les clés API. Jamais envoyé au client après l’enregistrement.
apiKey: { type: "secret", label: "API Key", description: "Stored encrypted"}Accéder aux paramètres
Section intitulée « Accéder aux paramètres »Lisez les paramètres dans les hooks et les routes via ctx.kv :
"content:beforeSave": async (event, ctx) => { // Read a setting const maxLength = await ctx.kv.get<number>("settings:maxTitleLength"); const apiKey = await ctx.kv.get<string>("settings:apiKey");
// Utilisez les valeurs par défaut si non définies const limit = maxLength ?? 60;
ctx.log.info("Using max length", { limit }); return event.content;}Les paramètres sont stockés avec le préfixe settings: par convention. Cela distingue les valeurs configurables par l’utilisateur de l’état interne du plugin.
API du stockage KV
Section intitulée « API du stockage KV »Le stockage KV (ctx.kv) est un stockage clé-valeur à usage général pour les données du plugin :
interface KVAccess { get<T>(key: string): Promise<T | null>; set(key: string, value: unknown): Promise<void>; delete(key: string): Promise<boolean>; list(prefix?: string): Promise<Array<{ key: string; value: unknown }>>;}Lire les valeurs
Section intitulée « Lire les valeurs »// Get a single valueconst enabled = await ctx.kv.get<boolean>("settings:enabled");
// Obtenir avec un typeconst config = await ctx.kv.get<{ url: string; timeout: number }>("state:config");Écrire des valeurs
Section intitulée « Écrire des valeurs »// Set a valueawait ctx.kv.set("settings:lastSync", new Date().toISOString());
// Définir des valeurs complexesawait ctx.kv.set("state:cache", { data: items, expiry: Date.now() + 3600000,});Lister les valeurs
Section intitulée « Lister les valeurs »// List all settingsconst settings = await ctx.kv.list("settings:");// Returns: [{ key: "settings:enabled", value: true }, ...]
// Lister toutes les clés du pluginconst all = await ctx.kv.list();Supprimer des valeurs
Section intitulée « Supprimer des valeurs »const deleted = await ctx.kv.delete("state:tempData");// Returns true if key existedConventions de nommage des clés
Section intitulée « Conventions de nommage des clés »Utilisez des préfixes pour organiser les données KV :
| Préfixe | Objectif | Exemple |
|---|---|---|
settings: | Préférences configurables par l’utilisateur | settings:apiKey |
state: | État interne du plugin | state:lastSync |
cache: | Données mises en cache | cache:results |
// Good: clear prefixesawait ctx.kv.set("settings:webhookUrl", url);await ctx.kv.set("state:lastRun", timestamp);await ctx.kv.set("cache:feed", feedData);
// À éviter : pas de préfixe, objectif peu clairawait ctx.kv.set("url", url);Paramètres vs Stockage vs KV
Section intitulée « Paramètres vs Stockage vs KV »Choisissez le bon mécanisme de stockage :
| Cas d’utilisation | Mécanisme |
|---|---|
| Préférences modifiables par l’administrateur | admin.settingsSchema + ctx.kv avec settings: |
| État interne du plugin | ctx.kv avec state: |
| Collections de documents | ctx.storage |
Les paramètres sont pour les valeurs configurables par l’utilisateur — des éléments qu’un administrateur pourrait changer. Ils bénéficient d’une interface générée automatiquement.
KV est pour l’état interne comme les horodatages, les curseurs de synchronisation ou les calculs mis en cache. Pas d’interface, juste du code.
Le stockage est pour les collections de documents avec des requêtes indexées — soumissions de formulaires, journaux d’audit, etc.
Charger les paramètres dans les routes
Section intitulée « Charger les paramètres dans les routes »Les routes API peuvent exposer les paramètres aux composants de l’interface d’administration :
routes: { settings: { handler: async (ctx) => { const settings = await ctx.kv.list("settings:"); const result: Record<string, unknown> = {};
for (const entry of settings) { const key = entry.key.replace("settings:", ""); result[key] = entry.value; }
return result; } },
"settings/save": { handler: async (ctx) => { const input = ctx.input as Record<string, unknown>;
for (const [key, value] of Object.entries(input)) { if (value !== undefined) { await ctx.kv.set(`settings:${key}`, value); } }
return { success: true }; } }}Valeurs par défaut
Section intitulée « Valeurs par défaut »Les paramètres de settingsSchema ne sont pas automatiquement persistés. Ce sont des valeurs par défaut dans l’interface d’administration. Votre code doit gérer les valeurs manquantes :
"content:afterSave": async (event, ctx) => { // Always provide a fallback const enabled = await ctx.kv.get<boolean>("settings:enabled") ?? true; const maxItems = await ctx.kv.get<number>("settings:maxItems") ?? 100;
if (!enabled) return; // ...}Alternativement, persistez les valeurs par défaut dans plugin:install :
hooks: { "plugin:install": async (_event, ctx) => { // Persist schema defaults await ctx.kv.set("settings:enabled", true); await ctx.kv.set("settings:maxItems", 100); }}Implémentation du stockage
Section intitulée « Implémentation du stockage »Les valeurs KV sont stockées dans la table _options avec des clés préfixées par le plugin :
INSERT INTO _options (name, value) VALUES ('plugin:seo:settings:siteTitle', '"Mon site"'), ('plugin:seo:settings:maxTitleLength', '60');Le préfixe plugin:seo: est ajouté automatiquement. Votre code utilise settings:siteTitle, et EmDash le stocke sous plugin:seo:settings:siteTitle.
Cela garantit que les plugins ne peuvent pas écraser accidentellement les données des uns et des autres.