EmDash 插件内容 API 全指南:schema、翻译、发布策略与恢复操作的权限边界
CMS后端前端插件系统【免费下载链接】emdashEmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress项目地址https://gitcode.com/gh_mirrors/emdas/emdash点击查看免费下载EmDash基于 Astro 的全栈 TypeScript CMS为插件提供了一整套按能力capability门控的内容 API覆盖 schema 读取、内容读写、翻译管理、发布策略钩子与回收站恢复。本文以 creating-plugins 技能参考文档 为主线结合 核心实现、发布策略实现 与 能力词表定义 展开帮助你理解每个能力边界、调用形态、稳定错误语义以及如何在真实项目中安全地读写与发布内容。能力门控总览同一套 API三种执行形态插件内容 API 是能力门控capability-gated的并且由原生插件、Cloudflare Worker Loader 与 Node/workerd 三种执行形态共享。这意味着无论你的插件以何种方式被宿主加载面对的都是同一套ctx.schema、ctx.content语义差异只体现在沙箱边界与传输层而不是 API 形状上。在 SandboxedPlugin 类型 中插件需要在emdash-plugin.jsonc里声明所需能力。与内容直接相关的能力及其授予范围如下完整能力表见 SKILL.md能力授予范围schema:read公开的集合collection与字段field定义content:read内容身份、翻译与已发布公开 URLcontent:revisions:read保留的修订数据隐含内容读取content:write创建、更新、删除与翻译创建隐含读取content:publish修订围栏revision-fenced的发布、取消发布、调度与取消调度隐含读取content:restore回收站内容的修订围栏读取与恢复hooks.content-policy:register发布前、调度前、取消发布前策略钩子值得强调的设计原则能力写在emdash-plugin.jsonc而不是src/plugin.ts。宿主管道会跳过缺少所需能力的钩子与 API 调用参见 hooks.md因此声明与实现必须保持一致这也是 插件发布校验 中declared capabilities and allowed hosts that match the plugin implementation的来源。发现与读取schema:read 与 content:read集合与字段定义schema:read暴露两个批量方法ctx.schema.listCollections()用于获取全部公开集合ctx.schema.getCollection()用于获取单个集合的字段定义。它们在宿主侧由SchemaRegistry提供支持参见 content-access.ts 中对new SchemaRegistry(db).getCollection(collection)的使用因此插件读取到的定义与站点后台管理界面看到的 schema 是同一份数据。内容项的数据形状schema:read之外读取内容本体需要content:read它暴露ctx.content.get(collection, id)按 id 获取单条内容ctx.content.list(collection, options?)分页列表支持limit默认 50、cursor游标、where过滤与orderBy排序ctx.content.getTranslations(collection, id)获取翻译组信息ctx.content.getPublicUrl(collection, id)解析公开可路由 URL。返回的内容项ContentItem结构可以从 createContentAccess 的实现中完整看到包含以下字段字段含义id内容项唯一 idtype/slug内容类型与 slugstatus状态如 draft / publisheddata结构化字段数据createdAt/updatedAt时间戳locale语言区域publishedAt/scheduledAt发布时间 / 计划时间authorId作者 idtranslationGroup翻译组标识liveRevisionId/draftRevisionId线上版与草稿版修订指针version行版本号乐观并发用如果集合启用了 SEO 模块结果中还会附带seo字段。公开 URL 只解析已发布内容getPublicUrl是一个需要特别注意安全语义的方法。查看 实现它要求item.status published、slug存在、且集合是可路由routable的然后按站点的urlPattern、trailingSlash与 locale 规则解析出完整 URL。也就是说公开 URL 解析永远只返回已发布的、可路由的 URL绝不返回预览。插件在生成外链、sitemap 或社交分享链接时应依赖这个方法而不是自己拼 URL。修订读取content:revisions:readcontent:revisions:read额外暴露listRevisions()与getRevision()用于读取修订历史。从 实现 可以看到一个隐私细节修订快照可以保留后来被删除的字段值但返回时通过解构去掉了authorId——修订数据不携带修订者身份。如果你的插件需要审计谁改的需要另行借助users:read或其他来源而不能依赖修订记录。写入与翻译content:writecontent:write在读取能力之上增加创建、更新与删除。创建一条翻译是最典型的用法参考文档给出的调用形态await ctx.content!.create(posts, data, { locale: fr, translationOf: sourceId });这条调用的语义约束非常明确源必须是同一集合中的活动条目active entry不存在的源会触发NOT_FOUND新行会加入源所在的翻译组并继承不可翻译字段、署名byline与分类taxonomy指派校验与保存钩子validation 与 save hooks都会运行且创建者插件会收到可重入围栏re-entrancy fencing保护避免同一插件在钩子内再次进入产生死循环一个翻译组每个 locale 只允许一条活动行重复 locale 会被拒绝。从 hooks.md 可知保存钩子content:beforeSave/content:afterSave分别需要content:write与content:read能力beforeSave可以返回修改后的内容或在沙箱中返回{ __emdashSandboxHookResult: true, version: 1, error: { code: SAVE_REJECTED, reason } }拒绝保存reason 必须为 1–500 字符的纯文本宿主进程则抛出ContentSaveRejectedError见 save-rejection.ts 相关实现。稳定的失败语义写入路径上插件可以依赖以下稳定错误码CONFLICT——并发冲突通常与行版本version不匹配相关NOT_FOUND——目标内容或源不存在VALIDATION_ERROR——字段校验失败SAVE_REJECTED——被钩子显式拒绝。插件应按这些错误码编写重试与用户提示逻辑而不是依赖不稳定的错误消息文本。发布策略钩子不授予任何读写权也能拦截发布hooks.content-policy:register是一个零读写权限的拦截能力它使插件能够注册content:beforePublish、content:beforeSchedule与content:beforeUnpublish但本身不授予任何内容读取、写入或发布操作。这实现了关注点分离——审查/审批类插件可以只做策略判断拿不到内容数据。决策形态与校验钩子返回void表示放行返回{ cancel: true, reason }表示拒绝。拒绝语义由 content-policy.ts 中的inspectContentPolicyDecision严格校验reason必须是非空字符串长度不超过500 个字符按码点计数不允许包含控制字符tab、换行、回车除外决策对象必须恰好包含cancel与reason两个键非法决策或意外中止错误会让整个动作以通用失败告终显式取消分别返回PUBLISH_REJECTED、SCHEDULE_REJECTED或UNPUBLISH_REJECTED。一个基于字段审批状态的示例源自 hooks.mdcontent:beforePublish: async (event) { const data event.content.data; const approvalStatus typeof data object data ! null approval_status in data ? data.approval_status : undefined; if (approvalStatus ! approved) { return { cancel: true, reason: Approve this entry before publishing. }; } },事件来源与调度拒绝策略钩子的事件携带{ content, collection, origin, actor? }其中content:beforeSchedule还包含scheduledAt。origin标识动作来源api、mcp、visual-editor人类操作同时携带相同的actor.sourcevisual-editor 要求来自已认证工具栏渲染的签名短期令牌、plugin附pluginId、scheduler与system。这意味着策略插件可以针对不同来源差异化放行——例如只允许管理员在管理界面发布拒绝 API 令牌直接发布。调度行为有一个容易忽略的细节到点执行的调度发布会再次运行发布策略。若调度器执行content:beforePublish时被拒绝条目会被取消调度unschedule拒绝原因被记录在案管理后台会展示该原因直到条目被重新调度、发布、删除或记录被消除。从源码看这个记录使用前缀emdash:scheduled-policy-rejection:的存储键见 content-policy.ts并携带collection、id、pluginId、reason、rejectedAt等字段。同时因为没有content:beforeUnschedule钩子管理员永远可以取消一次未来发布不会被策略插件锁死。发布与恢复动作content:publish 与 content:restore修订围栏revision fencecontent:publish在读取能力之上增加getVersioned()读取带版本号的内容publish()/unpublish()发布 / 取消发布schedule()/unschedule()调度 / 取消调度。这里最关键的模式是先读后写 携带_rev每次变更前先用getVersioned()读取并把不透明的_rev传给每一次变更动作。_rev是乐观并发锁防止两个进程同时基于同一版本做发布决策导致状态错乱。发布成功的动作会返回下一个修订next revision并正常运行策略、同步synchronization、媒体使用media-usage、缓存失效cache-invalidation以及 after 钩子等完整行为链。恢复不隐含删除权content:restore是一个刻意最小化的能力它只增加getTrashedVersioned()与restore()用于读取并恢复回收站中的内容不授予普通内容读取也不授予永久删除。这保证了能恢复的插件不会因此拥有能读全部内容或能清空回收站的权限是权限最小化设计的典型例子。插件动作的标识与重入防护所有插件动作都会报告{ source: plugin, pluginId }。宿主对同一插件针对同一规范条目canonical entry的相同动作实施重入拒绝——即插件发起发布后若该插件在钩子中再次对同一条目发起发布会被拒绝。这配合前面提到的保存钩子可重入围栏构成对插件递归行为的双层防护发布侧的重入语义见 hooks.ts 中钩子系统的运行机制。运行时测试用 fixture 与 action 覆盖关键行为参考文档给出的测试方法论非常实用用运行时 fixture 建立初始状态用运行时 action 调用生产边界用 inspector 读取持久化状态。fixture 用于初始数据初始条目entries、翻译、署名、分类指派都不应通过触发钩子的方式创建而应直接建立状态避免污染被测行为action 用于发布路径发布、调度、取消发布等必须走真实的生产边界runtime actions因为它们涉及修订围栏、策略运行与缓存失效inspector 用于验证持久化状态读取最终落库状态断言行为副作用是否符合预期。当以下行为对你的插件有意义时务必编写对应测试过期修订stale revisions即_rev已失效的并发场景、策略拒绝policy rejection、重复 locale、重入re-entrancy、重启restart验证调度拒绝记录与状态在进程重启后仍正确以及缓存失效cache invalidation。测试宿主的选择可以参考 SKILL.mdcreatePluginTestHost()适合快速验证钩子、路由、清单、能力、KV、设置与存储传输而涉及真实内容动作、插件激活、媒体、评论、重定向、调度、重启、授权、CSRF、缓存、Block Kit 校验或已保存条目扩展时应使用createPluginRuntimeTestHost()。每次使用后都要 dispose 宿主。能力边界速查表你想做的事需要的能力关键 API / 钩子读集合与字段定义schema:readctx.schema.listCollections()/getCollection()读内容、翻译、公开 URLcontent:readctx.content.get()/list()/getTranslations()/getPublicUrl()读修订历史content:revisions:readlistRevisions()/getRevision()无修订者身份创建 / 更新 / 删除 / 建翻译content:writectx.content.create()/update()/delete()发布 / 取消发布 / 调度content:publishgetVersioned()publish()/unpublish()/schedule()/unschedule()必须传_rev恢复回收站内容content:restoregetTrashedVersioned()/restore()拦截发布 / 调度 / 取消发布hooks.content-policy:registercontent:beforePublish/beforeSchedule/beforeUnpublish返回{ cancel: true, reason }小结EmDash 插件内容 API 的核心设计可以总结为三句话能力即权限每个读、写、发布、恢复动作都有独立能力开关且能力声明在清单而非代码中修订围栏保一致_rev贯穿所有发布与恢复动作先读后写是唯一正确姿势策略与执行分离发布策略钩子不授予任何读写权却能在发布、调度、取消发布三条路径上执行审批并通过调度拒绝记录让管理员始终保有最终控制权。理解这三点你就能写出既安全又实用的内容类插件。赞分享CMS后端前端插件系统【免费下载链接】emdashEmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress项目地址https://gitcode.com/gh_mirrors/emdas/emdash点击查看免费下载相关推荐EmDash 插件内容 API 指南schema 读取、翻译创建、发布策略与版本化发布操作EmDash 插件内容 API 指南schema 读取、翻译创建、发布策略与版本化发布操作 EmDash 是一套基于 Astro 的全栈 TypeScriptCMS后端前端插件系统EmDash 插件内容 API 指南Schema、翻译、发布与恢复的完整实现EmDash 插件内容 API 指南Schema、翻译、发布与恢复的完整实现 EmDash 是一款基于 Astro 的全栈 TypeScript CMSWoCMS后端前端插件系统EmDash 插件内容 API 实战Schema 读取、多语言翻译、发布策略与版本化恢复EmDash 插件内容 API 实战Schema 读取、多语言翻译、发布策略与版本化恢复 EmDash全栈 TypeScript CMSAstro 生态CMS后端前端插件系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

搞定致命的应用程序退出机制:Go语言panic与recover完整示例

搞定致命的应用程序退出机制:Go语言panic与recover完整示例

搞定致命的应用程序退出机制:Go语言panic与recover完整示例 学会语法却不知怎么搭项目,很多后端工程师卡在“程序崩了没人知道”这个死胡同。你以为 panic 只是打印个错误?错。它是 Go…

2026/9/23 21:01:47 阅读更多 →
2026通化电气检测机构排名 TOP5 CMA 资质机构提供防爆设备检测+防爆安全检测 联系方式推荐

2026通化电气检测机构排名 TOP5 CMA 资质机构提供防爆设备检测+防爆安全检测 联系方式推荐

通化电气防爆检测机构鱼龙混杂,化工园区、油库加油站、矿山厂区、制药企业、危化品仓储场所开展防爆电气安全排查与生产验收时,大量无资质机构出具的检测报告屡屡被应急管理部门驳回,企业主苦不堪言。小编实地走访筛选本地正规第三方电气防爆…

2026/9/23 21:01:47 阅读更多 →
DRV8703D-Q1半桥驱动SPI初始化与PWM调试要点

DRV8703D-Q1半桥驱动SPI初始化与PWM调试要点

简介:DRV8703D-Q1 芯片调试文档面向电机驱动开发者与硬件工程师,围绕芯片从电路搭建到 SPI 软件配置给出系统调试指引。文档先梳理半桥电路、SPI 接口和电源电路三块电路板设计要点,再详解 SPI 初始化参数,包括上升沿输出/下降沿输…

2026/9/23 21:01:46 阅读更多 →

最新新闻

Nasiko A2A Registry 设计解析:把“Agent 发现“本身做成一个 A2A Agent

Nasiko A2A Registry 设计解析:把“Agent 发现“本身做成一个 A2A Agent

【免费下载链接】nasiko Developer Control Plane for your AI Agents 项目地址: https://gitcode.com/gh_mirrors/na/nasiko 点击查看 免费下载 在 Nasiko(Developer Control Plane for your AI Agents)中,Agent 之间的通信、发…

2026/9/25 22:57:20 阅读更多 →
LDA主题词提取实战:从原理到Python实现与调参

LDA主题词提取实战:从原理到Python实现与调参

简介:面向自然语言处理与文本挖掘场景的LDA主题建模与关键词提取资源包,基于潜在狄利克雷分配模型,适合需要学习主题模型原理或快速搭建文本分析工具的开发者和研究者,可用于从文档集合中自动发现隐藏主题并提取代表性词语。压缩包…

2026/9/25 22:57:20 阅读更多 →
从ProX到UltraX:LLM预训练数据精炼方法演进史与UltraX-0.6B精炼模型完整详解

从ProX到UltraX:LLM预训练数据精炼方法演进史与UltraX-0.6B精炼模型完整详解

从ProX到UltraX:LLM预训练数据精炼方法演进史与UltraX-0.6B精炼模型完整详解 【免费下载链接】UltraX-Preview 项目地址: https://ai.gitcode.com/OpenBMB/UltraX-Preview OpenBMB 开源社区发布的 UltraX-Preview 数据集是 LLM 预训练数据精炼的最新成果&am…

2026/9/25 22:57:20 阅读更多 →
S型曲线Demo:手把手理解扩散模型DDPM原理与实现

S型曲线Demo:手把手理解扩散模型DDPM原理与实现

简介:面向机器学习初学者的扩散模型微型demo,通过生成S型曲线演示扩散模型从随机噪声逐步还原数据分布的核心过程,特别适合刚接触生成模型、想绕过复杂公式直接看代码逻辑的读者。压缩包共8个文件,大小约9.74MB,主程序…

2026/9/25 22:57:20 阅读更多 →
Robomongo 内嵌 esprima 2.7.3:ECMAScript 解析器在 MongoDB Shell 脚本解析中的集成与应用

Robomongo 内嵌 esprima 2.7.3:ECMAScript 解析器在 MongoDB Shell 脚本解析中的集成与应用

数据库客户端桌面应用 【免费下载链接】robomongo Native cross-platform MongoDB management tool 项目地址: https://gitcode.com/gh_mirrors/ro/robomongo 点击查看 免费下载 Robomongo(即 Robo 3T)是一款原生的跨平台 MongoDB 管理工具&…

2026/9/25 22:57:20 阅读更多 →
rsuite Calendar 自定义单元格样式:深入解析 cellClassName 的用法与实现原理

rsuite Calendar 自定义单元格样式:深入解析 cellClassName 的用法与实现原理

前端UI组件 【免费下载链接】rsuite 🧱 A suite of React components . 项目地址: https://gitcode.com/gh_mirrors/rs/rsuite 点击查看 免费下载 导读 本文围绕 rsuite 的 Calendar(日历)组件,重点讲解如何通过 ce…

2026/9/25 22:56:19 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/25 19:27:14 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/25 11:15:26 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/25 20:29:09 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/25 20:29:43 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/25 20:29:31 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/25 19:27:26 阅读更多 →