#!/usr/bin/env node 'use strict'; /** * 渲染 libredesk/config/config.toml: * - 读取顶层 .env(crm-new/.env) * - 替换模板中的 DB 用户/密码/加密密钥占位符 * - 输出 600 权限的 config.toml(不入库) */ const fs = require('fs'); const path = require('path'); const root = path.resolve(__dirname, '..'); const envPath = path.join(root, '.env'); const tplPath = path.join(root, 'libredesk', 'config', 'config.toml.example'); const outPath = path.join(root, 'libredesk', 'config', 'config.toml'); function parseEnv(text) { const out = {}; for (const line of text.split('\n')) { const t = line.trim(); if (!t || t.startsWith('#')) continue; const eq = t.indexOf('='); if (eq < 0) continue; const key = t.slice(0, eq).trim(); let value = t.slice(eq + 1).trim(); if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) { value = value.slice(1, -1); } out[key] = value; } return out; } if (!fs.existsSync(envPath)) { console.error('[render-config] .env 不存在,请先运行 scripts/bootstrap.sh'); process.exit(1); } const env = parseEnv(fs.readFileSync(envPath, 'utf8')); for (const key of ['POSTGRES_USER', 'POSTGRES_PASSWORD', 'LIBREDESK_ENC_KEY']) { if (!env[key]) { console.error(`[render-config] 缺少 ${key}`); process.exit(1); } } if (env.LIBREDESK_ENC_KEY.length !== 32) { console.error('[render-config] LIBREDESK_ENC_KEY 必须是 32 字符(openssl rand -hex 16)'); process.exit(1); } const rendered = fs .readFileSync(tplPath, 'utf8') .replaceAll('__DB_USER__', env.POSTGRES_USER) .replaceAll('__DB_PASSWORD__', env.POSTGRES_PASSWORD) .replaceAll('__ENCRYPTION_KEY__', env.LIBREDESK_ENC_KEY); fs.writeFileSync(outPath, rendered, { mode: 0o600 }); console.log(`[render-config] wrote ${path.relative(root, outPath)} (mode 600)`);