forked from imbytecat/fullstack-starter
refactor: 重构 AGENTS.md 并调整数据库忽略规则
- 移除SQLite数据库文件相关的忽略规则 - 添加SQLite数据库文件的忽略规则,防止数据库文件被提交到版本控制。 - 重构 AGENTS.md 文档结构,将 PostgreSQL 迁移记录整合为 SQLite 使用说明,并明确文档维护原则与更新时机。
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -155,9 +155,3 @@ dist
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
.vite/
|
||||
|
||||
# SQLite database files
|
||||
data/
|
||||
*.db
|
||||
*.db-shm
|
||||
*.db-wal
|
||||
|
||||
5
apps/server/.gitignore
vendored
Normal file
5
apps/server/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# SQLite database files
|
||||
data/
|
||||
*.db
|
||||
*.db-shm
|
||||
*.db-wal
|
||||
@@ -378,45 +378,22 @@ const fingerprint = createHash('sha256')
|
||||
- 专业库不一定解决所有问题(如并发去重)
|
||||
- 对于简单场景,手动实现 vs 库的选择主要取决于可维护性而非功能
|
||||
|
||||
### PostgreSQL → SQLite 迁移
|
||||
### SQLite 数据库使用说明
|
||||
|
||||
**迁移时间**: 2026-01-26
|
||||
|
||||
**原因**: 项目需要在嵌入环境中运行,无法安装 PostgreSQL
|
||||
|
||||
**技术选择**:
|
||||
- **驱动**: `better-sqlite3` v11.8.1 (跨平台,成熟稳定,原生模块)
|
||||
**技术栈**:
|
||||
- **驱动**: `better-sqlite3` v11.8.1 (原生模块,跨平台)
|
||||
- **类型定义**: `@types/better-sqlite3` v7.6.12
|
||||
- **主键**: TEXT 存储 UUIDv7 (保持全局唯一性,36 字符字符串)
|
||||
- **时间戳**: INTEGER 存储 Unix 毫秒时间戳 (`integer({ mode: 'timestamp_ms' })`)
|
||||
- **布尔值**: INTEGER 存储 0/1 (`integer({ mode: 'boolean' })`)
|
||||
- **数据库文件**: `./data/app.db`
|
||||
|
||||
**变更内容**:
|
||||
1. **依赖**: `postgres` → `better-sqlite3` + `@types/better-sqlite3`
|
||||
2. **Drizzle 方言**: `dialect: 'postgresql'` → `dialect: 'sqlite'`
|
||||
3. **Schema 导入**: `drizzle-orm/pg-core` → `drizzle-orm/sqlite-core`
|
||||
4. **表定义**: `pgTable` → `sqliteTable`
|
||||
5. **数据库连接**: `drizzle-orm/postgres-js` → `drizzle-orm/better-sqlite3`
|
||||
6. **数据类型映射**:
|
||||
- UUID: `uuid()` → `text()` (使用 `uuidv7()` 生成)
|
||||
- 时间戳: `timestamp({ withTimezone: true })` → `integer({ mode: 'timestamp_ms' })`
|
||||
- 布尔值: `boolean()` → `integer({ mode: 'boolean' })`
|
||||
- 默认值: `defaultNow()` → `$defaultFn(() => new Date())`
|
||||
7. **环境变量**: `DATABASE_URL` 从 URL 格式改为文件路径 (`./data/app.db`)
|
||||
8. **目录自动创建**: 添加了数据库文件目录的自动创建逻辑
|
||||
**数据类型策略**:
|
||||
- **主键**: TEXT 存储 UUIDv7 (36 字符字符串,全局唯一)
|
||||
- **时间戳**: INTEGER 存储 Unix 毫秒时间戳 (`integer({ mode: 'timestamp_ms' })`)
|
||||
- Drizzle 自动转换 `Date` ↔ `number`
|
||||
- **布尔值**: INTEGER 存储 0/1 (`integer({ mode: 'boolean' })`)
|
||||
- Drizzle 自动转换 `boolean` ↔ `0/1`
|
||||
|
||||
**数据库连接层变更**:
|
||||
**数据库连接**:
|
||||
```typescript
|
||||
// Before (PostgreSQL)
|
||||
import { drizzle } from 'drizzle-orm/postgres-js'
|
||||
export const createDB = () =>
|
||||
drizzle({
|
||||
connection: { url: env.DATABASE_URL, prepare: true },
|
||||
schema,
|
||||
})
|
||||
|
||||
// After (SQLite)
|
||||
import { drizzle } from 'drizzle-orm/better-sqlite3'
|
||||
import Database from 'better-sqlite3'
|
||||
import { mkdirSync } from 'node:fs'
|
||||
@@ -432,75 +409,33 @@ export const createDB = () => {
|
||||
}
|
||||
```
|
||||
|
||||
**Schema 变更示例**:
|
||||
```typescript
|
||||
// Before (PostgreSQL)
|
||||
import { pgTable, text, boolean, timestamp, uuid } from 'drizzle-orm/pg-core'
|
||||
export const todoTable = pgTable('todo', {
|
||||
id: uuid('id').primaryKey().$defaultFn(() => uuidv7()),
|
||||
title: text('title').notNull(),
|
||||
completed: boolean('completed').notNull().default(false),
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
})
|
||||
|
||||
// After (SQLite)
|
||||
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'
|
||||
export const todoTable = sqliteTable('todo', {
|
||||
id: text('id').primaryKey().$defaultFn(() => uuidv7()),
|
||||
title: text('title').notNull(),
|
||||
completed: integer('completed', { mode: 'boolean' }).notNull().default(false),
|
||||
createdAt: integer('created_at', { mode: 'timestamp_ms' }).notNull().$defaultFn(() => new Date()),
|
||||
})
|
||||
```
|
||||
|
||||
**兼容性保证**:
|
||||
- ✅ 所有业务逻辑保持不变
|
||||
- ✅ ORPC 契约和类型完全兼容
|
||||
- ✅ 应用层代码无需修改
|
||||
- ✅ Drizzle 自动处理类型转换 (Date ↔ number, boolean ↔ 0/1)
|
||||
|
||||
**构建验证**:
|
||||
- ✅ `bun typecheck` - 类型检查通过
|
||||
- ✅ `bun fix` - 代码质量检查通过
|
||||
- ✅ `bun run build` - Vite 构建成功
|
||||
- ✅ `bun db:push` - 数据库初始化成功
|
||||
- ✅ SQLite 文件已创建 (`./data/app.db`, 12KB)
|
||||
|
||||
**注意事项**:
|
||||
- SQLite 是文件数据库,适合嵌入环境和开发环境
|
||||
- 不支持多进程并发写入 (适合单应用实例)
|
||||
- 性能足够支持中小型应用 (日请求 < 10万)
|
||||
- SQLite 是文件数据库,适合嵌入环境和单实例应用
|
||||
- 不支持多进程并发写入
|
||||
- 数据库文件和 WAL 文件 (`.db-shm`, `.db-wal`) 已添加到 `.gitignore`
|
||||
- `better-sqlite3` 是原生模块,需要匹配生产环境的 OS 和架构 (构建输出会提示)
|
||||
- `better-sqlite3` 是原生模块,构建时需匹配生产环境 OS 和架构
|
||||
|
||||
**Drizzle 时间戳模式**:
|
||||
- `timestamp_ms`: Unix 毫秒时间戳 (推荐,精度更高)
|
||||
- `timestamp`: Unix 秒时间戳
|
||||
- Drizzle 自动转换 `Date` 对象 ↔ 数字
|
||||
### AGENTS.md 文档维护原则
|
||||
|
||||
**命令对比**:
|
||||
```bash
|
||||
# 开发环境初始化 (推荐)
|
||||
bun db:push
|
||||
**核心原则**:AGENTS.md 只记录当前项目状态,不记录重构历史
|
||||
|
||||
# 生产环境迁移
|
||||
bun db:generate # 生成迁移文件
|
||||
bun db:migrate # 执行迁移
|
||||
1. **当前状态优先**:只描述项目当前使用的技术栈、架构和最佳实践
|
||||
2. **无需向后兼容**:不保留旧技术栈的文档,重构后直接更新为新状态
|
||||
3. **避免历史记录**:不记录"从 X 迁移到 Y"的过程,只记录"当前使用 Y"
|
||||
4. **保持简洁**:删除过时信息,避免上下文过长影响 AI 理解
|
||||
5. **及时同步**:架构变更后立即更新文档,确保文档与代码一致
|
||||
|
||||
# 数据库管理 UI
|
||||
bun db:studio
|
||||
```
|
||||
**何时更新 AGENTS.md**:
|
||||
- 更换技术栈(如数据库、框架)
|
||||
- 修改项目架构或目录结构
|
||||
- 添加/移除重要依赖
|
||||
- 发现重要的最佳实践或经验教训
|
||||
|
||||
### Git 工作流要求
|
||||
|
||||
**重要原则**:保持代码仓库与文档同步
|
||||
|
||||
当遇到技术问题、做出架构决策、或发现重要经验时:
|
||||
1. **立即更新 AGENTS.md**:记录问题、原因、解决方案
|
||||
2. **持续同步**:每次重大变更后更新文档
|
||||
3. **版本关联**:在文档中标注相关的库版本、commit hash
|
||||
|
||||
这确保未来的开发者(包括 AI 助手)能快速理解项目历史和技术选择。
|
||||
**何时不更新 AGENTS.md**:
|
||||
- 日常功能开发
|
||||
- Bug 修复
|
||||
- 代码重构(不涉及架构变更)
|
||||
- 临时实验或 POC
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user