Spring Boot-inspired configuration management for Node.js with full TypeScript support. Bring the power of Spring's configuration philosophy to your Node.js applications with type-safe, decorator-based configuration management.
- Features
- Quick Start
- Packages
- Complete Examples
- Key Features
- Performance
- Documentation
- Why Type Config?
- Requirements
- Contributing
- License
- Support
β¨ Multi-source configuration - JSON, YAML, .env files, environment variables, and remote sources
π― Type-safe bindings - Decorator-based configuration with full TypeScript support
π Profile support - Environment-based profiles (development, production, etc.)
π Dependency injection - Built-in DI container with framework-native integrations
π Encryption support - Secure sensitive configuration values with AES-256-CBC
β
Validation - Integration with class-validator for config validation
π Remote sources - AWS Parameter Store, Consul, etcd support
π Framework adapters - Native integrations for Express, Fastify, and NestJS
π¦ Monorepo architecture - Modular packages for flexible usage
| Package | Description | NPM |
|---|---|---|
| @snow-tzu/type-config | Core configuration system with multi-source loading, and encryption | |
| @snow-tzu/type-config-express | Express.js middleware integration | |
| @snow-tzu/type-config-fastify | Fastify plugin for configuration | |
| @snow-tzu/type-config-nestjs | NestJS module with native DI integration | |
| @snow-tzu/type-config-remote | Remote configuration sources (AWS, Consul, etcd) | |
| @snow-tzu/type-config-testing | Testing utilities and mocks |
Choose the package for your framework:
# For Express
npm install @snow-tzu/type-config-express reflect-metadata
# For Fastify
npm install @snow-tzu/type-config-fastify reflect-metadata
# For NestJS
npm install @snow-tzu/type-config-nestjs reflect-metadata
# Core only (no framework)
npm install @snow-tzu/type-config reflect-metadataimport 'reflect-metadata';
import { ConfigurationProperties, ConfigProperty, Required } from '@snow-tzu/type-config';
@ConfigurationProperties('server')
class ServerConfig {
@ConfigProperty() port: number = 3000;
@ConfigProperty() host: string = 'localhost';
}
@ConfigurationProperties('database')
class DatabaseConfig {
@ConfigProperty() @Required() host: string;
@ConfigProperty() port: number = 5432;
@ConfigProperty() username: string;
@ConfigProperty() password: string;
}config/application.yml (default profile)
server:
host: localhost
port: 3000
database:
host: localhost
port: 5432
username: dev_user
password: dev_passconfig/application-production.yml (production profile)
server:
host: 0.0.0.0
port: 8080
database:
host: prod-db.example.com
username: prod_user
password: ENC(iv:encrypted-value) # Encrypted passwordimport express from 'express';
import { createTypeConfig } from '@snow-tzu/type-config-express';
const app = express();
// Initialize configuration
const config = await createTypeConfig({
profile: process.env.NODE_ENV || 'development',
configDir: './config',
configClasses: [ServerConfig, DatabaseConfig]
});
// Add middleware
app.use(config.middleware());
// Access config in routes
app.get('/api/info', (req, res) => {
const serverConfig = req.container!.get(ServerConfig);
res.json({
host: serverConfig.host,
port: serverConfig.port
});
});
// Start server with config
const serverConfig = config.get(ServerConfig);
app.listen(serverConfig.port, () => {
console.log(`Server running on ${serverConfig.host}:${serverConfig.port}`);
});import Fastify from 'fastify';
import { fastifyTypeConfig } from '@snow-tzu/type-config-fastify';
const fastify = Fastify();
// Register as plugin
await fastify.register(fastifyTypeConfig, {
profile: process.env.NODE_ENV || 'development',
configDir: './config',
configClasses: [ServerConfig, DatabaseConfig]
});
// Access config in routes
fastify.get('/api/info', async (request, reply) => {
const serverConfig = request.container.get(ServerConfig);
return {
host: serverConfig.host,
port: serverConfig.port
};
});
// Start with config
const serverConfig = fastify.container.get(ServerConfig);
await fastify.listen({
port: serverConfig.port,
host: serverConfig.host
});π See the full Fastify example
// app.module.ts
import { Module } from '@nestjs/common';
import { TypeConfigModule } from '@snow-tzu/type-config-nestjs';
import { DatabaseConfig, ServerConfig } from './config';
@Module({
imports: [
// Global configuration setup
TypeConfigModule.forRoot({
profile: process.env.NODE_ENV || 'development',
configDir: './config',
isGlobal: true,
}),
// Register config classes
TypeConfigModule.forFeature([ServerConfig, DatabaseConfig])
]
})
export class AppModule {
}
// user.service.ts - Inject configuration
import { Injectable } from '@nestjs/common';
import { DatabaseConfig } from './config';
@Injectable()
export class UserService {
constructor(
// Automatically injected via NestJS DI!
private readonly dbConfig: DatabaseConfig
) {
}
async connect() {
console.log(`Connecting to ${this.dbConfig.host}:${this.dbConfig.port}`);
}
}π See the full NestJS example
import { ConfigurationBuilder } from '@snow-tzu/type-config';
const { configManager, container } = await new ConfigurationBuilder()
.withProfile('production')
.withConfigDir('./config')
.registerConfig(ServerConfig)
.registerConfig(DatabaseConfig)
.build();
// Get config instances
const serverConfig = container.get(ServerConfig);
const dbConfig = container.get(DatabaseConfig);
// Or get raw values
const port = configManager.get('server.port', 3000);Check out the examples directory for fully working projects:
- express-basic - Express.js with profiles
- fastify-basic - Fastify with plugin integration
- nestjs-basic - NestJS with dependency injection
- nestjs-remote - NestJS with remote config server
- nodejs-basic - Vanilla Node.js without frameworks
Each example includes:
- Complete TypeScript setup
- Configuration files for multiple profiles
- Environment variable support
- Docker setup (where applicable)
Load different configs based on the environment:
# Development (default)
NODE_ENV=development npm start
# Production
NODE_ENV=production npm start
# Custom profile
NODE_ENV=staging npm startFiles are merged in priority order:
application.yml(base config)application-{profile}.yml(profile-specific)- Environment variables (the highest priority)
Full TypeScript support with decorators:
import { ConfigurationProperties, ConfigProperty, Required, DefaultValue } from '@snow-tzu/type-config';
import { IsUrl, IsNumber, Min, Max } from 'class-validator';
@ConfigurationProperties('api')
@Validate() // Enable validation
class ApiConfig {
@ConfigProperty()
@Required() // Must be provided
@IsUrl() // Validate as URL
baseUrl: string;
@ConfigProperty()
@DefaultValue(5000) // Default value
@IsNumber()
@Min(1000)
@Max(30000)
timeout: number;
@ConfigProperty()
@DefaultValue(3) // Complex defaults
maxRetries: number;
}Secure sensitive values with AES-256-CBC encryption:
import { EncryptionHelper } from '@snow-tzu/type-config';
// Encrypt a value
const encryptor = new EncryptionHelper('your-32-character-secret-key!!');
const encrypted = encryptor.encrypt('my-secret-password');
console.log(encrypted); // ENC(iv:encrypted-value)
// Use in config file
// config/application-production.yml
// database:
// password: ENC(iv:encrypted-value)
// Enable decryption
const config = await createTypeConfig({
encryptionKey: process.env.ENCRYPTION_KEY,
configClasses: [DatabaseConfig]
});Load configuration from remote sources:
import { AWSParameterStoreSource, ConsulSource, EtcdSource } from '@snow-tzu/type-config-remote';
// AWS Parameter Store
const config = await createTypeConfig({
additionalSources: [
new AWSParameterStoreSource({
path: '/myapp/production',
region: 'us-east-1',
priority: 300 // Higher priority than file sources
})
]
});
// Multiple sources
const config = await new ConfigurationBuilder()
.addSource(new ConsulSource({ prefix: 'myapp/shared', priority: 250 }))
.addSource(new AWSParameterStoreSource({ path: '/myapp/prod', priority: 350 }))
.build();π See remote config example
Environment variables automatically map to nested config:
# These environment variables...
DATABASE_HOST=my-host
DATABASE_PORT=3306
SERVER_PORT=8080
# ...map to this config structure:
# database:
# host: my-host
# port: 3306
# server:
# port: 8080Type Config is designed for production use with minimal overhead:
| Operation | Performance | Assessment |
|---|---|---|
| β‘ Config Loading | 1.6k-6.2k ops/sec | Sub-millisecond for typical configs |
| π Value Retrieval | >3.2M ops/sec | Negligible overhead |
| π― Container Access | >5.9M ops/sec | Recommended (fastest) |
| πΎ Memory Usage | 1-5 MB per instance | Efficient & predictable |
The core package includes performance benchmarks:
cd packages/core
# Run all benchmarks
yarn benchmark
# Run specific benchmarks
yarn benchmark:loading # Configuration loading performance
yarn benchmark:memory # Memory usage analysis- Core Package - Core configuration system, decorators, and encryption
- Express Package - Express middleware and integration
- Fastify Package - Fastify plugin and decorators
- NestJS Package - NestJS module and DI integration
- Remote Package - AWS, Consul, and etcd sources
- Testing Package - Mock utilities for tests
- Quick Start - Get started in 5 minutes
- Project Summary - Architecture and design decisions
- Examples README - Detailed example documentation
- Contributing - How to contribute
| Feature | Type Config | @nestjs/config |
|---|---|---|
| Type-safe config classes | β Decorator-based | β Manual typing |
| Native DI injection | β Automatic | |
| Profile support | β Built-in | β Manual |
| Encryption | β Built-in AES-256 | β Manual |
| Multi-source merging | β Priority-based | |
| Remote sources | β AWS, Consul, etcd | β Manual |
| YAML support | β Native | |
| Framework support | β Express, Fastify, NestJS | β NestJS only |
| Feature | Type Config | node-config |
|---|---|---|
| Type safety | β Full TypeScript | β No types |
| Validation | β class-validator | β No validation |
| Encryption | β Built-in | β No support |
| DI integration | β All frameworks | β None |
| Profile support | β Spring-style | β Basic |
- Node.js >= 16.0.0
- TypeScript >= 5.0.0 (for TypeScript projects)
- reflect-metadata
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
MIT Β© Ganesan Arunachalam
- π Documentation
- π¬ GitHub Issues
- π§ Email Support
- π‘ Examples