@anolilab/rc
Version:
The runtime configuration loader.
129 lines (123 loc) • 4.52 kB
JavaScript
;
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
const node_os = require('node:os');
const node_process = require('node:process');
const fs = require('@visulima/fs');
const utils = require('@visulima/fs/utils');
const path = require('@visulima/path');
const ini = require('ini');
const tsDeepmerge = require('ts-deepmerge');
var __defProp$1 = Object.defineProperty;
var __name$1 = (target, value) => __defProp$1(target, "name", { value, configurable: true });
const isJson = /* @__PURE__ */ __name$1((value) => {
try {
JSON.parse(value);
} catch {
return false;
}
return true;
}, "isJson");
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
/**
* Modified copy of the env function from https://github.com/dominictarr/rc/blob/a97f6adcc37ee1cad06ab7dc9b0bd842bbc5c664/lib/utils.js#L42.
* @license https://github.com/dominictarr/rc/blob/master/LICENSE.APACHE2
* @license https://github.com/dominictarr/rc/blob/master/LICENSE.BSD
* @license https://github.com/dominictarr/rc/blob/master/LICENSE.MIT
* @param prefix
* @param environment
* @returns
*/
const getEnvironment = /* @__PURE__ */ __name((prefix, environment = node_process.env) => {
const returnValue = {};
const l = prefix.length;
for (const k in environment) {
if (k.toLowerCase().startsWith(prefix.toLowerCase())) {
const keypath = k.slice(Math.max(0, l)).split("__");
let emptyStringIndex;
while ((emptyStringIndex = keypath.indexOf("")) > -1) {
keypath.splice(emptyStringIndex, 1);
}
let cursor = returnValue;
keypath.forEach((subkey, index) => {
if (!subkey || typeof cursor !== "object") {
return;
}
if (index === keypath.length - 1) {
cursor[subkey] = environment[k];
}
if (cursor[subkey] === void 0) {
cursor[subkey] = {};
}
cursor = cursor[subkey];
});
}
}
return returnValue;
}, "getEnvironment");
const getConfigFiles = /* @__PURE__ */ __name((name, home, internalCwd, stopAt, environmentConfig, optionConfig) => {
const configFiles = /* @__PURE__ */ new Set();
for (const file of [`/etc/${name}/config`, `/etc/${name}rc`]) {
if (fs.isAccessibleSync(file)) {
configFiles.add(file);
}
}
for (const file of [path.join(home, ".config", name, "config"), path.join(home, ".config", name), path.join(home, `.${name}`, "config"), path.join(home, `.${name}rc`)]) {
if (fs.isAccessibleSync(file)) {
configFiles.add(file);
}
if (fs.isAccessibleSync(`${file}.json`)) {
configFiles.add(`${file}.json`);
}
}
let start = internalCwd;
let endOfLoop = false;
const files = [path.join(`.${name}`, "config.json"), path.join(`.${name}`, "config"), path.join(`.${name}rc.json`), path.join(`.${name}rc`)];
const traversedFiles = [];
do {
for (const file of files) {
const traverseFile = path.join(start, file);
if (fs.isAccessibleSync(traverseFile)) {
traversedFiles.push(traverseFile);
}
}
start = path.dirname(start);
if (endOfLoop) {
break;
}
endOfLoop = path.dirname(start) === start;
} while (stopAt ? start === stopAt : true);
for (const file of traversedFiles.toReversed()) {
configFiles.add(file);
}
if (typeof environmentConfig === "string" && fs.isAccessibleSync(environmentConfig)) {
configFiles.add(environmentConfig);
}
if (optionConfig && fs.isAccessibleSync(optionConfig)) {
configFiles.add(optionConfig);
}
return [...configFiles];
}, "getConfigFiles");
const rc = /* @__PURE__ */ __name((name, options = {}) => {
options = {
cwd: node_process.cwd(),
home: node_os.homedir(),
...options
};
const { config: _, ...environment } = getEnvironment(`${name}_`);
const configFiles = getConfigFiles(name, options.home, options.cwd, options.stopAt, node_process.env[`${name}_config`], options.config);
const configs = [];
for (const file of configFiles) {
const content = fs.readFileSync(file, { buffer: false });
if (isJson(content)) {
configs.push(utils.parseJson(utils.stripJsonComments(content)));
} else {
configs.push(ini.parse(content));
}
}
if (environment) {
configs.push(environment);
}
return { config: tsDeepmerge.merge(options.defaults ?? {}, ...configs), files: configFiles };
}, "rc");
exports.rc = rc;