修改文件结构,统一文档格式

This commit is contained in:
ylweng
2025-09-01 02:42:03 +08:00
parent 2bd1d8c032
commit abc1184f81
151 changed files with 870 additions and 589 deletions

282
scripts/seed-manager.js Normal file
View File

@@ -0,0 +1,282 @@
/**
* 数据库种子数据管理器
* @file seed-manager.js
* @description 管理数据库种子数据,用于初始化和测试
*/
require('dotenv').config();
const fs = require('fs');
const path = require('path');
const { sequelize } = require('../config/database-simple');
const { QueryTypes } = require('sequelize');
// 种子文件目录
const SEEDS_DIR = path.join(__dirname, '../seeds');
// 确保种子目录存在
if (!fs.existsSync(SEEDS_DIR)) {
fs.mkdirSync(SEEDS_DIR, { recursive: true });
}
// 创建种子记录表(如果不存在)
async function createSeedTable() {
await sequelize.query(`
CREATE TABLE IF NOT EXISTS seeds (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
`);
}
// 获取已应用的种子
async function getAppliedSeeds() {
await createSeedTable();
const seeds = await sequelize.query(
'SELECT name FROM seeds ORDER BY id ASC',
{ type: QueryTypes.SELECT }
);
return seeds.map(seed => seed.name);
}
// 获取所有种子文件
function getAllSeeds() {
return fs.readdirSync(SEEDS_DIR)
.filter(file => file.endsWith('.js'))
.sort(); // 按文件名排序
}
// 应用种子数据
async function applySeed(seedName) {
const seed = require(path.join(SEEDS_DIR, seedName));
console.log(`正在应用种子数据: ${seedName}`);
// 开始事务
const transaction = await sequelize.transaction();
try {
// 执行种子的 up 方法
await seed.up(sequelize.getQueryInterface(), sequelize);
// 记录种子已应用
await sequelize.query(
'INSERT INTO seeds (name) VALUES (:name)',
{
replacements: { name: seedName },
transaction
}
);
// 提交事务
await transaction.commit();
console.log(`种子数据应用成功: ${seedName}`);
} catch (error) {
// 回滚事务
await transaction.rollback();
console.error(`种子数据应用失败: ${seedName}`, error);
throw error;
}
}
// 回滚种子数据
async function revertSeed(seedName) {
const seed = require(path.join(SEEDS_DIR, seedName));
console.log(`正在回滚种子数据: ${seedName}`);
// 开始事务
const transaction = await sequelize.transaction();
try {
// 执行种子的 down 方法
await seed.down(sequelize.getQueryInterface(), sequelize);
// 删除种子记录
await sequelize.query(
'DELETE FROM seeds WHERE name = :name',
{
replacements: { name: seedName },
transaction
}
);
// 提交事务
await transaction.commit();
console.log(`种子数据回滚成功: ${seedName}`);
} catch (error) {
// 回滚事务
await transaction.rollback();
console.error(`种子数据回滚失败: ${seedName}`, error);
throw error;
}
}
// 运行所有种子数据
async function runAllSeeds() {
const appliedSeeds = await getAppliedSeeds();
const allSeeds = getAllSeeds();
// 找出未应用的种子
const pendingSeeds = allSeeds.filter(
seed => !appliedSeeds.includes(seed)
);
if (pendingSeeds.length === 0) {
console.log('没有待处理的种子数据');
return;
}
console.log(`发现 ${pendingSeeds.length} 个待处理的种子数据`);
// 按顺序应用每个待处理的种子
for (const seed of pendingSeeds) {
await applySeed(seed);
}
console.log('所有待处理的种子数据已应用');
}
// 回滚所有种子数据
async function revertAllSeeds() {
const appliedSeeds = await getAppliedSeeds();
if (appliedSeeds.length === 0) {
console.log('没有可回滚的种子数据');
return;
}
// 从最新的种子开始,回滚所有种子
const seedsToRevert = [...appliedSeeds].reverse();
for (const seed of seedsToRevert) {
await revertSeed(seed);
}
console.log('所有种子数据已回滚');
}
// 创建新的种子文件
function createSeed(name) {
const timestamp = new Date().toISOString().replace(/[-:]/g, '').replace('T', '').split('.')[0];
const fileName = `${timestamp}_${name}.js`;
const filePath = path.join(SEEDS_DIR, fileName);
const template = `/**
* 种子数据: ${name}
* 创建时间: ${new Date().toISOString()}
*/
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
// 在此处添加种子数据
// 例如:
// await queryInterface.bulkInsert('users', [
// {
// username: 'admin',
// email: 'admin@example.com',
// password: '$2b$10$rVHMOB./a2mFmE4EEdI3QO4f./bN3LYb.dpDvtX9gRUM9gNwspj1a', // 123456
// created_at: new Date(),
// updated_at: new Date()
// },
// {
// username: 'user',
// email: 'user@example.com',
// password: '$2b$10$rVHMOB./a2mFmE4EEdI3QO4f./bN3LYb.dpDvtX9gRUM9gNwspj1a', // 123456
// created_at: new Date(),
// updated_at: new Date()
// }
// ]);
},
down: async (queryInterface, Sequelize) => {
// 在此处添加回滚代码
// 例如:
// await queryInterface.bulkDelete('users', null, {});
}
};
`;
fs.writeFileSync(filePath, template);
console.log(`已创建种子文件: ${fileName}`);
return fileName;
}
// 命令行接口
async function main() {
const args = process.argv.slice(2);
const command = args[0];
try {
switch (command) {
case 'create':
if (!args[1]) {
console.error('请提供种子名称');
process.exit(1);
}
createSeed(args[1]);
break;
case 'run':
await runAllSeeds();
break;
case 'revert':
await revertAllSeeds();
break;
case 'status':
const applied = await getAppliedSeeds();
const all = getAllSeeds();
console.log('已应用的种子数据:');
applied.forEach(s => console.log(` - ${s}`));
console.log('\n待处理的种子数据:');
all.filter(s => !applied.includes(s))
.forEach(s => console.log(` - ${s}`));
break;
default:
console.log(`
数据库种子数据管理器
用法:
node seed-manager.js <命令> [参数]
命令:
create <name> 创建新的种子文件
run 应用所有待处理的种子数据
revert 回滚所有种子数据
status 显示种子数据状态
`);
}
} catch (error) {
console.error('种子数据操作失败:', error);
process.exit(1);
} finally {
// 关闭数据库连接
await sequelize.close();
}
}
// 如果直接运行此脚本则执行main函数
if (require.main === module) {
main().catch(err => {
console.error('未处理的错误:', err);
process.exit(1);
});
}
module.exports = {
createSeedTable,
getAppliedSeeds,
getAllSeeds,
applySeed,
revertSeed,
runAllSeeds,
revertAllSeeds,
createSeed
};