EmDash 通过两个文件配置:astro.config.mjs 用于集成,src/live.config.ts 用于内容集合。
Astro 集成
在 astro.config.mjs 中将 EmDash 配置为 Astro 集成:
import { defineConfig } from "astro/config";
import emdash, { local, s3 } from "emdash/astro";
import { sqlite, libsql } from "emdash/db";
export default defineConfig({
integrations: [
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
plugins: [],
}),
],
});
集成选项
database
必需。 数据库适配器配置。选择一个适配器:
// SQLite(Node.js)
database: sqlite({ url: "file:./data.db" });
// PostgreSQL
database: postgres({ connectionString: process.env.DATABASE_URL });
// libSQL
database: libsql({
url: process.env.LIBSQL_DATABASE_URL,
authToken: process.env.LIBSQL_AUTH_TOKEN,
});
// Cloudflare D1(从 @emdash-cms/cloudflare 导入)
database: d1({ binding: "DB" });
详见数据库选项。
migrations
可选。 控制 EmDash 内部数据库迁移的运行时处理。省略此选项时默认为 { runtime: "auto" }。
migrations: {
runtime: "check", // "auto" | "check" | "manual"
dev: "auto", // 可选的开发覆盖
}
auto 检查并应用待执行的迁移,check 在运行构建已知的迁移待执行时返回 503,manual 不执行运行时迁移查询。EMDASH_MIGRATIONS_MODE 覆盖有效的运行时模式。在采用 check 或 manual 之前参见管理核心数据库迁移。
storage
必需。 媒体存储适配器配置。选择一个适配器:
// 本地文件系统(开发环境)
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
});
// R2 绑定(Cloudflare Workers)
storage: r2({
binding: "MEDIA",
publicUrl: "https://pub-xxxx.r2.dev", // 可选
});
// S3 兼容(任何平台)— 所有字段来自 S3_* 环境变量
storage: s3()
// 或使用显式值
storage: s3({
endpoint: "https://s3.amazonaws.com",
bucket: "my-bucket",
accessKeyId: process.env.S3_ACCESS_KEY_ID,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
region: "us-east-1", // 可选,默认:"auto"
publicUrl: "https://cdn.example.com", // 可选
});
详见存储选项。
objectCache
可选。 在键值存储中缓存内容和配置查询结果,使读取无需在每次请求时查询数据库。省略时禁用。选择一个适配器:
// Cloudflare KV(跨所有隔离器共享)
import { kvCache } from "@emdash-cms/cloudflare";
objectCache: kvCache({ binding: "CACHE" });
// 内存(Node.js / 开发环境)
import { memoryCache } from "emdash/astro";
objectCache: memoryCache();
详见对象缓存了解设置和选项。
middleware.outer
可选。 在完整的 EmDash 中间件栈外部注册一个 Astro 中间件模块。因为集成使用 Astro order: "pre" 注册它,它也会在 src/middleware.ts 中定义的中间件之前运行。用于必须在命中时避免运行时和数据库初始化的请求门控或完整响应缓存,或用于依赖 EmDash 最终 HTML 的响应头。
emdash({
middleware: {
outer: "./src/outer-middleware.ts",
},
});
执行顺序是:
- 外部中间件运行到
await next()。 - EmDash 初始化其运行时和数据库,然后运行设置、身份验证和请求上下文中间件。
- Astro 路由渲染。
- EmDash 应用响应变更,包括可视化编辑 HTML 和安全/计时头。
next()使用该最终响应解析回外部中间件。
在调用 next() 之前,中间件拥有正常的 Astro 请求和平台执行上下文,但 locals.emdash、locals.user、数据库和请求作用域的 EmDash 状态不可用。提前返回 Response 会完全跳过 EmDash,因此它必须包含其需要的任何安全和缓存头。在 next() 解析后,可以安全地最终确定 CSP nonce、缓存完整 body 或设置 Content-Length。如果中间件更改了 body,请移除或重新计算任何现有的 Content-Length 头。
该钩子在 Node 和 Cloudflare 上都使用 Astro 的中间件 API。以下最小的 Cloudflare Cache API 示例仅缓存匿名 HTML 响应,并在 EmDash 初始化之前返回命中:
import { waitUntil } from "cloudflare:workers";
import { defineMiddleware } from "astro:middleware";
export const onRequest = defineMiddleware(async ({ request }, next) => {
if (request.method !== "GET" || request.headers.has("cookie")) {
return next();
}
const cacheKey = new Request(request.url, { method: "GET" });
const cached = await caches.default.match(cacheKey);
if (cached) return cached;
const response = await next();
const isHtml = response.headers.get("content-type")?.includes("text/html");
const isPrivate = response.headers.get("cache-control")?.includes("no-store");
if (response.ok && isHtml && !isPrivate) {
waitUntil(caches.default.put(cacheKey, response.clone()));
}
return response;
});
在 Node 上,使用相同的中间件形式配合 Node 兼容的缓存(如 Redis)。缓存键和绕过规则必须包含改变渲染响应的每个请求属性。
plugins
可选。 EmDash 插件数组。以下示例注册一个插件:
import seoPlugin from "@emdash-cms/plugin-seo";
plugins: [seoPlugin()];
fonts
可选。 管理 UI 字体配置。
默认情况下,EmDash 通过 Astro Font API 加载 Noto Sans。字体在构建时从 Google 下载并自托管,因此没有运行时 CDN 请求。基础字体覆盖拉丁文、西里尔文、希腊文、天城文和越南文字。
要添加对其他书写系统的支持,请传入脚本名称。以下示例添加阿拉伯文和日文:
emdash({
fonts: {
scripts: ["arabic", "japanese"],
},
})
可用的脚本包括 arabic、armenian、bengali、chinese-simplified、chinese-traditional、chinese-hongkong、devanagari、ethiopic、farsi、georgian、gujarati、gurmukhi、hebrew、japanese、kannada、khmer、korean、lao、malayalam、myanmar、oriya、sinhala、tamil、telugu、thai 和 tibetan。
每个脚本映射到 Google Fonts 上对应的 Noto Sans 变体(例如 "arabic" 加载 Noto Sans Arabic)。所有字体面共享一个 font-family 名称并使用 unicode-range,因此浏览器只下载页面上字符所需的文件。
设置为 false 以完全禁用字体注入并使用系统字体:
emdash({
fonts: false,
})
管理 CSS 使用 --font-emdash CSS 变量。这由上述字体配置自动设置。
auth
可选。 身份验证适配器。EmDash 内置的登录方式是通行密钥;设置 auth 会将其替换为外部提供者。Cloudflare Access 适配器 access() 由 @emdash-cms/cloudflare 提供:
import { access } from "@emdash-cms/cloudflare";
emdash({
auth: access({
teamDomain: "myteam.cloudflareaccess.com",
audience: "your-app-audience-tag",
roleMapping: {
Admins: 50,
Editors: 40,
},
}),
});
access() 的选项:
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
teamDomain | string | 必需 | 您的 Cloudflare Access 团队域名 |
audience | string | — | 应用程序 Audience(AUD)标签。在 Workers 上,优先使用 audienceEnvVar。 |
audienceEnvVar | string | "CF_ACCESS_AUDIENCE" | 运行时读取 audience 标签的环境变量 |
autoProvision | boolean | true | 首次登录时创建 EmDash 用户 |
defaultRole | number | 30 | 未被 roleMapping 匹配的用户的角色级别(参见用户角色) |
syncRoles | boolean | false | 每次登录时重新应用 roleMapping 而不仅在预配置时 |
roleMapping | object | — | 将 IdP 组名映射到 EmDash 角色级别;第一个匹配获胜 |
authProviders
可选。 可插拔登录提供者的数组(顶级,与 auth 并列)。每个条目是调用提供者工厂的结果,如下所示:
import { github } from "emdash/auth/providers/github";
import { google } from "emdash/auth/providers/google";
import { atproto } from "@emdash-cms/auth-atproto";
emdash({
authProviders: [github(), google(), atproto()],
});
内置提供者:
github()— 读取EMDASH_OAUTH_GITHUB_CLIENT_ID/EMDASH_OAUTH_GITHUB_CLIENT_SECRET(或无前缀的回退)。google()— 读取EMDASH_OAUTH_GOOGLE_CLIENT_ID/EMDASH_OAUTH_GOOGLE_CLIENT_SECRET。atproto()— Atmosphere 账户登录(Bluesky 和更广泛的 AT Protocol 网络)。无需环境变量。接受{ allowedDIDs, allowedHandles, defaultRole }。参见 Atmosphere 登录指南。
第三方包可以使用相同的 AuthProviderDescriptor 形式注册自己的提供者——参见登录提供者。
siteUrl
可选。 站点面向浏览器的公共来源(协议 + 主机 + 可选端口,无路径)。
在 TLS 终止反向代理后面,Astro.url 返回内部地址(http://localhost:4321)而不是公共地址(https://cms.example.com)。这会导致通行密钥、CSRF 来源匹配、OAuth 重定向、登录重定向、MCP 发现、快照导出、sitemap、robots.txt 和 JSON-LD 结构化数据出错。设置 siteUrl 一次性修复所有这些问题。
集成在加载时验证此值:它必须是带有 http: 或 https: 协议的有效 URL,并被规范化为来源(路径被剥离)。
以下示例设置公共来源:
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
siteUrl: "https://cms.example.com",
});
当配置中未设置 siteUrl 时,EmDash 按顺序检查环境变量:EMDASH_SITE_URL,然后 SITE_URL。这对于公共 URL 在运行时设置的容器部署很有用。
在 Cloudflare Workers 上,环境变量回退读取 process.env,除非启用了 nodejs_compat_populate_process_env 兼容性标志,否则它是空的。要在那里使用环境变量而不是配置选项,请同时设置两者:
// wrangler.jsonc
{
"compatibility_flags": ["nodejs_compat", "nodejs_compat_populate_process_env"],
"vars": { "EMDASH_SITE_URL": "https://cms.example.com" },
}
多来源通行密钥验证
siteUrl 定义单一规范来源。当同一个 EmDash 部署可通过共享可注册父域名的多个主机名访问时(例如 https://example.com 和 https://preview.example.com),通行密钥验证会拒绝来源与 siteUrl 不完全匹配的断言——即使 WebAuthn 允许通行密钥在同一 rpId 下的子域名间有效。
通过 astro.config.mjs 中的 allowedOrigins 或 EMDASH_ALLOWED_ORIGINS 环境变量声明额外接受的来源。规范的 siteUrl 保持为 rpId 的来源;此处列出的条目在验证时被接受。两个来源在运行时合并,因此配置可以声明稳定的来源(版本化、经过代码审查),而环境变量添加特定于环境的额外来源(例如临时 PR 预览)。
以下示例在配置中声明一个额外来源:
emdash({
siteUrl: "https://example.com",
allowedOrigins: ["https://preview.example.com"],
})
等效的值也可以来自环境变量:
EMDASH_SITE_URL=https://example.com
EMDASH_ALLOWED_ORIGINS=https://preview.example.com,https://staging.example.com
验证
EmDash 验证这些值以防止浏览器永远不会尊重的无效配置:
- 每个条目必须是可解析的
http:或https:URL,主机名中没有尾随点和空标签。 - 当
allowedOrigins非空时,siteUrl必须设置(任一来源)且不能是 IP 字面量或具有尾随点主机名。 - 每个来源必须与
siteUrl是相同的主机名或其子域名。(WebAuthn 要求rpId是每个来源的可注册后缀。)
验证失败时,您将看到标注来源的错误,如 EmDash config error in EMDASH_ALLOWED_ORIGINS: "https://other-site.com" is not a subdomain of siteUrl "https://example.com". Allowed origins must be the same hostname as siteUrl or a subdomain of it.
错误出现的位置取决于值的声明位置:
- Astro 启动时,当
config.allowedOrigins和config.siteUrl都来自astro.config.mjs时——代码中的拼写错误会导致构建失败。 - 首次通行密钥验证时,当任一值来自
EMDASH_ALLOWED_ORIGINS或EMDASH_SITE_URL时——环境不匹配在首次验证尝试时以 500 错误出现。
反向代理设置
Astro 仅在公共主机被允许时反映 X-Forwarded-*。为您的用户访问的主机名(和协议)配置 security.allowedDomains。在 astro dev 中,添加匹配的 vite.server.allowedHosts 以便 Vite 接受代理 Host 头。
优先修复 allowedDomains(和转发头);当重建的 URL 仍然与浏览器来源不同时使用 siteUrl(典型场景是 TLS 在前面终止而上游请求保持 http://)。
使用前端 TLS 时,将开发服务器绑定到回环地址(astro dev --host 127.0.0.1)通常就足够了:代理在本地连接,而 siteUrl 匹配公共 HTTPS 来源。
如果您的代理写入客户端 IP 头,请设置 trustedProxyHeaders,以便 EmDash 的速率限制可以使用真实的客户端 IP,而不是将所有请求归入共享的”未知”桶。
以下配置同时为反向代理部署设置 allowedDomains、vite.server.allowedHosts 和 siteUrl:
import { defineConfig } from "astro/config";
import emdash, { local } from "emdash/astro";
import { sqlite } from "emdash/db";
export default defineConfig({
security: {
allowedDomains: [
{ hostname: "cms.example.com", protocol: "https" },
{ hostname: "cms.example.com", protocol: "http" },
],
},
vite: {
server: {
allowedHosts: ["cms.example.com"],
},
},
integrations: [
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
siteUrl: "https://cms.example.com",
}),
],
});
trustedProxyHeaders
可选。 在您控制的反向代理后面运行时,用于客户端 IP 解析的可信头。被身份验证速率限制(魔法链接、注册、通行密钥、OAuth 设备流)和公共评论端点使用。
在 Cloudflare 上,附加到请求的 cf 对象自动使用——您通常不需要设置此项。在 nginx、Caddy、Traefik、Fly、Railway 或类似服务后面的自托管部署上,将其设置为代理写入的头,以便速率限制可以按真实客户端 IP 分桶,而不是将每个请求视为”未知”。
以下示例信任 nginx、Caddy 或 Traefik 设置的 x-real-ip 头:
emdash({
database: sqlite({ url: "file:./data.db" }),
trustedProxyHeaders: ["x-real-ip"],
});
头按顺序尝试。匹配 *-forwarded-for 的值被解析为逗号分隔列表,使用第一个条目。以下示例优先使用 Fly.io 的头,回退到 x-forwarded-for:
emdash({
trustedProxyHeaders: ["fly-client-ip", "x-forwarded-for"],
});
当配置中未设置时,EmDash 读取 EMDASH_TRUSTED_PROXY_HEADERS 环境变量(逗号分隔)。配置中的显式空数组会覆盖环境变量。
maxUploadSize
可选。 媒体文件上传的最大允许大小(字节)。适用于直接多部分上传和签名 URL 上传。默认为 52_428_800(50 MB)。以下示例将限制提高到 100 MB:
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
}),
maxUploadSize: 100 * 1024 * 1024, // 100 MB
});
| 值 | 描述 |
|---|---|
number(字节) | 必须是正有限整数 |
| 省略 | 默认为 50 MB |
超出配置限制的上传在直接上传路径上被 413 Payload Too Large 响应拒绝,在签名 URL 路径上被 400 Validation Error 拒绝。
toolbar
可选。 控制编辑器工具栏(公共页面上的浮动按钮)的交付方式。默认为 "server"。
| 值 | 行为 |
|---|---|
"server"(默认) | 工具栏在每个为已认证编辑者渲染的 HTML 响应中服务端注入。 |
"client" | 公共 HTML 对每个访问者相同。一个小型引导脚本在已登录管理面板的浏览器中显示”Edit”按钮;点击它验证会话并使用 _edit 查询参数重新加载页面,该参数始终新鲜渲染(不缓存)并带有完整工具栏。 |
false | 不渲染工具栏或引导脚本。 |
emdash({
toolbar: "client",
})
当公共 HTML 通过共享缓存(Cloudflare Cache Everything / Workers Cache、Fastly、Varnish 等)提供时使用 "client"。使用服务端注入时,浏览公共站点的编辑者在匿名访问者首先填充缓存时会收到缓存的匿名变体——没有工具栏——因此工具栏随缓存状态出现和消失。在客户端模式下,没有会话特定内容注入到可共享的 HTML 中,因此缓存保持完全有效,工具栏也是可靠的。
关于 "client" 模式的说明:
- 打开共享
?_editURL 的未登录访问者被重定向到规范 URL,因此该参数不会泄露草稿或用页面内容填充额外的缓存条目。 - “已登录”信号是管理面板设置的非机密
localStorage标志;按钮在进入编辑视图前验证真实会话。 - 引导程序是一个小型内联
<script>。如果您的站点发送没有'unsafe-inline'的严格Content-Security-Policy,请为其添加哈希——服务端注入的工具栏也同样适用。 - EmDash 不注入任何会话特定内容——但如果您自己的模板基于
Astro.locals.user分支(例如为登录用户显示”Admin”导航链接),该差异仍在您的 HTML 中,仍会碎片化缓存。
在所有模式下,工具栏可以通过其 × 按钮在浏览器中关闭(每个浏览器,直到编辑者下次打开管理面板)。预览和编辑模式的响应始终带有 Cache-Control: private, no-store 服务端渲染。
experimental
可选。 选择加入的功能,其行为或传输格式可能在次要版本中更改或被移除。每个字段独立启用。
experimental.registry
可选。 将管理面板的插件浏览和安装流程指向联邦插件注册表而非中心化市场。需要 sandboxRunner,因为注册表插件在沙盒中运行。
传入裸聚合器 URL 字符串,或在需要标签方或发布时效策略时使用对象。以下示例使用对象形式:
import { sandbox } from "@emdash-cms/cloudflare";
emdash({
sandboxRunner: sandbox(),
experimental: {
registry: {
aggregatorUrl: "https://registry.emdashcms.com",
acceptLabelers: "did:web:labels.emdashcms.com",
policy: {
minimumReleaseAge: "48h",
minimumReleaseAgeExclude: ["did:plc:yourfirstpartydid"],
},
},
},
});
| 选项 | 类型 | 描述 |
|---|---|---|
aggregatorUrl | string | 注册表 XRPC 端点挂载的聚合器来源。生产环境中为 HTTPS。 |
acceptLabelers | string | 可选的逗号分隔裸标签方 DID,用作经过验证的请求和缓存声明。不能覆盖聚合器策略。 |
policy.minimumReleaseAge | string | number | 暂缓新于此时效的发布版本。持续时间字符串("48h"、"7d")或秒数。 |
policy.minimumReleaseAgeExclude | string[] | 不受暂缓限制的 DID(或 <did>/<slug> 对)。 |
参见插件注册表了解完整工作流、信任模型以及如何从您自己的站点查询注册表。
数据库适配器
从 emdash/db 导入适配器:
import { sqlite, libsql, postgres } from "emdash/db";
sqlite(config)
使用 Node.js 内置数据库驱动的 SQLite 数据库。以下示例连接到本地文件:
| 选项 | 类型 | 描述 |
|---|---|---|
url | string | 带有 file: 前缀的文件路径 |
sqlite({ url: "file:./data.db" });
libsql(config)
libSQL 数据库。以下示例连接到远程 libSQL 数据库:
| 选项 | 类型 | 描述 |
|---|---|---|
url | string | 数据库 URL |
authToken | string | 运行时认证令牌(本地文件可选) |
migrationAuthTokenEnv | string | 迁移令牌变量名(默认 TURSO_AUTH_TOKEN) |
libsql({
url: process.env.LIBSQL_DATABASE_URL,
authToken: process.env.LIBSQL_AUTH_TOKEN,
});
postgres(config)
带连接池的 PostgreSQL 数据库。
| 选项 | 类型 | 描述 |
|---|---|---|
connectionString | string | PostgreSQL 连接 URL |
host | string | 数据库主机 |
port | number | 数据库端口 |
database | string | 数据库名称 |
user | string | 数据库用户 |
password | string | 数据库密码 |
ssl | boolean | 启用 SSL |
pool.min | number | 最小池大小(默认:0) |
pool.max | number | 最大池大小(默认:10) |
pool.connectionTimeoutMillis | number | 最大连接等待时间(pg 默认:0,无超时) |
pool.idleTimeoutMillis | number | 空闲客户端生命周期(pg 默认:10,000 毫秒) |
migrationConnectionStringEnv | string | 迁移连接字符串变量名(默认 DATABASE_URL) |
以下示例使用连接字符串连接:
postgres({ connectionString: process.env.DATABASE_URL });
d1(config)
Cloudflare D1 数据库。从 @emdash-cms/cloudflare 导入。
| 选项 | 类型 | 默认值 | 描述 |
|---|---|---|---|
binding | string | — | wrangler.jsonc 中的 D1 绑定名称 |
session | string | "disabled" | 读取复制模式:"disabled"、"auto" 或 "primary-first" |
bookmarkCookie | string | "__em_d1_bookmark" | 会话书签的 Cookie 名称 |
以下示例展示了基本绑定和启用读取副本的绑定:
// 基本
d1({ binding: "DB" });
// 启用读取副本
d1({ binding: "DB", session: "auto" });
当 session 为 "auto" 或 "primary-first" 时,EmDash 使用 D1 Sessions API 将读取查询路由到附近的副本。已认证用户获得基于书签的读己所写一致性。详见数据库选项 — 读取副本。
存储适配器
从 emdash/astro 导入 local 和 s3。r2 适配器从 @emdash-cms/cloudflare 导入:
import emdash, { local, s3 } from "emdash/astro";
import { r2 } from "@emdash-cms/cloudflare";
local(config)
本地文件系统存储。以下示例从本地目录提供上传:
| 选项 | 类型 | 描述 |
|---|---|---|
directory | string | 目录路径 |
baseUrl | string | 文件服务的基 URL |
local({
directory: "./uploads",
baseUrl: "/_emdash/api/media/file",
});
r2(config)
Cloudflare R2 绑定。以下示例使用带公共 URL 的 R2 绑定:
| 选项 | 类型 | 描述 |
|---|---|---|
binding | string | R2 绑定名称 |
publicUrl | string | 可选的公共 URL |
r2({
binding: "MEDIA",
publicUrl: "https://pub-xxxx.r2.dev",
});
s3(config?)
S3 兼容存储。所有配置字段都是可选的:在 Node 进程启动时,从 s3({...}) 中省略的任何字段都从匹配的 S3_* 环境变量中解析。显式值始终优先。
前提条件: 在项目中安装 @aws-sdk/client-s3 和 @aws-sdk/s3-request-presigner。EmDash 核心不捆绑 AWS SDK。详见存储选项:S3 兼容存储。
| 选项 | 类型 | 描述 |
|---|---|---|
endpoint | string | S3 端点 URL(S3_ENDPOINT) |
bucket | string | 存储桶名称(S3_BUCKET) |
accessKeyId | string | 访问密钥(S3_ACCESS_KEY_ID) |
secretAccessKey | string | 秘密密钥(S3_SECRET_ACCESS_KEY) |
region | string | 区域,默认 "auto"(S3_REGION) |
publicUrl | string | 可选 CDN URL(S3_PUBLIC_URL) |
以下示例从环境解析所有字段、混合配置和环境,或显式传递每个字段:
// 所有字段来自 S3_* 环境变量(Node 容器部署)
s3()
// 混合:CDN 来自配置,其余来自环境
s3({ publicUrl: "https://cdn.example.com" })
// 全部显式
s3({
endpoint: "https://xxx.r2.cloudflarestorage.com",
bucket: "media",
accessKeyId: process.env.R2_ACCESS_KEY_ID,
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
publicUrl: "https://cdn.example.com",
})
运行时环境变量解析是 Node 专有功能。在 Cloudflare Workers 上,密钥和变量通过 fetch 处理程序的 env 参数暴露,而不是通过 process.env,因此 S3_* 环境变量不会被获取。Workers 部署应使用 r2(config) 适配器或向 s3({...}) 传递显式值。详见存储选项。
对象缓存适配器
将以下之一传递给 objectCache 选项。
kvCache(config)
Cloudflare KV 后端,跨所有隔离器共享。从 @emdash-cms/cloudflare 导入。
kvCache({
binding: "CACHE", // KV 绑定名称(必需)
defaultTtl: 3600, // 条目 TTL(秒,可选,KV 最小 60)
revalidate: 1000, // 跨隔离器过期窗口(毫秒,可选)
timeout: 2000, // 每操作超时(毫秒,超时前为未命中,可选,0 禁用)
keyPrefix: "em", // 缓存键前缀(可选)
})
memoryCache(config?)
用于 Node.js 和开发的进程内后端。从 emdash/astro 导入。
memoryCache({
defaultTtl: 3600, // 条目 TTL(秒,可选)
revalidate: 1000, // 过期窗口(毫秒,可选)
maxEntries: 1000, // 驱逐前的最大缓存键数(可选)
keyPrefix: "em", // 缓存键前缀(可选)
})
详见对象缓存了解设置和行为。
Live Collections
在 src/live.config.ts 中配置 EmDash loader:
import { defineLiveCollection } from "astro:content";
import { emdashLoader } from "emdash/runtime";
export const collections = {
_emdash: defineLiveCollection({
loader: emdashLoader(),
}),
};
Loader 选项
emdashLoader() 函数不接受参数:
emdashLoader();
环境变量
EmDash 识别以下环境变量:
| 变量 | 描述 |
|---|---|
EMDASH_SITE_URL | 面向浏览器的公共来源(回退到 SITE_URL) |
EMDASH_ALLOWED_ORIGINS | 逗号分隔的通行密钥验证接受的额外来源列表(多子域名部署)。 |
EMDASH_DATABASE_URL | 覆盖数据库 URL |
EMDASH_ENCRYPTION_KEY | 用于加密静态存储的插件密钥的密钥。由运维人员提供——永远不存储在数据库中。 |
EMDASH_PREVIEW_SECRET | 可选的预览 HMAC 密钥覆盖。未设置时,会生成一个稳定的每站点值并存储在数据库中。 |
EMDASH_IP_SALT | 可选的评论者 IP 哈希盐覆盖。未设置时,会生成一个稳定的每站点值并存储在数据库中。 |
EMDASH_AUTH_SECRET | 旧版。如果设置,用作 IP 盐来源;现有安装应保留此项以在升级后保持稳定的评论者 IP 哈希。 |
EMDASH_TURNSTILE_SECRET_KEY | Cloudflare Turnstile 密钥(回退到 TURNSTILE_SECRET_KEY)。设置后,评论提交必须包含有效的 Turnstile 令牌——将其与 <CommentForm> 上的 turnstileSiteKey 属性配对。 |
EMDASH_URL | 用于 schema 同步的远程 EmDash URL |
使用以下命令生成加密密钥:
npx emdash secrets generate
package.json 配置
模板和站点可以在 package.json 的 emdash 键下声明可选元数据:
{
"emdash": {
"label": "My Blog Template",
"seed": ".emdash/seed.json",
"url": "https://my-site.pages.dev"
}
}
| 选项 | 描述 |
|---|---|
label | 用于显示的模板名称 |
seed | 种子 JSON 文件路径 |
url | 用于 schema 同步的远程 URL |
TypeScript 配置
EmDash 在 .emdash/types.ts 中生成类型。在 tsconfig.json 中添加路径别名:
{
"compilerOptions": {
"paths": {
"@emdash-cms/types": ["./.emdash/types.ts"]
}
}
}
使用以下命令生成类型:
npx emdash types