c12 1.5.1 → 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 CHANGED
@@ -5,7 +5,7 @@
5
5
  [![Codecov][codecov-src]][codecov-href]
6
6
  [![License][license-src]][license-href]
7
7
 
8
- Smart Configuration Loader.
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.
@@ -220,7 +224,7 @@ In the repo, there should be a `config.ts` (or `config.{name}.ts`) file to be co
220
224
  ```js
221
225
  // config.ts
222
226
  export default {
223
- extends: "gh:repo/owner",
227
+ extends: "gh:user/repo",
224
228
  };
225
229
  ```
226
230
 
@@ -229,19 +233,21 @@ export default {
229
233
  ```js
230
234
  // config.ts
231
235
  export default {
232
- extends: "gh:repo/owner/theme#dev",
236
+ extends: "gh:user/repo/theme#dev",
233
237
  };
234
238
  ```
235
239
 
236
- **Example:** Extend with custom configuration ([giget](https://github.com/unjs/giget) options)
240
+ **Example:** Extend with clone configuration
237
241
 
238
242
  ```js
239
243
  // config.ts
240
244
  export default {
241
- extends: ["gh:repo/owner", { giget: { auth: process.env.GITHUB_TOKEN } }],
245
+ extends: ["gh:user/repo", { giget: { auth: process.env.GITHUB_TOKEN } }],
242
246
  };
243
247
  ```
244
248
 
249
+ Refer to [unjs/giget](https://giget.unjs.io) for more information.
250
+
245
251
  ## Environment-specific configuration
246
252
 
247
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 GIT_PREFIXES = ["gh:", "github:", "gitlab:", "bitbucket:", "https://"];
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 (GIT_PREFIXES.some((prefix) => source.startsWith(prefix))) {
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
- if (node_fs.existsSync(localNodeModules)) {
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);
@@ -273,6 +291,7 @@ async function resolveConfig(source, options, sourceOptions = {}) {
273
291
  }
274
292
  const cloned = await downloadTemplate(source, {
275
293
  dir: cloneDir,
294
+ install: sourceOptions.install,
276
295
  ...options.giget,
277
296
  ...sourceOptions.giget
278
297
  });
@@ -323,6 +342,8 @@ async function resolveConfig(source, options, sourceOptions = {}) {
323
342
  if (res.sourceOptions.overrides) {
324
343
  res.config = defu.defu(res.sourceOptions.overrides, res.config);
325
344
  }
345
+ res.configFile = _normalize(res.configFile);
346
+ res.source = _normalize(res.source);
326
347
  return res;
327
348
  }
328
349
 
package/dist/index.d.cts CHANGED
@@ -56,6 +56,7 @@ type InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigL
56
56
  interface SourceOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
57
57
  meta?: MT;
58
58
  giget?: DownloadTemplateOptions;
59
+ install?: boolean;
59
60
  overrides?: T;
60
61
  [key: string]: any;
61
62
  }
@@ -83,6 +84,7 @@ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT exte
83
84
  defaults?: T;
84
85
  defaultConfig?: T;
85
86
  overrides?: T;
87
+ omit$Keys?: boolean;
86
88
  resolve?: (id: string, options: LoadConfigOptions<T, MT>) => null | undefined | ResolvedConfig<T, MT> | Promise<ResolvedConfig<T, MT> | undefined | null>;
87
89
  jiti?: JITI;
88
90
  jitiOptions?: JITIOptions;
package/dist/index.d.mts CHANGED
@@ -56,6 +56,7 @@ type InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigL
56
56
  interface SourceOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
57
57
  meta?: MT;
58
58
  giget?: DownloadTemplateOptions;
59
+ install?: boolean;
59
60
  overrides?: T;
60
61
  [key: string]: any;
61
62
  }
@@ -83,6 +84,7 @@ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT exte
83
84
  defaults?: T;
84
85
  defaultConfig?: T;
85
86
  overrides?: T;
87
+ omit$Keys?: boolean;
86
88
  resolve?: (id: string, options: LoadConfigOptions<T, MT>) => null | undefined | ResolvedConfig<T, MT> | Promise<ResolvedConfig<T, MT> | undefined | null>;
87
89
  jiti?: JITI;
88
90
  jitiOptions?: JITIOptions;
package/dist/index.d.ts CHANGED
@@ -56,6 +56,7 @@ type InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigL
56
56
  interface SourceOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
57
57
  meta?: MT;
58
58
  giget?: DownloadTemplateOptions;
59
+ install?: boolean;
59
60
  overrides?: T;
60
61
  [key: string]: any;
61
62
  }
@@ -83,6 +84,7 @@ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT exte
83
84
  defaults?: T;
84
85
  defaultConfig?: T;
85
86
  overrides?: T;
87
+ omit$Keys?: boolean;
86
88
  resolve?: (id: string, options: LoadConfigOptions<T, MT>) => null | undefined | ResolvedConfig<T, MT> | Promise<ResolvedConfig<T, MT> | undefined | null>;
87
89
  jiti?: JITI;
88
90
  jitiOptions?: JITIOptions;
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { existsSync, promises } from 'node:fs';
2
- import { resolve, join, extname, basename, dirname } from 'pathe';
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 GIT_PREFIXES = ["gh:", "github:", "gitlab:", "bitbucket:", "https://"];
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 (GIT_PREFIXES.some((prefix) => source.startsWith(prefix))) {
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
- if (existsSync(localNodeModules)) {
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);
@@ -253,6 +271,7 @@ async function resolveConfig(source, options, sourceOptions = {}) {
253
271
  }
254
272
  const cloned = await downloadTemplate(source, {
255
273
  dir: cloneDir,
274
+ install: sourceOptions.install,
256
275
  ...options.giget,
257
276
  ...sourceOptions.giget
258
277
  });
@@ -303,6 +322,8 @@ async function resolveConfig(source, options, sourceOptions = {}) {
303
322
  if (res.sourceOptions.overrides) {
304
323
  res.config = defu(res.sourceOptions.overrides, res.config);
305
324
  }
325
+ res.configFile = _normalize(res.configFile);
326
+ res.source = _normalize(res.source);
306
327
  return res;
307
328
  }
308
329
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c12",
3
- "version": "1.5.1",
3
+ "version": "1.6.0",
4
4
  "description": "Smart Config Loader",
5
5
  "repository": "unjs/c12",
6
6
  "license": "MIT",
@@ -31,10 +31,10 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "chokidar": "^3.5.3",
34
- "defu": "^6.1.2",
34
+ "defu": "^6.1.3",
35
35
  "dotenv": "^16.3.1",
36
- "giget": "^1.1.3",
37
- "jiti": "^1.20.0",
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
- "@vitest/coverage-v8": "^0.34.6",
46
+ "@types/node": "^20.10.5",
47
+ "@vitest/coverage-v8": "^1.1.0",
47
48
  "changelogen": "^0.5.5",
48
- "eslint": "^8.51.0",
49
+ "eslint": "^8.56.0",
49
50
  "eslint-config-unjs": "^0.2.1",
50
51
  "expect-type": "^0.17.3",
51
- "prettier": "^3.0.3",
52
- "typescript": "^5.2.2",
52
+ "prettier": "^3.1.1",
53
+ "typescript": "^5.3.3",
53
54
  "unbuild": "^2.0.0",
54
- "vitest": "^0.34.6"
55
+ "vitest": "^1.1.0"
55
56
  },
56
- "packageManager": "pnpm@8.8.0"
57
+ "packageManager": "pnpm@8.13.1"
57
58
  }