c12 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -3,7 +3,8 @@
3
3
  const node_fs = require('node:fs');
4
4
  const pathe = require('pathe');
5
5
  const dotenv = require('dotenv');
6
- const os = require('node:os');
6
+ const promises = require('node:fs/promises');
7
+ const node_os = require('node:os');
7
8
  const createJiti = require('jiti');
8
9
  const rc9 = require('rc9');
9
10
  const defu = require('defu');
@@ -63,25 +64,32 @@ function interpolate(target, source = {}, parse = (v) => v) {
63
64
  return value;
64
65
  }
65
66
  const matches = value.match(/(.?\${?(?:[\w:]+)?}?)/g) || [];
66
- return parse(matches.reduce((newValue, match) => {
67
- const parts = /(.?)\${?([\w:]+)?}?/g.exec(match);
68
- const prefix = parts[1];
69
- let value2, replacePart;
70
- if (prefix === "\\") {
71
- replacePart = parts[0];
72
- value2 = replacePart.replace("\\$", "$");
73
- } else {
74
- const key = parts[2];
75
- replacePart = parts[0].slice(prefix.length);
76
- if (parents.includes(key)) {
77
- console.warn(`Please avoid recursive environment variables ( loop: ${parents.join(" > ")} > ${key} )`);
78
- return "";
67
+ return parse(
68
+ // eslint-disable-next-line unicorn/no-array-reduce
69
+ matches.reduce((newValue, match) => {
70
+ const parts = /(.?)\${?([\w:]+)?}?/g.exec(match);
71
+ const prefix = parts[1];
72
+ let value2, replacePart;
73
+ if (prefix === "\\") {
74
+ replacePart = parts[0];
75
+ value2 = replacePart.replace("\\$", "$");
76
+ } else {
77
+ const key = parts[2];
78
+ replacePart = parts[0].slice(prefix.length);
79
+ if (parents.includes(key)) {
80
+ console.warn(
81
+ `Please avoid recursive environment variables ( loop: ${parents.join(
82
+ " > "
83
+ )} > ${key} )`
84
+ );
85
+ return "";
86
+ }
87
+ value2 = getValue(key);
88
+ value2 = interpolate2(value2, [...parents, key]);
79
89
  }
80
- value2 = getValue(key);
81
- value2 = interpolate2(value2, [...parents, key]);
82
- }
83
- return value2 !== void 0 ? newValue.replace(replacePart, value2) : newValue;
84
- }, value));
90
+ return value2 !== void 0 ? newValue.replace(replacePart, value2) : newValue;
91
+ }, value)
92
+ );
85
93
  }
86
94
  for (const key in target) {
87
95
  target[key] = interpolate2(getValue(key));
@@ -124,14 +132,23 @@ async function loadConfig(options) {
124
132
  const configRC = {};
125
133
  if (options.rcFile) {
126
134
  if (options.globalRc) {
127
- Object.assign(configRC, rc9__namespace.readUser({ name: options.rcFile, dir: options.cwd }));
135
+ Object.assign(
136
+ configRC,
137
+ rc9__namespace.readUser({ name: options.rcFile, dir: options.cwd })
138
+ );
128
139
  const workspaceDir = await pkgTypes.findWorkspaceDir(options.cwd).catch(() => {
129
140
  });
130
141
  if (workspaceDir) {
131
- Object.assign(configRC, rc9__namespace.read({ name: options.rcFile, dir: workspaceDir }));
142
+ Object.assign(
143
+ configRC,
144
+ rc9__namespace.read({ name: options.rcFile, dir: workspaceDir })
145
+ );
132
146
  }
133
147
  }
134
- Object.assign(configRC, rc9__namespace.read({ name: options.rcFile, dir: options.cwd }));
148
+ Object.assign(
149
+ configRC,
150
+ rc9__namespace.read({ name: options.rcFile, dir: options.cwd })
151
+ );
135
152
  }
136
153
  r.config = defu.defu(
137
154
  options.overrides,
@@ -143,20 +160,18 @@ async function loadConfig(options) {
143
160
  await extendConfig(r.config, options);
144
161
  r.layers = r.config._layers;
145
162
  delete r.config._layers;
146
- r.config = defu.defu(
147
- r.config,
148
- ...r.layers.map((e) => e.config)
149
- );
163
+ r.config = defu.defu(r.config, ...r.layers.map((e) => e.config));
150
164
  }
151
165
  const baseLayers = [
152
- options.overrides && { config: options.overrides, configFile: void 0, cwd: void 0 },
166
+ options.overrides && {
167
+ config: options.overrides,
168
+ configFile: void 0,
169
+ cwd: void 0
170
+ },
153
171
  { config, configFile: options.configFile, cwd: options.cwd },
154
172
  options.rcFile && { config: configRC, configFile: options.rcFile }
155
173
  ].filter((l) => l && l.config);
156
- r.layers = [
157
- ...baseLayers,
158
- ...r.layers
159
- ];
174
+ r.layers = [...baseLayers, ...r.layers];
160
175
  if (options.defaults) {
161
176
  r.config = defu.defu(r.config, options.defaults);
162
177
  }
@@ -173,17 +188,27 @@ async function extendConfig(config, options) {
173
188
  }
174
189
  const extendSources = [];
175
190
  for (const key of keys) {
176
- extendSources.push(...(Array.isArray(config[key]) ? config[key] : [config[key]]).filter(Boolean));
191
+ extendSources.push(
192
+ ...(Array.isArray(config[key]) ? config[key] : [config[key]]).filter(
193
+ Boolean
194
+ )
195
+ );
177
196
  delete config[key];
178
197
  }
179
198
  for (const extendSource of extendSources) {
180
199
  if (typeof extendSource !== "string") {
181
- console.warn(`Cannot extend config from \`${JSON.stringify(extendSource)}\` (which should be a string) in ${options.cwd}`);
200
+ console.warn(
201
+ `Cannot extend config from \`${JSON.stringify(
202
+ extendSource
203
+ )}\` (which should be a string) in ${options.cwd}`
204
+ );
182
205
  continue;
183
206
  }
184
207
  const _config = await resolveConfig(extendSource, options);
185
208
  if (!_config.config) {
186
- console.warn(`Cannot extend config from \`${extendSource}\` in ${options.cwd}`);
209
+ console.warn(
210
+ `Cannot extend config from \`${extendSource}\` in ${options.cwd}`
211
+ );
187
212
  continue;
188
213
  }
189
214
  await extendConfig(_config.config, { ...options, cwd: _config.cwd });
@@ -204,16 +229,16 @@ async function resolveConfig(source, options) {
204
229
  }
205
230
  }
206
231
  if (GIT_PREFIXES.some((prefix) => source.startsWith(prefix))) {
232
+ const { downloadTemplate } = await import('giget');
207
233
  const url = new URL(source);
208
- const subPath = url.pathname.split("/").slice(2).join("/");
209
234
  const gitRepo = url.protocol + url.pathname.split("/").slice(0, 2).join("/");
210
- const tmpdir = pathe.resolve(os.tmpdir(), "c12/", gitRepo.replace(/[#/:@\\]/g, "_"));
211
- await node_fs.promises.rm(tmpdir, { recursive: true }).catch(() => {
212
- });
213
- const gittar = await import('gittar').then((r) => r.default || r);
214
- const tarFile = await gittar.fetch(gitRepo);
215
- await gittar.extract(tarFile, tmpdir);
216
- source = pathe.resolve(tmpdir, subPath);
235
+ const name = gitRepo.replace(/[#/:@\\]/g, "_");
236
+ const tmpDir = process.env.XDG_CACHE_HOME ? pathe.resolve(process.env.XDG_CACHE_HOME, "c12", name) : pathe.resolve(node_os.homedir(), ".cache/c12", name);
237
+ if (node_fs.existsSync(tmpDir)) {
238
+ await promises.rmdir(tmpDir, { recursive: true });
239
+ }
240
+ const clonned = await downloadTemplate(source, { dir: tmpDir });
241
+ source = clonned.dir;
217
242
  }
218
243
  if (NPM_PACKAGE_RE.test(source)) {
219
244
  try {
@@ -228,7 +253,9 @@ async function resolveConfig(source, options) {
228
253
  }
229
254
  const res = { config: void 0, cwd };
230
255
  try {
231
- res.configFile = options.jiti.resolve(pathe.resolve(cwd, source), { paths: [cwd] });
256
+ res.configFile = options.jiti.resolve(pathe.resolve(cwd, source), {
257
+ paths: [cwd]
258
+ });
232
259
  } catch {
233
260
  }
234
261
  if (!node_fs.existsSync(res.configFile)) {
package/dist/index.d.ts CHANGED
@@ -4,12 +4,12 @@ import { JITIOptions } from 'jiti/dist/types';
4
4
  interface DotenvOptions {
5
5
  /**
6
6
  * The project root directory (either absolute or relative to the current working directory).
7
- */
7
+ */
8
8
  cwd: string;
9
9
  /**
10
10
  * What file to look in for environment variables (either absolute or relative
11
11
  * to the current working directory). For example, `.env`.
12
- */
12
+ */
13
13
  fileName?: string;
14
14
  /**
15
15
  * Whether to interpolate variables within .env.
@@ -24,10 +24,10 @@ interface DotenvOptions {
24
24
  interpolate?: boolean;
25
25
  /**
26
26
  * An object describing environment variables (key, value pairs).
27
- */
27
+ */
28
28
  env?: NodeJS.ProcessEnv;
29
29
  }
30
- declare type Env = typeof process.env;
30
+ type Env = typeof process.env;
31
31
  /**
32
32
  * Load and interpolate environment variables into `process.env`.
33
33
  * If you need more control (or access to the values), consider using `loadDotenv` instead
package/dist/index.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import { existsSync, promises } from 'node:fs';
2
2
  import { resolve, extname, dirname } from 'pathe';
3
3
  import * as dotenv from 'dotenv';
4
- import os from 'node:os';
4
+ import { rmdir } from 'node:fs/promises';
5
+ import { homedir } from 'node:os';
5
6
  import createJiti from 'jiti';
6
7
  import * as rc9 from 'rc9';
7
8
  import { defu } from 'defu';
@@ -47,25 +48,32 @@ function interpolate(target, source = {}, parse = (v) => v) {
47
48
  return value;
48
49
  }
49
50
  const matches = value.match(/(.?\${?(?:[\w:]+)?}?)/g) || [];
50
- return parse(matches.reduce((newValue, match) => {
51
- const parts = /(.?)\${?([\w:]+)?}?/g.exec(match);
52
- const prefix = parts[1];
53
- let value2, replacePart;
54
- if (prefix === "\\") {
55
- replacePart = parts[0];
56
- value2 = replacePart.replace("\\$", "$");
57
- } else {
58
- const key = parts[2];
59
- replacePart = parts[0].slice(prefix.length);
60
- if (parents.includes(key)) {
61
- console.warn(`Please avoid recursive environment variables ( loop: ${parents.join(" > ")} > ${key} )`);
62
- return "";
51
+ return parse(
52
+ // eslint-disable-next-line unicorn/no-array-reduce
53
+ matches.reduce((newValue, match) => {
54
+ const parts = /(.?)\${?([\w:]+)?}?/g.exec(match);
55
+ const prefix = parts[1];
56
+ let value2, replacePart;
57
+ if (prefix === "\\") {
58
+ replacePart = parts[0];
59
+ value2 = replacePart.replace("\\$", "$");
60
+ } else {
61
+ const key = parts[2];
62
+ replacePart = parts[0].slice(prefix.length);
63
+ if (parents.includes(key)) {
64
+ console.warn(
65
+ `Please avoid recursive environment variables ( loop: ${parents.join(
66
+ " > "
67
+ )} > ${key} )`
68
+ );
69
+ return "";
70
+ }
71
+ value2 = getValue(key);
72
+ value2 = interpolate2(value2, [...parents, key]);
63
73
  }
64
- value2 = getValue(key);
65
- value2 = interpolate2(value2, [...parents, key]);
66
- }
67
- return value2 !== void 0 ? newValue.replace(replacePart, value2) : newValue;
68
- }, value));
74
+ return value2 !== void 0 ? newValue.replace(replacePart, value2) : newValue;
75
+ }, value)
76
+ );
69
77
  }
70
78
  for (const key in target) {
71
79
  target[key] = interpolate2(getValue(key));
@@ -108,14 +116,23 @@ async function loadConfig(options) {
108
116
  const configRC = {};
109
117
  if (options.rcFile) {
110
118
  if (options.globalRc) {
111
- Object.assign(configRC, rc9.readUser({ name: options.rcFile, dir: options.cwd }));
119
+ Object.assign(
120
+ configRC,
121
+ rc9.readUser({ name: options.rcFile, dir: options.cwd })
122
+ );
112
123
  const workspaceDir = await findWorkspaceDir(options.cwd).catch(() => {
113
124
  });
114
125
  if (workspaceDir) {
115
- Object.assign(configRC, rc9.read({ name: options.rcFile, dir: workspaceDir }));
126
+ Object.assign(
127
+ configRC,
128
+ rc9.read({ name: options.rcFile, dir: workspaceDir })
129
+ );
116
130
  }
117
131
  }
118
- Object.assign(configRC, rc9.read({ name: options.rcFile, dir: options.cwd }));
132
+ Object.assign(
133
+ configRC,
134
+ rc9.read({ name: options.rcFile, dir: options.cwd })
135
+ );
119
136
  }
120
137
  r.config = defu(
121
138
  options.overrides,
@@ -127,20 +144,18 @@ async function loadConfig(options) {
127
144
  await extendConfig(r.config, options);
128
145
  r.layers = r.config._layers;
129
146
  delete r.config._layers;
130
- r.config = defu(
131
- r.config,
132
- ...r.layers.map((e) => e.config)
133
- );
147
+ r.config = defu(r.config, ...r.layers.map((e) => e.config));
134
148
  }
135
149
  const baseLayers = [
136
- options.overrides && { config: options.overrides, configFile: void 0, cwd: void 0 },
150
+ options.overrides && {
151
+ config: options.overrides,
152
+ configFile: void 0,
153
+ cwd: void 0
154
+ },
137
155
  { config, configFile: options.configFile, cwd: options.cwd },
138
156
  options.rcFile && { config: configRC, configFile: options.rcFile }
139
157
  ].filter((l) => l && l.config);
140
- r.layers = [
141
- ...baseLayers,
142
- ...r.layers
143
- ];
158
+ r.layers = [...baseLayers, ...r.layers];
144
159
  if (options.defaults) {
145
160
  r.config = defu(r.config, options.defaults);
146
161
  }
@@ -157,17 +172,27 @@ async function extendConfig(config, options) {
157
172
  }
158
173
  const extendSources = [];
159
174
  for (const key of keys) {
160
- extendSources.push(...(Array.isArray(config[key]) ? config[key] : [config[key]]).filter(Boolean));
175
+ extendSources.push(
176
+ ...(Array.isArray(config[key]) ? config[key] : [config[key]]).filter(
177
+ Boolean
178
+ )
179
+ );
161
180
  delete config[key];
162
181
  }
163
182
  for (const extendSource of extendSources) {
164
183
  if (typeof extendSource !== "string") {
165
- console.warn(`Cannot extend config from \`${JSON.stringify(extendSource)}\` (which should be a string) in ${options.cwd}`);
184
+ console.warn(
185
+ `Cannot extend config from \`${JSON.stringify(
186
+ extendSource
187
+ )}\` (which should be a string) in ${options.cwd}`
188
+ );
166
189
  continue;
167
190
  }
168
191
  const _config = await resolveConfig(extendSource, options);
169
192
  if (!_config.config) {
170
- console.warn(`Cannot extend config from \`${extendSource}\` in ${options.cwd}`);
193
+ console.warn(
194
+ `Cannot extend config from \`${extendSource}\` in ${options.cwd}`
195
+ );
171
196
  continue;
172
197
  }
173
198
  await extendConfig(_config.config, { ...options, cwd: _config.cwd });
@@ -188,16 +213,16 @@ async function resolveConfig(source, options) {
188
213
  }
189
214
  }
190
215
  if (GIT_PREFIXES.some((prefix) => source.startsWith(prefix))) {
216
+ const { downloadTemplate } = await import('giget');
191
217
  const url = new URL(source);
192
- const subPath = url.pathname.split("/").slice(2).join("/");
193
218
  const gitRepo = url.protocol + url.pathname.split("/").slice(0, 2).join("/");
194
- const tmpdir = resolve(os.tmpdir(), "c12/", gitRepo.replace(/[#/:@\\]/g, "_"));
195
- await promises.rm(tmpdir, { recursive: true }).catch(() => {
196
- });
197
- const gittar = await import('gittar').then((r) => r.default || r);
198
- const tarFile = await gittar.fetch(gitRepo);
199
- await gittar.extract(tarFile, tmpdir);
200
- source = resolve(tmpdir, subPath);
219
+ const name = gitRepo.replace(/[#/:@\\]/g, "_");
220
+ const tmpDir = process.env.XDG_CACHE_HOME ? resolve(process.env.XDG_CACHE_HOME, "c12", name) : resolve(homedir(), ".cache/c12", name);
221
+ if (existsSync(tmpDir)) {
222
+ await rmdir(tmpDir, { recursive: true });
223
+ }
224
+ const clonned = await downloadTemplate(source, { dir: tmpDir });
225
+ source = clonned.dir;
201
226
  }
202
227
  if (NPM_PACKAGE_RE.test(source)) {
203
228
  try {
@@ -212,7 +237,9 @@ async function resolveConfig(source, options) {
212
237
  }
213
238
  const res = { config: void 0, cwd };
214
239
  try {
215
- res.configFile = options.jiti.resolve(resolve(cwd, source), { paths: [cwd] });
240
+ res.configFile = options.jiti.resolve(resolve(cwd, source), {
241
+ paths: [cwd]
242
+ });
216
243
  } catch {
217
244
  }
218
245
  if (!existsSync(res.configFile)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c12",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "description": "Smart Config Loader",
5
5
  "repository": "unjs/c12",
6
6
  "license": "MIT",
@@ -19,31 +19,34 @@
19
19
  "files": [
20
20
  "dist"
21
21
  ],
22
+ "scripts": {
23
+ "build": "unbuild",
24
+ "dev": "vitest dev",
25
+ "lint": "eslint --ext .ts,.js,.mjs,.cjs . && prettier -c src test",
26
+ "lint:fix": "eslint --ext .ts,.js,.mjs,.cjs . --fix && prettier -w src test",
27
+ "prepack": "unbuild",
28
+ "release": "pnpm test && changelogen --release && npm publish && git push --follow-tags",
29
+ "test": "vitest run --coverage"
30
+ },
22
31
  "dependencies": {
23
- "defu": "^6.1.1",
32
+ "defu": "^6.1.2",
24
33
  "dotenv": "^16.0.3",
25
- "gittar": "^0.1.1",
26
- "jiti": "^1.16.0",
27
- "mlly": "^1.0.0",
28
- "pathe": "^1.0.0",
34
+ "giget": "^1.0.0",
35
+ "jiti": "^1.17.0",
36
+ "mlly": "^1.1.1",
37
+ "pathe": "^1.1.0",
29
38
  "pkg-types": "^1.0.1",
30
- "rc9": "^2.0.0"
39
+ "rc9": "^2.0.1"
31
40
  },
32
41
  "devDependencies": {
33
- "@vitest/coverage-c8": "^0.25.2",
34
- "eslint": "^8.27.0",
35
- "eslint-config-unjs": "^0.0.2",
36
- "standard-version": "^9.5.0",
37
- "typescript": "^4.8.4",
38
- "unbuild": "^0.9.4",
39
- "vitest": "^0.25.2"
42
+ "@vitest/coverage-c8": "^0.28.5",
43
+ "changelogen": "^0.4.1",
44
+ "eslint": "^8.34.0",
45
+ "eslint-config-unjs": "^0.1.0",
46
+ "prettier": "^2.8.4",
47
+ "typescript": "^4.9.5",
48
+ "unbuild": "^1.1.1",
49
+ "vitest": "^0.28.5"
40
50
  },
41
- "packageManager": "pnpm@7.16.0",
42
- "scripts": {
43
- "build": "unbuild",
44
- "dev": "vitest dev",
45
- "lint": "eslint --ext .ts,.js,.mjs,.cjs .",
46
- "release": "pnpm test && standard-version && git push --follow-tags && pnpm publish",
47
- "test": "vitest run --coverage"
48
- }
49
- }
51
+ "packageManager": "pnpm@7.27.0"
52
+ }