try { self["workbox:core:6.5.3"] && _(); } catch { } const se = (n, ...e) => { let t = n; return e.length > 0 && (t += ` :: ${JSON.stringify(e)}`), t; }, ne = se; let w = class extends Error { /** * * @param {string} errorCode The error code that * identifies this particular error. * @param {Object=} details Any relevant arguments * that will help developers identify issues should * be added as a key on the context object. */ constructor(e, t) { const s = ne(e, t); super(s), this.name = e, this.details = t; } }; const Q = /* @__PURE__ */ new Set(); function re(n) { Q.add(n); } const d = { googleAnalytics: "googleAnalytics", precache: "precache-v2", prefix: "workbox", runtime: "runtime", suffix: typeof registration < "u" ? registration.scope : "" }, P = (n) => [d.prefix, n, d.suffix].filter((e) => e && e.length > 0).join("-"), ae = (n) => { for (const e of Object.keys(d)) n(e); }, z = { updateDetails: (n) => { ae((e) => { typeof n[e] == "string" && (d[e] = n[e]); }); }, getGoogleAnalyticsName: (n) => n || P(d.googleAnalytics), getPrecacheName: (n) => n || P(d.precache), getPrefix: () => d.prefix, getRuntimeName: (n) => n || P(d.runtime), getSuffix: () => d.suffix }; function q(n, e) { const t = new URL(n); for (const s of e) t.searchParams.delete(s); return t.href; } async function ie(n, e, t, s) { const r = q(e.url, t); if (e.url === r) return n.match(e, s); const i = Object.assign(Object.assign({}, s), { ignoreSearch: !0 }), a = await n.keys(e, i); for (const c of a) { const o = q(c.url, t); if (r === o) return n.match(c, s); } } function J(n) { n.then(() => { }); } let ce = class { /** * Creates a promise and exposes its resolve and reject functions as methods. */ constructor() { this.promise = new Promise((e, t) => { this.resolve = e, this.reject = t; }); } }; async function oe() { for (const n of Q) await n(); } const le = (n) => new URL(String(n), location.href).href.replace(new RegExp(`^${location.origin}`), ""); function he(n) { return new Promise((e) => setTimeout(e, n)); } function ue() { self.addEventListener("activate", () => self.clients.claim()); } const fe = (n, e) => e.some((t) => n instanceof t); let H, B; function de() { return H || (H = [ IDBDatabase, IDBObjectStore, IDBIndex, IDBCursor, IDBTransaction ]); } function pe() { return B || (B = [ IDBCursor.prototype.advance, IDBCursor.prototype.continue, IDBCursor.prototype.continuePrimaryKey ]); } const X = /* @__PURE__ */ new WeakMap(), K = /* @__PURE__ */ new WeakMap(), Y = /* @__PURE__ */ new WeakMap(), T = /* @__PURE__ */ new WeakMap(), j = /* @__PURE__ */ new WeakMap(); function ge(n) { const e = new Promise((t, s) => { const r = () => { n.removeEventListener("success", i), n.removeEventListener("error", a); }, i = () => { t(g(n.result)), r(); }, a = () => { s(n.error), r(); }; n.addEventListener("success", i), n.addEventListener("error", a); }); return e.then((t) => { t instanceof IDBCursor && X.set(t, n); }).catch(() => { }), j.set(e, n), e; } function me(n) { if (K.has(n)) return; const e = new Promise((t, s) => { const r = () => { n.removeEventListener("complete", i), n.removeEventListener("error", a), n.removeEventListener("abort", a); }, i = () => { t(), r(); }, a = () => { s(n.error || new DOMException("AbortError", "AbortError")), r(); }; n.addEventListener("complete", i), n.addEventListener("error", a), n.addEventListener("abort", a); }); K.set(n, e); } let S = { get(n, e, t) { if (n instanceof IDBTransaction) { if (e === "done") return K.get(n); if (e === "objectStoreNames") return n.objectStoreNames || Y.get(n); if (e === "store") return t.objectStoreNames[1] ? void 0 : t.objectStore(t.objectStoreNames[0]); } return g(n[e]); }, set(n, e, t) { return n[e] = t, !0; }, has(n, e) { return n instanceof IDBTransaction && (e === "done" || e === "store") ? !0 : e in n; } }; function we(n) { S = n(S); } function ye(n) { return n === IDBDatabase.prototype.transaction && !("objectStoreNames" in IDBTransaction.prototype) ? function(e, ...t) { const s = n.call(M(this), e, ...t); return Y.set(s, e.sort ? e.sort() : [e]), g(s); } : pe().includes(n) ? function(...e) { return n.apply(M(this), e), g(X.get(this)); } : function(...e) { return g(n.apply(M(this), e)); }; } function be(n) { return typeof n == "function" ? ye(n) : (n instanceof IDBTransaction && me(n), fe(n, de()) ? new Proxy(n, S) : n); } function g(n) { if (n instanceof IDBRequest) return ge(n); if (T.has(n)) return T.get(n); const e = be(n); return e !== n && (T.set(n, e), j.set(e, n)), e; } const M = (n) => j.get(n); function _e(n, e, { blocked: t, upgrade: s, blocking: r, terminated: i } = {}) { const a = indexedDB.open(n, e), c = g(a); return s && a.addEventListener("upgradeneeded", (o) => { s(g(a.result), o.oldVersion, o.newVersion, g(a.transaction), o); }), t && a.addEventListener("blocked", (o) => t( // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405 o.oldVersion, o.newVersion, o )), c.then((o) => { i && o.addEventListener("close", () => i()), r && o.addEventListener("versionchange", (l) => r(l.oldVersion, l.newVersion, l)); }).catch(() => { }), c; } function Re(n, { blocked: e } = {}) { const t = indexedDB.deleteDatabase(n); return e && t.addEventListener("blocked", (s) => e( // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405 s.oldVersion, s )), g(t).then(() => { }); } const Ce = ["get", "getKey", "getAll", "getAllKeys", "count"], xe = ["put", "add", "delete", "clear"], N = /* @__PURE__ */ new Map(); function $(n, e) { if (!(n instanceof IDBDatabase && !(e in n) && typeof e == "string")) return; if (N.get(e)) return N.get(e); const t = e.replace(/FromIndex$/, ""), s = e !== t, r = xe.includes(t); if ( // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge. !(t in (s ? IDBIndex : IDBObjectStore).prototype) || !(r || Ce.includes(t)) ) return; const i = async function(a, ...c) { const o = this.transaction(a, r ? "readwrite" : "readonly"); let l = o.store; return s && (l = l.index(c.shift())), (await Promise.all([ l[t](...c), r && o.done ]))[0]; }; return N.set(e, i), i; } we((n) => ({ ...n, get: (e, t, s) => $(e, t) || n.get(e, t, s), has: (e, t) => !!$(e, t) || n.has(e, t) })); try { self["workbox:expiration:6.5.3"] && _(); } catch { } const ke = "workbox-expiration", b = "cache-entries", F = (n) => { const e = new URL(n, location.href); return e.hash = "", e.href; }; class Ee { /** * * @param {string} cacheName * * @private */ constructor(e) { this._db = null, this._cacheName = e; } /** * Performs an upgrade of indexedDB. * * @param {IDBPDatabase} db * * @private */ _upgradeDb(e) { const t = e.createObjectStore(b, { keyPath: "id" }); t.createIndex("cacheName", "cacheName", { unique: !1 }), t.createIndex("timestamp", "timestamp", { unique: !1 }); } /** * Performs an upgrade of indexedDB and deletes deprecated DBs. * * @param {IDBPDatabase} db * * @private */ _upgradeDbAndDeleteOldDbs(e) { this._upgradeDb(e), this._cacheName && Re(this._cacheName); } /** * @param {string} url * @param {number} timestamp * * @private */ async setTimestamp(e, t) { e = F(e); const s = { url: e, timestamp: t, cacheName: this._cacheName, // Creating an ID from the URL and cache name won't be necessary once // Edge switches to Chromium and all browsers we support work with // array keyPaths. id: this._getId(e) }, i = (await this.getDb()).transaction(b, "readwrite", { durability: "relaxed" }); await i.store.put(s), await i.done; } /** * Returns the timestamp stored for a given URL. * * @param {string} url * @return {number | undefined} * * @private */ async getTimestamp(e) { const s = await (await this.getDb()).get(b, this._getId(e)); return s == null ? void 0 : s.timestamp; } /** * Iterates through all the entries in the object store (from newest to * oldest) and removes entries once either `maxCount` is reached or the * entry's timestamp is less than `minTimestamp`. * * @param {number} minTimestamp * @param {number} maxCount * @return {Array} * * @private */ async expireEntries(e, t) { const s = await this.getDb(); let r = await s.transaction(b).store.index("timestamp").openCursor(null, "prev"); const i = []; let a = 0; for (; r; ) { const o = r.value; o.cacheName === this._cacheName && (e && o.timestamp < e || t && a >= t ? i.push(r.value) : a++), r = await r.continue(); } const c = []; for (const o of i) await s.delete(b, o.id), c.push(o.url); return c; } /** * Takes a URL and returns an ID that will be unique in the object store. * * @param {string} url * @return {string} * * @private */ _getId(e) { return this._cacheName + "|" + F(e); } /** * Returns an open connection to the database. * * @private */ async getDb() { return this._db || (this._db = await _e(ke, 1, { upgrade: this._upgradeDbAndDeleteOldDbs.bind(this) })), this._db; } } class De { /** * To construct a new CacheExpiration instance you must provide at least * one of the `config` properties. * * @param {string} cacheName Name of the cache to apply restrictions to. * @param {Object} config * @param {number} [config.maxEntries] The maximum number of entries to cache. * Entries used the least will be removed as the maximum is reached. * @param {number} [config.maxAgeSeconds] The maximum age of an entry before * it's treated as stale and removed. * @param {Object} [config.matchOptions] The [`CacheQueryOptions`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/delete#Parameters) * that will be used when calling `delete()` on the cache. */ constructor(e, t = {}) { this._isRunning = !1, this._rerunRequested = !1, this._maxEntries = t.maxEntries, this._maxAgeSeconds = t.maxAgeSeconds, this._matchOptions = t.matchOptions, this._cacheName = e, this._timestampModel = new Ee(e); } /** * Expires entries for the given cache and given criteria. */ async expireEntries() { if (this._isRunning) { this._rerunRequested = !0; return; } this._isRunning = !0; const e = this._maxAgeSeconds ? Date.now() - this._maxAgeSeconds * 1e3 : 0, t = await this._timestampModel.expireEntries(e, this._maxEntries), s = await self.caches.open(this._cacheName); for (const r of t) await s.delete(r, this._matchOptions); this._isRunning = !1, this._rerunRequested && (this._rerunRequested = !1, J(this.expireEntries())); } /** * Update the timestamp for the given URL. This ensures the when * removing entries based on maximum entries, most recently used * is accurate or when expiring, the timestamp is up-to-date. * * @param {string} url */ async updateTimestamp(e) { await this._timestampModel.setTimestamp(e, Date.now()); } /** * Can be used to check if a URL has expired or not before it's used. * * This requires a look up from IndexedDB, so can be slow. * * Note: This method will not remove the cached entry, call * `expireEntries()` to remove indexedDB and Cache entries. * * @param {string} url * @return {boolean} */ async isURLExpired(e) { if (this._maxAgeSeconds) { const t = await this._timestampModel.getTimestamp(e), s = Date.now() - this._maxAgeSeconds * 1e3; return t !== void 0 ? t < s : !0; } else return !1; } /** * Removes the IndexedDB object store used to keep track of cache expiration * metadata. */ async delete() { this._rerunRequested = !1, await this._timestampModel.expireEntries(1 / 0); } } class Ue { /** * @param {ExpirationPluginOptions} config * @param {number} [config.maxEntries] The maximum number of entries to cache. * Entries used the least will be removed as the maximum is reached. * @param {number} [config.maxAgeSeconds] The maximum age of an entry before * it's treated as stale and removed. * @param {Object} [config.matchOptions] The [`CacheQueryOptions`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/delete#Parameters) * that will be used when calling `delete()` on the cache. * @param {boolean} [config.purgeOnQuotaError] Whether to opt this cache in to * automatic deletion if the available storage quota has been exceeded. */ constructor(e = {}) { this.cachedResponseWillBeUsed = async ({ event: t, request: s, cacheName: r, cachedResponse: i }) => { if (!i) return null; const a = this._isResponseDateFresh(i), c = this._getCacheExpiration(r); J(c.expireEntries()); const o = c.updateTimestamp(s.url); if (t) try { t.waitUntil(o); } catch { } return a ? i : null; }, this.cacheDidUpdate = async ({ cacheName: t, request: s }) => { const r = this._getCacheExpiration(t); await r.updateTimestamp(s.url), await r.expireEntries(); }, this._config = e, this._maxAgeSeconds = e.maxAgeSeconds, this._cacheExpirations = /* @__PURE__ */ new Map(), e.purgeOnQuotaError && re(() => this.deleteCacheAndMetadata()); } /** * A simple helper method to return a CacheExpiration instance for a given * cache name. * * @param {string} cacheName * @return {CacheExpiration} * * @private */ _getCacheExpiration(e) { if (e === z.getRuntimeName()) throw new w("expire-custom-caches-only"); let t = this._cacheExpirations.get(e); return t || (t = new De(e, this._config), this._cacheExpirations.set(e, t)), t; } /** * @param {Response} cachedResponse * @return {boolean} * * @private */ _isResponseDateFresh(e) { if (!this._maxAgeSeconds) return !0; const t = this._getDateHeaderTimestamp(e); if (t === null) return !0; const s = Date.now(); return t >= s - this._maxAgeSeconds * 1e3; } /** * This method will extract the data header and parse it into a useful * value. * * @param {Response} cachedResponse * @return {number|null} * * @private */ _getDateHeaderTimestamp(e) { if (!e.headers.has("date")) return null; const t = e.headers.get("date"), r = new Date(t).getTime(); return isNaN(r) ? null : r; } /** * This is a helper method that performs two operations: * * - Deletes *all* the underlying Cache instances associated with this plugin * instance, by calling caches.delete() on your behalf. * - Deletes the metadata from IndexedDB used to keep track of expiration * details for each Cache instance. * * When using cache expiration, calling this method is preferable to calling * `caches.delete()` directly, since this will ensure that the IndexedDB * metadata is also cleanly removed and open IndexedDB instances are deleted. * * Note that if you're *not* using cache expiration for a given cache, calling * `caches.delete()` and passing in the cache's name should be sufficient. * There is no Workbox-specific method needed for cleanup in that case. */ async deleteCacheAndMetadata() { for (const [e, t] of this._cacheExpirations) await self.caches.delete(e), await t.delete(); this._cacheExpirations = /* @__PURE__ */ new Map(); } } try { self["workbox:core:7.0.0"] && _(); } catch { } const Le = (n, ...e) => { let t = n; return e.length > 0 && (t += ` :: ${JSON.stringify(e)}`), t; }, ve = Le; class u extends Error { /** * * @param {string} errorCode The error code that * identifies this particular error. * @param {Object=} details Any relevant arguments * that will help developers identify issues should * be added as a key on the context object. */ constructor(e, t) { const s = ve(e, t); super(s), this.name = e, this.details = t; } } const p = { googleAnalytics: "googleAnalytics", precache: "precache-v2", prefix: "workbox", runtime: "runtime", suffix: typeof registration < "u" ? registration.scope : "" }, O = (n) => [p.prefix, n, p.suffix].filter((e) => e && e.length > 0).join("-"), Pe = (n) => { for (const e of Object.keys(p)) n(e); }, A = { updateDetails: (n) => { Pe((e) => { typeof n[e] == "string" && (p[e] = n[e]); }); }, getGoogleAnalyticsName: (n) => n || O(p.googleAnalytics), getPrecacheName: (n) => n || O(p.precache), getPrefix: () => p.prefix, getRuntimeName: (n) => n || O(p.runtime), getSuffix: () => p.suffix }; function V(n, e) { const t = e(); return n.waitUntil(t), t; } try { self["workbox:precaching:7.0.0"] && _(); } catch { } const Te = "__WB_REVISION__"; function Me(n) { if (!n) throw new u("add-to-cache-list-unexpected-type", { entry: n }); if (typeof n == "string") { const i = new URL(n, location.href); return { cacheKey: i.href, url: i.href }; } const { revision: e, url: t } = n; if (!t) throw new u("add-to-cache-list-unexpected-type", { entry: n }); if (!e) { const i = new URL(t, location.href); return { cacheKey: i.href, url: i.href }; } const s = new URL(t, location.href), r = new URL(t, location.href); return s.searchParams.set(Te, e), { cacheKey: s.href, url: r.href }; } class Ne { constructor() { this.updatedURLs = [], this.notUpdatedURLs = [], this.handlerWillStart = async ({ request: e, state: t }) => { t && (t.originalRequest = e); }, this.cachedResponseWillBeUsed = async ({ event: e, state: t, cachedResponse: s }) => { if (e.type === "install" && t && t.originalRequest && t.originalRequest instanceof Request) { const r = t.originalRequest.url; s ? this.notUpdatedURLs.push(r) : this.updatedURLs.push(r); } return s; }; } } class Oe { constructor({ precacheController: e }) { this.cacheKeyWillBeUsed = async ({ request: t, params: s }) => { const r = (s == null ? void 0 : s.cacheKey) || this._precacheController.getCacheKeyForURL(t.url); return r ? new Request(r, { headers: t.headers }) : t; }, this._precacheController = e; } } let R; function Ie() { if (R === void 0) { const n = new Response(""); if ("body" in n) try { new Response(n.body), R = !0; } catch { R = !1; } R = !1; } return R; } async function Ke(n, e) { let t = null; if (n.url && (t = new URL(n.url).origin), t !== self.location.origin) throw new u("cross-origin-copy-response", { origin: t }); const s = n.clone(), r = { headers: new Headers(s.headers), status: s.status, statusText: s.statusText }, i = e ? e(r) : r, a = Ie() ? s.body : await s.blob(); return new Response(a, i); } const Se = (n) => new URL(String(n), location.href).href.replace(new RegExp(`^${location.origin}`), ""); function G(n, e) { const t = new URL(n); for (const s of e) t.searchParams.delete(s); return t.href; } async function je(n, e, t, s) { const r = G(e.url, t); if (e.url === r) return n.match(e, s); const i = Object.assign(Object.assign({}, s), { ignoreSearch: !0 }), a = await n.keys(e, i); for (const c of a) { const o = G(c.url, t); if (r === o) return n.match(c, s); } } class Ae { /** * Creates a promise and exposes its resolve and reject functions as methods. */ constructor() { this.promise = new Promise((e, t) => { this.resolve = e, this.reject = t; }); } } const We = /* @__PURE__ */ new Set(); async function qe() { for (const n of We) await n(); } function He(n) { return new Promise((e) => setTimeout(e, n)); } try { self["workbox:strategies:7.0.0"] && _(); } catch { } function E(n) { return typeof n == "string" ? new Request(n) : n; } let Be = class { /** * Creates a new instance associated with the passed strategy and event * that's handling the request. * * The constructor also initializes the state that will be passed to each of * the plugins handling this request. * * @param {workbox-strategies.Strategy} strategy * @param {Object} options * @param {Request|string} options.request A request to run this strategy for. * @param {ExtendableEvent} options.event The event associated with the * request. * @param {URL} [options.url] * @param {*} [options.params] The return value from the * {@link workbox-routing~matchCallback} (if applicable). */ constructor(e, t) { this._cacheKeys = {}, Object.assign(this, t), this.event = t.event, this._strategy = e, this._handlerDeferred = new Ae(), this._extendLifetimePromises = [], this._plugins = [...e.plugins], this._pluginStateMap = /* @__PURE__ */ new Map(); for (const s of this._plugins) this._pluginStateMap.set(s, {}); this.event.waitUntil(this._handlerDeferred.promise); } /** * Fetches a given request (and invokes any applicable plugin callback * methods) using the `fetchOptions` (for non-navigation requests) and * `plugins` defined on the `Strategy` object. * * The following plugin lifecycle methods are invoked when using this method: * - `requestWillFetch()` * - `fetchDidSucceed()` * - `fetchDidFail()` * * @param {Request|string} input The URL or request to fetch. * @return {Promise} */ async fetch(e) { const { event: t } = this; let s = E(e); if (s.mode === "navigate" && t instanceof FetchEvent && t.preloadResponse) { const a = await t.preloadResponse; if (a) return a; } const r = this.hasCallback("fetchDidFail") ? s.clone() : null; try { for (const a of this.iterateCallbacks("requestWillFetch")) s = await a({ request: s.clone(), event: t }); } catch (a) { if (a instanceof Error) throw new u("plugin-error-request-will-fetch", { thrownErrorMessage: a.message }); } const i = s.clone(); try { let a; a = await fetch(s, s.mode === "navigate" ? void 0 : this._strategy.fetchOptions); for (const c of this.iterateCallbacks("fetchDidSucceed")) a = await c({ event: t, request: i, response: a }); return a; } catch (a) { throw r && await this.runCallbacks("fetchDidFail", { error: a, event: t, originalRequest: r.clone(), request: i.clone() }), a; } } /** * Calls `this.fetch()` and (in the background) runs `this.cachePut()` on * the response generated by `this.fetch()`. * * The call to `this.cachePut()` automatically invokes `this.waitUntil()`, * so you do not have to manually call `waitUntil()` on the event. * * @param {Request|string} input The request or URL to fetch and cache. * @return {Promise} */ async fetchAndCachePut(e) { const t = await this.fetch(e), s = t.clone(); return this.waitUntil(this.cachePut(e, s)), t; } /** * Matches a request from the cache (and invokes any applicable plugin * callback methods) using the `cacheName`, `matchOptions`, and `plugins` * defined on the strategy object. * * The following plugin lifecycle methods are invoked when using this method: * - cacheKeyWillByUsed() * - cachedResponseWillByUsed() * * @param {Request|string} key The Request or URL to use as the cache key. * @return {Promise} A matching response, if found. */ async cacheMatch(e) { const t = E(e); let s; const { cacheName: r, matchOptions: i } = this._strategy, a = await this.getCacheKey(t, "read"), c = Object.assign(Object.assign({}, i), { cacheName: r }); s = await caches.match(a, c); for (const o of this.iterateCallbacks("cachedResponseWillBeUsed")) s = await o({ cacheName: r, matchOptions: i, cachedResponse: s, request: a, event: this.event }) || void 0; return s; } /** * Puts a request/response pair in the cache (and invokes any applicable * plugin callback methods) using the `cacheName` and `plugins` defined on * the strategy object. * * The following plugin lifecycle methods are invoked when using this method: * - cacheKeyWillByUsed() * - cacheWillUpdate() * - cacheDidUpdate() * * @param {Request|string} key The request or URL to use as the cache key. * @param {Response} response The response to cache. * @return {Promise} `false` if a cacheWillUpdate caused the response * not be cached, and `true` otherwise. */ async cachePut(e, t) { const s = E(e); await He(0); const r = await this.getCacheKey(s, "write"); if (!t) throw new u("cache-put-with-no-response", { url: Se(r.url) }); const i = await this._ensureResponseSafeToCache(t); if (!i) return !1; const { cacheName: a, matchOptions: c } = this._strategy, o = await self.caches.open(a), l = this.hasCallback("cacheDidUpdate"), f = l ? await je( // TODO(philipwalton): the `__WB_REVISION__` param is a precaching // feature. Consider into ways to only add this behavior if using // precaching. o, r.clone(), ["__WB_REVISION__"], c ) : null; try { await o.put(r, l ? i.clone() : i); } catch (h) { if (h instanceof Error) throw h.name === "QuotaExceededError" && await qe(), h; } for (const h of this.iterateCallbacks("cacheDidUpdate")) await h({ cacheName: a, oldResponse: f, newResponse: i.clone(), request: r, event: this.event }); return !0; } /** * Checks the list of plugins for the `cacheKeyWillBeUsed` callback, and * executes any of those callbacks found in sequence. The final `Request` * object returned by the last plugin is treated as the cache key for cache * reads and/or writes. If no `cacheKeyWillBeUsed` plugin callbacks have * been registered, the passed request is returned unmodified * * @param {Request} request * @param {string} mode * @return {Promise} */ async getCacheKey(e, t) { const s = `${e.url} | ${t}`; if (!this._cacheKeys[s]) { let r = e; for (const i of this.iterateCallbacks("cacheKeyWillBeUsed")) r = E(await i({ mode: t, request: r, event: this.event, // params has a type any can't change right now. params: this.params // eslint-disable-line })); this._cacheKeys[s] = r; } return this._cacheKeys[s]; } /** * Returns true if the strategy has at least one plugin with the given * callback. * * @param {string} name The name of the callback to check for. * @return {boolean} */ hasCallback(e) { for (const t of this._strategy.plugins) if (e in t) return !0; return !1; } /** * Runs all plugin callbacks matching the given name, in order, passing the * given param object (merged ith the current plugin state) as the only * argument. * * Note: since this method runs all plugins, it's not suitable for cases * where the return value of a callback needs to be applied prior to calling * the next callback. See * {@link workbox-strategies.StrategyHandler#iterateCallbacks} * below for how to handle that case. * * @param {string} name The name of the callback to run within each plugin. * @param {Object} param The object to pass as the first (and only) param * when executing each callback. This object will be merged with the * current plugin state prior to callback execution. */ async runCallbacks(e, t) { for (const s of this.iterateCallbacks(e)) await s(t); } /** * Accepts a callback and returns an iterable of matching plugin callbacks, * where each callback is wrapped with the current handler state (i.e. when * you call each callback, whatever object parameter you pass it will * be merged with the plugin's current state). * * @param {string} name The name fo the callback to run * @return {Array} */ *iterateCallbacks(e) { for (const t of this._strategy.plugins) if (typeof t[e] == "function") { const s = this._pluginStateMap.get(t); yield (i) => { const a = Object.assign(Object.assign({}, i), { state: s }); return t[e](a); }; } } /** * Adds a promise to the * [extend lifetime promises]{@link https://w3c.github.io/ServiceWorker/#extendableevent-extend-lifetime-promises} * of the event event associated with the request being handled (usually a * `FetchEvent`). * * Note: you can await * {@link workbox-strategies.StrategyHandler~doneWaiting} * to know when all added promises have settled. * * @param {Promise} promise A promise to add to the extend lifetime promises * of the event that triggered the request. */ waitUntil(e) { return this._extendLifetimePromises.push(e), e; } /** * Returns a promise that resolves once all promises passed to * {@link workbox-strategies.StrategyHandler~waitUntil} * have settled. * * Note: any work done after `doneWaiting()` settles should be manually * passed to an event's `waitUntil()` method (not this handler's * `waitUntil()` method), otherwise the service worker thread my be killed * prior to your work completing. */ async doneWaiting() { let e; for (; e = this._extendLifetimePromises.shift(); ) await e; } /** * Stops running the strategy and immediately resolves any pending * `waitUntil()` promises. */ destroy() { this._handlerDeferred.resolve(null); } /** * This method will call cacheWillUpdate on the available plugins (or use * status === 200) to determine if the Response is safe and valid to cache. * * @param {Request} options.request * @param {Response} options.response * @return {Promise} * * @private */ async _ensureResponseSafeToCache(e) { let t = e, s = !1; for (const r of this.iterateCallbacks("cacheWillUpdate")) if (t = await r({ request: this.request, response: t, event: this.event }) || void 0, s = !0, !t) break; return s || t && t.status !== 200 && (t = void 0), t; } }, $e = class { /** * Creates a new instance of the strategy and sets all documented option * properties as public instance properties. * * Note: if a custom strategy class extends the base Strategy class and does * not need more than these properties, it does not need to define its own * constructor. * * @param {Object} [options] * @param {string} [options.cacheName] Cache name to store and retrieve * requests. Defaults to the cache names provided by * {@link workbox-core.cacheNames}. * @param {Array} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} * to use in conjunction with this caching strategy. * @param {Object} [options.fetchOptions] Values passed along to the * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) * of [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796) * `fetch()` requests made by this strategy. * @param {Object} [options.matchOptions] The * [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions} * for any `cache.match()` or `cache.put()` calls made by this strategy. */ constructor(e = {}) { this.cacheName = A.getRuntimeName(e.cacheName), this.plugins = e.plugins || [], this.fetchOptions = e.fetchOptions, this.matchOptions = e.matchOptions; } /** * Perform a request strategy and returns a `Promise` that will resolve with * a `Response`, invoking all relevant plugin callbacks. * * When a strategy instance is registered with a Workbox * {@link workbox-routing.Route}, this method is automatically * called when the route matches. * * Alternatively, this method can be used in a standalone `FetchEvent` * listener by passing it to `event.respondWith()`. * * @param {FetchEvent|Object} options A `FetchEvent` or an object with the * properties listed below. * @param {Request|string} options.request A request to run this strategy for. * @param {ExtendableEvent} options.event The event associated with the * request. * @param {URL} [options.url] * @param {*} [options.params] */ handle(e) { const [t] = this.handleAll(e); return t; } /** * Similar to {@link workbox-strategies.Strategy~handle}, but * instead of just returning a `Promise` that resolves to a `Response` it * it will return an tuple of `[response, done]` promises, where the former * (`response`) is equivalent to what `handle()` returns, and the latter is a * Promise that will resolve once any promises that were added to * `event.waitUntil()` as part of performing the strategy have completed. * * You can await the `done` promise to ensure any extra work performed by * the strategy (usually caching responses) completes successfully. * * @param {FetchEvent|Object} options A `FetchEvent` or an object with the * properties listed below. * @param {Request|string} options.request A request to run this strategy for. * @param {ExtendableEvent} options.event The event associated with the * request. * @param {URL} [options.url] * @param {*} [options.params] * @return {Array} A tuple of [response, done] * promises that can be used to determine when the response resolves as * well as when the handler has completed all its work. */ handleAll(e) { e instanceof FetchEvent && (e = { event: e, request: e.request }); const t = e.event, s = typeof e.request == "string" ? new Request(e.request) : e.request, r = "params" in e ? e.params : void 0, i = new Be(this, { event: t, request: s, params: r }), a = this._getResponse(i, s, t), c = this._awaitComplete(a, i, s, t); return [a, c]; } async _getResponse(e, t, s) { await e.runCallbacks("handlerWillStart", { event: s, request: t }); let r; try { if (r = await this._handle(t, e), !r || r.type === "error") throw new u("no-response", { url: t.url }); } catch (i) { if (i instanceof Error) { for (const a of e.iterateCallbacks("handlerDidError")) if (r = await a({ error: i, event: s, request: t }), r) break; } if (!r) throw i; } for (const i of e.iterateCallbacks("handlerWillRespond")) r = await i({ event: s, request: t, response: r }); return r; } async _awaitComplete(e, t, s, r) { let i, a; try { i = await e; } catch { } try { await t.runCallbacks("handlerDidRespond", { event: r, request: s, response: i }), await t.doneWaiting(); } catch (c) { c instanceof Error && (a = c); } if (await t.runCallbacks("handlerDidComplete", { event: r, request: s, response: i, error: a }), t.destroy(), a) throw a; } }; class m extends $e { /** * * @param {Object} [options] * @param {string} [options.cacheName] Cache name to store and retrieve * requests. Defaults to the cache names provided by * {@link workbox-core.cacheNames}. * @param {Array} [options.plugins] {@link https://developers.google.com/web/tools/workbox/guides/using-plugins|Plugins} * to use in conjunction with this caching strategy. * @param {Object} [options.fetchOptions] Values passed along to the * {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters|init} * of all fetch() requests made by this strategy. * @param {Object} [options.matchOptions] The * {@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions|CacheQueryOptions} * for any `cache.match()` or `cache.put()` calls made by this strategy. * @param {boolean} [options.fallbackToNetwork=true] Whether to attempt to * get the response from the network if there's a precache miss. */ constructor(e = {}) { e.cacheName = A.getPrecacheName(e.cacheName), super(e), this._fallbackToNetwork = e.fallbackToNetwork !== !1, this.plugins.push(m.copyRedirectedCacheableResponsesPlugin); } /** * @private * @param {Request|string} request A request to run this strategy for. * @param {workbox-strategies.StrategyHandler} handler The event that * triggered the request. * @return {Promise} */ async _handle(e, t) { const s = await t.cacheMatch(e); return s || (t.event && t.event.type === "install" ? await this._handleInstall(e, t) : await this._handleFetch(e, t)); } async _handleFetch(e, t) { let s; const r = t.params || {}; if (this._fallbackToNetwork) { const i = r.integrity, a = e.integrity, c = !a || a === i; s = await t.fetch(new Request(e, { integrity: e.mode !== "no-cors" ? a || i : void 0 })), i && c && e.mode !== "no-cors" && (this._useDefaultCacheabilityPluginIfNeeded(), await t.cachePut(e, s.clone())); } else throw new u("missing-precache-entry", { cacheName: this.cacheName, url: e.url }); return s; } async _handleInstall(e, t) { this._useDefaultCacheabilityPluginIfNeeded(); const s = await t.fetch(e); if (!await t.cachePut(e, s.clone())) throw new u("bad-precaching-response", { url: e.url, status: s.status }); return s; } /** * This method is complex, as there a number of things to account for: * * The `plugins` array can be set at construction, and/or it might be added to * to at any time before the strategy is used. * * At the time the strategy is used (i.e. during an `install` event), there * needs to be at least one plugin that implements `cacheWillUpdate` in the * array, other than `copyRedirectedCacheableResponsesPlugin`. * * - If this method is called and there are no suitable `cacheWillUpdate` * plugins, we need to add `defaultPrecacheCacheabilityPlugin`. * * - If this method is called and there is exactly one `cacheWillUpdate`, then * we don't have to do anything (this might be a previously added * `defaultPrecacheCacheabilityPlugin`, or it might be a custom plugin). * * - If this method is called and there is more than one `cacheWillUpdate`, * then we need to check if one is `defaultPrecacheCacheabilityPlugin`. If so, * we need to remove it. (This situation is unlikely, but it could happen if * the strategy is used multiple times, the first without a `cacheWillUpdate`, * and then later on after manually adding a custom `cacheWillUpdate`.) * * See https://github.com/GoogleChrome/workbox/issues/2737 for more context. * * @private */ _useDefaultCacheabilityPluginIfNeeded() { let e = null, t = 0; for (const [s, r] of this.plugins.entries()) r !== m.copyRedirectedCacheableResponsesPlugin && (r === m.defaultPrecacheCacheabilityPlugin && (e = s), r.cacheWillUpdate && t++); t === 0 ? this.plugins.push(m.defaultPrecacheCacheabilityPlugin) : t > 1 && e !== null && this.plugins.splice(e, 1); } } m.defaultPrecacheCacheabilityPlugin = { async cacheWillUpdate({ response: n }) { return !n || n.status >= 400 ? null : n; } }; m.copyRedirectedCacheableResponsesPlugin = { async cacheWillUpdate({ response: n }) { return n.redirected ? await Ke(n) : n; } }; class Fe { /** * Create a new PrecacheController. * * @param {Object} [options] * @param {string} [options.cacheName] The cache to use for precaching. * @param {string} [options.plugins] Plugins to use when precaching as well * as responding to fetch events for precached assets. * @param {boolean} [options.fallbackToNetwork=true] Whether to attempt to * get the response from the network if there's a precache miss. */ constructor({ cacheName: e, plugins: t = [], fallbackToNetwork: s = !0 } = {}) { this._urlsToCacheKeys = /* @__PURE__ */ new Map(), this._urlsToCacheModes = /* @__PURE__ */ new Map(), this._cacheKeysToIntegrities = /* @__PURE__ */ new Map(), this._strategy = new m({ cacheName: A.getPrecacheName(e), plugins: [ ...t, new Oe({ precacheController: this }) ], fallbackToNetwork: s }), this.install = this.install.bind(this), this.activate = this.activate.bind(this); } /** * @type {workbox-precaching.PrecacheStrategy} The strategy created by this controller and * used to cache assets and respond to fetch events. */ get strategy() { return this._strategy; } /** * Adds items to the precache list, removing any duplicates and * stores the files in the * {@link workbox-core.cacheNames|"precache cache"} when the service * worker installs. * * This method can be called multiple times. * * @param {Array} [entries=[]] Array of entries to precache. */ precache(e) { this.addToCacheList(e), this._installAndActiveListenersAdded || (self.addEventListener("install", this.install), self.addEventListener("activate", this.activate), this._installAndActiveListenersAdded = !0); } /** * This method will add items to the precache list, removing duplicates * and ensuring the information is valid. * * @param {Array} entries * Array of entries to precache. */ addToCacheList(e) { const t = []; for (const s of e) { typeof s == "string" ? t.push(s) : s && s.revision === void 0 && t.push(s.url); const { cacheKey: r, url: i } = Me(s), a = typeof s != "string" && s.revision ? "reload" : "default"; if (this._urlsToCacheKeys.has(i) && this._urlsToCacheKeys.get(i) !== r) throw new u("add-to-cache-list-conflicting-entries", { firstEntry: this._urlsToCacheKeys.get(i), secondEntry: r }); if (typeof s != "string" && s.integrity) { if (this._cacheKeysToIntegrities.has(r) && this._cacheKeysToIntegrities.get(r) !== s.integrity) throw new u("add-to-cache-list-conflicting-integrities", { url: i }); this._cacheKeysToIntegrities.set(r, s.integrity); } if (this._urlsToCacheKeys.set(i, r), this._urlsToCacheModes.set(i, a), t.length > 0) { const c = `Workbox is precaching URLs without revision info: ${t.join(", ")} This is generally NOT safe. Learn more at https://bit.ly/wb-precache`; console.warn(c); } } } /** * Precaches new and updated assets. Call this method from the service worker * install event. * * Note: this method calls `event.waitUntil()` for you, so you do not need * to call it yourself in your event handlers. * * @param {ExtendableEvent} event * @return {Promise} */ install(e) { return V(e, async () => { const t = new Ne(); this.strategy.plugins.push(t); for (const [i, a] of this._urlsToCacheKeys) { const c = this._cacheKeysToIntegrities.get(a), o = this._urlsToCacheModes.get(i), l = new Request(i, { integrity: c, cache: o, credentials: "same-origin" }); await Promise.all(this.strategy.handleAll({ params: { cacheKey: a }, request: l, event: e })); } const { updatedURLs: s, notUpdatedURLs: r } = t; return { updatedURLs: s, notUpdatedURLs: r }; }); } /** * Deletes assets that are no longer present in the current precache manifest. * Call this method from the service worker activate event. * * Note: this method calls `event.waitUntil()` for you, so you do not need * to call it yourself in your event handlers. * * @param {ExtendableEvent} event * @return {Promise} */ activate(e) { return V(e, async () => { const t = await self.caches.open(this.strategy.cacheName), s = await t.keys(), r = new Set(this._urlsToCacheKeys.values()), i = []; for (const a of s) r.has(a.url) || (await t.delete(a), i.push(a.url)); return { deletedURLs: i }; }); } /** * Returns a mapping of a precached URL to the corresponding cache key, taking * into account the revision information for the URL. * * @return {Map} A URL to cache key mapping. */ getURLsToCacheKeys() { return this._urlsToCacheKeys; } /** * Returns a list of all the URLs that have been precached by the current * service worker. * * @return {Array} The precached URLs. */ getCachedURLs() { return [...this._urlsToCacheKeys.keys()]; } /** * Returns the cache key used for storing a given URL. If that URL is * unversioned, like `/index.html', then the cache key will be the original * URL with a search parameter appended to it. * * @param {string} url A URL whose cache key you want to look up. * @return {string} The versioned URL that corresponds to a cache key * for the original URL, or undefined if that URL isn't precached. */ getCacheKeyForURL(e) { const t = new URL(e, location.href); return this._urlsToCacheKeys.get(t.href); } /** * @param {string} url A cache key whose SRI you want to look up. * @return {string} The subresource integrity associated with the cache key, * or undefined if it's not set. */ getIntegrityForCacheKey(e) { return this._cacheKeysToIntegrities.get(e); } /** * This acts as a drop-in replacement for * [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match) * with the following differences: * * - It knows what the name of the precache is, and only checks in that cache. * - It allows you to pass in an "original" URL without versioning parameters, * and it will automatically look up the correct cache key for the currently * active revision of that URL. * * E.g., `matchPrecache('index.html')` will find the correct precached * response for the currently active service worker, even if the actual cache * key is `'/index.html?__WB_REVISION__=1234abcd'`. * * @param {string|Request} request The key (without revisioning parameters) * to look up in the precache. * @return {Promise} */ async matchPrecache(e) { const t = e instanceof Request ? e.url : e, s = this.getCacheKeyForURL(t); if (s) return (await self.caches.open(this.strategy.cacheName)).match(s); } /** * Returns a function that looks up `url` in the precache (taking into * account revision information), and returns the corresponding `Response`. * * @param {string} url The precached URL which will be used to lookup the * `Response`. * @return {workbox-routing~handlerCallback} */ createHandlerBoundToURL(e) { const t = this.getCacheKeyForURL(e); if (!t) throw new u("non-precached-url", { url: e }); return (s) => (s.request = new Request(e), s.params = Object.assign({ cacheKey: t }, s.params), this.strategy.handle(s)); } } let I; const W = () => (I || (I = new Fe()), I); try { self["workbox:routing:7.0.0"] && _(); } catch { } const Z = "GET", L = (n) => n && typeof n == "object" ? n : { handle: n }; let k = class { /** * Constructor for Route class. * * @param {workbox-routing~matchCallback} match * A callback function that determines whether the route matches a given * `fetch` event by returning a non-falsy value. * @param {workbox-routing~handlerCallback} handler A callback * function that returns a Promise resolving to a Response. * @param {string} [method='GET'] The HTTP method to match the Route * against. */ constructor(e, t, s = Z) { this.handler = L(t), this.match = e, this.method = s; } /** * * @param {workbox-routing-handlerCallback} handler A callback * function that returns a Promise resolving to a Response */ setCatchHandler(e) { this.catchHandler = L(e); } }, Ve = class extends k { /** * If the regular expression contains * [capture groups]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references}, * the captured values will be passed to the * {@link workbox-routing~handlerCallback} `params` * argument. * * @param {RegExp} regExp The regular expression to match against URLs. * @param {workbox-routing~handlerCallback} handler A callback * function that returns a Promise resulting in a Response. * @param {string} [method='GET'] The HTTP method to match the Route * against. */ constructor(e, t, s) { const r = ({ url: i }) => { const a = e.exec(i.href); if (a && !(i.origin !== location.origin && a.index !== 0)) return a.slice(1); }; super(r, t, s); } }, Ge = class { /** * Initializes a new Router. */ constructor() { this._routes = /* @__PURE__ */ new Map(), this._defaultHandlerMap = /* @__PURE__ */ new Map(); } /** * @return {Map>} routes A `Map` of HTTP * method name ('GET', etc.) to an array of all the corresponding `Route` * instances that are registered. */ get routes() { return this._routes; } /** * Adds a fetch event listener to respond to events when a route matches * the event's request. */ addFetchListener() { self.addEventListener("fetch", (e) => { const { request: t } = e, s = this.handleRequest({ request: t, event: e }); s && e.respondWith(s); }); } /** * Adds a message event listener for URLs to cache from the window. * This is useful to cache resources loaded on the page prior to when the * service worker started controlling it. * * The format of the message data sent from the window should be as follows. * Where the `urlsToCache` array may consist of URL strings or an array of * URL string + `requestInit` object (the same as you'd pass to `fetch()`). * * ``` * { * type: 'CACHE_URLS', * payload: { * urlsToCache: [ * './script1.js', * './script2.js', * ['./script3.js', {mode: 'no-cors'}], * ], * }, * } * ``` */ addCacheListener() { self.addEventListener("message", (e) => { if (e.data && e.data.type === "CACHE_URLS") { const { payload: t } = e.data, s = Promise.all(t.urlsToCache.map((r) => { typeof r == "string" && (r = [r]); const i = new Request(...r); return this.handleRequest({ request: i, event: e }); })); e.waitUntil(s), e.ports && e.ports[0] && s.then(() => e.ports[0].postMessage(!0)); } }); } /** * Apply the routing rules to a FetchEvent object to get a Response from an * appropriate Route's handler. * * @param {Object} options * @param {Request} options.request The request to handle. * @param {ExtendableEvent} options.event The event that triggered the * request. * @return {Promise|undefined} A promise is returned if a * registered route can handle the request. If there is no matching * route and there's no `defaultHandler`, `undefined` is returned. */ handleRequest({ request: e, event: t }) { const s = new URL(e.url, location.href); if (!s.protocol.startsWith("http")) return; const r = s.origin === location.origin, { params: i, route: a } = this.findMatchingRoute({ event: t, request: e, sameOrigin: r, url: s }); let c = a && a.handler; const o = e.method; if (!c && this._defaultHandlerMap.has(o) && (c = this._defaultHandlerMap.get(o)), !c) return; let l; try { l = c.handle({ url: s, request: e, event: t, params: i }); } catch (h) { l = Promise.reject(h); } const f = a && a.catchHandler; return l instanceof Promise && (this._catchHandler || f) && (l = l.catch(async (h) => { if (f) try { return await f.handle({ url: s, request: e, event: t, params: i }); } catch (y) { y instanceof Error && (h = y); } if (this._catchHandler) return this._catchHandler.handle({ url: s, request: e, event: t }); throw h; })), l; } /** * Checks a request and URL (and optionally an event) against the list of * registered routes, and if there's a match, returns the corresponding * route along with any params generated by the match. * * @param {Object} options * @param {URL} options.url * @param {boolean} options.sameOrigin The result of comparing `url.origin` * against the current origin. * @param {Request} options.request The request to match. * @param {Event} options.event The corresponding event. * @return {Object} An object with `route` and `params` properties. * They are populated if a matching route was found or `undefined` * otherwise. */ findMatchingRoute({ url: e, sameOrigin: t, request: s, event: r }) { const i = this._routes.get(s.method) || []; for (const a of i) { let c; const o = a.match({ url: e, sameOrigin: t, request: s, event: r }); if (o) return c = o, (Array.isArray(c) && c.length === 0 || o.constructor === Object && // eslint-disable-line Object.keys(o).length === 0 || typeof o == "boolean") && (c = void 0), { route: a, params: c }; } return {}; } /** * Define a default `handler` that's called when no routes explicitly * match the incoming request. * * Each HTTP method ('GET', 'POST', etc.) gets its own default handler. * * Without a default handler, unmatched requests will go against the * network as if there were no service worker present. * * @param {workbox-routing~handlerCallback} handler A callback * function that returns a Promise resulting in a Response. * @param {string} [method='GET'] The HTTP method to associate with this * default handler. Each method has its own default. */ setDefaultHandler(e, t = Z) { this._defaultHandlerMap.set(t, L(e)); } /** * If a Route throws an error while handling a request, this `handler` * will be called and given a chance to provide a response. * * @param {workbox-routing~handlerCallback} handler A callback * function that returns a Promise resulting in a Response. */ setCatchHandler(e) { this._catchHandler = L(e); } /** * Registers a route with the router. * * @param {workbox-routing.Route} route The route to register. */ registerRoute(e) { this._routes.has(e.method) || this._routes.set(e.method, []), this._routes.get(e.method).push(e); } /** * Unregisters a route with the router. * * @param {workbox-routing.Route} route The route to unregister. */ unregisterRoute(e) { if (!this._routes.has(e.method)) throw new u("unregister-route-but-not-found-with-method", { method: e.method }); const t = this._routes.get(e.method).indexOf(e); if (t > -1) this._routes.get(e.method).splice(t, 1); else throw new u("unregister-route-route-not-registered"); } }, C; const Qe = () => (C || (C = new Ge(), C.addFetchListener(), C.addCacheListener()), C); function ze(n, e, t) { let s; if (typeof n == "string") { const i = new URL(n, location.href), a = ({ url: c }) => c.href === i.href; s = new k(a, e, t); } else if (n instanceof RegExp) s = new Ve(n, e, t); else if (typeof n == "function") s = new k(n, e, t); else if (n instanceof k) s = n; else throw new u("unsupported-route-type", { moduleName: "workbox-routing", funcName: "registerRoute", paramName: "capture" }); return Qe().registerRoute(s), s; } function Je(n, e = []) { for (const t of [...n.searchParams.keys()]) e.some((s) => s.test(t)) && n.searchParams.delete(t); return n; } function* Xe(n, { ignoreURLParametersMatching: e = [/^utm_/, /^fbclid$/], directoryIndex: t = "index.html", cleanURLs: s = !0, urlManipulation: r } = {}) { const i = new URL(n, location.href); i.hash = "", yield i.href; const a = Je(i, e); if (yield a.href, t && a.pathname.endsWith("/")) { const c = new URL(a.href); c.pathname += t, yield c.href; } if (s) { const c = new URL(a.href); c.pathname += ".html", yield c.href; } if (r) { const c = r({ url: i }); for (const o of c) yield o.href; } } class Ye extends k { /** * @param {PrecacheController} precacheController A `PrecacheController` * instance used to both match requests and respond to fetch events. * @param {Object} [options] Options to control how requests are matched * against the list of precached URLs. * @param {string} [options.directoryIndex=index.html] The `directoryIndex` will * check cache entries for a URLs ending with '/' to see if there is a hit when * appending the `directoryIndex` value. * @param {Array} [options.ignoreURLParametersMatching=[/^utm_/, /^fbclid$/]] An * array of regex's to remove search params when looking for a cache match. * @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will * check the cache for the URL with a `.html` added to the end of the end. * @param {workbox-precaching~urlManipulation} [options.urlManipulation] * This is a function that should take a URL and return an array of * alternative URLs that should be checked for precache matches. */ constructor(e, t) { const s = ({ request: r }) => { const i = e.getURLsToCacheKeys(); for (const a of Xe(r.url, t)) { const c = i.get(a); if (c) { const o = e.getIntegrityForCacheKey(c); return { cacheKey: c, integrity: o }; } } }; super(s, e.strategy); } } function Ze(n) { const e = W(), t = new Ye(e, n); ze(t); } function et(n) { return W().createHandlerBoundToURL(n); } function tt(n) { W().precache(n); } function st(n, e) { tt(n), Ze(e); } try { self["workbox:routing:6.5.3"] && _(); } catch { } const ee = "GET", v = (n) => n && typeof n == "object" ? n : { handle: n }; class U { /** * Constructor for Route class. * * @param {workbox-routing~matchCallback} match * A callback function that determines whether the route matches a given * `fetch` event by returning a non-falsy value. * @param {workbox-routing~handlerCallback} handler A callback * function that returns a Promise resolving to a Response. * @param {string} [method='GET'] The HTTP method to match the Route * against. */ constructor(e, t, s = ee) { this.handler = v(t), this.match = e, this.method = s; } /** * * @param {workbox-routing-handlerCallback} handler A callback * function that returns a Promise resolving to a Response */ setCatchHandler(e) { this.catchHandler = v(e); } } class nt extends U { /** * If the regular expression contains * [capture groups]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references}, * the captured values will be passed to the * {@link workbox-routing~handlerCallback} `params` * argument. * * @param {RegExp} regExp The regular expression to match against URLs. * @param {workbox-routing~handlerCallback} handler A callback * function that returns a Promise resulting in a Response. * @param {string} [method='GET'] The HTTP method to match the Route * against. */ constructor(e, t, s) { const r = ({ url: i }) => { const a = e.exec(i.href); if (a && !(i.origin !== location.origin && a.index !== 0)) return a.slice(1); }; super(r, t, s); } } class rt { /** * Initializes a new Router. */ constructor() { this._routes = /* @__PURE__ */ new Map(), this._defaultHandlerMap = /* @__PURE__ */ new Map(); } /** * @return {Map>} routes A `Map` of HTTP * method name ('GET', etc.) to an array of all the corresponding `Route` * instances that are registered. */ get routes() { return this._routes; } /** * Adds a fetch event listener to respond to events when a route matches * the event's request. */ addFetchListener() { self.addEventListener("fetch", (e) => { const { request: t } = e, s = this.handleRequest({ request: t, event: e }); s && e.respondWith(s); }); } /** * Adds a message event listener for URLs to cache from the window. * This is useful to cache resources loaded on the page prior to when the * service worker started controlling it. * * The format of the message data sent from the window should be as follows. * Where the `urlsToCache` array may consist of URL strings or an array of * URL string + `requestInit` object (the same as you'd pass to `fetch()`). * * ``` * { * type: 'CACHE_URLS', * payload: { * urlsToCache: [ * './script1.js', * './script2.js', * ['./script3.js', {mode: 'no-cors'}], * ], * }, * } * ``` */ addCacheListener() { self.addEventListener("message", (e) => { if (e.data && e.data.type === "CACHE_URLS") { const { payload: t } = e.data, s = Promise.all(t.urlsToCache.map((r) => { typeof r == "string" && (r = [r]); const i = new Request(...r); return this.handleRequest({ request: i, event: e }); })); e.waitUntil(s), e.ports && e.ports[0] && s.then(() => e.ports[0].postMessage(!0)); } }); } /** * Apply the routing rules to a FetchEvent object to get a Response from an * appropriate Route's handler. * * @param {Object} options * @param {Request} options.request The request to handle. * @param {ExtendableEvent} options.event The event that triggered the * request. * @return {Promise|undefined} A promise is returned if a * registered route can handle the request. If there is no matching * route and there's no `defaultHandler`, `undefined` is returned. */ handleRequest({ request: e, event: t }) { const s = new URL(e.url, location.href); if (!s.protocol.startsWith("http")) return; const r = s.origin === location.origin, { params: i, route: a } = this.findMatchingRoute({ event: t, request: e, sameOrigin: r, url: s }); let c = a && a.handler; const o = e.method; if (!c && this._defaultHandlerMap.has(o) && (c = this._defaultHandlerMap.get(o)), !c) return; let l; try { l = c.handle({ url: s, request: e, event: t, params: i }); } catch (h) { l = Promise.reject(h); } const f = a && a.catchHandler; return l instanceof Promise && (this._catchHandler || f) && (l = l.catch(async (h) => { if (f) try { return await f.handle({ url: s, request: e, event: t, params: i }); } catch (y) { y instanceof Error && (h = y); } if (this._catchHandler) return this._catchHandler.handle({ url: s, request: e, event: t }); throw h; })), l; } /** * Checks a request and URL (and optionally an event) against the list of * registered routes, and if there's a match, returns the corresponding * route along with any params generated by the match. * * @param {Object} options * @param {URL} options.url * @param {boolean} options.sameOrigin The result of comparing `url.origin` * against the current origin. * @param {Request} options.request The request to match. * @param {Event} options.event The corresponding event. * @return {Object} An object with `route` and `params` properties. * They are populated if a matching route was found or `undefined` * otherwise. */ findMatchingRoute({ url: e, sameOrigin: t, request: s, event: r }) { const i = this._routes.get(s.method) || []; for (const a of i) { let c; const o = a.match({ url: e, sameOrigin: t, request: s, event: r }); if (o) return c = o, (Array.isArray(c) && c.length === 0 || o.constructor === Object && // eslint-disable-line Object.keys(o).length === 0 || typeof o == "boolean") && (c = void 0), { route: a, params: c }; } return {}; } /** * Define a default `handler` that's called when no routes explicitly * match the incoming request. * * Each HTTP method ('GET', 'POST', etc.) gets its own default handler. * * Without a default handler, unmatched requests will go against the * network as if there were no service worker present. * * @param {workbox-routing~handlerCallback} handler A callback * function that returns a Promise resulting in a Response. * @param {string} [method='GET'] The HTTP method to associate with this * default handler. Each method has its own default. */ setDefaultHandler(e, t = ee) { this._defaultHandlerMap.set(t, v(e)); } /** * If a Route throws an error while handling a request, this `handler` * will be called and given a chance to provide a response. * * @param {workbox-routing~handlerCallback} handler A callback * function that returns a Promise resulting in a Response. */ setCatchHandler(e) { this._catchHandler = v(e); } /** * Registers a route with the router. * * @param {workbox-routing.Route} route The route to register. */ registerRoute(e) { this._routes.has(e.method) || this._routes.set(e.method, []), this._routes.get(e.method).push(e); } /** * Unregisters a route with the router. * * @param {workbox-routing.Route} route The route to unregister. */ unregisterRoute(e) { if (!this._routes.has(e.method)) throw new w("unregister-route-but-not-found-with-method", { method: e.method }); const t = this._routes.get(e.method).indexOf(e); if (t > -1) this._routes.get(e.method).splice(t, 1); else throw new w("unregister-route-route-not-registered"); } } let x; const at = () => (x || (x = new rt(), x.addFetchListener(), x.addCacheListener()), x); function te(n, e, t) { let s; if (typeof n == "string") { const i = new URL(n, location.href), a = ({ url: c }) => c.href === i.href; s = new U(a, e, t); } else if (n instanceof RegExp) s = new nt(n, e, t); else if (typeof n == "function") s = new U(n, e, t); else if (n instanceof U) s = n; else throw new w("unsupported-route-type", { moduleName: "workbox-routing", funcName: "registerRoute", paramName: "capture" }); return at().registerRoute(s), s; } try { self["workbox:strategies:6.5.3"] && _(); } catch { } function D(n) { return typeof n == "string" ? new Request(n) : n; } class it { /** * Creates a new instance associated with the passed strategy and event * that's handling the request. * * The constructor also initializes the state that will be passed to each of * the plugins handling this request. * * @param {workbox-strategies.Strategy} strategy * @param {Object} options * @param {Request|string} options.request A request to run this strategy for. * @param {ExtendableEvent} options.event The event associated with the * request. * @param {URL} [options.url] * @param {*} [options.params] The return value from the * {@link workbox-routing~matchCallback} (if applicable). */ constructor(e, t) { this._cacheKeys = {}, Object.assign(this, t), this.event = t.event, this._strategy = e, this._handlerDeferred = new ce(), this._extendLifetimePromises = [], this._plugins = [...e.plugins], this._pluginStateMap = /* @__PURE__ */ new Map(); for (const s of this._plugins) this._pluginStateMap.set(s, {}); this.event.waitUntil(this._handlerDeferred.promise); } /** * Fetches a given request (and invokes any applicable plugin callback * methods) using the `fetchOptions` (for non-navigation requests) and * `plugins` defined on the `Strategy` object. * * The following plugin lifecycle methods are invoked when using this method: * - `requestWillFetch()` * - `fetchDidSucceed()` * - `fetchDidFail()` * * @param {Request|string} input The URL or request to fetch. * @return {Promise} */ async fetch(e) { const { event: t } = this; let s = D(e); if (s.mode === "navigate" && t instanceof FetchEvent && t.preloadResponse) { const a = await t.preloadResponse; if (a) return a; } const r = this.hasCallback("fetchDidFail") ? s.clone() : null; try { for (const a of this.iterateCallbacks("requestWillFetch")) s = await a({ request: s.clone(), event: t }); } catch (a) { if (a instanceof Error) throw new w("plugin-error-request-will-fetch", { thrownErrorMessage: a.message }); } const i = s.clone(); try { let a; a = await fetch(s, s.mode === "navigate" ? void 0 : this._strategy.fetchOptions); for (const c of this.iterateCallbacks("fetchDidSucceed")) a = await c({ event: t, request: i, response: a }); return a; } catch (a) { throw r && await this.runCallbacks("fetchDidFail", { error: a, event: t, originalRequest: r.clone(), request: i.clone() }), a; } } /** * Calls `this.fetch()` and (in the background) runs `this.cachePut()` on * the response generated by `this.fetch()`. * * The call to `this.cachePut()` automatically invokes `this.waitUntil()`, * so you do not have to manually call `waitUntil()` on the event. * * @param {Request|string} input The request or URL to fetch and cache. * @return {Promise} */ async fetchAndCachePut(e) { const t = await this.fetch(e), s = t.clone(); return this.waitUntil(this.cachePut(e, s)), t; } /** * Matches a request from the cache (and invokes any applicable plugin * callback methods) using the `cacheName`, `matchOptions`, and `plugins` * defined on the strategy object. * * The following plugin lifecycle methods are invoked when using this method: * - cacheKeyWillByUsed() * - cachedResponseWillByUsed() * * @param {Request|string} key The Request or URL to use as the cache key. * @return {Promise} A matching response, if found. */ async cacheMatch(e) { const t = D(e); let s; const { cacheName: r, matchOptions: i } = this._strategy, a = await this.getCacheKey(t, "read"), c = Object.assign(Object.assign({}, i), { cacheName: r }); s = await caches.match(a, c); for (const o of this.iterateCallbacks("cachedResponseWillBeUsed")) s = await o({ cacheName: r, matchOptions: i, cachedResponse: s, request: a, event: this.event }) || void 0; return s; } /** * Puts a request/response pair in the cache (and invokes any applicable * plugin callback methods) using the `cacheName` and `plugins` defined on * the strategy object. * * The following plugin lifecycle methods are invoked when using this method: * - cacheKeyWillByUsed() * - cacheWillUpdate() * - cacheDidUpdate() * * @param {Request|string} key The request or URL to use as the cache key. * @param {Response} response The response to cache. * @return {Promise} `false` if a cacheWillUpdate caused the response * not be cached, and `true` otherwise. */ async cachePut(e, t) { const s = D(e); await he(0); const r = await this.getCacheKey(s, "write"); if (!t) throw new w("cache-put-with-no-response", { url: le(r.url) }); const i = await this._ensureResponseSafeToCache(t); if (!i) return !1; const { cacheName: a, matchOptions: c } = this._strategy, o = await self.caches.open(a), l = this.hasCallback("cacheDidUpdate"), f = l ? await ie( // TODO(philipwalton): the `__WB_REVISION__` param is a precaching // feature. Consider into ways to only add this behavior if using // precaching. o, r.clone(), ["__WB_REVISION__"], c ) : null; try { await o.put(r, l ? i.clone() : i); } catch (h) { if (h instanceof Error) throw h.name === "QuotaExceededError" && await oe(), h; } for (const h of this.iterateCallbacks("cacheDidUpdate")) await h({ cacheName: a, oldResponse: f, newResponse: i.clone(), request: r, event: this.event }); return !0; } /** * Checks the list of plugins for the `cacheKeyWillBeUsed` callback, and * executes any of those callbacks found in sequence. The final `Request` * object returned by the last plugin is treated as the cache key for cache * reads and/or writes. If no `cacheKeyWillBeUsed` plugin callbacks have * been registered, the passed request is returned unmodified * * @param {Request} request * @param {string} mode * @return {Promise} */ async getCacheKey(e, t) { const s = `${e.url} | ${t}`; if (!this._cacheKeys[s]) { let r = e; for (const i of this.iterateCallbacks("cacheKeyWillBeUsed")) r = D(await i({ mode: t, request: r, event: this.event, // params has a type any can't change right now. params: this.params // eslint-disable-line })); this._cacheKeys[s] = r; } return this._cacheKeys[s]; } /** * Returns true if the strategy has at least one plugin with the given * callback. * * @param {string} name The name of the callback to check for. * @return {boolean} */ hasCallback(e) { for (const t of this._strategy.plugins) if (e in t) return !0; return !1; } /** * Runs all plugin callbacks matching the given name, in order, passing the * given param object (merged ith the current plugin state) as the only * argument. * * Note: since this method runs all plugins, it's not suitable for cases * where the return value of a callback needs to be applied prior to calling * the next callback. See * {@link workbox-strategies.StrategyHandler#iterateCallbacks} * below for how to handle that case. * * @param {string} name The name of the callback to run within each plugin. * @param {Object} param The object to pass as the first (and only) param * when executing each callback. This object will be merged with the * current plugin state prior to callback execution. */ async runCallbacks(e, t) { for (const s of this.iterateCallbacks(e)) await s(t); } /** * Accepts a callback and returns an iterable of matching plugin callbacks, * where each callback is wrapped with the current handler state (i.e. when * you call each callback, whatever object parameter you pass it will * be merged with the plugin's current state). * * @param {string} name The name fo the callback to run * @return {Array} */ *iterateCallbacks(e) { for (const t of this._strategy.plugins) if (typeof t[e] == "function") { const s = this._pluginStateMap.get(t); yield (i) => { const a = Object.assign(Object.assign({}, i), { state: s }); return t[e](a); }; } } /** * Adds a promise to the * [extend lifetime promises]{@link https://w3c.github.io/ServiceWorker/#extendableevent-extend-lifetime-promises} * of the event event associated with the request being handled (usually a * `FetchEvent`). * * Note: you can await * {@link workbox-strategies.StrategyHandler~doneWaiting} * to know when all added promises have settled. * * @param {Promise} promise A promise to add to the extend lifetime promises * of the event that triggered the request. */ waitUntil(e) { return this._extendLifetimePromises.push(e), e; } /** * Returns a promise that resolves once all promises passed to * {@link workbox-strategies.StrategyHandler~waitUntil} * have settled. * * Note: any work done after `doneWaiting()` settles should be manually * passed to an event's `waitUntil()` method (not this handler's * `waitUntil()` method), otherwise the service worker thread my be killed * prior to your work completing. */ async doneWaiting() { let e; for (; e = this._extendLifetimePromises.shift(); ) await e; } /** * Stops running the strategy and immediately resolves any pending * `waitUntil()` promises. */ destroy() { this._handlerDeferred.resolve(null); } /** * This method will call cacheWillUpdate on the available plugins (or use * status === 200) to determine if the Response is safe and valid to cache. * * @param {Request} options.request * @param {Response} options.response * @return {Promise} * * @private */ async _ensureResponseSafeToCache(e) { let t = e, s = !1; for (const r of this.iterateCallbacks("cacheWillUpdate")) if (t = await r({ request: this.request, response: t, event: this.event }) || void 0, s = !0, !t) break; return s || t && t.status !== 200 && (t = void 0), t; } } class ct { /** * Creates a new instance of the strategy and sets all documented option * properties as public instance properties. * * Note: if a custom strategy class extends the base Strategy class and does * not need more than these properties, it does not need to define its own * constructor. * * @param {Object} [options] * @param {string} [options.cacheName] Cache name to store and retrieve * requests. Defaults to the cache names provided by * {@link workbox-core.cacheNames}. * @param {Array} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} * to use in conjunction with this caching strategy. * @param {Object} [options.fetchOptions] Values passed along to the * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) * of [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796) * `fetch()` requests made by this strategy. * @param {Object} [options.matchOptions] The * [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions} * for any `cache.match()` or `cache.put()` calls made by this strategy. */ constructor(e = {}) { this.cacheName = z.getRuntimeName(e.cacheName), this.plugins = e.plugins || [], this.fetchOptions = e.fetchOptions, this.matchOptions = e.matchOptions; } /** * Perform a request strategy and returns a `Promise` that will resolve with * a `Response`, invoking all relevant plugin callbacks. * * When a strategy instance is registered with a Workbox * {@link workbox-routing.Route}, this method is automatically * called when the route matches. * * Alternatively, this method can be used in a standalone `FetchEvent` * listener by passing it to `event.respondWith()`. * * @param {FetchEvent|Object} options A `FetchEvent` or an object with the * properties listed below. * @param {Request|string} options.request A request to run this strategy for. * @param {ExtendableEvent} options.event The event associated with the * request. * @param {URL} [options.url] * @param {*} [options.params] */ handle(e) { const [t] = this.handleAll(e); return t; } /** * Similar to {@link workbox-strategies.Strategy~handle}, but * instead of just returning a `Promise` that resolves to a `Response` it * it will return an tuple of `[response, done]` promises, where the former * (`response`) is equivalent to what `handle()` returns, and the latter is a * Promise that will resolve once any promises that were added to * `event.waitUntil()` as part of performing the strategy have completed. * * You can await the `done` promise to ensure any extra work performed by * the strategy (usually caching responses) completes successfully. * * @param {FetchEvent|Object} options A `FetchEvent` or an object with the * properties listed below. * @param {Request|string} options.request A request to run this strategy for. * @param {ExtendableEvent} options.event The event associated with the * request. * @param {URL} [options.url] * @param {*} [options.params] * @return {Array} A tuple of [response, done] * promises that can be used to determine when the response resolves as * well as when the handler has completed all its work. */ handleAll(e) { e instanceof FetchEvent && (e = { event: e, request: e.request }); const t = e.event, s = typeof e.request == "string" ? new Request(e.request) : e.request, r = "params" in e ? e.params : void 0, i = new it(this, { event: t, request: s, params: r }), a = this._getResponse(i, s, t), c = this._awaitComplete(a, i, s, t); return [a, c]; } async _getResponse(e, t, s) { await e.runCallbacks("handlerWillStart", { event: s, request: t }); let r; try { if (r = await this._handle(t, e), !r || r.type === "error") throw new w("no-response", { url: t.url }); } catch (i) { if (i instanceof Error) { for (const a of e.iterateCallbacks("handlerDidError")) if (r = await a({ error: i, event: s, request: t }), r) break; } if (!r) throw i; } for (const i of e.iterateCallbacks("handlerWillRespond")) r = await i({ event: s, request: t, response: r }); return r; } async _awaitComplete(e, t, s, r) { let i, a; try { i = await e; } catch { } try { await t.runCallbacks("handlerDidRespond", { event: r, request: s, response: i }), await t.doneWaiting(); } catch (c) { c instanceof Error && (a = c); } if (await t.runCallbacks("handlerDidComplete", { event: r, request: s, response: i, error: a }), t.destroy(), a) throw a; } } const ot = { /** * Returns a valid response (to allow caching) if the status is 200 (OK) or * 0 (opaque). * * @param {Object} options * @param {Response} options.response * @return {Response|null} * * @private */ cacheWillUpdate: async ({ response: n }) => n.status === 200 || n.status === 0 ? n : null }; class lt extends ct { /** * @param {Object} [options] * @param {string} [options.cacheName] Cache name to store and retrieve * requests. Defaults to cache names provided by * {@link workbox-core.cacheNames}. * @param {Array} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} * to use in conjunction with this caching strategy. * @param {Object} [options.fetchOptions] Values passed along to the * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) * of [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796) * `fetch()` requests made by this strategy. * @param {Object} [options.matchOptions] [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions) */ constructor(e = {}) { super(e), this.plugins.some((t) => "cacheWillUpdate" in t) || this.plugins.unshift(ot); } /** * @private * @param {Request|string} request A request to run this strategy for. * @param {workbox-strategies.StrategyHandler} handler The event that * triggered the request. * @return {Promise} */ async _handle(e, t) { const s = t.fetchAndCachePut(e).catch(() => { }); t.waitUntil(s); let r = await t.cacheMatch(e), i; if (!r) try { r = await s; } catch (a) { a instanceof Error && (i = a); } if (!r) throw new w("no-response", { url: e.url, error: i }); return r; } } const ht = "shlink-web-client", ut = "A React-based progressive web application for shlink", ft = "/shlink-web-client/dependabot/npm_and_yarn/workbox-precaching-7.0.0", dt = "https://github.com/shlinkio/shlink-web-client", pt = "MIT", gt = { lint: "npm run lint:css && npm run lint:js", "lint:css": "stylelint src/*.scss src/**/*.scss", "lint:js": "eslint --ext .js,.ts,.tsx src test", "lint:fix": "npm run lint:css:fix && npm run lint:js:fix", "lint:css:fix": "npm run lint:css -- --fix", "lint:js:fix": "npm run lint:js -- --fix", types: "tsc", start: "vite serve --host=0.0.0.0", preview: "vite preview --host=0.0.0.0", build: "npm run types && vite build && node scripts/replace-version.mjs", "build:dist": "npm run build && node scripts/create-dist-file.mjs", test: "vitest run --run", "test:watch": "vitest --watch", "test:ci": "npm run test -- --coverage", "test:verbose": "npm run test -- --verbose" }, mt = { "@fortawesome/fontawesome-free": "^6.4.2", "@fortawesome/fontawesome-svg-core": "^6.4.2", "@fortawesome/free-brands-svg-icons": "^6.4.2", "@fortawesome/free-regular-svg-icons": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.2", "@fortawesome/react-fontawesome": "^0.2.0", "@json2csv/plainjs": "^7.0.1", "@reduxjs/toolkit": "^1.9.5", "@shlinkio/shlink-frontend-kit": "^0.2.0", "@shlinkio/shlink-web-component": "^0.3.0", bootstrap: "5.2.3", bottlejs: "^2.0.1", classnames: "^2.3.2", "compare-versions": "^6.1.0", csvtojson: "^2.0.10", "date-fns": "^2.30.0", ramda: "^0.27.2", react: "^18.2.0", "react-dom": "^18.2.0", "react-external-link": "^2.2.0", "react-redux": "^8.1.2", "react-router-dom": "^6.14.2", reactstrap: "^9.2.0", "redux-localstorage-simple": "^2.5.1", uuid: "^9.0.0", "workbox-core": "^6.5.4", "workbox-expiration": "^6.5.4", "workbox-precaching": "^7.0.0", "workbox-routing": "^6.5.4", "workbox-strategies": "^6.5.4" }, wt = { "@shlinkio/eslint-config-js-coding-standard": "~2.2.0", "@shlinkio/stylelint-config-css-coding-standard": "~1.1.1", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", "@total-typescript/shoehorn": "^0.1.1", "@types/leaflet": "^1.9.3", "@types/ramda": "^0.27.66", "@types/react": "^18.2.19", "@types/react-dom": "^18.2.7", "@types/uuid": "^9.0.2", "@vitejs/plugin-react": "^4.0.4", "@vitest/coverage-v8": "^0.34.1", "adm-zip": "^0.5.10", chalk: "^5.3.0", eslint: "^8.46.0", history: "^5.3.0", jsdom: "^22.1.0", sass: "^1.64.2", stylelint: "^15.10.2", typescript: "^5.1.6", vite: "^4.4.9", "vite-plugin-pwa": "^0.16.4", vitest: "^0.34.1" }, yt = [ ">0.2%", "not dead", "not ie <= 11", "not op_mini all" ], bt = { name: ht, description: ut, private: !1, homepage: ft, repository: dt, license: pt, scripts: gt, dependencies: mt, devDependencies: wt, browserslist: yt }; ue(); st([{"revision":null,"url":"assets/index-0e8ab544.css"},{"revision":null,"url":"assets/index-2938603d.js"},{"revision":"cbb744bc91b3e31d91c3505ace6239b0","url":"index.html"},{"revision":"3e8169a112865ef0d76bba4e2dfd3a89","url":"./icons/icon-16x16.png"},{"revision":"20f0b51945ae3c973420e31d6b4d43c1","url":"./icons/icon-24x24.png"},{"revision":"4c9695cfb4cea403c1b66bbb7b4f7420","url":"./icons/icon-32x32.png"},{"revision":"f74edb9cc54ac938c1589876f8da9f21","url":"./icons/icon-40x40.png"},{"revision":"52933970fac8498311687de13549b014","url":"./icons/icon-48x48.png"},{"revision":"40209a194f29b21882571c77bd2bd906","url":"./icons/icon-60x60.png"},{"revision":"c8ba5a8c1da76d74c7bb21827fcf975c","url":"./icons/icon-64x64.png"},{"revision":"ae3435baceb494f9c966e2c2c736ea35","url":"./icons/icon-72x72.png"},{"revision":"850aa5b026fd1452af6c1ddd9d71850f","url":"./icons/icon-76x76.png"},{"revision":"8c62535e6b7a498ece1f6c6ae62ede59","url":"./icons/icon-96x96.png"},{"revision":"2dff586aaefa4c8d17f4c0bcbdef8b53","url":"./icons/icon-114x114.png"},{"revision":"8e28257a68ef1c55bc68bfff80e1a310","url":"./icons/icon-120x120.png"},{"revision":"0059b6f0c97fa871a5c29643b2857585","url":"./icons/icon-128x128.png"},{"revision":"41478c2456281f61e54d714718743ecc","url":"./icons/icon-144x144.png"},{"revision":"625251910295f33a578ae6d8117711c9","url":"./icons/icon-150x150.png"},{"revision":"19b71508b1d05defe32cf16a7d453001","url":"./icons/icon-152x152.png"},{"revision":"9d029a32a54ba3084c67acd5d74f8ac4","url":"./icons/icon-160x160.png"},{"revision":"6ec104aeaf745f003ecdaef2edddce97","url":"./icons/icon-167x167.png"},{"revision":"871d67907434ed0ddf5d2a6c220e09af","url":"./icons/icon-180x180.png"},{"revision":"cee2529402074d73b2135e2ddee25f6b","url":"./icons/icon-192x192.png"},{"revision":"85055b452284c0193142936dee7d2cd1","url":"./icons/icon-196x196.png"},{"revision":"f471155dd70b99924422dd9dd87ea94d","url":"./icons/icon-228x228.png"},{"revision":"4d896c5c7025582605de31fb74f0316b","url":"./icons/icon-256x256.png"},{"revision":"d99b49e5bcad41968313c3e132e7c661","url":"./icons/icon-310x310.png"},{"revision":"f9597636bef677327c3abc0fd1a743c4","url":"./icons/icon-384x384.png"},{"revision":"de22c0eb9e08d3576df5cedb568ca56b","url":"./icons/icon-512x512.png"},{"revision":"583b223ad8e20f05aaa64923d7db2e46","url":"./icons/icon-1024x1024.png"},{"revision":"6b5a0832d130ea1a7df59fc314dac241","url":"manifest.json"}]); const _t = new RegExp("/[^/?]+\\.[^/]+$"); te( // Return false to exempt requests from being fulfilled by index.html. ({ request: n, url: e }) => !(n.mode !== "navigate" || e.pathname.startsWith("/_") || e.pathname.match(_t)), et(`${bt.homepage}/index.html`) ); te( // Add in any other file extensions or routing criteria as needed. ({ url: n }) => n.origin === self.location.origin && n.pathname.endsWith(".png"), // Customize this strategy as needed, e.g., by changing to CacheFirst. new lt({ cacheName: "images", plugins: [ // Ensure that once this runtime cache reaches a maximum size the // least-recently used images are removed. new Ue({ maxEntries: 50 }) ] }) ); self.addEventListener("message", (n) => { n.data && n.data.type === "SKIP_WAITING" && self.skipWaiting(); });