loadEnvConfigWithSchema

JavaScript
// Reads environment variables through a schema with defaults and validation.
const parseEnv = {
  string: (value) => value,
  integer: (value) => {
    const number = Number(value);
    if (!Number.isInteger(number)) throw new Error('expected an integer');
    return number;
  },
  boolean: (value) => {
    if (!/^(true|false|1|0|yes|no)$/i.test(value)) throw new Error('expected a boolean');
    return /^(true|1|yes)$/i.test(value);
  },
};

export function loadEnvConfig(schema, env = process.env) {
  const config = {};
  const issues = [];
  for (const [key, spec] of Object.entries(schema)) {
    const name = spec.env ?? key;
    const raw = env[name];
    if (raw === undefined || raw === '') {
      if (Object.hasOwn(spec, 'default')) config[key] = spec.default;
      else if (spec.required) issues.push(`${name}: required but missing`);
      continue;
    }
    try {
      config[key] = (parseEnv[spec.type ?? 'string'] ?? parseEnv.string)(raw);
    } catch (error) {
      issues.push(`${name}: ${error.message}`);
    }
  }
  if (issues.length > 0) {
    throw new Error(`Invalid environment configuration:\n${issues.join('\n')}`);
  }
  return config;
}