atikin-env
Version:
Ultra-fast, zero-dependency .env loader with type safety for Node/TS. Created by: Atikin Verse.
56 lines (55 loc) • 1.95 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadEnv = loadEnv;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
function parseValue(value, type) {
switch (type) {
case 'number':
const n = Number(value);
if (isNaN(n))
throw new Error(`Invalid number: ${value}`);
return n;
case 'boolean':
if (value === 'true')
return true;
if (value === 'false')
return false;
throw new Error(`Invalid boolean: ${value}`);
case 'string':
default:
return value;
}
}
function loadEnv(schema, options = {}) {
const envPath = options.path || path_1.default.resolve(process.cwd(), '.env');
const allowPartial = options.allowPartial ?? false;
const defaults = options.defaults || {};
if (!fs_1.default.existsSync(envPath))
throw new Error(`.env file not found at ${envPath}`);
const raw = fs_1.default.readFileSync(envPath, 'utf8');
const lines = raw.split('\n');
const envRaw = {};
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#'))
continue;
const [key, ...rest] = trimmed.split('=');
envRaw[key] = rest.join('=').trim();
}
const finalEnv = {};
for (const key in schema) {
const expectedType = schema[key];
const rawValue = envRaw[key] ?? defaults[key];
if (rawValue === undefined) {
if (!allowPartial)
throw new Error(`Missing required env variable: ${key}`);
continue;
}
finalEnv[key] = parseValue(rawValue, expectedType);
}
return finalEnv;
}