Configuration Reference ​
This guide provides comprehensive information about configuring ziegel applications and individual packages.
Global Configuration ​
Application Bootstrap ​
Every ziegel application should follow this basic configuration pattern:
typescript
import { ServiceLocator } from '@breadstone/ziegel-platform';
import { ConfigurationManager } from '@breadstone/ziegel-platform-configuration';
import { LoggerManager } from '@breadstone/ziegel-platform-logging';
class Application {
async initialize() {
// 1. Setup configuration
const config = await this.setupConfiguration();
ServiceLocator.register('config', () => config);
// 2. Setup logging
await this.setupLogging(config);
// 3. Setup platform services
await this.setupPlatformServices(config);
// 4. Setup application services
await this.setupApplicationServices(config);
}
private async setupConfiguration(): Promise<ConfigurationManager> {
const config = new ConfigurationManager();
// Load configuration in order of precedence
await config.addJsonFile('appsettings.json');
await config.addJsonFile(`appsettings.${process.env.NODE_ENV}.json`);
config.addEnvironmentVariables();
return config;
}
}Package-Specific Configuration ​
ziegel-platform-configuration ​
Configuration Sources ​
typescript
import {
ConfigurationManager,
JsonFileProvider,
EnvironmentVariableProvider,
MemoryProvider
} from '@breadstone/ziegel-platform-configuration';
const config = new ConfigurationManager();
// JSON file configuration
await config.addProvider(new JsonFileProvider('appsettings.json'));
await config.addProvider(new JsonFileProvider('appsettings.production.json'));
// Environment variables
config.addProvider(new EnvironmentVariableProvider('MYAPP_'));
// In-memory configuration (highest priority)
config.addProvider(new MemoryProvider(new Map([
['feature:beta', 'true'],
['debug:enabled', 'false']
])));Configuration Schema ​
Define your configuration structure with TypeScript interfaces:
typescript
interface ApplicationConfiguration {
database: {
connectionString: string;
timeout: number;
poolSize: number;
enableLogging: boolean;
};
api: {
baseUrl: string;
timeout: number;
retryAttempts: number;
enableCaching: boolean;
};
logging: {
level: 'debug' | 'info' | 'warning' | 'error';
providers: Array<{
type: 'console' | 'file' | 'remote';
options: Record<string, any>;
}>;
};
features: {
enableAnalytics: boolean;
enableInternationalization: boolean;
maxFileUploadSize: number;
};
}Environment-Specific Configuration ​
json
// appsettings.json (defaults)
{
"database": {
"connectionString": "Server=localhost;Database=DevDB;",
"timeout": 30000,
"poolSize": 10,
"enableLogging": true
},
"api": {
"baseUrl": "https://dev-api.example.com",
"timeout": 5000,
"retryAttempts": 3,
"enableCaching": true
},
"logging": {
"level": "debug",
"providers": [
{
"type": "console",
"options": { "colorize": true }
}
]
}
}json
// appsettings.production.json (production overrides)
{
"database": {
"connectionString": "Server=prod-server;Database=ProdDB;",
"enableLogging": false
},
"api": {
"baseUrl": "https://api.example.com"
},
"logging": {
"level": "warning",
"providers": [
{
"type": "file",
"options": { "filename": "app.log" }
},
{
"type": "remote",
"options": { "endpoint": "https://logs.example.com" }
}
]
}
}ziegel-platform-logging ​
Logger Configuration ​
typescript
import {
LoggerManager,
LogLevel,
ConsoleLogProvider,
FileLogProvider,
RemoteLogProvider
} from '@breadstone/ziegel-platform-logging';
// Configure based on environment
if (process.env.NODE_ENV === 'production') {
LoggerManager.configure({
level: LogLevel.Warning,
providers: [
new FileLogProvider({
filename: 'logs/app.log',
maxFileSize: 10 * 1024 * 1024, // 10MB
maxFiles: 5,
format: 'json'
}),
new RemoteLogProvider({
endpoint: 'https://logging-service.example.com/api/logs',
apiKey: process.env.LOGGING_API_KEY,
batchSize: 100,
flushInterval: 5000
})
]
});
} else {
LoggerManager.configure({
level: LogLevel.Debug,
providers: [
new ConsoleLogProvider({
colorize: true,
timestamp: true,
format: 'simple'
})
]
});
}Custom Log Providers ​
typescript
import { ILogProvider, LogLevel, LogEntry } from '@breadstone/ziegel-platform-logging';
class CustomLogProvider implements ILogProvider {
constructor(private options: CustomLogOptions) {}
async log(entry: LogEntry): Promise<void> {
// Custom logging implementation
await this.sendToCustomService(entry);
}
isEnabled(level: LogLevel): boolean {
return level >= this.options.minimumLevel;
}
}
// Register custom provider
LoggerManager.configure({
providers: [
new CustomLogProvider({
minimumLevel: LogLevel.Info,
serviceUrl: 'https://custom-logging.example.com'
})
]
});ziegel-platform-http ​
HTTP Client Configuration ​
typescript
import { HttpClient, HttpInterceptor } from '@breadstone/ziegel-platform-http';
const httpClient = new HttpClient('https://api.example.com', {
timeout: 10000,
retryAttempts: 3,
retryDelay: 1000,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
});
// Authentication interceptor
class AuthInterceptor implements HttpInterceptor {
async intercept(request: Request): Promise<Request> {
const token = await this.getAuthToken();
if (token) {
request.headers.set('Authorization', `Bearer ${token}`);
}
return request;
}
}
// Error handling interceptor
class ErrorInterceptor implements HttpInterceptor {
async intercept(request: Request): Promise<Request> {
// Add request ID for tracking
request.headers.set('X-Request-ID', this.generateRequestId());
return request;
}
async onResponse(response: Response): Promise<Response> {
if (!response.ok) {
const error = await response.json();
throw new HttpError(response.status, error.message);
}
return response;
}
}
httpClient.addInterceptor(new AuthInterceptor());
httpClient.addInterceptor(new ErrorInterceptor());ziegel-platform-localization ​
Localization Configuration ​
typescript
import {
LocalizationManager,
LoaderLocalizationProvider,
HttpLocalizationLoader,
CamelCaseKeyResolver
} from '@breadstone/ziegel-platform-localization';
// HTTP-based localization
const httpLoader = new HttpLocalizationLoader('/api/localization/{culture}.json');
const provider = new LoaderLocalizationProvider(httpLoader);
const localizationManager = new LocalizationManager(
provider,
cultureProvider,
// Missing translation handler
(key, culture) => {
console.warn(`Missing translation: ${key} for culture: ${culture}`);
return `[${key}]`;
},
// Cache configuration
new LocalizationCache({
maxSize: 1000,
ttl: 3600000 // 1 hour
}),
// Value parsers
[
new FormatLocalizationValueParser(),
new RefLocalizationValueParser()
]
);
// Key resolver for different naming conventions
localizationManager.setKeyResolver(new CamelCaseKeyResolver());Translation Resource Structure ​
json
// en-US.json
{
"common": {
"welcome": "Welcome",
"goodbye": "Goodbye",
"loading": "Loading..."
},
"user": {
"profile": {
"title": "User Profile",
"name": "Name",
"email": "Email Address"
},
"messages": {
"created": "User created successfully",
"updated": "User updated successfully",
"deleted": "User deleted successfully"
}
},
"validation": {
"required": "This field is required",
"email": "Please enter a valid email address",
"minLength": "Minimum length is {0} characters"
}
}ziegel-platform-caching ​
Cache Configuration ​
typescript
import {
CacheManager,
MemoryCacheProvider,
RedisCacheProvider,
CachePolicy
} from '@breadstone/ziegel-platform-caching';
// Memory cache for development
const memoryCache = new MemoryCacheProvider({
maxSize: 1000,
defaultTtl: 300000, // 5 minutes
cleanupInterval: 60000 // 1 minute
});
// Redis cache for production
const redisCache = new RedisCacheProvider({
host: 'redis.example.com',
port: 6379,
password: process.env.REDIS_PASSWORD,
database: 0,
keyPrefix: 'myapp:'
});
const cacheManager = new CacheManager(
process.env.NODE_ENV === 'production' ? redisCache : memoryCache
);
// Cache policies
const userCachePolicy = new CachePolicy({
ttl: 900000, // 15 minutes
refreshThreshold: 0.8, // Refresh when 80% of TTL elapsed
maxStale: 300000 // Allow stale data for 5 minutes during refresh
});
cacheManager.setPolicy('users', userCachePolicy);ziegel-platform-analytics ​
Analytics Configuration ​
typescript
import {
AnalyticsManager,
GoogleAnalyticsProvider,
CustomAnalyticsProvider
} from '@breadstone/ziegel-platform-analytics';
const analyticsManager = new AnalyticsManager();
// Google Analytics
analyticsManager.addProvider(new GoogleAnalyticsProvider({
trackingId: 'GA_TRACKING_ID',
enableEnhancedEcommerce: true,
anonymizeIp: true
}));
// Custom analytics
analyticsManager.addProvider(new CustomAnalyticsProvider({
endpoint: 'https://analytics.example.com/api/events',
apiKey: process.env.ANALYTICS_API_KEY,
batchSize: 50,
flushInterval: 30000
}));
// Configure event tracking
analyticsManager.configure({
enableAutoPageTracking: true,
enableErrorTracking: true,
enablePerformanceTracking: true,
samplingRate: 0.1 // 10% sampling
});Environment Variables ​
Standard Environment Variables ​
bash
# Application Environment
NODE_ENV=production
APP_ENV=production
# Database Configuration
DB_CONNECTION_STRING=Server=prod-server;Database=ProdDB;
DB_TIMEOUT=30000
DB_POOL_SIZE=20
# API Configuration
API_BASE_URL=https://api.example.com
API_TIMEOUT=10000
API_RETRY_ATTEMPTS=3
# Logging Configuration
LOG_LEVEL=warning
LOG_FILE_PATH=/var/logs/app.log
LOG_REMOTE_ENDPOINT=https://logs.example.com
# Cache Configuration
REDIS_HOST=redis.example.com
REDIS_PORT=6379
REDIS_PASSWORD=your-redis-password
# Authentication
JWT_SECRET=your-jwt-secret
AUTH_TOKEN_EXPIRY=3600
# Feature Flags
FEATURE_ANALYTICS=true
FEATURE_INTERNATIONALIZATION=true
FEATURE_CACHING=true
# Third-party Services
GOOGLE_ANALYTICS_ID=GA_TRACKING_ID
OPENAI_API_KEY=your-openai-keyEnvironment Variable Naming Convention ​
ziegel follows a hierarchical naming convention for environment variables:
bash
# Format: PREFIX_SECTION__SUBSECTION__PROPERTY
MYAPP_DATABASE__CONNECTION_STRING=value
MYAPP_API__BASE_URL=value
MYAPP_LOGGING__LEVEL=value
# Maps to configuration structure:
{
"database": {
"connectionString": "value"
},
"api": {
"baseUrl": "value"
},
"logging": {
"level": "value"
}
}Docker Configuration ​
Dockerfile Example ​
dockerfile
FROM node:18-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
RUN npm ci --only=production
# Copy application code
COPY . .
# Build application
RUN npm run build
# Set environment variables
ENV NODE_ENV=production
ENV LOG_LEVEL=info
# Expose port
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# Start application
CMD ["node", "dist/index.js"]Docker Compose Example ​
yaml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_CONNECTION_STRING=Server=db;Database=AppDB;User=app;Password=password;
- REDIS_HOST=redis
- LOG_LEVEL=info
depends_on:
- db
- redis
volumes:
- ./logs:/app/logs
db:
image: postgres:14
environment:
- POSTGRES_DB=AppDB
- POSTGRES_USER=app
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:Configuration Validation ​
Runtime Validation ​
typescript
import { ConfigurationManager } from '@breadstone/ziegel-platform-configuration';
class ConfigurationValidator {
static validate(config: ConfigurationManager): void {
const requiredSettings = [
'database:connectionString',
'api:baseUrl',
'logging:level'
];
const errors: string[] = [];
for (const setting of requiredSettings) {
if (!config.hasValue(setting)) {
errors.push(`Missing required configuration: ${setting}`);
}
}
// Validate specific values
const logLevel = config.getValue<string>('logging:level');
if (!['debug', 'info', 'warning', 'error'].includes(logLevel)) {
errors.push(`Invalid log level: ${logLevel}`);
}
const apiTimeout = config.getValue<number>('api:timeout', 5000);
if (apiTimeout < 1000 || apiTimeout > 60000) {
errors.push(`API timeout must be between 1000 and 60000ms: ${apiTimeout}`);
}
if (errors.length > 0) {
throw new Error(`Configuration validation failed:\n${errors.join('\n')}`);
}
}
}
// Use in application startup
const config = new ConfigurationManager();
await config.loadConfiguration();
ConfigurationValidator.validate(config);Schema Validation ​
typescript
import Joi from 'joi';
const configSchema = Joi.object({
database: Joi.object({
connectionString: Joi.string().required(),
timeout: Joi.number().min(1000).max(60000).default(30000),
poolSize: Joi.number().min(1).max(100).default(10)
}).required(),
api: Joi.object({
baseUrl: Joi.string().uri().required(),
timeout: Joi.number().min(1000).max(60000).default(5000),
retryAttempts: Joi.number().min(0).max(10).default(3)
}).required(),
logging: Joi.object({
level: Joi.string().valid('debug', 'info', 'warning', 'error').default('info'),
providers: Joi.array().items(
Joi.object({
type: Joi.string().valid('console', 'file', 'remote').required(),
options: Joi.object().default({})
})
).min(1).required()
}).required()
});
// Validate configuration
const { error, value } = configSchema.validate(configObject);
if (error) {
throw new Error(`Configuration validation failed: ${error.message}`);
}Best Practices ​
Configuration Management ​
- Use hierarchical configuration with clear precedence order
- Validate configuration at application startup
- Use environment-specific files for different deployment stages
- Keep sensitive data in environment variables or secure vaults
- Document all configuration options with examples
- Use TypeScript interfaces to define configuration structure
- Implement configuration hot-reloading for non-critical settings
Security ​
- Never commit secrets to version control
- Use secure configuration stores for production
- Rotate secrets regularly
- Limit configuration access to necessary personnel
- Audit configuration changes
Performance ​
- Cache configuration values for frequently accessed settings
- Use lazy loading for expensive configuration operations
- Minimize configuration file size
- Use efficient serialization formats (JSON vs XML vs YAML)
Next Steps ​
- Best Practices - General ziegel best practices
- Troubleshooting - Common configuration issues
- Examples - Practical configuration examples