Skip to content

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-key

Environment 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 ​

  1. Use hierarchical configuration with clear precedence order
  2. Validate configuration at application startup
  3. Use environment-specific files for different deployment stages
  4. Keep sensitive data in environment variables or secure vaults
  5. Document all configuration options with examples
  6. Use TypeScript interfaces to define configuration structure
  7. Implement configuration hot-reloading for non-critical settings

Security ​

  1. Never commit secrets to version control
  2. Use secure configuration stores for production
  3. Rotate secrets regularly
  4. Limit configuration access to necessary personnel
  5. Audit configuration changes

Performance ​

  1. Cache configuration values for frequently accessed settings
  2. Use lazy loading for expensive configuration operations
  3. Minimize configuration file size
  4. Use efficient serialization formats (JSON vs XML vs YAML)

Next Steps ​