// 灵犀 · 种子数据(A0) // 原则: // 1) 只 seed 已建表的系统配置(system_configs),不提前创建 A1+ 业务表; // 2) 幂等:按 config_key upsert,已存在的配置不覆盖(避免冲掉人工调整值); // 3) 超管、角色、字典、电商行业包占位等种子依赖 A1/A3/A4/B0 的建表,见 prisma/SEED.md。 import { randomBytes } from 'node:crypto'; import { existsSync } from 'node:fs'; import { resolve } from 'node:path'; import { PrismaClient } from '@prisma/client'; import { config as loadDotenv } from 'dotenv'; for (const file of ['.env.local', '.env']) { const path = resolve(process.cwd(), file); if (existsSync(path)) { loadDotenv({ path }); } } const prisma = new PrismaClient(); const ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ'; function ulid(): string { let time = Date.now(); const timeChars = new Array(10); for (let i = 9; i >= 0; i -= 1) { timeChars[i] = ENCODING[time % 32] ?? '0'; time = Math.floor(time / 32); } const random = randomBytes(16); const randomChars = Array.from(random, (byte) => ENCODING[byte & 31] ?? '0'); return `${timeChars.join('')}${randomChars.join('')}`; } interface SeedConfig { key: string; value: string | number | boolean; valueType: 'string' | 'number' | 'boolean'; description: string; } const systemConfigs: SeedConfig[] = [ { key: 'platform.name', value: '灵犀', valueType: 'string', description: '平台名称(展示用)', }, { key: 'platform.export.signed_url_ttl_seconds', value: 900, valueType: 'number', description: '导出产物签名 URL 有效期(秒),短时效', }, { key: 'platform.export.archive_retention_days', value: 3, valueType: 'number', description: '导出打包产物默认保留天数', }, { key: 'platform.upload.max_upload_mb', value: 500, valueType: 'number', description: '单文件上传上限(MB)', }, { key: 'platform.page.default_limit', value: 20, valueType: 'number', description: '列表默认每页数量', }, { key: 'platform.ai.cost_soft_limit_ratio', value: 0.8, valueType: 'number', description: 'AI 成本软上限触发比例', }, { key: 'platform.ai.cost_hard_limit_ratio', value: 1, valueType: 'number', description: 'AI 成本硬上限触发比例(达到即拒绝新任务)', }, ]; async function main(): Promise { for (const item of systemConfigs) { await prisma.systemConfig.upsert({ where: { configKey: item.key }, update: {}, create: { id: ulid(), configKey: item.key, configValue: item.value, valueType: item.valueType, description: item.description, }, }); } console.log(`[seed] system_configs 就绪:${String(systemConfigs.length)} 项(幂等)`); } main() .catch((error: unknown) => { console.error('[seed] 失败:', error); process.exitCode = 1; }) .finally(async () => { await prisma.$disconnect(); });