PageSourceSearch

https://settleup.app/ngsw-worker.js

js settleup.app collected 2026-10-06 13:45:25 UTC 83,394 bytes, 2,263 lines download raw bytes

1(() => {
2  var __defProp = Object.defineProperty;
3  var __defProps = Object.defineProperties;
4  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6  var __hasOwnProp = Object.prototype.hasOwnProperty;
7  var __propIsEnum = Object.prototype.propertyIsEnumerable;
8  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9  var __spreadValues = (a, b) => {
10    for (var prop in b || (b = {}))
11      if (__hasOwnProp.call(b, prop))
12        __defNormalProp(a, prop, b[prop]);
13    if (__getOwnPropSymbols)
14      for (var prop of __getOwnPropSymbols(b)) {
15        if (__propIsEnum.call(b, prop))
16          __defNormalProp(a, prop, b[prop]);
17      }
18    return a;
19  };
20  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
21  var __publicField = (obj, key, value) => {
22    __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
23    return value;
24  };
25
26  
26// packages/service-worker/worker/src/named-cache-storage.js
27  var NamedCacheStorage = class {
28    constructor(original, cacheNamePrefix) {
29      __publicField(this, "original");
30      __publicField(this, "cacheNamePrefix");
31      this.original = original;
32      this.cacheNamePrefix = cacheNamePrefix;
33    }
34    delete(cacheName) {
35      return this.original.delete(`${this.cacheNamePrefix}:${cacheName}`);
36    }
37    has(cacheName) {
38      return this.original.has(`${this.cacheNamePrefix}:${cacheName}`);
39    }
40    async keys() {
41      const prefix = `${this.cacheNamePrefix}:`;
42      const allCacheNames = await this.original.keys();
43      const ownCacheNames = allCacheNames.filter((name) => name.startsWith(prefix));
44      return ownCacheNames.map((name) => name.slice(prefix.length));
45    }
46    match(request, options) {
47      return this.original.match(request, options);
48    }
49    async open(cacheName) {
50      const cache = await this.original.open(`${this.cacheNamePrefix}:${cacheName}`);
51      return Object.assign(cache, { name: cacheName });
52    }
53  };
54
55  
55// packages/service-worker/worker/src/adapter.js
56  var Adapter = class {
57    constructor(scopeUrl, caches) {
58      __publicField(this, "scopeUrl");
59      __publicField(this, "caches");
60      __publicField(this, "origin");
61      this.scopeUrl = scopeUrl;
62      const parsedScopeUrl = this.parseUrl(this.scopeUrl);
63      this.origin = parsedScopeUrl.origin;
64      this.caches = new NamedCacheStorage(caches, `ngsw:${parsedScopeUrl.path}`);
65    }
66    /**
67     * Wrapper around the `Request` constructor.
68     */
69    newRequest(input, init) {
70      return new Request(input, init);
71    }
72    /**
73     * Wrapper around the `Response` constructor.
74     */
75    newResponse(body, init) {
76      return new Response(body, init);
77    }
78    /**
79     * Wrapper around the `Headers` constructor.
80     */
81    newHeaders(headers) {
82      return new Headers(headers);
83    }
84    /**
85     * Test if a given object is an instance of `Client`.
86     */
87    isClient(source) {
88      return source instanceof Client;
89    }
90    /**
91     * Read the current UNIX time in milliseconds.
92     */
93    get time() {
94      return Date.now();
95    }
96    /**
97     * Get a normalized representation of a URL such as those found in the ServiceWorker's `ngsw.json`
98     * configuration.
99     *
100     * More specifically:
101     * 1. Resolve the URL relative to the ServiceWorker's scope.
102     * 2. If the URL is relative to the ServiceWorker's own origin, then only return the path part.
103     *    Otherwise, return the full URL.
104     *
105     * @param url The raw request URL.
106     * @return A normalized representation of the URL.
107     */
108    normalizeUrl(url) {
109      const parsed = this.parseUrl(url, this.scopeUrl);
110      return parsed.origin === this.origin ? parsed.path : url;
111    }
112    /**
113     * Parse a URL into its different parts, such as `origin`, `path` and `search`.
114     */
115    parseUrl(url, relativeTo) {
116      const parsed = !relativeTo ? new URL(url) : new URL(url, relativeTo);
117      return { origin: parsed.origin, path: parsed.pathname, search: parsed.search };
118    }
119    /**
120     * Wait for a given amount of time before completing a Promise.
121     */
122    timeout(ms) {
123      return new Promise((resolve) => {
124        setTimeout(() => resolve(), ms);
125      });
126    }
127  };
128
129  
129// packages/service-worker/worker/src/database.js
130  var NotFound = class {
131    constructor(table, key) {
132      __publicField(this, "table");
133      __publicField(this, "key");
134      this.table = table;
135      this.key = key;
136    }
137  };
138
139  
139// packages/service-worker/worker/src/db-cache.js
140  var CacheDatabase = class {
141    constructor(adapter2) {
142      __publicField(this, "adapter");
143      __publicField(this, "cacheNamePrefix", "db");
144      __publicField(this, "tables", /* @__PURE__ */ new Map());
145      this.adapter = adapter2;
146    }
147    "delete"(name) {
148      if (this.tables.has(name)) {
149        this.tables.delete(name);
150      }
151      return this.adapter.caches.delete(`${this.cacheNamePrefix}:${name}`);
152    }
153    async list() {
154      const prefix = `${this.cacheNamePrefix}:`;
155      const allCacheNames = await this.adapter.caches.keys();
156      const dbCacheNames = allCacheNames.filter((name) => name.startsWith(prefix));
157      return dbCacheNames.map((name) => name.slice(prefix.length));
158    }
159    async open(name, cacheQueryOptions) {
160      if (!this.tables.has(name)) {
161        const cache = await this.adapter.caches.open(`${this.cacheNamePrefix}:${name}`);
162        const table = new CacheTable(name, cache, this.adapter, cacheQueryOptions);
163        this.tables.set(name, table);
164      }
165      return this.tables.get(name);
166    }
167  };
168  var CacheTable = class {
169    constructor(name, cache, adapter2, cacheQueryOptions) {
170      __publicField(this, "name");
171      __publicField(this, "cache");
172      __publicField(this, "adapter");
173      __publicField(this, "cacheQueryOptions");
174      __publicField(this, "cacheName");
175      this.name = name;
176      this.cache = cache;
177      this.adapter = adapter2;
178      this.cacheQueryOptions = cacheQueryOptions;
179      this.cacheName = this.cache.name;
180    }
181    request(key) {
182      return this.adapter.newRequest("/" + key);
183    }
184    "delete"(key) {
185      return this.cache.delete(this.request(key), this.cacheQueryOptions);
186    }
187    keys() {
188      return this.cache.keys().then((requests) => requests.map((req) => req.url.slice(1)));
189    }
190    read(key) {
191      return this.cache.match(this.request(key), this.cacheQueryOptions).then((res) => {
192        if (res === void 0) {
193          return Promise.reject(new NotFound(this.name, key));
194        }
195        return res.json();
196      });
197    }
198    write(key, value) {
199      return this.cache.put(this.request(key), this.adapter.newResponse(JSON.stringify(value)));
200    }
201  };
202
203  
203// packages/service-worker/worker/src/api.js
204  var UpdateCacheStatus;
205  (function(UpdateCacheStatus2) {
206    UpdateCacheStatus2[UpdateCacheStatus2["NOT_CACHED"] = 0] = "NOT_CACHED";
207    UpdateCacheStatus2[UpdateCacheStatus2["CACHED_BUT_UNUSED"] = 1] = "CACHED_BUT_UNUSED";
208    UpdateCacheStatus2[UpdateCacheStatus2["CACHED"] = 2] = "CACHED";
209  })(UpdateCacheStatus || (UpdateCacheStatus = {}));
210
211  
211// packages/service-worker/worker/src/error.js
212  var SwCriticalError = class extends Error {
213    constructor() {
214      super(...arguments);
215      __publicField(this, "isCritical", true);
216    }
217  };
218  function errorToString(error) {
219    if (error instanceof Error) {
220      return `${error.message}
221${error.stack}`;
222    } else {
223      return `${error}`;
224    }
225  }
226  var SwUnrecoverableStateError = class extends SwCriticalError {
227    constructor() {
228      super(...arguments);
229      __publicField(this, "isUnrecoverableState", true);
230    }
231  };
232
233  
233// packages/service-worker/worker/src/sha1.js
234  function sha1(str) {
235    const utf8 = str;
236    const words32 = stringToWords32(utf8, Endian.Big);
237    return _sha1(words32, utf8.length * 8);
238  }
239  function sha1Binary(buffer) {
240    const words32 = arrayBufferToWords32(buffer, Endian.Big);
241    return _sha1(words32, buffer.byteLength * 8);
242  }
243  function _sha1(words32, len) {
244    const w = [];
245    let [a, b, c, d, e] = [1732584193, 4023233417, 2562383102, 271733878, 3285377520];
246    words32[len >> 5] |= 128 << 24 - len % 32;
247    words32[(len + 64 >> 9 << 4) + 15] = len;
248    for (let i = 0; i < words32.length; i += 16) {
249      const [h0, h1, h2, h3, h4] = [a, b, c, d, e];
250      for (let j = 0; j < 80; j++) {
251        if (j < 16) {
252          w[j] = words32[i + j];
253        } else {
254          w[j] = rol32(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
255        }
256        const [f, k] = fk(j, b, c, d);
257        const temp = [rol32(a, 5), f, e, k, w[j]].reduce(add32);
258        [e, d, c, b, a] = [d, c, rol32(b, 30), a, temp];
259      }
260      [a, b, c, d, e] = [add32(a, h0), add32(b, h1), add32(c, h2), add32(d, h3), add32(e, h4)];
261    }
262    return byteStringToHexString(words32ToByteString([a, b, c, d, e]));
263  }
264  function add32(a, b) {
265    return add32to64(a, b)[1];
266  }
267  function add32to64(a, b) {
268    const low = (a & 65535) + (b & 65535);
269    const high = (a >>> 16) + (b >>> 16) + (low >>> 16);
270    return [high >>> 16, high << 16 | low & 65535];
271  }
272  function rol32(a, count) {
273    return a << count | a >>> 32 - count;
274  }
275  var Endian;
276  (function(Endian2) {
277    Endian2[Endian2["Little"] = 0] = "Little";
278    Endian2[Endian2["Big"] = 1] = "Big";
279  })(Endian || (Endian = {}));
280  function fk(index, b, c, d) {
281    if (index < 20) {
282      return [b & c | ~b & d, 1518500249];
283    }
284    if (index < 40) {
285      return [b ^ c ^ d, 1859775393];
286    }
287    if (index < 60) {
288      return [b & c | b & d | c & d, 2400959708];
289    }
290    return [b ^ c ^ d, 3395469782];
291  }
292  function stringToWords32(str, endian) {
293    const size = str.length + 3 >>> 2;
294    const words32 = [];
295    for (let i = 0; i < size; i++) {
296      words32[i] = wordAt(str, i * 4, endian);
297    }
298    return words32;
299  }
300  function arrayBufferToWords32(buffer, endian) {
301    const size = buffer.byteLength + 3 >>> 2;
302    const words32 = [];
303    const view = new Uint8Array(buffer);
304    for (let i = 0; i < size; i++) {
305      words32[i] = wordAt(view, i * 4, endian);
306    }
307    return words32;
308  }
309  function byteAt(str, index) {
310    if (typeof str === "string") {
311      return index >= str.length ? 0 : str.charCodeAt(index) & 255;
312    } else {
313      return index >= str.byteLength ? 0 : str[index] & 255;
314    }
315  }
316  function wordAt(str, index, endian) {
317    let word = 0;
318    if (endian === Endian.Big) {
319      for (let i = 0; i < 4; i++) {
320        word += byteAt(str, index + i) << 24 - 8 * i;
321      }
322    } else {
323      for (let i = 0; i < 4; i++) {
324        word += byteAt(str, index + i) << 8 * i;
325      }
326    }
327    return word;
328  }
329  function words32ToByteString(words32) {
330    return words32.reduce((str, word) => str + word32ToByteString(word), "");
331  }
332  function word32ToByteString(word) {
333    let str = "";
334    for (let i = 0; i < 4; i++) {
335      str += String.fromCharCode(word >>> 8 * (3 - i) & 255);
336    }
337    return str;
338  }
339  function byteStringToHexString(str) {
340    let hex = "";
341    for (let i = 0; i < str.length; i++) {
342      const b = byteAt(str, i);
343      hex += (b >>> 4).toString(16) + (b & 15).toString(16);
344    }
345    return hex.toLowerCase();
346  }
347
348  
348// packages/service-worker/worker/src/assets.js
349  var AssetGroup = class {
350    constructor(scope2, adapter2, idle, config, hashes, db, cacheNamePrefix) {
351      __publicField(this, "scope");
352      __publicField(this, "adapter");
353      __publicField(this, "idle");
354      __publicField(this, "config");
355      __publicField(this, "hashes");
356      __publicField(this, "db");
357      /**
358       * A deduplication cache, to make sure the SW never makes two network requests
359       * for the same resource at once. Managed by `fetchAndCacheOnce`.
360       */
361      __publicField(this, "inFlightRequests", /* @__PURE__ */ new Map());
362      /**
363       * Normalized resource URLs.
364       */
365      __publicField(this, "urls", []);
366      /**
367       * Regular expression patterns.
368       */
369      __publicField(this, "patterns", []);
370      /**
371       * A Promise which resolves to the `Cache` used to back this asset group. This
372       * is opened from the constructor.
373       */
374      __publicField(this, "cache");
375      /**
376       * Group name from the configuration.
377       */
378      __publicField(this, "name");
379      /**
380       * Metadata associated with specific cache entries.
381       */
382      __publicField(this, "metadata");
383      this.scope = scope2;
384      this.adapter = adapter2;
385      this.idle = idle;
386      this.config = config;
387      this.hashes = hashes;
388      this.db = db;
389      this.name = config.name;
390      this.urls = config.urls.map((url) => adapter2.normalizeUrl(url));
391      this.patterns = config.patterns.map((pattern) => new RegExp(pattern));
392      this.cache = adapter2.caches.open(`${cacheNamePrefix}:${config.name}:cache`);
393      this.metadata = this.db.open(`${cacheNamePrefix}:${config.name}:meta`, config.cacheQueryOptions);
394    }
395    async cacheStatus(url) {
396      const cache = await this.cache;
397      const meta = await this.metadata;
398      const req = this.adapter.newRequest(url);
399      const res = await cache.match(req, this.config.cacheQueryOptions);
400      if (res === void 0) {
401        return UpdateCacheStatus.NOT_CACHED;
402      }
403      try {
404        const data = await meta.read(req.url);
405        if (!data.used) {
406          return UpdateCacheStatus.CACHED_BUT_UNUSED;
407        }
408      } catch (_) {
409      }
410      return UpdateCacheStatus.CACHED;
411    }
412    /**
413     * Return a list of the names of all caches used by this group.
414     */
415    async getCacheNames() {
416      const [cache, metadata] = await Promise.all([this.cache, this.metadata]);
417      return [cache.name, metadata.cacheName];
418    }
419    /**
420     * Process a request for a given resource and return it, or return null if it's not available.
421     */
422    async handleFetch(req, _event) {
423      const url = this.adapter.normalizeUrl(req.url);
424      if (this.urls.indexOf(url) !== -1 || this.patterns.some((pattern) => pattern.test(url))) {
425        const cache = await this.cache;
426        let cachedResponse;
427        try {
428          cachedResponse = await cache.match(req, this.config.cacheQueryOptions);
429        } catch (error) {
430          throw new SwCriticalError(`Cache is throwing while looking for a match: ${error}`);
431        }
432        if (cachedResponse !== void 0) {
433          if (this.hashes.has(url)) {
434            return cachedResponse;
435          } else {
436            if (await this.needToRevalidate(req, cachedResponse)) {
437              this.idle.schedule(`revalidate(${cache.name}): ${req.url}`, async () => {
438                await this.fetchAndCacheOnce(req);
439              });
440            }
441            return cachedResponse;
442          }
443        }
444        const res = await this.fetchAndCacheOnce(this.newRequestWithMetadata(req.url, req));
445        return res.clone();
446      } else {
447        return null;
448      }
449    }
450    /**
451     * Some resources are cached without a hash, meaning that their expiration is controlled
452     * by HTTP caching headers. Check whether the given request/response pair is still valid
453     * per the caching headers.
454     */
455    async needToRevalidate(req, res) {
456      if (res.headers.has("Cache-Control")) {
457        const cacheControl = res.headers.get("Cache-Control");
458        const cacheDirectives = cacheControl.split(",").map((v) => v.trim()).map((v) => v.split("="));
459        cacheDirectives.forEach((v) => v[0] = v[0].toLowerCase());
460        const maxAgeDirective = cacheDirectives.find((v) => v[0] === "max-age");
461        const cacheAge = maxAgeDirective ? maxAgeDirective[1] : void 0;
462        if (!cacheAge) {
463          return true;
464        }
465        try {
466          const maxAge = 1e3 * parseInt(cacheAge);
467          let ts;
468          try {
469            const metaTable = await this.metadata;
470            ts = (await metaTable.read(req.url)).ts;
471          } catch (e) {
472            const date = res.headers.get("Date");
473            if (date === null) {
474              return true;
475            }
476            ts = Date.parse(date);
477          }
478          const age = this.adapter.time - ts;
479          return age < 0 || age > maxAge;
480        } catch (e) {
481          return true;
482        }
483      } else if (res.headers.has("Expires")) {
484        const expiresStr = res.headers.get("Expires");
485        try {
486          return this.adapter.time > Date.parse(expiresStr);
487        } catch (e) {
488          return true;
489        }
490      } else {
491        return true;
492      }
493    }
494    /**
495     * Fetch the complete state of a cached resource, or return null if it's not found.
496     */
497    async fetchFromCacheOnly(url) {
498      const cache = await this.cache;
499      const metaTable = await this.metadata;
500      const request = this.adapter.newRequest(url);
501      const response = await cache.match(request, this.config.cacheQueryOptions);
502      if (response === void 0) {
503        return null;
504      }
505      let metadata = void 0;
506      try {
507        metadata = await metaTable.read(request.url);
508      } catch (e) {
509      }
510      return { response, metadata };
511    }
512    /**
513     * Lookup all resources currently stored in the cache which have no associated hash.
514     */
515    async unhashedResources() {
516      const cache = await this.cache;
517      return (await cache.keys()).map((request) => this.adapter.normalizeUrl(request.url)).filter((url) => !this.hashes.has(url));
518    }
519    /**
520     * Fetch the given resource from the network, and cache it if able.
521     */
522    async fetchAndCacheOnce(req, used = true) {
523      if (this.inFlightRequests.has(req.url)) {
524        return this.inFlightRequests.get(req.url);
525      }
526      const fetchOp = this.fetchFromNetwork(req);
527      this.inFlightRequests.set(req.url, fetchOp);
528      try {
529        const res = await fetchOp;
530        if (!res.ok) {
531          throw new Error(`Response not Ok (fetchAndCacheOnce): request for ${req.url} returned response ${res.status} ${res.statusText}`);
532        }
533        try {
534          const cache = await this.cache;
535          await cache.put(req, res.clone());
536          if (!this.hashes.has(this.adapter.normalizeUrl(req.url))) {
537            const meta = { ts: this.adapter.time, used };
538            const metaTable = await this.metadata;
539            await metaTable.write(req.url, meta);
540          }
541          return res;
542        } catch (err) {
543          throw new SwCriticalError(`Failed to update the caches for request to '${req.url}' (fetchAndCacheOnce): ${errorToString(err)}`);
544        }
545      } finally {
546        this.inFlightRequests.delete(req.url);
547      }
548    }
549    async fetchFromNetwork(req, redirectLimit = 3) {
550      const res = await this.cacheBustedFetchFromNetwork(req);
551      if (res["redirected"] && !!res.url) {
552        if (redirectLimit === 0) {
553          throw new SwCriticalError(`Response hit redirect limit (fetchFromNetwork): request redirected too many times, next is ${res.url}`);
554        }
555        return this.fetchFromNetwork(this.newRequestWithMetadata(res.url, req), redirectLimit - 1);
556      }
557      return res;
558    }
559    /**
560     * Load a particular asset from the network, accounting for hash validation.
561     */
562    async cacheBustedFetchFromNetwork(req) {
563      const url = this.adapter.normalizeUrl(req.url);
564      if (this.hashes.has(url)) {
565        const canonicalHash = this.hashes.get(url);
566        let response = await this.safeFetch(req);
567        let makeCacheBustedRequest = response.ok;
568        if (makeCacheBustedRequest) {
569          const fetchedHash = sha1Binary(await response.clone().arrayBuffer());
570          makeCacheBustedRequest = fetchedHash !== canonicalHash;
571        }
572        if (makeCacheBustedRequest) {
573          const cacheBustReq = this.newRequestWithMetadata(this.cacheBust(req.url), req);
574          response = await this.safeFetch(cacheBustReq);
575          if (response.ok) {
576            const cacheBustedHash = sha1Binary(await response.clone().arrayBuffer());
577            if (canonicalHash !== cacheBustedHash) {
578              throw new SwCriticalError(`Hash mismatch (cacheBustedFetchFromNetwork): ${req.url}: expected ${canonicalHash}, got ${cacheBustedHash} (after cache busting)`);
579            }
580          }
581        }
582        if (!response.ok && response.status === 404) {
583          throw new SwUnrecoverableStateError(`Failed to retrieve hashed resource from the server. (AssetGroup: ${this.config.name} | URL: ${url})`);
584        }
585        return response;
586      } else {
587        return this.safeFetch(req);
588      }
589    }
590    /**
591     * Possibly update a resource, if it's expired and needs to be updated. A no-op otherwise.
592     */
593    async maybeUpdate(updateFrom, req, cache) {
594      const url = this.adapter.normalizeUrl(req.url);
595      if (this.hashes.has(url)) {
596        const hash = this.hashes.get(url);
597        const res = await updateFrom.lookupResourceWithHash(url, hash);
598        if (res !== null) {
599          await cache.put(req, res);
600          return true;
601        }
602      }
603      return false;
604    }
605    /**
606     * Create a new `Request` based on the specified URL and `RequestInit` options, preserving only
607     * metadata that are known to be safe.
608     *
609     * Currently, only headers are preserved.
610     *
611     * NOTE:
612     *   Things like credential inclusion are intentionally omitted to avoid issues with opaque
613     *   responses.
614     *
615     * TODO(gkalpak):
616     *   Investigate preserving more metadata. See, also, discussion on preserving `mode`:
617     *   https://github.com/angular/angular/issues/41931#issuecomment-1227601347
618     */
619    newRequestWithMetadata(url, options) {
620      return this.adapter.newRequest(url, { headers: options.headers });
621    }
622    /**
623     * Construct a cache-busting URL for a given URL.
624     */
625    cacheBust(url) {
626      return url + (url.indexOf("?") === -1 ? "?" : "&") + "ngsw-cache-bust=" + Math.random();
627    }
628    async safeFetch(req) {
629      try {
630        return await this.scope.fetch(req);
631      } catch (e) {
632        return this.adapter.newResponse("", {
633          status: 504,
634          statusText: "Gateway Timeout"
635        });
636      }
637    }
638  };
639  var PrefetchAssetGroup = class extends AssetGroup {
640    async initializeFully(updateFrom) {
641      const cache = await this.cache;
642      await this.urls.reduce(async (previous, url) => {
643        await previous;
644        const req = this.adapter.newRequest(url);
645        let alreadyCached = false;
646        try {
647          alreadyCached = await cache.match(req, this.config.cacheQueryOptions) !== void 0;
648        } catch (error) {
649          throw new SwCriticalError(`Cache is throwing while looking for a match in a PrefetchAssetGroup: ${error}`);
650        }
651        if (alreadyCached) {
652          return;
653        }
654        if (updateFrom !== void 0 && await this.maybeUpdate(updateFrom, req, cache)) {
655          return;
656        }
657        await this.fetchAndCacheOnce(req, false);
658      }, Promise.resolve());
659      if (updateFrom !== void 0) {
660        const metaTable = await this.metadata;
661        await (await updateFrom.previouslyCachedResources()).filter((url) => this.urls.indexOf(url) !== -1 || this.patterns.some((pattern) => pattern.test(url))).reduce(async (previous, url) => {
662          await previous;
663          const req = this.adapter.newRequest(url);
664          const alreadyCached = await cache.match(req, this.config.cacheQueryOptions) !== void 0;
665          if (alreadyCached) {
666            return;
667          }
668          const res = await updateFrom.lookupResourceWithoutHash(url);
669          if (res === null || res.metadata === void 0) {
670            return;
671          }
672          await cache.put(req, res.response);
673          await metaTable.write(req.url, __spreadProps(__spreadValues({}, res.metadata), { used: false }));
674        }, Promise.resolve());
675      }
676    }
677  };
678  var LazyAssetGroup = class extends AssetGroup {
679    async initializeFully(updateFrom) {
680      if (updateFrom === void 0) {
681        return;
682      }
683      const cache = await this.cache;
684      await this.urls.reduce(async (previous, url) => {
685        await previous;
686        const req = this.adapter.newRequest(url);
687        let alreadyCached = false;
688        try {
689          alreadyCached = await cache.match(req, this.config.cacheQueryOptions) !== void 0;
690        } catch (error) {
691          throw new SwCriticalError(`Cache is throwing while looking for a match in a LazyAssetGroup: ${error}`);
692        }
693        if (alreadyCached) {
694          return;
695        }
696        const updated = await this.maybeUpdate(updateFrom, req, cache);
697        if (this.config.updateMode === "prefetch" && !updated) {
698          const cacheStatus = await updateFrom.recentCacheStatus(url);
699          if (cacheStatus !== UpdateCacheStatus.CACHED) {
700            return;
701          }
702          await this.fetchAndCacheOnce(req, false);
703        }
704      }, Promise.resolve());
705    }
706  };
707
708  
708// packages/service-worker/worker/src/data.js
709  var LruList = class {
710    constructor(state) {
711      __publicField(this, "state");
712      if (state === void 0) {
713        state = {
714          head: null,
715          tail: null,
716          map: {},
717          count: 0
718        };
719      }
720      this.state = state;
721    }
722    /**
723     * The current count of URLs in the list.
724     */
725    get size() {
726      return this.state.count;
727    }
728    /**
729     * Remove the tail.
730     */
731    pop() {
732      if (this.state.tail === null) {
733        return null;
734      }
735      const url = this.state.tail;
736      this.remove(url);
737      return url;
738    }
739    remove(url) {
740      const node = this.state.map[url];
741      if (node === void 0) {
742        return false;
743      }
744      if (this.state.head === url) {
745        if (node.next === null) {
746          this.state.head = null;
747          this.state.tail = null;
748          this.state.map = {};
749          this.state.count = 0;
750          return true;
751        }
752        const next = this.state.map[node.next];
753        next.previous = null;
754        this.state.head = next.url;
755        node.next = null;
756        delete this.state.map[url];
757        this.state.count--;
758        return true;
759      }
760      const previous = this.state.map[node.previous];
761      previous.next = node.next;
762      if (node.next !== null) {
763        this.state.map[node.next].previous = node.previous;
764      } else {
765        this.state.tail = node.previous;
766      }
767      node.next = null;
768      node.previous = null;
769      delete this.state.map[url];
770      this.state.count--;
771      return true;
772    }
773    accessed(url) {
774      if (this.state.head === url) {
775        return;
776      }
777      const node = this.state.map[url] || { url, next: null, previous: null };
778      if (this.state.map[url] !== void 0) {
779        this.remove(url);
780      }
781      if (this.state.head !== null) {
782        this.state.map[this.state.head].previous = url;
783      }
784      node.next = this.state.head;
785      this.state.head = url;
786      if (this.state.tail === null) {
787        this.state.tail = url;
788      }
789      this.state.map[url] = node;
790      this.state.count++;
791    }
792  };
793  var DataGroup = class {
794    constructor(scope2, adapter2, config, db, debugHandler, cacheNamePrefix) {
795      __publicField(this, "scope");
796      __publicField(this, "adapter");
797      __publicField(this, "config");
798      __publicField(this, "db");
799      __publicField(this, "debugHandler");
800      /**
801       * Compiled regular expression set used to determine which resources fall under the purview
802       * of this group.
803       */
804      __publicField(this, "patterns");
805      /**
806       * The `Cache` instance in which resources belonging to this group are cached.
807       */
808      __publicField(this, "cache");
809      /**
810       * Tracks the LRU state of resources in this cache.
811       */
812      __publicField(this, "_lru", null);
813      /**
814       * Database table used to store the state of the LRU cache.
815       */
816      __publicField(this, "lruTable");
817      /**
818       * Database table used to store metadata for resources in the cache.
819       */
820      __publicField(this, "ageTable");
821      this.scope = scope2;
822      this.adapter = adapter2;
823      this.config = config;
824      this.db = db;
825      this.debugHandler = debugHandler;
826      this.patterns = config.patterns.map((pattern) => new RegExp(pattern));
827      this.cache = adapter2.caches.open(`${cacheNamePrefix}:${config.name}:cache`);
828      this.lruTable = this.db.open(`${cacheNamePrefix}:${config.name}:lru`, config.cacheQueryOptions);
829      this.ageTable = this.db.open(`${cacheNamePrefix}:${config.name}:age`, config.cacheQueryOptions);
830    }
831    /**
832     * Lazily initialize/load the LRU chain.
833     */
834    async lru() {
835      if (this._lru === null) {
836        const table = await this.lruTable;
837        try {
838          this._lru = new LruList(await table.read("lru"));
839        } catch (e) {
840          this._lru = new LruList();
841        }
842      }
843      return this._lru;
844    }
845    /**
846     * Sync the LRU chain to non-volatile storage.
847     */
848    async syncLru() {
849      if (this._lru === null) {
850        return;
851      }
852      const table = await this.lruTable;
853      try {
854        return table.write("lru", this._lru.state);
855      } catch (err) {
856        this.debugHandler.log(err, `DataGroup(${this.config.name}@${this.config.version}).syncLru()`);
857        await this.detectStorageFull();
858      }
859    }
860    /**
861     * Process a fetch event and return a `Response` if the resource is covered by this group,
862     * or `null` otherwise.
863     */
864    async handleFetch(req, event) {
865      if (!this.patterns.some((pattern) => pattern.test(req.url))) {
866        return null;
867      }
868      const lru = await this.lru();
869      switch (req.method) {
870        case "OPTIONS":
871          return null;
872        case "GET":
873        case "HEAD":
874          switch (this.config.strategy) {
875            case "freshness":
876              return this.handleFetchWithFreshness(req, event, lru);
877            case "performance":
878              return this.handleFetchWithPerformance(req, event, lru);
879            default:
880              throw new Error(`Unknown strategy: ${this.config.strategy}`);
881          }
882        default:
883          const wasCached = lru.remove(req.url);
884          if (wasCached) {
885            await this.clearCacheForUrl(req.url);
886          }
887          await this.syncLru();
888          return this.safeFetch(req);
889      }
890    }
891    async handleFetchWithPerformance(req, event, lru) {
892      var _a;
893      const okToCacheOpaque = (_a = this.config.cacheOpaqueResponses) != null ? _a : false;
894      let res = null;
895      const fromCache = await this.loadFromCache(req, lru);
896      if (fromCache !== null) {
897        res = fromCache.res;
898        if (this.config.refreshAheadMs !== void 0 && fromCache.age >= this.config.refreshAheadMs) {
899          event.waitUntil(this.safeCacheResponse(req, this.safeFetch(req), lru, okToCacheOpaque));
900        }
901      }
902      if (res !== null) {
903        return res;
904      }
905      const [timeoutFetch, networkFetch] = this.networkFetchWithTimeout(req);
906      res = await timeoutFetch;
907      if (res === void 0) {
908        res = this.adapter.newResponse(null, { status: 504, statusText: "Gateway Timeout" });
909        event.waitUntil(this.safeCacheResponse(req, networkFetch, lru, okToCacheOpaque));
910      } else {
911        await this.safeCacheResponse(req, res, lru, okToCacheOpaque);
912      }
913      return res;
914    }
915    async handleFetchWithFreshness(req, event, lru) {
916      var _a;
917      const okToCacheOpaque = (_a = this.config.cacheOpaqueResponses) != null ? _a : true;
918      const [timeoutFetch, networkFetch] = this.networkFetchWithTimeout(req);
919      let res;
920      try {
921        res = await timeoutFetch;
922      } catch (e) {
923        res = void 0;
924      }
925      if (res === void 0) {
926        event.waitUntil(this.safeCacheResponse(req, networkFetch, lru, okToCacheOpaque));
927        const fromCache = await this.loadFromCache(req, lru);
928        res = fromCache !== null ? fromCache.res : null;
929      } else {
930        await this.safeCacheResponse(req, res, lru, okToCacheOpaque);
931      }
932      if (res !== null) {
933        return res;
934      }
935      return networkFetch;
936    }
937    networkFetchWithTimeout(req) {
938      if (this.config.timeoutMs !== void 0) {
939        const networkFetch = this.scope.fetch(req);
940        const safeNetworkFetch = (async () => {
941          try {
942            return await networkFetch;
943          } catch (e) {
944            return this.adapter.newResponse(null, {
945              status: 504,
946              statusText: "Gateway Timeout"
947            });
948          }
949        })();
950        const networkFetchUndefinedError = (async () => {
951          try {
952            return await networkFetch;
953          } catch (e) {
954            return void 0;
955          }
956        })();
957        const timeout = this.adapter.timeout(this.config.timeoutMs);
958        return [Promise.race([networkFetchUndefinedError, timeout]), safeNetworkFetch];
959      } else {
960        const networkFetch = this.safeFetch(req);
961        return [networkFetch, networkFetch];
962      }
963    }
964    async safeCacheResponse(req, resOrPromise, lru, okToCacheOpaque) {
965      try {
966        const res = await resOrPromise;
967        try {
968          await this.cacheResponse(req, res, lru, okToCacheOpaque);
969        } catch (err) {
970          this.debugHandler.log(err, `DataGroup(${this.config.name}@${this.config.version}).safeCacheResponse(${req.url}, status: ${res.status})`);
971          await this.detectStorageFull();
972        }
973      } catch (e) {
974      }
975    }
976    async loadFromCache(req, lru) {
977      const cache = await this.cache;
978      let res = await cache.match(req, this.config.cacheQueryOptions);
979      if (res !== void 0) {
980        try {
981          const ageTable = await this.ageTable;
982          const age = this.adapter.time - (await ageTable.read(req.url)).age;
983          if (age <= this.config.maxAge) {
984            lru.accessed(req.url);
985            return { res, age };
986          }
987        } catch (e) {
988        }
989        lru.remove(req.url);
990        await this.clearCacheForUrl(req.url);
991        await this.syncLru();
992      }
993      return null;
994    }
995    /**
996     * Operation for caching the response from the server. This has to happen all
997     * at once, so that the cache and LRU tracking remain in sync. If the network request
998     * completes before the timeout, this logic will be run inline with the response flow.
999     * If the request times out on the server, an error will be returned but the real network
1000     * request will still be running in the background, to be cached when it completes.
1001     */
1002    async cacheResponse(req, res, lru, okToCacheOpaque = false) {
1003      if (!(res.ok || okToCacheOpaque && res.type === "opaque")) {
1004        return;
1005      }
1006      if (lru.size >= this.config.maxSize) {
1007        const evictedUrl = lru.pop();
1008        if (evictedUrl !== null) {
1009          await this.clearCacheForUrl(evictedUrl);
1010        }
1011      }
1012      lru.accessed(req.url);
1013      await (await this.cache).put(req, res.clone());
1014      const ageTable = await this.ageTable;
1015      await ageTable.write(req.url, { age: this.adapter.time });
1016      await this.syncLru();
1017    }
1018    /**
1019     * Delete all of the saved state which this group uses to track resources.
1020     */
1021    async cleanup() {
1022      await Promise.all([
1023        this.cache.then((cache) => this.adapter.caches.delete(cache.name)),
1024        this.ageTable.then((table) => this.db.delete(table.name)),
1025        this.lruTable.then((table) => this.db.delete(table.name))
1026      ]);
1027    }
1028    /**
1029     * Return a list of the names of all caches used by this group.
1030     */
1031    async getCacheNames() {
1032      const [cache, ageTable, lruTable] = await Promise.all([
1033        this.cache,
1034        this.ageTable,
1035        this.lruTable
1036      ]);
1037      return [cache.name, ageTable.cacheName, lruTable.cacheName];
1038    }
1039    /**
1040     * Clear the state of the cache for a particular resource.
1041     *
1042     * This doesn't remove the resource from the LRU table, that is assumed to have
1043     * been done already. This clears the GET and HEAD versions of the request from
1044     * the cache itself, as well as the metadata stored in the age table.
1045     */
1046    async clearCacheForUrl(url) {
1047      const [cache, ageTable] = await Promise.all([this.cache, this.ageTable]);
1048      await Promise.all([
1049        cache.delete(this.adapter.newRequest(url, { method: "GET" }), this.config.cacheQueryOptions),
1050        cache.delete(this.adapter.newRequest(url, { method: "HEAD" }), this.config.cacheQueryOptions),
1051        ageTable.delete(url)
1052      ]);
1053    }
1054    async safeFetch(req) {
1055      try {
1056        return this.scope.fetch(req);
1057      } catch (e) {
1058        return this.adapter.newResponse(null, {
1059          status: 504,
1060          statusText: "Gateway Timeout"
1061        });
1062      }
1063    }
1064    /**
1065     * Detect if storage is full or approaching capacity.
1066     * Returns true if storage is at or near capacity.
1067     */
1068    async detectStorageFull() {
1069      try {
1070        const estimate = await navigator.storage.estimate();
1071        const { quota, usage } = estimate;
1072        if (typeof quota !== "number" || typeof usage !== "number") {
1073          return;
1074        }
1075        const usagePercentage = usage / quota * 100;
1076        const isStorageFull = usagePercentage >= 95;
1077        if (isStorageFull) {
1078          this.debugHandler.log("Storage is full or nearly full", `DataGroup(${this.config.name}@${this.config.version}).detectStorageFull()`);
1079        }
1080      } catch (e) {
1081      }
1082    }
1083  };
1084
1085  
1085// packages/service-worker/worker/src/app-version.js
1086  var AppVersion = class {
1087    constructor(scope2, adapter2, database, idle, debugHandler, manifest, manifestHash) {
1088      __publicField(this, "scope");
1089      __publicField(this, "adapter");
1090      __publicField(this, "database");
1091      __publicField(this, "debugHandler");
1092      __publicField(this, "manifest");
1093      __publicField(this, "manifestHash");
1094      /**
1095       * A Map of absolute URL paths (`/foo.txt`) to the known hash of their contents (if available).
1096       */
1097      __publicField(this, "hashTable", /* @__PURE__ */ new Map());
1098      /**
1099       * All of the asset groups active in this version of the app.
1100       */
1101      __publicField(this, "assetGroups");
1102      /**
1103       * All of the data groups active in this version of the app.
1104       */
1105      __publicField(this, "dataGroups");
1106      /**
1107       * Requests to URLs that match any of the `include` RegExps and none of the `exclude` RegExps
1108       * are considered navigation requests and handled accordingly.
1109       */
1110      __publicField(this, "navigationUrls");
1111      /**
1112       * The normalized URL to the file that serves as the index page to satisfy navigation requests.
1113       * Usually this is `/index.html`.
1114       */
1115      __publicField(this, "indexUrl");
1116      /**
1117       * Tracks whether the manifest has encountered any inconsistencies.
1118       */
1119      __publicField(this, "_okay", true);
1120      this.scope = scope2;
1121      this.adapter = adapter2;
1122      this.database = database;
1123      this.debugHandler = debugHandler;
1124      this.manifest = manifest;
1125      this.manifestHash = manifestHash;
1126      this.indexUrl = this.adapter.normalizeUrl(this.manifest.index);
1127      Object.keys(manifest.hashTable).forEach((url) => {
1128        this.hashTable.set(adapter2.normalizeUrl(url), manifest.hashTable[url]);
1129      });
1130      const assetCacheNamePrefix = `${manifestHash}:assets`;
1131      this.assetGroups = (manifest.assetGroups || []).map((config) => {
1132        switch (config.installMode) {
1133          case "prefetch":
1134            return new PrefetchAssetGroup(scope2, adapter2, idle, config, this.hashTable, database, assetCacheNamePrefix);
1135          case "lazy":
1136            return new LazyAssetGroup(scope2, adapter2, idle, config, this.hashTable, database, assetCacheNamePrefix);
1137        }
1138      });
1139      this.dataGroups = (manifest.dataGroups || []).map((config) => new DataGroup(scope2, adapter2, config, database, debugHandler, `${config.version}:data`));
1140      const includeUrls = manifest.navigationUrls.filter((spec) => spec.positive);
1141      const excludeUrls = manifest.navigationUrls.filter((spec) => !spec.positive);
1142      this.navigationUrls = {
1143        include: includeUrls.map((spec) => new RegExp(spec.regex)),
1144        exclude: excludeUrls.map((spec) => new RegExp(spec.regex))
1145      };
1146    }
1147    get okay() {
1148      return this._okay;
1149    }
1150    /**
1151     * Fully initialize this version of the application. If this Promise resolves successfully, all
1152     * required
1153     * data has been safely downloaded.
1154     */
1155    async initializeFully(updateFrom) {
1156      try {
1157        await this.assetGroups.reduce(async (previous, group) => {
1158          await previous;
1159          return group.initializeFully(updateFrom);
1160        }, Promise.resolve());
1161      } catch (err) {
1162        this._okay = false;
1163        throw err;
1164      }
1165    }
1166    async handleFetch(req, event) {
1167      const asset = await this.assetGroups.reduce(async (potentialResponse, group) => {
1168        const resp = await potentialResponse;
1169        if (resp !== null) {
1170          return resp;
1171        }
1172        return group.handleFetch(req, event);
1173      }, Promise.resolve(null));
1174      if (asset !== null) {
1175        return asset;
1176      }
1177      const data = await this.dataGroups.reduce(async (potentialResponse, group) => {
1178        const resp = await potentialResponse;
1179        if (resp !== null) {
1180          return resp;
1181        }
1182        return group.handleFetch(req, event);
1183      }, Promise.resolve(null));
1184      if (data !== null) {
1185        return data;
1186      }
1187      if (this.adapter.normalizeUrl(req.url) !== this.indexUrl && this.isNavigationRequest(req)) {
1188        if (this.manifest.navigationRequestStrategy === "freshness") {
1189          try {
1190            return await this.scope.fetch(req);
1191          } catch (e) {
1192          }
1193        }
1194        return this.handleFetch(this.adapter.newRequest(this.indexUrl), event);
1195      }
1196      return null;
1197    }
1198    /**
1199     * Determine whether the request is a navigation request.
1200     * Takes into account: Request method and mode, `Accept` header, `navigationUrls` patterns.
1201     */
1202    isNavigationRequest(req) {
1203      if (req.method !== "GET" || req.mode !== "navigate") {
1204        return false;
1205      }
1206      if (!this.acceptsTextHtml(req)) {
1207        return false;
1208      }
1209      const urlPrefix = this.scope.registration.scope.replace(/\/$/, "");
1210      const url = req.url.startsWith(urlPrefix) ? req.url.slice(urlPrefix.length) : req.url;
1211      const urlWithoutQueryOrHash = url.replace(/[?#].*$/, "");
1212      return this.navigationUrls.include.some((regex) => regex.test(urlWithoutQueryOrHash)) && !this.navigationUrls.exclude.some((regex) => regex.test(urlWithoutQueryOrHash));
1213    }
1214    /**
1215     * Check this version for a given resource with a particular hash.
1216     */
1217    async lookupResourceWithHash(url, hash) {
1218      if (!this.hashTable.has(url)) {
1219        return null;
1220      }
1221      if (this.hashTable.get(url) !== hash) {
1222        return null;
1223      }
1224      const cacheState = await this.lookupResourceWithoutHash(url);
1225      return cacheState && cacheState.response;
1226    }
1227    /**
1228     * Check this version for a given resource regardless of its hash.
1229     */
1230    lookupResourceWithoutHash(url) {
1231      return this.assetGroups.reduce(async (potentialResponse, group) => {
1232        const resp = await potentialResponse;
1233        if (resp !== null) {
1234          return resp;
1235        }
1236        return group.fetchFromCacheOnly(url);
1237      }, Promise.resolve(null));
1238    }
1239    /**
1240     * List all unhashed resources from all asset groups.
1241     */
1242    previouslyCachedResources() {
1243      return this.assetGroups.reduce(async (resources, group) => (await resources).concat(await group.unhashedResources()), Promise.resolve([]));
1244    }
1245    async recentCacheStatus(url) {
1246      return this.assetGroups.reduce(async (current, group) => {
1247        const status = await current;
1248        if (status === UpdateCacheStatus.CACHED) {
1249          return status;
1250        }
1251        const groupStatus = await group.cacheStatus(url);
1252        if (groupStatus === UpdateCacheStatus.NOT_CACHED) {
1253          return status;
1254        }
1255        return groupStatus;
1256      }, Promise.resolve(UpdateCacheStatus.NOT_CACHED));
1257    }
1258    /**
1259     * Return a list of the names of all caches used by this version.
1260     */
1261    async getCacheNames() {
1262      const allGroupCacheNames = await Promise.all([
1263        ...this.assetGroups.map((group) => group.getCacheNames()),
1264        ...this.dataGroups.map((group) => group.getCacheNames())
1265      ]);
1266      return [].concat(...allGroupCacheNames);
1267    }
1268    /**
1269     * Get the opaque application data which was provided with the manifest.
1270     */
1271    get appData() {
1272      return this.manifest.appData || null;
1273    }
1274    /**
1275     * Check whether a request accepts `text/html` (based on the `Accept` header).
1276     */
1277    acceptsTextHtml(req) {
1278      const accept = req.headers.get("Accept");
1279      if (accept === null) {
1280        return false;
1281      }
1282      const values = accept.split(",");
1283      return values.some((value) => value.trim().toLowerCase() === "text/html");
1284    }
1285  };
1286
1287  
1287// packages/service-worker/worker/src/debug.js
1288  var SW_VERSION = "20.3.16";
1289  var DEBUG_LOG_BUFFER_SIZE = 100;
1290  var DebugHandler = class {
1291    constructor(driver, adapter2) {
1292      __publicField(this, "driver");
1293      __publicField(this, "adapter");
1294      // There are two debug log message arrays. debugLogA records new debugging messages.
1295      // Once it reaches DEBUG_LOG_BUFFER_SIZE, the array is moved to debugLogB and a new
1296      // array is assigned to debugLogA. This ensures that insertion to the debug log is
1297      // always O(1) no matter the number of logged messages, and that the total number
1298      // of messages in the log never exceeds 2 * DEBUG_LOG_BUFFER_SIZE.
1299      __publicField(this, "debugLogA", []);
1300      __publicField(this, "debugLogB", []);
1301      this.driver = driver;
1302      this.adapter = adapter2;
1303    }
1304    async handleFetch(req) {
1305      const [state, versions, idle] = await Promise.all([
1306        this.driver.debugState(),
1307        this.driver.debugVersions(),
1308        this.driver.debugIdleState()
1309      ]);
1310      const msgState = `NGSW Debug Info:
1311
1312Driver version: ${SW_VERSION}
1313Driver state: ${state.state} (${state.why})
1314Latest manifest hash: ${state.latestHash || "none"}
1315Last update check: ${this.since(state.lastUpdateCheck)}`;
1316      const msgVersions = versions.map((version) => `=== Version ${version.hash} ===
1317
1318Clients: ${version.clients.join(", ")}`).join("\n\n");
1319      const msgIdle = `=== Idle Task Queue ===
1320Last update tick: ${this.since(idle.lastTrigger)}
1321Last update run: ${this.since(idle.lastRun)}
1322Task queue:
1323${idle.queue.map((v) => " * " + v).join("\n")}
1324
1325Debug log:
1326${this.formatDebugLog(this.debugLogB)}
1327${this.formatDebugLog(this.debugLogA)}
1328`;
1329      return this.adapter.newResponse(`${msgState}
1330
1331${msgVersions}
1332
1333${msgIdle}`, { headers: this.adapter.newHeaders({ "Content-Type": "text/plain" }) });
1334    }
1335    since(time) {
1336      if (time === null) {
1337        return "never";
1338      }
1339      let age = this.adapter.time - time;
1340      const days = Math.floor(age / 864e5);
1341      age = age % 864e5;
1342      const hours = Math.floor(age / 36e5);
1343      age = age % 36e5;
1344      const minutes = Math.floor(age / 6e4);
1345      age = age % 6e4;
1346      const seconds = Math.floor(age / 1e3);
1347      const millis = age % 1e3;
1348      return (days > 0 ? `${days}d` : "") + (hours > 0 ? `${hours}h` : "") + (minutes > 0 ? `${minutes}m` : "") + (seconds > 0 ? `${seconds}s` : "") + (millis > 0 ? `${millis}u` : "");
1349    }
1350    log(value, context = "") {
1351      if (this.debugLogA.length === DEBUG_LOG_BUFFER_SIZE) {
1352        this.debugLogB = this.debugLogA;
1353        this.debugLogA = [];
1354      }
1355      if (typeof value !== "string") {
1356        value = this.errorToString(value);
1357      }
1358      this.debugLogA.push({ value, time: this.adapter.time, context });
1359    }
1360    errorToString(err) {
1361      return `${err.name}(${err.message}, ${err.stack})`;
1362    }
1363    formatDebugLog(log) {
1364      return log.map((entry) => `[${this.since(entry.time)}] ${entry.value} ${entry.context}`).join("\n");
1365    }
1366  };
1367
1368  
1368// packages/service-worker/worker/src/idle.js
1369  var IdleScheduler = class {
1370    constructor(adapter2, delay, maxDelay, debug) {
1371      __publicField(this, "adapter");
1372      __publicField(this, "delay");
1373      __publicField(this, "maxDelay");
1374      __publicField(this, "debug");
1375      __publicField(this, "queue", []);
1376      __publicField(this, "scheduled", null);
1377      __publicField(this, "empty", Promise.resolve());
1378      __publicField(this, "emptyResolve", null);
1379      __publicField(this, "lastTrigger", null);
1380      __publicField(this, "lastRun", null);
1381      __publicField(this, "oldestScheduledAt", null);
1382      this.adapter = adapter2;
1383      this.delay = delay;
1384      this.maxDelay = maxDelay;
1385      this.debug = debug;
1386    }
1387    async trigger() {
1388      var _a;
1389      this.lastTrigger = this.adapter.time;
1390      if (this.queue.length === 0) {
1391        return;
1392      }
1393      if (this.scheduled !== null) {
1394        this.scheduled.cancel = true;
1395      }
1396      const scheduled = {
1397        cancel: false
1398      };
1399      this.scheduled = scheduled;
1400      const now = this.adapter.time;
1401      const maxDelay = Math.max(0, ((_a = this.oldestScheduledAt) != null ? _a : now) + this.maxDelay - now);
1402      const delay = Math.min(maxDelay, this.delay);
1403      await this.adapter.timeout(delay);
1404      if (scheduled.cancel) {
1405        return;
1406      }
1407      this.scheduled = null;
1408      await this.execute();
1409    }
1410    async execute() {
1411      this.lastRun = this.adapter.time;
1412      while (this.queue.length > 0) {
1413        const queue = this.queue;
1414        this.queue = [];
1415        await queue.reduce(async (previous, task) => {
1416          await previous;
1417          try {
1418            await task.run();
1419          } catch (err) {
1420            this.debug.log(err, `while running idle task ${task.desc}`);
1421          }
1422        }, Promise.resolve());
1423      }
1424      if (this.emptyResolve !== null) {
1425        this.emptyResolve();
1426        this.emptyResolve = null;
1427      }
1428      this.empty = Promise.resolve();
1429      this.oldestScheduledAt = null;
1430    }
1431    schedule(desc, run) {
1432      this.queue.push({ desc, run });
1433      if (this.emptyResolve === null) {
1434        this.empty = new Promise((resolve) => {
1435          this.emptyResolve = resolve;
1436        });
1437      }
1438      if (this.oldestScheduledAt === null) {
1439        this.oldestScheduledAt = this.adapter.time;
1440      }
1441    }
1442    get size() {
1443      return this.queue.length;
1444    }
1445    get taskDescriptions() {
1446      return this.queue.map((task) => task.desc);
1447    }
1448  };
1449
1450  
1450// packages/service-worker/worker/src/manifest.js
1451  function hashManifest(manifest) {
1452    return sha1(JSON.stringify(manifest));
1453  }
1454
1455  
1455// packages/service-worker/worker/src/msg.js
1456  function isMsgCheckForUpdates(msg) {
1457    return msg.action === "CHECK_FOR_UPDATES";
1458  }
1459  function isMsgActivateUpdate(msg) {
1460    return msg.action === "ACTIVATE_UPDATE";
1461  }
1462
1463  
1463// packages/service-worker/worker/src/driver.js
1464  var IDLE_DELAY = 5e3;
1465  var MAX_IDLE_DELAY = 3e4;
1466  var SUPPORTED_CONFIG_VERSION = 1;
1467  var NOTIFICATION_OPTION_NAMES = [
1468    "actions",
1469    "badge",
1470    "body",
1471    "data",
1472    "dir",
1473    "icon",
1474    "image",
1475    "lang",
1476    "renotify",
1477    "requireInteraction",
1478    "silent",
1479    "tag",
1480    "timestamp",
1481    "title",
1482    "vibrate"
1483  ];
1484  function isLocalhost(scope2) {
1485    return /(?:^https?:\/\/)?(?:(?:^|[^\w.])localhost|\[::1\]|127(?:\.\d{1,3}){3})(?::\d+)?(?:\/.*)?$/.test(scope2);
1486  }
1487  var DriverReadyState;
1488  (function(DriverReadyState2) {
1489    DriverReadyState2[DriverReadyState2["NORMAL"] = 0] = "NORMAL";
1490    DriverReadyState2[DriverReadyState2["EXISTING_CLIENTS_ONLY"] = 1] = "EXISTING_CLIENTS_ONLY";
1491    DriverReadyState2[DriverReadyState2["SAFE_MODE"] = 2] = "SAFE_MODE";
1492  })(DriverReadyState || (DriverReadyState = {}));
1493  var Driver = class {
1494    constructor(scope2, adapter2, db) {
1495      __publicField(this, "scope");
1496      __publicField(this, "adapter");
1497      __publicField(this, "db");
1498      /**
1499       * Tracks the current readiness condition under which the SW is operating. This controls
1500       * whether the SW attempts to respond to some or all requests.
1501       */
1502      __publicField(this, "state", DriverReadyState.NORMAL);
1503      __publicField(this, "stateMessage", "(nominal)");
1504      /**
1505       * Tracks whether the SW is in an initialized state or not. Before initialization,
1506       * it's not legal to respond to requests.
1507       */
1508      __publicField(this, "initialized", null);
1509      /**
1510       * Maps client IDs to the manifest hash of the application version being used to serve
1511       * them. If a client ID is not present here, it has not yet been assigned a version.
1512       *
1513       * If a ManifestHash appears here, it is also present in the `versions` map below.
1514       */
1515      __publicField(this, "clientVersionMap", /* @__PURE__ */ new Map());
1516      /**
1517       * Maps manifest hashes to instances of `AppVersion` for those manifests.
1518       */
1519      __publicField(this, "versions", /* @__PURE__ */ new Map());
1520      /**
1521       * The latest version fetched from the server.
1522       *
1523       * Valid after initialization has completed.
1524       */
1525      __publicField(this, "latestHash", null);
1526      __publicField(this, "lastUpdateCheck", null);
1527      /**
1528       * Whether there is a check for updates currently scheduled due to navigation.
1529       */
1530      __publicField(this, "scheduledNavUpdateCheck", false);
1531      /**
1532       * Keep track of whether we have logged an invalid `only-if-cached` request.
1533       * (See `.onFetch()` for details.)
1534       */
1535      __publicField(this, "loggedInvalidOnlyIfCachedRequest", false);
1536      __publicField(this, "ngswStatePath");
1537      /**
1538       * A scheduler which manages a queue of tasks that need to be executed when the SW is
1539       * not doing any other work (not processing any other requests).
1540       */
1541      __publicField(this, "idle");
1542      __publicField(this, "debugger");
1543      // A promise resolving to the control DB table.
1544      __publicField(this, "controlTable");
1545      this.scope = scope2;
1546      this.adapter = adapter2;
1547      this.db = db;
1548      this.controlTable = this.db.open("control");
1549      this.ngswStatePath = this.adapter.parseUrl("ngsw/state", this.scope.registration.scope).path;
1550      this.scope.addEventListener("install", (event) => {
1551        event.waitUntil(this.scope.skipWaiting());
1552      });
1553      this.scope.addEventListener("activate", (event) => {
1554        event.waitUntil((async () => {
1555          await this.scope.clients.claim();
1556        })());
1557        if (this.scope.registration.active !== null) {
1558          this.scope.registration.active.postMessage({ action: "INITIALIZE" });
1559        }
1560      });
1561      this.scope.addEventListener("fetch", (event) => this.onFetch(event));
1562      this.scope.addEventListener("message", (event) => this.onMessage(event));
1563      this.scope.addEventListener("push", (event) => this.onPush(event));
1564      this.scope.addEventListener("notificationclick", (event) => this.onClick(event));
1565      this.scope.addEventListener("notificationclose", (event) => this.onClose(event));
1566      this.scope.addEventListener("pushsubscriptionchange", (event) => (
1567        // This is a bug in TypeScript, where they removed `PushSub
1567scriptionChangeEvent`
1568        // based on the incorrect assumption that browsers don't support it.
1569        this.onPushSubscriptionChange(event)
1570      ));
1571      this.scope.addEventListener("messageerror", (event) => this.onMessageError(event));
1572      this.scope.addEventListener("unhandledrejection", (event) => this.onUnhandledRejection(event));
1573      this.debugger = new DebugHandler(this, this.adapter);
1574      this.idle = new IdleScheduler(this.adapter, IDLE_DELAY, MAX_IDLE_DELAY, this.debugger);
1575    }
1576    /**
1577     * The handler for fetch events.
1578     *
1579     * This is the transition point between the synchronous event handler and the
1580     * asynchronous execution that eventually resolves for respondWith() and waitUntil().
1581     */
1582    onFetch(event) {
1583      const req = event.request;
1584      const scopeUrl = this.scope.registration.scope;
1585      const requestUrlObj = this.adapter.parseUrl(req.url, scopeUrl);
1586      if (req.headers.has("ngsw-bypass") || /[?&]ngsw-bypass(?:[=&]|$)/i.test(requestUrlObj.search)) {
1587        return;
1588      }
1589      if (requestUrlObj.path === this.ngswStatePath) {
1590        event.respondWith(this.debugger.handleFetch(req));
1591        return;
1592      }
1593      if (this.state === DriverReadyState.SAFE_MODE) {
1594        event.waitUntil(this.idle.trigger());
1595        return;
1596      }
1597      if (requestUrlObj.origin.startsWith("http:") && scopeUrl.startsWith("https:")) {
1598        this.debugger.log(`Ignoring passive mixed content request: Driver.fetch(${req.url})`);
1599        return;
1600      }
1601      if (req.cache === "only-if-cached" && req.mode !== "same-origin") {
1602        if (!this.loggedInvalidOnlyIfCachedRequest) {
1603          this.loggedInvalidOnlyIfCachedRequest = true;
1604          this.debugger.log(`Ignoring invalid request: 'only-if-cached' can be set only with 'same-origin' mode`, `Driver.fetch(${req.url}, cache: ${req.cache}, mode: ${req.mode})`);
1605        }
1606        return;
1607      }
1608      event.respondWith(this.handleFetch(event));
1609    }
1610    /**
1611     * The handler for message events.
1612     */
1613    onMessage(event) {
1614      if (this.state === DriverReadyState.SAFE_MODE) {
1615        return;
1616      }
1617      const data = event.data;
1618      if (!data || !data.action) {
1619        return;
1620      }
1621      event.waitUntil((async () => {
1622        if (data.action === "INITIALIZE") {
1623          return this.ensureInitialized(event);
1624        }
1625        if (!this.adapter.isClient(event.source)) {
1626          return;
1627        }
1628        await this.ensureInitialized(event);
1629        await this.handleMessage(data, event.source);
1630      })());
1631    }
1632    onPush(msg) {
1633      if (!msg.data) {
1634        return;
1635      }
1636      msg.waitUntil(this.handlePush(msg.data.json()));
1637    }
1638    onClick(event) {
1639      event.waitUntil(this.handleClick(event.notification, event.action));
1640    }
1641    onClose(event) {
1642      event.waitUntil(this.handleClose(event.notification, event.action));
1643    }
1644    onPushSubscriptionChange(event) {
1645      event.waitUntil(this.handlePushSubscriptionChange(event));
1646    }
1647    onMessageError(event) {
1648      this.debugger.log(`Message error occurred - data could not be deserialized`, `Driver.onMessageError(origin: ${event.origin})`);
1649    }
1650    onUnhandledRejection(event) {
1651      this.debugger.log(`Unhandled promise rejection occurred`, `Driver.onUnhandledRejection(reason: ${event.reason})`);
1652    }
1653    async ensureInitialized(event) {
1654      if (this.initialized !== null) {
1655        return this.initialized;
1656      }
1657      try {
1658        this.initialized = this.initialize();
1659        await this.initialized;
1660      } catch (error) {
1661        this.state = DriverReadyState.SAFE_MODE;
1662        this.stateMessage = `Initialization failed due to error: ${errorToString(error)}`;
1663        throw error;
1664      } finally {
1665        event.waitUntil(this.idle.trigger());
1666      }
1667    }
1668    async handleMessage(msg, from) {
1669      if (isMsgCheckForUpdates(msg)) {
1670        const action = this.checkForUpdate();
1671        await this.completeOperation(from, action, msg.nonce);
1672      } else if (isMsgActivateUpdate(msg)) {
1673        const action = this.updateClient(from);
1674        await this.completeOperation(from, action, msg.nonce);
1675      }
1676    }
1677    async handlePush(data) {
1678      await this.broadcast({
1679        type: "PUSH",
1680        data
1681      });
1682      if (!data.notification || !data.notification.title) {
1683        return;
1684      }
1685      const desc = data.notification;
1686      let options = {};
1687      NOTIFICATION_OPTION_NAMES.filter((name) =>
1687 desc.hasOwnProperty(name)).forEach((name) => options[name] = desc[name]);
1688      await this.scope.registration.showNotification(desc["title"], options);
1689    }
1690    async handleClick(notification, action) {
1691      var _a, _b, _c;
1692      notification.close();
1693      const options = {};
1694      NOTIFICATION_OPTION_NAMES.filter((name) => name in notification).forEach((name) => options[name] = notification[name]);
1695      const notificationAction = action === "" || action === void 0 ? "default" : action;
1696      const onActionClick = (_b = (_a = notification == null ? void 0 : notification.data) == null ? void 0 : _a.onActionClick) == null ? void 0 : _b[notificationAction];
1697      const urlToOpen = new URL((_c = onActionClick == null ? void 0 : onActionClick.url) != null ? _c : "", this.scope.registration.scope).href;
1698      switch (onActionClick == null ? void 0 : onActionClick.operation) {
1699        case "openWindow":
1700          await this.scope.clients.openWindow(urlToOpen);
1701          break;
1702        case "focusLastFocusedOrOpen": {
1703          let matchingClient = await this.getLastFocusedMatchingClient(this.scope);
1704          if (matchingClient) {
1705            await (matchingClient == null ? void 0 : matchingClient.focus());
1706          } else {
1707            await this.scope.clients.openWindow(urlToOpen);
1708          }
1709          break;
1710        }
1711        case "navigateLastFocusedOrOpen": {
1712          let matchingClient = await this.getLastFocusedMatchingClient(this.scope);
1713          if (matchingClient) {
1714            matchingClient = await matchingClient.navigate(urlToOpen);
1715            await (matchingClient == null ? void 0 : matchingClient.focus());
1716          } else {
1717            await this.scope.clients.openWindow(urlToOpen);
1718          }
1719          break;
1720        }
1721        case "sendRequest": {
1722          await this.scope.fetch(urlToOpen);
1723          break;
1724        }
1725        default:
1726          break;
1727      }
1728      await this.broadcast({
1729        type: "NOTIFICATION_CLICK",
1730        data: { action, notification: options }
1731      });
1732    }
1733    /**
1734     * Handles the closing of a notification by extracting its options and
1735     * broadcasting a `NOTIFICATION_CLOSE` message.
1736     *
1737     * This is typically called when a notification is dismissed by the user
1738     * or closed programmatically, and it relays that information to clients
1739     * listening for service worker events.
1740     *
1741     * @param notification - The original `Notification` object that was closed.
1742     * @param action - The action string associated with the close event, if any (usually an empty string).
1743     */
1744    async handleClose(notification, action) {
1745      const options = {};
1746      NOTIFICATION_OPTION_NAMES.filter((name) => name in notification).forEach((name) => options[name] = notification[name]);
1747      await this.broadcast({
1748        type: "NOTIFICATION_CLOSE",
1749        data: { action, notification: options }
1750      });
1751    }
1752    /**
1753     * Handles changes to the push subscription by capturing the old and new
1754     * subscription details and broadcasting a `PUSH_SUBSCRIPTION_CHANGE` message.
1755     *
1756     * This method is triggered when the browser invalidates an existing push
1757     * subscription and creates a new one, which can happen without user interaction.
1758     * It ensures that clients listening for service worker events are informed
1759     * of the subscription update.
1760     *
1761     * @param event - The `PushSubscriptionChangeEvent` containing the old and new subscriptions.
1762     */
1763    async handlePushSubscriptionChange(event) {
1764      const { oldSubscription, newSubscription } = event;
1765      await this.broadcast({
1766        type: "PUSH_SUBSCRIPTION_CHANGE",
1767        data: { oldSubscription, newSubscription }
1768      });
1769    }
1770    async getLastFocusedMatchingClient(scope2) {
1771      const windowClients = await scope2.clients.matchAll({ type: "window" });
1772      return windowClients[0];
1773    }
1774    async completeOperation(client, promise, nonce) {
1775      const response = { type: "OPERATION_COMPLETED", nonce };
1776      try {
1777        client.postMessage(__spreadProps(__spreadValues({}, response), {
1778          result: await promise
1779        }));
1780      } catch (e) {
1781        client.postMessage(__spreadProps(__spreadValues({}, response), {
1782          error: e.toString()
1783        }));
1784      }
1785    }
1786    async updateClient(client) {
1787      const existing = this.clientVersionMap.get(client.id);
1788      if (existing === this.latestHash) {
1789        return false;
1790      }
1791      let previous = void 0;
1792      if (existing !== void 0) {
1793        const existingVersion = this.versions.get(existing);
1794        previous = this.mergeHashWithAppData(existingVersion.manifest, existing);
1795      }
1796      this.clientVersionMap.set(client.id, this.latestHash);
1797      await this.sync();
1798      const current = this.versions.get(this.latestHash);
1799      return true;
1800    }
1801    async handleFetch(event) {
1802      try {
1803        await this.ensureInitialized(event);
1804      } catch (e) {
1805        return this.safeFetch(event.request);
1806      }
1807      if (event.request.mode === "navigate" && !this.scheduledNavUpdateCheck) {
1808        this.scheduledNavUpdateCheck = true;
1809        this.idle.schedule("check-updates-on-navigation", async () => {
1810          this.scheduledNavUpdateCheck = false;
1811          await this.checkForUpdate();
1812        });
1813      }
1814      const appVersion = await this.assignVersion(event);
1815      const isVersionWithinMaxAge = (appVersion == null ? void 0 : appVersion.manifest.applicationMaxAge) === void 0 || this.adapter.time - appVersion.manifest.timestamp < appVersion.manifest.applicationMaxAge;
1816      let res = null;
1817      try {
1818        if (appVersion !== null && isVersionWithinMaxAge) {
1819          try {
1820            res = await appVersion.handleFetch(event.request, event);
1821          } catch (err) {
1822            if (err.isUnrecoverableState) {
1823              await this.notifyClientsAboutUnrecoverableState(appVersion, err.message);
1824            }
1825            if (err.isCritical) {
1826              this.debugger.log(err, `Driver.handleFetch(version: ${appVersion.manifestHash})`);
1827              await this.versionFailed(appVersion, err);
1828              return this.safeFetch(event.request);
1829            }
1830            throw err;
1831          }
1832        }
1833        if (res === null) {
1834          return this.safeFetch(event.request);
1835        }
1836        return res;
1837      } finally {
1838        event.waitUntil(this.idle.trigger());
1839      }
1840    }
1841    /**
1842     * Attempt to quickly reach a state where it's safe to serve responses.
1843     */
1844    async initialize() {
1845      const table = await this.controlTable;
1846      let manifests, assignments, latest;
1847      try {
1848        [manifests, assignments, latest] = await Promise.all([
1849          table.read("manifests"),
1850          table.read("assignments"),
1851          table.read("latest")
1852        ]);
1853        if (!this.versions.has(latest.latest) && !manifests.hasOwnProperty(latest.latest)) {
1854          this.debugger.log(`Missing manifest for latest version hash ${latest.latest}`, "initialize: read from DB");
1855          throw new Error(`Missing manifest for latest hash ${latest.latest}`);
1856        }
1857        this.idle.schedule("init post-load (update)", async () => {
1858          await this.checkForUpdate();
1859        });
1860      } catch (_) {
1861        const manifest = await this.fetchLatestManifest();
1862        const hash = hashManifest(manifest);
1863        manifests = { [hash]: manifest };
1864        assignments = {};
1865        latest = { latest: hash };
1866        await Promise.all([
1867          table.write("manifests", manifests),
1868          table.write("assignments", assignments),
1869          table.write("latest", latest)
1870        ]);
1871      }
1872      this.idle.schedule("init post-load (cleanup)", async () => {
1873        await this.cleanupCaches();
1874      });
1875      Object.keys(manifests).forEach((hash) => {
1876        const manifest = manifests[hash];
1877        if (!this.versions.has(hash)) {
1878          this.versions.set(hash, new AppVersion(this.scope, this.adapter, this.db, this.idle, this.debugger, manifest, hash));
1879        }
1880      });
1881      Object.keys(assignments).forEach((clientId) => {
1882        const hash = assignments[clientId];
1883        if (this.versions.has(hash)) {
1884          this.clientVersionMap.set(clientId, hash);
1885        } else {
1886          this.clientVersionMap.set(clientId, latest.latest);
1887          this.debugger.log(`Unknown version ${hash} mapped for client ${clientId}, using latest instead`, `initialize: map assignments`);
1888        }
1889      });
1890      this.latestHash = latest.latest;
1891      if (!this.versions.has(latest.latest)) {
1892        throw new Error(`Invariant violated (initialize): latest hash ${latest.latest} has no known manifest`);
1893      }
1894      await Promise.all(Object.keys(manifests).map(async (hash) => {
1895        try {
1896          await this.scheduleInitialization(this.versions.get(hash));
1897        } catch (err) {
1898          this.debugger.log(err, `initialize: schedule init of ${hash}`);
1899        }
1900      }));
1901    }
1902    lookupVersionByHash(hash, debugName = "lookupVersionByHash") {
1903      if (!this.versions.has(hash)) {
1904        throw new Error(`Invariant violated (${debugName}): want AppVersion for ${hash} but not loaded`);
1905      }
1906      return this.versions.get(hash);
1907    }
1908    /**
1909     * Decide which version of the manifest to use for the event.
1910     */
1911    async assignVersion(event) {
1912      const isWorkerScriptRequest = event.request.destination === "worker" && event.resultingClientId && event.clientId;
1913      const clientId = isWorkerScriptRequest ? event.clientId : event.resultingClientId || event.clientId;
1914      if (clientId) {
1915        if (this.clientVersionMap.has(clientId)) {
1916          const hash = this.clientVersionMap.get(clientId);
1917          let appVersion = this.lookupVersionByHash(hash, "assignVersion");
1918          if (this.state === DriverReadyState.NORMAL && hash !== this.latestHash && appVersion.isNavigationRequest(event.request)) {
1919            if (this.latestHash === null) {
1920              throw new Error(`Invariant violated (assignVersion): latestHash was null`);
1921            }
1922            const client = await this.scope.clients.get(clientId);
1923            if (client) {
1924              await this.updateClient(client);
1925            }
1926            appVersion = this.lookupVersionByHash(this.latestHash, "assignVersion");
1927          }
1928          if (isWorkerScriptRequest) {
1929            if (!this.clientVersionMap.has(event.resultingClientId)) {
1930              this.clientVersionMap.set(event.resultingClientId, hash);
1931              await this.sync();
1932            } else if (this.clientVersionMap.get(event.resultingClientId) !== hash) {
1933              throw new Error(`Version mismatch between worker client ${event.resultingClientId} and requesting client ${clientId}`);
1934            }
1935          }
1936          return appVersion;
1937        } else {
1938          if (this.state !== DriverReadyState.NORMAL) {
1939            return null;
1940          }
1941          if (this.latestHash === null) {
1942            throw new Error(`Invariant violated (assignVersion): latestHash was null`);
1943          }
1944          if (isWorkerScriptRequest) {
1945            if (!this.clientVersionMap.has(event.resultingClientId)) {
1946              this.clientVersionMap.set(event.resultingClientId, this.latestHash);
1947            } else if (this.clientVersionMap.get(event.resultingClientId) !== this.latestHash) {
1948              throw new Error(`Version mismatch between worker client ${event.resultingClientId} and requesting client ${clientId}`);
1949            }
1950          }
1951          this.clientVersionMap.set(clientId, this.latestHash);
1952          await this.sync();
1953          return this.lookupVersionByHash(this.latestHash, "assignVersion");
1954        }
1955      } else {
1956        if (this.state !== DriverReadyState.NORMAL) {
1957          return null;
1958        }
1959        if (this.latestHash === null) {
1960          throw new Error(`Invariant violated (assignVersion): latestHash was null`);
1961        }
1962        return this.lookupVersionByHash(this.latestHash, "assignVersion");
1963      }
1964    }
1965    async fetchLatestManifest(ignoreOfflineError = false) {
1966      const res = await this.safeFetch(this.adapter.newRequest("ngsw.json?ngsw-cache-bust=" + Math.random()));
1967      if (!res.ok) {
1968        if (res.status === 404) {
1969          await this.deleteAllCaches();
1970          await this.scope.registration.unregister();
1971        } else if ((res.status === 503 || res.status === 504) && ignoreOfflineError) {
1972          return null;
1973        }
1974        throw new Error(`Manifest fetch failed! (status: ${res.status})`);
1975      }
1976      this.lastUpdateCheck = this.adapter.time;
1977      return res.json();
1978    }
1979    async deleteAllCaches() {
1980      const cacheNames = await this.adapter.caches.keys();
1981      await Promise.all(cacheNames.map((name) => this.adapter.caches.delete(name)));
1982    }
1983    /**
1984     * Schedule the SW's attempt to reach a fully prefetched state for the given AppVersion
1985     * when the SW is not busy and has connectivity. This returns a Promise which must be
1986     * awaited, as under some conditions the AppVersion might be initialized immediately.
1987     */
1988    async scheduleInitialization(appVersion) {
1989      const initialize = async () => {
1990        try {
1991          await appVersion.initializeFully();
1992        } catch (err) {
1993          this.debugger.log(err, `initializeFully for ${appVersion.manifestHash}`);
1994          await this.versionFailed(appVersion, err);
1995        }
1996      };
1997      if (isLocalhost(this.scope.registration.scope)) {
1998        return initialize();
1999      }
2000      this.idle.schedule(`initialization(${appVersion.manifestHash})`, initialize);
2001    }
2002    async versionFailed(appVersion, err) {
2003      const broken = Array.from(this.versions.entries()).find(([hash, version]
2003) => version === appVersion);
2004      if (broken === void 0) {
2005        return;
2006      }
2007      const brokenHash = broken[0];
2008      if (this.latestHash === brokenHash) {
2009        this.state = DriverReadyState.EXISTING_CLIENTS_ONLY;
2010        this.stateMessage = `Degraded due to: ${errorToString(err)}`;
2011      }
2012    }
2013    async setupUpdate(manifest, hash) {
2014      try {
2015        const newVersion = new AppVersion(this.scope, this.adapter, this.db, this.idle, this.debugger, manifest, hash);
2016        if (manifest.configVersion !== SUPPORTED_CONFIG_VERSION) {
2017          await this.deleteAllCaches();
2018          await this.scope.registration.unregister();
2019          throw new Error(`Invalid config version: expected ${SUPPORTED_CONFIG_VERSION}, got ${manifest.configVersion}.`);
2020        }
2021        await newVersion.initializeFully(this);
2022        this.versions.set(hash, newVersion);
2023        this.latestHash = hash;
2024        if (this.state === DriverReadyState.EXISTING_CLIENTS_ONLY) {
2025          this.state = DriverReadyState.NORMAL;
2026          this.stateMessage = "(nominal)";
2027        }
2028        await this.sync();
2029        await this.notifyClientsAboutVersionReady(manifest, hash);
2030      } catch (e) {
2031        await this.notifyClientsAboutVersionInstallationFailed(manifest, hash, e);
2032        throw e;
2033      }
2034    }
2035    async checkForUpdate() {
2036      let hash = "(unknown)";
2037      try {
2038        const manifest = await this.fetchLatestManifest(true);
2039        if (manifest === null) {
2040          this.debugger.log("Check for update aborted. (Client or server offline.)");
2041          return false;
2042        }
2043        hash = hashManifest(manifest);
2044        if (this.versions.has(hash)) {
2045          await this.notifyClientsAboutNoNewVersionDetected(manifest, hash);
2046          return false;
2047        }
2048        await this.notifyClientsAboutVersionDetected(manifest, hash);
2049        await this.setupUpdate(manifest, hash);
2050        return true;
2051      } catch (err) {
2052        this.debugger.log(err, `Error occurred while updating to manifest ${hash}`);
2053        this.state = DriverReadyState.EXISTING_CLIENTS_ONLY;
2054        this.stateMessage = `Degraded due to failed initialization: ${errorToString(err)}`;
2055        return false;
2056      }
2057    }
2058    /**
2059     * Synchronize the existing state to the underlying database.
2060     */
2061    async sync() {
2062      const table = await this.controlTable;
2063      const manifests = {};
2064      this.versions.forEach((version, hash) => {
2065        manifests[hash] = version.manifest;
2066      });
2067      const assignments = {};
2068      this.clientVersionMap.forEach((hash, clientId) => {
2069        assignments[clientId] = hash;
2070      });
2071      const latest = {
2072        latest: this.latestHash
2073      };
2074      await Promise.all([
2075        table.write("manifests", manifests),
2076        table.write("assignments", assignments),
2077        table.write("latest", latest)
2078      ]);
2079    }
2080    async cleanupCaches() {
2081      try {
2082        const activeClients = new Set((await this.scope.clients.matchAll()).map((client) => client.id));
2083        const knownClients = Array.from(this.clientVersionMap.keys());
2084        const obsoleteClients = knownClients.filter((id) => !activeClients.has(id));
2085        obsoleteClients.forEach((id) => this.clientVersionMap.delete(id));
2086        const usedVersions = new Set(this.clientVersionMap.values());
2087        const obsoleteVersions = Array.from(this.versions.keys()).filter((version) => !usedVersions.has(version) && version !== this.latestHash);
2088        obsoleteVersions.forEach((version) => this.versions.delete(version));
2089        await this.sync();
2090        const allCaches = await this.adapter.caches.keys();
2091        const usedCaches = new Set(await this.getCacheNames());
2092        const cachesToDelete = allCaches.filter((name) => !usedCaches.has(name));
2093        await Promise.all(cachesToDelete.map((name) => this.adapter.caches.delete(name)));
2094      } catch (err) {
2095        this.debugger.log(err, "cleanupCaches");
2096      }
2097    }
2098    /**
2099     * Determine if a specific version of the given resource is cached anywhere within the SW,
2100     * and fetch it if so.
2101     */
2102    lookupResourceWithHash(url, hash) {
2103      return Array.from(this.versions.values()).reduce(async (prev, version) => {
2104        if (await prev !== null) {
2105          return prev;
2106        }
2107        return version.lookupResourceWithHash(url, hash);
2108      }, Promise.resolve(null));
2109    }
2110    async lookupResourceWithoutHash(url) {
2111      await this.initialized;
2112      const version = this.versions.get(this.latestHash);
2113      return version ? version.lookupResourceWithoutHash(url) : null;
2114    }
2115    async previouslyCachedResources() {
2116      await this.initialized;
2117      const version = this.versions.get(this.latestHash);
2118      return version ? version.previouslyCachedResources() : [];
2119    }
2120    async recentCacheStatus(url) {
2121      const version = this.versions.get(this.latestHash);
2122      return version ? version.recentCacheStatus(url) : UpdateCacheStatus.NOT_CACHED;
2123    }
2124    mergeHashWithAppData(manifest, hash) {
2125      return {
2126        hash,
2127        appData: manifest.appData
2128      };
2129    }
2130    async notifyClientsAboutUnrecoverableState(appVersion, reason) {
2131      const broken = Array.from(this.versions.entries()).find(([hash, version]) => version === appVersion);
2132      if (broken === void 0) {
2133        return;
2134      }
2135      const brokenHash = broken[0];
2136      const affectedClients = Array.from(this.clientVersionMap.entries()).filter(([clientId, hash]) => hash === brokenHash).map(([clientId]) => clientId);
2137      await Promise.all(affectedClients.map(async (clientId) => {
2138        const client = await this.scope.clients.get(clientId);
2139        if (client) {
2140          client.postMessage({ type: "UNRECOVERABLE_STATE", reason });
2141        }
2142      }));
2143    }
2144    async notifyClientsAboutVersionInstallationFailed(manifest, hash, error) {
2145      await this.initialized;
2146      const clients = await this.scope.clients.matchAll();
2147      await Promise.all(clients.map(async (client) => {
2148        client.postMessage({
2149          type: "VERSION_INSTALLATION_FAILED",
2150          version: this.mergeHashWithAppData(manifest, hash),
2151          error: errorToString(error)
2152        });
2153      }));
2154    }
2155    async notifyClientsAboutNoNewVersionDetected(manifest, hash) {
2156      await this.initialized;
2157      const clients = await this.scope.clients.matchAll();
2158      await Promise.all(clients.map(async (client) => {
2159        client.postMessage({
2160          type: "NO_NEW_VERSION_DETECTED",
2161          version: this.mergeHashWithAppData(manifest, hash)
2162        });
2163      }));
2164    }
2165    async notifyClientsAboutVersionDetected(manifest, hash) {
2166      await this.initialized;
2167      const clients = await this.scope.clients.matchAll();
2168      await Promise.all(clients.map(async (client) => {
2169        const version = this.clientVersionMap.get(client.id);
2170        if (version === void 0) {
2171          return;
2172        }
2173        client.postMessage({
2174          type: "VERSION_DETECTED",
2175          version: this.mergeHashWithAppData(manifest, hash)
2176        });
2177      }));
2178    }
2179    async notifyClientsAboutVersionReady(manifest, hash) {
2180      await this.initialized;
2181      const clients = await this.scope.clients.matchAll();
2182      await Promise.all(clients.map(async (client) => {
2183        const version = this.clientVersionMap.get(client.id);
2184        if (version === void 0) {
2185          return;
2186        }
2187        if (version === this.latestHash) {
2188          return;
2189        }
2190        const current = this.versions.get(version);
2191        const notice = {
2192          type: "VERSION_READY",
2193          currentVersion: this.mergeHashWithAppData(current.manifest, version),
2194          latestVersion: this.mergeHashWithAppData(manifest, hash)
2195        };
2196        client.postMessage(notice);
2197      }));
2198    }
2199    async broadcast(msg) {
2200      const clients = await this.scope.clients.matchAll();
2201      clients.forEach((client) => {
2202        client.postMessage(msg);
2203      });
2204    }
2205    async debugState() {
2206      return {
2207        state: DriverReadyState[this.state],
2208        why: this.stateMessage,
2209        latestHash: this.latestHash,
2210        lastUpdateCheck: this.lastUpdateCheck
2211      };
2212    }
2213    async debugVersions() {
2214      return Array.from(this.versions.keys()).map((hash) => {
2215        const version = this.versions.get(hash);
2216        const clients = Array.from(this.clientVersionMap.entries()).filter(([clientId, version2]) => version2 === hash).map(([clientId, version2]) => clientId);
2217        return {
2218          hash,
2219          manifest: version.manifest,
2220          clients,
2221          status: ""
2222        };
2223      });
2224    }
2225    async debugIdleState() {
2226      return {
2227        queue: this.idle.taskDescriptions,
2228        lastTrigger: this.idle.lastTrigger,
2229        lastRun: this.idle.lastRun
2230      };
2231    }
2232    async safeFetch(req) {
2233      try {
2234        return await this.scope.fetch(req);
2235      } catch (err) {
2236        this.debugger.log(err, `Driver.fetch(${req.url})`);
2237        return this.adapter.newResponse(null, {
2238          status: 504,
2239          statusText: "Gateway Timeout"
2240        });
2241      }
2242    }
2243    async getCacheNames() {
2244      const controlTable = await this.controlTable;
2245      const appVersions = Array.from(this.versions.values());
2246      const appVersionCacheNames = await Promise.all(appVersions.map((version) => version.getCacheNames()));
2247      return [controlTable.cacheName].concat(...appVersionCacheNames);
2248    }
2249  };
2250
2251  
2251// packages/service-worker/worker/main.ts
2252  var scope = self;
2253  var adapter = new Adapter(scope.registration.scope, self.caches);
2254  new Driver(scope, adapter, new CacheDatabase(adapter));
2255})();
2256/**
2257 * @license
2258 * Copyright Google LLC All Rights Reserved.
2259 *
2260 * Use of this source code is governed by an MIT-style license that can be
2261 * found in the LICENSE file at https://angular.dev/license
2262 */
2263importScripts("./ngsw-notifications.js");

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.