shlink-web-client/dependabot/npm_and_yarn/shlink-ad52743a18/service-worker.js

1821 lines
64 KiB
JavaScript
Raw Normal View History

try {
self["workbox:core:7.0.0"] && _();
} catch {
}
const G = (s, ...e) => {
let t = s;
return e.length > 0 && (t += ` :: ${JSON.stringify(e)}`), t;
}, Q = G;
class h 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 n = Q(e, t);
super(n), this.name = e, this.details = t;
}
}
const B = /* @__PURE__ */ new Set();
function z(s) {
B.add(s);
}
const d = {
googleAnalytics: "googleAnalytics",
precache: "precache-v2",
prefix: "workbox",
runtime: "runtime",
suffix: typeof registration < "u" ? registration.scope : ""
}, k = (s) => [d.prefix, s, d.suffix].filter((e) => e && e.length > 0).join("-"), J = (s) => {
for (const e of Object.keys(d))
s(e);
}, x = {
updateDetails: (s) => {
J((e) => {
typeof s[e] == "string" && (d[e] = s[e]);
});
},
getGoogleAnalyticsName: (s) => s || k(d.googleAnalytics),
getPrecacheName: (s) => s || k(d.precache),
getPrefix: () => d.prefix,
getRuntimeName: (s) => s || k(d.runtime),
getSuffix: () => d.suffix
};
function K(s, e) {
const t = new URL(s);
for (const n of e)
t.searchParams.delete(n);
return t.href;
}
async function X(s, e, t, n) {
const a = K(e.url, t);
if (e.url === a)
return s.match(e, n);
const r = Object.assign(Object.assign({}, n), { ignoreSearch: !0 }), i = await s.keys(e, r);
for (const c of i) {
const o = K(c.url, t);
if (a === o)
return s.match(c, n);
}
}
let m;
function Y() {
if (m === void 0) {
const s = new Response("");
if ("body" in s)
try {
new Response(s.body), m = !0;
} catch {
m = !1;
}
m = !1;
}
return m;
}
function q(s) {
s.then(() => {
});
}
class Z {
/**
* 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 ee() {
for (const s of B)
await s();
}
const te = (s) => new URL(String(s), location.href).href.replace(new RegExp(`^${location.origin}`), "");
function se(s) {
return new Promise((e) => setTimeout(e, s));
}
function A(s, e) {
const t = e();
return s.waitUntil(t), t;
}
async function ne(s, e) {
let t = null;
if (s.url && (t = new URL(s.url).origin), t !== self.location.origin)
throw new h("cross-origin-copy-response", { origin: t });
const n = s.clone(), a = {
headers: new Headers(n.headers),
status: n.status,
statusText: n.statusText
}, r = e ? e(a) : a, i = Y() ? n.body : await n.blob();
return new Response(i, r);
}
function ae() {
self.addEventListener("activate", () => self.clients.claim());
}
const re = (s, e) => e.some((t) => s instanceof t);
let j, O;
function ie() {
return j || (j = [
IDBDatabase,
IDBObjectStore,
IDBIndex,
IDBCursor,
IDBTransaction
]);
}
function ce() {
return O || (O = [
IDBCursor.prototype.advance,
IDBCursor.prototype.continue,
IDBCursor.prototype.continuePrimaryKey
]);
}
const F = /* @__PURE__ */ new WeakMap(), U = /* @__PURE__ */ new WeakMap(), H = /* @__PURE__ */ new WeakMap(), E = /* @__PURE__ */ new WeakMap(), P = /* @__PURE__ */ new WeakMap();
function oe(s) {
const e = new Promise((t, n) => {
const a = () => {
s.removeEventListener("success", r), s.removeEventListener("error", i);
}, r = () => {
t(f(s.result)), a();
}, i = () => {
n(s.error), a();
};
s.addEventListener("success", r), s.addEventListener("error", i);
});
return e.then((t) => {
t instanceof IDBCursor && F.set(t, s);
}).catch(() => {
}), P.set(e, s), e;
}
function le(s) {
if (U.has(s))
return;
const e = new Promise((t, n) => {
const a = () => {
s.removeEventListener("complete", r), s.removeEventListener("error", i), s.removeEventListener("abort", i);
}, r = () => {
t(), a();
}, i = () => {
n(s.error || new DOMException("AbortError", "AbortError")), a();
};
s.addEventListener("complete", r), s.addEventListener("error", i), s.addEventListener("abort", i);
});
U.set(s, e);
}
let T = {
get(s, e, t) {
if (s instanceof IDBTransaction) {
if (e === "done")
return U.get(s);
if (e === "objectStoreNames")
return s.objectStoreNames || H.get(s);
if (e === "store")
return t.objectStoreNames[1] ? void 0 : t.objectStore(t.objectStoreNames[0]);
}
return f(s[e]);
},
set(s, e, t) {
return s[e] = t, !0;
},
has(s, e) {
return s instanceof IDBTransaction && (e === "done" || e === "store") ? !0 : e in s;
}
};
function he(s) {
T = s(T);
}
function ue(s) {
return s === IDBDatabase.prototype.transaction && !("objectStoreNames" in IDBTransaction.prototype) ? function(e, ...t) {
const n = s.call(v(this), e, ...t);
return H.set(n, e.sort ? e.sort() : [e]), f(n);
} : ce().includes(s) ? function(...e) {
return s.apply(v(this), e), f(F.get(this));
} : function(...e) {
return f(s.apply(v(this), e));
};
}
function de(s) {
return typeof s == "function" ? ue(s) : (s instanceof IDBTransaction && le(s), re(s, ie()) ? new Proxy(s, T) : s);
}
function f(s) {
if (s instanceof IDBRequest)
return oe(s);
if (E.has(s))
return E.get(s);
const e = de(s);
return e !== s && (E.set(s, e), P.set(e, s)), e;
}
const v = (s) => P.get(s);
function fe(s, e, { blocked: t, upgrade: n, blocking: a, terminated: r } = {}) {
const i = indexedDB.open(s, e), c = f(i);
return n && i.addEventListener("upgradeneeded", (o) => {
n(f(i.result), o.oldVersion, o.newVersion, f(i.transaction), o);
}), t && i.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) => {
r && o.addEventListener("close", () => r()), a && o.addEventListener("versionchange", (l) => a(l.oldVersion, l.newVersion, l));
}).catch(() => {
}), c;
}
function pe(s, { blocked: e } = {}) {
const t = indexedDB.deleteDatabase(s);
return e && t.addEventListener("blocked", (n) => e(
// Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
n.oldVersion,
n
)), f(t).then(() => {
});
}
const ge = ["get", "getKey", "getAll", "getAllKeys", "count"], me = ["put", "add", "delete", "clear"], D = /* @__PURE__ */ new Map();
function S(s, e) {
if (!(s instanceof IDBDatabase && !(e in s) && typeof e == "string"))
return;
if (D.get(e))
return D.get(e);
const t = e.replace(/FromIndex$/, ""), n = e !== t, a = me.includes(t);
if (
// Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
!(t in (n ? IDBIndex : IDBObjectStore).prototype) || !(a || ge.includes(t))
)
return;
const r = async function(i, ...c) {
const o = this.transaction(i, a ? "readwrite" : "readonly");
let l = o.store;
return n && (l = l.index(c.shift())), (await Promise.all([
l[t](...c),
a && o.done
]))[0];
};
return D.set(e, r), r;
}
he((s) => ({
...s,
get: (e, t, n) => S(e, t) || s.get(e, t, n),
has: (e, t) => !!S(e, t) || s.has(e, t)
}));
try {
self["workbox:expiration:7.0.0"] && _();
} catch {
}
const we = "workbox-expiration", w = "cache-entries", W = (s) => {
const e = new URL(s, location.href);
return e.hash = "", e.href;
};
class ye {
/**
*
* @param {string} cacheName
*
* @private
*/
constructor(e) {
this._db = null, this._cacheName = e;
}
/**
* Performs an upgrade of indexedDB.
*
* @param {IDBPDatabase<CacheDbSchema>} db
*
* @private
*/
_upgradeDb(e) {
const t = e.createObjectStore(w, { 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<CacheDbSchema>} db
*
* @private
*/
_upgradeDbAndDeleteOldDbs(e) {
this._upgradeDb(e), this._cacheName && pe(this._cacheName);
}
/**
* @param {string} url
* @param {number} timestamp
*
* @private
*/
async setTimestamp(e, t) {
e = W(e);
const n = {
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)
}, r = (await this.getDb()).transaction(w, "readwrite", {
durability: "relaxed"
});
await r.store.put(n), await r.done;
}
/**
* Returns the timestamp stored for a given URL.
*
* @param {string} url
* @return {number | undefined}
*
* @private
*/
async getTimestamp(e) {
const n = await (await this.getDb()).get(w, this._getId(e));
return n == null ? void 0 : n.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<string>}
*
* @private
*/
async expireEntries(e, t) {
const n = await this.getDb();
let a = await n.transaction(w).store.index("timestamp").openCursor(null, "prev");
const r = [];
let i = 0;
for (; a; ) {
const o = a.value;
o.cacheName === this._cacheName && (e && o.timestamp < e || t && i >= t ? r.push(a.value) : i++), a = await a.continue();
}
const c = [];
for (const o of r)
await n.delete(w, 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 + "|" + W(e);
}
/**
* Returns an open connection to the database.
*
* @private
*/
async getDb() {
return this._db || (this._db = await fe(we, 1, {
upgrade: this._upgradeDbAndDeleteOldDbs.bind(this)
})), this._db;
}
}
class _e {
/**
* 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 ye(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), n = await self.caches.open(this._cacheName);
for (const a of t)
await n.delete(a, this._matchOptions);
this._isRunning = !1, this._rerunRequested && (this._rerunRequested = !1, q(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), n = Date.now() - this._maxAgeSeconds * 1e3;
return t !== void 0 ? t < n : !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 be {
/**
* @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: n, cacheName: a, cachedResponse: r }) => {
if (!r)
return null;
const i = this._isResponseDateFresh(r), c = this._getCacheExpiration(a);
q(c.expireEntries());
const o = c.updateTimestamp(n.url);
if (t)
try {
t.waitUntil(o);
} catch {
}
return i ? r : null;
}, this.cacheDidUpdate = async ({ cacheName: t, request: n }) => {
const a = this._getCacheExpiration(t);
await a.updateTimestamp(n.url), await a.expireEntries();
}, this._config = e, this._maxAgeSeconds = e.maxAgeSeconds, this._cacheExpirations = /* @__PURE__ */ new Map(), e.purgeOnQuotaError && z(() => 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 === x.getRuntimeName())
throw new h("expire-custom-caches-only");
let t = this._cacheExpirations.get(e);
return t || (t = new _e(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 n = Date.now();
return t >= n - 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"), a = new Date(t).getTime();
return isNaN(a) ? null : a;
}
/**
* 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:precaching:7.0.0"] && _();
} catch {
}
const Re = "__WB_REVISION__";
function Ce(s) {
if (!s)
throw new h("add-to-cache-list-unexpected-type", { entry: s });
if (typeof s == "string") {
const r = new URL(s, location.href);
return {
cacheKey: r.href,
url: r.href
};
}
const { revision: e, url: t } = s;
if (!t)
throw new h("add-to-cache-list-unexpected-type", { entry: s });
if (!e) {
const r = new URL(t, location.href);
return {
cacheKey: r.href,
url: r.href
};
}
const n = new URL(t, location.href), a = new URL(t, location.href);
return n.searchParams.set(Re, e), {
cacheKey: n.href,
url: a.href
};
}
class xe {
constructor() {
this.updatedURLs = [], this.notUpdatedURLs = [], this.handlerWillStart = async ({ request: e, state: t }) => {
t && (t.originalRequest = e);
}, this.cachedResponseWillBeUsed = async ({ event: e, state: t, cachedResponse: n }) => {
if (e.type === "install" && t && t.originalRequest && t.originalRequest instanceof Request) {
const a = t.originalRequest.url;
n ? this.notUpdatedURLs.push(a) : this.updatedURLs.push(a);
}
return n;
};
}
}
class ke {
constructor({ precacheController: e }) {
this.cacheKeyWillBeUsed = async ({ request: t, params: n }) => {
const a = (n == null ? void 0 : n.cacheKey) || this._precacheController.getCacheKeyForURL(t.url);
return a ? new Request(a, { headers: t.headers }) : t;
}, this._precacheController = e;
}
}
try {
self["workbox:strategies:7.0.0"] && _();
} catch {
}
function R(s) {
return typeof s == "string" ? new Request(s) : s;
}
class Ee {
/**
* 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 Z(), this._extendLifetimePromises = [], this._plugins = [...e.plugins], this._pluginStateMap = /* @__PURE__ */ new Map();
for (const n of this._plugins)
this._pluginStateMap.set(n, {});
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<Response>}
*/
async fetch(e) {
const { event: t } = this;
let n = R(e);
if (n.mode === "navigate" && t instanceof FetchEvent && t.preloadResponse) {
const i = await t.preloadResponse;
if (i)
return i;
}
const a = this.hasCallback("fetchDidFail") ? n.clone() : null;
try {
for (const i of this.iterateCallbacks("requestWillFetch"))
n = await i({ request: n.clone(), event: t });
} catch (i) {
if (i instanceof Error)
throw new h("plugin-error-request-will-fetch", {
thrownErrorMessage: i.message
});
}
const r = n.clone();
try {
let i;
i = await fetch(n, n.mode === "navigate" ? void 0 : this._strategy.fetchOptions);
for (const c of this.iterateCallbacks("fetchDidSucceed"))
i = await c({
event: t,
request: r,
response: i
});
return i;
} catch (i) {
throw a && await this.runCallbacks("fetchDidFail", {
error: i,
event: t,
originalRequest: a.clone(),
request: r.clone()
}), i;
}
}
/**
* 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<Response>}
*/
async fetchAndCachePut(e) {
const t = await this.fetch(e), n = t.clone();
return this.waitUntil(this.cachePut(e, n)), 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<Response|undefined>} A matching response, if found.
*/
async cacheMatch(e) {
const t = R(e);
let n;
const { cacheName: a, matchOptions: r } = this._strategy, i = await this.getCacheKey(t, "read"), c = Object.assign(Object.assign({}, r), { cacheName: a });
n = await caches.match(i, c);
for (const o of this.iterateCallbacks("cachedResponseWillBeUsed"))
n = await o({
cacheName: a,
matchOptions: r,
cachedResponse: n,
request: i,
event: this.event
}) || void 0;
return n;
}
/**
* 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<boolean>} `false` if a cacheWillUpdate caused the response
* not be cached, and `true` otherwise.
*/
async cachePut(e, t) {
const n = R(e);
await se(0);
const a = await this.getCacheKey(n, "write");
if (!t)
throw new h("cache-put-with-no-response", {
url: te(a.url)
});
const r = await this._ensureResponseSafeToCache(t);
if (!r)
return !1;
const { cacheName: i, matchOptions: c } = this._strategy, o = await self.caches.open(i), l = this.hasCallback("cacheDidUpdate"), g = l ? await X(
// TODO(philipwalton): the `__WB_REVISION__` param is a precaching
// feature. Consider into ways to only add this behavior if using
// precaching.
o,
a.clone(),
["__WB_REVISION__"],
c
) : null;
try {
await o.put(a, l ? r.clone() : r);
} catch (u) {
if (u instanceof Error)
throw u.name === "QuotaExceededError" && await ee(), u;
}
for (const u of this.iterateCallbacks("cacheDidUpdate"))
await u({
cacheName: i,
oldResponse: g,
newResponse: r.clone(),
request: a,
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<Request>}
*/
async getCacheKey(e, t) {
const n = `${e.url} | ${t}`;
if (!this._cacheKeys[n]) {
let a = e;
for (const r of this.iterateCallbacks("cacheKeyWillBeUsed"))
a = R(await r({
mode: t,
request: a,
event: this.event,
// params has a type any can't change right now.
params: this.params
// eslint-disable-line
}));
this._cacheKeys[n] = a;
}
return this._cacheKeys[n];
}
/**
* 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 n of this.iterateCallbacks(e))
await n(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<Function>}
*/
*iterateCallbacks(e) {
for (const t of this._strategy.plugins)
if (typeof t[e] == "function") {
const n = this._pluginStateMap.get(t);
yield (r) => {
const i = Object.assign(Object.assign({}, r), { state: n });
return t[e](i);
};
}
}
/**
* 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<Response|undefined>}
*
* @private
*/
async _ensureResponseSafeToCache(e) {
let t = e, n = !1;
for (const a of this.iterateCallbacks("cacheWillUpdate"))
if (t = await a({
request: this.request,
response: t,
event: this.event
}) || void 0, n = !0, !t)
break;
return n || t && t.status !== 200 && (t = void 0), t;
}
}
class V {
/**
* 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<Object>} [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 = x.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<Promise>} 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, n = typeof e.request == "string" ? new Request(e.request) : e.request, a = "params" in e ? e.params : void 0, r = new Ee(this, { event: t, request: n, params: a }), i = this._getResponse(r, n, t), c = this._awaitComplete(i, r, n, t);
return [i, c];
}
async _getResponse(e, t, n) {
await e.runCallbacks("handlerWillStart", { event: n, request: t });
let a;
try {
if (a = await this._handle(t, e), !a || a.type === "error")
throw new h("no-response", { url: t.url });
} catch (r) {
if (r instanceof Error) {
for (const i of e.iterateCallbacks("handlerDidError"))
if (a = await i({ error: r, event: n, request: t }), a)
break;
}
if (!a)
throw r;
}
for (const r of e.iterateCallbacks("handlerWillRespond"))
a = await r({ event: n, request: t, response: a });
return a;
}
async _awaitComplete(e, t, n, a) {
let r, i;
try {
r = await e;
} catch {
}
try {
await t.runCallbacks("handlerDidRespond", {
event: a,
request: n,
response: r
}), await t.doneWaiting();
} catch (c) {
c instanceof Error && (i = c);
}
if (await t.runCallbacks("handlerDidComplete", {
event: a,
request: n,
response: r,
error: i
}), t.destroy(), i)
throw i;
}
}
class p extends V {
/**
*
* @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<Object>} [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 = x.getPrecacheName(e.cacheName), super(e), this._fallbackToNetwork = e.fallbackToNetwork !== !1, this.plugins.push(p.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<Response>}
*/
async _handle(e, t) {
const n = await t.cacheMatch(e);
return n || (t.event && t.event.type === "install" ? await this._handleInstall(e, t) : await this._handleFetch(e, t));
}
async _handleFetch(e, t) {
let n;
const a = t.params || {};
if (this._fallbackToNetwork) {
const r = a.integrity, i = e.integrity, c = !i || i === r;
n = await t.fetch(new Request(e, {
integrity: e.mode !== "no-cors" ? i || r : void 0
})), r && c && e.mode !== "no-cors" && (this._useDefaultCacheabilityPluginIfNeeded(), await t.cachePut(e, n.clone()));
} else
throw new h("missing-precache-entry", {
cacheName: this.cacheName,
url: e.url
});
return n;
}
async _handleInstall(e, t) {
this._useDefaultCacheabilityPluginIfNeeded();
const n = await t.fetch(e);
if (!await t.cachePut(e, n.clone()))
throw new h("bad-precaching-response", {
url: e.url,
status: n.status
});
return n;
}
/**
* 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 [n, a] of this.plugins.entries())
a !== p.copyRedirectedCacheableResponsesPlugin && (a === p.defaultPrecacheCacheabilityPlugin && (e = n), a.cacheWillUpdate && t++);
t === 0 ? this.plugins.push(p.defaultPrecacheCacheabilityPlugin) : t > 1 && e !== null && this.plugins.splice(e, 1);
}
}
p.defaultPrecacheCacheabilityPlugin = {
async cacheWillUpdate({ response: s }) {
return !s || s.status >= 400 ? null : s;
}
};
p.copyRedirectedCacheableResponsesPlugin = {
async cacheWillUpdate({ response: s }) {
return s.redirected ? await ne(s) : s;
}
};
class ve {
/**
* 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: n = !0 } = {}) {
this._urlsToCacheKeys = /* @__PURE__ */ new Map(), this._urlsToCacheModes = /* @__PURE__ */ new Map(), this._cacheKeysToIntegrities = /* @__PURE__ */ new Map(), this._strategy = new p({
cacheName: x.getPrecacheName(e),
plugins: [
...t,
new ke({ precacheController: this })
],
fallbackToNetwork: n
}), 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<Object|string>} [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<workbox-precaching.PrecacheController.PrecacheEntry|string>} entries
* Array of entries to precache.
*/
addToCacheList(e) {
const t = [];
for (const n of e) {
typeof n == "string" ? t.push(n) : n && n.revision === void 0 && t.push(n.url);
const { cacheKey: a, url: r } = Ce(n), i = typeof n != "string" && n.revision ? "reload" : "default";
if (this._urlsToCacheKeys.has(r) && this._urlsToCacheKeys.get(r) !== a)
throw new h("add-to-cache-list-conflicting-entries", {
firstEntry: this._urlsToCacheKeys.get(r),
secondEntry: a
});
if (typeof n != "string" && n.integrity) {
if (this._cacheKeysToIntegrities.has(a) && this._cacheKeysToIntegrities.get(a) !== n.integrity)
throw new h("add-to-cache-list-conflicting-integrities", {
url: r
});
this._cacheKeysToIntegrities.set(a, n.integrity);
}
if (this._urlsToCacheKeys.set(r, a), this._urlsToCacheModes.set(r, i), 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<workbox-precaching.InstallResult>}
*/
install(e) {
return A(e, async () => {
const t = new xe();
this.strategy.plugins.push(t);
for (const [r, i] of this._urlsToCacheKeys) {
const c = this._cacheKeysToIntegrities.get(i), o = this._urlsToCacheModes.get(r), l = new Request(r, {
integrity: c,
cache: o,
credentials: "same-origin"
});
await Promise.all(this.strategy.handleAll({
params: { cacheKey: i },
request: l,
event: e
}));
}
const { updatedURLs: n, notUpdatedURLs: a } = t;
return { updatedURLs: n, notUpdatedURLs: a };
});
}
/**
* 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<workbox-precaching.CleanupResult>}
*/
activate(e) {
return A(e, async () => {
const t = await self.caches.open(this.strategy.cacheName), n = await t.keys(), a = new Set(this._urlsToCacheKeys.values()), r = [];
for (const i of n)
a.has(i.url) || (await t.delete(i), r.push(i.url));
return { deletedURLs: r };
});
}
/**
* Returns a mapping of a precached URL to the corresponding cache key, taking
* into account the revision information for the URL.
*
* @return {Map<string, string>} 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<string>} 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<Response|undefined>}
*/
async matchPrecache(e) {
const t = e instanceof Request ? e.url : e, n = this.getCacheKeyForURL(t);
if (n)
return (await self.caches.open(this.strategy.cacheName)).match(n);
}
/**
* 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 h("non-precached-url", { url: e });
return (n) => (n.request = new Request(e), n.params = Object.assign({ cacheKey: t }, n.params), this.strategy.handle(n));
}
}
let L;
const I = () => (L || (L = new ve()), L);
try {
self["workbox:routing:7.0.0"] && _();
} catch {
}
const $ = "GET", C = (s) => s && typeof s == "object" ? s : { handle: s };
class b {
/**
* 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, n = $) {
this.handler = C(t), this.match = e, this.method = n;
}
/**
*
* @param {workbox-routing-handlerCallback} handler A callback
* function that returns a Promise resolving to a Response
*/
setCatchHandler(e) {
this.catchHandler = C(e);
}
}
class De extends b {
/**
* 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, n) {
const a = ({ url: r }) => {
const i = e.exec(r.href);
if (i && !(r.origin !== location.origin && i.index !== 0))
return i.slice(1);
};
super(a, t, n);
}
}
class Le {
/**
* Initializes a new Router.
*/
constructor() {
this._routes = /* @__PURE__ */ new Map(), this._defaultHandlerMap = /* @__PURE__ */ new Map();
}
/**
* @return {Map<string, Array<workbox-routing.Route>>} 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, n = this.handleRequest({ request: t, event: e });
n && e.respondWith(n);
});
}
/**
* 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, n = Promise.all(t.urlsToCache.map((a) => {
typeof a == "string" && (a = [a]);
const r = new Request(...a);
return this.handleRequest({ request: r, event: e });
}));
e.waitUntil(n), e.ports && e.ports[0] && n.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<Response>|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 n = new URL(e.url, location.href);
if (!n.protocol.startsWith("http"))
return;
const a = n.origin === location.origin, { params: r, route: i } = this.findMatchingRoute({
event: t,
request: e,
sameOrigin: a,
url: n
});
let c = i && i.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: n, request: e, event: t, params: r });
} catch (u) {
l = Promise.reject(u);
}
const g = i && i.catchHandler;
return l instanceof Promise && (this._catchHandler || g) && (l = l.catch(async (u) => {
if (g)
try {
return await g.handle({ url: n, request: e, event: t, params: r });
} catch (N) {
N instanceof Error && (u = N);
}
if (this._catchHandler)
return this._catchHandler.handle({ url: n, request: e, event: t });
throw u;
})), 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: n, event: a }) {
const r = this._routes.get(n.method) || [];
for (const i of r) {
let c;
const o = i.match({ url: e, sameOrigin: t, request: n, event: a });
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: i, 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 = $) {
this._defaultHandlerMap.set(t, C(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 = C(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 h("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 h("unregister-route-route-not-registered");
}
}
let y;
const Ue = () => (y || (y = new Le(), y.addFetchListener(), y.addCacheListener()), y);
function M(s, e, t) {
let n;
if (typeof s == "string") {
const r = new URL(s, location.href), i = ({ url: c }) => c.href === r.href;
n = new b(i, e, t);
} else if (s instanceof RegExp)
n = new De(s, e, t);
else if (typeof s == "function")
n = new b(s, e, t);
else if (s instanceof b)
n = s;
else
throw new h("unsupported-route-type", {
moduleName: "workbox-routing",
funcName: "registerRoute",
paramName: "capture"
});
return Ue().registerRoute(n), n;
}
function Te(s, e = []) {
for (const t of [...s.searchParams.keys()])
e.some((n) => n.test(t)) && s.searchParams.delete(t);
return s;
}
function* Pe(s, { ignoreURLParametersMatching: e = [/^utm_/, /^fbclid$/], directoryIndex: t = "index.html", cleanURLs: n = !0, urlManipulation: a } = {}) {
const r = new URL(s, location.href);
r.hash = "", yield r.href;
const i = Te(r, e);
if (yield i.href, t && i.pathname.endsWith("/")) {
const c = new URL(i.href);
c.pathname += t, yield c.href;
}
if (n) {
const c = new URL(i.href);
c.pathname += ".html", yield c.href;
}
if (a) {
const c = a({ url: r });
for (const o of c)
yield o.href;
}
}
class Ie extends b {
/**
* @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<RegExp>} [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 n = ({ request: a }) => {
const r = e.getURLsToCacheKeys();
for (const i of Pe(a.url, t)) {
const c = r.get(i);
if (c) {
const o = e.getIntegrityForCacheKey(c);
return { cacheKey: c, integrity: o };
}
}
};
super(n, e.strategy);
}
}
function Me(s) {
const e = I(), t = new Ie(e, s);
M(t);
}
function Ne(s) {
return I().createHandlerBoundToURL(s);
}
function Ke(s) {
I().precache(s);
}
function Ae(s, e) {
Ke(s), Me(e);
}
const je = {
/**
* 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: s }) => s.status === 200 || s.status === 0 ? s : null
};
class Oe extends V {
/**
* @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<Object>} [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(je);
}
/**
* @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<Response>}
*/
async _handle(e, t) {
const n = t.fetchAndCachePut(e).catch(() => {
});
t.waitUntil(n);
let a = await t.cacheMatch(e), r;
if (!a)
try {
a = await n;
} catch (i) {
i instanceof Error && (r = i);
}
if (!a)
throw new h("no-response", { url: e.url, error: r });
return a;
}
}
const Se = "shlink-web-client", We = "A React-based progressive web application for shlink", Be = "/shlink-web-client/dependabot/npm_and_yarn/shlink-ad52743a18", qe = "https://github.com/shlinkio/shlink-web-client", Fe = "MIT", He = {
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"
}, Ve = {
"@fortawesome/fontawesome-free": "^6.5.1",
"@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-brands-svg-icons": "^6.5.1",
"@fortawesome/free-regular-svg-icons": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"@json2csv/plainjs": "^7.0.3",
"@reduxjs/toolkit": "^2.0.1",
"@shlinkio/data-manipulation": "^1.0.2",
"@shlinkio/shlink-frontend-kit": "^0.4.1",
"@shlinkio/shlink-js-sdk": "^0.2.0",
"@shlinkio/shlink-web-component": "^0.4.1",
bootstrap: "5.2.3",
bottlejs: "^2.0.1",
clsx: "^2.0.0",
"compare-versions": "^6.1.0",
csvtojson: "^2.0.10",
"date-fns": "^2.30.0",
react: "^18.2.0",
"react-dom": "^18.2.0",
"react-external-link": "^2.2.0",
"react-redux": "^9.0.2",
"react-router-dom": "^6.20.1",
reactstrap: "^9.2.1",
"redux-localstorage-simple": "^2.5.1",
uuid: "^9.0.1",
"workbox-core": "^7.0.0",
"workbox-expiration": "^7.0.0",
"workbox-precaching": "^7.0.0",
"workbox-routing": "^7.0.0",
"workbox-strategies": "^7.0.0"
}, $e = {
"@shlinkio/eslint-config-js-coding-standard": "~2.3.0",
"@shlinkio/stylelint-config-css-coding-standard": "~1.1.1",
"@testing-library/jest-dom": "^6.1.5",
"@testing-library/react": "^14.1.2",
"@testing-library/user-event": "^14.5.1",
"@total-typescript/shoehorn": "^0.1.1",
"@types/react": "^18.2.43",
"@types/react-dom": "^18.2.17",
"@types/uuid": "^9.0.7",
"@vitejs/plugin-react": "^4.2.1",
"@vitest/coverage-v8": "^1.0.4",
"adm-zip": "^0.5.10",
"axe-core": "^4.8.2",
chalk: "^5.3.0",
eslint: "^8.55.0",
history: "^5.3.0",
jsdom: "^23.0.1",
sass: "^1.69.5",
stylelint: "^15.11.0",
typescript: "^5.3.3",
vite: "^5.0.7",
"vite-plugin-pwa": "^0.17.4",
vitest: "^1.0.4"
}, Ge = [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
], Qe = {
name: Se,
description: We,
private: !1,
homepage: Be,
repository: qe,
license: Fe,
scripts: He,
dependencies: Ve,
devDependencies: $e,
browserslist: Ge
};
ae();
Ae([{"revision":null,"url":"assets/index-ck8Itpeu.js"},{"revision":null,"url":"assets/index-oITpymb_.css"},{"revision":"d453f1a2f06f21ce2ce43106fb7f111b","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":"c96981eb1dfd3ddad0f16000c22fe744","url":"manifest.json"}]);
const ze = new RegExp("/[^/?]+\\.[^/]+$");
M(
// Return false to exempt requests from being fulfilled by index.html.
({ request: s, url: e }) => !(s.mode !== "navigate" || e.pathname.startsWith("/_") || e.pathname.match(ze)),
Ne(`${Qe.homepage}/index.html`)
);
M(
// Add in any other file extensions or routing criteria as needed.
({ url: s }) => s.origin === self.location.origin && s.pathname.endsWith(".png"),
// Customize this strategy as needed, e.g., by changing to CacheFirst.
new Oe({
cacheName: "images",
plugins: [
// Ensure that once this runtime cache reaches a maximum size the
// least-recently used images are removed.
new be({ maxEntries: 50 })
]
})
);
self.addEventListener("message", (s) => {
s.data && s.data.type === "SKIP_WAITING" && self.skipWaiting();
});