イベントにフック
コンテンツ保存、メディアアップロード、プラグインライフサイクルイベントの前後にコードを実行します。
EmDashのプラグインシステムにより、コアコードを変更せずにCMSを拡張できます。プラグインはコンテンツライフサイクルイベントにフックし、独自のデータを保存し、管理者に設定を公開し、管理パネルにカスタムUIを追加できます。
EmDashプラグインは別個のアプリケーションではなく、設定トランスフォーマーです。これらはAstroサイトと同じプロセスで実行され、明確に定義されたインターフェースを通じて相互作用します。
主要原則:
イベントにフック
コンテンツ保存、メディアアップロード、プラグインライフサイクルイベントの前後にコードを実行します。
データを保存
データベースマイグレーションを書かずに、インデックス付きコレクションにプラグイン固有のデータを永続化します。
設定を公開
設定スキーマを宣言し、設定用の自動生成された管理UIを取得します。
管理ページを追加
Reactコンポーネントでカスタム管理ページとダッシュボードウィジェットを作成します。
APIルートを作成
プラグインの管理UIまたは外部インテグレーション用のエンドポイントを公開します。
HTTPリクエストを実行
セキュリティのため、宣言されたホスト制限で外部APIを呼び出します。
すべてのプラグインはdefinePlugin()で作成されます:
import { definePlugin } from "emdash";
export default definePlugin({ id: "my-plugin", version: "1.0.0",
// プラグインがアクセスを必要とするAPI capabilities: ["read:content", "network:fetch"],
// プラグインがHTTPリクエストを送信できるホスト allowedHosts: ["api.example.com"],
// 永続ストレージコレクション storage: { entries: { indexes: ["userId", "createdAt"], }, },
// イベントハンドラー hooks: { "content:afterSave": async (event, ctx) => { ctx.log.info("Content saved", { id: event.content.id }); }, },
// REST APIエンドポイント routes: { status: { handler: async (ctx) => ({ ok: true }), }, },
// 管理UI設定 admin: { settingsSchema: { apiKey: { type: "secret", label: "API Key" }, }, pages: [{ path: "/dashboard", label: "Dashboard" }], widgets: [{ id: "status", size: "half" }], },});すべてのフックとルートハンドラーは、以下へのアクセス権を持つPluginContextオブジェクトを受け取ります:
| プロパティ | 説明 | 可用性 |
|---|---|---|
ctx.storage | プラグインのドキュメントコレクション | 常時 (宣言されている場合) |
ctx.kv | 設定と状態のためのキーバリューストア | 常時 |
ctx.content | サイトコンテンツの読み書き | read:contentまたはwrite:contentを持つ場合 |
ctx.media | メディアファイルの読み書き | read:mediaまたはwrite:mediaを持つ場合 |
ctx.http | 外部リクエストのためのHTTPクライアント | network:fetchを持つ場合 |
ctx.log | 構造化ロガー (debug, info, warn, error) | 常時 |
ctx.plugin | プラグインメタデータ (id, version) | 常時 |
ctx.site | サイト情報: name, url, locale | 常時 |
ctx.url() | パスから絶対URLを生成 | 常時 |
ctx.users | ユーザー情報の読み取り: get(), getByEmail(), list() | read:usersを持つ場合 |
ctx.cron | タスクのスケジュール: schedule(), cancel(), list() | 常時 |
ctx.email | メール送信: send() | email:send + プロバイダー設定済みの場合 |
コンテキストの形状はすべてのフックとルートで同一です。能力で制限されたプロパティは、プラグインが必要な能力を宣言した場合にのみ存在します。
能力は、プラグインコンテキストでどのAPIが利用可能かを決定します:
| 能力 | アクセス権を付与 |
|---|---|
read:content | ctx.content.get(), ctx.content.list() |
write:content | ctx.content.create(), ctx.content.update(), ctx.content.delete() |
read:media | ctx.media.get(), ctx.media.list() |
write:media | ctx.media.getUploadUrl(), ctx.media.upload(), ctx.media.delete() |
network:fetch | ctx.http.fetch() (allowedHostsに制限) |
network:fetch:any | ctx.http.fetch() (無制限 — ユーザー設定URL用) |
read:users | ctx.users.get(), ctx.users.getByEmail(), ctx.users.list() |
email:send | ctx.email.send() (プロバイダープラグインが必要) |
email:provide | email:deliver排他フックの登録 (トランスポートプロバイダー) |
email:intercept | email:beforeSend / email:afterSendフックの登録 |
page:inject | page:metadata / page:fragmentsフックの登録 |
Astro設定でプラグインを登録します:
typescript title="astro.config.mjs"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 })], }), ],});プラグインはビルド時に解決されます。同じ優先度を持つフックの場合、順序が重要です—配列内で先に指定されたプラグインが最初に実行されます。
EmDashは2つのプラグイン実行モードをサポートしています:
| モード | 説明 | プラットフォーム |
|---|---|---|
| 信頼済み | プラグインはフルアクセス権限でプロセス内で実行されます | 任意 |
| サンドボックス化 | プラグインは分離されたV8ワーカーで実行されます | Cloudflareのみ |
信頼済みモード(デフォルト)では、機能は文書化された通りです—プラグインは何にでもアクセスできます。サンドボックス化モードでは、機能はランタイムレベルで強制されます。
プラグインを作成
ストレージ、フック、管理UIを備えた最初のプラグインを構築します。
利用可能なフック
コンテンツ、メディア、プラグインライフサイクルのすべてのフックを閲覧します。
プラグインストレージ
ストレージについて学び、プラグインデータのクエリ方法を理解します。
管理UI
管理ページを追加し、ダッシュボードウィジェットを設定します。
サンドボックスセキュリティ
CloudflareとNode.jsのデプロイメント全体でのサンドボックス分離を理解します。