Load Secrets From Environment Not From Files
A config loader that keeps secret values out of committed files by resolving them from the environment and refusing to read them from disk.
Code
export class SecretConfigError extends Error {
constructor(message, details = {}) {
super(message);
this.name = "SecretConfigError";
this.missing = details.missing ?? [];
this.leaked = details.leaked ?? [];
}
}
export function loadConfig(filePayload, secretSpecs, env = process.env) {
if (!filePayload || typeof filePayload !== "object" || Array.isArray(filePayload)) {
throw new SecretConfigError("file payload must be an object");
}
const leaked = secretSpecs
.filter((spec) => Object.prototype.hasOwnProperty.call(filePayload, spec.key))
.map((spec) => spec.key);
if (leaked.length > 0) {
throw new SecretConfigError(
"secret keys must never appear in a committed file: " + leaked.join(", "),
{ leaked },
);
}
const config = { ...filePayload };
const missing = [];
for (const spec of secretSpecs) {
const value = env[spec.envVar];
if (value === undefined || value === "") {
missing.push(spec.envVar);
continue;
}
config[spec.key] = value;
}
if (missing.length > 0) {
throw new SecretConfigError("missing required secrets: " + missing.join(", "), { missing });
}
return config;
}Report a problem with this exampleOpens a pre-filled issue on GitHub.