/** * Service Worker sync handler - executes sync operations in main thread * Listens to requests from Service Worker and executes them */ import { platformSyncService } from './platformSync' import { syncUserContentToCache } from './userContentSync' import { publishWorker } from './publishWorker' import { nostrService } from './nostr' import { swClient } from './swClient' import type { Event } from 'nostr-tools' class ServiceWorkerSyncHandler { private initialized = false /** * Initialize the sync handler * Sets up message listeners from Service Worker */ async initialize(): Promise { if (this.initialized) { return } if (typeof window === 'undefined') { return } try { await swClient.register() // Listen for sync requests from Service Worker swClient.onMessage('SYNC_REQUEST', (data: unknown) => { void (async (): Promise => { const syncData = data as { syncType: string; userPubkey?: string } if (syncData.syncType === 'platform') { await this.handlePlatformSyncRequest() } else if (syncData.syncType === 'user' && syncData.userPubkey) { await this.handleUserSyncRequest(syncData.userPubkey) } })() }) // Listen for publish worker requests swClient.onMessage('PUBLISH_WORKER_REQUEST', () => { void (async (): Promise => { await this.handlePublishWorkerRequest() })() }) // Listen for publish requests swClient.onMessage('PUBLISH_REQUEST', (data: unknown) => { void (async (): Promise => { const publishData = data as { event: Event; relays: string[] } await this.handlePublishRequest(publishData.event, publishData.relays) })() }) // Listen for notification detection requests swClient.onMessage('NOTIFICATION_DETECT_REQUEST', (data: unknown) => { void (async (): Promise => { const detectData = data as { userPubkey: string } await this.handleNotificationDetectRequest(detectData.userPubkey) })() }) this.initialized = true console.warn('[SWSyncHandler] Initialized') } catch (error) { console.error('[SWSyncHandler] Initialization failed:', error) } } /** * Handle platform sync request from Service Worker */ private async handlePlatformSyncRequest(): Promise { try { console.warn('[SWSyncHandler] Executing platform sync request') await platformSyncService.startSync() } catch (error) { console.error('[SWSyncHandler] Error in platform sync:', error) } } /** * Handle user sync request from Service Worker */ private async handleUserSyncRequest(userPubkey: string): Promise { try { console.warn('[SWSyncHandler] Executing user sync request for:', userPubkey) await syncUserContentToCache(userPubkey) } catch (error) { console.error('[SWSyncHandler] Error in user sync:', error) } } /** * Handle publish worker request from Service Worker */ private async handlePublishWorkerRequest(): Promise { try { console.warn('[SWSyncHandler] Executing publish worker request') // Trigger publish worker processing // The publishWorker will process unpublished objects await publishWorker['processUnpublished']() } catch (error) { console.error('[SWSyncHandler] Error in publish worker:', error) } } /** * Handle notification detection request from Service Worker * Le Service Worker détecte les changements indépendamment * Ce handler exécute la détection dans le thread principal et crée les notifications via writeService */ private async handleNotificationDetectRequest(userPubkey: string): Promise { try { console.warn('[SWSyncHandler] Executing notification detection request for:', userPubkey) const { notificationDetector } = await import('./notificationDetector') // Scanner IndexedDB pour détecter les nouveaux événements await notificationDetector.scan() // Les notifications sont créées via notificationDetector qui utilise notificationService // qui utilise maintenant writeService pour écrire via Web Worker } catch (error) { console.error('[SWSyncHandler] Error in notification detection:', error) } } /** * Handle publish request from Service Worker * Uses websocketService to route events to Service Worker */ private async handlePublishRequest(event: Event, relays: string[]): Promise { try { console.warn('[SWSyncHandler] Executing publish request for event:', event.id) const { websocketService } = await import('./websocketService') const { publishLog } = await import('./publishLog') // Publish to specified relays via websocketService (routes to Service Worker) const statuses = await websocketService.publishEvent(event, relays) const successfulRelays: string[] = [] statuses.forEach((status, index) => { const relayUrl = relays[index] if (!relayUrl) { return } if (status.success) { successfulRelays.push(relayUrl) // Log successful publication void publishLog.logPublication({ eventId: event.id, relayUrl, success: true, }) } else { const errorMessage = status.error ?? 'Unknown error' console.error(`[SWSyncHandler] Relay ${relayUrl} failed:`, errorMessage) // Log failed publication void publishLog.logPublication({ eventId: event.id, relayUrl, success: false, error: errorMessage, }) } }) // Update published status in IndexedDB // Access private method via type assertion const nostrServiceAny = nostrService as unknown as { updatePublishedStatus: (eventId: string, published: false | string[]) => Promise } await nostrServiceAny.updatePublishedStatus( event.id, successfulRelays.length > 0 ? successfulRelays : false ) } catch (error) { console.error('[SWSyncHandler] Error in publish request:', error) } } } export const swSyncHandler = new ServiceWorkerSyncHandler()