@meltstudio/config-loader
A type-safe configuration loader for Node.js. Define your schema once, load from YAML, JSON, or TOML files, .env files, environment variables, and CLI arguments — and get a fully typed result with zero manual type annotations.
Upgrading from v1? v1.x is deprecated and no longer maintained. Install the latest version with
npm install @meltstudio/config-loader@latest.
Why config-loader?
Most config libraries give you Record<string, unknown> and leave you to cast or validate manually. config-loader infers TypeScript types directly from your schema definition:
import c from "@meltstudio/config-loader";
const config = c
.schema({
port: c.number({ required: true, env: "PORT" }),
database: c.object({
item: {
host: c.string({ required: true }),
credentials: c.object({
item: {
username: c.string(),
password: c.string({ env: "DB_PASSWORD", sensitive: true }),
},
}),
},
}),
features: c.array({
required: true,
item: c.object({
item: {
name: c.string(),
enabled: c.bool(),
},
}),
}),
})
.load({
env: true,
args: true,
files: "./config.yaml",
});
// config is fully typed:
// {
// port: number;
// database: { host: string; credentials: { username: string; password: string } };
// features: { name: string; enabled: boolean }[];
// }
No separate interface to maintain. No as casts. The types flow from the schema.
Features
- Full type inference — schema definition produces typed output automatically
- Multiple sources — YAML, JSON, TOML files,
.envfiles, environment variables, CLI arguments - Priority resolution — CLI > process.env >
.envfiles > Config files > Defaults .envfile support — load environment variables from.envfiles with automatic line tracking- Nested objects and arrays — deeply nested configs with full type safety
- Structured errors — typed
ConfigLoadErrorwith per-field error details and warnings - Enum constraints — restrict values to a fixed set with
oneOf, with full type narrowing - Sensitive fields — mark fields with
sensitive: trueto auto-mask inprintConfig()andmaskSecrets() - Schema validation — optional per-field validation via Standard Schema (Zod, Valibot, ArkType, or custom)
- Strict mode — promote warnings to errors for production safety
- Default values — static or computed (via functions)
- Multiple files / directory loading — load from a list of files or an entire directory
- File watching —
watch()reloads config on file changes with debouncing, change detection, and error recovery
Requirements
- Node.js >= 20
Installation
npm install @meltstudio/config-loader
pnpm add @meltstudio/config-loader
yarn add @meltstudio/config-loader
Quick Start
Create a config file in your preferred format:
- YAML
- TOML
- JSON
config.yaml
version: 1.0.0
website:
title: My Website
description: A simple and elegant website
isProduction: false
database:
host: localhost
port: 5432
credentials:
username: admin
password: secret
socialMedia: [https://twitter.com/example, https://instagram.com/example]
features:
- name: Store
enabled: true
- name: Admin
enabled: false
config.toml
version = "1.0.0"
socialMedia = ["https://twitter.com/example", "https://instagram.com/example"]
[website]
title = "My Website"
description = "A simple and elegant website"
isProduction = false
[database]
host = "localhost"
port = 5432
[database.credentials]
username = "admin"
password = "secret"
[[features]]
name = "Store"
enabled = true
[[features]]
name = "Admin"
enabled = false
config.json
{
"version": "1.0.0",
"website": {
"title": "My Website",
"description": "A simple and elegant website",
"isProduction": false
},
"database": {
"host": "localhost",
"port": 5432,
"credentials": {
"username": "admin",
"password": "secret"
}
},
"socialMedia": [
"https://twitter.com/example",
"https://instagram.com/example"
],
"features": [
{ "name": "Store", "enabled": true },
{ "name": "Admin", "enabled": false }
]
}
index.ts:
import path from "path";
import c from "@meltstudio/config-loader";
const config = c
.schema({
version: c.string({ required: true, cli: true }),
website: c.object({
item: {
title: c.string({ required: true }),
url: c.string({
required: false,
defaultValue: "www.mywebsite.dev",
}),
description: c.string({ required: true }),
isProduction: c.bool({ required: true }),
},
}),
database: c.object({
item: {
host: c.string({ required: true }),
port: c.number({ required: true }),
credentials: c.object({
item: {
username: c.string(),
password: c.string(),
},
}),
},
}),
socialMedia: c.array({
required: true,
item: c.string({ required: true }),
}),
features: c.array({
required: true,
item: c.object({
item: {
name: c.string(),
enabled: c.bool(),
},
}),
}),
})
.load({
env: false,
args: true,
files: path.join(__dirname, "./config.yaml"),
});
console.log(JSON.stringify(config, null, 2));
Output:
{
"version": "1.0.0",
"website": {
"title": "My Website",
"url": "www.mywebsite.dev",
"description": "A simple and elegant website",
"isProduction": false
},
"database": {
"host": "localhost",
"port": 5432,
"credentials": {
"username": "admin",
"password": "secret"
}
},
"socialMedia": [
"https://twitter.com/example",
"https://instagram.com/example"
],
"features": [
{ "name": "Store", "enabled": true },
{ "name": "Admin", "enabled": false }
]
}