@catbee/utils
Version:
A modular, production-grade utility toolkit for Node.js and TypeScript, designed for robust, scalable applications (including Express-based services). All utilities are tree-shakable and can be imported independently.
794 lines (789 loc) • 26.9 kB
JavaScript
/*
* The MIT License
*
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
;
var fs = require('fs');
var path = require('path');
var date = require('@catbee/utils/date');
var validation = require('@catbee/utils/validation');
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var Environment = /* @__PURE__ */ (function(Environment2) {
Environment2["PRODUCTION"] = "production";
Environment2["DEVELOPMENT"] = "development";
Environment2["STAGING"] = "staging";
Environment2["TESTING"] = "testing";
return Environment2;
})({});
var Env = class _Env {
static {
__name(this, "Env");
}
// Cache for parsed values to avoid repeated parsing of complex values
static cache = /* @__PURE__ */ new Map();
/**
* Checks if the current NODE_ENV is 'development'.
*
* @returns {boolean} `true` if NODE_ENV is 'development', else `false`.
*/
static isDev() {
return _Env.get("NODE_ENV", "development") === "development";
}
/**
* Checks if the current NODE_ENV is 'production'.
*
* @returns {boolean} `true` if NODE_ENV is 'production', else `false`.
*/
static isProd() {
return _Env.get("NODE_ENV", "development") === "production";
}
/**
* Checks if the current NODE_ENV is 'testing'.
*
* @returns {boolean} `true` if NODE_ENV is 'testing', else `false`.
*/
static isTest() {
return _Env.get("NODE_ENV", "development") === "testing";
}
/**
* Checks if the current NODE_ENV is 'staging'.
*
* @returns {boolean} `true` if NODE_ENV is 'staging', else `false`.
*/
static isStaging() {
return _Env.get("NODE_ENV", "development") === "staging";
}
/**
* Sets an environment variable (only affects runtime memory).
*
* @param {string} key - The environment variable key.
* @param {string} value - The value to set.
*/
static set(key, value) {
process.env[key] = value;
this.cache.delete(key);
for (const cacheKey of this.cache.keys()) {
if (cacheKey.includes(`:${key}`)) {
this.cache.delete(cacheKey);
}
}
}
/**
* Returns all environment variables as an object.
*
* @returns {object} The current `process.env` object.
*/
static getAll() {
return process.env;
}
/**
* Retrieves a string environment variable with a fallback default.
* Supports variable expansion with ${VAR_NAME} syntax.
*
* @param {string} key - The environment variable key.
* @param {string} [defaultValue] - Value to return if the key is missing.
* @returns {string} The env value or the fallback.
*
* @example
* // If DATABASE_URL is "postgres://localhost:5432/${DB_NAME}"
* // and DB_NAME is "myapp"
* const url = Env.get('DATABASE_URL', ''); // "postgres://localhost:5432/myapp"
*/
static get(key, defaultValue) {
let value = process.env[key] ?? defaultValue;
if (value?.includes("${")) {
value = value.replace(/\${([A-Za-z0-9_]+)}/g, (_, varName) => {
return process.env[varName] ?? "";
});
}
return value;
}
/**
* Retrieves a string environment variable and throws if it's missing.
*
* @param {string} key - The environment variable key.
* @returns {string} The environment variable's value.
* @throws {Error} If the variable is not defined.
*/
static getRequired(key) {
const value = process.env[key];
if (value === void 0) {
throw new Error(`Required environment variable '${key}' is missing`);
}
return _Env.get(key, "");
}
/**
* Retrieves a value using a default generating function if the key doesn't exist.
* Useful for expensive default calculations.
*
* @param {string} key - The environment variable key.
* @param {() => string} defaultFn - Function that generates default value.
* @returns {string} The environment value or generated default.
*
* @example
* const hostname = Env.getWithDefault('HOSTNAME', () => {
* // Only called if HOSTNAME is not set
* return require('os').hostname();
* });
*/
static getWithDefault(key, defaultFn) {
if (_Env.has(key)) {
return _Env.get(key, "");
}
return defaultFn();
}
/**
* Retrieves an environment variable as a number, or returns a default.
*
* @param {string} key - The environment variable key.
* @param {number} defaultValue - Fallback number if key is not present.
* @returns {number} Parsed numeric value or default.
* @throws {Error} If the value is not a valid number.
*/
static getNumber(key, defaultValue) {
if (this.cache.has(`number:${key}`)) {
return this.cache.get(`number:${key}`);
}
const value = process.env[key];
if (value === void 0) {
return defaultValue;
}
const numberValue = Number(value);
if (Number.isNaN(numberValue)) {
throw new Error(`Environment variable '${key}' is not a valid number, got: "${value}"`);
}
this.cache.set(`number:${key}`, numberValue);
return numberValue;
}
/**
* Retrieves a required environment variable as a number.
*
* @param {string} key - The environment variable key.
* @returns {number} Parsed number.
* @throws {Error} If the value is missing or not a number.
*/
static getNumberRequired(key) {
const value = process.env[key];
if (value === void 0) {
throw new Error(`Required environment variable '${key}' is missing`);
}
return _Env.getNumber(key, 0);
}
/**
* Retrieves an integer environment variable and validates it.
*
* @param {string} key - The environment variable key.
* @param {number} defaultValue - Fallback number if key is not present.
* @param {object} [options] - Validation options.
* @param {number} [options.min] - Minimum allowed value.
* @param {number} [options.max] - Maximum allowed value.
* @returns {number} The parsed integer.
*
* @example
* // Require PORT to be between 1000 and 9999
* const port = Env.getInteger('PORT', 3000, { min: 1000, max: 9999 });
*/
static getInteger(key, defaultValue, options = {}) {
const num = _Env.getNumber(key, defaultValue);
const intValue = Math.floor(num);
if (intValue !== num) {
throw new Error(`Environment variable '${key}' must be an integer, got: ${num}`);
}
if (options.min !== void 0 && intValue < options.min) {
throw new Error(`Environment variable '${key}' must be at least ${options.min}, got: ${intValue}`);
}
if (options.max !== void 0 && intValue > options.max) {
throw new Error(`Environment variable '${key}' must be at most ${options.max}, got: ${intValue}`);
}
return intValue;
}
/**
* Retrieves an environment variable as a boolean.
* Accepts `true`, `1`, `yes`, `on` as true; `false`, `0`, `no`, `off` as false.
*
* @param {string} key - The environment variable key.
* @param {boolean} [defaultValue=false] - Optional fallback value if key is missing.
* @returns {boolean} Parsed boolean.
* @throws {Error} If the value is not a recognized boolean string.
*
* @example
* // If DEBUG=yes
* const isDebug = Env.getBoolean('DEBUG', false); // true
*/
static getBoolean(key, defaultValue = false) {
if (this.cache.has(`bool:${key}`)) {
return this.cache.get(`bool:${key}`);
}
const value = process.env[key];
if (value === void 0) {
return defaultValue;
}
const lowerValue = value.toLowerCase();
if ([
"true",
"1",
"yes",
"on"
].includes(lowerValue)) {
this.cache.set(`bool:${key}`, true);
return true;
}
if ([
"false",
"0",
"no",
"off"
].includes(lowerValue)) {
this.cache.set(`bool:${key}`, false);
return false;
}
throw new Error(`Environment variable '${key}' is not a valid boolean, got: "${value}". Use true/false, yes/no, 1/0, or on/off.`);
}
/**
* Retrieves a required environment variable as a boolean.
*
* @param {string} key - The environment variable key.
* @returns {boolean} Parsed boolean value.
* @throws {Error} If missing or invalid.
*/
static getBooleanRequired(key) {
const value = process.env[key];
if (value === void 0) {
throw new Error(`Required environment variable '${key}' is missing`);
}
return _Env.getBoolean(key);
}
/**
* Parses a stringified JSON object from an environment variable.
*
* @typeParam T - The type to parse as (defaults to `object`).
* @param {string} key - The environment variable key.
* @param {T} defaultValue - Value to return if key is missing.
* @returns {T} Parsed object or default.
* @throws {Error} If the value is not valid JSON.
*
* @example
* // If CONFIG='{"debug":true,"api":{"url":"https://api.example.com"}}'
* const config = Env.getJSON('CONFIG', { debug: false });
* // { debug: true, api: { url: "https://api.example.com" }}
*/
static getJSON(key, defaultValue) {
if (this.cache.has(`json:${key}`)) {
return this.cache.get(`json:${key}`);
}
const v = process.env[key];
if (v === void 0) {
return defaultValue;
}
try {
const parsed = JSON.parse(v);
this.cache.set(`json:${key}`, parsed);
return parsed;
} catch (error) {
throw new Error(`Environment variable '${key}' is not valid JSON: ${error.message}`);
}
}
/**
* Parses a comma-separated string as an array.
*
* @typeParam T - The item type (optional, defaults to string).
* @param {string} key - The environment variable key.
* @param {T[]} [defaultValue=[]] - Array to return if value is empty or missing.
* @param {string} [splitter=','] - Delimiter to split on.
* @param {(item: string) => T} [transform] - Optional function to transform each item.
* @returns {T[]} An array of items.
*
* @example
* // If ALLOWED_IPS=127.0.0.1,192.168.1.1,10.0.0.1
* const ips = Env.getArray('ALLOWED_IPS');
* // ["127.0.0.1", "192.168.1.1", "10.0.0.1"]
*
* // With transformation function
* const ports = Env.getArray('PORTS', [], ',', (p) => parseInt(p, 10));
*/
static getArray(key, defaultValue = [], splitter = ",", transform) {
const cacheKey = `array:${key}:${splitter}:${transform ? "transformed" : "raw"}`;
if (this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
const value = process.env[key];
if (!value || value.trim() === "") {
return defaultValue;
}
const items = value.split(splitter).map((item) => item.trim()).filter((item) => item.length > 0);
if (transform) {
try {
const result2 = items.map(transform);
this.cache.set(cacheKey, result2);
return result2;
} catch (error) {
throw new Error(`Failed to transform items in '${key}': ${error.message}`);
}
}
const result = items;
this.cache.set(cacheKey, result);
return result;
}
/**
* Parses a comma-separated list of numbers.
*
* @param {string} key - The environment variable key.
* @param {number[]} [defaultValue=[]] - Default value if not present.
* @param {string} [splitter=','] - Delimiter to split on.
* @returns {number[]} Array of parsed numbers.
*
* @example
* // If ALLOWED_PORTS=80,443,3000,8080
* const ports = Env.getNumberArray('ALLOWED_PORTS');
* // [80, 443, 3000, 8080]
*/
static getNumberArray(key, defaultValue = [], splitter = ",") {
return _Env.getArray(key, defaultValue, splitter, (item) => {
const num = Number(item);
if (Number.isNaN(num)) {
throw new Error(`Value "${item}" in array '${key}' is not a valid number`);
}
return num;
});
}
/**
* Retrieves an enum-like environment variable value, validating against allowed values.
*
* @typeParam T - The allowed value type (string literal types).
* @param {string} key - The environment variable key.
* @param {T} [defaultValue] - Optional fallback value.
* @param {T[]} allowedValues - Array of accepted string values.
* @returns {T} The validated environment value.
* @throws {Error} If missing or invalid.
*
* @example
* // If LOG_LEVEL=debug
* const level = Env.getEnum('LOG_LEVEL', 'info', ['debug', 'info', 'warn', 'error'] as const);
* // 'debug' (typed as 'debug' | 'info' | 'warn' | 'error')
*/
static getEnum(key, defaultValue, allowedValues) {
const value = process.env[key];
if (!value) {
return defaultValue;
}
if (!allowedValues.includes(value)) {
throw new Error(`Environment variable '${key}' must be one of: ${allowedValues.join(", ")}. Received: "${value}"`);
}
return value;
}
/**
* Retrieves an enum-like numeric environment variable.
*
* @param {string} key - The environment variable key.
* @param {number} defaultValue - Default value if not present.
* @param {number[]} allowedValues - Array of accepted values.
* @returns {number} The validated value.
*
* @example
* // If NODE_VERSION=16
* const version = Env.getNumberEnum('NODE_VERSION', 16, [14, 16, 18]);
*/
static getNumberEnum(key, defaultValue, allowedValues) {
const value = _Env.getNumber(key, defaultValue);
if (!allowedValues.includes(value)) {
throw new Error(`Environment variable '${key}' must be one of: ${allowedValues.join(", ")}. Received: ${value}`);
}
return value;
}
/**
* Retrieves a URL environment variable and validates it.
*
* @param {string} key - The environment variable key.
* @param {string} [defaultValue] - Optional fallback value.
* @param {UrlOptions} [options] - Validation options.
* @returns {string} The validated URL.
* @throws {Error} If URL is invalid.
*
* @example
* // Validate API URL requires HTTPS
* const apiUrl = Env.getUrl('API_URL', 'https://api.example.com', {
* protocols: ['https'],
* requireTld: true,
* allowIp: false
* });
*/
static getUrl(key, defaultValue, options = {}) {
const cacheKey = `url:${key}:${JSON.stringify(options)}`;
if (this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
const value = _Env.get(key, defaultValue);
if (!value) {
throw new Error(`URL environment variable '${key}' is missing or empty`);
}
const url = this.parseUrl(value, key);
this.validateProtocol(url, key, options);
this.validateHostname(url, key, options);
this.cache.set(cacheKey, value);
return value;
}
static parseUrl(value, key) {
try {
return new URL(value);
} catch {
throw new Error(`Environment variable '${key}' is not a valid URL: "${value}"`);
}
}
static validateProtocol(url, key, options) {
if (options.protocols && options.protocols.length > 0) {
const protocol = url.protocol.replace(":", "");
if (!options.protocols.includes(protocol)) {
throw new Error(`Environment variable '${key}' must use one of the protocols: ${options.protocols.join(", ")}. Got: ${protocol}`);
}
}
}
static isIp(hostname) {
return /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/.test(hostname);
}
static validateHostname(url, key, options) {
const { hostname } = url;
const isIp = _Env.isIp(hostname);
const isLocalhost = hostname === "localhost";
if (isIp && options.allowIp === false) {
throw new Error(`Environment variable '${key}' cannot be an IP address: "${hostname}"`);
}
if (isLocalhost && options.allowLocalhost === false) {
throw new Error(`Environment variable '${key}' cannot be localhost`);
}
if (options.requireTld === true) {
if (isLocalhost && options.allowLocalhost !== false) ; else if (isIp && options.allowIp !== false) ; else if (!hostname.includes(".") || hostname.endsWith(".")) {
throw new Error(`Environment variable '${key}' must have a valid host with TLD: "${hostname}"`);
}
}
}
/**
* Retrieves an email environment variable and validates it.
*
* @param {string} key - The environment variable key.
* @param {string} [defaultValue] - Optional fallback value.
* @returns {string} The validated email address.
* @throws {Error} If email is invalid.
*
* @example
* const supportEmail = Env.getEmail('SUPPORT_EMAIL', 'support@example.com');
*/
static getEmail(key, defaultValue) {
if (this.cache.has(`email:${key}`)) {
return this.cache.get(`email:${key}`);
}
const value = _Env.get(key, defaultValue);
if (!value) {
if (defaultValue === void 0) {
throw new Error(`Email environment variable '${key}' is missing`);
}
return defaultValue;
}
if (!validation.isEmail(value)) {
throw new Error(`Environment variable '${key}' is not a valid email address: "${value}"`);
}
this.cache.set(`email:${key}`, value);
return value;
}
/**
* Retrieves a path environment variable and validates it exists.
*
* @param {string} key - The environment variable key.
* @param {string} [defaultValue] - Optional fallback value.
* @param {PathOptions} [options] - Validation options.
* @returns {string} The validated path.
* @throws {Error} If path is invalid.
*
* @example
* // Require that the path exists and is a .json file
* const configPath = Env.getPath('CONFIG_PATH', './config.json', {
* mustExist: true,
* allowedExtensions: ['.json', '.yaml']
* });
*/
static getPath(key, defaultValue, options = {}) {
const cacheKey = `path:${key}:${JSON.stringify(options)}`;
if (this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
const value = _Env.get(key, defaultValue);
if (!value) {
if (defaultValue === void 0) {
throw new Error(`Path environment variable '${key}' is missing`);
}
return defaultValue;
}
const path$1 = options.makeAbsolute !== false && !path.isAbsolute(value) ? path.resolve(process.cwd(), value) : value;
if (options.mustExist && !fs.existsSync(path$1)) {
throw new Error(`Path in environment variable '${key}' does not exist: "${path$1}"`);
}
if (options.allowedExtensions && options.allowedExtensions.length > 0) {
const hasValidExtension = options.allowedExtensions.some((ext) => path$1.toLowerCase().endsWith(ext.toLowerCase()));
if (!hasValidExtension) {
throw new Error(`Path in environment variable '${key}' must have one of these extensions: ${options.allowedExtensions.join(", ")}. Got: "${path$1}"`);
}
}
this.cache.set(cacheKey, path$1);
return path$1;
}
/**
* Retrieves a port environment variable and validates it.
*
* @param {string} key - The environment variable key.
* @param {number} [defaultValue] - Optional fallback value.
* @returns {number} The validated port number.
* @throws {Error} If port is invalid.
*
* @example
* const serverPort = Env.getPort('PORT', 3000);
*/
static getPort(key, defaultValue) {
try {
return _Env.getInteger(key, defaultValue, {
min: 0,
max: 65535
});
} catch (error) {
if (error.message.includes("must be at most 65535")) {
throw new Error(`Environment variable '${key}' must be a valid port number (0-65535)`);
}
throw error;
}
}
/**
* Retrieves an ISO date string and converts it to a Date object.
*
* @param {string} key - The environment variable key.
* @param {string|Date} [defaultValue] - Optional fallback value.
* @returns {Date} The parsed Date object.
*
* @example
* // If EXPIRY_DATE=2023-12-31T23:59:59Z
* const expiryDate = Env.getDate('EXPIRY_DATE', new Date());
*/
static getDate(key, defaultValue = /* @__PURE__ */ new Date()) {
const value = _Env.get(key, defaultValue instanceof Date ? defaultValue.toISOString() : defaultValue);
if (!value) {
return defaultValue instanceof Date ? defaultValue : /* @__PURE__ */ new Date();
}
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
throw new Error(`Environment variable '${key}' is not a valid date: "${value}"`);
}
return date;
}
/**
* Retrieves a duration string and converts it to milliseconds.
* Supports formats like "1d", "2h", "30m", "45s", "100ms" or combinations like "1h30m".
*
* @param {string} key - The environment variable key.
* @param {string|number} [defaultValue='0'] - Optional fallback value.
* @returns {number} The duration in milliseconds.
* @throws {Error} If duration format is invalid.
*
* @example
* // If CACHE_TTL=2h30m
* const cacheTtlMs = Env.getDuration('CACHE_TTL', '1h');
* // 9000000 (2.5 hours in milliseconds)
*/
static getDuration(key, defaultValue = "0") {
const cacheKey = `duration:${key}`;
if (this.cache.has(cacheKey)) {
return this.cache.get(cacheKey);
}
const raw = _Env.get(key, String(defaultValue));
if (!raw) return 0;
const ms = date.parseDuration(raw);
this.cache.set(cacheKey, ms);
return ms;
}
/**
* Gets all environment variables with sensitive values masked for safe logging.
*
* @param {string[]} [sensitiveKeys=['password', 'secret', 'key', 'token', 'auth']] - Keys to mask.
* @returns {Record<string, string>} Environment variables with sensitive values masked.
*
* @example
* console.log(Env.getSafeEnv(['password', 'secret', 'key']));
* // { DATABASE_URL: "postgres://...", API_KEY: "******", ... }
*/
static getSafeEnv(sensitiveKeys = [
"password",
"secret",
"key",
"token",
"auth"
]) {
const safeEnv = {};
for (const [key, value] of Object.entries(process.env)) {
if (!value) continue;
const isSensitive = sensitiveKeys.some((sensitiveKey) => key.toLowerCase().includes(sensitiveKey.toLowerCase()));
safeEnv[key] = isSensitive ? "******" : value;
}
return safeEnv;
}
/**
* Loads environment variables from a .env file.
* Does not override existing variables.
*
* @param {string} [path='.env'] - Path to the .env file.
* @returns {Record<string, string>} Loaded environment variables.
*
* @example
* // Load variables from .env.development
* Env.loadFromFile('.env.development');
*/
static loadFromFile(path = ".env") {
if (!fs.existsSync(path)) {
throw new Error(`Environment file not found: "${path}"`);
}
const content = fs.readFileSync(path, "utf8");
const variables = this.parseEnvContent(content);
for (const [k, v] of Object.entries(variables)) {
if (!process.env[k]) {
process.env[k] = v;
}
}
return variables;
}
static parseEnvContent(content) {
const variables = {};
const lines = content.split(/\r?\n/);
let i = 0;
while (i < lines.length) {
let line = lines[i].trim();
if (this.isCommentOrEmpty(line)) {
i++;
continue;
}
const match = this.extractKeyValue(line);
if (!match) {
i++;
continue;
}
const key = match[1].trim();
let value = match[2].trim();
if (!this.isQuoted(value)) {
value = this.stripInlineComment(value);
}
if (this.isQuoted(value) && value.length > 1) {
const result = this.parseQuotedValue(lines, i, value);
value = result.value;
i = result.nextIndex;
} else {
const result = this.parseUnquotedMultiline(lines, i, value);
value = result.value;
i = result.nextIndex;
}
if (!process.env[key]) {
variables[key] = value;
}
i++;
}
return variables;
}
static isCommentOrEmpty(line) {
return !line || line.startsWith("#");
}
static extractKeyValue(line) {
return line.match(/^([^=]+)=(.*)$/);
}
static isQuoted(value) {
return /^['"]/.test(value);
}
static stripInlineComment(value) {
const hashIndex = value.indexOf(" #");
if (hashIndex !== -1) {
return value.slice(0, hashIndex).trim();
}
return value;
}
static parseQuotedValue(lines, currentIndex, value) {
const quote = value[0];
if (!value.endsWith(quote) || value.length === 1) {
let multilineValue = value.slice(1);
let i = currentIndex + 1;
while (i < lines.length) {
const nextLine = lines[i];
if (nextLine.endsWith(quote)) {
multilineValue += "\n" + nextLine.slice(0, -1);
break;
} else {
multilineValue += "\n" + nextLine;
}
i++;
}
return {
value: multilineValue,
nextIndex: i
};
}
return {
value: value.slice(1, -1),
nextIndex: currentIndex
};
}
static parseUnquotedMultiline(lines, currentIndex, value) {
let i = currentIndex + 1;
while (i < lines.length && !lines[i].includes("=") && lines[i].trim() !== "") {
value += "\n" + lines[i];
i++;
}
return {
value,
nextIndex: i - 1
};
}
/**
* Checks whether the specified environment variable exists.
*
* @param {string} key - The environment variable key.
* @returns {boolean} `true` if the variable is defined, otherwise `false`.
*/
static has(key) {
return process.env[key] !== void 0;
}
/**
* Deletes the given environment variable (useful in tests).
*
* @param {string} key - The environment variable key to delete.
* @returns {void}
*/
static delete(key) {
delete process.env[key];
this.cache.delete(key);
for (const cacheKey of this.cache.keys()) {
if (cacheKey.includes(`:${key}`)) {
this.cache.delete(cacheKey);
}
}
}
/**
* Clears the internal cache of parsed environment values.
* Useful for testing or when environment variables might change.
*/
static clearCache() {
this.cache.clear();
}
};
exports.Env = Env;
exports.Environment = Environment;