···1616- `.jsonc`, `.json5`, `.yaml`, `.yml`, `.toml` config loader with [unjs/confbox](https://confbox.unjs.io)
1717- `.config/` directory support ([config dir proposal](https://github.com/pi0/config-dir))
1818- `.rc` config support with [unjs/rc9](https://github.com/unjs/rc9)
1919-- `.env` support with [dotenv](https://www.npmjs.com/package/dotenv)
1919+- `.env` support with variable interpolation and `_FILE` references resolution
2020- Multiple sources merged with [unjs/defu](https://github.com/unjs/defu)
2121- Reads config from the nearest `package.json` file
2222- [Extends configurations](https://github.com/unjs/c12#extending-configuration) from multiple local or git sources
···137137138138console.log(config.config.connectionPoolMax); // "10"
139139console.log(config.config.databaseURL); // "<...localhost...>"
140140+```
141141+142142+#### `expandFileReferences`
143143+144144+Enabled by default. Environment variables ending with `_FILE` are resolved by reading the file at the specified path and assigning its trimmed content to the base key (without the `_FILE` suffix). This is useful for container secrets (e.g. Docker, Kubernetes) where sensitive values are mounted as files. Set to `false` to disable.
145145+146146+```ini
147147+# .env
148148+DATABASE_PASSWORD_FILE="/run/secrets/db_password"
149149+```
150150+151151+```ts
152152+import { loadConfig } from "c12";
153153+154154+const config = await loadConfig({
155155+ dotenv: true,
156156+});
157157+158158+// DATABASE_PASSWORD is now set to the contents of /run/secrets/db_password
140159```
141160142161### `packageJson`
+35
src/dotenv.ts
···3333 * An object describing environment variables (key, value pairs).
3434 */
3535 env?: NodeJS.ProcessEnv;
3636+3737+ /**
3838+ * Resolve `_FILE` suffixed environment variables by reading the file at the
3939+ * specified path and assigning its trimmed content to the base key.
4040+ *
4141+ * This is useful for container secrets (e.g. Docker, Kubernetes) where
4242+ * sensitive values are mounted as files.
4343+ *
4444+ * @default true
4545+ *
4646+ * @example
4747+ * ```env
4848+ * DATABASE_PASSWORD_FILE="/run/secrets/db_password"
4949+ * # resolves to DATABASE_PASSWORD=<contents of /run/secrets/db_password>
5050+ * ```
5151+ */
5252+ expandFileReferences?: boolean;
3653}
37543855export type Env = typeof process.env;
···5168 fileName: options.fileName ?? ".env",
5269 env: targetEnvironment,
5370 interpolate: options.interpolate ?? true,
7171+ expandFileReferences: options.expandFileReferences ?? true,
5472 });
55735674 const dotenvVars = getDotEnvVars(targetEnvironment);
···95113 }
96114 environment[key] = parsed[key];
97115 dotenvVars.add(key);
116116+ }
117117+ }
118118+119119+ // Support _FILE environment variables
120120+ if (options.expandFileReferences !== false) {
121121+ for (const key in environment) {
122122+ if (key.endsWith("_FILE")) {
123123+ const targetKey = key.slice(0, -5);
124124+ if (environment[targetKey] === undefined) {
125125+ const filePath = environment[key];
126126+ if (filePath && statSync(filePath, { throwIfNoEntry: false })?.isFile()) {
127127+ const value = readFileSync(filePath, "utf8");
128128+ environment[targetKey] = value.trim();
129129+ dotenvVars.add(targetKey);
130130+ }
131131+ }
132132+ }
98133 }
99134 }
100135