コンテンツにスキップ

プラグイン設定

プラグインには設定が必要です。APIキー、機能フラグ、表示設定などです。EmDashでは、管理者が設定可能なオプション用の設定スキーマと、プログラムによるアクセス用のKVストアという2つの仕組みを提供しています。

管理者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は、プラグインの管理者セクションに設定フォームを生成します。ユーザーはコードに触れることなく設定を編集できます。

単一行または複数行の文字列用のテキスト入力。

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"
}

APIキーなどの機密情報用の暗号化フィールド。保存後はクライアントに送信されません。

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

フックやルート内で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ストア(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 }>>;
}
// Get a single value
const enabled = await ctx.kv.get<boolean>("settings:enabled");
// 型を指定して取得
const config = await ctx.kv.get<{ url: string; timeout: number }>("state:config");
// Set a value
await ctx.kv.set("settings:lastSync", new Date().toISOString());
// 複雑な値を設定
await ctx.kv.set("state:cache", {
data: items,
expiry: Date.now() + 3600000,
});
// List all settings
const 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

KVデータを整理するためにプレフィックスを使用します:

プレフィックス目的例
settings:ユーザー設定可能な設定settings:apiKey
state:プラグイン内部の状態state:lastSync
cache:キャッシュされたデータcache: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);
// 避けるべき例:プレフィックスなし、目的が不明確
await ctx.kv.set("url", url);

適切なストレージメカニズムを選択します:

ユースケースメカニズム
管理者編集可能な設定admin.settingsSchema + ctx.kv(settings:付き)
プラグイン内部の状態ctx.kv(state:付き)
ドキュメントのコレクションctx.storage

設定は、管理者が変更する可能性のあるユーザー設定可能な値のためのものです。自動生成されたUIが提供されます。

KVは、タイムスタンプ、同期カーソル、キャッシュされた計算結果などの内部状態のためのものです。UIはなく、コードのみで操作します。

ストレージは、インデックス付きクエリが可能なドキュメントコレクション(フォーム送信、監査ログなど)のためのものです。

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 };
}
}
}

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

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として保存します。

これにより、プラグインが互いのデータを誤って上書きすることを防ぎます。