Content Types
Schema 管理
CLI 命令、Admin API、热重载和数据库迁移策略。
通过 CLI、Admin API 或直接编辑 TOML 文件来管理内容类型 Schema。变更无需重启服务器即可生效。
CLI 命令
创建内容类型
raisfast ct new course在 extensions/content_types/course.toml 生成基础 TOML 脚手架文件。
校验 Schema
raisfast ct check校验内容类型目录中的所有 TOML 文件。报告以下错误:
- 缺少必填字段(
name、singular、plural、table) - 无效的字段类型
- 重复的表名或保留表名
- 循环关联引用
生成 TypeScript 类型
raisfast ct types course -o types/course.ts从内容类型定义生成 TypeScript 接口,包括字段类型、可选标记和关联类型。
Admin API
通过 Admin API 在运行时管理 Schema:
GET /api/v1/admin/content-types 列出所有 Schema
GET /api/v1/admin/content-types/{singular} 获取单个 Schema
POST /api/v1/admin/content-types 创建 Schema
PUT /api/v1/admin/content-types/{singular} 更新 Schema
DELETE /api/v1/admin/content-types/{singular} 删除 Schema创建 Schema
curl -X POST http://localhost:9898/api/v1/admin/content-types \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Project",
"singular": "project",
"plural": "projects",
"table": "projects",
"fields": [
{"name": "title", "field_type": "text", "required": true},
{"name": "status", "field_type": "enum", "enum_values": ["active", "completed"], "default": "active"}
],
"protocols": ["timestampable", "ownable"]
}'这一步请求完成四件事:
- 校验 Schema
- 写入 TOML 文件到
extensions/content_types/ - 迁移 数据库(创建
projects表) - 注册 路由到内存
更新 Schema
curl -X PUT http://localhost:9898/api/v1/admin/content-types/project \
-H "Authorization: Bearer TOKEN" \
-H "Content-Type: application/json" \
-d '{
"fields": [
{"name": "title", "field_type": "text", "required": true},
{"name": "status", "field_type": "enum", "enum_values": ["active", "completed", "archived"], "default": "active"},
{"name": "priority", "field_type": "integer", "min": 1, "max": 5}
]
}'这会:
- 更新 TOML 文件
- 迁移 数据库(通过
ALTER TABLE添加新的priority列) - 重新注册 Schema 到内存
删除 Schema
curl -X DELETE http://localhost:9898/api/v1/admin/content-types/project \
-H "Authorization: Bearer TOKEN"这会注销路由并删除 TOML 文件。数据库表会被保留 — 不会丢失数据。
热重载
内容类型 Schema 使用无锁 ArcSwap 加载到内存中,实现零停机热重载:
- TOML 文件变更 在下次请求时生效(使用文件监控时)
- Admin API 变更 立即生效
- 动态路由(
/api/v1/cms/{*path})处理启动后添加的内容类型
迁移策略
系统采用安全的增量迁移方式:
新内容类型
CREATE TABLE IF NOT EXISTS {table} (
id TEXT PRIMARY KEY,
{field_columns},
{protocol_columns}
)新增字段
当 Schema 增加新字段时,系统比较期望列与实际列,生成:
ALTER TABLE {table} ADD COLUMN {column} {type}只有增量变更会自动执行。
类型变更
如果字段类型发生变化(如 text → integer),系统检测到不匹配后会生成重建迁移脚本,保存到 migrations/manual/:
- SQLite:使用
PRAGMA foreign_keys=OFF,创建新表、复制数据、删除旧表、重命名 - PostgreSQL:用事务包裹
BEGIN/COMMIT - MySQL:使用
SET FOREIGN_KEY_CHECKS=0
这些脚本需要手动审核和执行。
绝不会发生的事
- 列不会被删除 — 从 TOML 中移除字段不会删除列
- 数据不会被修改 — 现有值保持不变
- 表不会被删除 — 删除 Schema 会保留表
索引
自动为以下情况创建唯一索引:
- 标记为
unique = true的字段 - 显式定义的
[[indexes]]
[[indexes]]
fields = ["slug"]
unique = true
[[indexes]]
fields = ["status", "created_at"]中间表
对于 many_to_many 和 many_way 关联,中间表会自动创建:
CREATE TABLE IF NOT EXISTS {source}_{target} (
{source_singular}_id TEXT NOT NULL,
{target}_id TEXT NOT NULL,
PRIMARY KEY ({source_singular}_id, {target}_id)
)受保护的表
系统内置表不能作为内容类型的表名,包括:users、posts、pages、categories、tags、media、comments、products、orders、wallets 等所有内置表。
保留路由段(auth、admin、users、media 等)不能用作 singular 或 plural 名称。
文件结构
extensions/
content_types/
course.toml # 课程内容类型
instructor.toml # 讲师内容类型
lesson.toml # 课时内容类型
migrations/
manual/ # 类型变更重建脚本(需手动审核)