c12 1.7.0 → 1.9.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
@@ -1,16 +1,20 @@
1
1
  # ⚙️ c12
2
2
 
3
- [![npm version][npm-version-src]][npm-version-href]
4
- [![npm downloads][npm-downloads-src]][npm-downloads-href]
5
- [![Codecov][codecov-src]][codecov-href]
6
- [![License][license-src]][license-href]
3
+ <!-- automd:badges color=yellow codecov -->
4
+
5
+ [![npm version](https://img.shields.io/npm/v/c12?color=yellow)](https://npmjs.com/package/c12)
6
+ [![npm downloads](https://img.shields.io/npm/dm/c12?color=yellow)](https://npmjs.com/package/c12)
7
+ [![codecov](https://img.shields.io/codecov/c/gh/unjs/c12?color=yellow)](https://codecov.io/gh/unjs/c12)
8
+
9
+ <!-- /automd -->
7
10
 
8
11
  c12 (pronounced as /siːtwelv/, like c-twelve) is a smart configuration loader.
9
12
 
10
- ## Features
13
+ ## Features
11
14
 
12
- - `.js`, `.ts`, `.cjs`, `.mjs` config loader with [unjs/jiti](https://github.com/unjs/jiti)
13
- - `.json`, `.json5` and `.jsonc` config support.
15
+ - `.js`, `.ts`, `.mjs`, `.cjs`, `.mts`, `.cts` `.json` config loader with [unjs/jiti](https://jiti.unjs.io)
16
+ - `.jsonc`, `.json5`, `.yaml`, `.yml`, `.toml` config loader with [unjs/confbox](https://confbox.unjs.io)
17
+ - `.config/` directory support following [config dir proposal](https://github.com/pi0/config-dir)
14
18
  - `.rc` config support with [unjs/rc9](https://github.com/unjs/rc9)
15
19
  - `.env` support with [dotenv](https://www.npmjs.com/package/dotenv)
16
20
  - Multiple sources merged with [unjs/defu](https://github.com/unjs/defu)
@@ -19,21 +23,40 @@ c12 (pronounced as /siːtwelv/, like c-twelve) is a smart configuration loader.
19
23
  - Overwrite with [environment-specific configuration](#environment-specific-configuration)
20
24
  - Config watcher with auto-reload and HMR support
21
25
 
26
+ ## 🦴 Used by
27
+
28
+ - [Nuxt](https://nuxt.com/)
29
+ - [Nitro](https://nitro.unjs.io/)
30
+ - [Unbuild](https://unbuild.unjs.io)
31
+ - [Automd](https://automd.unjs.io)
32
+ - [Changelogen](https://changelogen.unjs.io)
33
+ - [RemixKit](https://github.com/jrestall/remix-kit)
34
+
22
35
  ## Usage
23
36
 
24
37
  Install package:
25
38
 
39
+ <!-- automd:pm-install -->
40
+
26
41
  ```sh
42
+ # ✨ Auto-detect
43
+ npx nypm i c12@^1.7.0
44
+
27
45
  # npm
28
- npm install c12
46
+ npm install c12@^1.7.0
29
47
 
30
48
  # yarn
31
- yarn add c12
49
+ yarn add c12@^1.7.0
32
50
 
33
51
  # pnpm
34
- pnpm install c12
52
+ pnpm install c12@^1.7.0
53
+
54
+ # bun
55
+ bun install c12@^1.7.0
35
56
  ```
36
57
 
58
+ <!-- /automd -->
59
+
37
60
  Import:
38
61
 
39
62
  ```js
package/dist/index.cjs CHANGED
@@ -10,7 +10,6 @@ const rc9 = require('rc9');
10
10
  const defu = require('defu');
11
11
  const ohash = require('ohash');
12
12
  const pkgTypes = require('pkg-types');
13
- const chokidar = require('chokidar');
14
13
  const perfectDebounce = require('perfect-debounce');
15
14
 
16
15
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
@@ -104,6 +103,29 @@ function interpolate(target, source = {}, parse = (v) => v) {
104
103
  }
105
104
 
106
105
  const _normalize = (p) => p?.replace(/\\/g, "/");
106
+ const ASYNC_LOADERS = {
107
+ ".yaml": () => import('confbox/yaml').then((r) => r.parseYAML),
108
+ ".yml": () => import('confbox/yaml').then((r) => r.parseYAML),
109
+ ".jsonc": () => import('confbox/jsonc').then((r) => r.parseJSONC),
110
+ ".json5": () => import('confbox/json5').then((r) => r.parseJSON5),
111
+ ".toml": () => import('confbox/toml').then((r) => r.parseTOML)
112
+ };
113
+ const SUPPORTED_EXTENSIONS = [
114
+ // with jiti
115
+ ".js",
116
+ ".ts",
117
+ ".mjs",
118
+ ".cjs",
119
+ ".mts",
120
+ ".cts",
121
+ ".json",
122
+ // with confbox
123
+ ".jsonc",
124
+ ".json5",
125
+ ".yaml",
126
+ ".yml",
127
+ ".toml"
128
+ ];
107
129
  async function loadConfig(options) {
108
130
  options.cwd = pathe.resolve(process.cwd(), options.cwd || ".");
109
131
  options.name = options.name || "config";
@@ -120,17 +142,7 @@ async function loadConfig(options) {
120
142
  interopDefault: true,
121
143
  requireCache: false,
122
144
  esmResolve: true,
123
- extensions: [
124
- ".js",
125
- ".mjs",
126
- ".cjs",
127
- ".ts",
128
- ".mts",
129
- ".cts",
130
- ".json",
131
- ".jsonc",
132
- ".json5"
133
- ],
145
+ extensions: [...SUPPORTED_EXTENSIONS],
134
146
  ...options.jitiOptions
135
147
  });
136
148
  const r = {
@@ -151,24 +163,17 @@ async function loadConfig(options) {
151
163
  }
152
164
  const configRC = {};
153
165
  if (options.rcFile) {
166
+ const rcSources = [];
167
+ rcSources.push(rc9__namespace.read({ name: options.rcFile, dir: options.cwd }));
154
168
  if (options.globalRc) {
155
- Object.assign(
156
- configRC,
157
- rc9__namespace.readUser({ name: options.rcFile, dir: options.cwd })
158
- );
159
169
  const workspaceDir = await pkgTypes.findWorkspaceDir(options.cwd).catch(() => {
160
170
  });
161
171
  if (workspaceDir) {
162
- Object.assign(
163
- configRC,
164
- rc9__namespace.read({ name: options.rcFile, dir: workspaceDir })
165
- );
172
+ rcSources.push(rc9__namespace.read({ name: options.rcFile, dir: workspaceDir }));
166
173
  }
174
+ rcSources.push(rc9__namespace.readUser({ name: options.rcFile, dir: options.cwd }));
167
175
  }
168
- Object.assign(
169
- configRC,
170
- rc9__namespace.read({ name: options.rcFile, dir: options.cwd })
171
- );
176
+ Object.assign(configRC, defu.defu({}, ...rcSources));
172
177
  }
173
178
  const pkgJson = {};
174
179
  if (options.packageJson) {
@@ -309,11 +314,14 @@ async function resolveConfig(source, options, sourceOptions = {}) {
309
314
  });
310
315
  source = cloned.dir;
311
316
  }
312
- if (NPM_PACKAGE_RE.test(source)) {
317
+ const tryResolve = (id) => {
313
318
  try {
314
- source = options.jiti.resolve(source, { paths: [options.cwd] });
319
+ return options.jiti.resolve(id, { paths: [options.cwd] });
315
320
  } catch {
316
321
  }
322
+ };
323
+ if (NPM_PACKAGE_RE.test(source)) {
324
+ source = tryResolve(source) || source;
317
325
  }
318
326
  const ext = pathe.extname(source);
319
327
  const isDir = !ext || ext === pathe.basename(source);
@@ -323,25 +331,20 @@ async function resolveConfig(source, options, sourceOptions = {}) {
323
331
  }
324
332
  const res = {
325
333
  config: void 0,
334
+ configFile: void 0,
326
335
  cwd,
327
336
  source,
328
337
  sourceOptions
329
338
  };
330
- try {
331
- res.configFile = options.jiti.resolve(pathe.resolve(cwd, source), {
332
- paths: [cwd]
333
- });
334
- } catch {
335
- }
339
+ res.configFile = tryResolve(pathe.resolve(cwd, source)) || tryResolve(pathe.resolve(cwd, ".config", source.replace(/\.config$/, ""))) || tryResolve(pathe.resolve(cwd, ".config", source)) || source;
336
340
  if (!node_fs.existsSync(res.configFile)) {
337
341
  return res;
338
342
  }
339
- if (res.configFile.endsWith(".jsonc")) {
340
- const { parse } = await import('jsonc-parser');
341
- res.config = parse(await promises.readFile(res.configFile, "utf8"));
342
- } else if (res.configFile.endsWith(".json5")) {
343
- const { parse } = await import('json5');
344
- res.config = parse(await promises.readFile(res.configFile, "utf8"));
343
+ const configFileExt = pathe.extname(res.configFile) || "";
344
+ if (configFileExt in ASYNC_LOADERS) {
345
+ const asyncLoader = await ASYNC_LOADERS[configFileExt]();
346
+ const contents = await promises.readFile(res.configFile, "utf8");
347
+ res.config = asyncLoader(contents);
345
348
  } else {
346
349
  res.config = options.jiti(res.configFile);
347
350
  }
@@ -383,9 +386,15 @@ async function watchConfig(options) {
383
386
  const watchingFiles = [
384
387
  ...new Set(
385
388
  (config.layers || []).filter((l) => l.cwd).flatMap((l) => [
386
- ...["ts", "js", "mjs", "cjs", "cts", "mts", "json"].map(
387
- (ext) => pathe.resolve(l.cwd, configFileName + "." + ext)
388
- ),
389
+ ...SUPPORTED_EXTENSIONS.flatMap((ext) => [
390
+ pathe.resolve(l.cwd, configFileName + ext),
391
+ pathe.resolve(l.cwd, ".config", configFileName + ext),
392
+ pathe.resolve(
393
+ l.cwd,
394
+ ".config",
395
+ configFileName.replace(/\.config$/, "") + ext
396
+ )
397
+ ]),
389
398
  l.source && pathe.resolve(l.cwd, l.source),
390
399
  // TODO: Support watching rc from home and workspace
391
400
  options.rcFile && pathe.resolve(
@@ -396,7 +405,8 @@ async function watchConfig(options) {
396
405
  ]).filter(Boolean)
397
406
  )
398
407
  ];
399
- const _fswatcher = chokidar.watch(watchingFiles, {
408
+ const watch = await import('chokidar').then((r) => r.watch || r.default || r);
409
+ const _fswatcher = watch(watchingFiles, {
400
410
  ignoreInitial: true,
401
411
  ...options.chokidarOptions
402
412
  });
@@ -450,6 +460,7 @@ async function watchConfig(options) {
450
460
  });
451
461
  }
452
462
 
463
+ exports.SUPPORTED_EXTENSIONS = SUPPORTED_EXTENSIONS;
453
464
  exports.createDefineConfig = createDefineConfig;
454
465
  exports.loadConfig = loadConfig;
455
466
  exports.loadDotenv = loadDotenv;
package/dist/index.d.cts CHANGED
@@ -96,6 +96,7 @@ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT exte
96
96
  type DefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = (input: InputConfig<T, MT>) => InputConfig<T, MT>;
97
97
  declare function createDefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(): DefineConfig<T, MT>;
98
98
 
99
+ declare const SUPPORTED_EXTENSIONS: readonly [".js", ".ts", ".mjs", ".cjs", ".mts", ".cts", ".json", ".jsonc", ".json5", ".yaml", ".yml", ".toml"];
99
100
  declare function loadConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: LoadConfigOptions<T, MT>): Promise<ResolvedConfig<T, MT>>;
100
101
 
101
102
  type ConfigWatcher<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = ResolvedConfig<T, MT> & {
@@ -122,4 +123,4 @@ interface WatchConfigOptions<T extends UserInputConfig = UserInputConfig, MT ext
122
123
  }
123
124
  declare function watchConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: WatchConfigOptions<T, MT>): Promise<ConfigWatcher<T, MT>>;
124
125
 
125
- export { type C12InputConfig, type ConfigLayer, type ConfigLayerMeta, type ConfigWatcher, type DefineConfig, type DotenvOptions, type Env, type InputConfig, type LoadConfigOptions, type ResolvedConfig, type SourceOptions, type UserInputConfig, type WatchConfigOptions, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
126
+ export { type C12InputConfig, type ConfigLayer, type ConfigLayerMeta, type ConfigWatcher, type DefineConfig, type DotenvOptions, type Env, type InputConfig, type LoadConfigOptions, type ResolvedConfig, SUPPORTED_EXTENSIONS, type SourceOptions, type UserInputConfig, type WatchConfigOptions, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
package/dist/index.d.mts CHANGED
@@ -96,6 +96,7 @@ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT exte
96
96
  type DefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = (input: InputConfig<T, MT>) => InputConfig<T, MT>;
97
97
  declare function createDefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(): DefineConfig<T, MT>;
98
98
 
99
+ declare const SUPPORTED_EXTENSIONS: readonly [".js", ".ts", ".mjs", ".cjs", ".mts", ".cts", ".json", ".jsonc", ".json5", ".yaml", ".yml", ".toml"];
99
100
  declare function loadConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: LoadConfigOptions<T, MT>): Promise<ResolvedConfig<T, MT>>;
100
101
 
101
102
  type ConfigWatcher<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = ResolvedConfig<T, MT> & {
@@ -122,4 +123,4 @@ interface WatchConfigOptions<T extends UserInputConfig = UserInputConfig, MT ext
122
123
  }
123
124
  declare function watchConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: WatchConfigOptions<T, MT>): Promise<ConfigWatcher<T, MT>>;
124
125
 
125
- export { type C12InputConfig, type ConfigLayer, type ConfigLayerMeta, type ConfigWatcher, type DefineConfig, type DotenvOptions, type Env, type InputConfig, type LoadConfigOptions, type ResolvedConfig, type SourceOptions, type UserInputConfig, type WatchConfigOptions, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
126
+ export { type C12InputConfig, type ConfigLayer, type ConfigLayerMeta, type ConfigWatcher, type DefineConfig, type DotenvOptions, type Env, type InputConfig, type LoadConfigOptions, type ResolvedConfig, SUPPORTED_EXTENSIONS, type SourceOptions, type UserInputConfig, type WatchConfigOptions, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
package/dist/index.d.ts CHANGED
@@ -96,6 +96,7 @@ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT exte
96
96
  type DefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = (input: InputConfig<T, MT>) => InputConfig<T, MT>;
97
97
  declare function createDefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(): DefineConfig<T, MT>;
98
98
 
99
+ declare const SUPPORTED_EXTENSIONS: readonly [".js", ".ts", ".mjs", ".cjs", ".mts", ".cts", ".json", ".jsonc", ".json5", ".yaml", ".yml", ".toml"];
99
100
  declare function loadConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: LoadConfigOptions<T, MT>): Promise<ResolvedConfig<T, MT>>;
100
101
 
101
102
  type ConfigWatcher<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = ResolvedConfig<T, MT> & {
@@ -122,4 +123,4 @@ interface WatchConfigOptions<T extends UserInputConfig = UserInputConfig, MT ext
122
123
  }
123
124
  declare function watchConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: WatchConfigOptions<T, MT>): Promise<ConfigWatcher<T, MT>>;
124
125
 
125
- export { type C12InputConfig, type ConfigLayer, type ConfigLayerMeta, type ConfigWatcher, type DefineConfig, type DotenvOptions, type Env, type InputConfig, type LoadConfigOptions, type ResolvedConfig, type SourceOptions, type UserInputConfig, type WatchConfigOptions, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
126
+ export { type C12InputConfig, type ConfigLayer, type ConfigLayerMeta, type ConfigWatcher, type DefineConfig, type DotenvOptions, type Env, type InputConfig, type LoadConfigOptions, type ResolvedConfig, SUPPORTED_EXTENSIONS, type SourceOptions, type UserInputConfig, type WatchConfigOptions, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
package/dist/index.mjs CHANGED
@@ -8,7 +8,6 @@ import * as rc9 from 'rc9';
8
8
  import { defu } from 'defu';
9
9
  import { hash, diff } from 'ohash';
10
10
  import { findWorkspaceDir, readPackageJSON } from 'pkg-types';
11
- import { watch } from 'chokidar';
12
11
  import { debounce } from 'perfect-debounce';
13
12
 
14
13
  async function setupDotenv(options) {
@@ -84,6 +83,29 @@ function interpolate(target, source = {}, parse = (v) => v) {
84
83
  }
85
84
 
86
85
  const _normalize = (p) => p?.replace(/\\/g, "/");
86
+ const ASYNC_LOADERS = {
87
+ ".yaml": () => import('confbox/yaml').then((r) => r.parseYAML),
88
+ ".yml": () => import('confbox/yaml').then((r) => r.parseYAML),
89
+ ".jsonc": () => import('confbox/jsonc').then((r) => r.parseJSONC),
90
+ ".json5": () => import('confbox/json5').then((r) => r.parseJSON5),
91
+ ".toml": () => import('confbox/toml').then((r) => r.parseTOML)
92
+ };
93
+ const SUPPORTED_EXTENSIONS = [
94
+ // with jiti
95
+ ".js",
96
+ ".ts",
97
+ ".mjs",
98
+ ".cjs",
99
+ ".mts",
100
+ ".cts",
101
+ ".json",
102
+ // with confbox
103
+ ".jsonc",
104
+ ".json5",
105
+ ".yaml",
106
+ ".yml",
107
+ ".toml"
108
+ ];
87
109
  async function loadConfig(options) {
88
110
  options.cwd = resolve(process.cwd(), options.cwd || ".");
89
111
  options.name = options.name || "config";
@@ -100,17 +122,7 @@ async function loadConfig(options) {
100
122
  interopDefault: true,
101
123
  requireCache: false,
102
124
  esmResolve: true,
103
- extensions: [
104
- ".js",
105
- ".mjs",
106
- ".cjs",
107
- ".ts",
108
- ".mts",
109
- ".cts",
110
- ".json",
111
- ".jsonc",
112
- ".json5"
113
- ],
125
+ extensions: [...SUPPORTED_EXTENSIONS],
114
126
  ...options.jitiOptions
115
127
  });
116
128
  const r = {
@@ -131,24 +143,17 @@ async function loadConfig(options) {
131
143
  }
132
144
  const configRC = {};
133
145
  if (options.rcFile) {
146
+ const rcSources = [];
147
+ rcSources.push(rc9.read({ name: options.rcFile, dir: options.cwd }));
134
148
  if (options.globalRc) {
135
- Object.assign(
136
- configRC,
137
- rc9.readUser({ name: options.rcFile, dir: options.cwd })
138
- );
139
149
  const workspaceDir = await findWorkspaceDir(options.cwd).catch(() => {
140
150
  });
141
151
  if (workspaceDir) {
142
- Object.assign(
143
- configRC,
144
- rc9.read({ name: options.rcFile, dir: workspaceDir })
145
- );
152
+ rcSources.push(rc9.read({ name: options.rcFile, dir: workspaceDir }));
146
153
  }
154
+ rcSources.push(rc9.readUser({ name: options.rcFile, dir: options.cwd }));
147
155
  }
148
- Object.assign(
149
- configRC,
150
- rc9.read({ name: options.rcFile, dir: options.cwd })
151
- );
156
+ Object.assign(configRC, defu({}, ...rcSources));
152
157
  }
153
158
  const pkgJson = {};
154
159
  if (options.packageJson) {
@@ -289,11 +294,14 @@ async function resolveConfig(source, options, sourceOptions = {}) {
289
294
  });
290
295
  source = cloned.dir;
291
296
  }
292
- if (NPM_PACKAGE_RE.test(source)) {
297
+ const tryResolve = (id) => {
293
298
  try {
294
- source = options.jiti.resolve(source, { paths: [options.cwd] });
299
+ return options.jiti.resolve(id, { paths: [options.cwd] });
295
300
  } catch {
296
301
  }
302
+ };
303
+ if (NPM_PACKAGE_RE.test(source)) {
304
+ source = tryResolve(source) || source;
297
305
  }
298
306
  const ext = extname(source);
299
307
  const isDir = !ext || ext === basename(source);
@@ -303,25 +311,20 @@ async function resolveConfig(source, options, sourceOptions = {}) {
303
311
  }
304
312
  const res = {
305
313
  config: void 0,
314
+ configFile: void 0,
306
315
  cwd,
307
316
  source,
308
317
  sourceOptions
309
318
  };
310
- try {
311
- res.configFile = options.jiti.resolve(resolve(cwd, source), {
312
- paths: [cwd]
313
- });
314
- } catch {
315
- }
319
+ res.configFile = tryResolve(resolve(cwd, source)) || tryResolve(resolve(cwd, ".config", source.replace(/\.config$/, ""))) || tryResolve(resolve(cwd, ".config", source)) || source;
316
320
  if (!existsSync(res.configFile)) {
317
321
  return res;
318
322
  }
319
- if (res.configFile.endsWith(".jsonc")) {
320
- const { parse } = await import('jsonc-parser');
321
- res.config = parse(await readFile(res.configFile, "utf8"));
322
- } else if (res.configFile.endsWith(".json5")) {
323
- const { parse } = await import('json5');
324
- res.config = parse(await readFile(res.configFile, "utf8"));
323
+ const configFileExt = extname(res.configFile) || "";
324
+ if (configFileExt in ASYNC_LOADERS) {
325
+ const asyncLoader = await ASYNC_LOADERS[configFileExt]();
326
+ const contents = await readFile(res.configFile, "utf8");
327
+ res.config = asyncLoader(contents);
325
328
  } else {
326
329
  res.config = options.jiti(res.configFile);
327
330
  }
@@ -363,9 +366,15 @@ async function watchConfig(options) {
363
366
  const watchingFiles = [
364
367
  ...new Set(
365
368
  (config.layers || []).filter((l) => l.cwd).flatMap((l) => [
366
- ...["ts", "js", "mjs", "cjs", "cts", "mts", "json"].map(
367
- (ext) => resolve(l.cwd, configFileName + "." + ext)
368
- ),
369
+ ...SUPPORTED_EXTENSIONS.flatMap((ext) => [
370
+ resolve(l.cwd, configFileName + ext),
371
+ resolve(l.cwd, ".config", configFileName + ext),
372
+ resolve(
373
+ l.cwd,
374
+ ".config",
375
+ configFileName.replace(/\.config$/, "") + ext
376
+ )
377
+ ]),
369
378
  l.source && resolve(l.cwd, l.source),
370
379
  // TODO: Support watching rc from home and workspace
371
380
  options.rcFile && resolve(
@@ -376,6 +385,7 @@ async function watchConfig(options) {
376
385
  ]).filter(Boolean)
377
386
  )
378
387
  ];
388
+ const watch = await import('chokidar').then((r) => r.watch || r.default || r);
379
389
  const _fswatcher = watch(watchingFiles, {
380
390
  ignoreInitial: true,
381
391
  ...options.chokidarOptions
@@ -430,4 +440,4 @@ async function watchConfig(options) {
430
440
  });
431
441
  }
432
442
 
433
- export { createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
443
+ export { SUPPORTED_EXTENSIONS, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c12",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "description": "Smart Config Loader",
5
5
  "repository": "unjs/c12",
6
6
  "license": "MIT",
@@ -31,12 +31,11 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "chokidar": "^3.5.3",
34
+ "confbox": "^0.1.3",
34
35
  "defu": "^6.1.4",
35
36
  "dotenv": "^16.3.2",
36
37
  "giget": "^1.2.1",
37
38
  "jiti": "^1.21.0",
38
- "json5": "^2.2.3",
39
- "jsonc-parser": "^3.2.1",
40
39
  "mlly": "^1.5.0",
41
40
  "ohash": "^1.1.3",
42
41
  "pathe": "^1.1.2",
@@ -47,6 +46,7 @@
47
46
  "devDependencies": {
48
47
  "@types/node": "^20.11.5",
49
48
  "@vitest/coverage-v8": "^1.2.1",
49
+ "automd": "^0.2.0",
50
50
  "changelogen": "^0.5.5",
51
51
  "eslint": "^8.56.0",
52
52
  "eslint-config-unjs": "^0.2.1",