diff --git a/ts_web_serviceworker/classes.serviceworker.ts b/ts_web_serviceworker/classes.serviceworker.ts index d330ffb..df9584a 100644 --- a/ts_web_serviceworker/classes.serviceworker.ts +++ b/ts_web_serviceworker/classes.serviceworker.ts @@ -31,6 +31,7 @@ export class ServiceWorker { // TypedSocket connection for server communication public typedsocket: plugins.typedsocket.TypedSocket; public typedrouter = new plugins.typedrequest.TypedRouter(); + private handlersInitialized = false; constructor(selfArg: interfaces.ServiceWindow) { logger.log('info', `Service worker instantiating at ${Date.now()}`); @@ -119,33 +120,43 @@ export class ServiceWorker { } } + /** + * Initialize typed handlers (idempotent - safe to call multiple times) + */ + private initHandlers(): void { + if (this.handlersInitialized) return; + this.handlersInitialized = true; + + // Register handler for cache invalidation from server + this.typedrouter.addTypedHandler( + new plugins.typedrequest.TypedHandler('serviceworker_cacheInvalidate', async (reqArg) => { + logger.log('info', `Cache invalidation requested from server: ${reqArg.reason}`); + + // Log cache invalidation event (survives) + const persistentStore = getPersistentStore(); + await persistentStore.init(); // Ensure store is initialized + await persistentStore.logEvent('cache_invalidated', `Cache invalidated: ${reqArg.reason}`, { + reason: reqArg.reason, + timestamp: reqArg.timestamp, + }); + + // Reset cumulative metrics (they don't survive cache invalidation) + await persistentStore.resetCumulativeMetrics(); + + await this.cacheManager.cleanCaches(reqArg.reason); + // Notify all clients to reload + await this.leleServiceWorkerBackend.triggerReloadAll(); + return { success: true }; + }) + ); + } + /** * Connect to TypedServer via TypedSocket for cache invalidation */ private async connectToServer(): Promise { try { - // Register handler for cache invalidation from server - this.typedrouter.addTypedHandler( - new plugins.typedrequest.TypedHandler('serviceworker_cacheInvalidate', async (reqArg) => { - logger.log('info', `Cache invalidation requested from server: ${reqArg.reason}`); - - // Log cache invalidation event (survives) - const persistentStore = getPersistentStore(); - await persistentStore.init(); // Ensure store is initialized - await persistentStore.logEvent('cache_invalidated', `Cache invalidated: ${reqArg.reason}`, { - reason: reqArg.reason, - timestamp: reqArg.timestamp, - }); - - // Reset cumulative metrics (they don't survive cache invalidation) - await persistentStore.resetCumulativeMetrics(); - - await this.cacheManager.cleanCaches(reqArg.reason); - // Notify all clients to reload - await this.leleServiceWorkerBackend.triggerReloadAll(); - return { success: true }; - }) - ); + this.initHandlers(); // Connect to server via TypedSocket this.typedsocket = await plugins.typedsocket.TypedSocket.createClient( diff --git a/ts_web_serviceworker_client/classes.globalsw.ts b/ts_web_serviceworker_client/classes.globalsw.ts index 075f982..ad5535b 100644 --- a/ts_web_serviceworker_client/classes.globalsw.ts +++ b/ts_web_serviceworker_client/classes.globalsw.ts @@ -1,5 +1,6 @@ import * as plugins from './plugins.js'; import { ServiceworkerClient } from './classes.serviceworkerclient.js'; +import { ActionManager } from './classes.actionmanager.js'; export class GlobalSW { losslessSw: ServiceworkerClient; @@ -8,6 +9,13 @@ export class GlobalSW { globalThis.globalSw = this; }; + /** + * Exposes the action manager for traffic logging and SW communication + */ + public get actionManager(): ActionManager { + return this.losslessSw.actionManager; + } + /** * purges the cache of the app's serviceworker * @returns