'use strict'; const node_fs = require('node:fs'); const pathe = require('pathe'); const dotenv = require('dotenv'); const promises = require('node:fs/promises'); const node_os = require('node:os'); const createJiti = require('jiti'); const rc9 = require('rc9'); const defu = require('defu'); const pkgTypes = require('pkg-types'); function _interopNamespaceDefault(e) { const n = Object.create(null); if (e) { for (const k in e) { n[k] = e[k]; } } n.default = e; return n; } const dotenv__namespace = /*#__PURE__*/_interopNamespaceDefault(dotenv); const rc9__namespace = /*#__PURE__*/_interopNamespaceDefault(rc9); async function setupDotenv(options) { const targetEnvironment = options.env ?? process.env; const environment = await loadDotenv({ cwd: options.cwd, fileName: options.fileName ?? ".env", env: targetEnvironment, interpolate: options.interpolate ?? true }); for (const key in environment) { if (!key.startsWith("_") && targetEnvironment[key] === void 0) { targetEnvironment[key] = environment[key]; } } return environment; } async function loadDotenv(options) { const environment = /* @__PURE__ */ Object.create(null); const dotenvFile = pathe.resolve(options.cwd, options.fileName); if (node_fs.existsSync(dotenvFile)) { const parsed = dotenv__namespace.parse(await node_fs.promises.readFile(dotenvFile, "utf8")); Object.assign(environment, parsed); } if (!options.env._applied) { Object.assign(environment, options.env); environment._applied = true; } if (options.interpolate) { interpolate(environment); } return environment; } function interpolate(target, source = {}, parse = (v) => v) { function getValue(key) { return source[key] !== void 0 ? source[key] : target[key]; } function interpolate2(value, parents = []) { if (typeof value !== "string") { return value; } const matches = value.match(/(.?\${?(?:[\w:]+)?}?)/g) || []; return parse(matches.reduce((newValue, match) => { const parts = /(.?)\${?([\w:]+)?}?/g.exec(match); const prefix = parts[1]; let value2, replacePart; if (prefix === "\\") { replacePart = parts[0]; value2 = replacePart.replace("\\$", "$"); } else { const key = parts[2]; replacePart = parts[0].slice(prefix.length); if (parents.includes(key)) { console.warn(`Please avoid recursive environment variables ( loop: ${parents.join(" > ")} > ${key} )`); return ""; } value2 = getValue(key); value2 = interpolate2(value2, [...parents, key]); } return value2 !== void 0 ? newValue.replace(replacePart, value2) : newValue; }, value)); } for (const key in target) { target[key] = interpolate2(getValue(key)); } } async function loadConfig(options) { options.cwd = pathe.resolve(process.cwd(), options.cwd || "."); options.name = options.name || "config"; options.configFile = options.configFile ?? (options.name !== "config" ? `${options.name}.config` : "config"); options.rcFile = options.rcFile ?? `.${options.name}rc`; if (options.extend !== false) { options.extend = { extendKey: "extends", ...options.extend }; } options.jiti = options.jiti || createJiti(void 0, { interopDefault: true, requireCache: false, esmResolve: true, ...options.jitiOptions }); const r = { config: {}, cwd: options.cwd, configFile: pathe.resolve(options.cwd, options.configFile), layers: [] }; if (options.dotenv) { await setupDotenv({ cwd: options.cwd, ...options.dotenv === true ? {} : options.dotenv }); } const { config, configFile } = await resolveConfig(".", options); if (configFile) { r.configFile = configFile; } const configRC = {}; if (options.rcFile) { if (options.globalRc) { Object.assign(configRC, rc9__namespace.readUser({ name: options.rcFile, dir: options.cwd })); const workspaceDir = await pkgTypes.findWorkspaceDir(options.cwd).catch(() => { }); if (workspaceDir) { Object.assign(configRC, rc9__namespace.read({ name: options.rcFile, dir: workspaceDir })); } } Object.assign(configRC, rc9__namespace.read({ name: options.rcFile, dir: options.cwd })); } r.config = defu.defu( options.overrides, config, configRC, options.defaultConfig ); if (options.extend) { await extendConfig(r.config, options); r.layers = r.config._layers; delete r.config._layers; r.config = defu.defu( r.config, ...r.layers.map((e) => e.config) ); } const baseLayers = [ options.overrides && { config: options.overrides, configFile: void 0, cwd: void 0 }, { config, configFile: options.configFile, cwd: options.cwd }, options.rcFile && { config: configRC, configFile: options.rcFile } ].filter((l) => l && l.config); r.layers = [ ...baseLayers, ...r.layers ]; if (options.defaults) { r.config = defu.defu(r.config, options.defaults); } return r; } async function extendConfig(config, options) { config._layers = config._layers || []; if (!options.extend) { return; } let keys = options.extend.extendKey; if (typeof keys === "string") { keys = [keys]; } const extendSources = []; for (const key of keys) { extendSources.push(...(Array.isArray(config[key]) ? config[key] : [config[key]]).filter(Boolean)); delete config[key]; } for (const extendSource of extendSources) { if (typeof extendSource !== "string") { console.warn(`Cannot extend config from \`${JSON.stringify(extendSource)}\` (which should be a string) in ${options.cwd}`); continue; } const _config = await resolveConfig(extendSource, options); if (!_config.config) { console.warn(`Cannot extend config from \`${extendSource}\` in ${options.cwd}`); continue; } await extendConfig(_config.config, { ...options, cwd: _config.cwd }); config._layers.push(_config); if (_config.config._layers) { config._layers.push(..._config.config._layers); delete _config.config._layers; } } } const GIT_PREFIXES = ["github:", "gitlab:", "bitbucket:", "https://"]; const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]*$/; async function resolveConfig(source, options) { if (options.resolve) { const res2 = await options.resolve(source, options); if (res2) { return res2; } } if (GIT_PREFIXES.some((prefix) => source.startsWith(prefix))) { const { downloadTemplate } = await import('giget'); const url = new URL(source); const gitRepo = url.protocol + url.pathname.split("/").slice(0, 2).join("/"); const name = gitRepo.replace(/[#/:@\\]/g, "_"); const tmpDir = process.env.XDG_CACHE_HOME ? pathe.resolve(process.env.XDG_CACHE_HOME, "c12", name) : pathe.resolve(node_os.homedir(), ".cache/c12", name); if (node_fs.existsSync(tmpDir)) { await promises.rmdir(tmpDir, { recursive: true }); } const clonned = await downloadTemplate(source, { dir: tmpDir }); source = clonned.dir; } if (NPM_PACKAGE_RE.test(source)) { try { source = options.jiti.resolve(source, { paths: [options.cwd] }); } catch { } } const isDir = !pathe.extname(source); const cwd = pathe.resolve(options.cwd, isDir ? source : pathe.dirname(source)); if (isDir) { source = options.configFile; } const res = { config: void 0, cwd }; try { res.configFile = options.jiti.resolve(pathe.resolve(cwd, source), { paths: [cwd] }); } catch { } if (!node_fs.existsSync(res.configFile)) { return res; } res.config = options.jiti(res.configFile); if (typeof res.config === "function") { res.config = await res.config(); } return res; } exports.loadConfig = loadConfig; exports.loadDotenv = loadDotenv; exports.setupDotenv = setupDotenv;