File size: 2,012 Bytes
7f88bdf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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.");