版博士V2.0程序
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. 'use strict';
  2. const node_fs = require('node:fs');
  3. const pathe = require('pathe');
  4. const dotenv = require('dotenv');
  5. const promises = require('node:fs/promises');
  6. const node_os = require('node:os');
  7. const createJiti = require('jiti');
  8. const rc9 = require('rc9');
  9. const defu = require('defu');
  10. const pkgTypes = require('pkg-types');
  11. function _interopNamespaceDefault(e) {
  12. const n = Object.create(null);
  13. if (e) {
  14. for (const k in e) {
  15. n[k] = e[k];
  16. }
  17. }
  18. n.default = e;
  19. return n;
  20. }
  21. const dotenv__namespace = /*#__PURE__*/_interopNamespaceDefault(dotenv);
  22. const rc9__namespace = /*#__PURE__*/_interopNamespaceDefault(rc9);
  23. async function setupDotenv(options) {
  24. const targetEnvironment = options.env ?? process.env;
  25. const environment = await loadDotenv({
  26. cwd: options.cwd,
  27. fileName: options.fileName ?? ".env",
  28. env: targetEnvironment,
  29. interpolate: options.interpolate ?? true
  30. });
  31. for (const key in environment) {
  32. if (!key.startsWith("_") && targetEnvironment[key] === void 0) {
  33. targetEnvironment[key] = environment[key];
  34. }
  35. }
  36. return environment;
  37. }
  38. async function loadDotenv(options) {
  39. const environment = /* @__PURE__ */ Object.create(null);
  40. const dotenvFile = pathe.resolve(options.cwd, options.fileName);
  41. if (node_fs.existsSync(dotenvFile)) {
  42. const parsed = dotenv__namespace.parse(await node_fs.promises.readFile(dotenvFile, "utf8"));
  43. Object.assign(environment, parsed);
  44. }
  45. if (!options.env._applied) {
  46. Object.assign(environment, options.env);
  47. environment._applied = true;
  48. }
  49. if (options.interpolate) {
  50. interpolate(environment);
  51. }
  52. return environment;
  53. }
  54. function interpolate(target, source = {}, parse = (v) => v) {
  55. function getValue(key) {
  56. return source[key] !== void 0 ? source[key] : target[key];
  57. }
  58. function interpolate2(value, parents = []) {
  59. if (typeof value !== "string") {
  60. return value;
  61. }
  62. const matches = value.match(/(.?\${?(?:[\w:]+)?}?)/g) || [];
  63. return parse(
  64. // eslint-disable-next-line unicorn/no-array-reduce
  65. matches.reduce((newValue, match) => {
  66. const parts = /(.?)\${?([\w:]+)?}?/g.exec(match);
  67. const prefix = parts[1];
  68. let value2, replacePart;
  69. if (prefix === "\\") {
  70. replacePart = parts[0];
  71. value2 = replacePart.replace("\\$", "$");
  72. } else {
  73. const key = parts[2];
  74. replacePart = parts[0].slice(prefix.length);
  75. if (parents.includes(key)) {
  76. console.warn(
  77. `Please avoid recursive environment variables ( loop: ${parents.join(
  78. " > "
  79. )} > ${key} )`
  80. );
  81. return "";
  82. }
  83. value2 = getValue(key);
  84. value2 = interpolate2(value2, [...parents, key]);
  85. }
  86. return value2 !== void 0 ? newValue.replace(replacePart, value2) : newValue;
  87. }, value)
  88. );
  89. }
  90. for (const key in target) {
  91. target[key] = interpolate2(getValue(key));
  92. }
  93. }
  94. async function loadConfig(options) {
  95. options.cwd = pathe.resolve(process.cwd(), options.cwd || ".");
  96. options.name = options.name || "config";
  97. options.envName = options.envName ?? process.env.NODE_ENV;
  98. options.configFile = options.configFile ?? (options.name !== "config" ? `${options.name}.config` : "config");
  99. options.rcFile = options.rcFile ?? `.${options.name}rc`;
  100. if (options.extend !== false) {
  101. options.extend = {
  102. extendKey: "extends",
  103. ...options.extend
  104. };
  105. }
  106. options.jiti = options.jiti || createJiti(void 0, {
  107. interopDefault: true,
  108. requireCache: false,
  109. esmResolve: true,
  110. ...options.jitiOptions
  111. });
  112. const r = {
  113. config: {},
  114. cwd: options.cwd,
  115. configFile: pathe.resolve(options.cwd, options.configFile),
  116. layers: []
  117. };
  118. if (options.dotenv) {
  119. await setupDotenv({
  120. cwd: options.cwd,
  121. ...options.dotenv === true ? {} : options.dotenv
  122. });
  123. }
  124. const { config, configFile } = await resolveConfig(".", options);
  125. if (configFile) {
  126. r.configFile = configFile;
  127. }
  128. const configRC = {};
  129. if (options.rcFile) {
  130. if (options.globalRc) {
  131. Object.assign(
  132. configRC,
  133. rc9__namespace.readUser({ name: options.rcFile, dir: options.cwd })
  134. );
  135. const workspaceDir = await pkgTypes.findWorkspaceDir(options.cwd).catch(() => {
  136. });
  137. if (workspaceDir) {
  138. Object.assign(
  139. configRC,
  140. rc9__namespace.read({ name: options.rcFile, dir: workspaceDir })
  141. );
  142. }
  143. }
  144. Object.assign(
  145. configRC,
  146. rc9__namespace.read({ name: options.rcFile, dir: options.cwd })
  147. );
  148. }
  149. const pkgJson = {};
  150. if (options.packageJson) {
  151. const keys = (Array.isArray(options.packageJson) ? options.packageJson : [
  152. typeof options.packageJson === "string" ? options.packageJson : options.name
  153. ]).filter((t) => t && typeof t === "string");
  154. const pkgJsonFile = await pkgTypes.readPackageJSON(options.cwd).catch(() => {
  155. });
  156. const values = keys.map((key) => pkgJsonFile?.[key]);
  157. Object.assign(pkgJson, defu.defu({}, ...values));
  158. }
  159. r.config = defu.defu(
  160. options.overrides,
  161. config,
  162. configRC,
  163. pkgJson,
  164. options.defaultConfig
  165. );
  166. if (options.extend) {
  167. await extendConfig(r.config, options);
  168. r.layers = r.config._layers;
  169. delete r.config._layers;
  170. r.config = defu.defu(r.config, ...r.layers.map((e) => e.config));
  171. }
  172. const baseLayers = [
  173. options.overrides && {
  174. config: options.overrides,
  175. configFile: void 0,
  176. cwd: void 0
  177. },
  178. { config, configFile: options.configFile, cwd: options.cwd },
  179. options.rcFile && { config: configRC, configFile: options.rcFile },
  180. options.packageJson && { config: pkgJson, configFile: "package.json" }
  181. ].filter((l) => l && l.config);
  182. r.layers = [...baseLayers, ...r.layers];
  183. if (options.defaults) {
  184. r.config = defu.defu(r.config, options.defaults);
  185. }
  186. return r;
  187. }
  188. async function extendConfig(config, options) {
  189. config._layers = config._layers || [];
  190. if (!options.extend) {
  191. return;
  192. }
  193. let keys = options.extend.extendKey;
  194. if (typeof keys === "string") {
  195. keys = [keys];
  196. }
  197. const extendSources = [];
  198. for (const key of keys) {
  199. extendSources.push(
  200. ...(Array.isArray(config[key]) ? config[key] : [config[key]]).filter(
  201. Boolean
  202. )
  203. );
  204. delete config[key];
  205. }
  206. for (let extendSource of extendSources) {
  207. const originalExtendSource = extendSource;
  208. let sourceOptions = {};
  209. if (extendSource.source) {
  210. sourceOptions = extendSource.options || {};
  211. extendSource = extendSource.source;
  212. }
  213. if (Array.isArray(extendSource)) {
  214. sourceOptions = extendSource[1] || {};
  215. extendSource = extendSource[0];
  216. }
  217. if (typeof extendSource !== "string") {
  218. console.warn(
  219. `Cannot extend config from \`${JSON.stringify(
  220. originalExtendSource
  221. )}\` in ${options.cwd}`
  222. );
  223. continue;
  224. }
  225. const _config = await resolveConfig(extendSource, options, sourceOptions);
  226. if (!_config.config) {
  227. console.warn(
  228. `Cannot extend config from \`${extendSource}\` in ${options.cwd}`
  229. );
  230. continue;
  231. }
  232. await extendConfig(_config.config, { ...options, cwd: _config.cwd });
  233. config._layers.push(_config);
  234. if (_config.config._layers) {
  235. config._layers.push(..._config.config._layers);
  236. delete _config.config._layers;
  237. }
  238. }
  239. }
  240. const GIT_PREFIXES = ["github:", "gitlab:", "bitbucket:", "https://"];
  241. const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]*($|\/.*)/;
  242. async function resolveConfig(source, options, sourceOptions = {}) {
  243. if (options.resolve) {
  244. const res2 = await options.resolve(source, options);
  245. if (res2) {
  246. return res2;
  247. }
  248. }
  249. if (GIT_PREFIXES.some((prefix) => source.startsWith(prefix))) {
  250. const { downloadTemplate } = await import('giget');
  251. const url = new URL(source);
  252. const gitRepo = url.protocol + url.pathname.split("/").slice(0, 2).join("/");
  253. const name = gitRepo.replace(/[#/:@\\]/g, "_");
  254. const tmpDir = process.env.XDG_CACHE_HOME ? pathe.resolve(process.env.XDG_CACHE_HOME, "c12", name) : pathe.resolve(node_os.homedir(), ".cache/c12", name);
  255. if (node_fs.existsSync(tmpDir)) {
  256. await promises.rmdir(tmpDir, { recursive: true });
  257. }
  258. const cloned = await downloadTemplate(source, { dir: tmpDir });
  259. source = cloned.dir;
  260. }
  261. if (NPM_PACKAGE_RE.test(source)) {
  262. try {
  263. source = options.jiti.resolve(source, { paths: [options.cwd] });
  264. } catch {
  265. }
  266. }
  267. const isDir = !pathe.extname(source);
  268. const cwd = pathe.resolve(options.cwd, isDir ? source : pathe.dirname(source));
  269. if (isDir) {
  270. source = options.configFile;
  271. }
  272. const res = { config: void 0, cwd, source, sourceOptions };
  273. try {
  274. res.configFile = options.jiti.resolve(pathe.resolve(cwd, source), {
  275. paths: [cwd]
  276. });
  277. } catch {
  278. }
  279. if (!node_fs.existsSync(res.configFile)) {
  280. return res;
  281. }
  282. res.config = options.jiti(res.configFile);
  283. if (res.config instanceof Function) {
  284. res.config = await res.config();
  285. }
  286. if (options.envName) {
  287. const envConfig = {
  288. ...res.config["$" + options.envName],
  289. ...res.config.$env?.[options.envName]
  290. };
  291. if (Object.keys(envConfig).length > 0) {
  292. res.config = defu.defu(envConfig, res.config);
  293. }
  294. }
  295. res.meta = defu.defu(res.sourceOptions.meta, res.config.$meta);
  296. delete res.config.$meta;
  297. if (res.sourceOptions.overrides) {
  298. res.config = defu.defu(res.sourceOptions.overrides, res.config);
  299. }
  300. return res;
  301. }
  302. exports.loadConfig = loadConfig;
  303. exports.loadDotenv = loadDotenv;
  304. exports.setupDotenv = setupDotenv;