# `register-service-worker` ## Purpose `register-service-worker.ts` collects four lifecycle helpers exposed via the `/utils` subpath: `registerPackedResourceServiceWorker`, `unregisterPackedResourceServiceWorker`, `clearServiceWorkerCache`, and `getServiceWorkerCacheStatus`. They wrap the `navigator.serviceWorker` API with typed errors, injectable container support (for tests), and `AbortSignal` honoured at every yield. Every boundary error uses `MessageResolver`-keyed messages rather than hard-coded English literals. ## Features - Injectable `container: ServiceWorkerContainerLike` — tests pass an in-memory implementation; production defaults to `navigator.serviceWorker`. - `AbortSignal` honoured pre-call (synchronous reject with `PackerBrowserError(ABORTED)`) and mid-call (channel teardown + reject) on both `clearServiceWorkerCache` and `getServiceWorkerCacheStatus`. - `getServiceWorkerCacheStatus` includes a hard 5-second timeout so a hung controller cannot leak a pending Promise. - Boundary errors: `SW_REGISTRATION_FAILED` (no SW support, register rejected, no controller attached), `LOAD_FAILED` (timeout / negative reply), `ABORTED` (signal fires). - Returns typed shapes: `ServiceWorkerRegistration`, `boolean`, `void`, `CacheStatusReply`. ## Usage: Basic ```ts import { clearServiceWorkerCache, getServiceWorkerCacheStatus, registerPackedResourceServiceWorker, } from "@suaveplan/packer-browser/utils"; await registerPackedResourceServiceWorker(); const status = await getServiceWorkerCacheStatus(); console.log(status.cacheSize, status.urls); await clearServiceWorkerCache(); ``` ## Usage: Advanced ```ts import type { ServiceWorkerContainerLike } from "@suaveplan/packer-browser/utils"; const ac = new AbortController(); const recorded: string[] = []; const container: ServiceWorkerContainerLike = { controller: createMockController(recorded), register: async () => fakeRegistration(), getRegistrations: async () => [], ready: Promise.resolve(fakeRegistration()), }; await registerPackedResourceServiceWorker({ container, scriptUrl: "/custom.js", signal: ac.signal, }); ``` ## API Reference - `registerPackedResourceServiceWorker(opts?: RegisterOptions): Promise` — - throws `SW_REGISTRATION_FAILED` for no SW support / rejected `register()`. - throws `ABORTED` on a pre-aborted signal. - `unregisterPackedResourceServiceWorker(opts?): Promise` — resolves `false` when no container is available. - `clearServiceWorkerCache(opts?): Promise` — throws `SW_REGISTRATION_FAILED` if no controller is attached; throws `ABORTED` if the signal fires. - `getServiceWorkerCacheStatus(opts?): Promise` — throws `LOAD_FAILED` on 5 s timeout; throws `ABORTED` on signal. - `ServiceWorkerContainerLike` / `RegisterOptions` / `ServiceWorkerLifecycleOptions` — type-only injection points. ## Implementation Notes The helpers route every `controller.postMessage` through a `MessageChannel` and listen on `port1` for the reply. The `AbortSignal` integration closes `port1` before rejecting so the underlying SW does not see a half-open channel. The 5-second `getServiceWorkerCacheStatus` timeout is hard-coded because the upstream form had the same value; Cluster B will widen this once the SW gains range-request support and a single status query can take arbitrarily long under load.