@mightyacorndigital/config
v1.0.1
Published
A configuration management library for TypeScript projects.
Maintainers
Readme
@mightyacorndigital/config
A lightweight TypeScript configuration fetching and validation library built on Zod. Provides type-safe configuration resolution from arbitrary sources (environment variables, AWS Secrets Manager, etc.) with runtime validation.
Features
- Flexible sources - Use static objects, accessor functions, or async sources (Promises)
- Type-safe - Full TypeScript support with inferred types from your Zod schema
- Lazy resolution - Configuration values are validated on access, not at startup
- Bulk validation - Validate all configuration at once to catch errors early
- CLI tools - Validate configuration and generate
.envtemplates from schemas
Installation
npm install @mightyacorndigital/config zodUsage
Define a Schema
// config/schema.ts
import { z } from "zod";
const schema = z.object({
DATABASE_URL: z.url().meta({
title: "Database URL",
description: "PostgreSQL connection string",
examples: ["postgres://user:password@localhost:5432/mydb"],
}),
API_KEY: z.string(),
PORT: z.coerce.number().default(3000),
});
export default schema;Synchronous Resolution
Use ConfigResolver when your configuration source is synchronous (e.g., environment variables):
import { ConfigResolver } from "@mightyacorndigital/config";
import schema from "./config/schema";
const config = new ConfigResolver(schema, process.env);
// Get individual values (validated on access)
const dbUrl = config.get("DATABASE_URL"); // string (validated URL)
const port = config.get("PORT"); // number
// Validate all configuration at once
const errors = config.validate();
if (errors) {
console.error("Configuration errors:", errors);
process.exit(1);
}Asynchronous Resolution
Use AsyncConfigResolver when fetching configuration from async sources like AWS Secrets Manager:
import { AsyncConfigResolver } from "@mightyacorndigital/config";
import { SecretsManager } from "@aws-sdk/client-secrets-manager";
const secretsManager = new SecretsManager();
const config = new AsyncConfigResolver(schema, async (key) => {
const secret = await secretsManager.getSecretValue({ SecretId: "my-app-config" });
return JSON.parse(secret.SecretString!);
});
// Get values asynchronously
const dbUrl = await config.get("DATABASE_URL");
// Validate all configuration
const errors = await config.validate();Source Types
Both resolvers accept flexible source types:
// Static object
new ConfigResolver(schema, process.env);
new ConfigResolver(schema, { DATABASE_URL: "...", API_KEY: "..." });
// Accessor function (called per-key)
new ConfigResolver(schema, (key) => myConfigStore.get(key));
// Async sources
new AsyncConfigResolver(schema, fetchConfigFromRemote());
new AsyncConfigResolver(schema, async (key) => fetchSecret(key));CLI
The package includes a CLI for common configuration tasks.
Validate Configuration
Validate a configuration file that exports a ConfigResolver or AsyncConfigResolver:
npx config-cli validate ./config.jsThe config file should have a default export:
// config.js
import { ConfigResolver } from "@mightyacorndigital/config";
import schema from "./schema.js";
export default new ConfigResolver(schema, process.env);Generate .env Template
Generate a .env template file from a Zod schema:
npx config-cli generate-env ./schema.js > .env.exampleThe schema file should have a default export:
// schema.js
import { z } from "zod";
export default z.object({
DATABASE_URL: z.url().meta({
title: "Database URL",
description: "PostgreSQL connection string",
examples: ["postgres://localhost:5432/mydb"],
}),
API_KEY: z.string().meta({
title: "API Key",
}),
DEBUG: z.boolean().default(false),
});Output:
# Database URL
# PostgreSQL connection string
DATABASE_URL=postgres://localhost:5432/mydb
# API Key
API_KEY=your_value_here
# DEBUG=false # default valueError Handling
The library provides typed errors for different failure scenarios:
InvalidConfigKeyError- Requested key not in schemaConfigValidationError- Value failed Zod validationConfigSourceError- Source function threw an error
All errors extend ConfigError and preserve the original cause for debugging.
License
MIT
