UNPKG

@anolilab/rc

Version:
145 lines (137 loc) 4.76 kB
import { createRequire as __cjs_createRequire } from "node:module"; const __cjs_require = __cjs_createRequire(import.meta.url); const __cjs_getProcess = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process; const __cjs_getBuiltinModule = (module) => { // Check if we're in Node.js and version supports getBuiltinModule if (typeof __cjs_getProcess !== "undefined" && __cjs_getProcess.versions && __cjs_getProcess.versions.node) { const [major, minor] = __cjs_getProcess.versions.node.split(".").map(Number); // Node.js 20.16.0+ and 22.3.0+ if (major > 22 || (major === 22 && minor >= 3) || (major === 20 && minor >= 16)) { return __cjs_getProcess.getBuiltinModule(module); } } // Fallback to createRequire return __cjs_require(module); }; const { homedir } = __cjs_getBuiltinModule("node:os"); const { cwd, env } = __cjs_getProcess; import { readFileSync, isAccessibleSync } from '@visulima/fs'; import { parseJson, stripJsonComments } from '@visulima/fs/utils'; import { join, dirname } from '@visulima/path'; import { parse } from 'ini'; import { merge } from 'ts-deepmerge'; const isJson = (value) => { try { JSON.parse(value); } catch { return false; } return 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 = (prefix, environment = 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; }; const getConfigFiles = (name, home, internalCwd, stopAt, environmentConfig, optionConfig) => { const configFiles = /* @__PURE__ */ new Set(); for (const file of [`/etc/${name}/config`, `/etc/${name}rc`]) { if (isAccessibleSync(file)) { configFiles.add(file); } } for (const file of [join(home, ".config", name, "config"), join(home, ".config", name), join(home, `.${name}`, "config"), join(home, `.${name}rc`)]) { if (isAccessibleSync(file)) { configFiles.add(file); } if (isAccessibleSync(`${file}.json`)) { configFiles.add(`${file}.json`); } } let start = internalCwd; let endOfLoop = false; const files = [join(`.${name}`, "config.json"), join(`.${name}`, "config"), join(`.${name}rc.json`), join(`.${name}rc`)]; const traversedFiles = []; do { for (const file of files) { const traverseFile = join(start, file); if (isAccessibleSync(traverseFile)) { traversedFiles.push(traverseFile); } } start = dirname(start); if (endOfLoop) { break; } endOfLoop = dirname(start) === start; } while (stopAt ? start === stopAt : true); for (const file of traversedFiles.toReversed()) { configFiles.add(file); } if (typeof environmentConfig === "string" && isAccessibleSync(environmentConfig)) { configFiles.add(environmentConfig); } if (optionConfig && isAccessibleSync(optionConfig)) { configFiles.add(optionConfig); } return [...configFiles]; }; const rc = (name, options = {}) => { options = { cwd: cwd(), home: homedir(), ...options }; const { config: _, ...environment } = getEnvironment(`${name}_`); const configFiles = getConfigFiles(name, options.home, options.cwd, options.stopAt, env[`${name}_config`], options.config); const configs = []; for (const file of configFiles) { const content = readFileSync(file, { buffer: false }); if (isJson(content)) { configs.push(parseJson(stripJsonComments(content))); } else { configs.push(parse(content)); } } if (environment) { configs.push(environment); } return { config: merge(options.defaults ?? {}, ...configs), files: configFiles }; }; export { rc };