Separate base database initialization from test data seeding

This commit is contained in:
2026-07-20 19:49:29 +08:00 Unverified
parent 5b86cdaec2
commit b8f2799ed6
11 changed files with 345 additions and 43 deletions
+37
View File
@@ -0,0 +1,37 @@
import { pbkdf2Sync, randomBytes } from 'node:crypto';
import { rm } from 'node:fs/promises';
import { isAbsolute, join, relative, resolve } from 'node:path';
import { createDatabase } from '../database.mjs';
import { createSeedDatabase } from '../src/data/seed.mjs';
const root = resolve(process.cwd());
const databasePath = resolve(process.env.SQLITE_PATH || join(root, 'data', 'exam.sqlite'));
const relativePath = relative(root, databasePath);
if (!relativePath || relativePath.startsWith('..') || isAbsolute(relativePath)) throw new Error('拒绝覆盖工作区以外的数据库');
function hashPassword(password, salt = randomBytes(16).toString('hex')) {
const hash = pbkdf2Sync(password, salt, 120000, 32, 'sha256').toString('hex');
return `${salt}:${hash}`;
}
await rm(databasePath, { force: true });
await rm(`${databasePath}-shm`, { force: true });
await rm(`${databasePath}-wal`, { force: true });
process.env.DATABASE_CLIENT = 'sqlite';
process.env.SQLITE_PATH = databasePath;
const database = await createDatabase({
root,
seed: () => createSeedDatabase({ nowIso: () => new Date().toISOString(), hashPassword })
});
const state = await database.read();
await database.close();
const pending = state.registrations.filter(item => item.status === 'pending').length;
const rejected = state.registrations.filter(item => item.status === 'rejected').length;
const unpaid = state.registrations.filter(item => item.status === 'approved' && item.paymentStatus === 'unpaid').length;
const paid = state.registrations.filter(item => item.status === 'approved' && item.paymentStatus === 'paid').length;
console.log(`Imported test data into ${databasePath}`);
console.log(`${state.schools.length} schools, ${state.candidateProfiles.length} candidates, ${state.registrations.length} registrations`);
console.log(`pending ${pending}, rejected ${rejected}, approved/unpaid ${unpaid}, approved/paid ${paid}`);
console.log(`arrangement plans ${state.arrangementPlans.length}, admit cards ${state.registrations.filter(item => item.admitCard).length}`);