import { InMemorySessionRepository } from '@/packages/infrastructure/repositories/InMemorySessionRepository'; import { MockBrowserAutomationAdapter } from '@/packages/infrastructure/adapters/automation/MockBrowserAutomationAdapter'; import { BrowserDevToolsAdapter } from '@/packages/infrastructure/adapters/automation/BrowserDevToolsAdapter'; import { NutJsAutomationAdapter } from '@/packages/infrastructure/adapters/automation/NutJsAutomationAdapter'; import { MockAutomationEngineAdapter } from '@/packages/infrastructure/adapters/automation/MockAutomationEngineAdapter'; import { StartAutomationSessionUseCase } from '@/packages/application/use-cases/StartAutomationSessionUseCase'; import { loadAutomationConfig, AutomationMode } from '@/packages/infrastructure/config'; import type { ISessionRepository } from '@/packages/application/ports/ISessionRepository'; import type { IBrowserAutomation } from '@/packages/application/ports/IBrowserAutomation'; import type { IAutomationEngine } from '@/packages/application/ports/IAutomationEngine'; export interface BrowserConnectionResult { success: boolean; error?: string; } /** * Create browser automation adapter based on configuration mode. * * @param mode - The automation mode from configuration * @returns IBrowserAutomation adapter instance */ function createBrowserAutomationAdapter(mode: AutomationMode): IBrowserAutomation { const config = loadAutomationConfig(); switch (mode) { case 'dev': return new BrowserDevToolsAdapter({ debuggingPort: config.devTools?.debuggingPort, browserWSEndpoint: config.devTools?.browserWSEndpoint, defaultTimeout: config.defaultTimeout, }); case 'production': return new NutJsAutomationAdapter({ mouseSpeed: config.nutJs?.mouseSpeed, keyboardDelay: config.nutJs?.keyboardDelay, defaultTimeout: config.defaultTimeout, }); case 'mock': default: return new MockBrowserAutomationAdapter(); } } export class DIContainer { private static instance: DIContainer; private sessionRepository: ISessionRepository; private browserAutomation: IBrowserAutomation; private automationEngine: IAutomationEngine; private startAutomationUseCase: StartAutomationSessionUseCase; private automationMode: AutomationMode; private constructor() { const config = loadAutomationConfig(); this.automationMode = config.mode; this.sessionRepository = new InMemorySessionRepository(); this.browserAutomation = createBrowserAutomationAdapter(config.mode); this.automationEngine = new MockAutomationEngineAdapter( this.browserAutomation, this.sessionRepository ); this.startAutomationUseCase = new StartAutomationSessionUseCase( this.automationEngine, this.browserAutomation, this.sessionRepository ); } public static getInstance(): DIContainer { if (!DIContainer.instance) { DIContainer.instance = new DIContainer(); } return DIContainer.instance; } public getStartAutomationUseCase(): StartAutomationSessionUseCase { return this.startAutomationUseCase; } public getSessionRepository(): ISessionRepository { return this.sessionRepository; } public getAutomationEngine(): IAutomationEngine { return this.automationEngine; } public getAutomationMode(): AutomationMode { return this.automationMode; } public getBrowserAutomation(): IBrowserAutomation { return this.browserAutomation; } /** * Initialize browser connection for dev mode. * In dev mode, connects to the browser via Chrome DevTools Protocol. * In mock mode, returns success immediately (no connection needed). */ public async initializeBrowserConnection(): Promise { if (this.automationMode === 'dev') { try { const devToolsAdapter = this.browserAutomation as BrowserDevToolsAdapter; await devToolsAdapter.connect(); return { success: true }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to connect to browser' }; } } if (this.automationMode === 'production') { try { const nutJsAdapter = this.browserAutomation as NutJsAutomationAdapter; const result = await nutJsAdapter.connect(); if (!result.success) { return { success: false, error: result.error }; } return { success: true }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Failed to initialize nut.js' }; } } return { success: true }; // Mock mode doesn't need connection } /** * Reset the singleton instance (useful for testing with different configurations). */ public static resetInstance(): void { DIContainer.instance = undefined as unknown as DIContainer; } }