/** * Copies missing env files from their .example templates, and warns about * any keys present in the example but not set in the environment. * Also warns about any VITE_ vars set in the environment that aren't listed * in any example file. * * Usage: * tsx scripts/setup-env.ts # checks .env * tsx scripts/setup-env.ts --desktop # also checks .env.desktop * tsx scripts/setup-env.ts --saas # also checks .env.saas */ import { existsSync, copyFileSync, readFileSync } from "fs"; import { join } from "path"; import { config, parse } from "dotenv"; // npm scripts run from the directory containing package.json (frontend/) const root = process.cwd(); const args = process.argv.slice(2); const isDesktop = args.includes("--desktop"); const isSaas = args.includes("--saas"); console.log( "setup-env: see frontend/README.md#environment-variables for documentation", ); function getExampleKeys(exampleFile: string): string[] { const examplePath = join(root, exampleFile); if (!existsSync(examplePath)) return []; return Object.keys(parse(readFileSync(examplePath, "utf-8"))); } function ensureEnvFile(envFile: string, exampleFile: string): boolean { const envPath = join(root, envFile); const examplePath = join(root, exampleFile); if (!existsSync(examplePath)) { console.warn(`setup-env: ${exampleFile} not found, skipping ${envFile}`); return false; } if (!existsSync(envPath)) { copyFileSync(examplePath, envPath); console.log(`setup-env: created ${envFile} from ${exampleFile}`); } config({ path: envPath }); const missing = getExampleKeys(exampleFile).filter( (k) => !(k in process.env), ); if (missing.length > 0) { console.error( `setup-env: ${envFile} is missing keys from ${exampleFile}:\n` + missing.map((k) => ` ${k}`).join("\n") + "\n Add them manually or delete your local file to re-copy from the example.", ); return true; } return false; } let failed = false; failed = ensureEnvFile(".env", "config/.env.example") || failed; if (isDesktop) { failed = ensureEnvFile(".env.desktop", "config/.env.desktop.example") || failed; } if (isSaas) { failed = ensureEnvFile(".env.saas", "config/.env.saas.example") || failed; } // Warn about any VITE_ vars set in the environment that aren't listed in any example file. const allExampleKeys = new Set([ ...getExampleKeys("config/.env.example"), ...getExampleKeys("config/.env.desktop.example"), ...getExampleKeys("config/.env.saas.example"), ]); const unknownViteVars = Object.keys(process.env).filter( (k) => k.startsWith("VITE_") && !allExampleKeys.has(k), ); if (unknownViteVars.length > 0) { console.warn( "setup-env: the following VITE_ vars are set but not listed in any example file:\n" + unknownViteVars.map((k) => ` ${k}`).join("\n") + "\n Add them to the appropriate config/.env.*.example file if they are required.", ); } if (failed) process.exit(1);