c12 1.5.0 → 1.6.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 +44 -1
- package/dist/index.cjs +29 -4
- package/dist/index.d.cts +5 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.mjs +30 -5
- package/package.json +12 -11
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[![Codecov][codecov-src]][codecov-href]
|
|
6
6
|
[![License][license-src]][license-href]
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
c12 (pronounced as /siːtwelv/, like c-twelve) is a smart configuration loader.
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
@@ -115,6 +115,10 @@ Specify default configuration. It is applied **before** extending config.
|
|
|
115
115
|
|
|
116
116
|
Specify override configuration. It has the **highest** priority and is applied **before extending** config.
|
|
117
117
|
|
|
118
|
+
### `omit$Keys`
|
|
119
|
+
|
|
120
|
+
Exclude environment-specific and built-in keys start with `$` in the resolved config. The default is `false`.
|
|
121
|
+
|
|
118
122
|
### `jiti`
|
|
119
123
|
|
|
120
124
|
Custom [unjs/jiti](https://github.com/unjs/jiti) instance used to import configuration files.
|
|
@@ -123,6 +127,10 @@ Custom [unjs/jiti](https://github.com/unjs/jiti) instance used to import configu
|
|
|
123
127
|
|
|
124
128
|
Custom [unjs/jiti](https://github.com/unjs/jiti) options to import configuration files.
|
|
125
129
|
|
|
130
|
+
### `giget`
|
|
131
|
+
|
|
132
|
+
Options passed to [unjs/giget](https://github.com/unjs/giget) when extending layer from git source.
|
|
133
|
+
|
|
126
134
|
### `envName`
|
|
127
135
|
|
|
128
136
|
Environment name used for [environment specific configuration](#environment-specific-configuration).
|
|
@@ -205,6 +213,41 @@ Layers:
|
|
|
205
213
|
]
|
|
206
214
|
```
|
|
207
215
|
|
|
216
|
+
## Extending Config Layer from Remote Sources
|
|
217
|
+
|
|
218
|
+
You can also extend configuration from remote sources such as npm or github.
|
|
219
|
+
|
|
220
|
+
In the repo, there should be a `config.ts` (or `config.{name}.ts`) file to be considered as a valid config layer.
|
|
221
|
+
|
|
222
|
+
**Example:** Extend from a github repository
|
|
223
|
+
|
|
224
|
+
```js
|
|
225
|
+
// config.ts
|
|
226
|
+
export default {
|
|
227
|
+
extends: "gh:user/repo",
|
|
228
|
+
};
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Example:** Extend from a github repository with branch and subpath
|
|
232
|
+
|
|
233
|
+
```js
|
|
234
|
+
// config.ts
|
|
235
|
+
export default {
|
|
236
|
+
extends: "gh:user/repo/theme#dev",
|
|
237
|
+
};
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Example:** Extend with clone configuration
|
|
241
|
+
|
|
242
|
+
```js
|
|
243
|
+
// config.ts
|
|
244
|
+
export default {
|
|
245
|
+
extends: ["gh:user/repo", { giget: { auth: process.env.GITHUB_TOKEN } }],
|
|
246
|
+
};
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Refer to [unjs/giget](https://giget.unjs.io) for more information.
|
|
250
|
+
|
|
208
251
|
## Environment-specific configuration
|
|
209
252
|
|
|
210
253
|
Users can define environment-specific configuration using these config keys:
|
package/dist/index.cjs
CHANGED
|
@@ -103,6 +103,7 @@ function interpolate(target, source = {}, parse = (v) => v) {
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
const _normalize = (p) => p?.replace(/\\/g, "/");
|
|
106
107
|
async function loadConfig(options) {
|
|
107
108
|
options.cwd = pathe.resolve(process.cwd(), options.cwd || ".");
|
|
108
109
|
options.name = options.name || "config";
|
|
@@ -195,6 +196,13 @@ async function loadConfig(options) {
|
|
|
195
196
|
if (options.defaults) {
|
|
196
197
|
r.config = defu.defu(r.config, options.defaults);
|
|
197
198
|
}
|
|
199
|
+
if (options.omit$Keys) {
|
|
200
|
+
for (const key in r.config) {
|
|
201
|
+
if (key.startsWith("$")) {
|
|
202
|
+
delete r.config[key];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
198
206
|
return r;
|
|
199
207
|
}
|
|
200
208
|
async function extendConfig(config, options) {
|
|
@@ -249,7 +257,14 @@ async function extendConfig(config, options) {
|
|
|
249
257
|
}
|
|
250
258
|
}
|
|
251
259
|
}
|
|
252
|
-
const
|
|
260
|
+
const GIGET_PREFIXES = [
|
|
261
|
+
"gh:",
|
|
262
|
+
"github:",
|
|
263
|
+
"gitlab:",
|
|
264
|
+
"bitbucket:",
|
|
265
|
+
"https://",
|
|
266
|
+
"http://"
|
|
267
|
+
];
|
|
253
268
|
const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]*($|\/.*)/;
|
|
254
269
|
async function resolveConfig(source, options, sourceOptions = {}) {
|
|
255
270
|
if (options.resolve) {
|
|
@@ -258,12 +273,15 @@ async function resolveConfig(source, options, sourceOptions = {}) {
|
|
|
258
273
|
return res2;
|
|
259
274
|
}
|
|
260
275
|
}
|
|
261
|
-
if (
|
|
276
|
+
if (GIGET_PREFIXES.some((prefix) => source.startsWith(prefix))) {
|
|
262
277
|
const { downloadTemplate } = await import('giget');
|
|
263
278
|
const cloneName = source.replace(/\W+/g, "_").split("_").splice(0, 3).join("_") + "_" + ohash.hash(source);
|
|
264
279
|
let cloneDir;
|
|
265
280
|
const localNodeModules = pathe.resolve(options.cwd, "node_modules");
|
|
266
|
-
|
|
281
|
+
const parentDir = pathe.dirname(options.cwd);
|
|
282
|
+
if (pathe.basename(parentDir) === ".c12") {
|
|
283
|
+
cloneDir = pathe.join(parentDir, cloneName);
|
|
284
|
+
} else if (node_fs.existsSync(localNodeModules)) {
|
|
267
285
|
cloneDir = pathe.join(localNodeModules, ".c12", cloneName);
|
|
268
286
|
} else {
|
|
269
287
|
cloneDir = process.env.XDG_CACHE_HOME ? pathe.resolve(process.env.XDG_CACHE_HOME, "c12", cloneName) : pathe.resolve(node_os.homedir(), ".cache/c12", cloneName);
|
|
@@ -271,7 +289,12 @@ async function resolveConfig(source, options, sourceOptions = {}) {
|
|
|
271
289
|
if (node_fs.existsSync(cloneDir)) {
|
|
272
290
|
await promises.rm(cloneDir, { recursive: true });
|
|
273
291
|
}
|
|
274
|
-
const cloned = await downloadTemplate(source, {
|
|
292
|
+
const cloned = await downloadTemplate(source, {
|
|
293
|
+
dir: cloneDir,
|
|
294
|
+
install: sourceOptions.install,
|
|
295
|
+
...options.giget,
|
|
296
|
+
...sourceOptions.giget
|
|
297
|
+
});
|
|
275
298
|
source = cloned.dir;
|
|
276
299
|
}
|
|
277
300
|
if (NPM_PACKAGE_RE.test(source)) {
|
|
@@ -319,6 +342,8 @@ async function resolveConfig(source, options, sourceOptions = {}) {
|
|
|
319
342
|
if (res.sourceOptions.overrides) {
|
|
320
343
|
res.config = defu.defu(res.sourceOptions.overrides, res.config);
|
|
321
344
|
}
|
|
345
|
+
res.configFile = _normalize(res.configFile);
|
|
346
|
+
res.source = _normalize(res.source);
|
|
322
347
|
return res;
|
|
323
348
|
}
|
|
324
349
|
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { JITI } from 'jiti';
|
|
2
2
|
import { JITIOptions } from 'jiti/dist/types';
|
|
3
|
+
import { DownloadTemplateOptions } from 'giget';
|
|
3
4
|
import { WatchOptions } from 'chokidar';
|
|
4
5
|
import { diff } from 'ohash';
|
|
5
6
|
|
|
@@ -54,6 +55,8 @@ interface C12InputConfig<T extends UserInputConfig = UserInputConfig, MT extends
|
|
|
54
55
|
type InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = C12InputConfig<T, MT> & T;
|
|
55
56
|
interface SourceOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
|
|
56
57
|
meta?: MT;
|
|
58
|
+
giget?: DownloadTemplateOptions;
|
|
59
|
+
install?: boolean;
|
|
57
60
|
overrides?: T;
|
|
58
61
|
[key: string]: any;
|
|
59
62
|
}
|
|
@@ -81,9 +84,11 @@ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT exte
|
|
|
81
84
|
defaults?: T;
|
|
82
85
|
defaultConfig?: T;
|
|
83
86
|
overrides?: T;
|
|
87
|
+
omit$Keys?: boolean;
|
|
84
88
|
resolve?: (id: string, options: LoadConfigOptions<T, MT>) => null | undefined | ResolvedConfig<T, MT> | Promise<ResolvedConfig<T, MT> | undefined | null>;
|
|
85
89
|
jiti?: JITI;
|
|
86
90
|
jitiOptions?: JITIOptions;
|
|
91
|
+
giget?: DownloadTemplateOptions;
|
|
87
92
|
extend?: false | {
|
|
88
93
|
extendKey?: string | string[];
|
|
89
94
|
};
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { JITI } from 'jiti';
|
|
2
2
|
import { JITIOptions } from 'jiti/dist/types';
|
|
3
|
+
import { DownloadTemplateOptions } from 'giget';
|
|
3
4
|
import { WatchOptions } from 'chokidar';
|
|
4
5
|
import { diff } from 'ohash';
|
|
5
6
|
|
|
@@ -54,6 +55,8 @@ interface C12InputConfig<T extends UserInputConfig = UserInputConfig, MT extends
|
|
|
54
55
|
type InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = C12InputConfig<T, MT> & T;
|
|
55
56
|
interface SourceOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
|
|
56
57
|
meta?: MT;
|
|
58
|
+
giget?: DownloadTemplateOptions;
|
|
59
|
+
install?: boolean;
|
|
57
60
|
overrides?: T;
|
|
58
61
|
[key: string]: any;
|
|
59
62
|
}
|
|
@@ -81,9 +84,11 @@ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT exte
|
|
|
81
84
|
defaults?: T;
|
|
82
85
|
defaultConfig?: T;
|
|
83
86
|
overrides?: T;
|
|
87
|
+
omit$Keys?: boolean;
|
|
84
88
|
resolve?: (id: string, options: LoadConfigOptions<T, MT>) => null | undefined | ResolvedConfig<T, MT> | Promise<ResolvedConfig<T, MT> | undefined | null>;
|
|
85
89
|
jiti?: JITI;
|
|
86
90
|
jitiOptions?: JITIOptions;
|
|
91
|
+
giget?: DownloadTemplateOptions;
|
|
87
92
|
extend?: false | {
|
|
88
93
|
extendKey?: string | string[];
|
|
89
94
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { JITI } from 'jiti';
|
|
2
2
|
import { JITIOptions } from 'jiti/dist/types';
|
|
3
|
+
import { DownloadTemplateOptions } from 'giget';
|
|
3
4
|
import { WatchOptions } from 'chokidar';
|
|
4
5
|
import { diff } from 'ohash';
|
|
5
6
|
|
|
@@ -54,6 +55,8 @@ interface C12InputConfig<T extends UserInputConfig = UserInputConfig, MT extends
|
|
|
54
55
|
type InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = C12InputConfig<T, MT> & T;
|
|
55
56
|
interface SourceOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
|
|
56
57
|
meta?: MT;
|
|
58
|
+
giget?: DownloadTemplateOptions;
|
|
59
|
+
install?: boolean;
|
|
57
60
|
overrides?: T;
|
|
58
61
|
[key: string]: any;
|
|
59
62
|
}
|
|
@@ -81,9 +84,11 @@ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT exte
|
|
|
81
84
|
defaults?: T;
|
|
82
85
|
defaultConfig?: T;
|
|
83
86
|
overrides?: T;
|
|
87
|
+
omit$Keys?: boolean;
|
|
84
88
|
resolve?: (id: string, options: LoadConfigOptions<T, MT>) => null | undefined | ResolvedConfig<T, MT> | Promise<ResolvedConfig<T, MT> | undefined | null>;
|
|
85
89
|
jiti?: JITI;
|
|
86
90
|
jitiOptions?: JITIOptions;
|
|
91
|
+
giget?: DownloadTemplateOptions;
|
|
87
92
|
extend?: false | {
|
|
88
93
|
extendKey?: string | string[];
|
|
89
94
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, promises } from 'node:fs';
|
|
2
|
-
import { resolve,
|
|
2
|
+
import { resolve, dirname, basename, join, extname } from 'pathe';
|
|
3
3
|
import * as dotenv from 'dotenv';
|
|
4
4
|
import { rm } from 'node:fs/promises';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
@@ -83,6 +83,7 @@ function interpolate(target, source = {}, parse = (v) => v) {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
const _normalize = (p) => p?.replace(/\\/g, "/");
|
|
86
87
|
async function loadConfig(options) {
|
|
87
88
|
options.cwd = resolve(process.cwd(), options.cwd || ".");
|
|
88
89
|
options.name = options.name || "config";
|
|
@@ -175,6 +176,13 @@ async function loadConfig(options) {
|
|
|
175
176
|
if (options.defaults) {
|
|
176
177
|
r.config = defu(r.config, options.defaults);
|
|
177
178
|
}
|
|
179
|
+
if (options.omit$Keys) {
|
|
180
|
+
for (const key in r.config) {
|
|
181
|
+
if (key.startsWith("$")) {
|
|
182
|
+
delete r.config[key];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
178
186
|
return r;
|
|
179
187
|
}
|
|
180
188
|
async function extendConfig(config, options) {
|
|
@@ -229,7 +237,14 @@ async function extendConfig(config, options) {
|
|
|
229
237
|
}
|
|
230
238
|
}
|
|
231
239
|
}
|
|
232
|
-
const
|
|
240
|
+
const GIGET_PREFIXES = [
|
|
241
|
+
"gh:",
|
|
242
|
+
"github:",
|
|
243
|
+
"gitlab:",
|
|
244
|
+
"bitbucket:",
|
|
245
|
+
"https://",
|
|
246
|
+
"http://"
|
|
247
|
+
];
|
|
233
248
|
const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]*($|\/.*)/;
|
|
234
249
|
async function resolveConfig(source, options, sourceOptions = {}) {
|
|
235
250
|
if (options.resolve) {
|
|
@@ -238,12 +253,15 @@ async function resolveConfig(source, options, sourceOptions = {}) {
|
|
|
238
253
|
return res2;
|
|
239
254
|
}
|
|
240
255
|
}
|
|
241
|
-
if (
|
|
256
|
+
if (GIGET_PREFIXES.some((prefix) => source.startsWith(prefix))) {
|
|
242
257
|
const { downloadTemplate } = await import('giget');
|
|
243
258
|
const cloneName = source.replace(/\W+/g, "_").split("_").splice(0, 3).join("_") + "_" + hash(source);
|
|
244
259
|
let cloneDir;
|
|
245
260
|
const localNodeModules = resolve(options.cwd, "node_modules");
|
|
246
|
-
|
|
261
|
+
const parentDir = dirname(options.cwd);
|
|
262
|
+
if (basename(parentDir) === ".c12") {
|
|
263
|
+
cloneDir = join(parentDir, cloneName);
|
|
264
|
+
} else if (existsSync(localNodeModules)) {
|
|
247
265
|
cloneDir = join(localNodeModules, ".c12", cloneName);
|
|
248
266
|
} else {
|
|
249
267
|
cloneDir = process.env.XDG_CACHE_HOME ? resolve(process.env.XDG_CACHE_HOME, "c12", cloneName) : resolve(homedir(), ".cache/c12", cloneName);
|
|
@@ -251,7 +269,12 @@ async function resolveConfig(source, options, sourceOptions = {}) {
|
|
|
251
269
|
if (existsSync(cloneDir)) {
|
|
252
270
|
await rm(cloneDir, { recursive: true });
|
|
253
271
|
}
|
|
254
|
-
const cloned = await downloadTemplate(source, {
|
|
272
|
+
const cloned = await downloadTemplate(source, {
|
|
273
|
+
dir: cloneDir,
|
|
274
|
+
install: sourceOptions.install,
|
|
275
|
+
...options.giget,
|
|
276
|
+
...sourceOptions.giget
|
|
277
|
+
});
|
|
255
278
|
source = cloned.dir;
|
|
256
279
|
}
|
|
257
280
|
if (NPM_PACKAGE_RE.test(source)) {
|
|
@@ -299,6 +322,8 @@ async function resolveConfig(source, options, sourceOptions = {}) {
|
|
|
299
322
|
if (res.sourceOptions.overrides) {
|
|
300
323
|
res.config = defu(res.sourceOptions.overrides, res.config);
|
|
301
324
|
}
|
|
325
|
+
res.configFile = _normalize(res.configFile);
|
|
326
|
+
res.source = _normalize(res.source);
|
|
302
327
|
return res;
|
|
303
328
|
}
|
|
304
329
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c12",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Smart Config Loader",
|
|
5
5
|
"repository": "unjs/c12",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,16 +25,16 @@
|
|
|
25
25
|
"lint": "eslint --ext .ts,.js,.mjs,.cjs . && prettier -c src test",
|
|
26
26
|
"lint:fix": "eslint --ext .ts,.js,.mjs,.cjs . --fix && prettier -w src test",
|
|
27
27
|
"prepack": "unbuild",
|
|
28
|
-
"release": "changelogen --release && npm publish && git push --follow-tags",
|
|
28
|
+
"release": "pnpm test && changelogen --release && npm publish && git push --follow-tags",
|
|
29
29
|
"test": "pnpm lint && vitest run --coverage && pnpm test:types",
|
|
30
30
|
"test:types": "tsc --noEmit"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"chokidar": "^3.5.3",
|
|
34
|
-
"defu": "^6.1.
|
|
34
|
+
"defu": "^6.1.3",
|
|
35
35
|
"dotenv": "^16.3.1",
|
|
36
|
-
"giget": "^1.1
|
|
37
|
-
"jiti": "^1.
|
|
36
|
+
"giget": "^1.2.1",
|
|
37
|
+
"jiti": "^1.21.0",
|
|
38
38
|
"mlly": "^1.4.2",
|
|
39
39
|
"ohash": "^1.1.3",
|
|
40
40
|
"pathe": "^1.1.1",
|
|
@@ -43,15 +43,16 @@
|
|
|
43
43
|
"rc9": "^2.1.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@
|
|
46
|
+
"@types/node": "^20.10.5",
|
|
47
|
+
"@vitest/coverage-v8": "^1.1.0",
|
|
47
48
|
"changelogen": "^0.5.5",
|
|
48
|
-
"eslint": "^8.
|
|
49
|
+
"eslint": "^8.56.0",
|
|
49
50
|
"eslint-config-unjs": "^0.2.1",
|
|
50
51
|
"expect-type": "^0.17.3",
|
|
51
|
-
"prettier": "^3.
|
|
52
|
-
"typescript": "^5.
|
|
52
|
+
"prettier": "^3.1.1",
|
|
53
|
+
"typescript": "^5.3.3",
|
|
53
54
|
"unbuild": "^2.0.0",
|
|
54
|
-
"vitest": "^
|
|
55
|
+
"vitest": "^1.1.0"
|
|
55
56
|
},
|
|
56
|
-
"packageManager": "pnpm@8.
|
|
57
|
+
"packageManager": "pnpm@8.13.1"
|
|
57
58
|
}
|