fix(tooling): harden database env loading
This commit is contained in:
@@ -1,14 +1,17 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { URL } from "node:url";
|
||||
import { loadWorkspaceEnv, resolveWorkspaceEnvPath } from "./load-env.mjs";
|
||||
import { loadWorkspaceEnv, resolveWorkspaceEnvPaths } from "./load-env.mjs";
|
||||
|
||||
const envPath = loadWorkspaceEnv();
|
||||
const loadedEnvPaths = loadWorkspaceEnv();
|
||||
const expectedDatabase = process.argv[2] ?? "capakraken";
|
||||
const rawUrl = process.env.DATABASE_URL;
|
||||
const expectedEnvSources = loadedEnvPaths.length > 0
|
||||
? loadedEnvPaths.join(", ")
|
||||
: resolveWorkspaceEnvPaths().join(", ");
|
||||
|
||||
if (!rawUrl) {
|
||||
console.error(`DATABASE_URL is not configured. Expected it from ${envPath ?? resolveWorkspaceEnvPath()}.`);
|
||||
console.error(`DATABASE_URL is not configured. Expected it from one of: ${expectedEnvSources}.`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
+49
-25
@@ -6,40 +6,64 @@ function resolveWorkspaceRoot() {
|
||||
return resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
}
|
||||
|
||||
export function resolveWorkspaceEnvPath() {
|
||||
return resolve(resolveWorkspaceRoot(), ".env");
|
||||
export function resolveWorkspaceEnvPath(options = {}) {
|
||||
const { workspaceRoot = resolveWorkspaceRoot() } = options;
|
||||
return resolve(workspaceRoot, ".env");
|
||||
}
|
||||
|
||||
export function loadWorkspaceEnv() {
|
||||
const envPath = resolveWorkspaceEnvPath();
|
||||
if (!existsSync(envPath)) {
|
||||
return envPath;
|
||||
export function resolveWorkspaceEnvPaths(options = {}) {
|
||||
const { workspaceRoot = resolveWorkspaceRoot(), nodeEnv = process.env.NODE_ENV } = options;
|
||||
const candidates = [".env"];
|
||||
|
||||
if (nodeEnv) {
|
||||
candidates.push(`.env.${nodeEnv}`);
|
||||
}
|
||||
|
||||
const contents = readFileSync(envPath, "utf8");
|
||||
for (const rawLine of contents.split(/\r?\n/u)) {
|
||||
const line = rawLine.trim();
|
||||
if (!line || line.startsWith("#")) {
|
||||
candidates.push(".env.local");
|
||||
|
||||
if (nodeEnv) {
|
||||
candidates.push(`.env.${nodeEnv}.local`);
|
||||
}
|
||||
|
||||
return [...new Set(candidates.map((candidate) => resolve(workspaceRoot, candidate)))];
|
||||
}
|
||||
|
||||
export function loadWorkspaceEnv(options = {}) {
|
||||
const envPaths = resolveWorkspaceEnvPaths(options);
|
||||
const originalKeys = new Set(Object.keys(process.env));
|
||||
const loadedPaths = [];
|
||||
|
||||
for (const envPath of envPaths) {
|
||||
if (!existsSync(envPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const separatorIndex = line.indexOf("=");
|
||||
if (separatorIndex <= 0) {
|
||||
continue;
|
||||
const contents = readFileSync(envPath, "utf8");
|
||||
for (const rawLine of contents.split(/\r?\n/u)) {
|
||||
const line = rawLine.trim();
|
||||
if (!line || line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const separatorIndex = line.indexOf("=");
|
||||
if (separatorIndex <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const key = line.slice(0, separatorIndex).trim();
|
||||
const rawValue = line.slice(separatorIndex + 1).trim();
|
||||
const quoted =
|
||||
(rawValue.startsWith("\"") && rawValue.endsWith("\""))
|
||||
|| (rawValue.startsWith("'") && rawValue.endsWith("'"));
|
||||
const value = quoted ? rawValue.slice(1, -1) : rawValue;
|
||||
|
||||
if (!originalKeys.has(key)) {
|
||||
process.env[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
const key = line.slice(0, separatorIndex).trim();
|
||||
const rawValue = line.slice(separatorIndex + 1).trim();
|
||||
const quoted =
|
||||
(rawValue.startsWith("\"") && rawValue.endsWith("\""))
|
||||
|| (rawValue.startsWith("'") && rawValue.endsWith("'"));
|
||||
const value = quoted ? rawValue.slice(1, -1) : rawValue;
|
||||
|
||||
if (process.env[key] == null) {
|
||||
process.env[key] = value;
|
||||
}
|
||||
loadedPaths.push(envPath);
|
||||
}
|
||||
|
||||
return envPath;
|
||||
return loadedPaths;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user