UNPKG

froge

Version:

Jump-start your NodeJS/Bun/... services with dependency & lifecycle management and handy helper methods

178 lines 6.67 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const node_net_1 = __importDefault(require("node:net")); const node_fs_1 = __importDefault(require("node:fs")); const boolMapStrict = { 'true': true, 'false': false, }; const boolMap = { ...boolMapStrict, '1': true, 'y': true, 'yes': true, '0': false, 'n': false, 'no': false, }; class EnvWrapper { name; constructor(name) { this.name = name; } toString() { return this.string(); } // Aliases s = this.string.bind(this); n = this.number.bind(this); i = this.int.bind(this); b = this.bool.bind(this); string(defaultOrConfig) { const config = typeof defaultOrConfig === 'object' ? defaultOrConfig : {}; const defVal = typeof defaultOrConfig === 'string' ? defaultOrConfig : config.def; const nonEmpty = config.nonEmpty ?? true; const val = process.env[this.name] ?? defVal; if (typeof val === 'undefined') { throw new Error(`Env var "${this.name}" is not set`); } if (nonEmpty && val.length === 0) { if (defVal?.length) { return defVal; } throw new Error(`Env var "${this.name}" is empty`); } return val; } match(regExp, defaultValue) { const val = this.string(defaultValue); const matches = val.match(regExp); if (matches === null) { throw new Error(`Env var "${this.name}" doesn't match expected format ${regExp}`); } return matches[0]; } path(defaultOrConfig) { const config = typeof defaultOrConfig === 'object' ? defaultOrConfig : {}; const defVal = typeof defaultOrConfig === 'string' ? defaultOrConfig : config.def; const val = this.string(defVal); if (config.exist || typeof config.file !== 'undefined') { try { const stat = node_fs_1.default.statSync(val); if (typeof config.file !== 'undefined') { if (config.file && !stat.isFile) { throw new Error(`Env var "${this.name}" is not a file path`); } if (!config.file && !stat.isDirectory) { throw new Error(`Env var "${this.name}" is not a directory path`); } } } catch (e) { if (e.code === 'ENOENT') { if (config.exist) { throw new Error(`Env var "${this.name}" path doesn't exist`); } } else { throw new Error(`Failed to check file stat for path in env var "${this.name}", error: ${e.message}`); } } } return val; } url(defaultValue) { return new URL(this.string(defaultValue)); } urls(defaultValue) { return this.url(defaultValue).toString(); } ip(defaultValue) { const val = this.string(defaultValue); if (!node_net_1.default.isIP(val)) { throw new Error(`Env var "${this.name}" is not a valid IP address`); } return val; } ipv4(defaultValue) { const val = this.string(defaultValue); if (!node_net_1.default.isIPv4(val)) { throw new Error(`Env var "${this.name}" is not a valid IPv4 address`); } return val; } ipv6(defaultValue) { const val = this.string(defaultValue); if (!node_net_1.default.isIPv6(val)) { throw new Error(`Env var "${this.name}" is not a valid IPv6 address`); } return val; } number(defaultOrConfig) { const config = typeof defaultOrConfig === 'object' ? defaultOrConfig : {}; const defVal = typeof defaultOrConfig === 'number' ? defaultOrConfig : config.def; const val = process.env[this.name]; if (typeof val === 'undefined' && typeof defVal === 'undefined') { throw new Error(`Env var "${this.name}" is not set`); } const num = Number(val ?? defVal); if (isNaN(num)) { throw new Error(`Env var "${this.name}" is not a valid number`); } if (typeof config.min !== 'undefined' && num < config.min) { throw new Error(`Env var "${this.name}" value is too small (<${config.min})`); } if (typeof config.max !== 'undefined' && num > config.max) { throw new Error(`Env var "${this.name}" value is too large (>${config.max})`); } return num; } int(defaultOrConfig) { const config = typeof defaultOrConfig === 'object' ? defaultOrConfig : {}; const defVal = typeof defaultOrConfig === 'number' ? defaultOrConfig : config.def; const strict = config.strict ?? true; const val = this.number({ ...config, def: defVal }); const int = parseInt(String(val)); if (strict && int != val) { throw new Error(`Env var "${this.name}" is not a valid integer`); } return int; } port(defaultOrConfig) { const config = typeof defaultOrConfig === 'object' ? defaultOrConfig : {}; const defVal = typeof defaultOrConfig === 'number' ? defaultOrConfig : config.def; const val = this.int({ ...config, def: defVal }); if (val < 0 || val > 65535) { throw new Error(`Env var "${this.name}" is not a valid port number`); } return val; } bool(defaultOrConfig) { const config = typeof defaultOrConfig === 'object' ? defaultOrConfig : {}; const defVal = typeof defaultOrConfig === 'boolean' ? defaultOrConfig : config.def; const strict = config.strict ?? false; const val = process.env[this.name]; if (typeof val === 'undefined') { if (typeof defVal === 'undefined') { throw new Error(`Env var "${this.name}" is not set`); } return defVal; } const map = config.map ?? (strict ? boolMapStrict : boolMap); const parsed = map[val.toLowerCase()]; if (typeof parsed === 'undefined') { throw new Error(`Env var "${this.name}" is not a valid boolean`); } return parsed; } } const envHelper = new Proxy({}, { get(_, prop) { return new EnvWrapper(prop); } }); exports.default = envHelper; //# sourceMappingURL=env.js.map