@jungvonmatt/config-loader
v0.6.1
Published
Load config from files & environment & ask for missing values
Keywords
Readme
@jungvonmatt/config-loader
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.
Features
- 🔍 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
Installation
# ✨ Auto-detect (supports npm, yarn, pnpm, deno and bun)
npx nypm install @jungvonmatt/config-loaderUsage
ESM (Node.js, Bun, Deno)
import { loadConfig } from "@jungvonmatt/config-loader";Basic Example
import { loadConfig } from "@jungvonmatt/config-loader";
const { config } = await loadConfig({
name: "myapp",
defaultConfig: {
port: 3000,
host: "localhost",
},
});
console.log(config.port); // 3000With Required Fields and Prompts
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:",
},
],
});Environment Variable Mapping
const { config } = await loadConfig({
name: "myapp",
envMap: {
DATABASE_URL: "databaseUrl",
API_KEY: "apiKey",
PORT: "port",
},
defaultConfig: {
port: 3000,
},
});Extending Configurations
// 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"
}
};Configuration Files
The loader searches for configuration in the following locations (in order):
package.json(in amyappproperty).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.
Example Config Files
.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
Automatic Environment Loading
Environment variables are automatically loaded from .env files:
.env.{NODE_ENV}(e.g.,.env.production).env
Configuration Override Pattern
Any configuration can be overridden using environment variables with the pattern:
{NAME}_CONFIG_{PATH}For example, with name: "myapp":
MYAPP_CONFIG_PORT=8080setsconfig.port = 8080MYAPP_CONFIG_DATABASE_URL=...setsconfig.databaseUrl = ...
API
loadConfig<T>(options: LoadConfigOptions<T>): Promise<ResolvedConfig<T>>
Options
| 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. |
Returns
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
}Prompt Options
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
}License
Published under the MIT license. Made by Jung von Matt TECH 💚
🤖 auto updated with automd
