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 +70 -43
- package/dist/index.d.ts +4 -4
- package/dist/index.mjs +70 -43
- package/package.json +26 -23
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
|
|
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(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
|
81
|
-
|
|
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(
|
|
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(
|
|
142
|
+
Object.assign(
|
|
143
|
+
configRC,
|
|
144
|
+
rc9__namespace.read({ name: options.rcFile, dir: workspaceDir })
|
|
145
|
+
);
|
|
132
146
|
}
|
|
133
147
|
}
|
|
134
|
-
Object.assign(
|
|
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 && {
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
await
|
|
216
|
-
source =
|
|
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), {
|
|
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
|
-
|
|
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
|
|
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(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
|
65
|
-
|
|
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(
|
|
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(
|
|
126
|
+
Object.assign(
|
|
127
|
+
configRC,
|
|
128
|
+
rc9.read({ name: options.rcFile, dir: workspaceDir })
|
|
129
|
+
);
|
|
116
130
|
}
|
|
117
131
|
}
|
|
118
|
-
Object.assign(
|
|
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 && {
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
await
|
|
200
|
-
source =
|
|
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), {
|
|
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.
|
|
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.
|
|
32
|
+
"defu": "^6.1.2",
|
|
24
33
|
"dotenv": "^16.0.3",
|
|
25
|
-
"
|
|
26
|
-
"jiti": "^1.
|
|
27
|
-
"mlly": "^1.
|
|
28
|
-
"pathe": "^1.
|
|
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.
|
|
39
|
+
"rc9": "^2.0.1"
|
|
31
40
|
},
|
|
32
41
|
"devDependencies": {
|
|
33
|
-
"@vitest/coverage-c8": "^0.
|
|
34
|
-
"
|
|
35
|
-
"eslint
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
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.
|
|
42
|
-
|
|
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
|
+
}
|