import { HealthStatus } from '@waku/sdk'; import { OpchanMessage } from '@/types/forum'; import { WakuNodeManager, HealthChangeCallback } from './core/WakuNodeManager'; import { MessageService, MessageStatusCallback, MissingMessageCallback, MissingMessageEvent, MissingMessageInfo, } from './services/MessageService'; import { ReliableMessaging } from './core/ReliableMessaging'; export type { HealthChangeCallback, MessageStatusCallback, MissingMessageCallback, MissingMessageEvent, MissingMessageInfo }; class MessageManager { private nodeManager: WakuNodeManager | null = null; // LocalDatabase eliminates the need for CacheService private messageService: MessageService | null = null; private reliableMessaging: ReliableMessaging | null = null; constructor() {} public static async create(): Promise { const manager = new MessageManager(); await manager.initialize(); return manager; } private async initialize(): Promise { try { this.nodeManager = await WakuNodeManager.create(); // Now create message service with proper dependencies this.messageService = new MessageService( this.reliableMessaging, this.nodeManager ); // Set up health-based reliable messaging initialization this.nodeManager.onHealthChange(isReady => { if (isReady && !this.reliableMessaging) { this.initializeReliableMessaging(); } else if (!isReady && this.reliableMessaging) { this.cleanupReliableMessaging(); } }); } catch (error) { console.error('Failed to initialize MessageManager:', error); throw error; } } private async initializeReliableMessaging(): Promise { if (!this.nodeManager || this.reliableMessaging) { return; } try { console.log('Initializing reliable messaging...'); this.reliableMessaging = new ReliableMessaging( this.nodeManager.getNode() ); this.messageService?.updateReliableMessaging(this.reliableMessaging); console.log('Reliable messaging initialized successfully'); } catch (error) { console.error('Failed to initialize reliable messaging:', error); } } private cleanupReliableMessaging(): void { if (this.reliableMessaging) { console.log('Cleaning up reliable messaging due to health status'); this.reliableMessaging.cleanup(); this.reliableMessaging = null; this.messageService?.updateReliableMessaging(null); } } public async stop(): Promise { this.cleanupReliableMessaging(); this.messageService?.cleanup(); await this.nodeManager?.stop(); } public get isReady(): boolean { return this.nodeManager?.isReady ?? false; } public get currentHealth(): HealthStatus { return this.nodeManager?.currentHealth ?? HealthStatus.Unhealthy; } public onHealthChange(callback: HealthChangeCallback): () => void { if (!this.nodeManager) { throw new Error('Node manager not initialized'); } return this.nodeManager.onHealthChange(callback); } //TODO: return event handlers? public async sendMessage( message: OpchanMessage, statusCallback?: MessageStatusCallback ): Promise { if (!this.messageService) { throw new Error('MessageManager not fully initialized'); } this.messageService.sendMessage(message, statusCallback); } public onMessageReceived( callback: (message: OpchanMessage) => void ): () => void { if (!this.messageService) { throw new Error('MessageManager not fully initialized'); } return this.messageService.onMessageReceived(callback); } public onMissingMessage(callback: MissingMessageCallback): () => void { if (!this.messageService) { throw new Error('MessageManager not fully initialized'); } return this.messageService.onMissingMessage(callback); } public getMissingMessages(): MissingMessageInfo[] { if (!this.messageService) { return []; } return this.messageService.getMissingMessages(); } public getRecoveredMessages(): string[] { if (!this.messageService) { return []; } return this.messageService.getRecoveredMessages(); } public getMissingMessageCount(): number { if (!this.messageService) { return 0; } return this.messageService.getMissingMessageCount(); } public getRecoveredMessageCount(): number { if (!this.messageService) { return 0; } return this.messageService.getRecoveredMessageCount(); } public get messageCache() { if (!this.messageService) { throw new Error('MessageManager not fully initialized'); } return this.messageService.messageCache; } } const messageManager = await MessageManager.create(); export default messageManager;