UNPKG

matterbridge-roborock-vacuum-plugin

Version:
191 lines 8.55 kB
import { RoborockAuthGateway } from '../roborockCommunication/adapters/RoborockAuthGateway.js'; import { RoborockAuthenticateApi } from '../roborockCommunication/api/authClient.js'; import { RoborockIoTApi } from '../roborockCommunication/api/iotClient.js'; import { AreaManagementService } from './areaManagementService.js'; import { AuthenticationCoordinator } from './authentication/AuthenticationCoordinator.js'; import { AuthenticationStateRepository } from './authentication/AuthenticationStateRepository.js'; import { PasswordAuthStrategy } from './authentication/PasswordAuthStrategy.js'; import { TwoFactorAuthStrategy } from './authentication/TwoFactorAuthStrategy.js'; import { UserDataRepository } from './authentication/UserDataRepository.js'; import { VerificationCodeService } from './authentication/VerificationCodeService.js'; import { AuthenticationService } from './authenticationService.js'; import ClientManager from './clientManager.js'; import { ConnectionService } from './connectionService.js'; import { DeviceManagementService } from './deviceManagementService.js'; import { MessageRoutingService } from './messageRoutingService.js'; import { PollingService } from './pollingService.js'; /** DI container managing service lifecycle. Services are lazily created and cached. */ export class ServiceContainer { logger; config; // Cached service instances (singletons) authenticationCoordinator; deviceManagementService; areaManagementService; messageRoutingService; pollingService; connectionService; // Shared infrastructure authenticateApi; authenticateApiFactory; iotApiFactory; clientManager; authGateway; // User data (set after authentication) userdata; iotApi; constructor(logger, config) { this.logger = logger; this.config = config; // Set up factory functions with defaults this.authenticateApiFactory = config.authenticateApiFactory ?? ((logger, baseUrl) => new RoborockAuthenticateApi(logger, undefined, undefined, baseUrl)); this.iotApiFactory = config.iotApiFactory ?? ((logger, ud) => new RoborockIoTApi(ud, logger)); this.clientManager = new ClientManager(this.logger); // Create login API instance this.authenticateApi = this.authenticateApiFactory(logger, config.baseUrl); this.authGateway = new RoborockAuthGateway(this.authenticateApi, this.logger); } /** Set user data after login to enable device services. */ setUserData(userdata) { this.userdata = userdata; this.iotApi = this.iotApiFactory(this.logger, userdata); // Update existing services if they're already created if (this.deviceManagementService) { this.deviceManagementService.setIotApi(this.iotApi); this.deviceManagementService.setAuthentication(userdata); } if (this.areaManagementService && this.iotApi) { this.areaManagementService.setIotApi(this.iotApi); } if (this.messageRoutingService && this.iotApi) { this.messageRoutingService.setIotApi(this.iotApi); } } /** Get or create AuthenticationCoordinator singleton. */ getAuthenticationCoordinator() { if (!this.authenticationCoordinator) { // Create core authentication service const authService = new AuthenticationService(this.authGateway, this.logger); // Create repositories const userDataRepository = new UserDataRepository(this.config.persist, this.config.configManager, this.logger); const authStateRepository = new AuthenticationStateRepository(this.config.persist); // Create verification code service const verificationCodeService = new VerificationCodeService(this.authGateway, authStateRepository, this.logger); // Create strategies const passwordStrategy = new PasswordAuthStrategy(authService, userDataRepository, this.config.configManager, this.logger); const twoFactorStrategy = new TwoFactorAuthStrategy(authService, userDataRepository, verificationCodeService, this.config.configManager, this.config.toastMessage, this.logger); // Create coordinator this.authenticationCoordinator = new AuthenticationCoordinator(passwordStrategy, twoFactorStrategy, this.logger); } return this.authenticationCoordinator; } /** Get or create PollingService singleton. */ getPollingService() { this.pollingService ??= new PollingService(this.config.refreshInterval, this.logger, this.getMessageRoutingService()); return this.pollingService; } /** Get or create DeviceManagementService singleton. Requires setUserData() after login. */ getDeviceManagementService() { this.deviceManagementService ??= new DeviceManagementService(this.logger, this.authenticateApi, this.userdata); return this.deviceManagementService; } /** * Get or create the AreaManagementService singleton. * * Note: Requires user authentication. Call setUserData() after login. * * @returns AreaManagementService instance */ getAreaManagementService() { this.areaManagementService ??= new AreaManagementService(this.logger, this.getMessageRoutingService()); return this.areaManagementService; } /** * Get or create the MessageRoutingService singleton. * * Note: Requires user authentication. Call setUserData() after login. * * @returns MessageRoutingService instance */ getMessageRoutingService() { this.messageRoutingService ??= new MessageRoutingService(this.logger, this.iotApi); return this.messageRoutingService; } getConnectionService() { return (this.connectionService ??= new ConnectionService(this.clientManager, this.logger, this.getMessageRoutingService(), this.config.configManager)); } synchronizeMessageClients() { const clientRouter = this.connectionService?.clientRouter; if (!clientRouter) { throw new Error('Message client not initialized in ConnectionService'); } this.areaManagementService?.setMessageClient(clientRouter); } /** * Get all services as a bundle. * Useful for passing to RoborockService facade. */ getAllServices() { return { authenticationCoordinator: this.getAuthenticationCoordinator(), deviceManagement: this.getDeviceManagementService(), areaManagement: this.getAreaManagementService(), messageRouting: this.getMessageRoutingService(), polling: this.getPollingService(), connection: this.getConnectionService(), }; } /** Destroy all services and clear cached instances. */ async destroy() { // Shutdown polling service first if (this.pollingService) { await this.pollingService.shutdown(); } if (this.connectionService) { await this.connectionService.shutdown(); this.connectionService = undefined; } if (this.messageRoutingService) { this.messageRoutingService.clearAll(); this.messageRoutingService = undefined; } if (this.areaManagementService) { this.areaManagementService.clearAll(); this.areaManagementService = undefined; } if (this.deviceManagementService) { this.deviceManagementService.stopService(); this.deviceManagementService = undefined; } if (this.authenticationCoordinator) { this.authenticationCoordinator = undefined; } if (this.pollingService) { await this.pollingService.shutdown(); this.pollingService = undefined; } // Clear user data this.userdata = undefined; this.iotApi = undefined; this.logger.debug('ServiceContainer destroyed'); } /** Get logger instance. */ getLogger() { return this.logger; } /** Get ClientManager instance. */ getClientManager() { return this.clientManager; } /** Get current user data (undefined if not authenticated). */ getUserData() { return this.userdata; } /** Get IoT API (undefined if not authenticated). */ getIotApi() { return this.iotApi; } } //# sourceMappingURL=serviceContainer.js.map