| import crypto from "node:crypto"; |
| import fs from "node:fs"; |
| import path from "node:path"; |
|
|
| const repoRoot = process.cwd(); |
| const examplePath = path.join(repoRoot, ".env.example"); |
| const targetPath = path.join(repoRoot, ".env.local"); |
|
|
| function parseEnv(text) { |
| const map = new Map(); |
| const order = []; |
|
|
| for (const rawLine of text.split(/\r?\n/)) { |
| const line = rawLine.trim(); |
| if (!line || line.startsWith("#")) { |
| continue; |
| } |
|
|
| const eqIndex = line.indexOf("="); |
| if (eqIndex === -1) { |
| continue; |
| } |
|
|
| const key = line.slice(0, eqIndex).trim(); |
| const value = line.slice(eqIndex + 1); |
| if (!map.has(key)) { |
| order.push(key); |
| } |
| map.set(key, value); |
| } |
|
|
| return { map, order }; |
| } |
|
|
| function readFileIfExists(filePath) { |
| return fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf8") : ""; |
| } |
|
|
| if (!fs.existsSync(examplePath)) { |
| throw new Error(".env.example was not found."); |
| } |
|
|
| const example = parseEnv(readFileIfExists(examplePath)); |
| const existing = parseEnv(readFileIfExists(targetPath)); |
|
|
| const merged = new Map(example.map); |
| for (const [key, value] of existing.map.entries()) { |
| merged.set(key, value); |
| } |
|
|
| if (!merged.get("DEV_ORGANIZATION_ID")) { |
| merged.set("DEV_ORGANIZATION_ID", crypto.randomUUID()); |
| } |
| if (!merged.get("DEV_USER_ID")) { |
| merged.set("DEV_USER_ID", crypto.randomUUID()); |
| } |
| if (!merged.get("DEV_AUTO_BOOTSTRAP")) { |
| merged.set("DEV_AUTO_BOOTSTRAP", "1"); |
| } |
|
|
| const orderedKeys = [...example.order]; |
| for (const key of existing.order) { |
| if (!orderedKeys.includes(key)) { |
| orderedKeys.push(key); |
| } |
| } |
|
|
| const output = [ |
| "# Generated by scripts/setup-env.mjs", |
| "# Fill required secrets before running db:migrate and API flows.", |
| ...orderedKeys.map((key) => `${key}=${merged.get(key) ?? ""}`), |
| "" |
| ].join("\n"); |
|
|
| fs.writeFileSync(targetPath, output, "utf8"); |
|
|
| console.log(`Wrote ${path.relative(repoRoot, targetPath)}`); |
| console.log("Set defaults for DEV_ORGANIZATION_ID, DEV_USER_ID, and DEV_AUTO_BOOTSTRAP."); |
|
|