Paramètres des plugins

Sur cette page

Les plugins ont besoin de configuration — clés API, feature flags, préférences d’affichage. EmDash propose deux mécanismes : un schéma de paramètres pour les options configurables dans l’admin et un store KV pour l’accès programmatique.

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: "Site Title",
				description: "Used in title tags and meta",
				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 admin du plugin. Les utilisateurs modifient les réglages sans toucher au code.

Types de champs

String

Saisie de texte pour des chaînes sur une ou plusieurs lignes.

siteTitle: {
  type: "string",
  label: "Site Title",
  description: "Optional help text",
  default: "My Site",
  multiline: false  // Set true for textarea
}

Number

Saisie numérique avec contraintes min/max optionnelles.

maxItems: {
  type: "number",
  label: "Maximum Items",
  default: 100,
  min: 1,
  max: 1000
}

Boolean

Interrupteur pour les valeurs vrai/faux.

enabled: {
  type: "boolean",
  label: "Enabled",
  description: "Turn this feature on or off",
  default: true
}

Select

Liste déroulante 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"
}

Secret

Champ chiffré pour des valeurs sensibles comme les clés API. Jamais renvoyé au client après enregistrement.

apiKey: {
  type: "secret",
  label: "API Key",
  description: "Stored encrypted"
}

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");

  // Use defaults if not set
  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 store KV

Le store 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 des valeurs

// Get a single value
const enabled = await ctx.kv.get<boolean>("settings:enabled");

// Get with type
const config = await ctx.kv.get<{ url: string; timeout: number }>("state:config");

Écrire des valeurs

// Set a value
await ctx.kv.set("settings:lastSync", new Date().toISOString());

// Set complex values
await ctx.kv.set("state:cache", {
	data: items,
	expiry: Date.now() + 3600000,
});

Lister des valeurs

// List all settings
const settings = await ctx.kv.list("settings:");
// Returns: [{ key: "settings:enabled", value: true }, ...]

// List all plugin keys
const all = await ctx.kv.list();

Supprimer des valeurs

const deleted = await ctx.kv.delete("state:tempData");
// Returns true if key existed

Conventions de nommage des clés

Utilisez des préfixes pour organiser les données KV :

PréfixeRôleExemple
settings:Préférences configurables par l’utilisateursettings:apiKey
state:État interne du pluginstate:lastSync
cache:Données mises en cachecache:results
// Good: clear prefixes
await ctx.kv.set("settings:webhookUrl", url);
await ctx.kv.set("state:lastRun", timestamp);
await ctx.kv.set("cache:feed", feedData);

// Avoid: no prefix, unclear purpose
await ctx.kv.set("url", url);

Paramètres vs Storage vs KV

Choisissez le bon mécanisme de stockage :

Cas d’usageMécanisme
Préférences modifiables dans l’adminadmin.settingsSchema + ctx.kv avec settings:
État interne du pluginctx.kv avec state:
Collections de documentsctx.storage

Les paramètres sont des valeurs configurables par l’utilisateur — ce qu’un administrateur pourrait modifier. Ils bénéficient d’une interface générée automatiquement.

Le KV sert à l’état interne : horodatages, curseurs de synchronisation, calculs mis en cache. Pas d’interface, uniquement du code.

Storage sert aux collections de documents avec requêtes indexées — soumissions de formulaires, journaux d’audit, etc.

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

Les paramètres issus de settingsSchema ne sont pas persistés automatiquement. 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;
  // ...
}

Vous pouvez aussi persister 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

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', '"My Site"'),
  ('plugin:seo:settings:maxTitleLength', '60');

Le préfixe plugin:seo: est ajouté automatiquement. Votre code utilise settings:siteTitle, et EmDash stocke plugin:seo:settings:siteTitle.

Cela garantit que les plugins n’écrasent pas accidentellement les données des autres.