初めての native プラグイン

このページ

native プラグインは、EmDash が Astro サイトと同じプロセスにインポートする npm パッケージです。このチュートリアルでは、コンテンツ保存を記録するプラグインを作成し、サイトにインストールして astro.config.mjs に登録します。

プラグインに React 管理コンポーネント、Astro レンダリングコンポーネント、信頼できるページフラグメントなどのインプロセス機能が必要なときは native 形式を使います。フック、ルート、ストレージ、Block Kit で機能をカバーできる場合は、sandboxed プラグインから始めてください。プラグイン形式の選択 が形式を比較します。

前提条件

pnpm を使い、開発サーバーを起動できる EmDash サイトから始めます。サイトはすでに emdash に依存している必要があり、それが下で使う emdash コマンドを提供します。

コマンドはサイトディレクトリを my-emdash-site と呼び、その横に plugin-activity を作成します。my-emdash-site を自分のサイトのディレクトリ名に置き換えてください。

パッケージの作成と登録

  1. サイトの横に native パッケージをスキャフォールドします。

    pnpm exec emdash plugin init --native --name @example/plugin-activity --dir ../plugin-activity

    コマンドはプラグイン ID を作成するときに npm スコープを取り除きます。パッケージ名は @example/plugin-activity、プラグイン ID は plugin-activity です。

  2. パッケージの依存関係をインストールします。

    cd ../plugin-activity
    pnpm install
  3. 生成された src/index.ts をコンテンツ保存フックに置き換えます。

    import { definePlugin } from "emdash";
    import type { PluginDescriptor } from "emdash";
    
    export interface ActivityPluginOptions {
        logUpdates?: boolean;
    }
    
    export function activityPlugin(
        options: ActivityPluginOptions = {},
    ): PluginDescriptor<ActivityPluginOptions> {
        return {
            id: "plugin-activity",
            version: "0.1.0",
            format: "native",
            entrypoint: "@example/plugin-activity",
            options,
        };
    }
    
    export function createPlugin(options: ActivityPluginOptions = {}) {
        return definePlugin({
            id: "plugin-activity",
            version: "0.1.0",
            capabilities: ["content:read"],
            hooks: {
                "content:afterSave": async (event, ctx) => {
                    if (!event.isNew && options.logUpdates === false) return;
    
                    ctx.log.info("Content saved", {
                        collection: event.collection,
                        contentId: event.content.id,
                        isNew: event.isNew,
                    });
                },
            },
        });
    }
    
    export default createPlugin;

    content:afterSave には content:read ケイパビリティが必要です。そのケイパビリティがないとき EmDash はそのフックをスキップします。

  4. パッケージをビルドします。

    pnpm build
  5. ローカルパッケージをサイトにインストールします。

    cd ../my-emdash-site
    pnpm add ../plugin-activity
  6. ディスクリプタファクトリを EmDash 統合に登録します。

    import { defineConfig } from "astro/config";
    import emdash from "emdash/astro";
    import { activityPlugin } from "@example/plugin-activity";
    
    export default defineConfig({
        integrations: [
            emdash({
                plugins: [activityPlugin({ logUpdates: true })],
            }),
        ],
    });

    native ディスクリプタは plugins に置き、sandboxed には置きません。EmDash は sandboxed 配列内の native ディスクリプタを拒否します。

  7. サイトを起動し、管理パネルでエントリーを保存します。

    pnpm dev

    サーバーログには、コレクション、コンテンツ ID、エントリーが作成されたかどうかを含む Content saved が出ます。

ディスクリプタとランタイムの境界

パッケージのエクスポートには 2 つの仕事があります。EmDash はそれぞれを異なる段階で使います。

  • ディスクリプタファクトリ activityPlugin() は、Astro が設定を評価するときに実行されます。シリアライズ可能なビルド時メタデータ id、version、format、entrypoint、options を返します。React と Astro のエントリポイントもこのディスクリプタに属します。
  • 名前付きの createPlugin() エクスポートは、EmDash が初期化するときに実行されます。EmDash はそれを entrypoint からインポートし、シリアライズされた options を渡し、definePlugin() からの解決済みプラグインを期待します。

名前付きの createPlugin エクスポートは必須です。デフォルトエクスポートはパッケージ利用者に有用かもしれませんが、EmDash の native ローダーは createPlugin を名前でインポートします。

id と version はディスクリプタと definePlugin() で同一にしてください。plugin-activity のようなスコープなしの kebab-case プラグイン ID を使い、npm スコープはパッケージ名と entrypoint に残します。これで ID が API ルート URL の単一プラグインセグメントとして使えます。

プラグインの識別とバージョン に受け入れられる ID とバージョンの形があります。

ランタイムの挙動は definePlugin() に置きます。

  • capabilities と allowedHosts
  • storage
  • hooks と routes
  • admin の設定、ページ、ウィジェット、Portable Text の宣言

ディスクリプタは、Astro がビルド時にインポートまたは公開しなければならない静的エントリを運びます。焦点を絞ったガイドは、どの管理フィールドに一致するディスクリプタとランタイム宣言が必要かを示します。

native ルートハンドラ

native ルートハンドラは 1 つの RouteContext を受け取ります。検証済み入力とリクエストデータを通常の PluginContext と組み合わせます。

routes: {
	status: {
		permission: "plugins:read",
		handler: async (ctx) => ({
			pluginId: ctx.plugin.id,
			callerId: ctx.user?.id ?? null,
		}),
	},
},

同等の sandboxed ハンドラは (routeCtx, ctx) を 2 引数で受け取ります。認証、権限、入力スキーマ、ルート URL はその他、共有の API ルート 契約に従います。

request.body を宣言する native ルートは definePluginRoute() でラップしてください。ヘルパーはボディモードから ctx.input を推論します。response: "raw" の native ルートは pluginResponse() を返します。 両方のヘルパーを emdash からインポートしてください。共有の API ルートガイドにボディモード、制限、応答ポリシー、互換性デフォルトがあります。

別のサーフェスを追加する