管理员Kit
AdminKit是我们用来管理与雨果一起建造并部署在Cloudflare Pages上的由内容驱动的小型网站的行政引擎.
它把Zod计划变成了必须同意的三件事:
- 在浏览器中编辑的模型;
- 2. 存储在存储库中的YAML前置物质;
- 服务器进行的验证.
没有第二个隐藏在UI中的字段列表,也没有第二个序列器隐藏在一个Worker. 一块地申报一次. 其余系统读取该声明.
该套件还包含React管理 shell,一个R2,Cloudflare Pages函数的媒体库,以及D1出版路径所使用的持久性原始.
传送电子邮件 - 2.2.45
传输支持独立所有者通知和自动收件人电子邮件
通过Resend,带有可选的收件人地址,明确的选入,可持久地重试,
发送历史和确认的转发 。 传输设置包括可编辑的所有者
每次新要求下载的电子邮件和所有者通知。 发送暂停直到配置
网站。 安装迁移 0012_delivery_email.sql 并仅配置服务器
描述的电子邮件变量 综合指南。 。 。 .
现有转账不会自动通过电子邮件。 插图转让指南
包括电子邮件工作流程,并解释供应商接受与交付.
重要财产
管理员小组不应仅仅因为不了解所有文件而损坏文件.
AdminKit保留了Markdown正文,未知的前事密钥,以及他们的评论. 省略的管理领域是指“单独处理”,而不是“删除”。 在覆盖现有文件之前, checkFidelity() 可以证明再读再写是字节稳定.
如果解码器无法复制一个文件,它会这么说. 拒绝省钱胜过产生假象的YAML 数据缺失.
安装
npm install @cardinali-studio/adminkit zod
核心解码器需要Zod 4. React 应用程序和表单导出还使用列表中的可选对等依赖 package.json; 安装您使用的出入口所需的出入口.
一揽子措施仅限无害环境管理.
一个完整的代码示例
每个字段有两个元数据:
ui描述人类如何编辑它;fm描述它是如何在文件中生活的.
import * as z from "zod";
import {
checkFidelity,
deserializeItem,
fm,
serializeItem,
ui,
yamlStr,
} from "@cardinali-studio/adminkit";
const Article = {
title: z.string().min(1).max(120)
.register(ui, {
label: "Title",
widget: "text",
group: "content",
})
.register(fm, {
keys: ["title"],
encode: (value) => [`title: ${yamlStr(value)}`],
decode: (raw) => String(raw.title ?? ""),
}),
published: z.boolean()
.register(ui, {
label: "Published",
widget: "boolean",
group: "visibility",
})
.register(fm, {
keys: ["visible"],
encode: (value) => [`visible: ${value === true}`],
decode: (raw) => raw.visible === true,
}),
};
const markdown = `---
# Kept with the field.
title: "A small page"
visible: false
# AdminKit does not own this key, so it stays untouched.
build-note: "keep me"
---
The Markdown body stays untouched too.
`;
if (!checkFidelity(markdown, Article).ok) {
throw new Error("This file cannot be edited without loss");
}
const article = deserializeItem(markdown, Article);
const updated = serializeItem(
{ ...article, published: true },
{ shape: Article, oldMd: markdown },
);
注意模型叫布尔 published 当文件调用时 visible转换属于计划 Hugo模板,React组件,和API处理器不应该各自发明自己的版本.
删除和退休字段
缺席不是删除。 要清除一个值, 只需传递其编码器所理解的空值, 并返回任何 YAML 行 .
当钥匙过时时, retired(schema, keys) 保持对旧钥匙的所有权,同时不排放任何东西。 现有文件随后在下次有意保存时丢失了该密钥,而没有单独保存一个迁移列表.
正在挂载管理员应用程序
应用程序被刻意挂载为一个单元:
import { mountAdmin, type SiteAdminConfig } from "@cardinali-studio/adminkit/app";
import "@cardinali-studio/adminkit/theme.css";
import "./site-theme.css";
const site: SiteAdminConfig = {
// Site identity, page types, schemas, enabled modules and persistence mode.
// TypeScript checks the complete contract here.
};
mountAdmin({
site,
root: document.querySelector("#root"),
storagePrefix: "example-admin",
});
在管理员Kit主题后导入该网站的主题. 这样可以让一个站点取代CSS自定义属性而不增加选择器的特异性.
storagePrefix 是网站浏览器数据的一部分。 在现场安装上更改它,默默地重置所保存的媒体偏好,因此迁移应该保持旧值.
该壳目前会说意大利语. 内容可以是单一语言的或多语言的;管理界面的语言是一个单独的关注.
云花板页函数
Cloudflare 路由按文件排列的函数, 而 npm 包无法在耗用工程中创建文件 functions/ 目录。 因此一个站点保留了两个小适配器.
API全面报道:
// functions/admin/api/[[path]].js
import { handleAdminApi } from "@cardinali-studio/adminkit/functions";
import { serverConfig } from "../../../src/admin/site-config.js";
export function onRequest(context) {
return handleAdminApi(context, serverConfig);
}
而接入中间软件:
// functions/admin/_middleware.js
export { adminAccess as onRequest } from "@cardinali-studio/adminkit/functions";
特定地点的终点可能位于这些文件旁边。 更具体的Cloudflare路线优于"包罗万象".
服务器配置为站点自有. 它提供chemas,寄存器的细节,启用模块,存储绑定,并在D1模式下提供完整的文档验证器. 缺少可选模块已关闭 .
持久性和出版
最初的坚持道通过GitHub来写作Markdown并让Hugo来建造. 更新的路径在D1中存储了不可改变的修改并发布准确的发布快照.
D1模块故意比管理员外壳更低等. 它们规定:
- 确定性要求核对和一能节省;
- 对同时提交的草案的比较和抽取保护;
- (一) 不可改变、检查和封存的释放出口;
- 代码和内容的单一部署道;
- 复制先行媒体移动并删除 R2 的日记;
- 版本网站访问秘密;
- 纯放出物质化,文件系统效果留给CI.
他们不决定网站文件的含义。 验证和物化仍然是场地所有.
入境点
| 导入 | 目的 |
|---|---|
@cardinali-studio/adminkit | Schema 注册、前题编码器、 API 客户端、 i18n、 持久性和释放原始 |
@cardinali-studio/adminkit/app | 完全反应管理外壳 |
@cardinali-studio/adminkit/form | 图表形式和媒体组件 |
@cardinali-studio/adminkit/functions | Cloudflare Pages API 路由器和访问中间软件 |
@cardinali-studio/adminkit/materializer | 纯释放到文件的实现 |
@cardinali-studio/adminkit/preview | 本地预览组件 |
@cardinali-studio/adminkit/testing | 对消费场所进行内容稳定性检查 |
@cardinali-studio/adminkit/theme.css | 默认设计符号 |
这不是什么
AdminKit不是一个通用的无头CMS,一个窗体构建者,或者一个支持每个YAML构造的承诺.
它对有用的狭义案例有观点:雨果内容,React 19,Zod 4,Cloudflare Pages,R2和可选D1. 前物质发射器支持该系统使用的结构,并投掷它不能安全代表的值.
这种狭义是故意的. 一个带有明显的失败模式的更小的系统更容易相信人们用手编辑的内容.
交付ZIP兼容性(2.2.38)
新的传送档案使用STORE成员及其CRC和每个本地标题的大小,没有数据描述符. 这防止了流取取子在文件尾端的照片中误取描述子形状的字节. CRC制备读取了4个MiB切片,仍无法保存,无法取出;源变化未关闭。 ZIP64大小和相抵独立推广.
持续的检查站记录 store-header-v1。继续使用以前发布的检查点 store-descriptor-v1,保留已确认的多段字节和衍生重写. 更新会影响新生成的档案;它不会重写已存储的ZIP. 消费者必须更新依赖、重建和重新部署.
回归包括208个合成成员在成员53时相撞、流线和索引读取器、ZIP64相抵以及2.2.37的字节同调.
永久交货储存清理
发送清理永久删除 所有版本并删除标记 输入 删除软件包的精确存储前缀,并中止未完成多段上传. 成功删除需要随后的空列表; 失败或部分扫描 保留数据库工作以进行重试。 不安装桶宽清理或生命周期.
应用 dist/functions/delivery-public/migrations/0010_delivery_storage_cleanup.sql
向消费者交付D1 在此之前 部署此代码 。 新的
delivery_storage_cleanup 表格没有外国钥匙:其范围墓碑能活下来
删除交付,所以已在飞行的PUT或多段完成不能
变成永久无轨 客房服务员必须继续打电话
purgeDue 不论访问行政网页或公共网页。 检查范围
15分钟之后,在第一个小时,然后是每天, 取决于打电话者的要求
预算和积压。 墓碑被故意无限期地保留. last_error
记录失败扫描; last_checked_at 记录成功的空验证.
过期交付不能要求新的上传签名或开始/完成新的 软件包。 上传软件包保留1小时元数据宽限期; 它的可持久范围也捕捉到在这一宽限期后完成的请求. 后期的写入可以暂时占用空间,直到下一次成功的扫描.
选入的活回归 scripts/verify-delivery-storage.mjs 使用新的随机
前缀和一个内元D1数据库。 它创建版本、删除标记、
未完成多部分上传,删除前授权的PUT. 它检查0
删除和到期后剩余版本/字节/上载,并进行比较
所有在前后存在的版本ID. 新事物之外的每一起突变
前缀被拒绝。 配置和秘密文件路径为参数; 证书
从不打印。 这项测试不会部署工人或改变生命周期规则.
现有生产桶时不要用这种清理 必须保留物体:待交付/过期交付将有资格获得 永久删除。 仅迁移就具有添加性,不整理旧数据.
发展
npm test
npm run build
npm run check
npm run check 重建软件包并运行节点测试套件. 测试内容包括字节-同位代码回程,错误的输入拒绝,导入解析,货币冲突,放出变量,媒体操作过渡等,以及防范特定站点代码进入共享包.
生成的文件存在 dist/ 并且是 npm tarball 中除了 npm 的标准包元数据和此 README 中唯一包含的应用程序文件.
许可证
0BSD 数据使用它,复制它,改变它,运送它。 对归属表示赞赏,但没有要求.
交货仪表板
发送概览读取下载 请求,没有完成下载。 活动 传输有准备的软件包、未过期的文件和至少一个有效的链接.
启用前 DELIVERY_STORAGE_DASHBOARD=true,应用
dist/functions/delivery-public/migrations/0011_delivery_storage_dashboard.sql 改为
消费者的交付D1数据库。 在消费者 现有的预定的处理器,
调用 verifyDeliveryStorage(env, {maxCalls: 4}) 从
@cardinali-studio/adminkit/functions/_shared/delivery-storage-dashboard.js 之后
户口. 每15分钟运行一个处理器: 更新已完成的库存
小时;在各种引用中恢复较大的库存。 行政投票也恢复
“Verifica ora”要求重新检查.
仅读扫描汇总所有 B2 对象版本并上传多部分, 包括隐藏版本和未指定的密钥。 它只存储完整的总数, 保留上次失败的快照, 并显示最后的完成时间 . 同时的 B2 写入可以在扫描时更改存储; 这是测量的 存货,不是供应商的账单。 盘片检查从不删除 对象。 现行保护政策仍然独立于这一特点.
转移仪表板和创建(2.2.42)
全体管理人员和 mountDeliveryAdmin 显示上面的 Dashboard 按钮
新转会 新的转移开始于画廊和低分辨率转换关闭,
选择 JPG 转换, 60天到期 。 现有包保留其选项.
在选择文件前先交付选项; 不可用的特性会崩溃 .
一个场地可以提供 deliveryPricing 内 SiteAdminConfig,或 pricing 内
DeliveryAdminOptions数字 : storageUsdPerTb30Days, (中文(简体) ), freeStorageGb, (中文(简体) ),
downloadUsdPerGb, (中文(简体) ), freeDownloadMultiplier日期 verifiedAt。 。 。 .
仪表板预测本日历月最后一个计量存储;
它不重建过去的用法,不扣减共享免费津贴,或推断
实际下载字节。 丢失的库存显示为没有,从零到零.
信息对话框解释了这些限制。 费率由消费者提供,
未从存储证书或供应商名称中推断.
专用交付项现在初始化了自己的模块配置;
消费者必须清除旧的内脏 setSiteConfig 工作的时候.
2.2.43 专用送出导航与全外壳相协调:共享图标,可访问标签和文本包可以保存两个管理员界面变体.
转移指南(2.2.44)
仪表板在一个新的标签中链接到捆绑的意大利向导. 两个公共管理挂载功能都承认 ?adminkit-guide=transfer ,在已有的保护管理员路径上。 阅读器上载有懒惰,没有传输API钩子,支持章节深层链接,并包含有7个本地捕获并有合成数据的截图. 屏幕截图并引导 CSS 飞船进入 dist/app/guide/;使用Vite的消费者自动将相对图像URL捆绑. 不需要外部文件主机、新路线或全权证书。 资料来源和截图来源: src/app/guide/ 财务报告和审定财务报表 scripts/preview-transfer-guide.mjs。 。 。 .
Cloudflare电子邮件服务和共享 B2 桶
传送电子邮件也支持 DELIVERY_EMAIL_PROVIDER=cloudflare,当地人
DELIVERY_EMAIL 发送装订和 DELIVERY_EMAIL_ENABLED=true设置
ENVIRONMENT=production,验证 DELIVERY_EMAIL_FROM{\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}这只犬
DELIVERY_PUBLIC_BASE 和马厩 DELIVERY_SECRET; 保存所有者/首选项
在传输设置中。 要求和要求需要同样的配置.
不需要重新发送密钥 。 使用发件人限制的绑定( 不仅限于所有者)
以发送客户链接 有关工人付费。 明确供应商的选择
永远不要回到Resend。 未知/超时结果需要审查以防止
不安全的自动重复发送; 记录的速率/ quota 拒绝可以重试 .
非生产试验必须注入明确的模拟约束.
DELIVERY_STORAGE_PREFIX=deliveries/consumer-a 可选择隔离对象密钥,
在一个共享的私有桶中签名的 URL,目录和版本意识删除 .
独立项目必须保持单独的传输数据库。 消费者省略
设置保留已有路径。 保持清理移徙和持续
清理记录, 如此未完成的签名写入在删除后收集 .