import { readFileSync, existsSync } from "node:fs"; import { resolve } from "node:path"; import { spawn } from "node:child_process"; import { parse } from "dotenv"; const [environment = "development", command = "dev", ...args] = process.argv.slice(2); if ( !["development", "test", "production"].includes(environment) || !["dev", "build", "start"].includes(command) ) { throw new Error( "Usage: tsx scripts/next-env.ts development|test|production dev|build|start", ); } const config = (file: string) => existsSync(file) ? parse(readFileSync(file)) : {}; const childEnv: NodeJS.ProcessEnv = { ...config(resolve(`config/${environment}.env`)), ...config(resolve(`config/${environment}.local.env`)), ...process.env, APP_ENV: environment, NODE_ENV: command === "dev" ? "development" : "production", }; if (command !== "build" && !childEnv.UPSTREAM_API_URL?.trim()) { throw new Error( `UPSTREAM_API_URL is required for ${environment}. Set config/${environment}.local.env or the process environment.`, ); } // Turbopack 16.4 can repeatedly restart the root runtime chunk on this site's // dynamic document routes. Keep stable development HMR and allow explicit opt-in. if (command === "dev" || command === "build") await import("./build-pwa"); const devBundler = command === "dev" && !args.some((arg) => ["--webpack", "--turbopack", "--turbo"].includes(arg)) ? [childEnv.NEXT_DEV_BUNDLER === "turbopack" ? "--turbopack" : "--webpack"] : []; const child = spawn( process.execPath, [ resolve("node_modules/next/dist/bin/next"), command, ...devBundler, ...(command === "build" ? [] : ["--port", childEnv.PORT || "25121"]), ...args, ], { stdio: "inherit", env: childEnv }, ); for (const signal of ["SIGINT", "SIGTERM"] as const) process.on(signal, () => child.kill(signal)); child.on("exit", (code) => process.exit(code ?? 1));