You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
237 lines
6.1 KiB
237 lines
6.1 KiB
/**
|
|
* 数据库工具脚本
|
|
* 用于创建迁移文件和种子数据文件
|
|
*/
|
|
|
|
import { writeFileSync, mkdirSync, existsSync } from 'fs'
|
|
import { resolve, dirname } from 'path'
|
|
import { fileURLToPath } from 'url'
|
|
|
|
// 获取当前文件目录
|
|
const __filename = fileURLToPath(import.meta.url)
|
|
const __dirname = dirname(__filename)
|
|
const projectRoot = resolve(__dirname, '..')
|
|
|
|
// 配置路径
|
|
const MIGRATIONS_DIR = 'src/infrastructure/database/migrations'
|
|
const SEEDS_DIR = 'src/infrastructure/database/seeds'
|
|
|
|
/**
|
|
* 生成时间戳
|
|
* @returns {string} 格式: YYYYMMDDHHMMSS
|
|
*/
|
|
function generateTimestamp() {
|
|
const now = new Date()
|
|
const year = now.getFullYear()
|
|
const month = String(now.getMonth() + 1).padStart(2, '0')
|
|
const day = String(now.getDate()).padStart(2, '0')
|
|
const hours = String(now.getHours()).padStart(2, '0')
|
|
const minutes = String(now.getMinutes()).padStart(2, '0')
|
|
const seconds = String(now.getSeconds()).padStart(2, '0')
|
|
|
|
return `${year}${month}${day}${hours}${minutes}${seconds}`
|
|
}
|
|
|
|
/**
|
|
* 创建迁移文件模板
|
|
* @param {string} migrationName 迁移名称
|
|
* @returns {string} 迁移文件内容
|
|
*/
|
|
function createMigrationTemplate(migrationName) {
|
|
return `/**
|
|
* ${migrationName} 迁移文件
|
|
* @param { import("knex").Knex } knex
|
|
* @returns { Promise<void> }
|
|
*/
|
|
export const up = async knex => {
|
|
// TODO: 在此处编写数据库结构变更逻辑
|
|
// 例如:创建表、添加列、创建索引等
|
|
|
|
/*
|
|
return knex.schema.createTable('table_name', table => {
|
|
table.increments('id').primary()
|
|
table.string('name').notNullable()
|
|
table.timestamps(true, true)
|
|
})
|
|
*/
|
|
}
|
|
|
|
/**
|
|
* @param { import("knex").Knex } knex
|
|
* @returns { Promise<void> }
|
|
*/
|
|
export const down = async knex => {
|
|
// TODO: 在此处编写回滚逻辑
|
|
// 例如:删除表、删除列、删除索引等
|
|
|
|
/*
|
|
return knex.schema.dropTable('table_name')
|
|
*/
|
|
}
|
|
`
|
|
}
|
|
|
|
/**
|
|
* 创建种子数据文件模板
|
|
* @param {string} seedName 种子数据名称
|
|
* @returns {string} 种子数据文件内容
|
|
*/
|
|
function createSeedTemplate(seedName) {
|
|
return `/**
|
|
* ${seedName} 种子数据
|
|
* @param { import("knex").Knex } knex
|
|
* @returns { Promise<void> }
|
|
*/
|
|
export const seed = async knex => {
|
|
// 清空现有数据(可选)
|
|
// await knex('table_name').del()
|
|
|
|
// 插入种子数据
|
|
/*
|
|
await knex('table_name').insert([
|
|
{
|
|
name: '示例数据1',
|
|
created_at: knex.fn.now(),
|
|
updated_at: knex.fn.now()
|
|
},
|
|
{
|
|
name: '示例数据2',
|
|
created_at: knex.fn.now(),
|
|
updated_at: knex.fn.now()
|
|
}
|
|
])
|
|
|
|
console.log('✅ ${seedName} seeded successfully!')
|
|
*/
|
|
}
|
|
`
|
|
}
|
|
|
|
/**
|
|
* 创建迁移文件
|
|
* @param {string} migrationName 迁移名称
|
|
*/
|
|
function createMigration(migrationName) {
|
|
if (!migrationName) {
|
|
console.error('❌ 请提供迁移名称')
|
|
console.log('用法: bun run scripts/db-tools.js migrate <migration_name>')
|
|
process.exit(1)
|
|
}
|
|
|
|
// 确保目录存在
|
|
const migrationsPath = resolve(projectRoot, MIGRATIONS_DIR)
|
|
if (!existsSync(migrationsPath)) {
|
|
mkdirSync(migrationsPath, { recursive: true })
|
|
}
|
|
|
|
// 生成文件名
|
|
const timestamp = generateTimestamp()
|
|
const fileName = `${timestamp}_${migrationName}.mjs`
|
|
const filePath = resolve(migrationsPath, fileName)
|
|
|
|
// 检查文件是否已存在
|
|
if (existsSync(filePath)) {
|
|
console.error(`❌ 迁移文件已存在: ${fileName}`)
|
|
process.exit(1)
|
|
}
|
|
|
|
// 创建文件
|
|
const content = createMigrationTemplate(migrationName)
|
|
writeFileSync(filePath, content, 'utf8')
|
|
|
|
console.log(`✅ 迁移文件创建成功: ${fileName}`)
|
|
console.log(`📁 路径: ${filePath}`)
|
|
console.log(`📝 请编辑文件并实现 up() 和 down() 方法`)
|
|
}
|
|
|
|
/**
|
|
* 创建种子数据文件
|
|
* @param {string} seedName 种子数据名称
|
|
*/
|
|
function createSeed(seedName) {
|
|
if (!seedName) {
|
|
console.error('❌ 请提供种子数据名称')
|
|
console.log('用法: bun run scripts/db-tools.js seed <seed_name>')
|
|
process.exit(1)
|
|
}
|
|
|
|
// 确保目录存在
|
|
const seedsPath = resolve(projectRoot, SEEDS_DIR)
|
|
if (!existsSync(seedsPath)) {
|
|
mkdirSync(seedsPath, { recursive: true })
|
|
}
|
|
|
|
// 生成文件名
|
|
const timestamp = generateTimestamp()
|
|
const fileName = `${timestamp}_${seedName}.mjs`
|
|
const filePath = resolve(seedsPath, fileName)
|
|
|
|
// 检查文件是否已存在
|
|
if (existsSync(filePath)) {
|
|
console.error(`❌ 种子数据文件已存在: ${fileName}`)
|
|
process.exit(1)
|
|
}
|
|
|
|
// 创建文件
|
|
const content = createSeedTemplate(seedName)
|
|
writeFileSync(filePath, content, 'utf8')
|
|
|
|
console.log(`✅ 种子数据文件创建成功: ${fileName}`)
|
|
console.log(`📁 路径: ${filePath}`)
|
|
console.log(`📝 请编辑文件并实现 seed() 方法`)
|
|
}
|
|
|
|
/**
|
|
* 显示帮助信息
|
|
*/
|
|
function showHelp() {
|
|
console.log(`
|
|
🗄️ 数据库工具 - 迁移和种子数据管理
|
|
|
|
用法:
|
|
bun run scripts/db-tools.js <command> [options]
|
|
|
|
命令:
|
|
migrate <name> 创建新的迁移文件
|
|
seed <name> 创建新的种子数据文件
|
|
help 显示帮助信息
|
|
|
|
示例:
|
|
bun run scripts/db-tools.js migrate create_posts_table
|
|
bun run scripts/db-tools.js seed posts_seed
|
|
|
|
💡 提示:
|
|
- 迁移文件用于管理数据库结构变更
|
|
- 种子数据文件用于插入测试或初始数据
|
|
- 文件名会自动添加时间戳前缀
|
|
- 所有文件使用 ES 模块格式 (.mjs)
|
|
`)
|
|
}
|
|
|
|
// 主函数
|
|
function main() {
|
|
const args = process.argv.slice(2)
|
|
const command = args[0]
|
|
const name = args[1]
|
|
|
|
switch (command) {
|
|
case 'migrate':
|
|
createMigration(name)
|
|
break
|
|
case 'seed':
|
|
createSeed(name)
|
|
break
|
|
case 'help':
|
|
case '--help':
|
|
case '-h':
|
|
showHelp()
|
|
break
|
|
default:
|
|
console.error(`❌ 未知命令: ${command}`)
|
|
showHelp()
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
// 运行主函数
|
|
main()
|