Load configuration from files, environment variables, and interactively prompt for missing values
A flexible configuration loader that extends c12 with additional features for environment variable mapping and interactive user prompts. Built on top of the unjs ecosystem for modern Node.js applications.
- 🔍 Multiple config sources: Load from package.json, rc files, config files, and more
- 🌍 Environment variable support: Automatic dotenv loading and environment variable mapping
- 💬 Interactive prompts: Ask users for missing required configuration values
- 🔄 Config merging: Smart merging of configuration from multiple sources with overrides
- 📁 Flexible file formats: Support for JSON, YAML, JS, TS, and more
- 🛡️ TypeScript support: Full TypeScript support with type safety
- 🔗 Config extension: Built-in support for extending configurations from other files or remote sources
# ✨ Auto-detect (supports npm, yarn, pnpm, deno and bun)
npx nypm install @jungvonmatt/config-loader
ESM (Node.js, Bun, Deno)
import { loadConfig } from "@jungvonmatt/config-loader";
import { loadConfig } from "@jungvonmatt/config-loader";
const { config } = await loadConfig({
name: "myapp",
defaultConfig: {
port: 3000,
host: "localhost",
},
});
console.log(config.port); // 3000
import { loadConfig } from "@jungvonmatt/config-loader";
const { config } = await loadConfig({
name: "myapp",
required: ["apiKey", "databaseUrl"],
prompts: [
{
name: "apiKey",
type: "password",
message: "Enter your API key:",
},
{
name: "databaseUrl",
type: "input",
message: "Enter database URL:",
},
],
});
const { config } = await loadConfig({
name: "myapp",
envMap: {
DATABASE_URL: "databaseUrl",
API_KEY: "apiKey",
PORT: "port",
},
defaultConfig: {
port: 3000,
},
});
// config.ts
export default {
extends: "./base.config.ts",
port: 8080,
database: {
url: "postgresql://localhost/mydb"
}
};
// base.config.ts
export default {
port: 3000,
host: "localhost",
database: {
url: "postgresql://localhost/default"
}
};
The loader searches for configuration in the following locations (in order):
-
package.json
(in amyapp
property) .myapprc.json
-
.myapprc.yaml
/.myapprc.yml
-
.myapprc.js
/.myapprc.ts
/.myapprc.mjs
/.myapprc.cjs
.config/.myapprc.*
-
myapp.config.js
/myapp.config.ts
/myapp.config.mjs
/myapp.config.cjs
Where myapp
is the name you provide in the options.
.myapprc.json
{
"port": 8080,
"database": {
"url": "postgresql://localhost/mydb"
}
}
myapp.config.js
export default {
port: process.env.PORT || 3000,
database: {
url: process.env.DATABASE_URL,
},
};
Environment variables are automatically loaded from .env
files:
-
.env.{NODE_ENV}
(e.g.,.env.production
) .env
Any configuration can be overridden using environment variables with the pattern:
{NAME}_CONFIG_{PATH}
For example, with name: "myapp"
:
-
MYAPP_CONFIG_PORT=8080
setsconfig.port = 8080
-
MYAPP_CONFIG_DATABASE_URL=...
setsconfig.databaseUrl = ...
Option | Type | Default | Description |
---|---|---|---|
name |
string |
Required | Name of the configuration (used for file searching) |
defaultConfig |
Partial<T> |
{} |
Default configuration values |
overrides |
Partial<T> |
{} |
Configuration overrides (highest priority) |
required |
Array<keyof T> | ((config: T) => Array<keyof T> | Promise<Array<keyof T>>) |
[] |
Array of required configuration keys or a function that returns them. The function receives the current config as an argument. |
envMap |
Record<string, keyof T> |
{} |
Map environment variable names to config keys |
dotenv |
boolean |
true |
Whether to load .env files |
envName |
string | false |
process.env.NODE_ENV |
Environment name for .env.{envName} file |
cwd |
string |
process.cwd() |
Working directory for file searching |
configFile |
string |
undefined |
Path to a specific config file to load |
prompt |
Array<keyof T> | ((config: T) => Array<keyof T> | Promise<Array<keyof T>>) |
[] |
Array of configuration keys to prompt for, even if they exist in the config. Can be a function that returns the keys. Keys will be sorted based on the order in prompts if provided. |
prompts |
PromptOptions[] | ((config: T) => PromptOptions[]) |
[] |
Interactive prompts for missing values. See enquirer for syntax details. The order of prompts determines the order of fields in the prompt sequence. |
interface ResolvedConfig<T> {
config: T; // The merged configuration object
filepath: string | undefined; // Path to the config file that was loaded
missing: string[]; // Array of missing required fields
layers: Array<{
type: "module" | "file" | "env" | "overrides" | "default" | "prompt";
filepath: string | undefined;
config: Partial<T> | undefined;
cwd: string | undefined;
}>; // Array of configuration layers in order of application
}
Prompts use enquirer under the hood:
interface PromptOptions {
name: string; // Configuration key name
type: string; // Prompt type: 'input', 'password', 'select', etc.
message: string; // Prompt message
choices?: string[]; // For select/multiselect prompts
initial?: any; // Default value
// ... other enquirer options
}
Published under the MIT license.
Made by Jung von Matt TECH 💚
🤖 auto updated with automd