dotenv-extended
Version:
A module for loading .env files and optionally loading defaults and a schema for validating all values are present.
241 lines (233 loc) • 8.08 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
// src/index.js
var import_dotenv2 = __toESM(require("dotenv"));
// src/utils/parse-primitive.js
var parsePrimitive = (value) => {
if (value === null || typeof value === "undefined") {
return value;
}
if (typeof value === "number" || typeof value === "boolean") {
return value;
}
if (typeof value !== "string") {
return value;
}
let normalized = value.trim().replace(/(^"|"$)|(^'|'$)/g, "").toLowerCase();
if (normalized === "" || normalized === "undefined") {
return void 0;
}
if (normalized === "null") {
return null;
}
if (normalized === "nan") {
return NaN;
}
if (normalized === "true" || normalized === "1") {
return true;
}
if (normalized === "false" || normalized === "0") {
return false;
}
const numeric = Number(normalized);
if (!Number.isNaN(numeric)) {
return numeric;
}
return value;
};
var parse_primitive_default = parsePrimitive;
// src/utils/normalize-option-key.js
var normalizedWithSeparators = (key) => key.toLowerCase().replace(/[_-\s]+([a-z0-9])/g, (_, next) => next.toUpperCase());
var normalizeOptionKey = (key) => {
const trimmed = key.trim();
if (!trimmed) {
return "";
}
if (/[_-\s]/.test(trimmed)) {
return normalizedWithSeparators(trimmed);
}
if (trimmed === trimmed.toUpperCase()) {
return trimmed.toLowerCase();
}
return trimmed.charAt(0).toLowerCase() + trimmed.slice(1);
};
var normalize_option_key_default = normalizeOptionKey;
// src/utils/config-from-env.js
var getConfigFromEnv = (env) => {
let config2 = {};
Object.keys(env).forEach((key) => {
const curr = key.split("DOTENV_CONFIG_");
if (curr.length === 2 && curr[0] === "" && curr[1].length) {
config2[normalize_option_key_default(curr[1])] = parse_primitive_default(env[key]);
}
});
return config2;
};
var config_from_env_default = getConfigFromEnv;
// src/utils/load-environment-file.js
var import_fs = __toESM(require("fs"));
var import_dotenv = __toESM(require("dotenv"));
var loadEnvironmentFile = (path, encoding, silent, errorOnMissingFiles = false) => {
try {
const data = import_fs.default.readFileSync(path, encoding);
return import_dotenv.default.parse(data);
} catch (err) {
if (errorOnMissingFiles && err && err.code === "ENOENT") {
throw new Error(`MISSING CONFIG FILE: ${path}`);
}
if (!silent) {
console.error(err.message);
}
return {};
}
};
var load_environment_file_default = loadEnvironmentFile;
// src/index.js
var normalizeLayeredFiles = (value) => {
if (!value) {
return [];
}
if (Array.isArray(value)) {
return value.filter(Boolean);
}
if (typeof value === "string") {
return value.split(",").map((item) => item.trim()).filter(Boolean);
}
return [];
};
var loadLayeredFiles = (files, options2) => normalizeLayeredFiles(files).reduce((acc, filePath) => {
const fileData = load_environment_file_default(
filePath,
options2.encoding,
options2.silent,
options2.errorOnMissingFiles
);
return Object.assign(acc, fileData);
}, {});
var parse = import_dotenv2.default.parse.bind(import_dotenv2.default);
var config = (options2) => {
let defaultsData, environmentData, defaultOptions = {
encoding: "utf8",
silent: true,
path: ".env",
defaults: ".env.defaults",
schema: ".env.schema",
schemaExtends: void 0,
errorOnMissing: false,
errorOnExtra: false,
errorOnRegex: false,
errorOnMissingFiles: false,
returnSchemaOnly: false,
includeProcessEnv: false,
assignToProcessEnv: true,
overrideProcessEnv: false
}, processEnvOptions = config_from_env_default(process.env);
options2 = Object.assign({}, defaultOptions, processEnvOptions, options2);
defaultsData = loadLayeredFiles(options2.defaults, options2);
environmentData = loadLayeredFiles(options2.path, options2);
let configData = Object.assign({}, defaultsData, environmentData);
const config2 = options2.includeProcessEnv ? Object.assign({}, configData, process.env) : configData;
const configOnlyKeys = Object.keys(configData);
const configKeys = Object.keys(config2);
let schemaKeys = null;
if (options2.errorOnMissing || options2.errorOnExtra || options2.errorOnRegex || options2.returnSchemaOnly) {
const baseSchema = load_environment_file_default(
options2.schema,
options2.encoding,
options2.silent,
options2.errorOnMissingFiles
);
const schema = normalizeLayeredFiles(options2.schemaExtends).reduce(
(acc, schemaPath) => {
const schemaLayer = load_environment_file_default(
schemaPath,
options2.encoding,
options2.silent,
options2.errorOnMissingFiles
);
return Object.assign(acc, schemaLayer);
},
Object.assign({}, baseSchema)
);
schemaKeys = Object.keys(schema);
let missingKeys = schemaKeys.filter(function(key) {
return configKeys.indexOf(key) < 0;
});
let extraKeys = configOnlyKeys.filter(function(key) {
return schemaKeys.indexOf(key) < 0;
});
if (options2.errorOnMissing && missingKeys.length) {
throw new Error("MISSING CONFIG VALUES: " + missingKeys.join(", "));
}
if (options2.errorOnExtra && extraKeys.length) {
throw new Error("EXTRA CONFIG VALUES: " + extraKeys.join(", "));
}
if (options2.errorOnRegex) {
const regexMismatchKeys = schemaKeys.filter(function(key) {
if (schema[key]) {
return !new RegExp(schema[key]).test(
typeof config2[key] === "string" ? config2[key] : ""
);
}
});
if (regexMismatchKeys.length) {
throw new Error("REGEX MISMATCH: " + regexMismatchKeys.join(", "));
}
}
}
if (options2.includeProcessEnv && !options2.overrideProcessEnv) {
for (let i = 0; i < configKeys.length; i++) {
if (typeof process.env[configKeys[i]] !== "undefined")
configData[configKeys[i]] = process.env[configKeys[i]];
}
}
if (options2.returnSchemaOnly && schemaKeys) {
configData = schemaKeys.reduce((acc, key) => {
if (typeof config2[key] !== "undefined") {
acc[key] = config2[key];
}
return acc;
}, {});
}
if (options2.assignToProcessEnv) {
if (options2.overrideProcessEnv) {
Object.assign(process.env, configData);
} else {
const tmp = Object.assign({}, configData, process.env);
Object.assign(process.env, tmp);
}
}
return configData;
};
// src/config.js
var reduceArguments = (prev, curr) => {
const matches = curr.match(/^dotenv_config_(.+)=(.+)/);
return hasMatches(matches) ? expandKeyValFromMatches(matches, prev) : prev;
};
var expandKeyValFromMatches = ([, key, value], prev) => ({
...prev,
[key]: value
});
var hasMatches = (matches) => matches && matches.length >= 3;
var options = process.argv.reduce(reduceArguments, {});
config(options);