c12 4.0.0-beta.3 → 4.0.0-beta.5

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
@@ -30,6 +30,7 @@ c12 (pronounced as /siːtwelv/, like c-twelve) is a smart configuration loader.
30
30
  ## 🦴 Used by
31
31
 
32
32
  - [Hey API](https://github.com/hey-api/openapi-ts)
33
+ - [Gen API](https://github.com/hairyf/genapi)
33
34
  - [Kysely](https://github.com/kysely-org/kysely-ctl)
34
35
  - [Nitro](https://nitro.build/)
35
36
  - [Nuxt](https://nuxt.com/)
@@ -205,6 +206,21 @@ const { config } = await loadConfig({
205
206
  });
206
207
  ```
207
208
 
209
+ ### `jitiOptions`
210
+
211
+ Options passed to [unjs/jiti](https://github.com/unjs/jiti) when c12 falls back to it for loading config files. Has no effect if a custom `import` is provided.
212
+
213
+ **Example:**
214
+
215
+ ```js
216
+ const { config } = await loadConfig({
217
+ jitiOptions: {
218
+ fsCache: false,
219
+ transformOptions: { /* ... */ },
220
+ },
221
+ });
222
+ ```
223
+
208
224
  ### `resolveModule`
209
225
 
210
226
  Custom resolver for picking which export to use from the loaded module. Default: `(mod) => mod.default || mod`.
@@ -1,4 +1,3 @@
1
- //#region node_modules/.pnpm/ohash@2.0.11/node_modules/ohash/dist/utils/index.d.mts
2
1
  /**
3
2
  * Calculates the difference between two objects and returns a list of differences.
4
3
  *
@@ -26,5 +25,4 @@ declare class DiffHashedObject {
26
25
  toString(): string;
27
26
  toJSON(): string;
28
27
  }
29
- //#endregion
30
28
  export { diff as t };
@@ -1,4 +1,3 @@
1
- import "node:module";
2
1
  import { createHash } from "node:crypto";
3
2
  var __defProp = Object.defineProperty;
4
3
  var __exportAll = (all, no_symbols) => {
package/dist/index.d.mts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { t as diff } from "./_chunks/libs/ohash.mjs";
2
- import { ChokidarOptions } from "chokidar";
2
+ import * as _$jiti from "jiti";
3
3
  import { DownloadTemplateOptions } from "giget";
4
-
5
- //#region src/dotenv.d.ts
4
+ import { ChokidarOptions } from "chokidar";
6
5
  interface DotenvOptions {
7
6
  /**
8
7
  * The project root directory (either absolute or relative to the current working directory).
@@ -60,8 +59,7 @@ declare function loadDotenv(options: DotenvOptions): Promise<Env>;
60
59
  declare global {
61
60
  var __c12_dotenv_vars__: Map<Record<string, any>, Set<string>>;
62
61
  }
63
- //#endregion
64
- //#region src/types.d.ts
62
+ type JitiOptions = NonNullable<Parameters<typeof _$jiti.createJiti>[1]>;
65
63
  interface ConfigLayerMeta {
66
64
  name?: string;
67
65
  [key: string]: any;
@@ -144,6 +142,8 @@ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT exte
144
142
  import?: (id: string) => Promise<unknown>;
145
143
  /** Custom resolver for picking which export to use from the loaded module. Default: `(mod) => mod.default || mod` */
146
144
  resolveModule?: (mod: any) => any;
145
+ /** Options to override defaults when c12 falls back to [jiti](https://github.com/unjs/jiti) for loading config files. */
146
+ jitiOptions?: JitiOptions;
147
147
  giget?: false | DownloadTemplateOptions;
148
148
  merger?: (...sources: Array<T | null | undefined>) => T;
149
149
  extend?: false | {
@@ -153,12 +153,8 @@ interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT exte
153
153
  }
154
154
  type DefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = (input: InputConfig<T, MT>) => InputConfig<T, MT>;
155
155
  declare function createDefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(): DefineConfig<T, MT>;
156
- //#endregion
157
- //#region src/loader.d.ts
158
156
  declare const SUPPORTED_EXTENSIONS: string[];
159
157
  declare function loadConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: LoadConfigOptions<T, MT>): Promise<ResolvedConfig<T, MT>>;
160
- //#endregion
161
- //#region src/watch.d.ts
162
158
  type DiffEntries = ReturnType<typeof diff>;
163
159
  type ConfigWatcher<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = ResolvedConfig<T, MT> & {
164
160
  watchingFiles: string[];
@@ -183,5 +179,4 @@ interface WatchConfigOptions<T extends UserInputConfig = UserInputConfig, MT ext
183
179
  }) => void | Promise<void>;
184
180
  }
185
181
  declare function watchConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: WatchConfigOptions<T, MT>): Promise<ConfigWatcher<T, MT>>;
186
- //#endregion
187
182
  export { C12InputConfig, ConfigFunctionContext, ConfigLayer, ConfigLayerMeta, ConfigSource, type ConfigWatcher, DefineConfig, type DotenvOptions, type Env, InputConfig, LoadConfigOptions, ResolvableConfig, ResolvableConfigContext, ResolvedConfig, SUPPORTED_EXTENSIONS, SourceOptions, UserInputConfig, type WatchConfigOptions, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };
package/dist/index.mjs CHANGED
@@ -102,6 +102,7 @@ function getDotEnvVars(targetEnvironment) {
102
102
  return globalRegistry.get(targetEnvironment);
103
103
  }
104
104
  const _normalize = (p) => p?.replace(/\\/g, "/");
105
+ let importCounter = 0;
105
106
  const ASYNC_LOADERS = {
106
107
  ".yaml": () => import("confbox/yaml").then((r) => r.parseYAML),
107
108
  ".yml": () => import("confbox/yaml").then((r) => r.parseYAML),
@@ -310,7 +311,7 @@ async function resolveConfig(source, options, sourceOptions = {}) {
310
311
  }
311
312
  if (NPM_PACKAGE_RE.test(source)) source = tryResolve(source, options) || source;
312
313
  const ext = extname(source);
313
- const isDir = !ext || ext === basename(source);
314
+ const isDir = _isDirectory(resolve(options.cwd, source)) ?? (!ext || ext === basename(source));
314
315
  const cwd = resolve(options.cwd, isDir ? source : dirname(source));
315
316
  if (isDir) source = options.configFile;
316
317
  const res = {
@@ -328,18 +329,23 @@ async function resolveConfig(source, options, sourceOptions = {}) {
328
329
  else {
329
330
  const _resolveModule = options.resolveModule || ((mod) => mod.default || mod);
330
331
  if (options.import) res.config = _resolveModule(await options.import(res.configFile));
331
- else res.config = await import(res.configFile).then(_resolveModule, async (error) => {
332
- const { createJiti } = await import("jiti").catch(() => {
333
- throw new Error(`Failed to load config file \`${res.configFile}\`: ${error?.message}. Hint install \`jiti\` for compatibility.`, { cause: error });
332
+ else {
333
+ const _configURL = pathToFileURL(res.configFile);
334
+ _configURL.search = `_${++importCounter}`;
335
+ res.config = await import(_configURL.href).then(_resolveModule, async (error) => {
336
+ const { createJiti } = await import("jiti").catch(() => {
337
+ throw new Error(`Failed to load config file \`${res.configFile}\`: ${error?.message}. Hint install \`jiti\` for compatibility.`, { cause: error });
338
+ });
339
+ const jiti = createJiti(join(options.cwd || ".", options.configFile || "/"), {
340
+ interopDefault: true,
341
+ moduleCache: false,
342
+ extensions: [...SUPPORTED_EXTENSIONS],
343
+ ...options.jitiOptions
344
+ });
345
+ options.import = (id) => jiti.import(id);
346
+ return _resolveModule(await options.import(res.configFile));
334
347
  });
335
- const jiti = createJiti(join(options.cwd || ".", options.configFile || "/"), {
336
- interopDefault: true,
337
- moduleCache: false,
338
- extensions: [...SUPPORTED_EXTENSIONS]
339
- });
340
- options.import = (id) => jiti.import(id);
341
- return _resolveModule(await options.import(res.configFile));
342
- });
348
+ }
343
349
  }
344
350
  if (typeof res.config === "function") res.config = await res.config(options.context);
345
351
  if (options.envName) {
@@ -366,6 +372,13 @@ function tryResolve(id, options) {
366
372
  });
367
373
  return res ? normalize(res) : void 0;
368
374
  }
375
+ function _isDirectory(path) {
376
+ try {
377
+ return statSync(path).isDirectory();
378
+ } catch {
379
+ return null;
380
+ }
381
+ }
369
382
  function createDefineConfig() {
370
383
  return (input) => input;
371
384
  }
package/dist/update.d.mts CHANGED
@@ -1,6 +1,4 @@
1
- import * as magicast from "magicast";
2
-
3
- //#region src/update.d.ts
1
+ import * as _$magicast from "magicast";
4
2
  /**
5
3
  * @experimental Update a config file or create a new one.
6
4
  */
@@ -10,7 +8,7 @@ interface UpdateConfigResult {
10
8
  created?: boolean;
11
9
  }
12
10
  type MaybePromise<T> = T | Promise<T>;
13
- type MagicAstOptions = Exclude<Parameters<(typeof magicast)["parseModule"]>[1], undefined>;
11
+ type MagicAstOptions = Exclude<Parameters<(typeof _$magicast)["parseModule"]>[1], undefined>;
14
12
  interface UpdateConfigOptions {
15
13
  /**
16
14
  * Current working directory
@@ -49,5 +47,4 @@ interface UpdateConfigOptions {
49
47
  configFile: string;
50
48
  }) => MaybePromise<string | boolean>;
51
49
  }
52
- //#endregion
53
50
  export { UpdateConfigOptions, UpdateConfigResult, updateConfig };
package/dist/update.mjs CHANGED
@@ -1,12 +1,6 @@
1
1
  import { resolveModulePath } from "exsolve";
2
- import "node:fs";
3
2
  import { mkdir, readFile, writeFile } from "node:fs/promises";
4
- import "node:url";
5
- import "node:os";
6
3
  import { join, normalize } from "pathe";
7
- import "rc9";
8
- import "defu";
9
- import "pkg-types";
10
4
  import { dirname, extname } from "node:path";
11
5
  const SUPPORTED_EXTENSIONS = Object.freeze([
12
6
  ".js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c12",
3
- "version": "4.0.0-beta.3",
3
+ "version": "4.0.0-beta.5",
4
4
  "description": "Smart Config Loader",
5
5
  "license": "MIT",
6
6
  "repository": "unjs/c12",
@@ -19,38 +19,38 @@
19
19
  "dev": "vitest dev",
20
20
  "lint": "oxlint . && oxfmt --check src test",
21
21
  "lint:fix": "automd && oxlint . --fix && oxfmt src test",
22
- "release": "pnpm test && pnpm build && changelogen --release --prerelease --publish && git push --follow-tags",
22
+ "release": "pnpm test && pnpm build && changelogen --release --prerelease --push && npm publish",
23
23
  "test": "pnpm lint && vitest run --coverage && pnpm test:types",
24
24
  "test:types": "tsgo --noEmit"
25
25
  },
26
26
  "dependencies": {
27
27
  "confbox": "^0.2.4",
28
- "defu": "^6.1.4",
28
+ "defu": "^6.1.7",
29
29
  "exsolve": "^1.0.8",
30
30
  "pathe": "^2.0.3",
31
- "pkg-types": "^2.3.0",
32
- "rc9": "^3.0.0"
31
+ "pkg-types": "^2.3.1",
32
+ "rc9": "^3.0.1"
33
33
  },
34
34
  "devDependencies": {
35
- "@types/node": "^25.2.3",
36
- "@typescript/native-preview": "^7.0.0-dev.20260216.1",
37
- "@vitest/coverage-v8": "^4.0.18",
35
+ "@types/node": "^25.6.0",
36
+ "@typescript/native-preview": "^7.0.0-dev.20260505.1",
37
+ "@vitest/coverage-v8": "^4.1.5",
38
38
  "automd": "^0.4.3",
39
39
  "changelogen": "^0.6.2",
40
40
  "chokidar": "^5.0.0",
41
- "dotenv": "^17.3.1",
41
+ "dotenv": "^17.4.2",
42
42
  "eslint-config-unjs": "^0.6.2",
43
43
  "expect-type": "^1.3.0",
44
- "giget": "^3.1.2",
45
- "jiti": "^2.6.1",
44
+ "giget": "^3.2.0",
45
+ "jiti": "^2.7.0",
46
46
  "magicast": "^0.5.2",
47
- "obuild": "^0.4.27",
47
+ "obuild": "^0.4.34",
48
48
  "ohash": "^2.0.11",
49
- "oxfmt": "^0.33.0",
50
- "oxlint": "^1.48.0",
49
+ "oxfmt": "^0.48.0",
50
+ "oxlint": "^1.63.0",
51
51
  "perfect-debounce": "^2.1.0",
52
- "typescript": "^5.9.3",
53
- "vitest": "^4.0.18"
52
+ "typescript": "^6.0.3",
53
+ "vitest": "^4.1.5"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "chokidar": "^5",
@@ -76,5 +76,5 @@
76
76
  "optional": true
77
77
  }
78
78
  },
79
- "packageManager": "pnpm@10.29.3"
79
+ "packageManager": "pnpm@10.33.3"
80
80
  }