Browse Source

feat: Update database schema and migration scripts

- Added new migration scripts for the `users` table, replacing the deprecated `users_table`.
- Updated `package.json` with new database commands for generating, pushing, and migrating schemas.
- Enhanced `README.md` with instructions for database migration and deployment.
- Refactored database connection handling to use a connection pool for improved performance.
db
谢亚昕 2 months ago
parent
commit
4229894af2
  1. 13
      README.md
  2. 10
      packages/server/drizzle/0000_damp_rocket_racer.sql
  3. 8
      packages/server/drizzle/0000_thick_may_parker.sql
  4. 59
      packages/server/drizzle/meta/0000_snapshot.json
  5. 4
      packages/server/drizzle/meta/_journal.json
  6. 6
      packages/server/package.json
  7. 11
      packages/server/src/db/index.ts
  8. 19
      packages/server/src/db/migrate.ts
  9. 19
      packages/server/src/db/schema.ts

13
README.md

@ -10,4 +10,15 @@ https://www.doubao.com/chat/23869592666505474
## 要求 ## 要求
bun < 1.2.0 bun < 1.2.0
# 1) 生成迁移(根据 schema 变更生成 SQL 到 packages/server/drizzle)
bun run --cwd packages/server db:generate # 生成迁移文件
# 2) 推送/迁移(任选其一)
bun run --cwd packages/server db:push # 直接将 schema 同步到 DB(简单场景)
bun run --cwd packages/server db:migrate # 执行已生成的迁移脚本(更可控)
# 3) 部署阶段(CI/CD)
bun run --cwd packages/server deploy:migrate # 在部署容器/机器执行迁移

10
packages/server/drizzle/0000_damp_rocket_racer.sql

@ -0,0 +1,10 @@
CREATE TABLE `users` (
`id` serial AUTO_INCREMENT NOT NULL,
`username` varchar(64) NOT NULL,
`email` varchar(255) NOT NULL,
`password_hash` varchar(255) NOT NULL,
`is_active` boolean NOT NULL DEFAULT true,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `users_id` PRIMARY KEY(`id`)
);

8
packages/server/drizzle/0000_thick_may_parker.sql

@ -1,8 +0,0 @@
CREATE TABLE `users_table` (
`id` serial AUTO_INCREMENT NOT NULL,
`name` varchar(255) NOT NULL,
`age` int NOT NULL,
`email` varchar(255) NOT NULL,
CONSTRAINT `users_table_id` PRIMARY KEY(`id`),
CONSTRAINT `users_table_email_unique` UNIQUE(`email`)
);

59
packages/server/drizzle/meta/0000_snapshot.json

@ -1,11 +1,11 @@
{ {
"version": "5", "version": "5",
"dialect": "mysql", "dialect": "mysql",
"id": "3770df0e-b3f2-4223-8e66-2880f634d8b0", "id": "df298012-0f90-4945-b49b-e9713616dcaf",
"prevId": "00000000-0000-0000-0000-000000000000", "prevId": "00000000-0000-0000-0000-000000000000",
"tables": { "tables": {
"users_table": { "users": {
"name": "users_table", "name": "users",
"columns": { "columns": {
"id": { "id": {
"name": "id", "name": "id",
@ -14,46 +14,63 @@
"notNull": true, "notNull": true,
"autoincrement": true "autoincrement": true
}, },
"name": { "username": {
"name": "name", "name": "username",
"type": "varchar(255)", "type": "varchar(64)",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"age": { "email": {
"name": "age", "name": "email",
"type": "int", "type": "varchar(255)",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"email": { "password_hash": {
"name": "email", "name": "password_hash",
"type": "varchar(255)", "type": "varchar(255)",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
},
"is_active": {
"name": "is_active",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"
} }
}, },
"indexes": {}, "indexes": {},
"foreignKeys": {}, "foreignKeys": {},
"compositePrimaryKeys": { "compositePrimaryKeys": {
"users_table_id": { "users_id": {
"name": "users_table_id", "name": "users_id",
"columns": [ "columns": [
"id" "id"
] ]
} }
}, },
"uniqueConstraints": { "uniqueConstraints": {},
"users_table_email_unique": {
"name": "users_table_email_unique",
"columns": [
"email"
]
}
},
"checkConstraint": {} "checkConstraint": {}
} }
}, },

4
packages/server/drizzle/meta/_journal.json

@ -5,8 +5,8 @@
{ {
"idx": 0, "idx": 0,
"version": "5", "version": "5",
"when": 1760625865036, "when": 1760694111964,
"tag": "0000_thick_may_parker", "tag": "0000_damp_rocket_racer",
"breakpoints": true "breakpoints": true
} }
] ]

6
packages/server/package.json

@ -8,7 +8,11 @@
} }
}, },
"scripts": { "scripts": {
"db": "bunx --bun drizzle-kit " "db": "bunx --bun drizzle-kit",
"db:generate": "bunx --bun drizzle-kit generate",
"db:push": "bunx --bun drizzle-kit push",
"db:migrate": "bun run ./src/db/migrate.ts",
"deploy:migrate": "bun run ./src/db/migrate.ts"
}, },
"devDependencies": { "devDependencies": {
"@types/formidable": "^3.4.5", "@types/formidable": "^3.4.5",

11
packages/server/src/db/index.ts

@ -1,4 +1,11 @@
import { drizzle } from "drizzle-orm/mysql2"; import { drizzle } from "drizzle-orm/mysql2";
import mysql from "mysql2/promise";
// You can specify any property from the mysql2 connection options // 使用连接池提升并发能力;支持通过 DATABASE_URL 直连(例:mysql://user:pass@host:3306/db)
const db = drizzle({ connection: { uri: process.env.DATABASE_URL } }); // 生产/本地统一从环境变量读取,避免硬编码
const pool = mysql.createPool(process.env.DATABASE_URL as string);
// Drizzle 实例,供全局复用;建议在应用层只导入 db,不直接操作 pool
const db = drizzle(pool);
export { db, pool };

19
packages/server/src/db/migrate.ts

@ -0,0 +1,19 @@
import { migrate } from 'drizzle-orm/mysql2/migrator'
import { db, pool } from './index'
// 运行数据库迁移脚本(部署阶段调用)
// 要求:环境变量 DATABASE_URL 已配置
// 迁移文件目录:packages/server/drizzle
(async () => {
try {
await migrate(db, { migrationsFolder: new URL('../../drizzle', import.meta.url).pathname })
console.log('[drizzle] migration completed')
} catch (err) {
console.error('[drizzle] migration failed:', err)
process.exitCode = 1
} finally {
await pool.end()
}
})()

19
packages/server/src/db/schema.ts

@ -1,8 +1,13 @@
import { int, mysqlTable, serial, varchar } from 'drizzle-orm/mysql-core'; import { mysqlTable, serial, varchar, timestamp, boolean } from 'drizzle-orm/mysql-core'
import { sql } from 'drizzle-orm'
export const usersTable = mysqlTable('users_table', { // 用户表:满足基础登录/鉴权与审计需求
id: serial().primaryKey(), export const usersTable = mysqlTable('users', {
name: varchar({ length: 255 }).notNull(), id: serial('id').primaryKey(), // 自增主键
age: int().notNull(), username: varchar('username', { length: 64 }).notNull(), // 用户名,登录凭证之一
email: varchar({ length: 255 }).notNull().unique(), email: varchar('email', { length: 255 }).notNull(), // 邮箱,唯一
}); passwordHash: varchar('password_hash', { length: 255 }).notNull(), // 密码哈希
isActive: boolean('is_active').notNull().default(true), // 启用状态
createdAt: timestamp('created_at').notNull().default(sql`CURRENT_TIMESTAMP`), // 创建时间
updatedAt: timestamp('updated_at').notNull().default(sql`CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP`), // 更新时间
})

Loading…
Cancel
Save