UNPKG

67.2 kBJavaScriptView Raw
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
22 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/named-cache-storage.mjs
23 var NamedCacheStorage = class {
24 constructor(original, cacheNamePrefix) {
25 this.original = original;
26 this.cacheNamePrefix = cacheNamePrefix;
27 }
28 delete(cacheName) {
29 return this.original.delete(`${this.cacheNamePrefix}:${cacheName}`);
30 }
31 has(cacheName) {
32 return this.original.has(`${this.cacheNamePrefix}:${cacheName}`);
33 }
34 async keys() {
35 const prefix = `${this.cacheNamePrefix}:`;
36 const allCacheNames = await this.original.keys();
37 const ownCacheNames = allCacheNames.filter((name) => name.startsWith(prefix));
38 return ownCacheNames.map((name) => name.slice(prefix.length));
39 }
40 match(request, options) {
41 return this.original.match(request, options);
42 }
43 async open(cacheName) {
44 const cache = await this.original.open(`${this.cacheNamePrefix}:${cacheName}`);
45 return Object.assign(cache, { name: cacheName });
46 }
47 };
48
49 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/adapter.mjs
50 var Adapter = class {
51 constructor(scopeUrl, caches) {
52 this.scopeUrl = scopeUrl;
53 const parsedScopeUrl = this.parseUrl(this.scopeUrl);
54 this.origin = parsedScopeUrl.origin;
55 this.caches = new NamedCacheStorage(caches, `ngsw:${parsedScopeUrl.path}`);
56 }
57 newRequest(input, init) {
58 return new Request(input, init);
59 }
60 newResponse(body, init) {
61 return new Response(body, init);
62 }
63 newHeaders(headers) {
64 return new Headers(headers);
65 }
66 isClient(source) {
67 return source instanceof Client;
68 }
69 get time() {
70 return Date.now();
71 }
72 normalizeUrl(url) {
73 const parsed = this.parseUrl(url, this.scopeUrl);
74 return parsed.origin === this.origin ? parsed.path : url;
75 }
76 parseUrl(url, relativeTo) {
77 const parsed = !relativeTo ? new URL(url) : new URL(url, relativeTo);
78 return { origin: parsed.origin, path: parsed.pathname, search: parsed.search };
79 }
80 timeout(ms) {
81 return new Promise((resolve) => {
82 setTimeout(() => resolve(), ms);
83 });
84 }
85 };
86
87 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/database.mjs
88 var NotFound = class {
89 constructor(table, key) {
90 this.table = table;
91 this.key = key;
92 }
93 };
94
95 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/db-cache.mjs
96 var CacheDatabase = class {
97 constructor(adapter2) {
98 this.adapter = adapter2;
99 this.cacheNamePrefix = "db";
100 this.tables = /* @__PURE__ */ new Map();
101 }
102 "delete"(name) {
103 if (this.tables.has(name)) {
104 this.tables.delete(name);
105 }
106 return this.adapter.caches.delete(`${this.cacheNamePrefix}:${name}`);
107 }
108 async list() {
109 const prefix = `${this.cacheNamePrefix}:`;
110 const allCacheNames = await this.adapter.caches.keys();
111 const dbCacheNames = allCacheNames.filter((name) => name.startsWith(prefix));
112 return dbCacheNames.map((name) => name.slice(prefix.length));
113 }
114 async open(name, cacheQueryOptions) {
115 if (!this.tables.has(name)) {
116 const cache = await this.adapter.caches.open(`${this.cacheNamePrefix}:${name}`);
117 const table = new CacheTable(name, cache, this.adapter, cacheQueryOptions);
118 this.tables.set(name, table);
119 }
120 return this.tables.get(name);
121 }
122 };
123 var CacheTable = class {
124 constructor(name, cache, adapter2, cacheQueryOptions) {
125 this.name = name;
126 this.cache = cache;
127 this.adapter = adapter2;
128 this.cacheQueryOptions = cacheQueryOptions;
129 this.cacheName = this.cache.name;
130 }
131 request(key) {
132 return this.adapter.newRequest("/" + key);
133 }
134 "delete"(key) {
135 return this.cache.delete(this.request(key), this.cacheQueryOptions);
136 }
137 keys() {
138 return this.cache.keys().then((requests) => requests.map((req) => req.url.slice(1)));
139 }
140 read(key) {
141 return this.cache.match(this.request(key), this.cacheQueryOptions).then((res) => {
142 if (res === void 0) {
143 return Promise.reject(new NotFound(this.name, key));
144 }
145 return res.json();
146 });
147 }
148 write(key, value) {
149 return this.cache.put(this.request(key), this.adapter.newResponse(JSON.stringify(value)));
150 }
151 };
152
153 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/api.mjs
154 var UpdateCacheStatus;
155 (function(UpdateCacheStatus2) {
156 UpdateCacheStatus2[UpdateCacheStatus2["NOT_CACHED"] = 0] = "NOT_CACHED";
157 UpdateCacheStatus2[UpdateCacheStatus2["CACHED_BUT_UNUSED"] = 1] = "CACHED_BUT_UNUSED";
158 UpdateCacheStatus2[UpdateCacheStatus2["CACHED"] = 2] = "CACHED";
159 })(UpdateCacheStatus || (UpdateCacheStatus = {}));
160
161 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/error.mjs
162 var SwCriticalError = class extends Error {
163 constructor() {
164 super(...arguments);
165 this.isCritical = true;
166 }
167 };
168 function errorToString(error) {
169 if (error instanceof Error) {
170 return `${error.message}
171${error.stack}`;
172 } else {
173 return `${error}`;
174 }
175 }
176 var SwUnrecoverableStateError = class extends SwCriticalError {
177 constructor() {
178 super(...arguments);
179 this.isUnrecoverableState = true;
180 }
181 };
182
183 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/sha1.mjs
184 function sha1(str) {
185 const utf8 = str;
186 const words32 = stringToWords32(utf8, Endian.Big);
187 return _sha1(words32, utf8.length * 8);
188 }
189 function sha1Binary(buffer) {
190 const words32 = arrayBufferToWords32(buffer, Endian.Big);
191 return _sha1(words32, buffer.byteLength * 8);
192 }
193 function _sha1(words32, len) {
194 const w = [];
195 let [a, b, c, d, e] = [1732584193, 4023233417, 2562383102, 271733878, 3285377520];
196 words32[len >> 5] |= 128 << 24 - len % 32;
197 words32[(len + 64 >> 9 << 4) + 15] = len;
198 for (let i = 0; i < words32.length; i += 16) {
199 const [h0, h1, h2, h3, h4] = [a, b, c, d, e];
200 for (let j = 0; j < 80; j++) {
201 if (j < 16) {
202 w[j] = words32[i + j];
203 } else {
204 w[j] = rol32(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
205 }
206 const [f, k] = fk(j, b, c, d);
207 const temp = [rol32(a, 5), f, e, k, w[j]].reduce(add32);
208 [e, d, c, b, a] = [d, c, rol32(b, 30), a, temp];
209 }
210 [a, b, c, d, e] = [add32(a, h0), add32(b, h1), add32(c, h2), add32(d, h3), add32(e, h4)];
211 }
212 return byteStringToHexString(words32ToByteString([a, b, c, d, e]));
213 }
214 function add32(a, b) {
215 return add32to64(a, b)[1];
216 }
217 function add32to64(a, b) {
218 const low = (a & 65535) + (b & 65535);
219 const high = (a >>> 16) + (b >>> 16) + (low >>> 16);
220 return [high >>> 16, high << 16 | low & 65535];
221 }
222 function rol32(a, count) {
223 return a << count | a >>> 32 - count;
224 }
225 var Endian;
226 (function(Endian2) {
227 Endian2[Endian2["Little"] = 0] = "Little";
228 Endian2[Endian2["Big"] = 1] = "Big";
229 })(Endian || (Endian = {}));
230 function fk(index, b, c, d) {
231 if (index < 20) {
232 return [b & c | ~b & d, 1518500249];
233 }
234 if (index < 40) {
235 return [b ^ c ^ d, 1859775393];
236 }
237 if (index < 60) {
238 return [b & c | b & d | c & d, 2400959708];
239 }
240 return [b ^ c ^ d, 3395469782];
241 }
242 function stringToWords32(str, endian) {
243 const size = str.length + 3 >>> 2;
244 const words32 = [];
245 for (let i = 0; i < size; i++) {
246 words32[i] = wordAt(str, i * 4, endian);
247 }
248 return words32;
249 }
250 function arrayBufferToWords32(buffer, endian) {
251 const size = buffer.byteLength + 3 >>> 2;
252 const words32 = [];
253 const view = new Uint8Array(buffer);
254 for (let i = 0; i < size; i++) {
255 words32[i] = wordAt(view, i * 4, endian);
256 }
257 return words32;
258 }
259 function byteAt(str, index) {
260 if (typeof str === "string") {
261 return index >= str.length ? 0 : str.charCodeAt(index) & 255;
262 } else {
263 return index >= str.byteLength ? 0 : str[index] & 255;
264 }
265 }
266 function wordAt(str, index, endian) {
267 let word = 0;
268 if (endian === Endian.Big) {
269 for (let i = 0; i < 4; i++) {
270 word += byteAt(str, index + i) << 24 - 8 * i;
271 }
272 } else {
273 for (let i = 0; i < 4; i++) {
274 word += byteAt(str, index + i) << 8 * i;
275 }
276 }
277 return word;
278 }
279 function words32ToByteString(words32) {
280 return words32.reduce((str, word) => str + word32ToByteString(word), "");
281 }
282 function word32ToByteString(word) {
283 let str = "";
284 for (let i = 0; i < 4; i++) {
285 str += String.fromCharCode(word >>> 8 * (3 - i) & 255);
286 }
287 return str;
288 }
289 function byteStringToHexString(str) {
290 let hex = "";
291 for (let i = 0; i < str.length; i++) {
292 const b = byteAt(str, i);
293 hex += (b >>> 4).toString(16) + (b & 15).toString(16);
294 }
295 return hex.toLowerCase();
296 }
297
298 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/assets.mjs
299 var AssetGroup = class {
300 constructor(scope2, adapter2, idle, config, hashes, db, cacheNamePrefix) {
301 this.scope = scope2;
302 this.adapter = adapter2;
303 this.idle = idle;
304 this.config = config;
305 this.hashes = hashes;
306 this.db = db;
307 this.inFlightRequests = /* @__PURE__ */ new Map();
308 this.urls = [];
309 this.patterns = [];
310 this.name = config.name;
311 this.urls = config.urls.map((url) => adapter2.normalizeUrl(url));
312 this.patterns = config.patterns.map((pattern) => new RegExp(pattern));
313 this.cache = adapter2.caches.open(`${cacheNamePrefix}:${config.name}:cache`);
314 this.metadata = this.db.open(`${cacheNamePrefix}:${config.name}:meta`, config.cacheQueryOptions);
315 }
316 async cacheStatus(url) {
317 const cache = await this.cache;
318 const meta = await this.metadata;
319 const req = this.adapter.newRequest(url);
320 const res = await cache.match(req, this.config.cacheQueryOptions);
321 if (res === void 0) {
322 return UpdateCacheStatus.NOT_CACHED;
323 }
324 try {
325 const data = await meta.read(req.url);
326 if (!data.used) {
327 return UpdateCacheStatus.CACHED_BUT_UNUSED;
328 }
329 } catch (_) {
330 }
331 return UpdateCacheStatus.CACHED;
332 }
333 async getCacheNames() {
334 const [cache, metadata] = await Promise.all([
335 this.cache,
336 this.metadata
337 ]);
338 return [cache.name, metadata.cacheName];
339 }
340 async handleFetch(req, _event) {
341 const url = this.adapter.normalizeUrl(req.url);
342 if (this.urls.indexOf(url) !== -1 || this.patterns.some((pattern) => pattern.test(url))) {
343 const cache = await this.cache;
344 const cachedResponse = await cache.match(req, this.config.cacheQueryOptions);
345 if (cachedResponse !== void 0) {
346 if (this.hashes.has(url)) {
347 return cachedResponse;
348 } else {
349 if (await this.needToRevalidate(req, cachedResponse)) {
350 this.idle.schedule(`revalidate(${cache.name}): ${req.url}`, async () => {
351 await this.fetchAndCacheOnce(req);
352 });
353 }
354 return cachedResponse;
355 }
356 }
357 const res = await this.fetchAndCacheOnce(this.adapter.newRequest(req.url));
358 return res.clone();
359 } else {
360 return null;
361 }
362 }
363 async needToRevalidate(req, res) {
364 if (res.headers.has("Cache-Control")) {
365 const cacheControl = res.headers.get("Cache-Control");
366 const cacheDirectives = cacheControl.split(",").map((v) => v.trim()).map((v) => v.split("="));
367 cacheDirectives.forEach((v) => v[0] = v[0].toLowerCase());
368 const maxAgeDirective = cacheDirectives.find((v) => v[0] === "max-age");
369 const cacheAge = maxAgeDirective ? maxAgeDirective[1] : void 0;
370 if (!cacheAge) {
371 return true;
372 }
373 try {
374 const maxAge = 1e3 * parseInt(cacheAge);
375 let ts;
376 try {
377 const metaTable = await this.metadata;
378 ts = (await metaTable.read(req.url)).ts;
379 } catch (e) {
380 const date = res.headers.get("Date");
381 if (date === null) {
382 return true;
383 }
384 ts = Date.parse(date);
385 }
386 const age = this.adapter.time - ts;
387 return age < 0 || age > maxAge;
388 } catch (e) {
389 return true;
390 }
391 } else if (res.headers.has("Expires")) {
392 const expiresStr = res.headers.get("Expires");
393 try {
394 return this.adapter.time > Date.parse(expiresStr);
395 } catch (e) {
396 return true;
397 }
398 } else {
399 return true;
400 }
401 }
402 async fetchFromCacheOnly(url) {
403 const cache = await this.cache;
404 const metaTable = await this.metadata;
405 const request = this.adapter.newRequest(url);
406 const response = await cache.match(request, this.config.cacheQueryOptions);
407 if (response === void 0) {
408 return null;
409 }
410 let metadata = void 0;
411 try {
412 metadata = await metaTable.read(request.url);
413 } catch (e) {
414 }
415 return { response, metadata };
416 }
417 async unhashedResources() {
418 const cache = await this.cache;
419 return (await cache.keys()).map((request) => this.adapter.normalizeUrl(request.url)).filter((url) => !this.hashes.has(url));
420 }
421 async fetchAndCacheOnce(req, used = true) {
422 if (this.inFlightRequests.has(req.url)) {
423 return this.inFlightRequests.get(req.url);
424 }
425 const fetchOp = this.fetchFromNetwork(req);
426 this.inFlightRequests.set(req.url, fetchOp);
427 try {
428 const res = await fetchOp;
429 if (!res.ok) {
430 throw new Error(`Response not Ok (fetchAndCacheOnce): request for ${req.url} returned response ${res.status} ${res.statusText}`);
431 }
432 try {
433 const cache = await this.cache;
434 await cache.put(req, res.clone());
435 if (!this.hashes.has(this.adapter.normalizeUrl(req.url))) {
436 const meta = { ts: this.adapter.time, used };
437 const metaTable = await this.metadata;
438 await metaTable.write(req.url, meta);
439 }
440 return res;
441 } catch (err) {
442 throw new SwCriticalError(`Failed to update the caches for request to '${req.url}' (fetchAndCacheOnce): ${errorToString(err)}`);
443 }
444 } finally {
445 this.inFlightRequests.delete(req.url);
446 }
447 }
448 async fetchFromNetwork(req, redirectLimit = 3) {
449 const res = await this.cacheBustedFetchFromNetwork(req);
450 if (res["redirected"] && !!res.url) {
451 if (redirectLimit === 0) {
452 throw new SwCriticalError(`Response hit redirect limit (fetchFromNetwork): request redirected too many times, next is ${res.url}`);
453 }
454 return this.fetchFromNetwork(this.adapter.newRequest(res.url), redirectLimit - 1);
455 }
456 return res;
457 }
458 async cacheBustedFetchFromNetwork(req) {
459 const url = this.adapter.normalizeUrl(req.url);
460 if (this.hashes.has(url)) {
461 const canonicalHash = this.hashes.get(url);
462 let response = await this.safeFetch(req);
463 let makeCacheBustedRequest = response.ok;
464 if (makeCacheBustedRequest) {
465 const fetchedHash = sha1Binary(await response.clone().arrayBuffer());
466 makeCacheBustedRequest = fetchedHash !== canonicalHash;
467 }
468 if (makeCacheBustedRequest) {
469 const cacheBustReq = this.adapter.newRequest(this.cacheBust(req.url));
470 response = await this.safeFetch(cacheBustReq);
471 if (response.ok) {
472 const cacheBustedHash = sha1Binary(await response.clone().arrayBuffer());
473 if (canonicalHash !== cacheBustedHash) {
474 throw new SwCriticalError(`Hash mismatch (cacheBustedFetchFromNetwork): ${req.url}: expected ${canonicalHash}, got ${cacheBustedHash} (after cache busting)`);
475 }
476 }
477 }
478 if (!response.ok && response.status === 404) {
479 throw new SwUnrecoverableStateError(`Failed to retrieve hashed resource from the server. (AssetGroup: ${this.config.name} | URL: ${url})`);
480 }
481 return response;
482 } else {
483 return this.safeFetch(req);
484 }
485 }
486 async maybeUpdate(updateFrom, req, cache) {
487 const url = this.adapter.normalizeUrl(req.url);
488 if (this.hashes.has(url)) {
489 const hash = this.hashes.get(url);
490 const res = await updateFrom.lookupResourceWithHash(url, hash);
491 if (res !== null) {
492 await cache.put(req, res);
493 return true;
494 }
495 }
496 return false;
497 }
498 cacheBust(url) {
499 return url + (url.indexOf("?") === -1 ? "?" : "&") + "ngsw-cache-bust=" + Math.random();
500 }
501 async safeFetch(req) {
502 try {
503 return await this.scope.fetch(req);
504 } catch (e) {
505 return this.adapter.newResponse("", {
506 status: 504,
507 statusText: "Gateway Timeout"
508 });
509 }
510 }
511 };
512 var PrefetchAssetGroup = class extends AssetGroup {
513 async initializeFully(updateFrom) {
514 const cache = await this.cache;
515 await this.urls.reduce(async (previous, url) => {
516 await previous;
517 const req = this.adapter.newRequest(url);
518 const alreadyCached = await cache.match(req, this.config.cacheQueryOptions) !== void 0;
519 if (alreadyCached) {
520 return;
521 }
522 if (updateFrom !== void 0 && await this.maybeUpdate(updateFrom, req, cache)) {
523 return;
524 }
525 await this.fetchAndCacheOnce(req, false);
526 }, Promise.resolve());
527 if (updateFrom !== void 0) {
528 const metaTable = await this.metadata;
529 await (await updateFrom.previouslyCachedResources()).filter((url) => this.urls.indexOf(url) !== -1 || this.patterns.some((pattern) => pattern.test(url))).reduce(async (previous, url) => {
530 await previous;
531 const req = this.adapter.newRequest(url);
532 const alreadyCached = await cache.match(req, this.config.cacheQueryOptions) !== void 0;
533 if (alreadyCached) {
534 return;
535 }
536 const res = await updateFrom.lookupResourceWithoutHash(url);
537 if (res === null || res.metadata === void 0) {
538 return;
539 }
540 await cache.put(req, res.response);
541 await metaTable.write(req.url, __spreadProps(__spreadValues({}, res.metadata), { used: false }));
542 }, Promise.resolve());
543 }
544 }
545 };
546 var LazyAssetGroup = class extends AssetGroup {
547 async initializeFully(updateFrom) {
548 if (updateFrom === void 0) {
549 return;
550 }
551 const cache = await this.cache;
552 await this.urls.reduce(async (previous, url) => {
553 await previous;
554 const req = this.adapter.newRequest(url);
555 const alreadyCached = await cache.match(req, this.config.cacheQueryOptions) !== void 0;
556 if (alreadyCached) {
557 return;
558 }
559 const updated = await this.maybeUpdate(updateFrom, req, cache);
560 if (this.config.updateMode === "prefetch" && !updated) {
561 const cacheStatus = await updateFrom.recentCacheStatus(url);
562 if (cacheStatus !== UpdateCacheStatus.CACHED) {
563 return;
564 }
565 await this.fetchAndCacheOnce(req, false);
566 }
567 }, Promise.resolve());
568 }
569 };
570
571 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/data.mjs
572 var LruList = class {
573 constructor(state) {
574 if (state === void 0) {
575 state = {
576 head: null,
577 tail: null,
578 map: {},
579 count: 0
580 };
581 }
582 this.state = state;
583 }
584 get size() {
585 return this.state.count;
586 }
587 pop() {
588 if (this.state.tail === null) {
589 return null;
590 }
591 const url = this.state.tail;
592 this.remove(url);
593 return url;
594 }
595 remove(url) {
596 const node = this.state.map[url];
597 if (node === void 0) {
598 return false;
599 }
600 if (this.state.head === url) {
601 if (node.next === null) {
602 this.state.head = null;
603 this.state.tail = null;
604 this.state.map = {};
605 this.state.count = 0;
606 return true;
607 }
608 const next = this.state.map[node.next];
609 next.previous = null;
610 this.state.head = next.url;
611 node.next = null;
612 delete this.state.map[url];
613 this.state.count--;
614 return true;
615 }
616 const previous = this.state.map[node.previous];
617 previous.next = node.next;
618 if (node.next !== null) {
619 this.state.map[node.next].previous = node.previous;
620 } else {
621 this.state.tail = node.previous;
622 }
623 node.next = null;
624 node.previous = null;
625 delete this.state.map[url];
626 this.state.count--;
627 return true;
628 }
629 accessed(url) {
630 if (this.state.head === url) {
631 return;
632 }
633 const node = this.state.map[url] || { url, next: null, previous: null };
634 if (this.state.map[url] !== void 0) {
635 this.remove(url);
636 }
637 if (this.state.head !== null) {
638 this.state.map[this.state.head].previous = url;
639 }
640 node.next = this.state.head;
641 this.state.head = url;
642 if (this.state.tail === null) {
643 this.state.tail = url;
644 }
645 this.state.map[url] = node;
646 this.state.count++;
647 }
648 };
649 var DataGroup = class {
650 constructor(scope2, adapter2, config, db, debugHandler, cacheNamePrefix) {
651 this.scope = scope2;
652 this.adapter = adapter2;
653 this.config = config;
654 this.db = db;
655 this.debugHandler = debugHandler;
656 this._lru = null;
657 this.patterns = config.patterns.map((pattern) => new RegExp(pattern));
658 this.cache = adapter2.caches.open(`${cacheNamePrefix}:${config.name}:cache`);
659 this.lruTable = this.db.open(`${cacheNamePrefix}:${config.name}:lru`, config.cacheQueryOptions);
660 this.ageTable = this.db.open(`${cacheNamePrefix}:${config.name}:age`, config.cacheQueryOptions);
661 }
662 async lru() {
663 if (this._lru === null) {
664 const table = await this.lruTable;
665 try {
666 this._lru = new LruList(await table.read("lru"));
667 } catch (e) {
668 this._lru = new LruList();
669 }
670 }
671 return this._lru;
672 }
673 async syncLru() {
674 if (this._lru === null) {
675 return;
676 }
677 const table = await this.lruTable;
678 try {
679 return table.write("lru", this._lru.state);
680 } catch (err) {
681 this.debugHandler.log(err, `DataGroup(${this.config.name}@${this.config.version}).syncLru()`);
682 }
683 }
684 async handleFetch(req, event) {
685 if (!this.patterns.some((pattern) => pattern.test(req.url))) {
686 return null;
687 }
688 const lru = await this.lru();
689 switch (req.method) {
690 case "OPTIONS":
691 return null;
692 case "GET":
693 case "HEAD":
694 switch (this.config.strategy) {
695 case "freshness":
696 return this.handleFetchWithFreshness(req, event, lru);
697 case "performance":
698 return this.handleFetchWithPerformance(req, event, lru);
699 default:
700 throw new Error(`Unknown strategy: ${this.config.strategy}`);
701 }
702 default:
703 const wasCached = lru.remove(req.url);
704 if (wasCached) {
705 await this.clearCacheForUrl(req.url);
706 }
707 await this.syncLru();
708 return this.safeFetch(req);
709 }
710 }
711 async handleFetchWithPerformance(req, event, lru) {
712 var _a;
713 const okToCacheOpaque = (_a = this.config.cacheOpaqueResponses) != null ? _a : false;
714 let res = null;
715 const fromCache = await this.loadFromCache(req, lru);
716 if (fromCache !== null) {
717 res = fromCache.res;
718 if (this.config.refreshAheadMs !== void 0 && fromCache.age >= this.config.refreshAheadMs) {
719 event.waitUntil(this.safeCacheResponse(req, this.safeFetch(req), lru, okToCacheOpaque));
720 }
721 }
722 if (res !== null) {
723 return res;
724 }
725 const [timeoutFetch, networkFetch] = this.networkFetchWithTimeout(req);
726 res = await timeoutFetch;
727 if (res === void 0) {
728 res = this.adapter.newResponse(null, { status: 504, statusText: "Gateway Timeout" });
729 event.waitUntil(this.safeCacheResponse(req, networkFetch, lru, okToCacheOpaque));
730 } else {
731 await this.safeCacheResponse(req, res, lru, okToCacheOpaque);
732 }
733 return res;
734 }
735 async handleFetchWithFreshness(req, event, lru) {
736 var _a;
737 const okToCacheOpaque = (_a = this.config.cacheOpaqueResponses) != null ? _a : true;
738 const [timeoutFetch, networkFetch] = this.networkFetchWithTimeout(req);
739 let res;
740 try {
741 res = await timeoutFetch;
742 } catch (e) {
743 res = void 0;
744 }
745 if (res === void 0) {
746 event.waitUntil(this.safeCacheResponse(req, networkFetch, lru, okToCacheOpaque));
747 const fromCache = await this.loadFromCache(req, lru);
748 res = fromCache !== null ? fromCache.res : null;
749 } else {
750 await this.safeCacheResponse(req, res, lru, okToCacheOpaque);
751 }
752 if (res !== null) {
753 return res;
754 }
755 return networkFetch;
756 }
757 networkFetchWithTimeout(req) {
758 if (this.config.timeoutMs !== void 0) {
759 const networkFetch = this.scope.fetch(req);
760 const safeNetworkFetch = (async () => {
761 try {
762 return await networkFetch;
763 } catch (e) {
764 return this.adapter.newResponse(null, {
765 status: 504,
766 statusText: "Gateway Timeout"
767 });
768 }
769 })();
770 const networkFetchUndefinedError = (async () => {
771 try {
772 return await networkFetch;
773 } catch (e) {
774 return void 0;
775 }
776 })();
777 const timeout = this.adapter.timeout(this.config.timeoutMs);
778 return [Promise.race([networkFetchUndefinedError, timeout]), safeNetworkFetch];
779 } else {
780 const networkFetch = this.safeFetch(req);
781 return [networkFetch, networkFetch];
782 }
783 }
784 async safeCacheResponse(req, resOrPromise, lru, okToCacheOpaque) {
785 try {
786 const res = await resOrPromise;
787 try {
788 await this.cacheResponse(req, res, lru, okToCacheOpaque);
789 } catch (err) {
790 this.debugHandler.log(err, `DataGroup(${this.config.name}@${this.config.version}).safeCacheResponse(${req.url}, status: ${res.status})`);
791 }
792 } catch (e) {
793 }
794 }
795 async loadFromCache(req, lru) {
796 const cache = await this.cache;
797 let res = await cache.match(req, this.config.cacheQueryOptions);
798 if (res !== void 0) {
799 try {
800 const ageTable = await this.ageTable;
801 const age = this.adapter.time - (await ageTable.read(req.url)).age;
802 if (age <= this.config.maxAge) {
803 lru.accessed(req.url);
804 return { res, age };
805 }
806 } catch (e) {
807 }
808 lru.remove(req.url);
809 await this.clearCacheForUrl(req.url);
810 await this.syncLru();
811 }
812 return null;
813 }
814 async cacheResponse(req, res, lru, okToCacheOpaque = false) {
815 if (!(res.ok || okToCacheOpaque && res.type === "opaque")) {
816 return;
817 }
818 if (lru.size >= this.config.maxSize) {
819 const evictedUrl = lru.pop();
820 if (evictedUrl !== null) {
821 await this.clearCacheForUrl(evictedUrl);
822 }
823 }
824 lru.accessed(req.url);
825 await (await this.cache).put(req, res.clone());
826 const ageTable = await this.ageTable;
827 await ageTable.write(req.url, { age: this.adapter.time });
828 await this.syncLru();
829 }
830 async cleanup() {
831 await Promise.all([
832 this.cache.then((cache) => this.adapter.caches.delete(cache.name)),
833 this.ageTable.then((table) => this.db.delete(table.name)),
834 this.lruTable.then((table) => this.db.delete(table.name))
835 ]);
836 }
837 async getCacheNames() {
838 const [cache, ageTable, lruTable] = await Promise.all([
839 this.cache,
840 this.ageTable,
841 this.lruTable
842 ]);
843 return [cache.name, ageTable.cacheName, lruTable.cacheName];
844 }
845 async clearCacheForUrl(url) {
846 const [cache, ageTable] = await Promise.all([this.cache, this.ageTable]);
847 await Promise.all([
848 cache.delete(this.adapter.newRequest(url, { method: "GET" }), this.config.cacheQueryOptions),
849 cache.delete(this.adapter.newRequest(url, { method: "HEAD" }), this.config.cacheQueryOptions),
850 ageTable.delete(url)
851 ]);
852 }
853 async safeFetch(req) {
854 try {
855 return this.scope.fetch(req);
856 } catch (e) {
857 return this.adapter.newResponse(null, {
858 status: 504,
859 statusText: "Gateway Timeout"
860 });
861 }
862 }
863 };
864
865 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/app-version.mjs
866 var BACKWARDS_COMPATIBILITY_NAVIGATION_URLS = [
867 { positive: true, regex: "^/.*$" },
868 { positive: false, regex: "^/.*\\.[^/]*$" },
869 { positive: false, regex: "^/.*__" }
870 ];
871 var AppVersion = class {
872 constructor(scope2, adapter2, database, idle, debugHandler, manifest, manifestHash) {
873 this.scope = scope2;
874 this.adapter = adapter2;
875 this.database = database;
876 this.debugHandler = debugHandler;
877 this.manifest = manifest;
878 this.manifestHash = manifestHash;
879 this.hashTable = /* @__PURE__ */ new Map();
880 this.indexUrl = this.adapter.normalizeUrl(this.manifest.index);
881 this._okay = true;
882 Object.keys(manifest.hashTable).forEach((url) => {
883 this.hashTable.set(adapter2.normalizeUrl(url), manifest.hashTable[url]);
884 });
885 const assetCacheNamePrefix = `${manifestHash}:assets`;
886 this.assetGroups = (manifest.assetGroups || []).map((config) => {
887 switch (config.installMode) {
888 case "prefetch":
889 return new PrefetchAssetGroup(scope2, adapter2, idle, config, this.hashTable, database, assetCacheNamePrefix);
890 case "lazy":
891 return new LazyAssetGroup(scope2, adapter2, idle, config, this.hashTable, database, assetCacheNamePrefix);
892 }
893 });
894 this.dataGroups = (manifest.dataGroups || []).map((config) => new DataGroup(scope2, adapter2, config, database, debugHandler, `${config.version}:data`));
895 manifest.navigationUrls = manifest.navigationUrls || BACKWARDS_COMPATIBILITY_NAVIGATION_URLS;
896 const includeUrls = manifest.navigationUrls.filter((spec) => spec.positive);
897 const excludeUrls = manifest.navigationUrls.filter((spec) => !spec.positive);
898 this.navigationUrls = {
899 include: includeUrls.map((spec) => new RegExp(spec.regex)),
900 exclude: excludeUrls.map((spec) => new RegExp(spec.regex))
901 };
902 }
903 get okay() {
904 return this._okay;
905 }
906 async initializeFully(updateFrom) {
907 try {
908 await this.assetGroups.reduce(async (previous, group) => {
909 await previous;
910 return group.initializeFully(updateFrom);
911 }, Promise.resolve());
912 } catch (err) {
913 this._okay = false;
914 throw err;
915 }
916 }
917 async handleFetch(req, event) {
918 const asset = await this.assetGroups.reduce(async (potentialResponse, group) => {
919 const resp = await potentialResponse;
920 if (resp !== null) {
921 return resp;
922 }
923 return group.handleFetch(req, event);
924 }, Promise.resolve(null));
925 if (asset !== null) {
926 return asset;
927 }
928 const data = await this.dataGroups.reduce(async (potentialResponse, group) => {
929 const resp = await potentialResponse;
930 if (resp !== null) {
931 return resp;
932 }
933 return group.handleFetch(req, event);
934 }, Promise.resolve(null));
935 if (data !== null) {
936 return data;
937 }
938 if (this.adapter.normalizeUrl(req.url) !== this.indexUrl && this.isNavigationRequest(req)) {
939 if (this.manifest.navigationRequestStrategy === "freshness") {
940 try {
941 return await this.scope.fetch(req);
942 } catch (e) {
943 }
944 }
945 return this.handleFetch(this.adapter.newRequest(this.indexUrl), event);
946 }
947 return null;
948 }
949 isNavigationRequest(req) {
950 if (req.mode !== "navigate") {
951 return false;
952 }
953 if (!this.acceptsTextHtml(req)) {
954 return false;
955 }
956 const urlPrefix = this.scope.registration.scope.replace(/\/$/, "");
957 const url = req.url.startsWith(urlPrefix) ? req.url.slice(urlPrefix.length) : req.url;
958 const urlWithoutQueryOrHash = url.replace(/[?#].*$/, "");
959 return this.navigationUrls.include.some((regex) => regex.test(urlWithoutQueryOrHash)) && !this.navigationUrls.exclude.some((regex) => regex.test(urlWithoutQueryOrHash));
960 }
961 async lookupResourceWithHash(url, hash) {
962 if (!this.hashTable.has(url)) {
963 return null;
964 }
965 if (this.hashTable.get(url) !== hash) {
966 return null;
967 }
968 const cacheState = await this.lookupResourceWithoutHash(url);
969 return cacheState && cacheState.response;
970 }
971 lookupResourceWithoutHash(url) {
972 return this.assetGroups.reduce(async (potentialResponse, group) => {
973 const resp = await potentialResponse;
974 if (resp !== null) {
975 return resp;
976 }
977 return group.fetchFromCacheOnly(url);
978 }, Promise.resolve(null));
979 }
980 previouslyCachedResources() {
981 return this.assetGroups.reduce(async (resources, group) => (await resources).concat(await group.unhashedResources()), Promise.resolve([]));
982 }
983 async recentCacheStatus(url) {
984 return this.assetGroups.reduce(async (current, group) => {
985 const status = await current;
986 if (status === UpdateCacheStatus.CACHED) {
987 return status;
988 }
989 const groupStatus = await group.cacheStatus(url);
990 if (groupStatus === UpdateCacheStatus.NOT_CACHED) {
991 return status;
992 }
993 return groupStatus;
994 }, Promise.resolve(UpdateCacheStatus.NOT_CACHED));
995 }
996 async getCacheNames() {
997 const allGroupCacheNames = await Promise.all([
998 ...this.assetGroups.map((group) => group.getCacheNames()),
999 ...this.dataGroups.map((group) => group.getCacheNames())
1000 ]);
1001 return [].concat(...allGroupCacheNames);
1002 }
1003 get appData() {
1004 return this.manifest.appData || null;
1005 }
1006 acceptsTextHtml(req) {
1007 const accept = req.headers.get("Accept");
1008 if (accept === null) {
1009 return false;
1010 }
1011 const values = accept.split(",");
1012 return values.some((value) => value.trim().toLowerCase() === "text/html");
1013 }
1014 };
1015
1016 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/debug.mjs
1017 var SW_VERSION = "14.1.2";
1018 var DEBUG_LOG_BUFFER_SIZE = 100;
1019 var DebugHandler = class {
1020 constructor(driver, adapter2) {
1021 this.driver = driver;
1022 this.adapter = adapter2;
1023 this.debugLogA = [];
1024 this.debugLogB = [];
1025 }
1026 async handleFetch(req) {
1027 const [state, versions, idle] = await Promise.all([
1028 this.driver.debugState(),
1029 this.driver.debugVersions(),
1030 this.driver.debugIdleState()
1031 ]);
1032 const msgState = `NGSW Debug Info:
1033
1034Driver version: ${SW_VERSION}
1035Driver state: ${state.state} (${state.why})
1036Latest manifest hash: ${state.latestHash || "none"}
1037Last update check: ${this.since(state.lastUpdateCheck)}`;
1038 const msgVersions = versions.map((version) => `=== Version ${version.hash} ===
1039
1040Clients: ${version.clients.join(", ")}`).join("\n\n");
1041 const msgIdle = `=== Idle Task Queue ===
1042Last update tick: ${this.since(idle.lastTrigger)}
1043Last update run: ${this.since(idle.lastRun)}
1044Task queue:
1045${idle.queue.map((v) => " * " + v).join("\n")}
1046
1047Debug log:
1048${this.formatDebugLog(this.debugLogB)}
1049${this.formatDebugLog(this.debugLogA)}
1050`;
1051 return this.adapter.newResponse(`${msgState}
1052
1053${msgVersions}
1054
1055${msgIdle}`, { headers: this.adapter.newHeaders({ "Content-Type": "text/plain" }) });
1056 }
1057 since(time) {
1058 if (time === null) {
1059 return "never";
1060 }
1061 let age = this.adapter.time - time;
1062 const days = Math.floor(age / 864e5);
1063 age = age % 864e5;
1064 const hours = Math.floor(age / 36e5);
1065 age = age % 36e5;
1066 const minutes = Math.floor(age / 6e4);
1067 age = age % 6e4;
1068 const seconds = Math.floor(age / 1e3);
1069 const millis = age % 1e3;
1070 return (days > 0 ? `${days}d` : "") + (hours > 0 ? `${hours}h` : "") + (minutes > 0 ? `${minutes}m` : "") + (seconds > 0 ? `${seconds}s` : "") + (millis > 0 ? `${millis}u` : "");
1071 }
1072 log(value, context = "") {
1073 if (this.debugLogA.length === DEBUG_LOG_BUFFER_SIZE) {
1074 this.debugLogB = this.debugLogA;
1075 this.debugLogA = [];
1076 }
1077 if (typeof value !== "string") {
1078 value = this.errorToString(value);
1079 }
1080 this.debugLogA.push({ value, time: this.adapter.time, context });
1081 }
1082 errorToString(err) {
1083 return `${err.name}(${err.message}, ${err.stack})`;
1084 }
1085 formatDebugLog(log) {
1086 return log.map((entry) => `[${this.since(entry.time)}] ${entry.value} ${entry.context}`).join("\n");
1087 }
1088 };
1089
1090 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/idle.mjs
1091 var IdleScheduler = class {
1092 constructor(adapter2, delay, maxDelay, debug) {
1093 this.adapter = adapter2;
1094 this.delay = delay;
1095 this.maxDelay = maxDelay;
1096 this.debug = debug;
1097 this.queue = [];
1098 this.scheduled = null;
1099 this.empty = Promise.resolve();
1100 this.emptyResolve = null;
1101 this.lastTrigger = null;
1102 this.lastRun = null;
1103 this.oldestScheduledAt = null;
1104 }
1105 async trigger() {
1106 var _a;
1107 this.lastTrigger = this.adapter.time;
1108 if (this.queue.length === 0) {
1109 return;
1110 }
1111 if (this.scheduled !== null) {
1112 this.scheduled.cancel = true;
1113 }
1114 const scheduled = {
1115 cancel: false
1116 };
1117 this.scheduled = scheduled;
1118 const now = this.adapter.time;
1119 const maxDelay = Math.max(0, ((_a = this.oldestScheduledAt) != null ? _a : now) + this.maxDelay - now);
1120 const delay = Math.min(maxDelay, this.delay);
1121 await this.adapter.timeout(delay);
1122 if (scheduled.cancel) {
1123 return;
1124 }
1125 this.scheduled = null;
1126 await this.execute();
1127 }
1128 async execute() {
1129 this.lastRun = this.adapter.time;
1130 while (this.queue.length > 0) {
1131 const queue = this.queue;
1132 this.queue = [];
1133 await queue.reduce(async (previous, task) => {
1134 await previous;
1135 try {
1136 await task.run();
1137 } catch (err) {
1138 this.debug.log(err, `while running idle task ${task.desc}`);
1139 }
1140 }, Promise.resolve());
1141 }
1142 if (this.emptyResolve !== null) {
1143 this.emptyResolve();
1144 this.emptyResolve = null;
1145 }
1146 this.empty = Promise.resolve();
1147 this.oldestScheduledAt = null;
1148 }
1149 schedule(desc, run) {
1150 this.queue.push({ desc, run });
1151 if (this.emptyResolve === null) {
1152 this.empty = new Promise((resolve) => {
1153 this.emptyResolve = resolve;
1154 });
1155 }
1156 if (this.oldestScheduledAt === null) {
1157 this.oldestScheduledAt = this.adapter.time;
1158 }
1159 }
1160 get size() {
1161 return this.queue.length;
1162 }
1163 get taskDescriptions() {
1164 return this.queue.map((task) => task.desc);
1165 }
1166 };
1167
1168 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/manifest.mjs
1169 function hashManifest(manifest) {
1170 return sha1(JSON.stringify(manifest));
1171 }
1172
1173 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/msg.mjs
1174 function isMsgCheckForUpdates(msg) {
1175 return msg.action === "CHECK_FOR_UPDATES";
1176 }
1177 function isMsgActivateUpdate(msg) {
1178 return msg.action === "ACTIVATE_UPDATE";
1179 }
1180
1181 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/src/driver.mjs
1182 var IDLE_DELAY = 5e3;
1183 var MAX_IDLE_DELAY = 3e4;
1184 var SUPPORTED_CONFIG_VERSION = 1;
1185 var NOTIFICATION_OPTION_NAMES = [
1186 "actions",
1187 "badge",
1188 "body",
1189 "data",
1190 "dir",
1191 "icon",
1192 "image",
1193 "lang",
1194 "renotify",
1195 "requireInteraction",
1196 "silent",
1197 "tag",
1198 "timestamp",
1199 "title",
1200 "vibrate"
1201 ];
1202 var DriverReadyState;
1203 (function(DriverReadyState2) {
1204 DriverReadyState2[DriverReadyState2["NORMAL"] = 0] = "NORMAL";
1205 DriverReadyState2[DriverReadyState2["EXISTING_CLIENTS_ONLY"] = 1] = "EXISTING_CLIENTS_ONLY";
1206 DriverReadyState2[DriverReadyState2["SAFE_MODE"] = 2] = "SAFE_MODE";
1207 })(DriverReadyState || (DriverReadyState = {}));
1208 var Driver = class {
1209 constructor(scope2, adapter2, db) {
1210 this.scope = scope2;
1211 this.adapter = adapter2;
1212 this.db = db;
1213 this.state = DriverReadyState.NORMAL;
1214 this.stateMessage = "(nominal)";
1215 this.initialized = null;
1216 this.clientVersionMap = /* @__PURE__ */ new Map();
1217 this.versions = /* @__PURE__ */ new Map();
1218 this.latestHash = null;
1219 this.lastUpdateCheck = null;
1220 this.scheduledNavUpdateCheck = false;
1221 this.loggedInvalidOnlyIfCachedRequest = false;
1222 this.ngswStatePath = this.adapter.parseUrl("ngsw/state", this.scope.registration.scope).path;
1223 this.controlTable = this.db.open("control");
1224 this.scope.addEventListener("install", (event) => {
1225 event.waitUntil(this.scope.skipWaiting());
1226 });
1227 this.scope.addEventListener("activate", (event) => {
1228 event.waitUntil((async () => {
1229 await this.scope.clients.claim();
1230 this.idle.schedule("activate: cleanup-old-sw-caches", async () => {
1231 try {
1232 await this.cleanupOldSwCaches();
1233 } catch (err) {
1234 this.debugger.log(err, "cleanupOldSwCaches @ activate: cleanup-old-sw-caches");
1235 }
1236 });
1237 })());
1238 if (this.scope.registration.active !== null) {
1239 this.scope.registration.active.postMessage({ action: "INITIALIZE" });
1240 }
1241 });
1242 this.scope.addEventListener("fetch", (event) => this.onFetch(event));
1243 this.scope.addEventListener("message", (event) => this.onMessage(event));
1244 this.scope.addEventListener("push", (event) => this.onPush(event));
1245 this.scope.addEventListener("notificationclick", (event) => this.onClick(event));
1246 this.debugger = new DebugHandler(this, this.adapter);
1247 this.idle = new IdleScheduler(this.adapter, IDLE_DELAY, MAX_IDLE_DELAY, this.debugger);
1248 }
1249 onFetch(event) {
1250 const req = event.request;
1251 const scopeUrl = this.scope.registration.scope;
1252 const requestUrlObj = this.adapter.parseUrl(req.url, scopeUrl);
1253 if (req.headers.has("ngsw-bypass") || /[?&]ngsw-bypass(?:[=&]|$)/i.test(requestUrlObj.search)) {
1254 return;
1255 }
1256 if (requestUrlObj.path === this.ngswStatePath) {
1257 event.respondWith(this.debugger.handleFetch(req));
1258 return;
1259 }
1260 if (this.state === DriverReadyState.SAFE_MODE) {
1261 event.waitUntil(this.idle.trigger());
1262 return;
1263 }
1264 if (requestUrlObj.origin.startsWith("http:") && scopeUrl.startsWith("https:")) {
1265 this.debugger.log(`Ignoring passive mixed content request: Driver.fetch(${req.url})`);
1266 return;
1267 }
1268 if (req.cache === "only-if-cached" && req.mode !== "same-origin") {
1269 if (!this.loggedInvalidOnlyIfCachedRequest) {
1270 this.loggedInvalidOnlyIfCachedRequest = true;
1271 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})`);
1272 }
1273 return;
1274 }
1275 event.respondWith(this.handleFetch(event));
1276 }
1277 onMessage(event) {
1278 if (this.state === DriverReadyState.SAFE_MODE) {
1279 return;
1280 }
1281 const data = event.data;
1282 if (!data || !data.action) {
1283 return;
1284 }
1285 event.waitUntil((async () => {
1286 if (data.action === "INITIALIZE") {
1287 return this.ensureInitialized(event);
1288 }
1289 if (!this.adapter.isClient(event.source)) {
1290 return;
1291 }
1292 await this.ensureInitialized(event);
1293 await this.handleMessage(data, event.source);
1294 })());
1295 }
1296 onPush(msg) {
1297 if (!msg.data) {
1298 return;
1299 }
1300 msg.waitUntil(this.handlePush(msg.data.json()));
1301 }
1302 onClick(event) {
1303 event.waitUntil(this.handleClick(event.notification, event.action));
1304 }
1305 async ensureInitialized(event) {
1306 if (this.initialized !== null) {
1307 return this.initialized;
1308 }
1309 try {
1310 this.initialized = this.initialize();
1311 await this.initialized;
1312 } catch (error) {
1313 this.state = DriverReadyState.SAFE_MODE;
1314 this.stateMessage = `Initialization failed due to error: ${errorToString(error)}`;
1315 throw error;
1316 } finally {
1317 event.waitUntil(this.idle.trigger());
1318 }
1319 }
1320 async handleMessage(msg, from) {
1321 if (isMsgCheckForUpdates(msg)) {
1322 const action = this.checkForUpdate();
1323 await this.completeOperation(from, action, msg.nonce);
1324 } else if (isMsgActivateUpdate(msg)) {
1325 const action = this.updateClient(from);
1326 await this.completeOperation(from, action, msg.nonce);
1327 }
1328 }
1329 async handlePush(data) {
1330 await this.broadcast({
1331 type: "PUSH",
1332 data
1333 });
1334 if (!data.notification || !data.notification.title) {
1335 return;
1336 }
1337 const desc = data.notification;
1338 let options = {};
1339 NOTIFICATION_OPTION_NAMES.filter((name) => desc.hasOwnProperty(name)).forEach((name) => options[name] = desc[name]);
1340 await this.scope.registration.showNotification(desc["title"], options);
1341 }
1342 async handleClick(notification, action) {
1343 var _a, _b, _c;
1344 notification.close();
1345 const options = {};
1346 NOTIFICATION_OPTION_NAMES.filter((name) => name in notification).forEach((name) => options[name] = notification[name]);
1347 const notificationAction = action === "" || action === void 0 ? "default" : action;
1348 const onActionClick = (_b = (_a = notification == null ? void 0 : notification.data) == null ? void 0 : _a.onActionClick) == null ? void 0 : _b[notificationAction];
1349 const urlToOpen = new URL((_c = onActionClick == null ? void 0 : onActionClick.url) != null ? _c : "", this.scope.registration.scope).href;
1350 switch (onActionClick == null ? void 0 : onActionClick.operation) {
1351 case "openWindow":
1352 await this.scope.clients.openWindow(urlToOpen);
1353 break;
1354 case "focusLastFocusedOrOpen": {
1355 let matchingClient = await this.getLastFocusedMatchingClient(this.scope);
1356 if (matchingClient) {
1357 await (matchingClient == null ? void 0 : matchingClient.focus());
1358 } else {
1359 await this.scope.clients.openWindow(urlToOpen);
1360 }
1361 break;
1362 }
1363 case "navigateLastFocusedOrOpen": {
1364 let matchingClient = await this.getLastFocusedMatchingClient(this.scope);
1365 if (matchingClient) {
1366 matchingClient = await matchingClient.navigate(urlToOpen);
1367 await (matchingClient == null ? void 0 : matchingClient.focus());
1368 } else {
1369 await this.scope.clients.openWindow(urlToOpen);
1370 }
1371 break;
1372 }
1373 default:
1374 break;
1375 }
1376 await this.broadcast({
1377 type: "NOTIFICATION_CLICK",
1378 data: { action, notification: options }
1379 });
1380 }
1381 async getLastFocusedMatchingClient(scope2) {
1382 const windowClients = await scope2.clients.matchAll({ type: "window" });
1383 return windowClients[0];
1384 }
1385 async completeOperation(client, promise, nonce) {
1386 const response = { type: "OPERATION_COMPLETED", nonce };
1387 try {
1388 client.postMessage(__spreadProps(__spreadValues({}, response), {
1389 result: await promise
1390 }));
1391 } catch (e) {
1392 client.postMessage(__spreadProps(__spreadValues({}, response), {
1393 error: e.toString()
1394 }));
1395 }
1396 }
1397 async updateClient(client) {
1398 const existing = this.clientVersionMap.get(client.id);
1399 if (existing === this.latestHash) {
1400 return false;
1401 }
1402 let previous = void 0;
1403 if (existing !== void 0) {
1404 const existingVersion = this.versions.get(existing);
1405 previous = this.mergeHashWithAppData(existingVersion.manifest, existing);
1406 }
1407 this.clientVersionMap.set(client.id, this.latestHash);
1408 await this.sync();
1409 const current = this.versions.get(this.latestHash);
1410 const notice = {
1411 type: "UPDATE_ACTIVATED",
1412 previous,
1413 current: this.mergeHashWithAppData(current.manifest, this.latestHash)
1414 };
1415 client.postMessage(notice);
1416 return true;
1417 }
1418 async handleFetch(event) {
1419 try {
1420 await this.ensureInitialized(event);
1421 } catch (e) {
1422 return this.safeFetch(event.request);
1423 }
1424 if (event.request.mode === "navigate" && !this.scheduledNavUpdateCheck) {
1425 this.scheduledNavUpdateCheck = true;
1426 this.idle.schedule("check-updates-on-navigation", async () => {
1427 this.scheduledNavUpdateCheck = false;
1428 await this.checkForUpdate();
1429 });
1430 }
1431 const appVersion = await this.assignVersion(event);
1432 let res = null;
1433 try {
1434 if (appVersion !== null) {
1435 try {
1436 res = await appVersion.handleFetch(event.request, event);
1437 } catch (err) {
1438 if (err.isUnrecoverableState) {
1439 await this.notifyClientsAboutUnrecoverableState(appVersion, err.message);
1440 }
1441 if (err.isCritical) {
1442 this.debugger.log(err, `Driver.handleFetch(version: ${appVersion.manifestHash})`);
1443 await this.versionFailed(appVersion, err);
1444 return this.safeFetch(event.request);
1445 }
1446 throw err;
1447 }
1448 }
1449 if (res === null) {
1450 return this.safeFetch(event.request);
1451 }
1452 return res;
1453 } finally {
1454 event.waitUntil(this.idle.trigger());
1455 }
1456 }
1457 async initialize() {
1458 const table = await this.controlTable;
1459 let manifests, assignments, latest;
1460 try {
1461 [manifests, assignments, latest] = await Promise.all([
1462 table.read("manifests"),
1463 table.read("assignments"),
1464 table.read("latest")
1465 ]);
1466 if (!this.versions.has(latest.latest) && !manifests.hasOwnProperty(latest.latest)) {
1467 this.debugger.log(`Missing manifest for latest version hash ${latest.latest}`, "initialize: read from DB");
1468 throw new Error(`Missing manifest for latest hash ${latest.latest}`);
1469 }
1470 this.idle.schedule("init post-load (update)", async () => {
1471 await this.checkForUpdate();
1472 });
1473 } catch (_) {
1474 const manifest = await this.fetchLatestManifest();
1475 const hash = hashManifest(manifest);
1476 manifests = { [hash]: manifest };
1477 assignments = {};
1478 latest = { latest: hash };
1479 await Promise.all([
1480 table.write("manifests", manifests),
1481 table.write("assignments", assignments),
1482 table.write("latest", latest)
1483 ]);
1484 }
1485 this.idle.schedule("init post-load (cleanup)", async () => {
1486 await this.cleanupCaches();
1487 });
1488 Object.keys(manifests).forEach((hash) => {
1489 const manifest = manifests[hash];
1490 if (!this.versions.has(hash)) {
1491 this.versions.set(hash, new AppVersion(this.scope, this.adapter, this.db, this.idle, this.debugger, manifest, hash));
1492 }
1493 });
1494 Object.keys(assignments).forEach((clientId) => {
1495 const hash = assignments[clientId];
1496 if (this.versions.has(hash)) {
1497 this.clientVersionMap.set(clientId, hash);
1498 } else {
1499 this.clientVersionMap.set(clientId, latest.latest);
1500 this.debugger.log(`Unknown version ${hash} mapped for client ${clientId}, using latest instead`, `initialize: map assignments`);
1501 }
1502 });
1503 this.latestHash = latest.latest;
1504 if (!this.versions.has(latest.latest)) {
1505 throw new Error(`Invariant violated (initialize): latest hash ${latest.latest} has no known manifest`);
1506 }
1507 await Promise.all(Object.keys(manifests).map(async (hash) => {
1508 try {
1509 await this.scheduleInitialization(this.versions.get(hash));
1510 } catch (err) {
1511 this.debugger.log(err, `initialize: schedule init of ${hash}`);
1512 return false;
1513 }
1514 }));
1515 }
1516 lookupVersionByHash(hash, debugName = "lookupVersionByHash") {
1517 if (!this.versions.has(hash)) {
1518 throw new Error(`Invariant violated (${debugName}): want AppVersion for ${hash} but not loaded`);
1519 }
1520 return this.versions.get(hash);
1521 }
1522 async assignVersion(event) {
1523 const clientId = event.resultingClientId || event.clientId;
1524 if (clientId) {
1525 if (this.clientVersionMap.has(clientId)) {
1526 const hash = this.clientVersionMap.get(clientId);
1527 let appVersion = this.lookupVersionByHash(hash, "assignVersion");
1528 if (this.state === DriverReadyState.NORMAL && hash !== this.latestHash && appVersion.isNavigationRequest(event.request)) {
1529 if (this.latestHash === null) {
1530 throw new Error(`Invariant violated (assignVersion): latestHash was null`);
1531 }
1532 const client = await this.scope.clients.get(clientId);
1533 if (client) {
1534 await this.updateClient(client);
1535 }
1536 appVersion = this.lookupVersionByHash(this.latestHash, "assignVersion");
1537 }
1538 return appVersion;
1539 } else {
1540 if (this.state !== DriverReadyState.NORMAL) {
1541 return null;
1542 }
1543 if (this.latestHash === null) {
1544 throw new Error(`Invariant violated (assignVersion): latestHash was null`);
1545 }
1546 this.clientVersionMap.set(clientId, this.latestHash);
1547 await this.sync();
1548 return this.lookupVersionByHash(this.latestHash, "assignVersion");
1549 }
1550 } else {
1551 if (this.state !== DriverReadyState.NORMAL) {
1552 return null;
1553 }
1554 if (this.latestHash === null) {
1555 throw new Error(`Invariant violated (assignVersion): latestHash was null`);
1556 }
1557 return this.lookupVersionByHash(this.latestHash, "assignVersion");
1558 }
1559 }
1560 async fetchLatestManifest(ignoreOfflineError = false) {
1561 const res = await this.safeFetch(this.adapter.newRequest("ngsw.json?ngsw-cache-bust=" + Math.random()));
1562 if (!res.ok) {
1563 if (res.status === 404) {
1564 await this.deleteAllCaches();
1565 await this.scope.registration.unregister();
1566 } else if ((res.status === 503 || res.status === 504) && ignoreOfflineError) {
1567 return null;
1568 }
1569 throw new Error(`Manifest fetch failed! (status: ${res.status})`);
1570 }
1571 this.lastUpdateCheck = this.adapter.time;
1572 return res.json();
1573 }
1574 async deleteAllCaches() {
1575 const cacheNames = await this.adapter.caches.keys();
1576 await Promise.all(cacheNames.map((name) => this.adapter.caches.delete(name)));
1577 }
1578 async scheduleInitialization(appVersion) {
1579 const initialize = async () => {
1580 try {
1581 await appVersion.initializeFully();
1582 } catch (err) {
1583 this.debugger.log(err, `initializeFully for ${appVersion.manifestHash}`);
1584 await this.versionFailed(appVersion, err);
1585 }
1586 };
1587 if (this.scope.registration.scope.indexOf("://localhost") > -1) {
1588 return initialize();
1589 }
1590 this.idle.schedule(`initialization(${appVersion.manifestHash})`, initialize);
1591 }
1592 async versionFailed(appVersion, err) {
1593 const broken = Array.from(this.versions.entries()).find(([hash, version]) => version === appVersion);
1594 if (broken === void 0) {
1595 return;
1596 }
1597 const brokenHash = broken[0];
1598 if (this.latestHash === brokenHash) {
1599 this.state = DriverReadyState.EXISTING_CLIENTS_ONLY;
1600 this.stateMessage = `Degraded due to: ${errorToString(err)}`;
1601 }
1602 }
1603 async setupUpdate(manifest, hash) {
1604 try {
1605 const newVersion = new AppVersion(this.scope, this.adapter, this.db, this.idle, this.debugger, manifest, hash);
1606 if (manifest.configVersion !== SUPPORTED_CONFIG_VERSION) {
1607 await this.deleteAllCaches();
1608 await this.scope.registration.unregister();
1609 throw new Error(`Invalid config version: expected ${SUPPORTED_CONFIG_VERSION}, got ${manifest.configVersion}.`);
1610 }
1611 await newVersion.initializeFully(this);
1612 this.versions.set(hash, newVersion);
1613 this.latestHash = hash;
1614 if (this.state === DriverReadyState.EXISTING_CLIENTS_ONLY) {
1615 this.state = DriverReadyState.NORMAL;
1616 this.stateMessage = "(nominal)";
1617 }
1618 await this.sync();
1619 await this.notifyClientsAboutVersionReady(manifest, hash);
1620 } catch (e) {
1621 await this.notifyClientsAboutVersionInstallationFailed(manifest, hash, e);
1622 throw e;
1623 }
1624 }
1625 async checkForUpdate() {
1626 let hash = "(unknown)";
1627 try {
1628 const manifest = await this.fetchLatestManifest(true);
1629 if (manifest === null) {
1630 this.debugger.log("Check for update aborted. (Client or server offline.)");
1631 return false;
1632 }
1633 hash = hashManifest(manifest);
1634 if (this.versions.has(hash)) {
1635 await this.notifyClientsAboutNoNewVersionDetected(manifest, hash);
1636 return false;
1637 }
1638 await this.notifyClientsAboutVersionDetected(manifest, hash);
1639 await this.setupUpdate(manifest, hash);
1640 return true;
1641 } catch (err) {
1642 this.debugger.log(err, `Error occurred while updating to manifest ${hash}`);
1643 this.state = DriverReadyState.EXISTING_CLIENTS_ONLY;
1644 this.stateMessage = `Degraded due to failed initialization: ${errorToString(err)}`;
1645 return false;
1646 }
1647 }
1648 async sync() {
1649 const table = await this.controlTable;
1650 const manifests = {};
1651 this.versions.forEach((version, hash) => {
1652 manifests[hash] = version.manifest;
1653 });
1654 const assignments = {};
1655 this.clientVersionMap.forEach((hash, clientId) => {
1656 assignments[clientId] = hash;
1657 });
1658 const latest = {
1659 latest: this.latestHash
1660 };
1661 await Promise.all([
1662 table.write("manifests", manifests),
1663 table.write("assignments", assignments),
1664 table.write("latest", latest)
1665 ]);
1666 }
1667 async cleanupCaches() {
1668 try {
1669 const activeClients = new Set((await this.scope.clients.matchAll()).map((client) => client.id));
1670 const knownClients = Array.from(this.clientVersionMap.keys());
1671 const obsoleteClients = knownClients.filter((id) => !activeClients.has(id));
1672 obsoleteClients.forEach((id) => this.clientVersionMap.delete(id));
1673 const usedVersions = new Set(this.clientVersionMap.values());
1674 const obsoleteVersions = Array.from(this.versions.keys()).filter((version) => !usedVersions.has(version) && version !== this.latestHash);
1675 obsoleteVersions.forEach((version) => this.versions.delete(version));
1676 await this.sync();
1677 const allCaches = await this.adapter.caches.keys();
1678 const usedCaches = new Set(await this.getCacheNames());
1679 const cachesToDelete = allCaches.filter((name) => !usedCaches.has(name));
1680 await Promise.all(cachesToDelete.map((name) => this.adapter.caches.delete(name)));
1681 } catch (err) {
1682 this.debugger.log(err, "cleanupCaches");
1683 }
1684 }
1685 async cleanupOldSwCaches() {
1686 const caches = this.adapter.caches.original;
1687 const cacheNames = await caches.keys();
1688 const oldSwCacheNames = cacheNames.filter((name) => /^ngsw:(?!\/)/.test(name));
1689 await Promise.all(oldSwCacheNames.map((name) => caches.delete(name)));
1690 }
1691 lookupResourceWithHash(url, hash) {
1692 return Array.from(this.versions.values()).reduce(async (prev, version) => {
1693 if (await prev !== null) {
1694 return prev;
1695 }
1696 return version.lookupResourceWithHash(url, hash);
1697 }, Promise.resolve(null));
1698 }
1699 async lookupResourceWithoutHash(url) {
1700 await this.initialized;
1701 const version = this.versions.get(this.latestHash);
1702 return version ? version.lookupResourceWithoutHash(url) : null;
1703 }
1704 async previouslyCachedResources() {
1705 await this.initialized;
1706 const version = this.versions.get(this.latestHash);
1707 return version ? version.previouslyCachedResources() : [];
1708 }
1709 async recentCacheStatus(url) {
1710 const version = this.versions.get(this.latestHash);
1711 return version ? version.recentCacheStatus(url) : UpdateCacheStatus.NOT_CACHED;
1712 }
1713 mergeHashWithAppData(manifest, hash) {
1714 return {
1715 hash,
1716 appData: manifest.appData
1717 };
1718 }
1719 async notifyClientsAboutUnrecoverableState(appVersion, reason) {
1720 const broken = Array.from(this.versions.entries()).find(([hash, version]) => version === appVersion);
1721 if (broken === void 0) {
1722 return;
1723 }
1724 const brokenHash = broken[0];
1725 const affectedClients = Array.from(this.clientVersionMap.entries()).filter(([clientId, hash]) => hash === brokenHash).map(([clientId]) => clientId);
1726 await Promise.all(affectedClients.map(async (clientId) => {
1727 const client = await this.scope.clients.get(clientId);
1728 if (client) {
1729 client.postMessage({ type: "UNRECOVERABLE_STATE", reason });
1730 }
1731 }));
1732 }
1733 async notifyClientsAboutVersionInstallationFailed(manifest, hash, error) {
1734 await this.initialized;
1735 const clients = await this.scope.clients.matchAll();
1736 await Promise.all(clients.map(async (client) => {
1737 client.postMessage({
1738 type: "VERSION_INSTALLATION_FAILED",
1739 version: this.mergeHashWithAppData(manifest, hash),
1740 error: errorToString(error)
1741 });
1742 }));
1743 }
1744 async notifyClientsAboutNoNewVersionDetected(manifest, hash) {
1745 await this.initialized;
1746 const clients = await this.scope.clients.matchAll();
1747 await Promise.all(clients.map(async (client) => {
1748 client.postMessage({ type: "NO_NEW_VERSION_DETECTED", version: this.mergeHashWithAppData(manifest, hash) });
1749 }));
1750 }
1751 async notifyClientsAboutVersionDetected(manifest, hash) {
1752 await this.initialized;
1753 const clients = await this.scope.clients.matchAll();
1754 await Promise.all(clients.map(async (client) => {
1755 const version = this.clientVersionMap.get(client.id);
1756 if (version === void 0) {
1757 return;
1758 }
1759 client.postMessage({ type: "VERSION_DETECTED", version: this.mergeHashWithAppData(manifest, hash) });
1760 }));
1761 }
1762 async notifyClientsAboutVersionReady(manifest, hash) {
1763 await this.initialized;
1764 const clients = await this.scope.clients.matchAll();
1765 await Promise.all(clients.map(async (client) => {
1766 const version = this.clientVersionMap.get(client.id);
1767 if (version === void 0) {
1768 return;
1769 }
1770 if (version === this.latestHash) {
1771 return;
1772 }
1773 const current = this.versions.get(version);
1774 const notice = {
1775 type: "VERSION_READY",
1776 currentVersion: this.mergeHashWithAppData(current.manifest, version),
1777 latestVersion: this.mergeHashWithAppData(manifest, hash)
1778 };
1779 client.postMessage(notice);
1780 }));
1781 }
1782 async broadcast(msg) {
1783 const clients = await this.scope.clients.matchAll();
1784 clients.forEach((client) => {
1785 client.postMessage(msg);
1786 });
1787 }
1788 async debugState() {
1789 return {
1790 state: DriverReadyState[this.state],
1791 why: this.stateMessage,
1792 latestHash: this.latestHash,
1793 lastUpdateCheck: this.lastUpdateCheck
1794 };
1795 }
1796 async debugVersions() {
1797 return Array.from(this.versions.keys()).map((hash) => {
1798 const version = this.versions.get(hash);
1799 const clients = Array.from(this.clientVersionMap.entries()).filter(([clientId, version2]) => version2 === hash).map(([clientId, version2]) => clientId);
1800 return {
1801 hash,
1802 manifest: version.manifest,
1803 clients,
1804 status: ""
1805 };
1806 });
1807 }
1808 async debugIdleState() {
1809 return {
1810 queue: this.idle.taskDescriptions,
1811 lastTrigger: this.idle.lastTrigger,
1812 lastRun: this.idle.lastRun
1813 };
1814 }
1815 async safeFetch(req) {
1816 try {
1817 return await this.scope.fetch(req);
1818 } catch (err) {
1819 this.debugger.log(err, `Driver.fetch(${req.url})`);
1820 return this.adapter.newResponse(null, {
1821 status: 504,
1822 statusText: "Gateway Timeout"
1823 });
1824 }
1825 }
1826 async getCacheNames() {
1827 const controlTable = await this.controlTable;
1828 const appVersions = Array.from(this.versions.values());
1829 const appVersionCacheNames = await Promise.all(appVersions.map((version) => version.getCacheNames()));
1830 return [controlTable.cacheName].concat(...appVersionCacheNames);
1831 }
1832 };
1833
1834 // bazel-out/darwin-fastbuild-ST-2e5f3376adb5/bin/packages/service-worker/worker/main.mjs
1835 var scope = self;
1836 var adapter = new Adapter(scope.registration.scope, self.caches);
1837 new Driver(scope, adapter, new CacheDatabase(adapter));
1838})();
1839/**
1840 * @license
1841 * Copyright Google LLC All Rights Reserved.
1842 *
1843 * Use of this source code is governed by an MIT-style license that can be
1844 * found in the LICENSE file at https://angular.io/license
1845 */