c12 1.1.2 → 1.2.0
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/README.md +79 -38
- package/dist/index.cjs +48 -11
- package/dist/index.d.ts +24 -2
- package/dist/index.mjs +49 -12
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
|
-
- JSON, CJS, Typescript and ESM config loader with [unjs/jiti](https://github.com/unjs/jiti)
|
|
12
|
+
- JSON, CJS, Typescript, and ESM config loader with [unjs/jiti](https://github.com/unjs/jiti)
|
|
13
13
|
- RC config support with [unjs/rc9](https://github.com/unjs/rc9)
|
|
14
14
|
- Multiple sources merged with [unjs/defu](https://github.com/unjs/defu)
|
|
15
15
|
- `.env` support with [dotenv](https://www.npmjs.com/package/dotenv)
|
|
16
|
+
- Support reading config from the nearest `package.json` file
|
|
16
17
|
- Support extending nested configurations from multiple local or git sources
|
|
17
18
|
|
|
18
19
|
## Usage
|
|
@@ -34,48 +35,49 @@ Import:
|
|
|
34
35
|
|
|
35
36
|
```js
|
|
36
37
|
// ESM
|
|
37
|
-
import { loadConfig } from
|
|
38
|
+
import { loadConfig } from "c12";
|
|
38
39
|
|
|
39
40
|
// CommonJS
|
|
40
|
-
const { loadConfig } = require(
|
|
41
|
+
const { loadConfig } = require("c12");
|
|
41
42
|
```
|
|
42
43
|
|
|
43
44
|
Load configuration:
|
|
44
45
|
|
|
45
46
|
```js
|
|
46
47
|
// Get loaded config
|
|
47
|
-
const { config } = await loadConfig({})
|
|
48
|
+
const { config } = await loadConfig({});
|
|
48
49
|
|
|
49
50
|
// Get resolved config and extended layers
|
|
50
|
-
const { config, configFile, layers } = await loadConfig({})
|
|
51
|
+
const { config, configFile, layers } = await loadConfig({});
|
|
51
52
|
```
|
|
52
53
|
|
|
53
54
|
## Loading priority
|
|
54
55
|
|
|
55
56
|
c12 merged config sources with [unjs/defu](https://github.com/unjs/defu) by below order:
|
|
56
57
|
|
|
57
|
-
1.
|
|
58
|
-
2.
|
|
58
|
+
1. Config overrides passed by options
|
|
59
|
+
2. Config file in CWD
|
|
59
60
|
3. RC file in CWD
|
|
60
|
-
4.
|
|
61
|
-
5.
|
|
62
|
-
6.
|
|
61
|
+
4. Global RC file in user's home directory
|
|
62
|
+
5. Config from `package.json`
|
|
63
|
+
6. Default config passed by options
|
|
64
|
+
7. Extended config layers
|
|
63
65
|
|
|
64
66
|
## Options
|
|
65
67
|
|
|
66
68
|
### `cwd`
|
|
67
69
|
|
|
68
|
-
Resolve configuration from this working directory.
|
|
70
|
+
Resolve configuration from this working directory. The default is `process.cwd()`
|
|
69
71
|
|
|
70
72
|
### `name`
|
|
71
73
|
|
|
72
|
-
Configuration base name.
|
|
74
|
+
Configuration base name. The default is `config`.
|
|
73
75
|
|
|
74
76
|
### `configName`
|
|
75
77
|
|
|
76
|
-
Configuration file name without extension
|
|
78
|
+
Configuration file name without extension. Default is generated from `name` (name=foo => `foo.config`).
|
|
77
79
|
|
|
78
|
-
Set to `false` to avoid loading config file.
|
|
80
|
+
Set to `false` to avoid loading the config file.
|
|
79
81
|
|
|
80
82
|
### `rcFile`
|
|
81
83
|
|
|
@@ -85,12 +87,20 @@ Set to `false` to disable loading RC config.
|
|
|
85
87
|
|
|
86
88
|
### `globalRC`
|
|
87
89
|
|
|
88
|
-
Load RC config from the workspace directory and user's home directory. Only enabled when `rcFile` is provided. Set to `false` to disable this functionality.
|
|
90
|
+
Load RC config from the workspace directory and the user's home directory. Only enabled when `rcFile` is provided. Set to `false` to disable this functionality.
|
|
89
91
|
|
|
90
92
|
### `dotenv`
|
|
91
93
|
|
|
92
94
|
Loads `.env` file if enabled. It is disabled by default.
|
|
93
95
|
|
|
96
|
+
### `packageJson`
|
|
97
|
+
|
|
98
|
+
Loads config from nearest `package.json` file. It is disabled by default.
|
|
99
|
+
|
|
100
|
+
If `true` value is passed, c12 uses `name` field from `package.json`.
|
|
101
|
+
|
|
102
|
+
You can also pass either a string or an array of strings as a value to use those fields.
|
|
103
|
+
|
|
94
104
|
### `defaults`
|
|
95
105
|
|
|
96
106
|
Specify default configuration. It has the **lowest** priority and is applied **after extending** config.
|
|
@@ -99,7 +109,7 @@ Specify default configuration. It has the **lowest** priority and is applied **a
|
|
|
99
109
|
|
|
100
110
|
Specify default configuration. It is applied **before** extending config.
|
|
101
111
|
|
|
102
|
-
### `
|
|
112
|
+
### `overrides`
|
|
103
113
|
|
|
104
114
|
Specify override configuration. It has the **highest** priority and is applied **before extending** config.
|
|
105
115
|
|
|
@@ -111,16 +121,22 @@ Custom [unjs/jiti](https://github.com/unjs/jiti) instance used to import configu
|
|
|
111
121
|
|
|
112
122
|
Custom [unjs/jiti](https://github.com/unjs/jiti) options to import configuration files.
|
|
113
123
|
|
|
124
|
+
### `envName`
|
|
125
|
+
|
|
126
|
+
Environment name used for [environment specific configuration](#environment-specific-configuration).
|
|
127
|
+
|
|
128
|
+
The default is `process.env.NODE_ENV`. You can set `envName` to `false` or an empty string to disable the feature.
|
|
129
|
+
|
|
114
130
|
## Extending configuration
|
|
115
131
|
|
|
116
|
-
If resolved config contains a `extends` key, it will be used to extend configuration.
|
|
132
|
+
If resolved config contains a `extends` key, it will be used to extend the configuration.
|
|
117
133
|
|
|
118
134
|
Extending can be nested and each layer can extend from one base or more.
|
|
119
135
|
|
|
120
|
-
|
|
136
|
+
The final config is merged result of extended options and user options with [unjs/defu](https://github.com/unjs/defu).
|
|
121
137
|
|
|
122
|
-
Each item in extends
|
|
123
|
-
If it starts with either
|
|
138
|
+
Each item in extends is a string that can be either an absolute or relative path to the current config file pointing to a config file for extending or the directory containing the config file.
|
|
139
|
+
If it starts with either `github:`, `gitlab:`, `bitbucket:`, or `https:`, c12 automatically clones it.
|
|
124
140
|
|
|
125
141
|
For custom merging strategies, you can directly access each layer with `layers` property.
|
|
126
142
|
|
|
@@ -130,31 +146,28 @@ For custom merging strategies, you can directly access each layer with `layers`
|
|
|
130
146
|
// config.ts
|
|
131
147
|
export default {
|
|
132
148
|
colors: {
|
|
133
|
-
primary:
|
|
149
|
+
primary: "user_primary",
|
|
134
150
|
},
|
|
135
|
-
extends: [
|
|
136
|
-
|
|
137
|
-
'./config.dev.ts'
|
|
138
|
-
]
|
|
139
|
-
}
|
|
151
|
+
extends: ["./theme"],
|
|
152
|
+
};
|
|
140
153
|
```
|
|
141
154
|
|
|
142
155
|
```js
|
|
143
156
|
// config.dev.ts
|
|
144
157
|
export default {
|
|
145
|
-
dev: true
|
|
146
|
-
}
|
|
158
|
+
dev: true,
|
|
159
|
+
};
|
|
147
160
|
```
|
|
148
161
|
|
|
149
162
|
```js
|
|
150
163
|
// theme/config.ts
|
|
151
164
|
export default {
|
|
152
|
-
extends:
|
|
165
|
+
extends: "../base",
|
|
153
166
|
colors: {
|
|
154
|
-
primary:
|
|
155
|
-
secondary:
|
|
156
|
-
}
|
|
157
|
-
}
|
|
167
|
+
primary: "theme_primary",
|
|
168
|
+
secondary: "theme_secondary",
|
|
169
|
+
},
|
|
170
|
+
};
|
|
158
171
|
```
|
|
159
172
|
|
|
160
173
|
```js
|
|
@@ -167,7 +180,7 @@ export default {
|
|
|
167
180
|
}
|
|
168
181
|
```
|
|
169
182
|
|
|
170
|
-
|
|
183
|
+
The loaded configuration would look like this:
|
|
171
184
|
|
|
172
185
|
```js
|
|
173
186
|
{
|
|
@@ -190,6 +203,36 @@ Layers:
|
|
|
190
203
|
]
|
|
191
204
|
```
|
|
192
205
|
|
|
206
|
+
## Environment-specific configuration
|
|
207
|
+
|
|
208
|
+
Users can define environment-specific configuration using these config keys:
|
|
209
|
+
|
|
210
|
+
- `$test: {...}`
|
|
211
|
+
- `$development: {...}`
|
|
212
|
+
- `$production: {...}`
|
|
213
|
+
- `$env: { [env]: {...} }`
|
|
214
|
+
|
|
215
|
+
c12 tries to match [`envName`](#envname) and override environment config if specified.
|
|
216
|
+
|
|
217
|
+
**Note:** Environment will be applied when extending each configuration layer. This way layers can provide environment-specific configuration.
|
|
218
|
+
|
|
219
|
+
**Example:**
|
|
220
|
+
|
|
221
|
+
```js
|
|
222
|
+
{
|
|
223
|
+
// Default configuration
|
|
224
|
+
logLevel: 'info',
|
|
225
|
+
|
|
226
|
+
// Environment overrides
|
|
227
|
+
$test: { logLevel: 'silent' },
|
|
228
|
+
$development: { logLevel: 'warning' },
|
|
229
|
+
$production: { logLevel: 'error' },
|
|
230
|
+
$env: {
|
|
231
|
+
staging: { logLevel: 'debug' }
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
193
236
|
## 💻 Development
|
|
194
237
|
|
|
195
238
|
- Clone this repository
|
|
@@ -202,14 +245,12 @@ Layers:
|
|
|
202
245
|
Made with 💛 Published under [MIT License](./LICENSE).
|
|
203
246
|
|
|
204
247
|
<!-- Badges -->
|
|
248
|
+
|
|
205
249
|
[npm-version-src]: https://img.shields.io/npm/v/c12?style=flat-square
|
|
206
250
|
[npm-version-href]: https://npmjs.com/package/c12
|
|
207
|
-
|
|
208
251
|
[npm-downloads-src]: https://img.shields.io/npm/dm/c12?style=flat-square
|
|
209
252
|
[npm-downloads-href]: https://npmjs.com/package/c12
|
|
210
|
-
|
|
211
|
-
[github-actions-src]: https://img.shields.io/github/workflow/status/unjs/c12/ci/main?style=flat-square
|
|
253
|
+
[github-actions-src]: https://img.shields.io/github/actions/workflow/status/unjs/c12/ci.yml?branch=main&style=flat-square
|
|
212
254
|
[github-actions-href]: https://github.com/unjs/c12/actions?query=workflow%3Aci
|
|
213
|
-
|
|
214
255
|
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/c12/main?style=flat-square
|
|
215
256
|
[codecov-href]: https://codecov.io/gh/unjs/c12
|
package/dist/index.cjs
CHANGED
|
@@ -99,6 +99,7 @@ function interpolate(target, source = {}, parse = (v) => v) {
|
|
|
99
99
|
async function loadConfig(options) {
|
|
100
100
|
options.cwd = pathe.resolve(process.cwd(), options.cwd || ".");
|
|
101
101
|
options.name = options.name || "config";
|
|
102
|
+
options.envName = options.envName ?? process.env.NODE_ENV;
|
|
102
103
|
options.configFile = options.configFile ?? (options.name !== "config" ? `${options.name}.config` : "config");
|
|
103
104
|
options.rcFile = options.rcFile ?? `.${options.name}rc`;
|
|
104
105
|
if (options.extend !== false) {
|
|
@@ -150,10 +151,21 @@ async function loadConfig(options) {
|
|
|
150
151
|
rc9__namespace.read({ name: options.rcFile, dir: options.cwd })
|
|
151
152
|
);
|
|
152
153
|
}
|
|
154
|
+
const pkgJson = {};
|
|
155
|
+
if (options.packageJson) {
|
|
156
|
+
const keys = (Array.isArray(options.packageJson) ? options.packageJson : [
|
|
157
|
+
typeof options.packageJson === "string" ? options.packageJson : options.name
|
|
158
|
+
]).filter((t) => t && typeof t === "string");
|
|
159
|
+
const pkgJsonFile = await pkgTypes.readPackageJSON(options.cwd).catch(() => {
|
|
160
|
+
});
|
|
161
|
+
const values = keys.map((key) => pkgJsonFile?.[key]);
|
|
162
|
+
Object.assign(pkgJson, defu.defu({}, ...values));
|
|
163
|
+
}
|
|
153
164
|
r.config = defu.defu(
|
|
154
165
|
options.overrides,
|
|
155
166
|
config,
|
|
156
167
|
configRC,
|
|
168
|
+
pkgJson,
|
|
157
169
|
options.defaultConfig
|
|
158
170
|
);
|
|
159
171
|
if (options.extend) {
|
|
@@ -169,7 +181,8 @@ async function loadConfig(options) {
|
|
|
169
181
|
cwd: void 0
|
|
170
182
|
},
|
|
171
183
|
{ config, configFile: options.configFile, cwd: options.cwd },
|
|
172
|
-
options.rcFile && { config: configRC, configFile: options.rcFile }
|
|
184
|
+
options.rcFile && { config: configRC, configFile: options.rcFile },
|
|
185
|
+
options.packageJson && { config: pkgJson, configFile: "package.json" }
|
|
173
186
|
].filter((l) => l && l.config);
|
|
174
187
|
r.layers = [...baseLayers, ...r.layers];
|
|
175
188
|
if (options.defaults) {
|
|
@@ -195,16 +208,26 @@ async function extendConfig(config, options) {
|
|
|
195
208
|
);
|
|
196
209
|
delete config[key];
|
|
197
210
|
}
|
|
198
|
-
for (
|
|
211
|
+
for (let extendSource of extendSources) {
|
|
212
|
+
const originalExtendSource = extendSource;
|
|
213
|
+
let sourceOptions = {};
|
|
214
|
+
if (extendSource.source) {
|
|
215
|
+
sourceOptions = extendSource.options || {};
|
|
216
|
+
extendSource = extendSource.source;
|
|
217
|
+
}
|
|
218
|
+
if (Array.isArray(extendSource)) {
|
|
219
|
+
sourceOptions = extendSource[1] || {};
|
|
220
|
+
extendSource = extendSource[0];
|
|
221
|
+
}
|
|
199
222
|
if (typeof extendSource !== "string") {
|
|
200
223
|
console.warn(
|
|
201
224
|
`Cannot extend config from \`${JSON.stringify(
|
|
202
|
-
|
|
203
|
-
)}\`
|
|
225
|
+
originalExtendSource
|
|
226
|
+
)}\` in ${options.cwd}`
|
|
204
227
|
);
|
|
205
228
|
continue;
|
|
206
229
|
}
|
|
207
|
-
const _config = await resolveConfig(extendSource, options);
|
|
230
|
+
const _config = await resolveConfig(extendSource, options, sourceOptions);
|
|
208
231
|
if (!_config.config) {
|
|
209
232
|
console.warn(
|
|
210
233
|
`Cannot extend config from \`${extendSource}\` in ${options.cwd}`
|
|
@@ -220,8 +243,8 @@ async function extendConfig(config, options) {
|
|
|
220
243
|
}
|
|
221
244
|
}
|
|
222
245
|
const GIT_PREFIXES = ["github:", "gitlab:", "bitbucket:", "https://"];
|
|
223
|
-
const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]
|
|
224
|
-
async function resolveConfig(source, options) {
|
|
246
|
+
const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]*($|\/.*)/;
|
|
247
|
+
async function resolveConfig(source, options, sourceOptions = {}) {
|
|
225
248
|
if (options.resolve) {
|
|
226
249
|
const res2 = await options.resolve(source, options);
|
|
227
250
|
if (res2) {
|
|
@@ -237,8 +260,8 @@ async function resolveConfig(source, options) {
|
|
|
237
260
|
if (node_fs.existsSync(tmpDir)) {
|
|
238
261
|
await promises.rmdir(tmpDir, { recursive: true });
|
|
239
262
|
}
|
|
240
|
-
const
|
|
241
|
-
source =
|
|
263
|
+
const cloned = await downloadTemplate(source, { dir: tmpDir });
|
|
264
|
+
source = cloned.dir;
|
|
242
265
|
}
|
|
243
266
|
if (NPM_PACKAGE_RE.test(source)) {
|
|
244
267
|
try {
|
|
@@ -251,7 +274,7 @@ async function resolveConfig(source, options) {
|
|
|
251
274
|
if (isDir) {
|
|
252
275
|
source = options.configFile;
|
|
253
276
|
}
|
|
254
|
-
const res = { config: void 0, cwd };
|
|
277
|
+
const res = { config: void 0, cwd, source, sourceOptions };
|
|
255
278
|
try {
|
|
256
279
|
res.configFile = options.jiti.resolve(pathe.resolve(cwd, source), {
|
|
257
280
|
paths: [cwd]
|
|
@@ -262,9 +285,23 @@ async function resolveConfig(source, options) {
|
|
|
262
285
|
return res;
|
|
263
286
|
}
|
|
264
287
|
res.config = options.jiti(res.configFile);
|
|
265
|
-
if (
|
|
288
|
+
if (res.config instanceof Function) {
|
|
266
289
|
res.config = await res.config();
|
|
267
290
|
}
|
|
291
|
+
if (options.envName) {
|
|
292
|
+
const envConfig = {
|
|
293
|
+
...res.config["$" + options.envName],
|
|
294
|
+
...res.config.$env?.[options.envName]
|
|
295
|
+
};
|
|
296
|
+
if (Object.keys(envConfig).length > 0) {
|
|
297
|
+
res.config = defu.defu(envConfig, res.config);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
res.meta = defu.defu(res.sourceOptions.meta, res.config.$meta);
|
|
301
|
+
delete res.config.$meta;
|
|
302
|
+
if (res.sourceOptions.overrides) {
|
|
303
|
+
res.config = defu.defu(res.sourceOptions.overrides, res.config);
|
|
304
|
+
}
|
|
268
305
|
return res;
|
|
269
306
|
}
|
|
270
307
|
|
package/dist/index.d.ts
CHANGED
|
@@ -37,10 +37,30 @@ declare function setupDotenv(options: DotenvOptions): Promise<Env>;
|
|
|
37
37
|
/** Load environment variables into an object. */
|
|
38
38
|
declare function loadDotenv(options: DotenvOptions): Promise<Env>;
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
type UserInputConfig = Record<string, any>;
|
|
41
|
+
interface ConfigLayerMeta {
|
|
42
|
+
name?: string;
|
|
43
|
+
[key: string]: any;
|
|
44
|
+
}
|
|
45
|
+
interface C12InputConfig {
|
|
46
|
+
$test?: UserInputConfig;
|
|
47
|
+
$development?: UserInputConfig;
|
|
48
|
+
$production?: UserInputConfig;
|
|
49
|
+
$env?: Record<string, UserInputConfig>;
|
|
50
|
+
$meta?: ConfigLayerMeta;
|
|
51
|
+
}
|
|
52
|
+
interface InputConfig extends C12InputConfig, UserInputConfig {
|
|
53
|
+
}
|
|
54
|
+
interface SourceOptions {
|
|
55
|
+
meta?: ConfigLayerMeta;
|
|
56
|
+
overrides?: UserInputConfig;
|
|
57
|
+
[key: string]: any;
|
|
41
58
|
}
|
|
42
59
|
interface ConfigLayer<T extends InputConfig = InputConfig> {
|
|
43
60
|
config: T | null;
|
|
61
|
+
source?: string;
|
|
62
|
+
sourceOptions?: SourceOptions;
|
|
63
|
+
meta?: ConfigLayerMeta;
|
|
44
64
|
cwd?: string;
|
|
45
65
|
configFile?: string;
|
|
46
66
|
}
|
|
@@ -58,6 +78,8 @@ interface LoadConfigOptions<T extends InputConfig = InputConfig> {
|
|
|
58
78
|
rcFile?: false | string;
|
|
59
79
|
globalRc?: boolean;
|
|
60
80
|
dotenv?: boolean | DotenvOptions;
|
|
81
|
+
envName?: string | false;
|
|
82
|
+
packageJson?: boolean | string | string[];
|
|
61
83
|
defaults?: T;
|
|
62
84
|
defaultConfig?: T;
|
|
63
85
|
overrides?: T;
|
|
@@ -70,4 +92,4 @@ interface LoadConfigOptions<T extends InputConfig = InputConfig> {
|
|
|
70
92
|
}
|
|
71
93
|
declare function loadConfig<T extends InputConfig = InputConfig>(options: LoadConfigOptions<T>): Promise<ResolvedConfig<T>>;
|
|
72
94
|
|
|
73
|
-
export { ConfigLayer, DotenvOptions, Env, InputConfig, LoadConfigOptions, ResolveConfigOptions, ResolvedConfig, loadConfig, loadDotenv, setupDotenv };
|
|
95
|
+
export { C12InputConfig, ConfigLayer, ConfigLayerMeta, DotenvOptions, Env, InputConfig, LoadConfigOptions, ResolveConfigOptions, ResolvedConfig, SourceOptions, UserInputConfig, loadConfig, loadDotenv, setupDotenv };
|
package/dist/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { homedir } from 'node:os';
|
|
|
6
6
|
import createJiti from 'jiti';
|
|
7
7
|
import * as rc9 from 'rc9';
|
|
8
8
|
import { defu } from 'defu';
|
|
9
|
-
import { findWorkspaceDir } from 'pkg-types';
|
|
9
|
+
import { findWorkspaceDir, readPackageJSON } from 'pkg-types';
|
|
10
10
|
|
|
11
11
|
async function setupDotenv(options) {
|
|
12
12
|
const targetEnvironment = options.env ?? process.env;
|
|
@@ -83,6 +83,7 @@ function interpolate(target, source = {}, parse = (v) => v) {
|
|
|
83
83
|
async function loadConfig(options) {
|
|
84
84
|
options.cwd = resolve(process.cwd(), options.cwd || ".");
|
|
85
85
|
options.name = options.name || "config";
|
|
86
|
+
options.envName = options.envName ?? process.env.NODE_ENV;
|
|
86
87
|
options.configFile = options.configFile ?? (options.name !== "config" ? `${options.name}.config` : "config");
|
|
87
88
|
options.rcFile = options.rcFile ?? `.${options.name}rc`;
|
|
88
89
|
if (options.extend !== false) {
|
|
@@ -134,10 +135,21 @@ async function loadConfig(options) {
|
|
|
134
135
|
rc9.read({ name: options.rcFile, dir: options.cwd })
|
|
135
136
|
);
|
|
136
137
|
}
|
|
138
|
+
const pkgJson = {};
|
|
139
|
+
if (options.packageJson) {
|
|
140
|
+
const keys = (Array.isArray(options.packageJson) ? options.packageJson : [
|
|
141
|
+
typeof options.packageJson === "string" ? options.packageJson : options.name
|
|
142
|
+
]).filter((t) => t && typeof t === "string");
|
|
143
|
+
const pkgJsonFile = await readPackageJSON(options.cwd).catch(() => {
|
|
144
|
+
});
|
|
145
|
+
const values = keys.map((key) => pkgJsonFile?.[key]);
|
|
146
|
+
Object.assign(pkgJson, defu({}, ...values));
|
|
147
|
+
}
|
|
137
148
|
r.config = defu(
|
|
138
149
|
options.overrides,
|
|
139
150
|
config,
|
|
140
151
|
configRC,
|
|
152
|
+
pkgJson,
|
|
141
153
|
options.defaultConfig
|
|
142
154
|
);
|
|
143
155
|
if (options.extend) {
|
|
@@ -153,7 +165,8 @@ async function loadConfig(options) {
|
|
|
153
165
|
cwd: void 0
|
|
154
166
|
},
|
|
155
167
|
{ config, configFile: options.configFile, cwd: options.cwd },
|
|
156
|
-
options.rcFile && { config: configRC, configFile: options.rcFile }
|
|
168
|
+
options.rcFile && { config: configRC, configFile: options.rcFile },
|
|
169
|
+
options.packageJson && { config: pkgJson, configFile: "package.json" }
|
|
157
170
|
].filter((l) => l && l.config);
|
|
158
171
|
r.layers = [...baseLayers, ...r.layers];
|
|
159
172
|
if (options.defaults) {
|
|
@@ -179,16 +192,26 @@ async function extendConfig(config, options) {
|
|
|
179
192
|
);
|
|
180
193
|
delete config[key];
|
|
181
194
|
}
|
|
182
|
-
for (
|
|
195
|
+
for (let extendSource of extendSources) {
|
|
196
|
+
const originalExtendSource = extendSource;
|
|
197
|
+
let sourceOptions = {};
|
|
198
|
+
if (extendSource.source) {
|
|
199
|
+
sourceOptions = extendSource.options || {};
|
|
200
|
+
extendSource = extendSource.source;
|
|
201
|
+
}
|
|
202
|
+
if (Array.isArray(extendSource)) {
|
|
203
|
+
sourceOptions = extendSource[1] || {};
|
|
204
|
+
extendSource = extendSource[0];
|
|
205
|
+
}
|
|
183
206
|
if (typeof extendSource !== "string") {
|
|
184
207
|
console.warn(
|
|
185
208
|
`Cannot extend config from \`${JSON.stringify(
|
|
186
|
-
|
|
187
|
-
)}\`
|
|
209
|
+
originalExtendSource
|
|
210
|
+
)}\` in ${options.cwd}`
|
|
188
211
|
);
|
|
189
212
|
continue;
|
|
190
213
|
}
|
|
191
|
-
const _config = await resolveConfig(extendSource, options);
|
|
214
|
+
const _config = await resolveConfig(extendSource, options, sourceOptions);
|
|
192
215
|
if (!_config.config) {
|
|
193
216
|
console.warn(
|
|
194
217
|
`Cannot extend config from \`${extendSource}\` in ${options.cwd}`
|
|
@@ -204,8 +227,8 @@ async function extendConfig(config, options) {
|
|
|
204
227
|
}
|
|
205
228
|
}
|
|
206
229
|
const GIT_PREFIXES = ["github:", "gitlab:", "bitbucket:", "https://"];
|
|
207
|
-
const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]
|
|
208
|
-
async function resolveConfig(source, options) {
|
|
230
|
+
const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]*($|\/.*)/;
|
|
231
|
+
async function resolveConfig(source, options, sourceOptions = {}) {
|
|
209
232
|
if (options.resolve) {
|
|
210
233
|
const res2 = await options.resolve(source, options);
|
|
211
234
|
if (res2) {
|
|
@@ -221,8 +244,8 @@ async function resolveConfig(source, options) {
|
|
|
221
244
|
if (existsSync(tmpDir)) {
|
|
222
245
|
await rmdir(tmpDir, { recursive: true });
|
|
223
246
|
}
|
|
224
|
-
const
|
|
225
|
-
source =
|
|
247
|
+
const cloned = await downloadTemplate(source, { dir: tmpDir });
|
|
248
|
+
source = cloned.dir;
|
|
226
249
|
}
|
|
227
250
|
if (NPM_PACKAGE_RE.test(source)) {
|
|
228
251
|
try {
|
|
@@ -235,7 +258,7 @@ async function resolveConfig(source, options) {
|
|
|
235
258
|
if (isDir) {
|
|
236
259
|
source = options.configFile;
|
|
237
260
|
}
|
|
238
|
-
const res = { config: void 0, cwd };
|
|
261
|
+
const res = { config: void 0, cwd, source, sourceOptions };
|
|
239
262
|
try {
|
|
240
263
|
res.configFile = options.jiti.resolve(resolve(cwd, source), {
|
|
241
264
|
paths: [cwd]
|
|
@@ -246,9 +269,23 @@ async function resolveConfig(source, options) {
|
|
|
246
269
|
return res;
|
|
247
270
|
}
|
|
248
271
|
res.config = options.jiti(res.configFile);
|
|
249
|
-
if (
|
|
272
|
+
if (res.config instanceof Function) {
|
|
250
273
|
res.config = await res.config();
|
|
251
274
|
}
|
|
275
|
+
if (options.envName) {
|
|
276
|
+
const envConfig = {
|
|
277
|
+
...res.config["$" + options.envName],
|
|
278
|
+
...res.config.$env?.[options.envName]
|
|
279
|
+
};
|
|
280
|
+
if (Object.keys(envConfig).length > 0) {
|
|
281
|
+
res.config = defu(envConfig, res.config);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
res.meta = defu(res.sourceOptions.meta, res.config.$meta);
|
|
285
|
+
delete res.config.$meta;
|
|
286
|
+
if (res.sourceOptions.overrides) {
|
|
287
|
+
res.config = defu(res.sourceOptions.overrides, res.config);
|
|
288
|
+
}
|
|
252
289
|
return res;
|
|
253
290
|
}
|
|
254
291
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c12",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Smart Config Loader",
|
|
5
5
|
"repository": "unjs/c12",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,22 +31,22 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"defu": "^6.1.2",
|
|
33
33
|
"dotenv": "^16.0.3",
|
|
34
|
-
"giget": "^1.1.
|
|
35
|
-
"jiti": "^1.17.
|
|
36
|
-
"mlly": "^1.
|
|
34
|
+
"giget": "^1.1.2",
|
|
35
|
+
"jiti": "^1.17.2",
|
|
36
|
+
"mlly": "^1.2.0",
|
|
37
37
|
"pathe": "^1.1.0",
|
|
38
38
|
"pkg-types": "^1.0.2",
|
|
39
39
|
"rc9": "^2.0.1"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@vitest/coverage-c8": "^0.
|
|
43
|
-
"changelogen": "^0.
|
|
44
|
-
"eslint": "^8.
|
|
42
|
+
"@vitest/coverage-c8": "^0.29.2",
|
|
43
|
+
"changelogen": "^0.5.1",
|
|
44
|
+
"eslint": "^8.36.0",
|
|
45
45
|
"eslint-config-unjs": "^0.1.0",
|
|
46
46
|
"prettier": "^2.8.4",
|
|
47
47
|
"typescript": "^4.9.5",
|
|
48
|
-
"unbuild": "^1.1.
|
|
49
|
-
"vitest": "^0.
|
|
48
|
+
"unbuild": "^1.1.2",
|
|
49
|
+
"vitest": "^0.29.2"
|
|
50
50
|
},
|
|
51
|
-
"packageManager": "pnpm@7.
|
|
51
|
+
"packageManager": "pnpm@7.29.1"
|
|
52
52
|
}
|