c12 1.2.0 → 1.3.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 +11 -10
- package/dist/index.cjs +24 -10
- package/dist/index.d.ts +23 -24
- package/dist/index.mjs +17 -8
- package/package.json +15 -13
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# c12
|
|
1
|
+
# ⚙️ c12
|
|
2
2
|
|
|
3
3
|
[![npm version][npm-version-src]][npm-version-href]
|
|
4
4
|
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
|
-
[![Github Actions][github-actions-src]][github-actions-href]
|
|
6
5
|
[![Codecov][codecov-src]][codecov-href]
|
|
6
|
+
[![License][license-src]][license-href]
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Smart Configuration Loader.
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
@@ -13,8 +13,9 @@
|
|
|
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
|
-
-
|
|
17
|
-
-
|
|
16
|
+
- Reads config from the nearest `package.json` file
|
|
17
|
+
- [Extends configurations](https://github.com/unjs/c12#extending-configuration) from multiple local or git sources
|
|
18
|
+
- Overwrite with [environment-specific configuration](#environment-specific-configuration)
|
|
18
19
|
|
|
19
20
|
## Usage
|
|
20
21
|
|
|
@@ -246,11 +247,11 @@ Made with 💛 Published under [MIT License](./LICENSE).
|
|
|
246
247
|
|
|
247
248
|
<!-- Badges -->
|
|
248
249
|
|
|
249
|
-
[npm-version-src]: https://img.shields.io/npm/v/c12?style=flat
|
|
250
|
+
[npm-version-src]: https://img.shields.io/npm/v/c12?style=flat&colorA=18181B&colorB=F0DB4F
|
|
250
251
|
[npm-version-href]: https://npmjs.com/package/c12
|
|
251
|
-
[npm-downloads-src]: https://img.shields.io/npm/dm/c12?style=flat
|
|
252
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/c12?style=flat&colorA=18181B&colorB=F0DB4F
|
|
252
253
|
[npm-downloads-href]: https://npmjs.com/package/c12
|
|
253
|
-
[
|
|
254
|
-
[github-actions-href]: https://github.com/unjs/c12/actions?query=workflow%3Aci
|
|
255
|
-
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/c12/main?style=flat-square
|
|
254
|
+
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/c12/main?style=flat&colorA=18181B&colorB=F0DB4F
|
|
256
255
|
[codecov-href]: https://codecov.io/gh/unjs/c12
|
|
256
|
+
[license-src]: https://img.shields.io/github/license/unjs/c12.svg?style=flat&colorA=18181B&colorB=F0DB4F
|
|
257
|
+
[license-href]: https://github.com/unjs/c12/blob/main/LICENSE
|
package/dist/index.cjs
CHANGED
|
@@ -10,7 +10,10 @@ const rc9 = require('rc9');
|
|
|
10
10
|
const defu = require('defu');
|
|
11
11
|
const pkgTypes = require('pkg-types');
|
|
12
12
|
|
|
13
|
-
function
|
|
13
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
14
|
+
|
|
15
|
+
function _interopNamespaceCompat(e) {
|
|
16
|
+
if (e && typeof e === 'object' && 'default' in e) return e;
|
|
14
17
|
const n = Object.create(null);
|
|
15
18
|
if (e) {
|
|
16
19
|
for (const k in e) {
|
|
@@ -21,8 +24,9 @@ function _interopNamespaceDefault(e) {
|
|
|
21
24
|
return n;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
const dotenv__namespace = /*#__PURE__*/
|
|
25
|
-
const
|
|
27
|
+
const dotenv__namespace = /*#__PURE__*/_interopNamespaceCompat(dotenv);
|
|
28
|
+
const createJiti__default = /*#__PURE__*/_interopDefaultCompat(createJiti);
|
|
29
|
+
const rc9__namespace = /*#__PURE__*/_interopNamespaceCompat(rc9);
|
|
26
30
|
|
|
27
31
|
async function setupDotenv(options) {
|
|
28
32
|
const targetEnvironment = options.env ?? process.env;
|
|
@@ -46,7 +50,7 @@ async function loadDotenv(options) {
|
|
|
46
50
|
const parsed = dotenv__namespace.parse(await node_fs.promises.readFile(dotenvFile, "utf8"));
|
|
47
51
|
Object.assign(environment, parsed);
|
|
48
52
|
}
|
|
49
|
-
if (!options.env
|
|
53
|
+
if (!options.env?._applied) {
|
|
50
54
|
Object.assign(environment, options.env);
|
|
51
55
|
environment._applied = true;
|
|
52
56
|
}
|
|
@@ -67,15 +71,15 @@ function interpolate(target, source = {}, parse = (v) => v) {
|
|
|
67
71
|
return parse(
|
|
68
72
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
69
73
|
matches.reduce((newValue, match) => {
|
|
70
|
-
const parts = /(.?)\${?([\w:]+)?}?/g.exec(match);
|
|
74
|
+
const parts = /(.?)\${?([\w:]+)?}?/g.exec(match) || [];
|
|
71
75
|
const prefix = parts[1];
|
|
72
76
|
let value2, replacePart;
|
|
73
77
|
if (prefix === "\\") {
|
|
74
|
-
replacePart = parts[0];
|
|
78
|
+
replacePart = parts[0] || "";
|
|
75
79
|
value2 = replacePart.replace("\\$", "$");
|
|
76
80
|
} else {
|
|
77
81
|
const key = parts[2];
|
|
78
|
-
replacePart = parts[0].slice(prefix.length);
|
|
82
|
+
replacePart = (parts[0] || "").slice(prefix.length);
|
|
79
83
|
if (parents.includes(key)) {
|
|
80
84
|
console.warn(
|
|
81
85
|
`Please avoid recursive environment variables ( loop: ${parents.join(
|
|
@@ -108,7 +112,7 @@ async function loadConfig(options) {
|
|
|
108
112
|
...options.extend
|
|
109
113
|
};
|
|
110
114
|
}
|
|
111
|
-
options.jiti = options.jiti ||
|
|
115
|
+
options.jiti = options.jiti || createJiti__default(void 0, {
|
|
112
116
|
interopDefault: true,
|
|
113
117
|
requireCache: false,
|
|
114
118
|
esmResolve: true,
|
|
@@ -258,7 +262,7 @@ async function resolveConfig(source, options, sourceOptions = {}) {
|
|
|
258
262
|
const name = gitRepo.replace(/[#/:@\\]/g, "_");
|
|
259
263
|
const tmpDir = process.env.XDG_CACHE_HOME ? pathe.resolve(process.env.XDG_CACHE_HOME, "c12", name) : pathe.resolve(node_os.homedir(), ".cache/c12", name);
|
|
260
264
|
if (node_fs.existsSync(tmpDir)) {
|
|
261
|
-
await promises.
|
|
265
|
+
await promises.rm(tmpDir, { recursive: true });
|
|
262
266
|
}
|
|
263
267
|
const cloned = await downloadTemplate(source, { dir: tmpDir });
|
|
264
268
|
source = cloned.dir;
|
|
@@ -274,7 +278,12 @@ async function resolveConfig(source, options, sourceOptions = {}) {
|
|
|
274
278
|
if (isDir) {
|
|
275
279
|
source = options.configFile;
|
|
276
280
|
}
|
|
277
|
-
const res = {
|
|
281
|
+
const res = {
|
|
282
|
+
config: void 0,
|
|
283
|
+
cwd,
|
|
284
|
+
source,
|
|
285
|
+
sourceOptions
|
|
286
|
+
};
|
|
278
287
|
try {
|
|
279
288
|
res.configFile = options.jiti.resolve(pathe.resolve(cwd, source), {
|
|
280
289
|
paths: [cwd]
|
|
@@ -305,6 +314,11 @@ async function resolveConfig(source, options, sourceOptions = {}) {
|
|
|
305
314
|
return res;
|
|
306
315
|
}
|
|
307
316
|
|
|
317
|
+
function createDefineConfig() {
|
|
318
|
+
return (input) => input;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
exports.createDefineConfig = createDefineConfig;
|
|
308
322
|
exports.loadConfig = loadConfig;
|
|
309
323
|
exports.loadDotenv = loadDotenv;
|
|
310
324
|
exports.setupDotenv = setupDotenv;
|
package/dist/index.d.ts
CHANGED
|
@@ -37,41 +37,37 @@ 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
|
-
type UserInputConfig = Record<string, any>;
|
|
41
40
|
interface ConfigLayerMeta {
|
|
42
41
|
name?: string;
|
|
43
42
|
[key: string]: any;
|
|
44
43
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
$
|
|
48
|
-
$
|
|
49
|
-
$
|
|
50
|
-
$
|
|
51
|
-
|
|
52
|
-
interface InputConfig extends C12InputConfig, UserInputConfig {
|
|
44
|
+
type UserInputConfig = Record<string, any>;
|
|
45
|
+
interface C12InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
|
|
46
|
+
$test?: T;
|
|
47
|
+
$development?: T;
|
|
48
|
+
$production?: T;
|
|
49
|
+
$env?: Record<string, T>;
|
|
50
|
+
$meta?: MT;
|
|
53
51
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
type InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = C12InputConfig<T, MT> & T;
|
|
53
|
+
interface SourceOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
|
|
54
|
+
meta?: MT;
|
|
55
|
+
overrides?: T;
|
|
57
56
|
[key: string]: any;
|
|
58
57
|
}
|
|
59
|
-
interface ConfigLayer<T extends
|
|
58
|
+
interface ConfigLayer<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
|
|
60
59
|
config: T | null;
|
|
61
60
|
source?: string;
|
|
62
|
-
sourceOptions?: SourceOptions
|
|
63
|
-
meta?:
|
|
61
|
+
sourceOptions?: SourceOptions<T, MT>;
|
|
62
|
+
meta?: MT;
|
|
64
63
|
cwd?: string;
|
|
65
64
|
configFile?: string;
|
|
66
65
|
}
|
|
67
|
-
interface ResolvedConfig<T extends
|
|
68
|
-
layers?: ConfigLayer<T>[];
|
|
66
|
+
interface ResolvedConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> extends ConfigLayer<T, MT> {
|
|
67
|
+
layers?: ConfigLayer<T, MT>[];
|
|
69
68
|
cwd?: string;
|
|
70
69
|
}
|
|
71
|
-
interface
|
|
72
|
-
cwd: string;
|
|
73
|
-
}
|
|
74
|
-
interface LoadConfigOptions<T extends InputConfig = InputConfig> {
|
|
70
|
+
interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
|
|
75
71
|
name?: string;
|
|
76
72
|
cwd?: string;
|
|
77
73
|
configFile?: string;
|
|
@@ -83,13 +79,16 @@ interface LoadConfigOptions<T extends InputConfig = InputConfig> {
|
|
|
83
79
|
defaults?: T;
|
|
84
80
|
defaultConfig?: T;
|
|
85
81
|
overrides?: T;
|
|
86
|
-
resolve?: (id: string, options: LoadConfigOptions) => null | ResolvedConfig | Promise<ResolvedConfig | null>;
|
|
82
|
+
resolve?: (id: string, options: LoadConfigOptions<T, MT>) => null | undefined | ResolvedConfig<T, MT> | Promise<ResolvedConfig<T, MT> | undefined | null>;
|
|
87
83
|
jiti?: JITI;
|
|
88
84
|
jitiOptions?: JITIOptions;
|
|
89
85
|
extend?: false | {
|
|
90
86
|
extendKey?: string | string[];
|
|
91
87
|
};
|
|
92
88
|
}
|
|
93
|
-
|
|
89
|
+
type DefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = (input: InputConfig<T, MT>) => InputConfig<T, MT>;
|
|
90
|
+
declare function createDefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(): DefineConfig<T, MT>;
|
|
91
|
+
|
|
92
|
+
declare function loadConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: LoadConfigOptions<T, MT>): Promise<ResolvedConfig<T, MT>>;
|
|
94
93
|
|
|
95
|
-
export { C12InputConfig, ConfigLayer, ConfigLayerMeta, DotenvOptions, Env, InputConfig, LoadConfigOptions,
|
|
94
|
+
export { C12InputConfig, ConfigLayer, ConfigLayerMeta, DefineConfig, DotenvOptions, Env, InputConfig, LoadConfigOptions, ResolvedConfig, SourceOptions, UserInputConfig, createDefineConfig, loadConfig, loadDotenv, setupDotenv };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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 { rm } from 'node:fs/promises';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import createJiti from 'jiti';
|
|
7
7
|
import * as rc9 from 'rc9';
|
|
@@ -30,7 +30,7 @@ async function loadDotenv(options) {
|
|
|
30
30
|
const parsed = dotenv.parse(await promises.readFile(dotenvFile, "utf8"));
|
|
31
31
|
Object.assign(environment, parsed);
|
|
32
32
|
}
|
|
33
|
-
if (!options.env
|
|
33
|
+
if (!options.env?._applied) {
|
|
34
34
|
Object.assign(environment, options.env);
|
|
35
35
|
environment._applied = true;
|
|
36
36
|
}
|
|
@@ -51,15 +51,15 @@ function interpolate(target, source = {}, parse = (v) => v) {
|
|
|
51
51
|
return parse(
|
|
52
52
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
53
53
|
matches.reduce((newValue, match) => {
|
|
54
|
-
const parts = /(.?)\${?([\w:]+)?}?/g.exec(match);
|
|
54
|
+
const parts = /(.?)\${?([\w:]+)?}?/g.exec(match) || [];
|
|
55
55
|
const prefix = parts[1];
|
|
56
56
|
let value2, replacePart;
|
|
57
57
|
if (prefix === "\\") {
|
|
58
|
-
replacePart = parts[0];
|
|
58
|
+
replacePart = parts[0] || "";
|
|
59
59
|
value2 = replacePart.replace("\\$", "$");
|
|
60
60
|
} else {
|
|
61
61
|
const key = parts[2];
|
|
62
|
-
replacePart = parts[0].slice(prefix.length);
|
|
62
|
+
replacePart = (parts[0] || "").slice(prefix.length);
|
|
63
63
|
if (parents.includes(key)) {
|
|
64
64
|
console.warn(
|
|
65
65
|
`Please avoid recursive environment variables ( loop: ${parents.join(
|
|
@@ -242,7 +242,7 @@ async function resolveConfig(source, options, sourceOptions = {}) {
|
|
|
242
242
|
const name = gitRepo.replace(/[#/:@\\]/g, "_");
|
|
243
243
|
const tmpDir = process.env.XDG_CACHE_HOME ? resolve(process.env.XDG_CACHE_HOME, "c12", name) : resolve(homedir(), ".cache/c12", name);
|
|
244
244
|
if (existsSync(tmpDir)) {
|
|
245
|
-
await
|
|
245
|
+
await rm(tmpDir, { recursive: true });
|
|
246
246
|
}
|
|
247
247
|
const cloned = await downloadTemplate(source, { dir: tmpDir });
|
|
248
248
|
source = cloned.dir;
|
|
@@ -258,7 +258,12 @@ async function resolveConfig(source, options, sourceOptions = {}) {
|
|
|
258
258
|
if (isDir) {
|
|
259
259
|
source = options.configFile;
|
|
260
260
|
}
|
|
261
|
-
const res = {
|
|
261
|
+
const res = {
|
|
262
|
+
config: void 0,
|
|
263
|
+
cwd,
|
|
264
|
+
source,
|
|
265
|
+
sourceOptions
|
|
266
|
+
};
|
|
262
267
|
try {
|
|
263
268
|
res.configFile = options.jiti.resolve(resolve(cwd, source), {
|
|
264
269
|
paths: [cwd]
|
|
@@ -289,4 +294,8 @@ async function resolveConfig(source, options, sourceOptions = {}) {
|
|
|
289
294
|
return res;
|
|
290
295
|
}
|
|
291
296
|
|
|
292
|
-
|
|
297
|
+
function createDefineConfig() {
|
|
298
|
+
return (input) => input;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export { createDefineConfig, loadConfig, loadDotenv, setupDotenv };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c12",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Smart Config Loader",
|
|
5
5
|
"repository": "unjs/c12",
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,27 +26,29 @@
|
|
|
26
26
|
"lint:fix": "eslint --ext .ts,.js,.mjs,.cjs . --fix && prettier -w src test",
|
|
27
27
|
"prepack": "unbuild",
|
|
28
28
|
"release": "changelogen --release && npm publish && git push --follow-tags",
|
|
29
|
-
"test": "vitest run --coverage"
|
|
29
|
+
"test": "vitest run --coverage && pnpm test:types",
|
|
30
|
+
"test:types": "tsc --noEmit"
|
|
30
31
|
},
|
|
31
32
|
"dependencies": {
|
|
32
33
|
"defu": "^6.1.2",
|
|
33
34
|
"dotenv": "^16.0.3",
|
|
34
35
|
"giget": "^1.1.2",
|
|
35
|
-
"jiti": "^1.
|
|
36
|
+
"jiti": "^1.18.2",
|
|
36
37
|
"mlly": "^1.2.0",
|
|
37
38
|
"pathe": "^1.1.0",
|
|
38
39
|
"pkg-types": "^1.0.2",
|
|
39
|
-
"rc9": "^2.0
|
|
40
|
+
"rc9": "^2.1.0"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
|
-
"@vitest/coverage-c8": "^0.
|
|
43
|
-
"changelogen": "^0.5.
|
|
44
|
-
"eslint": "^8.
|
|
43
|
+
"@vitest/coverage-c8": "^0.30.1",
|
|
44
|
+
"changelogen": "^0.5.3",
|
|
45
|
+
"eslint": "^8.38.0",
|
|
45
46
|
"eslint-config-unjs": "^0.1.0",
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
47
|
+
"expect-type": "^0.15.0",
|
|
48
|
+
"prettier": "^2.8.7",
|
|
49
|
+
"typescript": "^5.0.4",
|
|
50
|
+
"unbuild": "^1.2.1",
|
|
51
|
+
"vitest": "^0.30.1"
|
|
50
52
|
},
|
|
51
|
-
"packageManager": "pnpm@
|
|
52
|
-
}
|
|
53
|
+
"packageManager": "pnpm@8.2.0"
|
|
54
|
+
}
|