プラグイン設定
プラグインには設定が必要です。APIキー、機能フラグ、表示設定などです。EmDashでは、管理者が設定可能なオプション用の設定スキーマと、プログラムによるアクセス用のKVストアという2つの仕組みを提供しています。
設定スキーマ
Section titled “設定スキーマ”管理者UIを自動生成するには、admin.settingsSchemaで設定スキーマを宣言します:
import { definePlugin } from "emdash";
export default definePlugin({ id: "seo", version: "1.0.0",
admin: { settingsSchema: { siteTitle: { type: "string", label: "サイトタイトル", description: "titleタグとメタ情報で使用します", 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: "デフォルトの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は、プラグインの管理者セクションに設定フォームを生成します。ユーザーはコードに触れることなく設定を編集できます。
フィールドタイプ
Section titled “フィールドタイプ”単一行または複数行の文字列用のテキスト入力。
siteTitle: { type: "string", label: "サイトタイトル", description: "任意のヘルプテキスト", default: "私のサイト", multiline: false // textarea にする場合は true}オプションで最小値/最大値の制約を設定できる数値入力。
maxItems: { type: "number", label: "Maximum Items", default: 100, min: 1, max: 1000}真/偽の値用のトグルスイッチ。
enabled: { type: "boolean", label: "Enabled", description: "Turn this feature on or off", default: true}事前定義されたオプション用のドロップダウン。
theme: { type: "select", label: "Theme", options: [ { value: "light", label: "Light" }, { value: "dark", label: "Dark" }, { value: "auto", label: "System" } ], default: "auto"}シークレット
Section titled “シークレット”APIキーなどの機密情報用の暗号化フィールド。保存後はクライアントに送信されません。
apiKey: { type: "secret", label: "API Key", description: "Stored encrypted"}設定へのアクセス
Section titled “設定へのアクセス”フックやルート内で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");
// 設定されていない場合はデフォルト値を使用 const limit = maxLength ?? 60;
ctx.log.info("最大長を使用中", { limit }); return event.content;}設定は慣例によりsettings:プレフィックスで保存されます。これにより、ユーザーが設定可能な値とプラグイン内部の状態が区別されます。
KVストアAPI
Section titled “KVストアAPI”KVストア(ctx.kv)は、プラグインデータ用の汎用キー・バリューストアです:
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 }>>;}値の読み取り
Section titled “値の読み取り”// Get a single valueconst enabled = await ctx.kv.get<boolean>("settings:enabled");
// 型を指定して取得const config = await ctx.kv.get<{ url: string; timeout: number }>("state:config");値の書き込み
Section titled “値の書き込み”// Set a valueawait ctx.kv.set("settings:lastSync", new Date().toISOString());
// 複雑な値を設定await ctx.kv.set("state:cache", { data: items, expiry: Date.now() + 3600000,});値の一覧表示
Section titled “値の一覧表示”// List all settingsconst settings = await ctx.kv.list("settings:");// Returns: [{ key: "settings:enabled", value: true }, ...]
// すべてのプラグインキーを一覧表示const all = await ctx.kv.list();const deleted = await ctx.kv.delete("state:tempData");// Returns true if key existedキー命名規則
Section titled “キー命名規則”KVデータを整理するためにプレフィックスを使用します:
| プレフィックス | 目的 | 例 |
|---|---|---|
settings: | ユーザー設定可能な設定 | settings:apiKey |
state: | プラグイン内部の状態 | state:lastSync |
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);
// 避けるべき例:プレフィックスなし、目的が不明確await ctx.kv.set("url", url);設定 vs ストレージ vs KV
Section titled “設定 vs ストレージ vs KV”適切なストレージメカニズムを選択します:
| ユースケース | メカニズム |
|---|---|
| 管理者編集可能な設定 | admin.settingsSchema + ctx.kv(settings:付き) |
| プラグイン内部の状態 | ctx.kv(state:付き) |
| ドキュメントのコレクション | ctx.storage |
設定は、管理者が変更する可能性のあるユーザー設定可能な値のためのものです。自動生成されたUIが提供されます。
KVは、タイムスタンプ、同期カーソル、キャッシュされた計算結果などの内部状態のためのものです。UIはなく、コードのみで操作します。
ストレージは、インデックス付きクエリが可能なドキュメントコレクション(フォーム送信、監査ログなど)のためのものです。
ルートでの設定の読み込み
Section titled “ルートでの設定の読み込み”APIルートは、設定を管理者UIコンポーネントに公開できます:
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 }; } }}デフォルト値
Section titled “デフォルト値”settingsSchemaからの設定は自動的には永続化されません。これらは管理者UIでのデフォルト値です。コードでは欠落した値を処理する必要があります:
"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; // ...}または、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); }}ストレージ実装
Section titled “ストレージ実装”KV値は、プラグイン名空間付きのキーで_optionsテーブルに保存されます:
INSERT INTO _options (name, value) VALUES ('plugin:seo:settings:siteTitle', '"私のサイト"'), ('plugin:seo:settings:maxTitleLength', '60');plugin:seo:プレフィックスは自動的に追加されます。コードではsettings:siteTitleを使用し、EmDashはそれをplugin:seo:settings:siteTitleとして保存します。
これにより、プラグインが互いのデータを誤って上書きすることを防ぎます。