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}`);