1- import type { ServiceWorkerPacket } from './service-worker-bridge' ;
1+ import type { ServiceWorker } from './service-worker-bridge' ;
22
33self . addEventListener ( 'activate' , ( ) => {
44 void self . clients . claim ( ) ;
@@ -23,24 +23,64 @@ function contentType(url: string): string {
2323 return CONTENT_TYPES [ url . substring ( url . lastIndexOf ( '.' ) + 1 ) ] || 'text/plain' ;
2424}
2525
26- async function post ( data : unknown ) : Promise < void > {
26+ const cacheName = 'ccmod-service-worker-cache' ;
27+
28+ function getCacheKey ( key : string ) : string {
29+ return `https://${ key } ` ;
30+ }
31+
32+ async function storeInCache < T extends object > ( key : string , value : T ) : Promise < void > {
33+ const cache = await caches . open ( cacheName ) ;
34+ const response = new Response ( JSON . stringify ( value ) , {
35+ headers : { 'Content-Type' : 'application/json' } ,
36+ } ) ;
37+ await cache . put ( getCacheKey ( key ) , response ) ;
38+ }
39+
40+ async function getFromCache < T extends object > ( key : string ) : Promise < T | null > {
41+ const cache = await caches . open ( cacheName ) ;
42+ const response = await cache . match ( getCacheKey ( key ) ) ;
43+ if ( ! response ) return null ;
44+ return await response . json ( ) ;
45+ }
46+
47+ const validPathPrefixesCacheKey = 'validPathPrefixes' ;
48+
49+ async function post ( data : ServiceWorker . Incoming . Packet ) : Promise < void > {
2750 const clients = await self . clients . matchAll ( ) ;
2851 const client = clients [ 0 ] ;
2952 client . postMessage ( data ) ;
3053}
3154
32- const waitingFor = new Map < string , ( packet : ServiceWorkerPacket ) => void > ( ) ;
55+ const waitingFor = new Map < string , ( packet : ServiceWorker . Outgoing . DataPacket ) => void > ( ) ;
3356
34- async function requestContents ( path : string ) : Promise < Response > {
35- let resolve ! : ( packet : ServiceWorkerPacket ) => void ;
36- const promise = new Promise < ServiceWorkerPacket > ( ( res ) => {
37- resolve = res ;
57+ async function requestAndAwaitAck (
58+ packet : ServiceWorker . Incoming . PathPacket ,
59+ ) : Promise < ServiceWorker . Outgoing . DataPacket > {
60+ return new Promise < ServiceWorker . Outgoing . DataPacket > ( ( resolve ) => {
61+ waitingFor . set ( packet . path , resolve ) ;
62+ void post ( packet ) ;
3863 } ) ;
39- await post ( path ) ;
64+ }
65+
66+ let validPathPrefixes : string [ ] | null ;
67+
68+ self . addEventListener ( 'message' , ( event ) => {
69+ const packet : ServiceWorker . Outgoing . Packet = event . data ;
70+
71+ if ( packet . type === 'ValidPathPrefixes' ) {
72+ validPathPrefixes = packet . validPathPrefixes ;
73+
74+ void storeInCache ( validPathPrefixesCacheKey , validPathPrefixes ) ;
75+ } else {
76+ waitingFor . get ( packet . path ) ?.( packet ) ;
77+ waitingFor . delete ( packet . path ) ;
78+ }
79+ } ) ;
4080
41- waitingFor . set ( path , resolve ) ;
81+ async function requestContents ( path : string ) : Promise < Response > {
82+ const { data } = await requestAndAwaitAck ( { type : 'Path' , path } ) ;
4283
43- const { data } = await promise ;
4484 if ( ! data ) {
4585 return new Response ( null , { status : 404 } ) ;
4686 }
@@ -54,32 +94,19 @@ async function requestContents(path: string): Promise<Response> {
5494 } ) ;
5595}
5696
57- let validPathPrefixes : string [ ] | undefined ;
97+ async function respond ( event : FetchEvent ) : Promise < Response > {
98+ const { request } = event ;
99+ const path = decodeURI ( new URL ( request . url ) . pathname ) ;
58100
59- self . addEventListener ( 'message' , ( event ) => {
60- if ( Array . isArray ( event . data ) ) {
61- validPathPrefixes = event . data ;
101+ validPathPrefixes ??= await getFromCache < string [ ] > ( validPathPrefixesCacheKey ) ;
102+
103+ if ( validPathPrefixes ?. some ( ( pathPrefix ) => path . startsWith ( pathPrefix ) ) ) {
104+ return requestContents ( path ) ;
62105 } else {
63- const packet : ServiceWorkerPacket = event . data ;
64- const resolve = waitingFor . get ( packet . path ) ! ;
65- resolve ( packet ) ;
66- waitingFor . delete ( packet . path ) ;
106+ return fetch ( request ) ;
67107 }
68- } ) ;
108+ }
69109
70110self . addEventListener ( 'fetch' , ( event : FetchEvent ) => {
71- if ( ! validPathPrefixes ) {
72- return ;
73- }
74-
75- const { request } = event ;
76- const path = decodeURI ( new URL ( request . url ) . pathname ) ;
77-
78- if (
79- validPathPrefixes . some (
80- ( pathPrefix ) => path . length > pathPrefix . length && path . startsWith ( pathPrefix ) ,
81- )
82- ) {
83- event . respondWith ( requestContents ( path ) ) ;
84- }
111+ event . respondWith ( respond ( event ) ) ;
85112} ) ;
0 commit comments