数据库
使用 D1 与 Drizzle 管理 schema、本地数据、生产迁移和资源归属。
数据库文件与运行方式
packages/db/src/schema.ts 是 Drizzle schema,packages/db/migrations 保存版本化 SQL,根目录 drizzle.config.ts 使用 SQLite 方言。Worker 通过 DB binding 访问 D1;本地由 Wrangler 模拟 D1,并不要求先创建远程数据库。
认证、订单、积分账本、文件元数据、任务、Webhook 事件、审计与限流数据共用当前应用的 D1。R2 保存文件正文,D1 保存文件归属与索引;两者不能互相替代。
本地初始化
pnpm install --frozen-lockfile
pnpm muse:init
pnpm devinit 应用本地迁移并创建开发账号。重复运行保留已有账号的密码,不会将本地 seed 写入生产。若要设置自定义 seed 密码,在第一次 init 前设置 MUSE_SEED_PASSWORD,至少 8 个字符。不要为了修复密码而删除整个本地数据库;先确认是否正在使用同一份 Wrangler 本地状态。
本地状态属于开发机文件,不纳入 Git。换电脑时重新 init 可以获得干净开发数据,但不是生产备份恢复。
新增字段的正确顺序
- 修改
packages/db/src/schema.ts,明确 null、默认值、唯一性、外键与索引。 - 生成 SQL 并逐条审查:
pnpm db:generate- 执行
pnpm muse:init应用本地待执行迁移,检查已有记录和新记录都能读写。 - 同步查询、API schema、界面类型和契约;不要只让表单增加一个字段。
- 提交 schema 和生成迁移。已部署的迁移文件不应重新改写,修复应添加下一份迁移。
对于已有数据的必填字段,优先分阶段添加可空字段、回填、验证后收紧约束。先检查生产数据规模与锁定影响,不把开发机上的成功等同于安全生产迁移。
D1 与事务边界
代码运行于 Worker,使用 D1 支持的 batch 和现有仓储封装。不要引入依赖长连接的 Node 数据库驱动,也不要照搬其他数据库的回调事务。当前时间字段使用整数毫秒,新增查询与报表不要误当秒或字符串时间。
积分预留、账本与 outbox 有自己的原子写入和幂等约束。支付通知、后台补发与队列重试可能并发到达,新增写入必须沿用这些约束,而不是先查余额再分两次更新。
生产迁移与目标身份
先在 packages/cli/src/target-resources.ts 确认目标 D1 名称。新产品需要自己的名称;已上线产品必须继续使用原名称及相同账户。仓库当前生产示例名 flare-musemvp-com-d1 属于演示项目,不应作为所有买家的共享名称。
pnpm muse:doctor --target production --json
pnpm muse:deploy --target production --plan --jsonplan 显示迁移和资源动作。若升级时出现意外的 create,先核对账户、资源名与部署状态,不要直接接受。CLI 对待执行 SQL 中 DROP、TRUNCATE、DELETE、UPDATE SET 等高风险形式设置阻断;需要独立审查、备份、执行和记录后再继续,而不是删除保护。
验证与排障
- 本地提示缺表:确认 init 成功、迁移目录正确、运行的是目标仓库。
- 生产突然没有历史数据:优先核对 D1 binding、账户和资源名称,停止继续写入新的空库。
- 唯一约束冲突:检查是否是同一业务事件重试,复用其幂等结果。
- Worker 版本回滚:只回滚代码不会撤销 D1 迁移,必须单独评估 schema 兼容性。
至少运行 pnpm type-check、pnpm test:unit 和 pnpm test:workers,然后按照 部署指南 审查远程 plan。