ConfigurationManager.ts•4.83 kB
// Import config types for services as they are added
import { ExampleServiceConfig } from '../types/index.js';
// Define the structure for all configurations managed
interface ManagedConfigs {
    exampleService: Required<ExampleServiceConfig>;
// Add other service config types here:
    // yourService: Required<YourServiceConfig>;
    databasePath: string; // Added for database file location
}
/**
 * Centralized configuration management for all services.
 * Implements singleton pattern to ensure consistent configuration.
 */
export class ConfigurationManager {
    private static instance: ConfigurationManager | null = null;
    private static instanceLock = false;
    private config: ManagedConfigs;
    private constructor() {
        // Initialize with default configurations
        this.config = {
            exampleService: {
                // Define defaults for ExampleService
                greeting: "Hello",
                enableDetailedLogs: false,
            },
            // Initialize other service configs with defaults:
            // yourService: {
            //   someSetting: 'default value',
            //   retryCount: 3,
            // },
            // Default database path
            databasePath: './data/taskmanager.db',
        };
        // Optional: Load overrides from environment variables or config files here
        this.loadEnvironmentOverrides();
    }
    /**
     * Get the singleton instance of ConfigurationManager.
     * Basic lock to prevent race conditions during initial creation.
     */
    public static getInstance(): ConfigurationManager {
        if (!ConfigurationManager.instance) {
            if (!ConfigurationManager.instanceLock) {
                ConfigurationManager.instanceLock = true; // Lock
                try {
                    ConfigurationManager.instance = new ConfigurationManager();
                } finally {
                    ConfigurationManager.instanceLock = false; // Unlock
                }
            } else {
                // Basic busy wait if locked (consider a more robust async lock if high contention is expected)
                while (ConfigurationManager.instanceLock) { }
                // Re-check instance after wait
                if (!ConfigurationManager.instance) {
                    // This path is less likely but handles edge cases if lock logic needs refinement
                    return ConfigurationManager.getInstance();
                }
            }
        }
        return ConfigurationManager.instance;
    }
    // --- Getters for specific configurations ---
    public getExampleServiceConfig(): Required<ExampleServiceConfig> {
        // Return a copy to prevent accidental modification of the internal state
        return { ...this.config.exampleService };
    }
    // Add getters for other service configs:
    // public getYourServiceConfig(): Required<YourServiceConfig> {
    //   return { ...this.config.yourService };
    // }
    public getDatabasePath(): string {
        // Return a copy to prevent accidental modification (though less critical for a string)
        return this.config.databasePath;
    }
    // --- Updaters for specific configurations (if runtime updates are needed) ---
    public updateExampleServiceConfig(update: Partial<ExampleServiceConfig>): void {
        this.config.exampleService = {
            ...this.config.exampleService,
            ...update,
        };
        // Optional: Notify relevant services about the config change
    }
    // Add updaters for other service configs:
    // public updateYourServiceConfig(update: Partial<YourServiceConfig>): void {
    //   this.config.yourService = {
    //     ...this.config.yourService,
    //     ...update,
    //   };
    // }
    /**
     * Example method to load configuration overrides from environment variables.
     * Call this in the constructor.
     */
    private loadEnvironmentOverrides(): void {
        // Example for ExampleService
        if (process.env.EXAMPLE_GREETING) {
            this.config.exampleService.greeting = process.env.EXAMPLE_GREETING;
        }
        if (process.env.EXAMPLE_ENABLE_LOGS) {
            this.config.exampleService.enableDetailedLogs = process.env.EXAMPLE_ENABLE_LOGS.toLowerCase() === 'true';
        }
        // Override for Database Path
        if (process.env.DATABASE_PATH) {
            this.config.databasePath = process.env.DATABASE_PATH;
        }
        // Add logic for other services based on their environment variables
        // if (process.env.YOUR_SERVICE_RETRY_COUNT) {
        //   const retryCount = parseInt(process.env.YOUR_SERVICE_RETRY_COUNT, 10);
        //   if (!isNaN(retryCount)) {
        //     this.config.yourService.retryCount = retryCount;
        //   }
        // }
    }
}