froge
Version:
Jump-start your NodeJS/Bun/... services with dependency & lifecycle management and handy helper methods
178 lines • 6.67 kB
JavaScript
;
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