@thalorlabs/config
v1.1.1
Published
Centralized runtime config loading for ThalorLabs projects with AWS Parameter Store and Secrets Manager integration
Readme
@thalorlabs/config
A TypeScript configuration package for ThalorLabs projects, providing centralized runtime config loading with AWS Parameter Store and Secrets Manager integration.
Installation
npm install @thalorlabs/configFeatures
- Environment Variable Loading - Load and validate environment variables
- AWS Parameter Store Integration - Fetch configuration parameters from AWS SSM
- AWS Secrets Manager Integration - Securely retrieve secrets from AWS Secrets Manager
- Environment Normalization - Normalize configuration across environments (dev, sit, uat, prod)
- Type Safety - Full TypeScript support with Zod schema validation
- No Business Logic - Pure configuration loading without application logic
Usage
Basic Configuration Loading
import { ConfigLoader } from '@thalorlabs/config';
const config = await ConfigLoader.load({
environment: 'production',
region: 'us-east-1',
parameterPrefix: '/myapp/prod',
secretPrefix: '/myapp/secrets'
});
console.log(config.database.url);
console.log(config.api.keys.stripe);Environment-Specific Configuration
import { ConfigLoader, Environment } from '@thalorlabs/config';
// Automatically loads environment-specific parameters
const config = await ConfigLoader.load({
environment: Environment.PRODUCTION,
region: 'us-east-1',
parameterPrefix: '/myapp',
secretPrefix: '/myapp/secrets'
});
// Config is normalized for production environment
console.log(config.database.url); // Production database URL
console.log(config.logging.level); // 'error' in productionCustom Configuration Schema
import { ConfigLoader, z } from '@thalorlabs/config';
const AppConfigSchema = z.object({
database: z.object({
url: z.string().url(),
maxConnections: z.number().min(1).max(100),
}),
api: z.object({
port: z.number().min(1000).max(65535),
timeout: z.number().min(1000),
}),
logging: z.object({
level: z.enum(['debug', 'info', 'warn', 'error']),
format: z.enum(['json', 'text']),
}),
});
const config = await ConfigLoader.load({
environment: 'development',
region: 'us-east-1',
parameterPrefix: '/myapp/dev',
secretPrefix: '/myapp/secrets',
schema: AppConfigSchema
});
// Type-safe access to configuration
const dbUrl: string = config.database.url;
const logLevel: 'debug' | 'info' | 'warn' | 'error' = config.logging.level;Environment Variables Only
import { ConfigLoader } from '@thalorlabs/config';
// Load only from environment variables
const config = await ConfigLoader.loadFromEnv({
schema: AppConfigSchema,
envPrefix: 'MYAPP_' // Only loads MYAPP_* variables
});
console.log(config.database.url); // From MYAPP_DATABASE_URLConfiguration Sources
1. Environment Variables
The loader automatically reads environment variables and maps them to configuration keys:
# Environment variables
MYAPP_DATABASE_URL=postgresql://localhost:5432/myapp
MYAPP_API_PORT=3000
MYAPP_LOGGING_LEVEL=info2. AWS Parameter Store
Parameters are loaded from AWS SSM Parameter Store:
// Parameters in AWS SSM:
// /myapp/prod/database/url
// /myapp/prod/api/port
// /myapp/prod/logging/level
const config = await ConfigLoader.load({
environment: 'production',
region: 'us-east-1',
parameterPrefix: '/myapp/prod'
});3. AWS Secrets Manager
Secrets are securely retrieved from AWS Secrets Manager:
// Secrets in AWS Secrets Manager:
// /myapp/secrets/database/password
// /myapp/secrets/api/keys/stripe
const config = await ConfigLoader.load({
environment: 'production',
region: 'us-east-1',
parameterPrefix: '/myapp/prod',
secretPrefix: '/myapp/secrets'
});Environment Normalization
The package automatically normalizes configuration based on the environment:
Development Environment
- Logging level:
debug - Database connections: Lower limits
- API timeouts: Longer for debugging
Production Environment
- Logging level:
error - Database connections: Higher limits
- API timeouts: Optimized for performance
import { Environment } from '@thalorlabs/config';
const config = await ConfigLoader.load({
environment: Environment.DEVELOPMENT, // or 'dev'
// ... other options
});
// Automatically normalized for development
console.log(config.logging.level); // 'debug'
console.log(config.database.maxConnections); // Lower limitAvailable Types
Core Types
| Type | Description | Usage |
| ----------------------- | ---------------------------------------------- | ------------------------------------ |
| ConfigLoader | Main configuration loading class | ConfigLoader.load(options) |
| ConfigOptions | Configuration loading options | ConfigLoader.load(options) |
| Environment | Environment enum (dev, sit, uat, prod) | Environment.PRODUCTION |
| ConfigSchema | Base configuration schema type | z.object({ ... }) |
AWS Integration Types
| Type | Description | Usage |
| ----------------------- | ---------------------------------------------- | ------------------------------------ |
| ParameterStoreConfig | AWS Parameter Store configuration | { parameterPrefix: '/myapp' } |
| SecretsManagerConfig | AWS Secrets Manager configuration | { secretPrefix: '/myapp/secrets' } |
| AWSConfig | Combined AWS configuration | { region: 'us-east-1', ... } |
Configuration Hierarchy
Configuration values are loaded in the following order (later sources override earlier ones):
- Default values (from schema)
- Environment variables (with prefix)
- AWS Parameter Store (environment-specific)
- AWS Secrets Manager (environment-specific)
Error Handling
import { ConfigLoader, ConfigError } from '@thalorlabs/config';
try {
const config = await ConfigLoader.load({
environment: 'production',
region: 'us-east-1',
parameterPrefix: '/myapp/prod'
});
} catch (error) {
if (error instanceof ConfigError) {
console.error('Configuration error:', error.message);
console.error('Missing parameters:', error.missingParameters);
}
}AWS Permissions
Your AWS credentials need the following permissions:
Parameter Store Permissions
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:GetParametersByPath"
],
"Resource": "arn:aws:ssm:*:*:parameter/myapp/*"
}
]
}Secrets Manager Permissions
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue"
],
"Resource": "arn:aws:secretsmanager:*:*:secret:myapp/secrets/*"
}
]
}Project Structure
src/
├── index.ts # Main exports
├── types/ # Type definitions
│ ├── Config.ts # Configuration types and schemas
│ ├── Environment.ts # Environment enum and types
│ └── AWS.ts # AWS integration types
├── loaders/ # Configuration loaders
│ ├── ConfigLoader.ts # Main configuration loader
│ ├── ParameterStoreLoader.ts # AWS Parameter Store loader
│ └── SecretsManagerLoader.ts # AWS Secrets Manager loader
└── normalizers/ # Environment normalizers
└── EnvironmentNormalizer.ts # Environment-specific normalizationTypeScript Support
This package includes full TypeScript support with:
- Complete type definitions
- Zod schema validation
- IntelliSense support
- Compile-time type checking
- AWS SDK integration
Best Practices
Schema Definition
Always define your configuration schema with proper validation:
const AppConfigSchema = z.object({
database: z.object({
url: z.string().url('Invalid database URL'),
maxConnections: z.number().min(1).max(100, 'Invalid connection limit'),
}),
api: z.object({
port: z.number().min(1000).max(65535, 'Invalid port number'),
timeout: z.number().min(1000, 'Timeout too short'),
}),
});Environment Separation
Use environment-specific parameter prefixes:
// Development
parameterPrefix: '/myapp/dev'
// Production
parameterPrefix: '/myapp/prod'Secret Management
Store sensitive data in AWS Secrets Manager:
// Store in Secrets Manager: /myapp/secrets/database/password
// Access via: config.database.passwordDevelopment
Building
npm run buildTesting
npm testType Checking
npx tsc --noEmitLicense
ISC
