本指南從零開始建置一個最小的沙箱外掛程式。該外掛程式記錄每次內容儲存並公開一個 API 路由。它在由設定的沙箱執行器提供的隔離執行環境中執行。當網站操作員將其從 sandboxed: [] 移動到 plugins: [] 時(例如在沒有沙箱執行器的平台上),相同的程式碼也會在處理程序內執行。
如果你還沒有在沙箱和原生之間做出決定,請先閱讀選擇外掛程式格式。
兩個部分
一個沙箱外掛程式包含:
emdash-plugin.jsonc— 手動編輯的清單:身份、信任契約(capabilities、hosts、storage)和設定檔欄位。無程式碼。src/plugin.ts— 執行環境:鉤子和路由。僅從emdash/plugin匯入型別;無執行時emdash匯入。
emdash-plugin build 讀取兩者並產生網站使用的 dist/ 工件。
以下範例顯示了完整外掛程式的檔案配置:
my-plugin/
├── emdash-plugin.jsonc # 身份 + 信任契約 + 設定檔
├── src/
│ └── plugin.ts # 鉤子、路由 — 在沙箱執行環境中執行
├── package.json
└── tsconfig.json
設定套件
-
建立目錄和
package.json。建置命令是emdash-plugin build;無需編寫tsdown呼叫。{ "name": "@my-org/plugin-hello", "version": "0.1.0", "type": "module", "main": "dist/index.mjs", "exports": { ".": { "import": "./dist/index.mjs", "types": "./dist/index.d.mts" }, "./sandbox": "./dist/plugin.mjs" }, "files": ["dist", "emdash-plugin.jsonc"], "scripts": { "build": "emdash-plugin build", "dev": "emdash-plugin dev" }, "peerDependencies": { "emdash": ">=0.13.0" }, "devDependencies": { "@emdash-cms/plugin-cli": "0.2.0", "emdash": ">=0.13.0", "typescript": "^5.9.0" } }"."是網站匯入的產生描述符;"./sandbox"是建置的執行時檔案。emdash-plugin build產生兩者。 -
新增
tsconfig.json:{ "compilerOptions": { "target": "ES2022", "module": "preserve", "moduleResolution": "bundler", "strict": true, "esModuleInterop": true, "verbatimModuleSyntax": true, "skipLibCheck": true, "types": [] }, "include": ["src/**/*"], "exclude": ["node_modules"] }
編寫清單
emdash-plugin.jsonc 包含外掛程式的身份(slug)、其信任契約(capabilities、allowedHosts、storage)、設定檔欄位和發布者固定。
以下範例顯示了 hello 外掛程式的完整清單:
{
"$schema": "./node_modules/@emdash-cms/plugin-cli/schemas/emdash-plugin.schema.json",
"slug": "plugin-hello",
"publisher": "did:plc:abc123def456", // your Atmosphere account DID
"license": "MIT",
"author": { "name": "Jane Doe", "url": "https://example.com" },
"security": { "email": "security@example.com" },
"capabilities": [],
"allowedHosts": [],
"storage": { "events": { "indexes": ["timestamp"] } }
}
關於此清單的說明:
slug是 URL 安全的 ID,不是 npm 套件名稱。/^[a-z][a-z0-9_-]*$/,最大 64 個字元。它是外掛程式路由 URL(/_emdash/api/plugins/<slug>/...)中的單一路徑段,也是為儲存索引產生的 SQL 識別符的一部分,因此@、/、前導數字和大寫字母都會失敗。將無作用域的slug(plugin-hello)與有作用域的 npm 套件名稱配對。storage提前宣告集合。ctx.storage.events在執行時工作只是因為events在這裡宣告了。存取未宣告的集合會拋出錯誤。- 省略了
version。 建置從package.json讀取它,因此有一個唯一的真實來源。參見清單參考。 - 信任契約是同意。 稍後變更
capabilities、allowedHosts或storage需要版本升級 — 已安裝的網站已同意舊契約。
編寫執行環境
src/plugin.ts 預設匯出一個用 satisfies SandboxedPlugin 標註的簡單物件。emdash/plugin 僅提供型別,因此沙箱外掛程式對 emdash 沒有執行時相依性。
以下範例將每次內容儲存記錄到外掛程式儲存中,並公開一個傳回最後十次儲存的 recent 路由:
import type { SandboxedPlugin } from "emdash/plugin";
export default {
hooks: {
"content:afterSave": {
handler: async (event, ctx) => {
ctx.log.info("Content saved", {
collection: event.collection,
id: event.content.id,
});
await ctx.storage.events.put(`save-${Date.now()}`, {
timestamp: new Date().toISOString(),
collection: event.collection,
contentId: event.content.id,
});
},
},
},
routes: {
recent: {
handler: async (_routeCtx, ctx) => {
const result = await ctx.storage.events.query({ limit: 10 });
return { events: result.items };
},
},
},
} satisfies SandboxedPlugin;
關於執行時檔案的說明:
satisfies SandboxedPlugin型別化一切。 它從鉤子名稱推斷event(具有完整的規範事件型別)和ctx作為PluginContext,因此處理程式不需要參數標註。像"content:afterSav"這樣的拼寫錯誤的鉤子鍵是編譯錯誤。- 鉤子處理程式接受
(event, ctx)。 事件形狀取決於鉤子名稱;請參閱鉤子指南。 - 路由處理程式接受
(routeCtx, ctx)— 兩個參數。routeCtx是{ input, request, requestMeta? };ctx是相同的PluginContext。路由可在/_emdash/api/plugins/<slug>/<route-name>存取。 ctx.storage.events起作用是因為events在清單中宣告了。ctx.kv始終可用 — 每個外掛程式的鍵值儲存,具有get、set、delete、list(prefix)。
註冊外掛程式
在網站的 astro.config.mjs 中,匯入外掛程式的預設匯出並傳遞它。沙箱外掛程式放在 sandboxed: [] 中;處理程序內外掛程式放在 plugins: [] 中。沙箱外掛程式在兩者中都有效。以下範例使用 sandboxed::
import { defineConfig } from "astro/config";
import emdash from "emdash/astro";
import { sandbox } from "@emdash-cms/cloudflare";
import hello from "@my-org/plugin-hello";
export default defineConfig({
integrations: [
emdash({
sandboxed: [hello],
sandboxRunner: sandbox(),
}),
],
});
sandboxRunner 是可插拔的部分。該範例使用來自 @emdash-cms/cloudflare 的 sandbox(),這是當今大多數網站使用的執行器。如果沒有設定執行器(或設定的執行器在目前平台上不可用),sandboxed: [] 外掛程式在啟動時會被跳過 — 將外掛程式移至 plugins: [] 以在處理程序內執行它。
建置和執行
從外掛程式目錄:
emdash-plugin validate # 首先檢查清單架構
emdash-plugin build # 產生 dist/
對於編輯迴圈,執行 emdash-plugin dev(在儲存時重建,在建置失敗時保留最後的良好 dist/)。在網站中,安裝或連結外掛程式(pnpm add file:../plugin-hello 或工作區連結)並啟動開發伺服器。在管理員中儲存一段內容,你應該在日誌中看到 Content saved …;GET /_emdash/api/plugins/plugin-hello/recent 傳回最後十個儲存事件。
接下來閱讀什麼
- 清單 — 每個欄位、信任契約、發布者固定
emdash-pluginCLI —build、dev、bundle- 鉤子 — 完整的事件集
- API 路由 — 輸入驗證、公共路由、錯誤
- 儲存和 KV — 查詢選項、索引、批次處理操作
- Capabilities 和安全性 — 內容存取、網路、主機允許清單
- 打包和發布 — 運送到市場