c12 3.2.0 → 3.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 CHANGED
@@ -14,7 +14,7 @@ c12 (pronounced as /siːtwelv/, like c-twelve) is a smart configuration loader.
14
14
 
15
15
  - `.js`, `.ts`, `.mjs`, `.cjs`, `.mts`, `.cts` `.json` config loader with [unjs/jiti](https://jiti.unjs.io)
16
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)
17
+ - `.config/` directory support ([config dir proposal](https://github.com/pi0/config-dir))
18
18
  - `.rc` config support with [unjs/rc9](https://github.com/unjs/rc9)
19
19
  - `.env` support with [dotenv](https://www.npmjs.com/package/dotenv)
20
20
  - Multiple sources merged with [unjs/defu](https://github.com/unjs/defu)
@@ -26,15 +26,14 @@ c12 (pronounced as /siːtwelv/, like c-twelve) is a smart configuration loader.
26
26
 
27
27
  ## 🦴 Used by
28
28
 
29
- - [Nuxt](https://nuxt.com/)
30
- - [Nitro](https://nitro.build/)
31
- - [Unbuild](https://unbuild.unjs.io)
32
- - [Automd](https://automd.unjs.io)
33
- - [Changelogen](https://changelogen.unjs.io)
34
- - [RemixKit](https://github.com/jrestall/remix-kit)
35
29
  - [Hey API](https://github.com/hey-api/openapi-ts)
36
- - [kysely-ctl](https://github.com/kysely-org/kysely-ctl)
30
+ - [Kysely](https://github.com/kysely-org/kysely-ctl)
31
+ - [Nitro](https://nitro.build/)
32
+ - [Nuxt](https://nuxt.com/)
37
33
  - [Prisma](https://github.com/prisma/prisma)
34
+ - [Trigger.dev](https://github.com/triggerdotdev/trigger.dev)
35
+ - [UnJS](https://github.com/unjs)
36
+ - [WXT](https://github.com/wxt-dev/wxt)
38
37
 
39
38
  ## Usage
40
39
 
@@ -103,7 +102,42 @@ Load RC config from the workspace directory and the user's home directory. Only
103
102
 
104
103
  ### `dotenv`
105
104
 
106
- Loads `.env` file if enabled. It is disabled by default.
105
+ Loads `.env` file when `true` or an options object is passed. It is disabled by default.
106
+
107
+ Supports loading multiple files that extend eachother in left-to-right order when a `fileName`s array of relative/absolute paths is passed in the options object.
108
+
109
+ **Example:**
110
+
111
+ ```ini
112
+ # .env
113
+ CONNECTION_POOL_MAX="10"
114
+ DATABASE_URL="<...rds...>"
115
+ ```
116
+
117
+ ```ini
118
+ # .env.local
119
+ DATABASE_URL="<...localhost...>"
120
+ ```
121
+
122
+ ```js
123
+ export default {
124
+ connectionPoolMax: process.env.CONNECTION_POOL_MAX,
125
+ databaseURL: process.env.DATABASE_URL,
126
+ };
127
+ ```
128
+
129
+ ```ts
130
+ import { loadConfig } from "c12";
131
+
132
+ const config = await loadConfig({
133
+ dotenv: {
134
+ fileName: [".env", ".env.local"],
135
+ },
136
+ });
137
+
138
+ console.log(config.config.connectionPoolMax); // "10"
139
+ console.log(config.config.databaseURL); // "<...localhost...>"
140
+ ```
107
141
 
108
142
  ### `packageJson`
109
143
 
package/dist/index.d.mts CHANGED
@@ -6,8 +6,10 @@ import { diff } from 'ohash/utils';
6
6
  interface DotenvOptions {
7
7
  /**
8
8
  * The project root directory (either absolute or relative to the current working directory).
9
+ *
10
+ * Defaults to `options.cwd` in `loadConfig` context, or `process.cwd()` when used as standalone.
9
11
  */
10
- cwd: string;
12
+ cwd?: string;
11
13
  /**
12
14
  * What file or files to look in for environment variables (either absolute or relative
13
15
  * to the current working directory). For example, `.env`.
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { l as loadConfig, S as SUPPORTED_EXTENSIONS } from './shared/c12.DDjD4HmS.mjs';
2
- export { a as loadDotenv, s as setupDotenv } from './shared/c12.DDjD4HmS.mjs';
1
+ import { l as loadConfig, S as SUPPORTED_EXTENSIONS } from './shared/c12.Bzgyhsy6.mjs';
2
+ export { a as loadDotenv, s as setupDotenv } from './shared/c12.Bzgyhsy6.mjs';
3
3
  import { debounce } from 'perfect-debounce';
4
4
  import { resolve } from 'pathe';
5
5
  import 'node:fs';
@@ -31,12 +31,13 @@ async function setupDotenv(options) {
31
31
  }
32
32
  async function loadDotenv(options) {
33
33
  const environment = /* @__PURE__ */ Object.create(null);
34
+ const cwd = resolve(options.cwd || ".");
34
35
  const _fileName = options.fileName || ".env";
35
36
  const dotenvFiles = typeof _fileName === "string" ? [_fileName] : _fileName;
36
37
  const dotenvVars = getDotEnvVars(options.env || {});
37
38
  Object.assign(environment, options.env);
38
39
  for (const file of dotenvFiles) {
39
- const dotenvFile = resolve(options.cwd, file);
40
+ const dotenvFile = resolve(cwd, file);
40
41
  if (!statSync(dotenvFile, { throwIfNoEntry: false })?.isFile()) {
41
42
  continue;
42
43
  }
@@ -201,18 +202,22 @@ async function loadConfig(options) {
201
202
  const value = rawConfigs[key];
202
203
  configs[key] = await (typeof value === "function" ? value({ configs, rawConfigs }) : value);
203
204
  }
204
- r.config = _merger(
205
- configs.overrides,
206
- configs.main,
207
- configs.rc,
208
- configs.packageJson,
209
- configs.defaultConfig
210
- );
211
- if (options.extend) {
212
- await extendConfig(r.config, options);
213
- r.layers = r.config._layers;
214
- delete r.config._layers;
215
- r.config = _merger(r.config, ...r.layers.map((e) => e.config));
205
+ if (Array.isArray(configs.main)) {
206
+ r.config = configs.main;
207
+ } else {
208
+ r.config = _merger(
209
+ configs.overrides,
210
+ configs.main,
211
+ configs.rc,
212
+ configs.packageJson,
213
+ configs.defaultConfig
214
+ );
215
+ if (options.extend) {
216
+ await extendConfig(r.config, options);
217
+ r.layers = r.config._layers;
218
+ delete r.config._layers;
219
+ r.config = _merger(r.config, ...r.layers.map((e) => e.config));
220
+ }
216
221
  }
217
222
  const baseLayers = [
218
223
  configs.overrides && {
@@ -305,6 +310,7 @@ const GIGET_PREFIXES = [
305
310
  ];
306
311
  const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]*($|\/.*)/;
307
312
  async function resolveConfig(source, options, sourceOptions = {}) {
313
+ const originalSource = source;
308
314
  if (options.resolve) {
309
315
  const res2 = await options.resolve(source, options);
310
316
  if (res2) {
@@ -362,7 +368,7 @@ async function resolveConfig(source, options, sourceOptions = {}) {
362
368
  res.configFile = tryResolve(resolve(cwd, source), options) || tryResolve(
363
369
  resolve(cwd, ".config", source.replace(/\.config$/, "")),
364
370
  options
365
- ) || tryResolve(resolve(cwd, ".config", source), options) || source;
371
+ ) || tryResolve(resolve(cwd, ".config", source), options) || tryResolve(resolve(options.cwd || cwd, originalSource), options) || source;
366
372
  if (!existsSync(res.configFile)) {
367
373
  return res;
368
374
  }
package/dist/update.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { resolveModulePath } from 'exsolve';
2
- import { S as SUPPORTED_EXTENSIONS } from './shared/c12.DDjD4HmS.mjs';
2
+ import { S as SUPPORTED_EXTENSIONS } from './shared/c12.Bzgyhsy6.mjs';
3
3
  import { join, normalize } from 'pathe';
4
4
  import { mkdir, writeFile, readFile } from 'node:fs/promises';
5
5
  import { dirname, extname } from 'node:path';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c12",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Smart Config Loader",
5
5
  "repository": "unjs/c12",
6
6
  "license": "MIT",
@@ -34,28 +34,28 @@
34
34
  "chokidar": "^4.0.3",
35
35
  "confbox": "^0.2.2",
36
36
  "defu": "^6.1.4",
37
- "dotenv": "^17.2.1",
37
+ "dotenv": "^17.2.2",
38
38
  "exsolve": "^1.0.7",
39
39
  "giget": "^2.0.0",
40
40
  "jiti": "^2.5.1",
41
41
  "ohash": "^2.0.11",
42
42
  "pathe": "^2.0.3",
43
- "perfect-debounce": "^1.0.0",
44
- "pkg-types": "^2.2.0",
43
+ "perfect-debounce": "^2.0.0",
44
+ "pkg-types": "^2.3.0",
45
45
  "rc9": "^2.1.2"
46
46
  },
47
47
  "devDependencies": {
48
- "@types/node": "^24.1.0",
48
+ "@types/node": "^24.4.0",
49
49
  "@vitest/coverage-v8": "^3.2.4",
50
50
  "automd": "^0.4.0",
51
51
  "changelogen": "^0.6.2",
52
- "eslint": "^9.32.0",
52
+ "eslint": "^9.35.0",
53
53
  "eslint-config-unjs": "^0.5.0",
54
54
  "expect-type": "^1.2.2",
55
55
  "magicast": "^0.3.5",
56
56
  "prettier": "^3.6.2",
57
- "typescript": "^5.8.3",
58
- "unbuild": "^3.6.0",
57
+ "typescript": "^5.9.2",
58
+ "unbuild": "^3.6.1",
59
59
  "vitest": "^3.2.4"
60
60
  },
61
61
  "peerDependencies": {
@@ -66,5 +66,5 @@
66
66
  "optional": true
67
67
  }
68
68
  },
69
- "packageManager": "pnpm@10.13.1"
69
+ "packageManager": "pnpm@10.16.1"
70
70
  }