{
  "version": 3,
  "sources": ["<define:self.__SW_MANIFEST>", "node_modules/serwist/src/utils/cacheNames.ts", "node_modules/serwist/src/utils/canConstructResponseFromBodyStream.ts", "node_modules/serwist/src/models/messages/messages.ts", "node_modules/serwist/src/models/messages/messageGenerator.ts", "node_modules/serwist/src/utils/SerwistError.ts", "node_modules/serwist/src/utils/assert.ts", "node_modules/serwist/src/utils/getFriendlyURL.ts", "node_modules/serwist/src/utils/logger.ts", "node_modules/serwist/src/utils/timeout.ts", "node_modules/serwist/src/models/quotaErrorCallbacks.ts", "node_modules/serwist/src/utils/cacheMatchIgnoreParams.ts", "node_modules/serwist/src/utils/Deferred.ts", "node_modules/serwist/src/utils/executeQuotaErrorCallbacks.ts", "node_modules/serwist/src/utils/deleteOutdatedCaches.ts", "node_modules/serwist/src/utils/cleanupOutdatedCaches.ts", "node_modules/serwist/src/utils/clientsClaim.ts", "node_modules/serwist/src/utils/waitUntil.ts", "node_modules/idb/build/index.js", "node_modules/serwist/src/copyResponse.ts", "node_modules/serwist/src/disableDevLogs.ts", "node_modules/serwist/src/lib/backgroundSync/BackgroundSyncQueueDb.ts", "node_modules/serwist/src/lib/backgroundSync/BackgroundSyncQueueStore.ts", "node_modules/serwist/src/lib/backgroundSync/StorableRequest.ts", "node_modules/serwist/src/lib/backgroundSync/BackgroundSyncQueue.ts", "node_modules/serwist/src/lib/backgroundSync/BackgroundSyncPlugin.ts", "node_modules/serwist/src/lib/strategies/plugins/cacheOkAndOpaquePlugin.ts", "node_modules/serwist/src/lib/strategies/StrategyHandler.ts", "node_modules/serwist/src/lib/strategies/Strategy.ts", "node_modules/serwist/src/lib/strategies/utils/messages.ts", "node_modules/serwist/src/lib/strategies/NetworkFirst.ts", "node_modules/serwist/src/lib/strategies/NetworkOnly.ts", "node_modules/serwist/src/constants.ts", "node_modules/serwist/src/utils/normalizeHandler.ts", "node_modules/serwist/src/Route.ts", "node_modules/serwist/src/lib/strategies/PrecacheStrategy.ts", "node_modules/serwist/src/NavigationRoute.ts", "node_modules/serwist/src/navigationPreload.ts", "node_modules/serwist/src/utils/removeIgnoredSearchParams.ts", "node_modules/serwist/src/utils/generateURLVariations.ts", "node_modules/serwist/src/RegExpRoute.ts", "node_modules/serwist/src/setCacheNameDetails.ts", "node_modules/serwist/src/utils/createCacheKey.ts", "node_modules/serwist/src/utils/PrecacheInstallReportPlugin.ts", "node_modules/serwist/src/utils/parseRoute.ts", "node_modules/serwist/src/utils/printCleanupDetails.ts", "node_modules/serwist/src/utils/printInstallDetails.ts", "node_modules/@serwist/utils/src/non-nullable.ts", "node_modules/@serwist/utils/src/parallel.ts", "node_modules/@serwist/utils/src/to-unix.ts", "node_modules/@serwist/utils/src/compare.ts", "node_modules/@serwist/utils/src/constants.ts", "node_modules/@serwist/utils/src/semver.ts", "node_modules/@serwist/utils/src/browserslist.ts", "node_modules/serwist/src/cacheNames.ts", "node_modules/serwist/src/lib/broadcastUpdate/constants.ts", "node_modules/serwist/src/lib/broadcastUpdate/responsesAreSame.ts", "node_modules/serwist/src/lib/broadcastUpdate/BroadcastCacheUpdate.ts", "node_modules/serwist/src/lib/broadcastUpdate/BroadcastUpdatePlugin.ts", "node_modules/serwist/src/lib/cacheableResponse/CacheableResponse.ts", "node_modules/serwist/src/lib/cacheableResponse/CacheableResponsePlugin.ts", "node_modules/serwist/src/lib/expiration/models/CacheTimestampsModel.ts", "node_modules/serwist/src/lib/expiration/CacheExpiration.ts", "node_modules/serwist/src/registerQuotaErrorCallback.ts", "node_modules/serwist/src/lib/expiration/ExpirationPlugin.ts", "node_modules/serwist/src/lib/googleAnalytics/constants.ts", "node_modules/serwist/src/lib/googleAnalytics/initializeGoogleAnalytics.ts", "node_modules/serwist/src/lib/precaching/PrecacheFallbackPlugin.ts", "node_modules/serwist/src/lib/rangeRequests/utils/calculateEffectiveBoundaries.ts", "node_modules/serwist/src/lib/rangeRequests/utils/parseRangeHeader.ts", "node_modules/serwist/src/lib/rangeRequests/createPartialResponse.ts", "node_modules/serwist/src/lib/rangeRequests/RangeRequestsPlugin.ts", "node_modules/serwist/src/lib/strategies/CacheFirst.ts", "node_modules/serwist/src/lib/strategies/CacheOnly.ts", "node_modules/serwist/src/lib/strategies/StaleWhileRevalidate.ts", "node_modules/serwist/src/PrecacheRoute.ts", "node_modules/serwist/src/utils/PrecacheCacheKeyPlugin.ts", "node_modules/serwist/src/utils/parsePrecacheOptions.ts", "node_modules/serwist/src/Serwist.ts", "node_modules/@serwist/turbopack/src/index.worker.ts", "app/sw.ts"],
  "sourcesContent": ["[\n  {\n    \"url\": \"/_next/static/chunks/turbopack-2u3zijpxmp46i.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/3pvsyhm4qwapq.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/3kb1i4ztda_qz.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/2zmcm0jh9et_o.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/2ujkaofjrasy8.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/2ijofgz7u8_5w.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/2dq2fr-1nb-n5.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/21n3rebq9_fnz.css\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/20g897wokh_dh.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/204cyp2bj7mi_.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/1z7v_r6rjgp-r.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/1z7gnmxte_2--.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/1q87jel12q_3z.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/1q1enut8ga1qj.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/1bq3q9f9p7tnp.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0x1crwlej_ymv.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0j56xq4zpxsw6.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0gthr0_43bd8_.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0fwioguaet7gq.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0e09nsw4etv3w.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0cz1d0mv5g_q7.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0cdi3bfr-9jl0.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/0_1ggujuma6sh.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/05cij2_7_b_xd.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/chunks/05-c3ty_6dwfk.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/YnwsTwlgJdO8wqCyYueDp/_ssgManifest.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/YnwsTwlgJdO8wqCyYueDp/_clientMiddlewareManifest.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/_next/static/YnwsTwlgJdO8wqCyYueDp/_buildManifest.js\",\n    \"revision\": null\n  },\n  {\n    \"url\": \"/vue-certificate.png\",\n    \"revision\": \"dd5f158e44f16b630f8aa4baf8a14776\"\n  },\n  {\n    \"url\": \"/skriza_logo.svg\",\n    \"revision\": \"394bfeacf956ec09708be07a84f38e8b\"\n  },\n  {\n    \"url\": \"/sitemap.xml\",\n    \"revision\": \"c5f59fb1b238330478b8104c159b65d9\"\n  },\n  {\n    \"url\": \"/single_bird.svg\",\n    \"revision\": \"9280b120498ac03a906ab67e4e6391a8\"\n  },\n  {\n    \"url\": \"/robots.txt\",\n    \"revision\": \"709c9e2fbaa29aa5c3fb2bf44a4d677a\"\n  },\n  {\n    \"url\": \"/manifest.json\",\n    \"revision\": \"4730cf13c7393d0c720c7faa4b37dc10\"\n  },\n  {\n    \"url\": \"/logsysdev.png\",\n    \"revision\": \"1779a5f352899f93c78612c06ec76b1c\"\n  },\n  {\n    \"url\": \"/livalink_logo.svg\",\n    \"revision\": \"f3492864e48d13d16ab8e9369cc36115\"\n  },\n  {\n    \"url\": \"/image.png\",\n    \"revision\": \"23ee0a439ef599c1d179c46b0c18b35d\"\n  },\n  {\n    \"url\": \"/icons8-favicon.gif\",\n    \"revision\": \"543b02d2cf17195934706117492b3f8c\"\n  },\n  {\n    \"url\": \"/go-certificate.png\",\n    \"revision\": \"e622317c5ea6e1e2d911af96dbd061ec\"\n  },\n  {\n    \"url\": \"/darkquiz.svg\",\n    \"revision\": \"e50f99c7d7e48cd7958799940838eedd\"\n  },\n  {\n    \"url\": \"/AI-README.md\",\n    \"revision\": \"a88f85d43614aa95decd097fc080cb6d\"\n  },\n  {\n    \"url\": \"/icons/icon-512x512.png\",\n    \"revision\": \"543b02d2cf17195934706117492b3f8c\"\n  },\n  {\n    \"url\": \"/icons/icon-192x192.png\",\n    \"revision\": \"543b02d2cf17195934706117492b3f8c\"\n  },\n  {\n    \"url\": \"/icons/icon-144x144.png\",\n    \"revision\": \"543b02d2cf17195934706117492b3f8c\"\n  },\n  {\n    \"revision\": \"build-1785097119197\",\n    \"url\": \"/~offline\"\n  }\n]", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\ndeclare let registration: ServiceWorkerRegistration | undefined;\n\nexport interface CacheNameDetails {\n  googleAnalytics: string;\n  precache: string;\n  prefix: string;\n  runtime: string;\n  suffix: string;\n}\n\nexport interface PartialCacheNameDetails {\n  /**\n   * The string to add to the beginning of the precache and runtime cache names.\n   */\n  prefix?: string;\n  /**\n   * The string to add to the end of the precache and runtime cache names.\n   */\n  suffix?: string;\n  /**\n   * The cache name to use for precache caching.\n   */\n  precache?: string;\n  /**\n   * The cache name to use for runtime caching.\n   */\n  runtime?: string;\n  /**\n   * The cache name to use for {@linkcode initializeGoogleAnalytics}.\n   */\n  googleAnalytics?: string;\n  [propName: string]: string | undefined;\n}\n\nexport type CacheNameDetailsProp = \"googleAnalytics\" | \"precache\" | \"prefix\" | \"runtime\" | \"suffix\";\n\nconst _cacheNameDetails: CacheNameDetails = {\n  googleAnalytics: \"googleAnalytics\",\n  precache: \"precache-v2\",\n  prefix: \"serwist\",\n  runtime: \"runtime\",\n  suffix: typeof registration !== \"undefined\" ? registration.scope : \"\",\n};\n\nconst _createCacheName = (cacheName: string): string => {\n  return [_cacheNameDetails.prefix, cacheName, _cacheNameDetails.suffix].filter((value) => value && value.length > 0).join(\"-\");\n};\n\nconst eachCacheNameDetail = (fn: (key: CacheNameDetailsProp) => void): void => {\n  for (const key of Object.keys(_cacheNameDetails)) {\n    fn(key as CacheNameDetailsProp);\n  }\n};\n\nexport const cacheNames = {\n  updateDetails: (details: PartialCacheNameDetails): void => {\n    eachCacheNameDetail((key: CacheNameDetailsProp): void => {\n      const detail = details[key];\n      if (typeof detail === \"string\") {\n        _cacheNameDetails[key] = detail;\n      }\n    });\n  },\n  getGoogleAnalyticsName: (userCacheName?: string): string => {\n    return userCacheName || _createCacheName(_cacheNameDetails.googleAnalytics);\n  },\n  getPrecacheName: (userCacheName?: string): string => {\n    return userCacheName || _createCacheName(_cacheNameDetails.precache);\n  },\n  getPrefix: (): string => {\n    return _cacheNameDetails.prefix;\n  },\n  getRuntimeName: (userCacheName?: string): string => {\n    return userCacheName || _createCacheName(_cacheNameDetails.runtime);\n  },\n  getSuffix: (): string => {\n    return _cacheNameDetails.suffix;\n  },\n};\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nlet supportStatus: boolean | undefined;\n\n/**\n * A utility function that determines whether the current browser supports\n * constructing a new response from a `response.body` stream.\n *\n * @returns `true`, if the current browser can successfully construct\n * a response from a `response.body` stream, `false` otherwise.\n * @private\n */\nfunction canConstructResponseFromBodyStream(): boolean {\n  if (supportStatus === undefined) {\n    const testResponse = new Response(\"\");\n\n    if (\"body\" in testResponse) {\n      try {\n        new Response(testResponse.body);\n        supportStatus = true;\n      } catch {\n        supportStatus = false;\n      }\n    }\n    supportStatus = false;\n  }\n\n  return supportStatus;\n}\n\nexport { canConstructResponseFromBodyStream };\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\ninterface LoggableObject {\n  [key: string]: string | number;\n}\ninterface MessageMap {\n  [messageID: string]: (param: LoggableObject) => string;\n}\n\nexport const messages = {\n  \"invalid-value\": ({ paramName, validValueDescription, value }) => {\n    if (!paramName || !validValueDescription) {\n      throw new Error(`Unexpected input to 'invalid-value' error.`);\n    }\n    return (\n      `The '${paramName}' parameter was given a value with an ` +\n      `unexpected value. ${validValueDescription} Received a value of ` +\n      `${JSON.stringify(value)}.`\n    );\n  },\n\n  \"not-an-array\": ({ moduleName, className, funcName, paramName }) => {\n    if (!moduleName || !className || !funcName || !paramName) {\n      throw new Error(`Unexpected input to 'not-an-array' error.`);\n    }\n    return `The parameter '${paramName}' passed into ` + `'${moduleName}.${className}.${funcName}()' must be an array.`;\n  },\n\n  \"incorrect-type\": ({ expectedType, paramName, moduleName, className, funcName }) => {\n    if (!expectedType || !paramName || !moduleName || !funcName) {\n      throw new Error(`Unexpected input to 'incorrect-type' error.`);\n    }\n    const classNameStr = className ? `${className}.` : \"\";\n    return `The parameter '${paramName}' passed into ` + `'${moduleName}.${classNameStr}` + `${funcName}()' must be of type ${expectedType}.`;\n  },\n\n  \"incorrect-class\": ({ expectedClassName, paramName, moduleName, className, funcName, isReturnValueProblem }) => {\n    if (!expectedClassName || !moduleName || !funcName) {\n      throw new Error(`Unexpected input to 'incorrect-class' error.`);\n    }\n    const classNameStr = className ? `${className}.` : \"\";\n    if (isReturnValueProblem) {\n      return `The return value from '${moduleName}.${classNameStr}${funcName}()' must be an instance of class ${expectedClassName}.`;\n    }\n\n    return (\n      `The parameter '${paramName}' passed into ` +\n      `'${moduleName}.${classNameStr}${funcName}()' ` +\n      `must be an instance of class ${expectedClassName}.`\n    );\n  },\n\n  \"missing-a-method\": ({ expectedMethod, paramName, moduleName, className, funcName }) => {\n    if (!expectedMethod || !paramName || !moduleName || !className || !funcName) {\n      throw new Error(`Unexpected input to 'missing-a-method' error.`);\n    }\n    return `${moduleName}.${className}.${funcName}() expected the ` + `'${paramName}' parameter to expose a '${expectedMethod}' method.`;\n  },\n\n  \"add-to-cache-list-unexpected-type\": ({ entry }) => {\n    return `An unexpected entry was passed to 'serwist.Serwist.addToPrecacheList()' The entry '${JSON.stringify(\n      entry,\n    )}' isn't supported. You must supply an array of strings with one or more characters, objects with a url property or Request objects.`;\n  },\n\n  \"add-to-cache-list-conflicting-entries\": ({ firstEntry, secondEntry }) => {\n    if (!firstEntry || !secondEntry) {\n      throw new Error(\"Unexpected input to \" + `'add-to-cache-list-duplicate-entries' error.`);\n    }\n\n    return `Two of the entries passed to 'serwist.Serwist.addToPrecacheList()' had the URL ${firstEntry} but different revision details. Serwist is unable to cache and version the asset correctly. Please remove one of the entries.`;\n  },\n\n  \"plugin-error-request-will-fetch\": ({ thrownErrorMessage }) => {\n    if (!thrownErrorMessage) {\n      throw new Error(\"Unexpected input to \" + `'plugin-error-request-will-fetch', error.`);\n    }\n\n    return `An error was thrown by a plugin's 'requestWillFetch()' method. The thrown error message was: '${thrownErrorMessage}'.`;\n  },\n\n  \"invalid-cache-name\": ({ cacheNameId, value }) => {\n    if (!cacheNameId) {\n      throw new Error(`Expected a 'cacheNameId' for error 'invalid-cache-name'`);\n    }\n\n    return `You must provide a name containing at least one character for setCacheDetails({${cacheNameId}: '...'}). Received a value of '${JSON.stringify(\n      value,\n    )}'`;\n  },\n\n  \"unregister-route-but-not-found-with-method\": ({ method }) => {\n    if (!method) {\n      throw new Error(\"Unexpected input to \" + `'unregister-route-but-not-found-with-method' error.`);\n    }\n\n    return `The route you're trying to unregister was not  previously registered for the method type '${method}'.`;\n  },\n\n  \"unregister-route-route-not-registered\": () => {\n    return `The route you're trying to unregister was not previously ` + \"registered.\";\n  },\n\n  \"queue-replay-failed\": ({ name }) => {\n    return `Replaying the background sync queue '${name}' failed.`;\n  },\n\n  \"duplicate-queue-name\": ({ name }) => {\n    return `The queue name '${name}' is already being used. All instances of 'serwist.BackgroundSyncQueue' must be given unique names.`;\n  },\n\n  \"expired-test-without-max-age\": ({ methodName, paramName }) => {\n    return `The '${methodName}()' method can only be used when the ` + `'${paramName}' is used in the constructor.`;\n  },\n\n  \"unsupported-route-type\": ({ moduleName, className, funcName, paramName }) => {\n    return `The supplied '${paramName}' parameter was an unsupported type. Please check the docs for ${moduleName}.${className}.${funcName} for valid input types.`;\n  },\n\n  \"not-array-of-class\": ({ value, expectedClass, moduleName, className, funcName, paramName }) => {\n    return `The supplied '${paramName}' parameter must be an array of '${expectedClass}' objects. Received '${JSON.stringify(\n      value,\n    )},'. Please check the call to ${moduleName}.${className}.${funcName}() to fix the issue.`;\n  },\n\n  \"max-entries-or-age-required\": ({ moduleName, className, funcName }) => {\n    return `You must define either 'config.maxEntries' or 'config.maxAgeSeconds' in '${moduleName}.${className}.${funcName}'`;\n  },\n\n  \"statuses-or-headers-required\": ({ moduleName, className, funcName }) => {\n    return `You must define either 'config.statuses' or 'config.headers' in '${moduleName}.${className}.${funcName}'`;\n  },\n\n  \"invalid-string\": ({ moduleName, funcName, paramName }) => {\n    if (!paramName || !moduleName || !funcName) {\n      throw new Error(`Unexpected input to 'invalid-string' error.`);\n    }\n    return `When using strings, the '${paramName}' parameter must start with 'http' (for cross-origin matches) or '/' (for same-origin matches). Please see the docs for ${moduleName}.${funcName}() for more info.`;\n  },\n\n  \"channel-name-required\": () => {\n    return \"You must provide a channelName to construct a \" + \"BroadcastCacheUpdate instance.\";\n  },\n\n  \"invalid-responses-are-same-args\": () => {\n    return \"The arguments passed into responsesAreSame() appear to be \" + \"invalid. Please ensure valid Responses are used.\";\n  },\n\n  \"expire-custom-caches-only\": () => {\n    return `You must provide a 'cacheName' property when using the ` + \"expiration plugin with a runtime caching strategy.\";\n  },\n\n  \"unit-must-be-bytes\": ({ normalizedRangeHeader }) => {\n    if (!normalizedRangeHeader) {\n      throw new Error(`Unexpected input to 'unit-must-be-bytes' error.`);\n    }\n    return `The 'unit' portion of the Range header must be set to 'bytes'. The Range header provided was \"${normalizedRangeHeader}\"`;\n  },\n\n  \"single-range-only\": ({ normalizedRangeHeader }) => {\n    if (!normalizedRangeHeader) {\n      throw new Error(`Unexpected input to 'single-range-only' error.`);\n    }\n    return `Multiple ranges are not supported. Please use a  single start value, and optional end value. The Range header provided was \"${normalizedRangeHeader}\"`;\n  },\n\n  \"invalid-range-values\": ({ normalizedRangeHeader }) => {\n    if (!normalizedRangeHeader) {\n      throw new Error(`Unexpected input to 'invalid-range-values' error.`);\n    }\n    return `The Range header is missing both start and end values. At least one of those values is needed. The Range header provided was \"${normalizedRangeHeader}\"`;\n  },\n\n  \"no-range-header\": () => {\n    return \"No Range header was found in the Request provided.\";\n  },\n\n  \"range-not-satisfiable\": ({ size, start, end }) => {\n    return `The start (${start}) and end (${end}) values in the Range are ` + `not satisfiable by the cached response, which is ${size} bytes.`;\n  },\n\n  \"attempt-to-cache-non-get-request\": ({ url, method }) => {\n    return `Unable to cache '${url}' because it is a '${method}' request and only 'GET' requests can be cached.`;\n  },\n\n  \"cache-put-with-no-response\": ({ url }) => {\n    return `There was an attempt to cache '${url}' but the response was not defined.`;\n  },\n\n  \"no-response\": ({ url, error }) => {\n    let message = `The strategy could not generate a response for '${url}'.`;\n    if (error) {\n      message += ` The underlying error is ${error}.`;\n    }\n    return message;\n  },\n\n  \"bad-precaching-response\": ({ url, status }) => {\n    return `The precaching request for '${url}' failed${status ? ` with an HTTP status of ${status}.` : \".\"}`;\n  },\n\n  \"non-precached-url\": ({ url }) => {\n    return `'createHandlerBoundToURL(\"${url}\")' was called, but that URL is not precached. Please pass in a URL that is precached instead.`;\n  },\n\n  \"add-to-cache-list-conflicting-integrities\": ({ url }) => {\n    return `Two of the entries passed to 'serwist.Serwist.addToPrecacheList()' had the URL ${url} with different integrity values. Please remove one of them.`;\n  },\n\n  \"missing-precache-entry\": ({ cacheName, url }) => {\n    return `Unable to find a precached response in ${cacheName} for ${url}.`;\n  },\n\n  \"cross-origin-copy-response\": ({ origin }) => {\n    return `'@serwist/core.copyResponse()' can only be used with same-origin responses. It was passed a response with origin ${origin}.`;\n  },\n\n  \"opaque-streams-source\": ({ type }) => {\n    const message = `One of the '@serwist/streams' sources resulted in an '${type}' response.`;\n    if (type === \"opaqueredirect\") {\n      return `${message} Please do not use a navigation request that results in a redirect as a source.`;\n    }\n    return `${message} Please ensure your sources are CORS-enabled.`;\n  },\n} satisfies MessageMap;\n\nexport type MessageKey = keyof typeof messages;\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { MapLikeObject } from \"../../types.js\";\nimport { type MessageKey, messages } from \"./messages.js\";\n\nconst fallback = (code: string, ...args: any[]) => {\n  let msg = code;\n  if (args.length > 0) {\n    msg += ` :: ${JSON.stringify(args)}`;\n  }\n  return msg;\n};\n\nconst generatorFunction = (code: MessageKey, details: MapLikeObject = {}) => {\n  const message = messages[code];\n  if (!message) {\n    throw new Error(`Unable to find message for code '${code}'.`);\n  }\n\n  return message(details);\n};\n\nexport const messageGenerator = process.env.NODE_ENV === \"production\" ? fallback : generatorFunction;\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { messageGenerator } from \"../models/messages/messageGenerator.js\";\nimport type { MessageKey } from \"../models/messages/messages.js\";\nimport type { MapLikeObject } from \"../types.js\";\n\n/**\n * Serwist errors should be thrown with this class.\n * This allows use to ensure the type easily in tests,\n * helps developers identify errors from Serwist\n * easily and allows use to optimise error\n * messages correctly.\n *\n * @private\n */\nexport class SerwistError extends Error {\n  details?: MapLikeObject;\n\n  /**\n   *\n   * @param errorCode The error code that\n   * identifies this particular error.\n   * @param details Any relevant arguments\n   * that will help developers identify issues should\n   * be added as a key on the context object.\n   */\n  constructor(errorCode: MessageKey, details?: MapLikeObject) {\n    const message = messageGenerator(errorCode, details);\n\n    super(message);\n\n    this.name = errorCode;\n    this.details = details;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { MapLikeObject } from \"../types.js\";\nimport { SerwistError } from \"./SerwistError.js\";\n\n/*\n * This method throws if the supplied value is not an array.\n * The destructed values are required to produce a meaningful error for users.\n * The destructed and restructured object is so it's clear what is\n * needed.\n */\nconst isArray = (value: any[], details: MapLikeObject) => {\n  if (!Array.isArray(value)) {\n    throw new SerwistError(\"not-an-array\", details);\n  }\n};\n\nconst hasMethod = (object: MapLikeObject, expectedMethod: string, details: MapLikeObject) => {\n  const type = typeof object[expectedMethod];\n  if (type !== \"function\") {\n    details.expectedMethod = expectedMethod;\n    throw new SerwistError(\"missing-a-method\", details);\n  }\n};\n\nconst isType = (object: unknown, expectedType: string, details: MapLikeObject) => {\n  if (typeof object !== expectedType) {\n    details.expectedType = expectedType;\n    throw new SerwistError(\"incorrect-type\", details);\n  }\n};\n\nconst isInstance = (\n  object: unknown,\n  // biome-ignore lint/complexity/noBannedTypes: Need the general type to do the check later.\n  expectedClass: Function,\n  details: MapLikeObject,\n) => {\n  if (!(object instanceof expectedClass)) {\n    details.expectedClassName = expectedClass.name;\n    throw new SerwistError(\"incorrect-class\", details);\n  }\n};\n\nconst isOneOf = (value: any, validValues: any[], details: MapLikeObject) => {\n  if (!validValues.includes(value)) {\n    details.validValueDescription = `Valid values are ${JSON.stringify(validValues)}.`;\n    throw new SerwistError(\"invalid-value\", details);\n  }\n};\n\nconst isArrayOfClass = (\n  value: any,\n  // biome-ignore lint/complexity/noBannedTypes: Need general type to do check later.\n  expectedClass: Function,\n  details: MapLikeObject,\n) => {\n  const error = new SerwistError(\"not-array-of-class\", details);\n  if (!Array.isArray(value)) {\n    throw error;\n  }\n\n  for (const item of value) {\n    if (!(item instanceof expectedClass)) {\n      throw error;\n    }\n  }\n};\n\nconst finalAssertExports =\n  process.env.NODE_ENV === \"production\"\n    ? null\n    : {\n        hasMethod,\n        isArray,\n        isInstance,\n        isOneOf,\n        isType,\n        isArrayOfClass,\n      };\n\nexport { finalAssertExports as assert };\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nconst getFriendlyURL = (url: URL | string): string => {\n  const urlObj = new URL(String(url), location.href);\n  // See https://github.com/GoogleChrome/workbox/issues/2323\n  // We want to include everything, except for the origin if it's same-origin.\n  return urlObj.href.replace(new RegExp(`^${location.origin}`), \"\");\n};\n\nexport { getFriendlyURL };\n", "/*\n  Copyright 2019 Google LLC\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n// logger is used inside of both service workers and the window global scope.\ndeclare global {\n  interface WorkerGlobalScope {\n    __WB_DISABLE_DEV_LOGS: boolean;\n  }\n\n  interface Window {\n    __WB_DISABLE_DEV_LOGS: boolean;\n  }\n}\n\n/**\n * The logger used by Serwist inside of both service workers and the window global scope.\n *\n * Note: This is forcibly `null` in production mode to reduce bundle size. Do check whether\n * you are currently in development mode (by using `process.env.NODE_ENV !== \"production\"`)\n * before using it.\n */\nexport const logger =\n  process.env.NODE_ENV === \"production\" || typeof self === \"undefined\"\n    ? null!\n    : (() => {\n        // Don't overwrite this value if it's already set.\n        // See https://github.com/GoogleChrome/workbox/pull/2284#issuecomment-560470923\n        if (!(\"__WB_DISABLE_DEV_LOGS\" in globalThis)) {\n          self.__WB_DISABLE_DEV_LOGS = false;\n        }\n\n        let inGroup = false;\n\n        const methodToColorMap = {\n          debug: \"#7f8c8d\", // Gray\n          log: \"#2ecc71\", // Green\n          warn: \"#f39c12\", // Yellow\n          error: \"#c0392b\", // Red\n          groupCollapsed: \"#3498db\", // Blue\n          groupEnd: null, // No colored prefix on groupEnd\n        };\n\n        type LoggerMethods = keyof typeof methodToColorMap;\n\n        const print = (method: LoggerMethods, args: any[]) => {\n          if (self.__WB_DISABLE_DEV_LOGS) {\n            return;\n          }\n\n          if (method === \"groupCollapsed\") {\n            // Safari doesn't print all console.groupCollapsed() arguments:\n            // https://bugs.webkit.org/show_bug.cgi?id=182754\n            if (typeof navigator !== \"undefined\" && /^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {\n              console[method](...args);\n              return;\n            }\n          }\n\n          const styles = [\n            `background: ${methodToColorMap[method]!}`,\n            \"border-radius: 0.5em\",\n            \"color: white\",\n            \"font-weight: bold\",\n            \"padding: 2px 0.5em\",\n          ];\n\n          // When in a group, the serwist prefix is not displayed.\n          const logPrefix = inGroup ? [] : [\"%cserwist\", styles.join(\";\")];\n\n          console[method](...logPrefix, ...args);\n\n          if (method === \"groupCollapsed\") {\n            inGroup = true;\n          }\n          if (method === \"groupEnd\") {\n            inGroup = false;\n          }\n        };\n\n        const loggerMethods = Object.keys(methodToColorMap) as LoggerMethods[];\n\n        return loggerMethods.reduce(\n          (api, method) => {\n            api[method] = (...args: any[]) => {\n              print(method, args);\n            };\n            return api;\n          },\n          {} as { [method in LoggerMethods]: (...args: any[]) => void },\n        );\n      })();\n", "/*\n  Copyright 2019 Google LLC\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n/**\n * Returns a promise that resolves and the passed number of milliseconds.\n * This utility is an async/await-friendly version of `setTimeout`.\n *\n * @param ms\n * @returns\n * @private\n */\n\nexport function timeout(ms: number): Promise<unknown> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n// Callbacks to be executed whenever there's a quota error.\n// biome-ignore lint/complexity/noBannedTypes: Can't change Function type right now.\nconst quotaErrorCallbacks: Set<Function> = new Set();\n\nexport { quotaErrorCallbacks };\n", "/*\n  Copyright 2020 Google LLC\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nfunction stripParams(fullURL: string, ignoreParams: string[]) {\n  const strippedURL = new URL(fullURL);\n  for (const param of ignoreParams) {\n    strippedURL.searchParams.delete(param);\n  }\n  return strippedURL.href;\n}\n\n/**\n * Matches an item in the cache, ignoring specific URL params. This is similar\n * to the `ignoreSearch` option, but it allows you to ignore just specific\n * params (while continuing to match on the others).\n *\n * @private\n * @param cache\n * @param request\n * @param matchOptions\n * @param ignoreParams\n * @returns\n */\nasync function cacheMatchIgnoreParams(\n  cache: Cache,\n  request: Request,\n  ignoreParams: string[],\n  matchOptions?: CacheQueryOptions,\n): Promise<Response | undefined> {\n  const strippedRequestURL = stripParams(request.url, ignoreParams);\n\n  // If the request doesn't include any ignored params, match as normal.\n  if (request.url === strippedRequestURL) {\n    return cache.match(request, matchOptions);\n  }\n\n  // Otherwise, match by comparing keys\n  const keysOptions = { ...matchOptions, ignoreSearch: true };\n  const cacheKeys = await cache.keys(request, keysOptions);\n\n  for (const cacheKey of cacheKeys) {\n    const strippedCacheKeyURL = stripParams(cacheKey.url, ignoreParams);\n    if (strippedRequestURL === strippedCacheKeyURL) {\n      return cache.match(cacheKey, matchOptions);\n    }\n  }\n  return;\n}\n\nexport { cacheMatchIgnoreParams };\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n/**\n * The Deferred class composes Promises in a way that allows for them to be\n * resolved or rejected from outside the constructor. In most cases promises\n * should be used directly, but Deferreds can be necessary when the logic to\n * resolve a promise must be separate.\n *\n * @private\n */\nclass Deferred<T> {\n  promise: Promise<T>;\n  resolve!: (value: T) => void;\n  reject!: (reason?: any) => void;\n\n  /**\n   * Creates a promise and exposes its resolve and reject functions as methods.\n   */\n  constructor() {\n    this.promise = new Promise((resolve, reject) => {\n      this.resolve = resolve;\n      this.reject = reject;\n    });\n  }\n}\n\nexport { Deferred };\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { quotaErrorCallbacks } from \"../models/quotaErrorCallbacks.js\";\nimport { logger } from \"./logger.js\";\n\n/**\n * Runs all of the callback functions, one at a time sequentially, in the order\n * in which they were registered.\n *\n * @private\n */\nexport const executeQuotaErrorCallbacks = async (): Promise<void> => {\n  if (process.env.NODE_ENV !== \"production\") {\n    logger.log(`About to run ${quotaErrorCallbacks.size} callbacks to clean up caches.`);\n  }\n\n  for (const callback of quotaErrorCallbacks) {\n    await callback();\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(callback, \"is complete.\");\n    }\n  }\n\n  if (process.env.NODE_ENV !== \"production\") {\n    logger.log(\"Finished running callbacks.\");\n  }\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n// Give TypeScript the correct global.\ndeclare const self: ServiceWorkerGlobalScope;\n\nconst SUBSTRING_TO_FIND = \"-precache-\";\n\n/**\n * Cleans up incompatible precaches that were created by older versions of\n * Serwist, by a service worker registered under the current scope.\n *\n * This is meant to be called as part of the `activate` event.\n *\n * This should be safe to use as long as you don't include `substringToFind`\n * (defaulting to `-precache-`) in your non-precache cache names.\n *\n * @param currentPrecacheName The cache name currently in use for\n * precaching. This cache won't be deleted.\n * @param substringToFind Cache names which include this\n * substring will be deleted (excluding `currentPrecacheName`).\n * @returns A list of all the cache names that were deleted.\n * @private\n */\nexport const deleteOutdatedCaches = async (currentPrecacheName: string, substringToFind: string = SUBSTRING_TO_FIND): Promise<string[]> => {\n  const cacheNames = await self.caches.keys();\n\n  const cacheNamesToDelete = cacheNames.filter((cacheName) => {\n    return cacheName.includes(substringToFind) && cacheName.includes(self.registration.scope) && cacheName !== currentPrecacheName;\n  });\n\n  await Promise.all(cacheNamesToDelete.map((cacheName) => self.caches.delete(cacheName)));\n\n  return cacheNamesToDelete;\n};\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { cacheNames as privateCacheNames } from \"./cacheNames.js\";\nimport { deleteOutdatedCaches } from \"./deleteOutdatedCaches.js\";\nimport { logger } from \"./logger.js\";\n\ndeclare const self: ServiceWorkerGlobalScope;\n\n/**\n * Adds an `activate` event listener which will clean up incompatible\n * precaches that were created by older versions of Serwist.\n */\nexport const cleanupOutdatedCaches = (cacheName?: string): void => {\n  self.addEventListener(\"activate\", (event: ExtendableEvent) => {\n    event.waitUntil(\n      deleteOutdatedCaches(privateCacheNames.getPrecacheName(cacheName)).then((cachesDeleted) => {\n        if (process.env.NODE_ENV !== \"production\") {\n          if (cachesDeleted.length > 0) {\n            logger.log(\"The following out-of-date precaches were cleaned up automatically:\", cachesDeleted);\n          }\n        }\n      }),\n    );\n  });\n};\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n// Give TypeScript the correct global.\ndeclare let self: ServiceWorkerGlobalScope;\n\n/**\n * Claims any currently available clients once the service worker\n * becomes active. This is normally used in conjunction with `skipWaiting()`.\n */\nexport const clientsClaim = (): void => {\n  self.addEventListener(\"activate\", () => self.clients.claim());\n};\n", "/*\n  Copyright 2020 Google LLC\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n/**\n * A utility method that makes it easier to use `event.waitUntil` with\n * async functions and return the result.\n *\n * @param event\n * @param asyncFn\n * @returns\n * @private\n */\nexport const waitUntil = <T = any>(event: ExtendableEvent, asyncFn: () => Promise<T>): Promise<T> => {\n  const returnPromise = asyncFn();\n  event.waitUntil(returnPromise);\n  return returnPromise;\n};\n", "const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);\n\nlet idbProxyableTypes;\nlet cursorAdvanceMethods;\n// This is a function to prevent it throwing up in node environments.\nfunction getIdbProxyableTypes() {\n    return (idbProxyableTypes ||\n        (idbProxyableTypes = [\n            IDBDatabase,\n            IDBObjectStore,\n            IDBIndex,\n            IDBCursor,\n            IDBTransaction,\n        ]));\n}\n// This is a function to prevent it throwing up in node environments.\nfunction getCursorAdvanceMethods() {\n    return (cursorAdvanceMethods ||\n        (cursorAdvanceMethods = [\n            IDBCursor.prototype.advance,\n            IDBCursor.prototype.continue,\n            IDBCursor.prototype.continuePrimaryKey,\n        ]));\n}\nconst transactionDoneMap = new WeakMap();\nconst transformCache = new WeakMap();\nconst reverseTransformCache = new WeakMap();\nfunction promisifyRequest(request) {\n    const promise = new Promise((resolve, reject) => {\n        const unlisten = () => {\n            request.removeEventListener('success', success);\n            request.removeEventListener('error', error);\n        };\n        const success = () => {\n            resolve(wrap(request.result));\n            unlisten();\n        };\n        const error = () => {\n            reject(request.error);\n            unlisten();\n        };\n        request.addEventListener('success', success);\n        request.addEventListener('error', error);\n    });\n    // This mapping exists in reverseTransformCache but doesn't exist in transformCache. This\n    // is because we create many promises from a single IDBRequest.\n    reverseTransformCache.set(promise, request);\n    return promise;\n}\nfunction cacheDonePromiseForTransaction(tx) {\n    // Early bail if we've already created a done promise for this transaction.\n    if (transactionDoneMap.has(tx))\n        return;\n    const done = new Promise((resolve, reject) => {\n        const unlisten = () => {\n            tx.removeEventListener('complete', complete);\n            tx.removeEventListener('error', error);\n            tx.removeEventListener('abort', error);\n        };\n        const complete = () => {\n            resolve();\n            unlisten();\n        };\n        const error = () => {\n            reject(tx.error || new DOMException('AbortError', 'AbortError'));\n            unlisten();\n        };\n        tx.addEventListener('complete', complete);\n        tx.addEventListener('error', error);\n        tx.addEventListener('abort', error);\n    });\n    // Cache it for later retrieval.\n    transactionDoneMap.set(tx, done);\n}\nlet idbProxyTraps = {\n    get(target, prop, receiver) {\n        if (target instanceof IDBTransaction) {\n            // Special handling for transaction.done.\n            if (prop === 'done')\n                return transactionDoneMap.get(target);\n            // Make tx.store return the only store in the transaction, or undefined if there are many.\n            if (prop === 'store') {\n                return receiver.objectStoreNames[1]\n                    ? undefined\n                    : receiver.objectStore(receiver.objectStoreNames[0]);\n            }\n        }\n        // Else transform whatever we get back.\n        return wrap(target[prop]);\n    },\n    set(target, prop, value) {\n        target[prop] = value;\n        return true;\n    },\n    has(target, prop) {\n        if (target instanceof IDBTransaction &&\n            (prop === 'done' || prop === 'store')) {\n            return true;\n        }\n        return prop in target;\n    },\n};\nfunction replaceTraps(callback) {\n    idbProxyTraps = callback(idbProxyTraps);\n}\nfunction wrapFunction(func) {\n    // Due to expected object equality (which is enforced by the caching in `wrap`), we\n    // only create one new func per func.\n    // Cursor methods are special, as the behaviour is a little more different to standard IDB. In\n    // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the\n    // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense\n    // with real promises, so each advance methods returns a new promise for the cursor object, or\n    // undefined if the end of the cursor has been reached.\n    if (getCursorAdvanceMethods().includes(func)) {\n        return function (...args) {\n            // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n            // the original object.\n            func.apply(unwrap(this), args);\n            return wrap(this.request);\n        };\n    }\n    return function (...args) {\n        // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use\n        // the original object.\n        return wrap(func.apply(unwrap(this), args));\n    };\n}\nfunction transformCachableValue(value) {\n    if (typeof value === 'function')\n        return wrapFunction(value);\n    // This doesn't return, it just creates a 'done' promise for the transaction,\n    // which is later returned for transaction.done (see idbObjectHandler).\n    if (value instanceof IDBTransaction)\n        cacheDonePromiseForTransaction(value);\n    if (instanceOfAny(value, getIdbProxyableTypes()))\n        return new Proxy(value, idbProxyTraps);\n    // Return the same value back if we're not going to transform it.\n    return value;\n}\nfunction wrap(value) {\n    // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because\n    // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.\n    if (value instanceof IDBRequest)\n        return promisifyRequest(value);\n    // If we've already transformed this value before, reuse the transformed value.\n    // This is faster, but it also provides object equality.\n    if (transformCache.has(value))\n        return transformCache.get(value);\n    const newValue = transformCachableValue(value);\n    // Not all types are transformed.\n    // These may be primitive types, so they can't be WeakMap keys.\n    if (newValue !== value) {\n        transformCache.set(value, newValue);\n        reverseTransformCache.set(newValue, value);\n    }\n    return newValue;\n}\nconst unwrap = (value) => reverseTransformCache.get(value);\n\n/**\n * Open a database.\n *\n * @param name Name of the database.\n * @param version Schema version.\n * @param callbacks Additional callbacks.\n */\nfunction openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {\n    const request = indexedDB.open(name, version);\n    const openPromise = wrap(request);\n    if (upgrade) {\n        request.addEventListener('upgradeneeded', (event) => {\n            upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);\n        });\n    }\n    if (blocked) {\n        request.addEventListener('blocked', (event) => blocked(\n        // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n        event.oldVersion, event.newVersion, event));\n    }\n    openPromise\n        .then((db) => {\n        if (terminated)\n            db.addEventListener('close', () => terminated());\n        if (blocking) {\n            db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));\n        }\n    })\n        .catch(() => { });\n    return openPromise;\n}\n/**\n * Delete a database.\n *\n * @param name Name of the database.\n */\nfunction deleteDB(name, { blocked } = {}) {\n    const request = indexedDB.deleteDatabase(name);\n    if (blocked) {\n        request.addEventListener('blocked', (event) => blocked(\n        // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405\n        event.oldVersion, event));\n    }\n    return wrap(request).then(() => undefined);\n}\n\nconst readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];\nconst writeMethods = ['put', 'add', 'delete', 'clear'];\nconst cachedMethods = new Map();\nfunction getMethod(target, prop) {\n    if (!(target instanceof IDBDatabase &&\n        !(prop in target) &&\n        typeof prop === 'string')) {\n        return;\n    }\n    if (cachedMethods.get(prop))\n        return cachedMethods.get(prop);\n    const targetFuncName = prop.replace(/FromIndex$/, '');\n    const useIndex = prop !== targetFuncName;\n    const isWrite = writeMethods.includes(targetFuncName);\n    if (\n    // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.\n    !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||\n        !(isWrite || readMethods.includes(targetFuncName))) {\n        return;\n    }\n    const method = async function (storeName, ...args) {\n        // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(\n        const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');\n        let target = tx.store;\n        if (useIndex)\n            target = target.index(args.shift());\n        // Must reject if op rejects.\n        // If it's a write operation, must reject if tx.done rejects.\n        // Must reject with op rejection first.\n        // Must resolve with op value.\n        // Must handle both promises (no unhandled rejections)\n        return (await Promise.all([\n            target[targetFuncName](...args),\n            isWrite && tx.done,\n        ]))[0];\n    };\n    cachedMethods.set(prop, method);\n    return method;\n}\nreplaceTraps((oldTraps) => ({\n    ...oldTraps,\n    get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),\n    has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),\n}));\n\nconst advanceMethodProps = ['continue', 'continuePrimaryKey', 'advance'];\nconst methodMap = {};\nconst advanceResults = new WeakMap();\nconst ittrProxiedCursorToOriginalProxy = new WeakMap();\nconst cursorIteratorTraps = {\n    get(target, prop) {\n        if (!advanceMethodProps.includes(prop))\n            return target[prop];\n        let cachedFunc = methodMap[prop];\n        if (!cachedFunc) {\n            cachedFunc = methodMap[prop] = function (...args) {\n                advanceResults.set(this, ittrProxiedCursorToOriginalProxy.get(this)[prop](...args));\n            };\n        }\n        return cachedFunc;\n    },\n};\nasync function* iterate(...args) {\n    // tslint:disable-next-line:no-this-assignment\n    let cursor = this;\n    if (!(cursor instanceof IDBCursor)) {\n        cursor = await cursor.openCursor(...args);\n    }\n    if (!cursor)\n        return;\n    cursor = cursor;\n    const proxiedCursor = new Proxy(cursor, cursorIteratorTraps);\n    ittrProxiedCursorToOriginalProxy.set(proxiedCursor, cursor);\n    // Map this double-proxy back to the original, so other cursor methods work.\n    reverseTransformCache.set(proxiedCursor, unwrap(cursor));\n    while (cursor) {\n        yield proxiedCursor;\n        // If one of the advancing methods was not called, call continue().\n        cursor = await (advanceResults.get(proxiedCursor) || cursor.continue());\n        advanceResults.delete(proxiedCursor);\n    }\n}\nfunction isIteratorProp(target, prop) {\n    return ((prop === Symbol.asyncIterator &&\n        instanceOfAny(target, [IDBIndex, IDBObjectStore, IDBCursor])) ||\n        (prop === 'iterate' && instanceOfAny(target, [IDBIndex, IDBObjectStore])));\n}\nreplaceTraps((oldTraps) => ({\n    ...oldTraps,\n    get(target, prop, receiver) {\n        if (isIteratorProp(target, prop))\n            return iterate;\n        return oldTraps.get(target, prop, receiver);\n    },\n    has(target, prop) {\n        return isIteratorProp(target, prop) || oldTraps.has(target, prop);\n    },\n}));\n\nexport { deleteDB, openDB, unwrap, wrap };\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { canConstructResponseFromBodyStream } from \"./utils/canConstructResponseFromBodyStream.js\";\nimport { SerwistError } from \"./utils/SerwistError.js\";\n\n/**\n * Allows developers to copy a response and modify its `headers`, `status`,\n * or `statusText` values (the [valid options](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response#options)\n * when constructing a `Response` object).\n * To modify these values, pass a function as the second argument. That\n * function will be invoked with the options of the initial `Response` object.\n * The return value of this function will be used as the options for the new `Response` object.\n * To change the values either modify the passed parameter(s) and return it or return a totally\n * new object.\n *\n * This method is intentionally limited to same-origin responses, regardless of\n * whether CORS was used or not.\n *\n * @param response The initial response.\n * @param modifier The function used to modify the options of the `Response` object.\n */\nexport const copyResponse = async (response: Response, modifier?: (responseInit: ResponseInit) => ResponseInit): Promise<Response> => {\n  let origin = null;\n  // If response.url isn't set, assume it's cross-origin and keep origin null.\n  if (response.url) {\n    const responseURL = new URL(response.url);\n    origin = responseURL.origin;\n  }\n\n  if (origin !== self.location.origin) {\n    throw new SerwistError(\"cross-origin-copy-response\", { origin });\n  }\n\n  const clonedResponse = response.clone();\n\n  // Create a fresh `ResponseInit` object by cloning the headers.\n  const responseInit: ResponseInit = {\n    headers: new Headers(clonedResponse.headers),\n    status: clonedResponse.status,\n    statusText: clonedResponse.statusText,\n  };\n\n  // Apply any user modifications.\n  const modifiedResponseInit = modifier ? modifier(responseInit) : responseInit;\n\n  // Create the new response from the body stream and `ResponseInit`\n  // modifications. Note: not all browsers support the Response.body stream,\n  // so fall back to reading the entire body into memory as a blob.\n  const body = canConstructResponseFromBodyStream() ? clonedResponse.body : await clonedResponse.blob();\n\n  return new Response(body, modifiedResponseInit);\n};\n", "declare const self: ServiceWorkerGlobalScope;\n\n/**\n * Disables Serwist's logging in development mode.\n *\n * @see https://serwist.pages.dev/docs/serwist/core/disable-dev-logs\n */\nexport const disableDevLogs = (): void => {\n  self.__WB_DISABLE_DEV_LOGS = true;\n};\n", "/*\n  Copyright 2021 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { DBSchema, IDBPDatabase } from \"idb\";\nimport { openDB } from \"idb\";\n\nimport type { RequestData } from \"./StorableRequest.js\";\n\ninterface BackgroundSyncQueueDBSchema extends DBSchema {\n  requests: {\n    key: number;\n    value: BackgroundSyncQueueStoreEntry;\n    indexes: { queueName: string };\n  };\n}\n\nconst BACKGROUND_SYNC_DB_VERSION = 3;\nconst BACKGROUND_SYNC_DB_NAME = \"serwist-background-sync\";\nconst REQUEST_OBJECT_STORE_NAME = \"requests\";\nconst QUEUE_NAME_INDEX = \"queueName\";\n\nexport interface UnidentifiedQueueStoreEntry {\n  requestData: RequestData;\n  timestamp: number;\n  id?: number;\n  queueName?: string;\n  metadata?: Record<string, unknown>;\n}\n\nexport interface BackgroundSyncQueueStoreEntry extends UnidentifiedQueueStoreEntry {\n  id: number;\n}\n\n/**\n * A class to interact directly an IndexedDB created specifically to save and\n * retrieve QueueStoreEntries. This class encapsulates all the schema details\n * to store the representation of a Queue.\n *\n * @private\n */\n\nexport class BackgroundSyncQueueDb {\n  private _db: IDBPDatabase<BackgroundSyncQueueDBSchema> | null = null;\n\n  /**\n   * Add QueueStoreEntry to underlying db.\n   *\n   * @param entry\n   */\n  async addEntry(entry: UnidentifiedQueueStoreEntry): Promise<void> {\n    const db = await this.getDb();\n    const tx = db.transaction(REQUEST_OBJECT_STORE_NAME, \"readwrite\", {\n      durability: \"relaxed\",\n    });\n    await tx.store.add(entry as BackgroundSyncQueueStoreEntry);\n    await tx.done;\n  }\n\n  /**\n   * Returns the first entry id in the ObjectStore.\n   *\n   * @returns\n   */\n  async getFirstEntryId(): Promise<number | undefined> {\n    const db = await this.getDb();\n    const cursor = await db.transaction(REQUEST_OBJECT_STORE_NAME).store.openCursor();\n    return cursor?.value.id;\n  }\n\n  /**\n   * Get all the entries filtered by index\n   *\n   * @param queueName\n   * @returns\n   */\n  async getAllEntriesByQueueName(queueName: string): Promise<BackgroundSyncQueueStoreEntry[]> {\n    const db = await this.getDb();\n    const results = await db.getAllFromIndex(REQUEST_OBJECT_STORE_NAME, QUEUE_NAME_INDEX, IDBKeyRange.only(queueName));\n    return results ? results : ([] as BackgroundSyncQueueStoreEntry[]);\n  }\n\n  /**\n   * Returns the number of entries filtered by index\n   *\n   * @param queueName\n   * @returns\n   */\n  async getEntryCountByQueueName(queueName: string): Promise<number> {\n    const db = await this.getDb();\n    return db.countFromIndex(REQUEST_OBJECT_STORE_NAME, QUEUE_NAME_INDEX, IDBKeyRange.only(queueName));\n  }\n\n  /**\n   * Deletes a single entry by id.\n   *\n   * @param id the id of the entry to be deleted\n   */\n  async deleteEntry(id: number): Promise<void> {\n    const db = await this.getDb();\n    await db.delete(REQUEST_OBJECT_STORE_NAME, id);\n  }\n\n  /**\n   *\n   * @param queueName\n   * @returns\n   */\n  async getFirstEntryByQueueName(queueName: string): Promise<BackgroundSyncQueueStoreEntry | undefined> {\n    return await this.getEndEntryFromIndex(IDBKeyRange.only(queueName), \"next\");\n  }\n\n  /**\n   *\n   * @param queueName\n   * @returns\n   */\n  async getLastEntryByQueueName(queueName: string): Promise<BackgroundSyncQueueStoreEntry | undefined> {\n    return await this.getEndEntryFromIndex(IDBKeyRange.only(queueName), \"prev\");\n  }\n\n  /**\n   * Returns either the first or the last entries, depending on direction.\n   * Filtered by index.\n   *\n   * @param direction\n   * @param query\n   * @returns\n   * @private\n   */\n  async getEndEntryFromIndex(query: IDBKeyRange, direction: IDBCursorDirection): Promise<BackgroundSyncQueueStoreEntry | undefined> {\n    const db = await this.getDb();\n\n    const cursor = await db.transaction(REQUEST_OBJECT_STORE_NAME).store.index(QUEUE_NAME_INDEX).openCursor(query, direction);\n    return cursor?.value;\n  }\n\n  /**\n   * Returns an open connection to the database.\n   *\n   * @private\n   */\n  private async getDb() {\n    if (!this._db) {\n      this._db = await openDB(BACKGROUND_SYNC_DB_NAME, BACKGROUND_SYNC_DB_VERSION, {\n        upgrade: this._upgradeDb,\n      });\n    }\n    return this._db;\n  }\n\n  /**\n   * Upgrades QueueDB\n   *\n   * @param db\n   * @param oldVersion\n   * @private\n   */\n  private _upgradeDb(db: IDBPDatabase<BackgroundSyncQueueDBSchema>, oldVersion: number) {\n    if (oldVersion > 0 && oldVersion < BACKGROUND_SYNC_DB_VERSION) {\n      if (db.objectStoreNames.contains(REQUEST_OBJECT_STORE_NAME)) {\n        db.deleteObjectStore(REQUEST_OBJECT_STORE_NAME);\n      }\n    }\n\n    const objStore = db.createObjectStore(REQUEST_OBJECT_STORE_NAME, {\n      autoIncrement: true,\n      keyPath: \"id\",\n    });\n    objStore.createIndex(QUEUE_NAME_INDEX, QUEUE_NAME_INDEX, { unique: false });\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\nimport { assert } from \"../../utils/assert.js\";\nimport type { BackgroundSyncQueueStoreEntry, UnidentifiedQueueStoreEntry } from \"./BackgroundSyncQueueDb.js\";\nimport { BackgroundSyncQueueDb } from \"./BackgroundSyncQueueDb.js\";\n\n/**\n * A class to manage storing requests from a Queue in IndexedDB,\n * indexed by their queue name for easier access.\n *\n * Most developers will not need to access this class directly;\n * it is exposed for advanced use cases.\n */\nexport class BackgroundSyncQueueStore {\n  private readonly _queueName: string;\n  private readonly _queueDb: BackgroundSyncQueueDb;\n\n  /**\n   * Associates this instance with a Queue instance, so entries added can be\n   * identified by their queue name.\n   *\n   * @param queueName\n   */\n  constructor(queueName: string) {\n    this._queueName = queueName;\n    this._queueDb = new BackgroundSyncQueueDb();\n  }\n\n  /**\n   * Append an entry last in the queue.\n   *\n   * @param entry\n   */\n  async pushEntry(entry: UnidentifiedQueueStoreEntry): Promise<void> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(entry, \"object\", {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueueStore\",\n        funcName: \"pushEntry\",\n        paramName: \"entry\",\n      });\n      assert!.isType(entry.requestData, \"object\", {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueueStore\",\n        funcName: \"pushEntry\",\n        paramName: \"entry.requestData\",\n      });\n    }\n\n    delete entry.id;\n    entry.queueName = this._queueName;\n\n    await this._queueDb.addEntry(entry);\n  }\n\n  /**\n   * Prepend an entry first in the queue.\n   *\n   * @param entry\n   */\n  async unshiftEntry(entry: UnidentifiedQueueStoreEntry): Promise<void> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(entry, \"object\", {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueueStore\",\n        funcName: \"unshiftEntry\",\n        paramName: \"entry\",\n      });\n      assert!.isType(entry.requestData, \"object\", {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueueStore\",\n        funcName: \"unshiftEntry\",\n        paramName: \"entry.requestData\",\n      });\n    }\n\n    const firstId = await this._queueDb.getFirstEntryId();\n\n    if (firstId) {\n      // Pick an ID one less than the lowest ID in the object store.\n      entry.id = firstId - 1;\n    } else {\n      delete entry.id;\n    }\n    entry.queueName = this._queueName;\n\n    await this._queueDb.addEntry(entry);\n  }\n\n  /**\n   * Removes and returns the last entry in the queue matching the `queueName`.\n   *\n   * @returns\n   */\n  async popEntry(): Promise<BackgroundSyncQueueStoreEntry | undefined> {\n    return this._removeEntry(await this._queueDb.getLastEntryByQueueName(this._queueName));\n  }\n\n  /**\n   * Removes and returns the first entry in the queue matching the `queueName`.\n   *\n   * @returns\n   */\n  async shiftEntry(): Promise<BackgroundSyncQueueStoreEntry | undefined> {\n    return this._removeEntry(await this._queueDb.getFirstEntryByQueueName(this._queueName));\n  }\n\n  /**\n   * Returns all entries in the store matching the `queueName`.\n   *\n   * @returns\n   */\n  async getAll(): Promise<BackgroundSyncQueueStoreEntry[]> {\n    return await this._queueDb.getAllEntriesByQueueName(this._queueName);\n  }\n\n  /**\n   * Returns the number of entries in the store matching the `queueName`.\n   *\n   * @returns\n   */\n  async size(): Promise<number> {\n    return await this._queueDb.getEntryCountByQueueName(this._queueName);\n  }\n\n  /**\n   * Deletes the entry for the given ID.\n   *\n   * WARNING: this method does not ensure the deleted entry belongs to this\n   * queue (i.e. matches the `queueName`). But this limitation is acceptable\n   * as this class is not publicly exposed. An additional check would make\n   * this method slower than it needs to be.\n   *\n   * @param id\n   */\n  async deleteEntry(id: number): Promise<void> {\n    await this._queueDb.deleteEntry(id);\n  }\n\n  /**\n   * Removes and returns the first or last entry in the queue (based on the\n   * `direction` argument) matching the `queueName`.\n   *\n   * @returns\n   * @private\n   */\n  async _removeEntry(entry?: BackgroundSyncQueueStoreEntry): Promise<BackgroundSyncQueueStoreEntry | undefined> {\n    if (entry) {\n      await this.deleteEntry(entry.id);\n    }\n    return entry;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { MapLikeObject } from \"../../types.js\";\nimport { assert } from \"../../utils/assert.js\";\n\ntype SerializableProperties = \"method\" | \"referrer\" | \"referrerPolicy\" | \"mode\" | \"credentials\" | \"cache\" | \"redirect\" | \"integrity\" | \"keepalive\";\n\nconst serializableProperties: SerializableProperties[] = [\n  \"method\",\n  \"referrer\",\n  \"referrerPolicy\",\n  \"mode\",\n  \"credentials\",\n  \"cache\",\n  \"redirect\",\n  \"integrity\",\n  \"keepalive\",\n];\n\nexport interface RequestData extends MapLikeObject {\n  url: string;\n  headers: MapLikeObject;\n  body?: ArrayBuffer;\n}\n\n/**\n * A class to make it easier to serialize and de-serialize requests so they\n * can be stored in IndexedDB.\n *\n * Most developers will not need to access this class directly;\n * it is exposed for advanced use cases.\n */\nexport class StorableRequest {\n  private readonly _requestData: RequestData;\n\n  /**\n   * Converts a Request object to a plain object that can be structured\n   * cloned or stringified to JSON.\n   *\n   * @param request\n   * @returns\n   */\n  static async fromRequest(request: Request): Promise<StorableRequest> {\n    const requestData: RequestData = {\n      url: request.url,\n      headers: {},\n    };\n\n    // Set the body if present.\n    if (request.method !== \"GET\") {\n      // Use ArrayBuffer to support non-text request bodies.\n      // NOTE: we can't use Blobs becuse Safari doesn't support storing\n      // Blobs in IndexedDB in some cases:\n      // https://github.com/dfahlander/Dexie.js/issues/618#issuecomment-398348457\n      requestData.body = await request.clone().arrayBuffer();\n    }\n\n    request.headers.forEach((value, key) => {\n      requestData.headers[key] = value;\n    });\n\n    // Add all other serializable request properties\n    for (const prop of serializableProperties) {\n      if (request[prop] !== undefined) {\n        requestData[prop] = request[prop];\n      }\n    }\n\n    return new StorableRequest(requestData);\n  }\n\n  /**\n   * Accepts an object of request data that can be used to construct a\n   * `Request` object but can also be stored in IndexedDB.\n   *\n   * @param requestData An object of request data that includes the `url` plus any relevant property of\n   * [`requestInit`](https://fetch.spec.whatwg.org/#requestinit).\n   */\n  constructor(requestData: RequestData) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(requestData, \"object\", {\n        moduleName: \"serwist\",\n        className: \"StorableRequest\",\n        funcName: \"constructor\",\n        paramName: \"requestData\",\n      });\n      assert!.isType(requestData.url, \"string\", {\n        moduleName: \"serwist\",\n        className: \"StorableRequest\",\n        funcName: \"constructor\",\n        paramName: \"requestData.url\",\n      });\n    }\n\n    // If the request's mode is `navigate`, convert it to `same-origin` since\n    // navigation requests can't be constructed via script.\n    if (requestData.mode === \"navigate\") {\n      requestData.mode = \"same-origin\";\n    }\n\n    this._requestData = requestData;\n  }\n\n  /**\n   * Returns a deep clone of the instance's `requestData` object.\n   *\n   * @returns\n   */\n  toObject(): RequestData {\n    const requestData = Object.assign({}, this._requestData);\n    requestData.headers = Object.assign({}, this._requestData.headers);\n    if (requestData.body) {\n      requestData.body = requestData.body.slice(0);\n    }\n\n    return requestData;\n  }\n\n  /**\n   * Converts this instance to a Request.\n   *\n   * @returns\n   */\n  toRequest(): Request {\n    return new Request(this._requestData.url, this._requestData);\n  }\n\n  /**\n   * Creates and returns a deep clone of the instance.\n   *\n   * @returns\n   */\n  clone(): StorableRequest {\n    return new StorableRequest(this.toObject());\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\nimport { assert } from \"../../utils/assert.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport type { BackgroundSyncQueueStoreEntry, UnidentifiedQueueStoreEntry } from \"./BackgroundSyncQueueDb.js\";\nimport { BackgroundSyncQueueStore } from \"./BackgroundSyncQueueStore.js\";\nimport { StorableRequest } from \"./StorableRequest.js\";\n\n// See https://github.com/GoogleChrome/workbox/issues/2946\ninterface SyncManager {\n  getTags(): Promise<string[]>;\n  register(tag: string): Promise<void>;\n}\n\ndeclare global {\n  interface ServiceWorkerRegistration {\n    readonly sync: SyncManager;\n  }\n\n  interface SyncEvent extends ExtendableEvent {\n    readonly lastChance: boolean;\n    readonly tag: string;\n  }\n\n  interface ServiceWorkerGlobalScopeEventMap {\n    sync: SyncEvent;\n  }\n}\n\n// Give TypeScript the correct global.\ndeclare const self: ServiceWorkerGlobalScope;\n\ninterface OnSyncCallbackOptions {\n  queue: BackgroundSyncQueue;\n}\n\ntype OnSyncCallback = (options: OnSyncCallbackOptions) => void | Promise<void>;\n\nexport interface BackgroundSyncQueueOptions {\n  /**\n   * If `true`, instead of attempting to use background sync events, always attempt\n   * to replay queued request at service worker startup. Most folks will not need\n   * this, unless you explicitly target a runtime like Electron that exposes the\n   * interfaces for background sync, but does not have a working implementation.\n   *\n   * @default false\n   */\n  forceSyncFallback?: boolean;\n  /**\n   * The amount of time (in minutes) a request may be retried. After this amount\n   * of time has passed, the request will be deleted from the queue.\n   *\n   * @default 60 * 24 * 7\n   */\n  maxRetentionTime?: number;\n  /**\n   * A function that gets invoked whenever the 'sync' event fires. The function\n   * is invoked with an object containing the `queue` property (referencing this\n   * instance), and you can use the callback to customize the replay behavior of\n   * the queue. When not set the `replayRequests()` method is called. Note: if the\n   * replay fails after a sync event, make sure you throw an error, so the browser\n   * knows to retry the sync event later.\n   */\n  onSync?: OnSyncCallback;\n}\n\nexport interface BackgroundSyncQueueEntry {\n  /**\n   * The request to store in the queue.\n   */\n  request: Request;\n  /**\n   * The timestamp (Epoch time in milliseconds) when the request was first added\n   * to the queue. This is used along with `maxRetentionTime` to remove outdated\n   * requests. In general you don't need to set this value, as it's automatically\n   * set for you (defaulting to `Date.now()`), but you can update it if you don't\n   * want particular requests to expire.\n   */\n  timestamp?: number;\n  /**\n   * Any metadata you want associated with the stored request. When requests are\n   * replayed you'll have access to this metadata object in case you need to modify\n   * the request beforehand.\n   */\n  metadata?: Record<string, unknown>;\n}\n\nconst TAG_PREFIX = \"serwist-background-sync\";\nconst MAX_RETENTION_TIME = 60 * 24 * 7; // 7 days in minutes\n\nconst queueNames = new Set<string>();\n\n/**\n * Converts a QueueStore entry into the format exposed by Queue. This entails\n * converting the request data into a real request and omitting the `id` and\n * `queueName` properties.\n *\n * @param queueStoreEntry\n * @returns\n * @private\n */\nconst convertEntry = (queueStoreEntry: UnidentifiedQueueStoreEntry): BackgroundSyncQueueEntry => {\n  const queueEntry: BackgroundSyncQueueEntry = {\n    request: new StorableRequest(queueStoreEntry.requestData).toRequest(),\n    timestamp: queueStoreEntry.timestamp,\n  };\n  if (queueStoreEntry.metadata) {\n    queueEntry.metadata = queueStoreEntry.metadata;\n  }\n  return queueEntry;\n};\n\n/**\n * A class to manage storing failed requests in IndexedDB and retrying them\n * later. All parts of the storing and replaying process are observable via\n * callbacks.\n */\nexport class BackgroundSyncQueue {\n  private readonly _name: string;\n  private readonly _onSync: OnSyncCallback;\n  private readonly _maxRetentionTime: number;\n  private readonly _queueStore: BackgroundSyncQueueStore;\n  private readonly _forceSyncFallback: boolean;\n  private _syncInProgress = false;\n  private _requestsAddedDuringSync = false;\n\n  /**\n   * Creates an instance of Queue with the given options\n   *\n   * @param name The unique name for this queue. This name must be\n   * unique as it's used to register sync events and store requests\n   * in IndexedDB specific to this instance. An error will be thrown if\n   * a duplicate name is detected.\n   * @param options\n   */\n  constructor(name: string, { forceSyncFallback, onSync, maxRetentionTime }: BackgroundSyncQueueOptions = {}) {\n    // Ensure the store name is not already being used\n    if (queueNames.has(name)) {\n      throw new SerwistError(\"duplicate-queue-name\", { name });\n    }\n    queueNames.add(name);\n\n    this._name = name;\n    this._onSync = onSync || this.replayRequests;\n    this._maxRetentionTime = maxRetentionTime || MAX_RETENTION_TIME;\n    this._forceSyncFallback = Boolean(forceSyncFallback);\n    this._queueStore = new BackgroundSyncQueueStore(this._name);\n\n    this._addSyncListener();\n  }\n\n  /**\n   * @returns\n   */\n  get name(): string {\n    return this._name;\n  }\n\n  /**\n   * Stores the passed request in IndexedDB (with its timestamp and any\n   * metadata) at the end of the queue.\n   *\n   * @param entry\n   */\n  async pushRequest(entry: BackgroundSyncQueueEntry): Promise<void> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(entry, \"object\", {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueue\",\n        funcName: \"pushRequest\",\n        paramName: \"entry\",\n      });\n      assert!.isInstance(entry.request, Request, {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueue\",\n        funcName: \"pushRequest\",\n        paramName: \"entry.request\",\n      });\n    }\n\n    await this._addRequest(entry, \"push\");\n  }\n\n  /**\n   * Stores the passed request in IndexedDB (with its timestamp and any\n   * metadata) at the beginning of the queue.\n   *\n   * @param entry\n   */\n  async unshiftRequest(entry: BackgroundSyncQueueEntry): Promise<void> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(entry, \"object\", {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueue\",\n        funcName: \"unshiftRequest\",\n        paramName: \"entry\",\n      });\n      assert!.isInstance(entry.request, Request, {\n        moduleName: \"serwist\",\n        className: \"BackgroundSyncQueue\",\n        funcName: \"unshiftRequest\",\n        paramName: \"entry.request\",\n      });\n    }\n\n    await this._addRequest(entry, \"unshift\");\n  }\n\n  /**\n   * Removes and returns the last request in the queue (along with its\n   * timestamp and any metadata).\n   *\n   * @returns\n   */\n  async popRequest(): Promise<BackgroundSyncQueueEntry | undefined> {\n    return this._removeRequest(\"pop\");\n  }\n\n  /**\n   * Removes and returns the first request in the queue (along with its\n   * timestamp and any metadata).\n   *\n   * @returns\n   */\n  async shiftRequest(): Promise<BackgroundSyncQueueEntry | undefined> {\n    return this._removeRequest(\"shift\");\n  }\n\n  /**\n   * Returns all the entries that have not expired (per `maxRetentionTime`).\n   * Any expired entries are removed from the queue.\n   *\n   * @returns\n   */\n  async getAll(): Promise<BackgroundSyncQueueEntry[]> {\n    const allEntries = await this._queueStore.getAll();\n    const now = Date.now();\n\n    const unexpiredEntries = [];\n    for (const entry of allEntries) {\n      // Ignore requests older than maxRetentionTime. Call this function\n      // recursively until an unexpired request is found.\n      const maxRetentionTimeInMs = this._maxRetentionTime * 60 * 1000;\n      if (now - entry.timestamp > maxRetentionTimeInMs) {\n        await this._queueStore.deleteEntry(entry.id);\n      } else {\n        unexpiredEntries.push(convertEntry(entry));\n      }\n    }\n\n    return unexpiredEntries;\n  }\n\n  /**\n   * Returns the number of entries present in the queue.\n   * Note that expired entries (per `maxRetentionTime`) are also included in this count.\n   *\n   * @returns\n   */\n  async size(): Promise<number> {\n    return await this._queueStore.size();\n  }\n\n  /**\n   * Adds the entry to the QueueStore and registers for a sync event.\n   *\n   * @param entry\n   * @param operation\n   * @private\n   */\n  async _addRequest({ request, metadata, timestamp = Date.now() }: BackgroundSyncQueueEntry, operation: \"push\" | \"unshift\"): Promise<void> {\n    const storableRequest = await StorableRequest.fromRequest(request.clone());\n    const entry: UnidentifiedQueueStoreEntry = {\n      requestData: storableRequest.toObject(),\n      timestamp,\n    };\n\n    // Only include metadata if it's present.\n    if (metadata) {\n      entry.metadata = metadata;\n    }\n\n    switch (operation) {\n      case \"push\":\n        await this._queueStore.pushEntry(entry);\n        break;\n      case \"unshift\":\n        await this._queueStore.unshiftEntry(entry);\n        break;\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(`Request for '${getFriendlyURL(request.url)}' has ` + `been added to background sync queue '${this._name}'.`);\n    }\n\n    // Don't register for a sync if we're in the middle of a sync. Instead,\n    // we wait until the sync is complete and call register if\n    // `this._requestsAddedDuringSync` is true.\n    if (this._syncInProgress) {\n      this._requestsAddedDuringSync = true;\n    } else {\n      await this.registerSync();\n    }\n  }\n\n  /**\n   * Removes and returns the first or last (depending on `operation`) entry\n   * from the {@linkcode BackgroundSyncQueueStore} that's not older than the `maxRetentionTime`.\n   *\n   * @param operation\n   * @returns\n   * @private\n   */\n  async _removeRequest(operation: \"pop\" | \"shift\"): Promise<BackgroundSyncQueueEntry | undefined> {\n    const now = Date.now();\n    let entry: BackgroundSyncQueueStoreEntry | undefined;\n    switch (operation) {\n      case \"pop\":\n        entry = await this._queueStore.popEntry();\n        break;\n      case \"shift\":\n        entry = await this._queueStore.shiftEntry();\n        break;\n    }\n\n    if (entry) {\n      // Ignore requests older than maxRetentionTime. Call this function\n      // recursively until an unexpired request is found.\n      const maxRetentionTimeInMs = this._maxRetentionTime * 60 * 1000;\n      if (now - entry.timestamp > maxRetentionTimeInMs) {\n        return this._removeRequest(operation);\n      }\n\n      return convertEntry(entry);\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Loops through each request in the queue and attempts to re-fetch it.\n   * If any request fails to re-fetch, it's put back in the same position in\n   * the queue (which registers a retry for the next sync event).\n   */\n  async replayRequests(): Promise<void> {\n    let entry: BackgroundSyncQueueEntry | undefined;\n    while ((entry = await this.shiftRequest())) {\n      try {\n        await fetch(entry.request.clone());\n\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.log(`Request for '${getFriendlyURL(entry.request.url)}' ` + `has been replayed in queue '${this._name}'`);\n        }\n      } catch {\n        await this.unshiftRequest(entry);\n\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.log(`Request for '${getFriendlyURL(entry.request.url)}' ` + `failed to replay, putting it back in queue '${this._name}'`);\n        }\n        throw new SerwistError(\"queue-replay-failed\", { name: this._name });\n      }\n    }\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(`All requests in queue '${this.name}' have successfully replayed; the queue is now empty!`);\n    }\n  }\n\n  /**\n   * Registers a sync event with a tag unique to this instance.\n   */\n  async registerSync(): Promise<void> {\n    // See https://github.com/GoogleChrome/workbox/issues/2393\n    if (\"sync\" in self.registration && !this._forceSyncFallback) {\n      try {\n        await self.registration.sync.register(`${TAG_PREFIX}:${this._name}`);\n      } catch (err) {\n        // This means the registration failed for some reason, possibly due to\n        // the user disabling it.\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.warn(`Unable to register sync event for '${this._name}'.`, err);\n        }\n      }\n    }\n  }\n\n  /**\n   * In sync-supporting browsers, this adds a listener for the sync event.\n   * In non-sync-supporting browsers, or if _forceSyncFallback is true, this\n   * will retry the queue on service worker startup.\n   *\n   * @private\n   */\n  private _addSyncListener() {\n    // See https://github.com/GoogleChrome/workbox/issues/2393\n    if (\"sync\" in self.registration && !this._forceSyncFallback) {\n      self.addEventListener(\"sync\", (event: SyncEvent) => {\n        if (event.tag === `${TAG_PREFIX}:${this._name}`) {\n          if (process.env.NODE_ENV !== \"production\") {\n            logger.log(`Background sync for tag '${event.tag}' has been received`);\n          }\n\n          const syncComplete = async () => {\n            this._syncInProgress = true;\n\n            let syncError: Error | undefined;\n            try {\n              await this._onSync({ queue: this });\n            } catch (error) {\n              if (error instanceof Error) {\n                syncError = error;\n\n                // Rethrow the error. Note: the logic in the finally clause\n                // will run before this gets rethrown.\n                throw syncError;\n              }\n            } finally {\n              // New items may have been added to the queue during the sync,\n              // so we need to register for a new sync if that's happened...\n              // Unless there was an error during the sync, in which\n              // case the browser will automatically retry later, as long\n              // as `event.lastChance` is not true.\n              if (this._requestsAddedDuringSync && !(syncError && !event.lastChance)) {\n                await this.registerSync();\n              }\n\n              this._syncInProgress = false;\n              this._requestsAddedDuringSync = false;\n            }\n          };\n          event.waitUntil(syncComplete());\n        }\n      });\n    } else {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.log(\"Background sync replaying without background sync event\");\n      }\n      // If the browser doesn't support background sync, or the developer has\n      // opted-in to not using it, retry every time the service worker starts up\n      // as a fallback.\n      void this._onSync({ queue: this });\n    }\n  }\n\n  /**\n   * Returns the set of queue names. This is primarily used to reset the list\n   * of queue names in tests.\n   *\n   * @returns\n   * @private\n   */\n  static get _queueNames(): Set<string> {\n    return queueNames;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { FetchDidFailCallbackParam, SerwistPlugin } from \"../../types.js\";\nimport type { BackgroundSyncQueueOptions } from \"./BackgroundSyncQueue.js\";\nimport { BackgroundSyncQueue } from \"./BackgroundSyncQueue.js\";\n\n/**\n * A class implementing the `fetchDidFail` lifecycle callback. This makes it\n * easier to add failed requests to a {@linkcode BackgroundSyncQueue}.\n */\nexport class BackgroundSyncPlugin implements SerwistPlugin {\n  private readonly _queue: BackgroundSyncQueue;\n\n  /**\n   * @param name See the {@linkcode BackgroundSyncQueue}\n   * documentation for parameter details.\n   * @param options See the {@linkcode BackgroundSyncQueue}\n   * documentation for parameter details.\n   * @see https://serwist.pages.dev/docs/serwist/core/background-sync-queue\n   */\n  constructor(name: string, options?: BackgroundSyncQueueOptions) {\n    this._queue = new BackgroundSyncQueue(name, options);\n  }\n\n  /**\n   * @param options\n   * @private\n   */\n  async fetchDidFail({ request }: FetchDidFailCallbackParam) {\n    await this._queue.pushRequest({ request });\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { SerwistPlugin } from \"../../../types.js\";\n\nexport const cacheOkAndOpaquePlugin: SerwistPlugin = {\n  /**\n   * Returns a valid response (to allow caching) if the status is 200 (OK) or\n   * 0 (opaque).\n   *\n   * @param options\n   * @returns\n   * @private\n   */\n  cacheWillUpdate: async ({ response }) => {\n    if (response.status === 200 || response.status === 0) {\n      return response;\n    }\n    return null;\n  },\n};\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { Route } from \"../../Route.js\";\nimport type { HandlerCallbackOptions, MapLikeObject, SerwistPlugin, SerwistPluginCallbackParam } from \"../../types.js\";\nimport { assert } from \"../../utils/assert.js\";\nimport { cacheMatchIgnoreParams } from \"../../utils/cacheMatchIgnoreParams.js\";\nimport { Deferred } from \"../../utils/Deferred.js\";\nimport { executeQuotaErrorCallbacks } from \"../../utils/executeQuotaErrorCallbacks.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { timeout } from \"../../utils/timeout.js\";\nimport type { Strategy } from \"./Strategy.js\";\n\nfunction toRequest(input: RequestInfo) {\n  return typeof input === \"string\" ? new Request(input) : input;\n}\n\n/**\n * A class created every time a {@linkcode Strategy} instance calls {@linkcode Strategy.handle} or\n * {@linkcode Strategy.handleAll} that wraps all fetch and cache actions around plugin callbacks\n * and keeps track of when the strategy is \"done\" (i.e. when all added `event.waitUntil()` promises\n * have resolved).\n */\nexport class StrategyHandler {\n  /**\n   * The event associated with this request.\n   */\n  public event: ExtendableEvent;\n  /**\n   * The request the strategy is processing (passed to the strategy's\n   * `handle()` or `handleAll()` method).\n   */\n  public request: Request;\n  /**\n   * A `URL` instance of `request.url` (if passed to the strategy's\n   * `handle()` or `handleAll()` method).\n   * Note: the `url` param will be present if the strategy is invoked\n   * from a {@linkcode Route} object.\n   */\n  public url?: URL;\n  /**\n   * Some additional params (if passed to the strategy's\n   * `handle()` or `handleAll()` method).\n   *\n   * Note: the `params` param will be present if the strategy is invoked\n   * from a {@linkcode Route} object and that route's matcher returned a truthy\n   * value (it will be that value).\n   */\n  public params?: string[] | MapLikeObject;\n\n  private _cacheKeys: Record<string, Request> = {};\n  private readonly _strategy: Strategy;\n  private readonly _handlerDeferred: Deferred<any>;\n  private readonly _extendLifetimePromises: Promise<any>[];\n  private readonly _plugins: SerwistPlugin[];\n  private readonly _pluginStateMap: Map<SerwistPlugin, MapLikeObject>;\n\n  /**\n   * Creates a new instance associated with the passed strategy and event\n   * that's handling the request.\n   *\n   * The constructor also initializes the state that will be passed to each of\n   * the plugins handling this request.\n   *\n   * @param strategy\n   * @param options\n   */\n  constructor(\n    strategy: Strategy,\n    options: HandlerCallbackOptions & {\n      request: HandlerCallbackOptions[\"request\"] & Request;\n    },\n  ) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(options.event, ExtendableEvent, {\n        moduleName: \"serwist\",\n        className: \"StrategyHandler\",\n        funcName: \"constructor\",\n        paramName: \"options.event\",\n      });\n      assert!.isInstance(options.request, Request, {\n        moduleName: \"serwist\",\n        className: \"StrategyHandler\",\n        funcName: \"constructor\",\n        paramName: \"options.request\",\n      });\n    }\n\n    this.event = options.event;\n    this.request = options.request;\n    if (options.url) {\n      this.url = options.url;\n      this.params = options.params;\n    }\n    this._strategy = strategy;\n    this._handlerDeferred = new Deferred();\n    this._extendLifetimePromises = [];\n\n    // Copy the plugins list (since it's mutable on the strategy),\n    // so any mutations don't affect this handler instance.\n    this._plugins = [...strategy.plugins];\n    this._pluginStateMap = new Map();\n    for (const plugin of this._plugins) {\n      this._pluginStateMap.set(plugin, {});\n    }\n\n    this.event.waitUntil(this._handlerDeferred.promise);\n  }\n\n  /**\n   * Fetches a given request (and invokes any applicable plugin callback\n   * methods), taking the `fetchOptions` (for non-navigation requests) and\n   * `plugins` provided to the {@linkcode Strategy} object into account.\n   *\n   * The following plugin lifecycle methods are invoked when using this method:\n   * - `requestWillFetch()`\n   * - `fetchDidSucceed()`\n   * - `fetchDidFail()`\n   *\n   * @param input The URL or request to fetch.\n   * @returns\n   */\n  async fetch(input: RequestInfo): Promise<Response> {\n    const { event } = this;\n    let request: Request = toRequest(input);\n\n    const preloadResponse = await this.getPreloadResponse();\n\n    if (preloadResponse) {\n      return preloadResponse;\n    }\n\n    // If there is a fetchDidFail plugin, we need to save a clone of the\n    // original request before it's either modified by a requestWillFetch\n    // plugin or before the original request's body is consumed via fetch().\n    const originalRequest = this.hasCallback(\"fetchDidFail\") ? request.clone() : null;\n\n    try {\n      for (const cb of this.iterateCallbacks(\"requestWillFetch\")) {\n        request = await cb({ request: request.clone(), event });\n      }\n    } catch (err) {\n      if (err instanceof Error) {\n        throw new SerwistError(\"plugin-error-request-will-fetch\", {\n          thrownErrorMessage: err.message,\n        });\n      }\n    }\n\n    // The request can be altered by plugins with `requestWillFetch` making\n    // the original request (most likely from a `fetch` event) different\n    // from the Request we make. Pass both to `fetchDidFail` to aid debugging.\n    const pluginFilteredRequest: Request = request.clone();\n\n    try {\n      let fetchResponse: Response;\n\n      // See https://github.com/GoogleChrome/workbox/issues/1796\n      fetchResponse = await fetch(request, request.mode === \"navigate\" ? undefined : this._strategy.fetchOptions);\n\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.debug(`Network request for '${getFriendlyURL(request.url)}' returned a response with status '${fetchResponse.status}'.`);\n      }\n\n      for (const callback of this.iterateCallbacks(\"fetchDidSucceed\")) {\n        fetchResponse = await callback({\n          event,\n          request: pluginFilteredRequest,\n          response: fetchResponse,\n        });\n      }\n      return fetchResponse;\n    } catch (error) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.log(`Network request for '${getFriendlyURL(request.url)}' threw an error.`, error);\n      }\n\n      // `originalRequest` will only exist if a `fetchDidFail` callback\n      // is being used (see above).\n      if (originalRequest) {\n        await this.runCallbacks(\"fetchDidFail\", {\n          error: error as Error,\n          event,\n          originalRequest: originalRequest.clone(),\n          request: pluginFilteredRequest.clone(),\n        });\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * Calls `this.fetch()` and (in the background) caches the generated response.\n   *\n   * The call to `this.cachePut()` automatically invokes `this.waitUntil()`,\n   * so you do not have to call `waitUntil()` yourself.\n   *\n   * @param input The request or URL to fetch and cache.\n   * @returns\n   */\n  async fetchAndCachePut(input: RequestInfo): Promise<Response> {\n    const response = await this.fetch(input);\n    const responseClone = response.clone();\n\n    void this.waitUntil(this.cachePut(input, responseClone));\n\n    return response;\n  }\n\n  /**\n   * Matches a request from the cache (and invokes any applicable plugin\n   * callback method) using the `cacheName`, `matchOptions`, and `plugins`\n   * provided to the `Strategy` object.\n   *\n   * The following lifecycle methods are invoked when using this method:\n   * - `cacheKeyWillBeUsed`\n   * - `cachedResponseWillBeUsed`\n   *\n   * @param key The `Request` or `URL` object to use as the cache key.\n   * @returns A matching response, if found.\n   */\n  async cacheMatch(key: RequestInfo): Promise<Response | undefined> {\n    const request: Request = toRequest(key);\n    let cachedResponse: Response | undefined;\n    const { cacheName, matchOptions } = this._strategy;\n\n    const effectiveRequest = await this.getCacheKey(request, \"read\");\n    const multiMatchOptions = { ...matchOptions, ...{ cacheName } };\n\n    cachedResponse = await caches.match(effectiveRequest, multiMatchOptions);\n\n    if (process.env.NODE_ENV !== \"production\") {\n      if (cachedResponse) {\n        logger.debug(`Found a cached response in '${cacheName}'.`);\n      } else {\n        logger.debug(`No cached response found in '${cacheName}'.`);\n      }\n    }\n\n    for (const callback of this.iterateCallbacks(\"cachedResponseWillBeUsed\")) {\n      cachedResponse =\n        (await callback({\n          cacheName,\n          matchOptions,\n          cachedResponse,\n          request: effectiveRequest,\n          event: this.event,\n        })) || undefined;\n    }\n    return cachedResponse;\n  }\n\n  /**\n   * Puts a request/response pair into the cache (and invokes any applicable\n   * plugin callback method) using the `cacheName` and `plugins` provided to\n   * the {@linkcode Strategy} object.\n   *\n   * The following plugin lifecycle methods are invoked when using this method:\n   * - `cacheKeyWillBeUsed`\n   * - `cacheWillUpdate`\n   * - `cacheDidUpdate`\n   *\n   * @param key The request or URL to use as the cache key.\n   * @param response The response to cache.\n   * @returns `false` if a `cacheWillUpdate` caused the response to\n   * not be cached, and `true` otherwise.\n   */\n  async cachePut(key: RequestInfo, response: Response): Promise<boolean> {\n    const request: Request = toRequest(key);\n\n    // Run in the next task to avoid blocking other cache reads.\n    // https://github.com/w3c/ServiceWorker/issues/1397\n    await timeout(0);\n\n    const effectiveRequest = await this.getCacheKey(request, \"write\");\n\n    if (process.env.NODE_ENV !== \"production\") {\n      if (effectiveRequest.method && effectiveRequest.method !== \"GET\") {\n        throw new SerwistError(\"attempt-to-cache-non-get-request\", {\n          url: getFriendlyURL(effectiveRequest.url),\n          method: effectiveRequest.method,\n        });\n      }\n    }\n\n    if (!response) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.error(`Cannot cache non-existent response for '${getFriendlyURL(effectiveRequest.url)}'.`);\n      }\n\n      throw new SerwistError(\"cache-put-with-no-response\", {\n        url: getFriendlyURL(effectiveRequest.url),\n      });\n    }\n\n    const responseToCache = await this._ensureResponseSafeToCache(response);\n\n    if (!responseToCache) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.debug(`Response '${getFriendlyURL(effectiveRequest.url)}' will not be cached.`, responseToCache);\n      }\n      return false;\n    }\n\n    const { cacheName, matchOptions } = this._strategy;\n    const cache = await self.caches.open(cacheName);\n\n    if (process.env.NODE_ENV !== \"production\") {\n      // See https://github.com/GoogleChrome/workbox/issues/2818\n      const vary = response.headers.get(\"Vary\");\n      if (vary && matchOptions?.ignoreVary !== true) {\n        logger.debug(\n          `The response for ${getFriendlyURL(\n            effectiveRequest.url,\n          )} has a 'Vary: ${vary}' header. Consider setting the {ignoreVary: true} option on your strategy to ensure cache matching and deletion works as expected.`,\n        );\n      }\n    }\n\n    const hasCacheUpdateCallback = this.hasCallback(\"cacheDidUpdate\");\n    const oldResponse = hasCacheUpdateCallback\n      ? await cacheMatchIgnoreParams(\n          // TODO(philipwalton): the `__WB_REVISION__` param is a precaching\n          // feature. Consider into ways to only add this behavior if using\n          // precaching.\n          cache,\n          effectiveRequest.clone(),\n          [\"__WB_REVISION__\"],\n          matchOptions,\n        )\n      : null;\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.debug(`Updating the '${cacheName}' cache with a new Response for ${getFriendlyURL(effectiveRequest.url)}.`);\n    }\n\n    try {\n      await cache.put(effectiveRequest, hasCacheUpdateCallback ? responseToCache.clone() : responseToCache);\n    } catch (error) {\n      if (error instanceof Error) {\n        // See https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-QuotaExceededError\n        if (error.name === \"QuotaExceededError\") {\n          await executeQuotaErrorCallbacks();\n        }\n        throw error;\n      }\n    }\n\n    for (const callback of this.iterateCallbacks(\"cacheDidUpdate\")) {\n      await callback({\n        cacheName,\n        oldResponse,\n        newResponse: responseToCache.clone(),\n        request: effectiveRequest,\n        event: this.event,\n      });\n    }\n\n    return true;\n  }\n\n  /**\n   * Checks the `plugins` provided to the {@linkcode Strategy} object for `cacheKeyWillBeUsed`\n   * callbacks and executes found callbacks in sequence. The final `Request`\n   * object returned by the last plugin is treated as the cache key for cache\n   * reads and/or writes. If no `cacheKeyWillBeUsed` plugin callbacks have\n   * been registered, the passed request is returned unmodified.\n   *\n   * @param request\n   * @param mode\n   * @returns\n   */\n  async getCacheKey(request: Request, mode: \"read\" | \"write\"): Promise<Request> {\n    const key = `${request.url} | ${mode}`;\n    if (!this._cacheKeys[key]) {\n      let effectiveRequest = request;\n\n      for (const callback of this.iterateCallbacks(\"cacheKeyWillBeUsed\")) {\n        effectiveRequest = toRequest(\n          await callback({\n            mode,\n            request: effectiveRequest,\n            event: this.event,\n            params: this.params,\n          }),\n        );\n      }\n\n      this._cacheKeys[key] = effectiveRequest;\n    }\n    return this._cacheKeys[key];\n  }\n\n  /**\n   * Returns `true` if the strategy has at least one plugin with the given\n   * callback.\n   *\n   * @param name The name of the callback to check for.\n   * @returns\n   */\n  hasCallback<C extends keyof SerwistPlugin>(name: C): boolean {\n    for (const plugin of this._strategy.plugins) {\n      if (name in plugin) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Runs all plugin callbacks matching the given name, in order, passing the\n   * given param object as the only argument.\n   *\n   * Note: since this method runs all plugins, it's not suitable for cases\n   * where the return value of a callback needs to be applied prior to calling\n   * the next callback. See {@linkcode StrategyHandler.iterateCallbacks} for how to handle that case.\n   *\n   * @param name The name of the callback to run within each plugin.\n   * @param param The object to pass as the first (and only) param when executing each callback. This object will be merged with the\n   * current plugin state prior to callback execution.\n   */\n  async runCallbacks<C extends keyof NonNullable<SerwistPlugin>>(name: C, param: Omit<SerwistPluginCallbackParam[C], \"state\">): Promise<void> {\n    for (const callback of this.iterateCallbacks(name)) {\n      // TODO(philipwalton): not sure why `any` is needed. It seems like\n      // this should work with `as SerwistPluginCallbackParam[C]`.\n      await callback(param as any);\n    }\n  }\n\n  /**\n   * Accepts a callback name and returns an iterable of matching plugin callbacks.\n   *\n   * @param name The name fo the callback to run\n   * @returns\n   */\n  *iterateCallbacks<C extends keyof SerwistPlugin>(name: C): Generator<NonNullable<SerwistPlugin[C]>> {\n    for (const plugin of this._strategy.plugins) {\n      if (typeof plugin[name] === \"function\") {\n        const state = this._pluginStateMap.get(plugin);\n        const statefulCallback = (param: Omit<SerwistPluginCallbackParam[C], \"state\">) => {\n          const statefulParam = { ...param, state };\n\n          // TODO(philipwalton): not sure why `any` is needed. It seems like\n          // this should work with `as WorkboxPluginCallbackParam[C]`.\n          return plugin[name]!(statefulParam as any);\n        };\n        yield statefulCallback as NonNullable<SerwistPlugin[C]>;\n      }\n    }\n  }\n\n  /**\n   * Adds a promise to the\n   * [extend lifetime promises](https://w3c.github.io/ServiceWorker/#extendableevent-extend-lifetime-promises)\n   * of the event event associated with the request being handled (usually a `FetchEvent`).\n   *\n   * Note: you can await {@linkcode StrategyHandler.doneWaiting} to know when all added promises have settled.\n   *\n   * @param promise A promise to add to the extend lifetime promises of\n   * the event that triggered the request.\n   */\n  waitUntil<T>(promise: Promise<T>): Promise<T> {\n    this._extendLifetimePromises.push(promise);\n    return promise;\n  }\n\n  /**\n   * Returns a promise that resolves once all promises passed to\n   * `this.waitUntil()` have settled.\n   *\n   * Note: any work done after `doneWaiting()` settles should be manually\n   * passed to an event's `waitUntil()` method (not `this.waitUntil()`), otherwise\n   * the service worker thread may be killed prior to your work completing.\n   */\n  async doneWaiting(): Promise<void> {\n    let promise: Promise<any> | undefined;\n    while ((promise = this._extendLifetimePromises.shift())) {\n      await promise;\n    }\n  }\n\n  /**\n   * Stops running the strategy and immediately resolves any pending\n   * `waitUntil()` promise.\n   */\n  destroy(): void {\n    this._handlerDeferred.resolve(null);\n  }\n\n  /**\n   * This method checks if the navigation preload `Response` is available.\n   *\n   * @param request\n   * @param event\n   * @returns\n   */\n  async getPreloadResponse(): Promise<Response | undefined> {\n    if (this.event instanceof FetchEvent && this.event.request.mode === \"navigate\" && \"preloadResponse\" in this.event) {\n      try {\n        const possiblePreloadResponse = (await this.event.preloadResponse) as Response | undefined;\n        if (possiblePreloadResponse) {\n          if (process.env.NODE_ENV !== \"production\") {\n            logger.log(`Using a preloaded navigation response for '${getFriendlyURL(this.event.request.url)}'`);\n          }\n          return possiblePreloadResponse;\n        }\n      } catch (error) {\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.error(error);\n        }\n        return undefined;\n      }\n    }\n    return undefined;\n  }\n\n  /**\n   * This method will call `cacheWillUpdate` on the available plugins (or use\n   * status === 200) to determine if the response is safe and valid to cache.\n   *\n   * @param response\n   * @returns\n   * @private\n   */\n  async _ensureResponseSafeToCache(response: Response): Promise<Response | undefined> {\n    let responseToCache: Response | undefined = response;\n    let pluginsUsed = false;\n\n    for (const callback of this.iterateCallbacks(\"cacheWillUpdate\")) {\n      responseToCache =\n        (await callback({\n          request: this.request,\n          response: responseToCache,\n          event: this.event,\n        })) || undefined;\n      pluginsUsed = true;\n\n      if (!responseToCache) {\n        break;\n      }\n    }\n\n    if (!pluginsUsed) {\n      if (responseToCache && responseToCache.status !== 200) {\n        if (process.env.NODE_ENV !== \"production\") {\n          if (responseToCache.status === 0) {\n            logger.warn(\n              `The response for '${this.request.url}' is an opaque response. The caching strategy that you're using will not cache opaque responses by default.`,\n            );\n          } else {\n            logger.debug(`The response for '${this.request.url}' returned a status code of '${response.status}' and won't be cached as a result.`);\n          }\n        }\n        responseToCache = undefined;\n      }\n    }\n\n    return responseToCache;\n  }\n}\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { HandlerCallbackOptions, RouteHandlerObject, SerwistPlugin } from \"../../types.js\";\nimport { cacheNames as privateCacheNames } from \"../../utils/cacheNames.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { StrategyHandler } from \"./StrategyHandler.js\";\n\nexport interface StrategyOptions {\n  /**\n   * Cache name to store and retrieve requests. Defaults to Serwist's default cache names.\n   */\n  cacheName?: string;\n  /**\n   * [Plugins](https://serwist.pages.dev/docs/serwist/runtime-caching/plugins) to use in conjunction with this caching strategy.\n   */\n  plugins?: SerwistPlugin[];\n  /**\n   * Options passed to [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796) `fetch()` calls made by\n   * this strategy.\n   */\n  fetchOptions?: RequestInit;\n  /**\n   * The [`CacheQueryOptions`](https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions)\n   * passed to any `cache.match()` or `cache.put()` call made by this strategy.\n   */\n  matchOptions?: CacheQueryOptions;\n}\n\n/**\n * Abstract class for implementing runtime caching strategies.\n *\n * Custom strategies should extend this class and leverage `StrategyHandler`, which will ensure all relevant cache options,\n * fetch options, and plugins are used (per the current strategy instance), to perform all fetching and caching logic.\n */\nexport abstract class Strategy implements RouteHandlerObject {\n  cacheName: string;\n  plugins: SerwistPlugin[];\n  fetchOptions?: RequestInit;\n  matchOptions?: CacheQueryOptions;\n\n  protected abstract _handle(request: Request, handler: StrategyHandler): Promise<Response | undefined>;\n\n  /**\n   * Creates a new instance of the strategy and sets all documented option\n   * properties as public instance properties.\n   *\n   * Note: if a custom strategy class extends the base Strategy class and does\n   * not need more than these properties, it does not need to define its own\n   * constructor.\n   *\n   * @param options\n   */\n  constructor(options: StrategyOptions = {}) {\n    this.cacheName = privateCacheNames.getRuntimeName(options.cacheName);\n    this.plugins = options.plugins || [];\n    this.fetchOptions = options.fetchOptions;\n    this.matchOptions = options.matchOptions;\n  }\n\n  /**\n   * Performs a request strategy and returns a promise that will resolve to\n   * a response, invoking all relevant plugin callbacks.\n   *\n   * When a strategy instance is registered with a route, this method is automatically\n   * called when the route matches.\n   *\n   * Alternatively, this method can be used in a standalone `fetch` event\n   * listener by passing it to `event.respondWith()`.\n   *\n   * @param options A `FetchEvent` or an object with the properties listed below.\n   * @param options.request A request to run this strategy for.\n   * @param options.event The event associated with the request.\n   * @param options.url\n   * @param options.params\n   */\n  handle(options: FetchEvent | HandlerCallbackOptions): Promise<Response> {\n    const [responseDone] = this.handleAll(options);\n    return responseDone;\n  }\n\n  /**\n   * Similar to `handle()`, but instead of just returning a promise that\n   * resolves to a response, it will return an tuple of `[response, done]` promises,\n   * where `response` is equivalent to what `handle()` returns, and `done` is a\n   * promise that will resolve once all promises added to `event.waitUntil()` as a part\n   * of performing the strategy have completed.\n   *\n   * You can await the `done` promise to ensure any extra work performed by\n   * the strategy (usually caching responses) completes successfully.\n   *\n   * @param options A `FetchEvent` or `HandlerCallbackOptions` object.\n   * @returns A tuple of [response, done] promises that can be used to determine when the response resolves as\n   * well as when the handler has completed all its work.\n   */\n  handleAll(options: FetchEvent | HandlerCallbackOptions): [Promise<Response>, Promise<void>] {\n    // Allow for flexible options to be passed.\n    if (options instanceof FetchEvent) {\n      options = {\n        event: options,\n        request: options.request,\n      };\n    }\n\n    const event = options.event;\n    const request = typeof options.request === \"string\" ? new Request(options.request) : options.request;\n\n    const handler = new StrategyHandler(this, options.url ? { event, request, url: options.url, params: options.params } : { event, request });\n\n    const responseDone = this._getResponse(handler, request, event);\n    const handlerDone = this._awaitComplete(responseDone, handler, request, event);\n\n    // Return an array of promises, suitable for use with Promise.all().\n    return [responseDone, handlerDone];\n  }\n\n  async _getResponse(handler: StrategyHandler, request: Request, event: ExtendableEvent): Promise<Response> {\n    await handler.runCallbacks(\"handlerWillStart\", { event, request });\n\n    let response: Response | undefined;\n    try {\n      response = await this._handle(request, handler);\n      // The \"official\" Strategy subclasses all throw this error automatically,\n      // but in case a third-party Strategy doesn't, ensure that we have a\n      // consistent failure when there's no response or an error response.\n      if (response === undefined || response.type === \"error\") {\n        throw new SerwistError(\"no-response\", { url: request.url });\n      }\n    } catch (error) {\n      if (error instanceof Error) {\n        for (const callback of handler.iterateCallbacks(\"handlerDidError\")) {\n          response = await callback({ error, event, request });\n          if (response !== undefined) {\n            break;\n          }\n        }\n      }\n\n      if (!response) {\n        throw error;\n      }\n      if (process.env.NODE_ENV !== \"production\") {\n        throw logger.log(\n          `While responding to '${getFriendlyURL(request.url)}', an ${\n            error instanceof Error ? error.toString() : \"\"\n          } error occurred. Using a fallback response provided by a handlerDidError plugin.`,\n        );\n      }\n    }\n\n    for (const callback of handler.iterateCallbacks(\"handlerWillRespond\")) {\n      response = (await callback({ event, request, response })) as Response;\n    }\n\n    return response;\n  }\n\n  async _awaitComplete(responseDone: Promise<Response>, handler: StrategyHandler, request: Request, event: ExtendableEvent): Promise<void> {\n    let response: Response | undefined;\n    let error: Error | undefined;\n\n    try {\n      response = await responseDone;\n    } catch {\n      // Ignore errors, as response errors should be caught via the `response`\n      // promise above. The `done` promise will only throw for errors in\n      // promises passed to `handler.waitUntil()`.\n    }\n\n    try {\n      await handler.runCallbacks(\"handlerDidRespond\", {\n        event,\n        request,\n        response,\n      });\n      await handler.doneWaiting();\n    } catch (waitUntilError) {\n      if (waitUntilError instanceof Error) {\n        error = waitUntilError;\n      }\n    }\n\n    await handler.runCallbacks(\"handlerDidComplete\", {\n      event,\n      request,\n      response,\n      error,\n    });\n    handler.destroy();\n\n    if (error) {\n      throw error;\n    }\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { getFriendlyURL } from \"../../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../../utils/logger.js\";\n\nexport const messages = {\n  strategyStart: (strategyName: string, request: Request): string => `Using ${strategyName} to respond to '${getFriendlyURL(request.url)}'`,\n  printFinalResponse: (response?: Response): void => {\n    if (response) {\n      logger.groupCollapsed(\"View the final response here.\");\n      logger.log(response || \"[No response returned]\");\n      logger.groupEnd();\n    }\n  },\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { cacheOkAndOpaquePlugin } from \"./plugins/cacheOkAndOpaquePlugin.js\";\nimport type { StrategyOptions } from \"./Strategy.js\";\nimport { Strategy } from \"./Strategy.js\";\nimport type { StrategyHandler } from \"./StrategyHandler.js\";\nimport { messages } from \"./utils/messages.js\";\n\nexport interface NetworkFirstOptions extends StrategyOptions {\n  /**\n   * If set, any network requests that fail to respond within the timeout will fallback to the cache.\n   */\n  networkTimeoutSeconds?: number;\n}\n\n/**\n * An implementation of the [network first](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#network_first_falling_back_to_cache)\n * request strategy.\n *\n * By default, this strategy will cache responses with a 200 status code as\n * well as [opaque responses](https://developer.chrome.com/docs/workbox/caching-resources-during-runtime/#opaque_responses).\n * Opaque responses are are cross-origin requests where the response doesn't\n * support [CORS](https://enable-cors.org/).\n *\n * If the network request fails, and there is no cache match, this will throw\n * a {@linkcode SerwistError} exception.\n */\nexport class NetworkFirst extends Strategy {\n  private readonly _networkTimeoutSeconds: number;\n  /**\n   * @param options\n   * This option can be used to combat\n   * \"[lie-fi](https://developers.google.com/web/fundamentals/performance/poor-connectivity/#lie-fi)\"\n   * scenarios.\n   */\n  constructor(options: NetworkFirstOptions = {}) {\n    super(options);\n\n    // If this instance contains no plugins with a 'cacheWillUpdate' callback,\n    // prepend the `cacheOkAndOpaquePlugin` plugin to the plugins list.\n    if (!this.plugins.some((p) => \"cacheWillUpdate\" in p)) {\n      this.plugins.unshift(cacheOkAndOpaquePlugin);\n    }\n\n    this._networkTimeoutSeconds = options.networkTimeoutSeconds || 0;\n    if (process.env.NODE_ENV !== \"production\") {\n      if (this._networkTimeoutSeconds) {\n        assert!.isType(this._networkTimeoutSeconds, \"number\", {\n          moduleName: \"serwist\",\n          className: this.constructor.name,\n          funcName: \"constructor\",\n          paramName: \"networkTimeoutSeconds\",\n        });\n      }\n    }\n  }\n\n  /**\n   * @private\n   * @param request A request to run this strategy for.\n   * @param handler The event that triggered the request.\n   * @returns\n   */\n  async _handle(request: Request, handler: StrategyHandler): Promise<Response> {\n    const logs: any[] = [];\n\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: this.constructor.name,\n        funcName: \"handle\",\n        paramName: \"makeRequest\",\n      });\n    }\n\n    const promises: Promise<Response | undefined>[] = [];\n    let timeoutId: number | undefined;\n\n    if (this._networkTimeoutSeconds) {\n      const { id, promise } = this._getTimeoutPromise({\n        request,\n        logs,\n        handler,\n      });\n      timeoutId = id;\n      promises.push(promise);\n    }\n\n    const networkPromise = this._getNetworkPromise({\n      timeoutId,\n      request,\n      logs,\n      handler,\n    });\n\n    promises.push(networkPromise);\n\n    const response = await handler.waitUntil(\n      (async () => {\n        // Promise.race() will resolve as soon as the first promise resolves.\n        return (\n          (await handler.waitUntil(Promise.race(promises))) ||\n          // If Promise.race() resolved with null, it might be due to a network\n          // timeout + a cache miss. If that were to happen, we'd rather wait until\n          // the networkPromise resolves instead of returning null.\n          // Note that it's fine to await an already-resolved promise, so we don't\n          // have to check to see if it's still \"in flight\".\n          (await networkPromise)\n        );\n      })(),\n    );\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));\n      for (const log of logs) {\n        logger.log(log);\n      }\n      messages.printFinalResponse(response);\n      logger.groupEnd();\n    }\n\n    if (!response) {\n      throw new SerwistError(\"no-response\", { url: request.url });\n    }\n    return response;\n  }\n\n  /**\n   * @param options\n   * @returns\n   * @private\n   */\n  private _getTimeoutPromise({\n    request,\n    logs,\n    handler,\n  }: {\n    request: Request;\n    /**\n     * A reference to the logs array.\n     */\n    logs: any[];\n    handler: StrategyHandler;\n  }): { promise: Promise<Response | undefined>; id?: number } {\n    // biome-ignore lint/suspicious/noImplicitAnyLet: setTimeout is typed with Node.js's typings, so we can't use number | undefined here.\n    let timeoutId;\n    const timeoutPromise: Promise<Response | undefined> = new Promise((resolve) => {\n      const onNetworkTimeout = async () => {\n        if (process.env.NODE_ENV !== \"production\") {\n          logs.push(`Timing out the network response at ${this._networkTimeoutSeconds} seconds.`);\n        }\n        resolve(await handler.cacheMatch(request));\n      };\n      timeoutId = setTimeout(onNetworkTimeout, this._networkTimeoutSeconds * 1000);\n    });\n\n    return {\n      promise: timeoutPromise,\n      id: timeoutId,\n    };\n  }\n\n  /**\n   * @param options\n   * @param options.timeoutId\n   * @param options.request\n   * @param options.logs A reference to the logs Array.\n   * @param options.event\n   * @returns\n   *\n   * @private\n   */\n  async _getNetworkPromise({\n    timeoutId,\n    request,\n    logs,\n    handler,\n  }: {\n    request: Request;\n    logs: any[];\n    timeoutId?: number;\n    handler: StrategyHandler;\n  }): Promise<Response | undefined> {\n    let error: Error | undefined;\n    let response: Response | undefined;\n    try {\n      response = await handler.fetchAndCachePut(request);\n    } catch (fetchError) {\n      if (fetchError instanceof Error) {\n        error = fetchError;\n      }\n    }\n\n    if (timeoutId) {\n      clearTimeout(timeoutId);\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      if (response) {\n        logs.push(\"Got response from network.\");\n      } else {\n        logs.push(\"Unable to get a response from the network. Will respond \" + \"with a cached response.\");\n      }\n    }\n\n    if (error || !response) {\n      response = await handler.cacheMatch(request);\n\n      if (process.env.NODE_ENV !== \"production\") {\n        if (response) {\n          logs.push(`Found a cached response in the '${this.cacheName}' cache.`);\n        } else {\n          logs.push(`No response found in the '${this.cacheName}' cache.`);\n        }\n      }\n    }\n\n    return response;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { timeout } from \"../../utils/timeout.js\";\nimport type { StrategyOptions } from \"./Strategy.js\";\nimport { Strategy } from \"./Strategy.js\";\nimport type { StrategyHandler } from \"./StrategyHandler.js\";\nimport { messages } from \"./utils/messages.js\";\n\nexport interface NetworkOnlyOptions extends Omit<StrategyOptions, \"cacheName\" | \"matchOptions\"> {\n  /**\n   * If set, any network requests that fail to respond within the timeout will result in a network error.\n   */\n  networkTimeoutSeconds?: number;\n}\n\n/**\n * An implementation of the [network only](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#network_only)\n * request strategy.\n *\n * This class is useful if you require specific requests to only be fulfilled from the network.\n *\n * If the network request fails, this will throw a {@linkcode SerwistError} exception.\n */\nexport class NetworkOnly extends Strategy {\n  private readonly _networkTimeoutSeconds: number;\n\n  /**\n   * @param options\n   */\n  constructor(options: NetworkOnlyOptions = {}) {\n    super(options);\n\n    this._networkTimeoutSeconds = options.networkTimeoutSeconds || 0;\n  }\n\n  /**\n   * @private\n   * @param request A request to run this strategy for.\n   * @param handler The event that triggered the request.\n   * @returns\n   */\n  async _handle(request: Request, handler: StrategyHandler): Promise<Response> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: this.constructor.name,\n        funcName: \"_handle\",\n        paramName: \"request\",\n      });\n    }\n\n    let error: Error | undefined;\n    let response: Response | undefined;\n\n    try {\n      const promises: Promise<Response | undefined>[] = [handler.fetch(request)];\n\n      if (this._networkTimeoutSeconds) {\n        const timeoutPromise = timeout(this._networkTimeoutSeconds * 1000) as Promise<undefined>;\n        promises.push(timeoutPromise);\n      }\n\n      response = await Promise.race(promises);\n      if (!response) {\n        throw new Error(`Timed out the network response after ${this._networkTimeoutSeconds} seconds.`);\n      }\n    } catch (err) {\n      if (err instanceof Error) {\n        error = err;\n      }\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));\n      if (response) {\n        logger.log(\"Got response from network.\");\n      } else {\n        logger.log(\"Unable to get a response from the network.\");\n      }\n      messages.printFinalResponse(response);\n      logger.groupEnd();\n    }\n\n    if (!response) {\n      throw new SerwistError(\"no-response\", { url: request.url, error });\n    }\n    return response;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nexport type HTTPMethod = \"DELETE\" | \"GET\" | \"HEAD\" | \"PATCH\" | \"POST\" | \"PUT\" | \"OPTIONS\";\n\n/**\n * The default HTTP method, 'GET', used when there's no specific method\n * configured for a route.\n *\n * @private\n */\nexport const defaultMethod = \"GET\" satisfies HTTPMethod;\n\n/**\n * The list of valid HTTP methods associated with requests that could be routed.\n *\n * @private\n */\nexport const validMethods = [\"DELETE\", \"GET\", \"HEAD\", \"PATCH\", \"POST\", \"PUT\"] satisfies HTTPMethod[];\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { RouteHandler, RouteHandlerObject } from \"../types.js\";\nimport { assert } from \"./assert.js\";\n\n/**\n * @param handler Either a function, or an object with a\n * 'handle' method.\n * @returns An object with a handle method.\n *\n * @private\n */\nexport const normalizeHandler = (handler: RouteHandler): RouteHandlerObject => {\n  if (handler && typeof handler === \"object\") {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.hasMethod(handler, \"handle\", {\n        moduleName: \"serwist\",\n        className: \"Route\",\n        funcName: \"constructor\",\n        paramName: \"handler\",\n      });\n    }\n    return handler;\n  }\n  if (process.env.NODE_ENV !== \"production\") {\n    assert!.isType(handler, \"function\", {\n      moduleName: \"serwist\",\n      className: \"Route\",\n      funcName: \"constructor\",\n      paramName: \"handler\",\n    });\n  }\n  return { handle: handler };\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { HTTPMethod } from \"./constants.js\";\nimport { defaultMethod, validMethods } from \"./constants.js\";\nimport type { RouteHandler, RouteHandlerObject, RouteMatchCallback } from \"./types.js\";\nimport { assert } from \"./utils/assert.js\";\nimport { normalizeHandler } from \"./utils/normalizeHandler.js\";\n\n/**\n * A `Route` consists of a pair of callback functions, `match` and `handler`.\n * The `match` callback determines if a route should be used to handle a\n * request by returning a truthy value if it can. The `handler` callback\n * is called when the route matches and should return a promise that resolves\n * to a response.\n */\nexport class Route {\n  handler: RouteHandlerObject;\n  match: RouteMatchCallback;\n  method: HTTPMethod;\n  catchHandler?: RouteHandlerObject;\n\n  /**\n   * Constructor for Route class.\n   *\n   * @param match A callback function that determines whether the\n   * route matches a given `fetch` event by returning a truthy value.\n   * @param handler A callback function that returns a `Promise` resolving\n   * to a `Response`.\n   * @param method The HTTP method to match the route against. Defaults\n   * to `GET`.\n   */\n  constructor(match: RouteMatchCallback, handler: RouteHandler, method: HTTPMethod = defaultMethod) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(match, \"function\", {\n        moduleName: \"serwist\",\n        className: \"Route\",\n        funcName: \"constructor\",\n        paramName: \"match\",\n      });\n\n      if (method) {\n        assert!.isOneOf(method, validMethods, { paramName: \"method\" });\n      }\n    }\n\n    // These values are referenced directly by Router so cannot be\n    // altered by minificaton.\n    this.handler = normalizeHandler(handler);\n    this.match = match;\n    this.method = method;\n  }\n\n  /**\n   *\n   * @param handler A callback function that returns a Promise resolving\n   * to a Response.\n   */\n  setCatchHandler(handler: RouteHandler): void {\n    this.catchHandler = normalizeHandler(handler);\n  }\n}\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { copyResponse } from \"../../copyResponse.js\";\nimport type { Serwist } from \"../../Serwist.js\";\nimport type { SerwistPlugin } from \"../../types.js\";\nimport { cacheNames as privateCacheNames } from \"../../utils/cacheNames.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport type { StrategyOptions } from \"./Strategy.js\";\nimport { Strategy } from \"./Strategy.js\";\nimport type { StrategyHandler } from \"./StrategyHandler.js\";\n\nexport interface PrecacheStrategyOptions extends StrategyOptions {\n  /**\n   * Plugins to use when precaching as well as responding to `fetch` events for precached assets.\n   */\n  plugins?: StrategyOptions[\"plugins\"];\n  /**\n   * Whether to attempt to get the response from the network\n   * if there's a precache miss.\n   */\n  fallbackToNetwork?: boolean;\n}\n\n/**\n * A {@linkcode Strategy} implementation specifically designed to both cache\n * and fetch precached assets.\n *\n * Note: an instance of this class is created automatically when creating a\n * {@linkcode Serwist} instance; it's generally not necessary to create this yourself.\n */\nexport class PrecacheStrategy extends Strategy {\n  private readonly _fallbackToNetwork: boolean;\n\n  static readonly defaultPrecacheCacheabilityPlugin: SerwistPlugin = {\n    async cacheWillUpdate({ response }) {\n      if (!response || response.status >= 400) {\n        return null;\n      }\n\n      return response;\n    },\n  };\n\n  static readonly copyRedirectedCacheableResponsesPlugin: SerwistPlugin = {\n    async cacheWillUpdate({ response }) {\n      return response.redirected ? await copyResponse(response) : response;\n    },\n  };\n\n  /**\n   * @param options\n   */\n  constructor(options: PrecacheStrategyOptions = {}) {\n    options.cacheName = privateCacheNames.getPrecacheName(options.cacheName);\n\n    super(options);\n\n    this._fallbackToNetwork = options.fallbackToNetwork !== false;\n\n    // Redirected responses cannot be used to satisfy a navigation request, so\n    // any redirected response must be \"copied\" rather than cloned, so the new\n    // response doesn't contain the `redirected` flag. See:\n    // https://bugs.chromium.org/p/chromium/issues/detail?id=669363&desc=2#c1\n    this.plugins.push(PrecacheStrategy.copyRedirectedCacheableResponsesPlugin);\n  }\n\n  /**\n   * @private\n   * @param request A request to run this strategy for.\n   * @param handler The event that triggered the request.\n   * @returns\n   */\n  async _handle(request: Request, handler: StrategyHandler): Promise<Response> {\n    const preloadResponse = await handler.getPreloadResponse();\n\n    if (preloadResponse) {\n      return preloadResponse;\n    }\n\n    const response = await handler.cacheMatch(request);\n\n    if (response) {\n      return response;\n    }\n\n    // If this is an `install` event for an entry that isn't already cached,\n    // then populate the cache.\n    if (handler.event && handler.event.type === \"install\") {\n      return await this._handleInstall(request, handler);\n    }\n\n    // Getting here means something went wrong. An entry that should have been\n    // precached wasn't found in the cache.\n    return await this._handleFetch(request, handler);\n  }\n\n  async _handleFetch(request: Request, handler: StrategyHandler): Promise<Response> {\n    let response: Response | undefined;\n\n    const params = (handler.params || {}) as {\n      cacheKey?: string;\n      integrity?: string;\n    };\n\n    // Fallback to the network if we're configured to do so.\n    if (this._fallbackToNetwork) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.warn(`The precached response for ${getFriendlyURL(request.url)} in ${this.cacheName} was not found. Falling back to the network.`);\n      }\n\n      const integrityInManifest = params.integrity;\n      const integrityInRequest = request.integrity;\n      const noIntegrityConflict = !integrityInRequest || integrityInRequest === integrityInManifest;\n\n      // Do not add integrity if the original request is no-cors\n      // See https://github.com/GoogleChrome/workbox/issues/3096\n      response = await handler.fetch(\n        new Request(request, {\n          integrity: request.mode !== \"no-cors\" ? integrityInRequest || integrityInManifest : undefined,\n        }),\n      );\n\n      // It's only \"safe\" to repair the cache if we're using SRI to guarantee\n      // that the response matches the precache manifest's expectations,\n      // and there's either a) no integrity property in the incoming request\n      // or b) there is an integrity, and it matches the precache manifest.\n      // See https://github.com/GoogleChrome/workbox/issues/2858\n      // Also if the original request users no-cors we don't use integrity.\n      // See https://github.com/GoogleChrome/workbox/issues/3096\n      if (integrityInManifest && noIntegrityConflict && request.mode !== \"no-cors\") {\n        this._useDefaultCacheabilityPluginIfNeeded();\n        const wasCached = await handler.cachePut(request, response.clone());\n        if (process.env.NODE_ENV !== \"production\") {\n          if (wasCached) {\n            logger.log(`A response for ${getFriendlyURL(request.url)} was used to \"repair\" the precache.`);\n          }\n        }\n      }\n    } else {\n      // This shouldn't normally happen, but there are edge cases:\n      // https://github.com/GoogleChrome/workbox/issues/1441\n      throw new SerwistError(\"missing-precache-entry\", {\n        cacheName: this.cacheName,\n        url: request.url,\n      });\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      const cacheKey = params.cacheKey || (await handler.getCacheKey(request, \"read\"));\n\n      // Serwist is going to handle the route.\n      // print the routing details to the console.\n      logger.groupCollapsed(`Precaching is responding to: ${getFriendlyURL(request.url)}`);\n      logger.log(`Serving the precached url: ${getFriendlyURL(cacheKey instanceof Request ? cacheKey.url : cacheKey)}`);\n\n      logger.groupCollapsed(\"View request details here.\");\n      logger.log(request);\n      logger.groupEnd();\n\n      logger.groupCollapsed(\"View response details here.\");\n      logger.log(response);\n      logger.groupEnd();\n\n      logger.groupEnd();\n    }\n\n    return response;\n  }\n\n  async _handleInstall(request: Request, handler: StrategyHandler): Promise<Response> {\n    this._useDefaultCacheabilityPluginIfNeeded();\n\n    const response = await handler.fetch(request);\n\n    // Make sure we defer cachePut() until after we know the response\n    // should be cached; see https://github.com/GoogleChrome/workbox/issues/2737\n    const wasCached = await handler.cachePut(request, response.clone());\n\n    if (!wasCached) {\n      // Throwing here will lead to the `install` handler failing, which\n      // we want to do if *any* of the responses aren't safe to cache.\n      throw new SerwistError(\"bad-precaching-response\", {\n        url: request.url,\n        status: response.status,\n      });\n    }\n\n    return response;\n  }\n\n  /**\n   * This method is complex, as there a number of things to account for:\n   *\n   * The `plugins` array can be set at construction, and/or it might be added to\n   * to at any time before the strategy is used.\n   *\n   * At the time the strategy is used (i.e. during an `install` event), there\n   * needs to be at least one plugin that implements `cacheWillUpdate` in the\n   * array, other than `copyRedirectedCacheableResponsesPlugin`.\n   *\n   * - If this method is called and there are no suitable `cacheWillUpdate`\n   * plugins, we need to add `defaultPrecacheCacheabilityPlugin`.\n   *\n   * - If this method is called and there is exactly one `cacheWillUpdate`, then\n   * we don't have to do anything (this might be a previously added\n   * `defaultPrecacheCacheabilityPlugin`, or it might be a custom plugin).\n   *\n   * - If this method is called and there is more than one `cacheWillUpdate`,\n   * then we need to check if one is `defaultPrecacheCacheabilityPlugin`. If so,\n   * we need to remove it. (This situation is unlikely, but it could happen if\n   * the strategy is used multiple times, the first without a `cacheWillUpdate`,\n   * and then later on after manually adding a custom `cacheWillUpdate`.)\n   *\n   * See https://github.com/GoogleChrome/workbox/issues/2737 for more context.\n   *\n   * @private\n   */\n  _useDefaultCacheabilityPluginIfNeeded(): void {\n    let defaultPluginIndex: number | null = null;\n    let cacheWillUpdatePluginCount = 0;\n\n    for (const [index, plugin] of this.plugins.entries()) {\n      // Ignore the copy redirected plugin when determining what to do.\n      if (plugin === PrecacheStrategy.copyRedirectedCacheableResponsesPlugin) {\n        continue;\n      }\n\n      // Save the default plugin's index, in case it needs to be removed.\n      if (plugin === PrecacheStrategy.defaultPrecacheCacheabilityPlugin) {\n        defaultPluginIndex = index;\n      }\n\n      if (plugin.cacheWillUpdate) {\n        cacheWillUpdatePluginCount++;\n      }\n    }\n\n    if (cacheWillUpdatePluginCount === 0) {\n      this.plugins.push(PrecacheStrategy.defaultPrecacheCacheabilityPlugin);\n    } else if (cacheWillUpdatePluginCount > 1 && defaultPluginIndex !== null) {\n      // Only remove the default plugin; multiple custom plugins are allowed.\n      this.plugins.splice(defaultPluginIndex, 1);\n    }\n    // Nothing needs to be done if cacheWillUpdatePluginCount is 1\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { Route } from \"./Route.js\";\nimport type { RouteHandler, RouteMatchCallbackOptions } from \"./types.js\";\nimport { assert } from \"./utils/assert.js\";\nimport { logger } from \"./utils/logger.js\";\n\nexport interface NavigationRouteMatchOptions {\n  /**\n   * If any of these patterns\n   * match the URL's pathname and search parameter, the route will handle the\n   * request (assuming the denylist doesn't match).\n   *\n   * @default [/./]\n   */\n  allowlist?: RegExp[];\n  /**\n   * If any of these patterns match, the route will not handle the request (even if a allowlist RegExp matches).\n   */\n  denylist?: RegExp[];\n}\n\n/**\n * A class that makes it easy to create a {@linkcode Route} object that matches navigation requests.\n *\n * It will only match incoming requests whose [`mode`](https://fetch.spec.whatwg.org/#concept-request-mode) is set to `\"navigate\"`.\n *\n * You can optionally only apply this route to a subset of navigation requests\n * by using one or both of the `denylist` and `allowlist` parameters.\n */\nexport class NavigationRoute extends Route {\n  private readonly _allowlist: RegExp[];\n  private readonly _denylist: RegExp[];\n\n  /**\n   * If both `denylist` and `allowlist` are provided, `denylist` will\n   * take precedence.\n   *\n   * The regular expressions in `allowlist` and `denylist`\n   * are matched against the concatenated\n   * [`pathname`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname)\n   * and [`search`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/search)\n   * portions of the requested URL.\n   *\n   * *Note*: These RegExps may be evaluated against every destination URL during\n   * a navigation. Avoid using\n   * [complex RegExps](https://github.com/GoogleChrome/workbox/issues/3077),\n   * or else your users may see delays when navigating your site.\n   *\n   * @param handler A callback function that returns a `Promise` resulting in a `Response`.\n   * @param options\n   */\n  constructor(handler: RouteHandler, { allowlist = [/./], denylist = [] }: NavigationRouteMatchOptions = {}) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isArrayOfClass(allowlist, RegExp, {\n        moduleName: \"serwist\",\n        className: \"NavigationRoute\",\n        funcName: \"constructor\",\n        paramName: \"options.allowlist\",\n      });\n      assert!.isArrayOfClass(denylist, RegExp, {\n        moduleName: \"serwist\",\n        className: \"NavigationRoute\",\n        funcName: \"constructor\",\n        paramName: \"options.denylist\",\n      });\n    }\n\n    super((options: RouteMatchCallbackOptions) => this._match(options), handler);\n\n    this._allowlist = allowlist;\n    this._denylist = denylist;\n  }\n\n  /**\n   * Routes match handler.\n   *\n   * @param options\n   * @returns\n   * @private\n   */\n  private _match({ url, request }: RouteMatchCallbackOptions): boolean {\n    if (request && request.mode !== \"navigate\") {\n      return false;\n    }\n\n    const pathnameAndSearch = url.pathname + url.search;\n\n    for (const regExp of this._denylist) {\n      if (regExp.test(pathnameAndSearch)) {\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.log(\n            `The navigation route ${pathnameAndSearch} is not being used, since the URL matches this denylist pattern: ${regExp.toString()}`,\n          );\n        }\n        return false;\n      }\n    }\n\n    if (this._allowlist.some((regExp) => regExp.test(pathnameAndSearch))) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.debug(`The navigation route ${pathnameAndSearch} is being used.`);\n      }\n      return true;\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(`The navigation route ${pathnameAndSearch} is not being used, since the URL being navigated to doesn't match the allowlist.`);\n    }\n    return false;\n  }\n}\n", "import { logger } from \"./utils/logger.js\";\n\ndeclare const self: ServiceWorkerGlobalScope;\n\n/**\n * Checks whether the current browser supports\n * navigation preloading.\n *\n * @returns\n * @see https://serwist.pages.dev/docs/serwist/core/is-navigation-preload-supported\n */\nexport const isNavigationPreloadSupported = (): boolean => {\n  return Boolean(self.registration?.navigationPreload);\n};\n\n/**\n * If the browser supports navigation preloading, then this will enable it.\n *\n * @param headerValue Optional. Allows developers to override the value of\n * the `Service-Worker-Navigation-Preload` header which will be sent to the\n * server when making the navigation request.\n * @see https://serwist.pages.dev/docs/serwist/core/enable-navigation-preload\n */\nexport const enableNavigationPreload = (headerValue?: string): void => {\n  if (isNavigationPreloadSupported()) {\n    self.addEventListener(\"activate\", (event) => {\n      event.waitUntil(\n        self.registration.navigationPreload.enable().then(() => {\n          // Defaults to Service-Worker-Navigation-Preload: true if not set.\n          if (headerValue) {\n            void self.registration.navigationPreload.setHeaderValue(headerValue);\n          }\n\n          if (process.env.NODE_ENV !== \"production\") {\n            logger.log(\"Navigation preloading is enabled.\");\n          }\n        }),\n      );\n    });\n  } else {\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(\"Navigation preloading is not supported in this browser.\");\n    }\n  }\n};\n\n/**\n * If the browser supports navigation preloading, then this will disable it.\n *\n * @see https://serwist.pages.dev/docs/serwist/core/disable-navigation-preload\n */\nexport const disableNavigationPreload = (): void => {\n  if (isNavigationPreloadSupported()) {\n    self.addEventListener(\"activate\", (event: ExtendableEvent) => {\n      event.waitUntil(\n        self.registration.navigationPreload.disable().then(() => {\n          if (process.env.NODE_ENV !== \"production\") {\n            logger.log(\"Navigation preloading is disabled.\");\n          }\n        }),\n      );\n    });\n  } else {\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(\"Navigation preloading is not supported in this browser.\");\n    }\n  }\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\n/**\n * Removes any URL search parameters that should be ignored.\n *\n * @param urlObject The original URL.\n * @param ignoreURLParametersMatching RegExps to test against\n * each search parameter name. Matches mean that the search parameter should be\n * ignored.\n * @returns The URL with any ignored search parameters removed.\n * @private\n */\nexport const removeIgnoredSearchParams = (urlObject: URL, ignoreURLParametersMatching: RegExp[] = []): URL => {\n  // Convert the iterable into an array at the start of the loop to make sure\n  // deletion doesn't mess up iteration.\n  for (const paramName of [...urlObject.searchParams.keys()]) {\n    if (ignoreURLParametersMatching.some((regExp) => regExp.test(paramName))) {\n      urlObject.searchParams.delete(paramName);\n    }\n  }\n\n  return urlObject;\n};\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { PrecacheRouteOptions } from \"../types.js\";\nimport { removeIgnoredSearchParams } from \"./removeIgnoredSearchParams.js\";\n\n/**\n * Generator function that yields possible variations on the original URL to\n * check, one at a time.\n *\n * @param url\n * @param options\n *\n * @private\n */\nexport function* generateURLVariations(\n  url: string,\n  {\n    directoryIndex = \"index.html\",\n    ignoreURLParametersMatching = [/^utm_/, /^fbclid$/],\n    cleanURLs = true,\n    urlManipulation,\n  }: PrecacheRouteOptions = {},\n): Generator<string, void, unknown> {\n  const urlObject = new URL(url, location.href);\n  urlObject.hash = \"\";\n  yield urlObject.href;\n\n  const urlWithoutIgnoredParams = removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching);\n  yield urlWithoutIgnoredParams.href;\n\n  if (directoryIndex && urlWithoutIgnoredParams.pathname.endsWith(\"/\")) {\n    const directoryURL = new URL(urlWithoutIgnoredParams.href);\n    directoryURL.pathname += directoryIndex;\n    yield directoryURL.href;\n  }\n\n  if (cleanURLs) {\n    const cleanURL = new URL(urlWithoutIgnoredParams.href);\n    cleanURL.pathname += \".html\";\n    yield cleanURL.href;\n  }\n\n  if (urlManipulation) {\n    const additionalURLs = urlManipulation({ url: urlObject });\n    for (const urlToAttempt of additionalURLs) {\n      yield urlToAttempt.href;\n    }\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { HTTPMethod } from \"./constants.js\";\nimport { Route } from \"./Route.js\";\nimport type { RouteHandler, RouteMatchCallback, RouteMatchCallbackOptions } from \"./types.js\";\nimport { assert } from \"./utils/assert.js\";\nimport { logger } from \"./utils/logger.js\";\n\n/**\n * A class that makes it easy to create a {@linkcode Route} object with a regular expression.\n *\n * For same-origin requests the `RegExp` only needs to match part of the URL. For\n * requests against third-party servers, you must define a `RegExp` that matches\n * the start of the URL.\n */\nexport class RegExpRoute extends Route {\n  /**\n   * If the regular expression contains\n   * [capture groups](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references),\n   * the captured values will be passed to the `params` argument.\n   *\n   * @param regExp The regular expression to match against URLs.\n   * @param handler A callback function that returns a `Promise` resulting in a `Response`.\n   * @param method The HTTP method to match the {@linkcode Route} against. Defaults to `GET`.\n   * against.\n   */\n  constructor(regExp: RegExp, handler: RouteHandler, method?: HTTPMethod) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(regExp, RegExp, {\n        moduleName: \"serwist\",\n        className: \"RegExpRoute\",\n        funcName: \"constructor\",\n        paramName: \"pattern\",\n      });\n    }\n\n    const match: RouteMatchCallback = ({ url }: RouteMatchCallbackOptions) => {\n      const result = regExp.exec(url.href);\n\n      // Return immediately if there's no match.\n      if (!result) {\n        return;\n      }\n\n      // Require that the match start at the first character in the URL string\n      // if it's a cross-origin request.\n      // See https://github.com/GoogleChrome/workbox/issues/281 for the context\n      // behind this behavior.\n      if (url.origin !== location.origin && result.index !== 0) {\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.debug(\n            `The regular expression '${regExp.toString()}' only partially matched against the cross-origin URL '${url.toString()}'. RegExpRoute's will only handle cross-origin requests if they match the entire URL.`,\n          );\n        }\n\n        return;\n      }\n\n      // If the route matches, but there aren't any capture groups defined, then\n      // this will return [], which is truthy and therefore sufficient to\n      // indicate a match.\n      // If there are capture groups, then it will return their values.\n      return result.slice(1);\n    };\n\n    super(match, handler, method);\n  }\n}\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"./utils/assert.js\";\nimport type { PartialCacheNameDetails } from \"./utils/cacheNames.js\";\nimport { cacheNames } from \"./utils/cacheNames.js\";\nimport { SerwistError } from \"./utils/SerwistError.js\";\n\n/**\n * Modifies the default cache names used by Serwist packages.\n * Cache names are generated as `<prefix>-<Cache Name>-<suffix>`.\n *\n * @param details\n */\nexport const setCacheNameDetails = (details: PartialCacheNameDetails): void => {\n  if (process.env.NODE_ENV !== \"production\") {\n    for (const key of Object.keys(details)) {\n      assert!.isType(details[key], \"string\", {\n        moduleName: \"@serwist/core\",\n        funcName: \"setCacheNameDetails\",\n        paramName: `details.${key}`,\n      });\n    }\n\n    if (details.precache?.length === 0) {\n      throw new SerwistError(\"invalid-cache-name\", {\n        cacheNameId: \"precache\",\n        value: details.precache,\n      });\n    }\n\n    if (details.runtime?.length === 0) {\n      throw new SerwistError(\"invalid-cache-name\", {\n        cacheNameId: \"runtime\",\n        value: details.runtime,\n      });\n    }\n\n    if (details.googleAnalytics?.length === 0) {\n      throw new SerwistError(\"invalid-cache-name\", {\n        cacheNameId: \"googleAnalytics\",\n        value: details.googleAnalytics,\n      });\n    }\n  }\n\n  cacheNames.updateDetails(details);\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { PrecacheEntry } from \"../types.js\";\nimport { SerwistError } from \"./SerwistError.js\";\n\ninterface CacheKey {\n  cacheKey: string;\n  url: string;\n}\n\n// Name of the search parameter used to store revision info.\nconst REVISION_SEARCH_PARAM = \"__WB_REVISION__\";\n\n/**\n * Converts a manifest entry into a versioned URL suitable for precaching.\n *\n * @param entry\n * @returns A URL with versioning info.\n *\n * @private\n */\nexport const createCacheKey = (entry: PrecacheEntry | string): CacheKey => {\n  if (!entry) {\n    throw new SerwistError(\"add-to-cache-list-unexpected-type\", { entry });\n  }\n\n  // If a precache manifest entry is a string, it's assumed to be a versioned\n  // URL, like '/app.abcd1234.js'. Return as-is.\n  if (typeof entry === \"string\") {\n    const urlObject = new URL(entry, location.href);\n    return {\n      cacheKey: urlObject.href,\n      url: urlObject.href,\n    };\n  }\n\n  const { revision, url } = entry;\n  if (!url) {\n    throw new SerwistError(\"add-to-cache-list-unexpected-type\", { entry });\n  }\n\n  // If there's just a URL and no revision, then it's also assumed to be a\n  // versioned URL.\n  if (!revision) {\n    const urlObject = new URL(url, location.href);\n    return {\n      cacheKey: urlObject.href,\n      url: urlObject.href,\n    };\n  }\n\n  // Otherwise, construct a properly versioned URL using the custom Serwist\n  // search parameter along with the revision info.\n  const cacheKeyURL = new URL(url, location.href);\n  const originalURL = new URL(url, location.href);\n  cacheKeyURL.searchParams.set(REVISION_SEARCH_PARAM, revision);\n  return {\n    cacheKey: cacheKeyURL.href,\n    url: originalURL.href,\n  };\n};\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { SerwistPlugin, SerwistPluginCallbackParam } from \"../types.js\";\n\n/**\n * A plugin designed to determine the number of assets that were updated (or not updated)\n * during the `install` event.\n *\n * @private\n */\nexport class PrecacheInstallReportPlugin implements SerwistPlugin {\n  updatedURLs: string[] = [];\n  notUpdatedURLs: string[] = [];\n\n  handlerWillStart: SerwistPlugin[\"handlerWillStart\"] = async ({ request, state }: SerwistPluginCallbackParam[\"handlerWillStart\"]) => {\n    // TODO: `state` should never be undefined...\n    if (state) {\n      state.originalRequest = request;\n    }\n  };\n\n  cachedResponseWillBeUsed: SerwistPlugin[\"cachedResponseWillBeUsed\"] = async ({\n    event,\n    state,\n    cachedResponse,\n  }: SerwistPluginCallbackParam[\"cachedResponseWillBeUsed\"]) => {\n    if (event.type === \"install\") {\n      if (state?.originalRequest && state.originalRequest instanceof Request) {\n        // TODO: `state` should never be undefined...\n        const url = state.originalRequest.url;\n\n        if (cachedResponse) {\n          this.notUpdatedURLs.push(url);\n        } else {\n          this.updatedURLs.push(url);\n        }\n      }\n    }\n    return cachedResponse;\n  };\n}\n", "import type { HTTPMethod } from \"../constants.js\";\nimport { RegExpRoute } from \"../RegExpRoute.js\";\nimport { Route } from \"../Route.js\";\nimport type { RouteHandler, RouteMatchCallback } from \"../types.js\";\nimport { logger } from \"./logger.js\";\nimport { SerwistError } from \"./SerwistError.js\";\n\n/**\n * Parses a `RegExp`, string, or function with a caching strategy into a {@linkcode Route}. This is for\n * when you want to create a {@linkcode Route}, but you don't want to register it just yet: sometimes\n * you want to call {@linkcode Route.setCatchHandler} first, for example.\n *\n * @param capture If the capture param is a {@linkcode Route} object, all other arguments will be ignored.\n * @param handler A callback function that returns a promise resulting in a response.\n * This parameter is required if `capture` is not a {@linkcode Route} object.\n * @param method The HTTP method to match the route against. Defaults to `'GET'`.\n * @returns The generated {@linkcode Route}.\n */\nexport const parseRoute = (capture: RegExp | string | RouteMatchCallback | Route, handler?: RouteHandler, method?: HTTPMethod): Route => {\n  if (typeof capture === \"string\") {\n    const captureUrl = new URL(capture, location.href);\n\n    if (process.env.NODE_ENV !== \"production\") {\n      if (!(capture.startsWith(\"/\") || capture.startsWith(\"http\"))) {\n        throw new SerwistError(\"invalid-string\", {\n          moduleName: \"serwist\",\n          funcName: \"parseRoute\",\n          paramName: \"capture\",\n        });\n      }\n\n      // We want to check if Express-style wildcards are in the pathname only.\n      // TODO: Remove this log message in v4.\n      const valueToCheck = capture.startsWith(\"http\") ? captureUrl.pathname : capture;\n\n      // See https://github.com/pillarjs/path-to-regexp#parameters\n      const wildcards = \"[*:?+]\";\n      if (new RegExp(`${wildcards}`).exec(valueToCheck)) {\n        logger.debug(\n          `The '$capture' parameter contains an Express-style wildcard character (${wildcards}). Strings are now always interpreted as exact matches; use a RegExp for partial or wildcard matches.`,\n        );\n      }\n    }\n\n    const matchCallback: RouteMatchCallback = ({ url }) => {\n      if (process.env.NODE_ENV !== \"production\") {\n        if (url.pathname === captureUrl.pathname && url.origin !== captureUrl.origin) {\n          logger.debug(\n            `${capture} only partially matches the cross-origin URL ${url.toString()}. This route will only handle cross-origin requests if they match the entire URL.`,\n          );\n        }\n      }\n\n      return url.href === captureUrl.href;\n    };\n\n    // If `capture` is a string then `handler` and `method` must be present.\n    return new Route(matchCallback, handler!, method);\n  }\n  if (capture instanceof RegExp) {\n    // If `capture` is a `RegExp` then `handler` and `method` must be present.\n    return new RegExpRoute(capture, handler!, method);\n  }\n  if (typeof capture === \"function\") {\n    // If `capture` is a function then `handler` and `method` must be present.\n    return new Route(capture, handler!, method);\n  }\n  if (capture instanceof Route) {\n    return capture;\n  }\n  throw new SerwistError(\"unsupported-route-type\", {\n    moduleName: \"serwist\",\n    funcName: \"parseRoute\",\n    paramName: \"capture\",\n  });\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { logger } from \"./logger.js\";\n\n/**\n * @param groupTitle\n * @param deletedURLs\n *\n * @private\n */\nconst logGroup = (groupTitle: string, deletedURLs: string[]) => {\n  logger.groupCollapsed(groupTitle);\n\n  for (const url of deletedURLs) {\n    logger.log(url);\n  }\n\n  logger.groupEnd();\n};\n\n/**\n * @param deletedURLs\n * @private\n */\nexport const printCleanupDetails = (deletedURLs: string[]): void => {\n  const deletionCount = deletedURLs.length;\n  if (deletionCount > 0) {\n    logger.groupCollapsed(`During precaching cleanup, ${deletionCount} cached request${deletionCount === 1 ? \" was\" : \"s were\"} deleted.`);\n    logGroup(\"Deleted Cache Requests\", deletedURLs);\n    logger.groupEnd();\n  }\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { logger } from \"./logger.js\";\n\n/**\n * @param groupTitle\n * @param urls\n *\n * @private\n */\nfunction _nestedGroup(groupTitle: string, urls: string[]): void {\n  if (urls.length === 0) {\n    return;\n  }\n\n  logger.groupCollapsed(groupTitle);\n\n  for (const url of urls) {\n    logger.log(url);\n  }\n\n  logger.groupEnd();\n}\n\n/**\n * @param urlsToPrecache\n * @param  urlsAlreadyPrecached\n * @private\n */\nexport const printInstallDetails = (urlsToPrecache: string[], urlsAlreadyPrecached: string[]): void => {\n  const precachedCount = urlsToPrecache.length;\n  const alreadyPrecachedCount = urlsAlreadyPrecached.length;\n\n  if (precachedCount || alreadyPrecachedCount) {\n    let message = `Precaching ${precachedCount} file${precachedCount === 1 ? \"\" : \"s\"}.`;\n\n    if (alreadyPrecachedCount > 0) {\n      message += ` ${alreadyPrecachedCount} ` + `file${alreadyPrecachedCount === 1 ? \" is\" : \"s are\"} already cached.`;\n    }\n\n    logger.groupCollapsed(message);\n\n    _nestedGroup(\"View newly precached URLs.\", urlsToPrecache);\n    _nestedGroup(\"View previously precached URLs.\", urlsAlreadyPrecached);\n    logger.groupEnd();\n  }\n};\n", "export const nonNullable = <T>(value: T): value is NonNullable<T> => value !== null && value !== undefined;\n", "// Source code: https://github.com/rayepps/radash/blob/03dd3152f560414e933cedcd3bda3c6db3e8306b/src/async.ts#L112-L147\n// License: MIT\n// Author: rayepps\ninterface ItemResult<K> {\n  index: number;\n  result: K;\n}\n\n/**\n * Executes many async functions in parallel. Returns the\n * results from all functions as an array. Does not handle\n * any error.\n */\nexport const parallel = async <T, K>(limit: number, array: readonly T[], func: (item: T) => Promise<K>): Promise<K[]> => {\n  const work = array.map((item, index) => ({\n    index,\n    item,\n  }));\n  // Process array items\n  const processor = async (res: (value: ItemResult<K>[]) => void) => {\n    const results: ItemResult<K>[] = [];\n    while (true) {\n      const next = work.pop();\n      if (!next) {\n        return res(results);\n      }\n      const result = await func(next.item);\n      results.push({\n        result: result,\n        index: next.index,\n      });\n    }\n  };\n  // Create queues\n  const queues = Array.from({ length: limit }, () => new Promise(processor));\n  // Wait for all queues to complete\n  const results = (await Promise.all(queues))\n    .flat()\n    .sort((a, b) => (a.index < b.index ? -1 : 1))\n    .map((res) => res.result);\n  return results;\n};\n", "export const toUnix = (p: string) => p.replace(/\\\\/g, \"/\").replace(/(?<!^)\\/+/g, \"/\");\n", "export const compare = <T extends string | number>(a: T, b: T) => {\n  if (a < b) return -1;\n  if (a > b) return +1;\n  return 0;\n};\n", "/** @see https://esbuild.github.io/api/#target */\nexport const SUPPORTED_ESBUILD_TARGETS = [\"chrome\", \"deno\", \"edge\", \"firefox\", \"hermes\", \"ie\", \"ios\", \"node\", \"opera\", \"rhino\", \"safari\"];\n\nexport const UNSUPPORTED_BROWSERLIST_TARGETS = [\"android 4\", \"android 3\", \"android 2\"];\n", "// Source: https://github.com/browserslist/browserslist/blob/5cad191bc1a1e5beb7768ca263503cc15d0dcc7d/index.js#L139-L151\n// License: MIT\nimport { compare } from \"./compare.js\";\n\nexport const compareSemver = (a: string[], b: string[]) => {\n  return (\n    compare(Number.parseInt(a[0], 10), Number.parseInt(b[0], 10)) ||\n    compare(Number.parseInt(a[1] || \"0\", 10), Number.parseInt(b[1] || \"0\", 10)) ||\n    compare(Number.parseInt(a[2] || \"0\", 10), Number.parseInt(b[2] || \"0\", 10))\n  );\n};\n", "import type Browserslist from \"browserslist\";\nimport { compare } from \"./compare.js\";\nimport { SUPPORTED_ESBUILD_TARGETS, UNSUPPORTED_BROWSERLIST_TARGETS } from \"./constants.js\";\nimport { compareSemver } from \"./semver.js\";\n\n// Original: https://github.com/marcofugaro/browserslist-to-esbuild/blob/0875f1a4ec71f206a634ba406c3528ca5ecf04de/src/index.js\n// License: MIT\n/**\n * Loads and converts Browserslist into esbuild's `target` option.\n *\n * @param cwd\n * @returns\n */\nexport const browserslistToEsbuild = (browserslist: typeof Browserslist, cwd: string, defaultBrowserslist: string[]): string[] => {\n  const browserslistConfig = browserslist.loadConfig({ path: cwd }) ?? defaultBrowserslist;\n  return (\n    browserslist(browserslistConfig)\n      // Filter out legacy Android webview to avoid converting them into Chrome targets\n      .filter((query) => !UNSUPPORTED_BROWSERLIST_TARGETS.some((target) => query.startsWith(target)))\n      .map((query) => {\n        const modified = query === \"safari TP\" ? browserslist(\"last 1 safari version\")[0] : query;\n        const split = modified.split(\" \");\n        // https://github.com/browserslist/browserslist/blob/5cad191bc1a1e5beb7768ca263503cc15d0dcc7d/README.md?plain=1#L329-L350\n        // https://esbuild.github.io/api/#target\n        if (split[0] === \"android\" || split[0] === \"and_chr\") {\n          split[0] = \"chrome\";\n        }\n        if (split[0] === \"and_ff\") {\n          split[0] = \"firefox\";\n        }\n        if (split[0] === \"ios_saf\" || split[0] === \"ios\") {\n          split[0] = \"safari\";\n        }\n        // Remove upper version bound\n        if (split[1].includes(\"-\")) {\n          split[1] = split[1].slice(0, split[1].indexOf(\"-\"));\n        }\n        // Trim ending .0\n        if (split[1].endsWith(\".0\")) {\n          split[1] = split[1].slice(0, -2);\n        }\n        return split;\n      })\n      // Remove unsupported browsers and invalid versions\n      .filter((split) => SUPPORTED_ESBUILD_TARGETS.includes(split[0]) && /^\\d+(\\.\\d+)*$/.test(split[1]))\n      // Re-sort the result such that the oldest versions end up the latest, same as how\n      // Browserslist does it.\n      .sort((a, b) => {\n        if (a[0] === b[0]) {\n          return compareSemver(b[1].split(\".\"), a[1].split(\".\"));\n        } else {\n          return compare(a[0], b[0]);\n        }\n      })\n      // Only pick the oldest included version for each browser to avoid duplications.\n      .reduce((acc, browser) => {\n        const existingIndex = acc.findIndex((br) => br[0] === browser[0]);\n        if (existingIndex !== -1) {\n          acc[existingIndex][1] = browser[1];\n        } else {\n          acc.push(browser);\n        }\n        return acc;\n      }, [] as string[][])\n      .map((split) => split.join(\"\"))\n  );\n};\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { cacheNames as privateCacheNames } from \"./utils/cacheNames.js\";\n\n/**\n * Get the current cache names and prefix/suffix used by Serwist.\n *\n * `cacheNames.precache` is used for precached assets,\n * `cacheNames.googleAnalytics` is used by `@serwist/google-analytics` to\n * store `analytics.js`, and `cacheNames.runtime` is used for everything else.\n *\n * `cacheNames.prefix` can be used to retrieve just the current prefix value.\n * `cacheNames.suffix` can be used to retrieve just the current suffix value.\n *\n * @returns An object with `precache`, `runtime`, `prefix`, and `googleAnalytics` properties.\n */\nexport const cacheNames = {\n  get googleAnalytics(): string {\n    return privateCacheNames.getGoogleAnalyticsName();\n  },\n  get precache(): string {\n    return privateCacheNames.getPrecacheName();\n  },\n  get prefix(): string {\n    return privateCacheNames.getPrefix();\n  },\n  get runtime(): string {\n    return privateCacheNames.getRuntimeName();\n  },\n  get suffix(): string {\n    return privateCacheNames.getSuffix();\n  },\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nexport const BROADCAST_UPDATE_MESSAGE_TYPE = \"CACHE_UPDATED\";\nexport const BROADCAST_UPDATE_MESSAGE_META = \"serwist-broadcast-update\";\nexport const BROADCAST_UPDATE_DEFAULT_NOTIFY = true;\nexport const BROADCAST_UPDATE_DEFAULT_HEADERS = [\"content-length\", \"etag\", \"last-modified\"];\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\n\n/**\n * Given two responses, compares several header values to see if they are\n * the same or not.\n *\n * @param firstResponse The first response.\n * @param secondResponse The second response.\n * @param headersToCheck A list of headers to check.\n * @returns\n */\nexport const responsesAreSame = (firstResponse: Response, secondResponse: Response, headersToCheck: string[]): boolean => {\n  if (process.env.NODE_ENV !== \"production\") {\n    if (!(firstResponse instanceof Response && secondResponse instanceof Response)) {\n      throw new SerwistError(\"invalid-responses-are-same-args\");\n    }\n  }\n\n  const atLeastOneHeaderAvailable = headersToCheck.some((header) => {\n    return firstResponse.headers.has(header) && secondResponse.headers.has(header);\n  });\n\n  if (!atLeastOneHeaderAvailable) {\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.warn(\"Unable to determine where the response has been updated because none of the headers that would be checked are present.\");\n      logger.debug(\"Attempting to compare the following: \", firstResponse, secondResponse, headersToCheck);\n    }\n\n    // Just return true, indicating the that responses are the same, since we\n    // can't determine otherwise.\n    return true;\n  }\n\n  return headersToCheck.every((header) => {\n    const headerStateComparison = firstResponse.headers.has(header) === secondResponse.headers.has(header);\n    const headerValueComparison = firstResponse.headers.get(header) === secondResponse.headers.get(header);\n\n    return headerStateComparison && headerValueComparison;\n  });\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { CacheDidUpdateCallbackParam } from \"../../types.js\";\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { resultingClientExists } from \"../../utils/resultingClientExists.js\";\nimport { timeout } from \"../../utils/timeout.js\";\nimport {\n  BROADCAST_UPDATE_DEFAULT_HEADERS,\n  BROADCAST_UPDATE_DEFAULT_NOTIFY,\n  BROADCAST_UPDATE_MESSAGE_META,\n  BROADCAST_UPDATE_MESSAGE_TYPE,\n} from \"./constants.js\";\nimport { responsesAreSame } from \"./responsesAreSame.js\";\nimport type { BroadcastCacheUpdateOptions, BroadcastMessage, BroadcastPayload, BroadcastPayloadGenerator } from \"./types.js\";\n\n// UA-sniff Safari: https://stackoverflow.com/questions/7944460/detect-safari-browser\n// TODO(philipwalton): remove once this Safari bug fix has been released.\n// https://bugs.webkit.org/show_bug.cgi?id=201169\nconst isSafari = typeof navigator !== \"undefined\" && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n\n// Give TypeScript the correct global.\ndeclare const self: ServiceWorkerGlobalScope;\n/**\n * Generates the default payload used in update messages. By default the\n * payload includes the `cacheName` and `updatedURL` fields.\n *\n * @returns\n * @private\n */\nconst defaultPayloadGenerator = (data: CacheDidUpdateCallbackParam): BroadcastPayload => {\n  return {\n    cacheName: data.cacheName,\n    updatedURL: data.request.url,\n  };\n};\n\n/**\n * A class that uses the `postMessage()` API to inform any open windows/tabs when\n * a cached response has been updated.\n *\n * For efficiency's sake, the underlying response bodies are not compared;\n * only specific response headers are checked.\n */\nexport class BroadcastCacheUpdate {\n  private readonly _headersToCheck: string[];\n  private readonly _generatePayload: BroadcastPayloadGenerator;\n  private readonly _notifyAllClients: boolean;\n\n  /**\n   * Construct an instance of `BroadcastCacheUpdate`.\n   *\n   * @param options\n   */\n  constructor({ generatePayload, headersToCheck, notifyAllClients }: BroadcastCacheUpdateOptions = {}) {\n    this._headersToCheck = headersToCheck || BROADCAST_UPDATE_DEFAULT_HEADERS;\n    this._generatePayload = generatePayload || defaultPayloadGenerator;\n    this._notifyAllClients = notifyAllClients ?? BROADCAST_UPDATE_DEFAULT_NOTIFY;\n  }\n\n  /**\n   * Compares two responses and sends a message (via `postMessage()`) to all window clients if the\n   * responses differ. Neither of the Responses can be opaque.\n   *\n   * The message that's posted has the following format (where `payload` can\n   * be customized via the `generatePayload` option the instance is created\n   * with):\n   *\n   * ```\n   * {\n   *   type: 'CACHE_UPDATED',\n   *   meta: 'workbox-broadcast-update',\n   *   payload: {\n   *     cacheName: 'the-cache-name',\n   *     updatedURL: 'https://example.com/'\n   *   }\n   * }\n   * ```\n   *\n   * @param options\n   * @returns Resolves once the update is sent.\n   */\n  async notifyIfUpdated(options: CacheDidUpdateCallbackParam): Promise<void> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(options.cacheName, \"string\", {\n        moduleName: \"serwist\",\n        className: \"BroadcastCacheUpdate\",\n        funcName: \"notifyIfUpdated\",\n        paramName: \"cacheName\",\n      });\n      assert!.isInstance(options.newResponse, Response, {\n        moduleName: \"serwist\",\n        className: \"BroadcastCacheUpdate\",\n        funcName: \"notifyIfUpdated\",\n        paramName: \"newResponse\",\n      });\n      assert!.isInstance(options.request, Request, {\n        moduleName: \"serwist\",\n        className: \"BroadcastCacheUpdate\",\n        funcName: \"notifyIfUpdated\",\n        paramName: \"request\",\n      });\n    }\n\n    // Without two responses there is nothing to compare.\n    if (!options.oldResponse) {\n      return;\n    }\n\n    if (!responsesAreSame(options.oldResponse, options.newResponse, this._headersToCheck)) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.log(\"Newer response found (and cached) for:\", options.request.url);\n      }\n\n      const messageData = {\n        type: BROADCAST_UPDATE_MESSAGE_TYPE,\n        meta: BROADCAST_UPDATE_MESSAGE_META,\n        payload: this._generatePayload(options),\n      } satisfies BroadcastMessage;\n\n      // For navigation requests, wait until the new window client exists\n      // before sending the message\n      if (options.request.mode === \"navigate\") {\n        let resultingClientId: string | undefined;\n        if (options.event instanceof FetchEvent) {\n          resultingClientId = options.event.resultingClientId;\n        }\n\n        const resultingWin = await resultingClientExists(resultingClientId);\n\n        // Safari does not currently implement postMessage buffering and\n        // there's no good way to feature detect that, so to increase the\n        // chances of the message being delivered in Safari, we add a timeout.\n        // We also do this if `resultingClientExists()` didn't return a client,\n        // which means it timed out, so it's worth waiting a bit longer.\n        if (!resultingWin || isSafari) {\n          // 3500 is chosen because (according to CrUX data) 80% of mobile\n          // websites hit the DOMContentLoaded event in less than 3.5 seconds.\n          // And presumably sites implementing service worker are on the\n          // higher end of the performance spectrum.\n          await timeout(3500);\n        }\n      }\n\n      if (this._notifyAllClients) {\n        const windows = await self.clients.matchAll({ type: \"window\" });\n        for (const win of windows) {\n          win.postMessage(messageData);\n        }\n      } else {\n        // See https://github.com/GoogleChrome/workbox/issues/2895\n        if (options.event instanceof FetchEvent) {\n          const client = await self.clients.get(options.event.clientId);\n          client?.postMessage(messageData);\n        }\n      }\n    }\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { CacheDidUpdateCallbackParam, SerwistPlugin } from \"../../types.js\";\nimport { BroadcastCacheUpdate } from \"./BroadcastCacheUpdate.js\";\nimport type { BroadcastCacheUpdateOptions } from \"./types.js\";\n\n/**\n * A class implementing the `cacheDidUpdate` lifecycle callback. It will automatically\n * broadcast a message whenever a cached response is updated.\n */\nexport class BroadcastUpdatePlugin implements SerwistPlugin {\n  private readonly _broadcastUpdate: BroadcastCacheUpdate;\n\n  /**\n   * Construct a {@linkcode BroadcastCacheUpdate} instance with\n   * the passed options and calls its {@linkcode BroadcastCacheUpdate.notifyIfUpdated}\n   * method whenever the plugin's {@linkcode BroadcastUpdatePlugin.cacheDidUpdate} callback\n   * is invoked.\n   *\n   * @param options\n   */\n  constructor(options?: BroadcastCacheUpdateOptions) {\n    this._broadcastUpdate = new BroadcastCacheUpdate(options);\n  }\n\n  /**\n   * @private\n   * @param options The input object to this function.\n   */\n  cacheDidUpdate(options: CacheDidUpdateCallbackParam) {\n    void this._broadcastUpdate.notifyIfUpdated(options);\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\n\nexport interface CacheableResponseOptions {\n  /**\n   * One or more HTTP status codes that a response can have to be considered cacheable.\n   */\n  statuses?: number[];\n  /**\n   * A mapping of header names and expected values that a response can have and be\n   * considered cacheable. If multiple headers are provided, only one needs to be present.\n   */\n  headers?: HeadersInit;\n}\n\n/**\n * Allows you to set up rules determining what status codes and/or headers need\n * to be present in order for a [response](https://developer.mozilla.org/en-US/docs/Web/API/Response)\n * to be considered cacheable.\n */\nexport class CacheableResponse {\n  private readonly _statuses?: CacheableResponseOptions[\"statuses\"];\n  private readonly _headers?: Headers;\n\n  /**\n   * To construct a new `CacheableResponse` instance you must provide at least\n   * one of the `config` properties.\n   *\n   * If both `statuses` and `headers` are specified, then both conditions must\n   * be met for the response to be considered cacheable.\n   *\n   * @param config\n   */\n  constructor(config: CacheableResponseOptions = {}) {\n    if (process.env.NODE_ENV !== \"production\") {\n      if (!(config.statuses || config.headers)) {\n        throw new SerwistError(\"statuses-or-headers-required\", {\n          moduleName: \"serwist\",\n          className: \"CacheableResponse\",\n          funcName: \"constructor\",\n        });\n      }\n\n      if (config.statuses) {\n        assert!.isArray(config.statuses, {\n          moduleName: \"serwist\",\n          className: \"CacheableResponse\",\n          funcName: \"constructor\",\n          paramName: \"config.statuses\",\n        });\n      }\n\n      if (config.headers) {\n        assert!.isType(config.headers, \"object\", {\n          moduleName: \"serwist\",\n          className: \"CacheableResponse\",\n          funcName: \"constructor\",\n          paramName: \"config.headers\",\n        });\n      }\n    }\n\n    this._statuses = config.statuses;\n    if (config.headers) {\n      this._headers = new Headers(config.headers);\n    }\n  }\n\n  /**\n   * Checks a response to see whether it's cacheable or not.\n   *\n   * @param response The response whose cacheability is being\n   * checked.\n   * @returns `true` if the response is cacheable, and `false`\n   * otherwise.\n   */\n  isResponseCacheable(response: Response): boolean {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(response, Response, {\n        moduleName: \"serwist\",\n        className: \"CacheableResponse\",\n        funcName: \"isResponseCacheable\",\n        paramName: \"response\",\n      });\n    }\n\n    let cacheable = true;\n\n    if (this._statuses) {\n      cacheable = this._statuses.includes(response.status);\n    }\n\n    if (this._headers && cacheable) {\n      for (const [headerName, headerValue] of this._headers.entries()) {\n        if (response.headers.get(headerName) !== headerValue) {\n          cacheable = false;\n          break;\n        }\n      }\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      if (!cacheable) {\n        logger.groupCollapsed(\n          `The request for '${getFriendlyURL(response.url)}' returned a response that does not meet the criteria for being cached.`,\n        );\n\n        logger.groupCollapsed(\"View cacheability criteria here.\");\n        logger.log(`Cacheable statuses: ${JSON.stringify(this._statuses)}`);\n        logger.log(`Cacheable headers: ${JSON.stringify(this._headers, null, 2)}`);\n        logger.groupEnd();\n\n        const logFriendlyHeaders: { [key: string]: string } = {};\n        response.headers.forEach((value, key) => {\n          logFriendlyHeaders[key] = value;\n        });\n\n        logger.groupCollapsed(\"View response status and headers here.\");\n        logger.log(`Response status: ${response.status}`);\n        logger.log(`Response headers: ${JSON.stringify(logFriendlyHeaders, null, 2)}`);\n        logger.groupEnd();\n\n        logger.groupCollapsed(\"View full response details here.\");\n        logger.log(response.headers);\n        logger.log(response);\n        logger.groupEnd();\n\n        logger.groupEnd();\n      }\n    }\n\n    return cacheable;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { SerwistPlugin } from \"../../types.js\";\nimport type { CacheableResponseOptions } from \"./CacheableResponse.js\";\nimport { CacheableResponse } from \"./CacheableResponse.js\";\n\n/**\n * A class implementing the `cacheWillUpdate` lifecycle callback. This makes it\n * easier to add in cacheability checks to requests made via Serwist's built-in\n * strategies.\n */\nexport class CacheableResponsePlugin implements SerwistPlugin {\n  private readonly _cacheableResponse: CacheableResponse;\n\n  /**\n   * To construct a new `CacheableResponsePlugin` instance you must provide at\n   * least one of the `config` properties.\n   *\n   * If both `statuses` and `headers` are specified, then both conditions must\n   * be met for the response to be considered cacheable.\n   *\n   * @param config\n   */\n  constructor(config: CacheableResponseOptions) {\n    this._cacheableResponse = new CacheableResponse(config);\n  }\n\n  /**\n   * @param options\n   * @returns\n   * @private\n   */\n  cacheWillUpdate: SerwistPlugin[\"cacheWillUpdate\"] = async ({ response }) => {\n    if (this._cacheableResponse.isResponseCacheable(response)) {\n      return response;\n    }\n    return null;\n  };\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { DBSchema, IDBPDatabase } from \"idb\";\nimport { deleteDB, openDB } from \"idb\";\n\nconst DB_NAME = \"serwist-expiration\";\nconst CACHE_OBJECT_STORE = \"cache-entries\";\n\nconst normalizeURL = (unNormalizedUrl: string) => {\n  const url = new URL(unNormalizedUrl, location.href);\n  url.hash = \"\";\n\n  return url.href;\n};\n\ninterface CacheTimestampsModelEntry {\n  id: string;\n  cacheName: string;\n  url: string;\n  timestamp: number;\n}\n\ninterface CacheDbSchema extends DBSchema {\n  \"cache-entries\": {\n    key: string;\n    value: CacheTimestampsModelEntry;\n    indexes: { cacheName: string; timestamp: number };\n  };\n}\n\n/**\n * Returns the timestamp model.\n *\n * @private\n */\nexport class CacheTimestampsModel {\n  private readonly _cacheName: string;\n  private _db: IDBPDatabase<CacheDbSchema> | null = null;\n\n  /**\n   *\n   * @param cacheName\n   *\n   * @private\n   */\n  constructor(cacheName: string) {\n    this._cacheName = cacheName;\n  }\n\n  /**\n   * Takes a URL and returns an ID that will be unique in the object store.\n   *\n   * @param url\n   * @returns\n   * @private\n   */\n  private _getId(url: string): string {\n    return `${this._cacheName}|${normalizeURL(url)}`;\n  }\n\n  /**\n   * Performs an upgrade of indexedDB.\n   *\n   * @param db\n   *\n   * @private\n   */\n  private _upgradeDb(db: IDBPDatabase<CacheDbSchema>) {\n    const objStore = db.createObjectStore(CACHE_OBJECT_STORE, {\n      keyPath: \"id\",\n    });\n\n    // TODO(philipwalton): once we don't have to support EdgeHTML, we can\n    // create a single index with the keyPath `['cacheName', 'timestamp']`\n    // instead of doing both these indexes.\n    objStore.createIndex(\"cacheName\", \"cacheName\", { unique: false });\n    objStore.createIndex(\"timestamp\", \"timestamp\", { unique: false });\n  }\n\n  /**\n   * Performs an upgrade of indexedDB and deletes deprecated DBs.\n   *\n   * @param db\n   *\n   * @private\n   */\n  private _upgradeDbAndDeleteOldDbs(db: IDBPDatabase<CacheDbSchema>) {\n    this._upgradeDb(db);\n    if (this._cacheName) {\n      void deleteDB(this._cacheName);\n    }\n  }\n\n  /**\n   * @param url\n   * @param timestamp\n   *\n   * @private\n   */\n  async setTimestamp(url: string, timestamp: number): Promise<void> {\n    url = normalizeURL(url);\n\n    const entry = {\n      id: this._getId(url),\n      cacheName: this._cacheName,\n      url,\n      timestamp,\n    } satisfies CacheTimestampsModelEntry;\n    const db = await this.getDb();\n    const tx = db.transaction(CACHE_OBJECT_STORE, \"readwrite\", {\n      durability: \"relaxed\",\n    });\n    await tx.store.put(entry);\n    await tx.done;\n  }\n\n  /**\n   * Returns the timestamp stored for a given URL.\n   *\n   * @param url\n   * @returns\n   * @private\n   */\n  async getTimestamp(url: string): Promise<number | undefined> {\n    const db = await this.getDb();\n    const entry = await db.get(CACHE_OBJECT_STORE, this._getId(url));\n    return entry?.timestamp;\n  }\n\n  /**\n   * Iterates through all the entries in the object store (from newest to\n   * oldest) and removes entries once either `maxCount` is reached or the\n   * entry's timestamp is less than `minTimestamp`.\n   *\n   * @param minTimestamp\n   * @param maxCount\n   * @returns\n   * @private\n   */\n  async expireEntries(minTimestamp: number, maxCount?: number): Promise<string[]> {\n    const db = await this.getDb();\n    let cursor = await db.transaction(CACHE_OBJECT_STORE, \"readwrite\").store.index(\"timestamp\").openCursor(null, \"prev\");\n    const urlsDeleted: string[] = [];\n    let entriesNotDeletedCount = 0;\n    while (cursor) {\n      const result = cursor.value;\n      // TODO(philipwalton): once we can use a multi-key index, we\n      // won't have to check `cacheName` here.\n      if (result.cacheName === this._cacheName) {\n        // Delete an entry if it's older than the max age or\n        // if we already have the max number allowed.\n        if ((minTimestamp && result.timestamp < minTimestamp) || (maxCount && entriesNotDeletedCount >= maxCount)) {\n          cursor.delete();\n          urlsDeleted.push(result.url);\n        } else {\n          entriesNotDeletedCount++;\n        }\n      }\n      cursor = await cursor.continue();\n    }\n\n    return urlsDeleted;\n  }\n\n  /**\n   * Returns an open connection to the database.\n   *\n   * @private\n   */\n  private async getDb() {\n    if (!this._db) {\n      this._db = await openDB(DB_NAME, 1, {\n        upgrade: this._upgradeDbAndDeleteOldDbs.bind(this),\n      });\n    }\n    return this._db;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { CacheTimestampsModel } from \"./models/CacheTimestampsModel.js\";\n\ninterface CacheExpirationConfig {\n  /**\n   * The maximum number of entries to cache. Entries used least recently will\n   * be removed as the maximum is reached.\n   */\n  maxEntries?: number;\n  /**\n   * The maximum age of an entry before it's treated as stale and removed.\n   */\n  maxAgeSeconds?: number;\n  /**\n   * The [`CacheQueryOptions`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/delete#Parameters)\n   * that will be used when calling `delete()` on the cache.\n   */\n  matchOptions?: CacheQueryOptions;\n}\n\n/**\n * Allows you to expires cached responses based on age or maximum number of entries.\n * @see https://serwist.pages.dev/docs/serwist/core/cache-expiration\n */\nexport class CacheExpiration {\n  private _isRunning = false;\n  private _rerunRequested = false;\n  private readonly _maxEntries?: number;\n  private readonly _maxAgeSeconds?: number;\n  private readonly _matchOptions?: CacheQueryOptions;\n  private readonly _cacheName: string;\n  private readonly _timestampModel: CacheTimestampsModel;\n\n  /**\n   * To construct a new `CacheExpiration` instance you must provide at least\n   * one of the `config` properties.\n   *\n   * @param cacheName Name of the cache to apply restrictions to.\n   * @param config\n   */\n  constructor(cacheName: string, config: CacheExpirationConfig = {}) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(cacheName, \"string\", {\n        moduleName: \"serwist\",\n        className: \"CacheExpiration\",\n        funcName: \"constructor\",\n        paramName: \"cacheName\",\n      });\n\n      if (!(config.maxEntries || config.maxAgeSeconds)) {\n        throw new SerwistError(\"max-entries-or-age-required\", {\n          moduleName: \"serwist\",\n          className: \"CacheExpiration\",\n          funcName: \"constructor\",\n        });\n      }\n\n      if (config.maxEntries) {\n        assert!.isType(config.maxEntries, \"number\", {\n          moduleName: \"serwist\",\n          className: \"CacheExpiration\",\n          funcName: \"constructor\",\n          paramName: \"config.maxEntries\",\n        });\n      }\n\n      if (config.maxAgeSeconds) {\n        assert!.isType(config.maxAgeSeconds, \"number\", {\n          moduleName: \"serwist\",\n          className: \"CacheExpiration\",\n          funcName: \"constructor\",\n          paramName: \"config.maxAgeSeconds\",\n        });\n      }\n    }\n\n    this._maxEntries = config.maxEntries;\n    this._maxAgeSeconds = config.maxAgeSeconds;\n    this._matchOptions = config.matchOptions;\n    this._cacheName = cacheName;\n    this._timestampModel = new CacheTimestampsModel(cacheName);\n  }\n\n  /**\n   * Expires entries for the given cache and given criteria.\n   */\n  async expireEntries(): Promise<void> {\n    if (this._isRunning) {\n      this._rerunRequested = true;\n      return;\n    }\n    this._isRunning = true;\n\n    const minTimestamp = this._maxAgeSeconds ? Date.now() - this._maxAgeSeconds * 1000 : 0;\n\n    const urlsExpired = await this._timestampModel.expireEntries(minTimestamp, this._maxEntries);\n\n    // Delete URLs from the cache\n    const cache = await self.caches.open(this._cacheName);\n    for (const url of urlsExpired) {\n      await cache.delete(url, this._matchOptions);\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      if (urlsExpired.length > 0) {\n        logger.groupCollapsed(\n          `Expired ${urlsExpired.length} ` +\n            `${urlsExpired.length === 1 ? \"entry\" : \"entries\"} and removed ` +\n            `${urlsExpired.length === 1 ? \"it\" : \"them\"} from the ` +\n            `'${this._cacheName}' cache.`,\n        );\n        logger.log(`Expired the following ${urlsExpired.length === 1 ? \"URL\" : \"URLs\"}:`);\n        for (const url of urlsExpired) {\n          logger.log(`    ${url}`);\n        }\n        logger.groupEnd();\n      } else {\n        logger.debug(\"Cache expiration ran and found no entries to remove.\");\n      }\n    }\n\n    this._isRunning = false;\n    if (this._rerunRequested) {\n      this._rerunRequested = false;\n      void this.expireEntries();\n    }\n  }\n\n  /**\n   * Updates the timestamp for the given URL, allowing it to be correctly\n   * tracked by the class.\n   *\n   * @param url\n   */\n  async updateTimestamp(url: string): Promise<void> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(url, \"string\", {\n        moduleName: \"serwist\",\n        className: \"CacheExpiration\",\n        funcName: \"updateTimestamp\",\n        paramName: \"url\",\n      });\n    }\n\n    await this._timestampModel.setTimestamp(url, Date.now());\n  }\n\n  /**\n   * Checks if a URL has expired or not before it's used.\n   *\n   * This looks the timestamp up in IndexedDB and can be slow.\n   *\n   * Note: This method does not remove an expired entry, call\n   * `expireEntries()` to remove such entries instead.\n   *\n   * @param url\n   * @returns\n   */\n  async isURLExpired(url: string): Promise<boolean> {\n    if (!this._maxAgeSeconds) {\n      if (process.env.NODE_ENV !== \"production\") {\n        throw new SerwistError(\"expired-test-without-max-age\", {\n          methodName: \"isURLExpired\",\n          paramName: \"maxAgeSeconds\",\n        });\n      }\n      return false;\n    }\n    const timestamp = await this._timestampModel.getTimestamp(url);\n    const expireOlderThan = Date.now() - this._maxAgeSeconds * 1000;\n    return timestamp !== undefined ? timestamp < expireOlderThan : true;\n  }\n\n  /**\n   * Removes the IndexedDB used to keep track of cache expiration metadata.\n   */\n  async delete(): Promise<void> {\n    // Make sure we don't attempt another rerun if we're called in the middle of\n    // a cache expiration.\n    this._rerunRequested = false;\n    await this._timestampModel.expireEntries(Number.POSITIVE_INFINITY); // Expires all.\n  }\n}\n", "/*\n  Copyright 2019 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { quotaErrorCallbacks } from \"./models/quotaErrorCallbacks.js\";\nimport { assert } from \"./utils/assert.js\";\nimport { logger } from \"./utils/logger.js\";\n\n/**\n * Adds a function to the set of quotaErrorCallbacks that will be executed if\n * there's a quota error.\n *\n * @param callback\n */\n// biome-ignore lint/complexity/noBannedTypes: Can't change Function type\nexport const registerQuotaErrorCallback = (callback: Function): void => {\n  if (process.env.NODE_ENV !== \"production\") {\n    assert!.isType(callback, \"function\", {\n      moduleName: \"@serwist/core\",\n      funcName: \"register\",\n      paramName: \"callback\",\n    });\n  }\n\n  quotaErrorCallbacks.add(callback);\n\n  if (process.env.NODE_ENV !== \"production\") {\n    logger.log(\"Registered a callback to respond to quota errors.\", callback);\n  }\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { registerQuotaErrorCallback } from \"../../registerQuotaErrorCallback.js\";\nimport type { CacheDidUpdateCallbackParam, CachedResponseWillBeUsedCallbackParam, SerwistPlugin } from \"../../types.js\";\nimport { assert } from \"../../utils/assert.js\";\nimport { cacheNames as privateCacheNames } from \"../../utils/cacheNames.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport type { Strategy } from \"../strategies/Strategy.js\";\nimport { CacheExpiration } from \"./CacheExpiration.js\";\n\nexport interface ExpirationPluginOptions {\n  /**\n   * The maximum number of entries to cache. Entries used (if `maxAgeFrom` is\n   * `\"last-used\"`) or fetched from the network (if `maxAgeFrom` is `\"last-fetched\"`)\n   * least recently will be removed as the maximum is reached.\n   */\n  maxEntries?: number;\n  /**\n   * The maximum number of seconds before an entry is treated as stale and removed.\n   */\n  maxAgeSeconds?: number;\n  /**\n   * Determines whether `maxAgeSeconds` should be calculated from when an\n   * entry was last fetched or when it was last used.\n   *\n   * @default \"last-fetched\"\n   */\n  maxAgeFrom?: \"last-fetched\" | \"last-used\";\n  /**\n   * The [`CacheQueryOptions`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/delete#Parameters)\n   * that will be used when calling `delete()` on the cache.\n   */\n  matchOptions?: CacheQueryOptions;\n  /**\n   * Whether to opt this cache into automatic deletion if the available storage quota has been exceeded.\n   */\n  purgeOnQuotaError?: boolean;\n}\n\n/**\n * This plugin can be used in a {@linkcode Strategy} to regularly enforce a\n * limit on the age and/or the number of cached requests.\n *\n * It can only be used with {@linkcode Strategy} instances that have a custom `cacheName` property set.\n * In other words, it can't be used to expire entries in strategies that use the default runtime\n * cache name.\n *\n * Whenever a cached response is used or updated, this plugin will look\n * at the associated cache and remove any old or extra responses.\n *\n * When using `maxAgeSeconds`, responses may be used *once* after expiring\n * because the expiration clean up will not have occurred until *after* the\n * cached response has been used. If the response has a \"Date\" header, then a lightweight expiration\n * check is performed, and the response will not be used immediately.\n *\n * When using `maxEntries`, the least recently requested entry will be removed\n * from the cache.\n *\n * @see https://serwist.pages.dev/docs/serwist/runtime-caching/plugins/expiration-plugin\n */\nexport class ExpirationPlugin implements SerwistPlugin {\n  private readonly _config: ExpirationPluginOptions;\n  private _cacheExpirations: Map<string, CacheExpiration>;\n\n  /**\n   * @param config\n   */\n  constructor(config: ExpirationPluginOptions = {}) {\n    if (process.env.NODE_ENV !== \"production\") {\n      if (!(config.maxEntries || config.maxAgeSeconds)) {\n        throw new SerwistError(\"max-entries-or-age-required\", {\n          moduleName: \"serwist\",\n          className: \"ExpirationPlugin\",\n          funcName: \"constructor\",\n        });\n      }\n\n      if (config.maxEntries) {\n        assert!.isType(config.maxEntries, \"number\", {\n          moduleName: \"serwist\",\n          className: \"ExpirationPlugin\",\n          funcName: \"constructor\",\n          paramName: \"config.maxEntries\",\n        });\n      }\n\n      if (config.maxAgeSeconds) {\n        assert!.isType(config.maxAgeSeconds, \"number\", {\n          moduleName: \"serwist\",\n          className: \"ExpirationPlugin\",\n          funcName: \"constructor\",\n          paramName: \"config.maxAgeSeconds\",\n        });\n      }\n\n      if (config.maxAgeFrom) {\n        assert!.isType(config.maxAgeFrom, \"string\", {\n          moduleName: \"serwist\",\n          className: \"ExpirationPlugin\",\n          funcName: \"constructor\",\n          paramName: \"config.maxAgeFrom\",\n        });\n      }\n    }\n\n    this._config = config;\n    this._cacheExpirations = new Map();\n\n    if (!this._config.maxAgeFrom) {\n      this._config.maxAgeFrom = \"last-fetched\";\n    }\n\n    if (this._config.purgeOnQuotaError) {\n      registerQuotaErrorCallback(() => this.deleteCacheAndMetadata());\n    }\n  }\n\n  /**\n   * A simple helper method to return a CacheExpiration instance for a given\n   * cache name.\n   *\n   * @param cacheName\n   * @returns\n   * @private\n   */\n  private _getCacheExpiration(cacheName: string): CacheExpiration {\n    if (cacheName === privateCacheNames.getRuntimeName()) {\n      throw new SerwistError(\"expire-custom-caches-only\");\n    }\n\n    let cacheExpiration = this._cacheExpirations.get(cacheName);\n    if (!cacheExpiration) {\n      cacheExpiration = new CacheExpiration(cacheName, this._config);\n      this._cacheExpirations.set(cacheName, cacheExpiration);\n    }\n    return cacheExpiration;\n  }\n\n  /**\n   * A lifecycle callback that will be triggered automatically when a\n   * response is about to be returned from a [`Cache`](https://developer.mozilla.org/en-US/docs/Web/API/Cache).\n   * It allows the response to be inspected for freshness and\n   * prevents it from being used if the response's `Date` header value is\n   * older than the configured `maxAgeSeconds`.\n   *\n   * @param options\n   * @returns `cachedResponse` if it is fresh and `null` if it is stale or\n   * not available.\n   * @private\n   */\n  cachedResponseWillBeUsed({ event, cacheName, request, cachedResponse }: CachedResponseWillBeUsedCallbackParam) {\n    if (!cachedResponse) {\n      return null;\n    }\n\n    const isFresh = this._isResponseDateFresh(cachedResponse);\n\n    // Expire entries to ensure that even if the expiration date has\n    // expired, it'll only be used once.\n    const cacheExpiration = this._getCacheExpiration(cacheName);\n\n    const isMaxAgeFromLastUsed = this._config.maxAgeFrom === \"last-used\";\n\n    const done = (async () => {\n      // Update the metadata for the request URL to the current timestamp.\n      // Only applies if `maxAgeFrom` is `\"last-used\"`, since the current\n      // lifecycle callback is `cachedResponseWillBeUsed`.\n      // This needs to be called before `expireEntries()` so as to avoid\n      // this URL being marked as expired.\n      if (isMaxAgeFromLastUsed) {\n        await cacheExpiration.updateTimestamp(request.url);\n      }\n      await cacheExpiration.expireEntries();\n    })();\n    try {\n      event.waitUntil(done);\n    } catch {\n      if (process.env.NODE_ENV !== \"production\") {\n        if (event instanceof FetchEvent) {\n          logger.warn(`Unable to ensure service worker stays alive when updating cache entry for '${getFriendlyURL(event.request.url)}'.`);\n        }\n      }\n    }\n\n    return isFresh ? cachedResponse : null;\n  }\n\n  /**\n   * @param cachedResponse\n   * @returns\n   * @private\n   */\n  private _isResponseDateFresh(cachedResponse: Response): boolean {\n    const isMaxAgeFromLastUsed = this._config.maxAgeFrom === \"last-used\";\n    // If `maxAgeFrom` is `\"last-used\"`, the `Date` header doesn't really\n    // matter since it is about when the response was created.\n    if (isMaxAgeFromLastUsed) {\n      return true;\n    }\n    const now = Date.now();\n    if (!this._config.maxAgeSeconds) {\n      return true;\n    }\n    // Check if the `Date` header will suffice a quick expiration check.\n    // See https://github.com/GoogleChromeLabs/sw-toolbox/issues/164 for\n    // discussion.\n    const dateHeaderTimestamp = this._getDateHeaderTimestamp(cachedResponse);\n    if (dateHeaderTimestamp === null) {\n      // Unable to parse date, so assume it's fresh.\n      return true;\n    }\n    // If we have a valid headerTime, then our response is fresh if the\n    // headerTime plus maxAgeSeconds is greater than the current time.\n    return dateHeaderTimestamp >= now - this._config.maxAgeSeconds * 1000;\n  }\n\n  /**\n   * Extracts the `Date` header and parse it into an useful value.\n   *\n   * @param cachedResponse\n   * @returns\n   * @private\n   */\n  private _getDateHeaderTimestamp(cachedResponse: Response): number | null {\n    if (!cachedResponse.headers.has(\"date\")) {\n      return null;\n    }\n\n    const dateHeader = cachedResponse.headers.get(\"date\")!;\n    const parsedDate = new Date(dateHeader);\n    const headerTime = parsedDate.getTime();\n\n    // If the `Date` header is invalid for some reason, `parsedDate.getTime()`\n    // will return NaN.\n    if (Number.isNaN(headerTime)) {\n      return null;\n    }\n\n    return headerTime;\n  }\n\n  /**\n   * A lifecycle callback that will be triggered automatically when an entry is added\n   * to a cache.\n   *\n   * @param options\n   * @private\n   */\n  async cacheDidUpdate({ cacheName, request }: CacheDidUpdateCallbackParam) {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(cacheName, \"string\", {\n        moduleName: \"serwist\",\n        className: \"Plugin\",\n        funcName: \"cacheDidUpdate\",\n        paramName: \"cacheName\",\n      });\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: \"Plugin\",\n        funcName: \"cacheDidUpdate\",\n        paramName: \"request\",\n      });\n    }\n\n    const cacheExpiration = this._getCacheExpiration(cacheName);\n    await cacheExpiration.updateTimestamp(request.url);\n    await cacheExpiration.expireEntries();\n  }\n\n  /**\n   * Deletes the underlying `Cache` instance associated with this instance and the metadata\n   * from IndexedDB used to keep track of expiration details for each `Cache` instance.\n   *\n   * When using cache expiration, calling this method is preferable to calling\n   * `caches.delete()` directly, since this will ensure that the IndexedDB\n   * metadata is also cleanly removed and that open IndexedDB instances are deleted.\n   *\n   * Note that if you're *not* using cache expiration for a given cache, calling\n   * `caches.delete()` and passing in the cache's name should be sufficient.\n   * There is no Serwist-specific method needed for cleanup in that case.\n   */\n  async deleteCacheAndMetadata(): Promise<void> {\n    // Do this one at a time instead of all at once via `Promise.all()` to\n    // reduce the chance of inconsistency if a promise rejects.\n    for (const [cacheName, cacheExpiration] of this._cacheExpirations) {\n      await self.caches.delete(cacheName);\n      await cacheExpiration.delete();\n    }\n\n    // Reset this._cacheExpirations to its initial state.\n    this._cacheExpirations = new Map();\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nexport const QUEUE_NAME = \"serwist-google-analytics\";\nexport const MAX_RETENTION_TIME = 60 * 48; // Two days in minutes\nexport const GOOGLE_ANALYTICS_HOST = \"www.google-analytics.com\";\nexport const GTM_HOST = \"www.googletagmanager.com\";\nexport const ANALYTICS_JS_PATH = \"/analytics.js\";\nexport const GTAG_JS_PATH = \"/gtag/js\";\nexport const GTM_JS_PATH = \"/gtm.js\";\nexport const COLLECT_DEFAULT_PATH = \"/collect\";\n\n// This RegExp matches all known Measurement Protocol single-hit collect\n// endpoints. Most of the time the default path (/collect) is used, but\n// occasionally an experimental endpoint is used when testing new features,\n// (e.g. /r/collect or /j/collect)\nexport const COLLECT_PATHS_REGEX = /^\\/(\\w+\\/)?collect/;\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { NetworkFirst } from \"../../lib/strategies/NetworkFirst.js\";\nimport { NetworkOnly } from \"../../lib/strategies/NetworkOnly.js\";\nimport { Route } from \"../../Route.js\";\nimport type { Serwist } from \"../../Serwist.js\";\nimport type { RouteMatchCallbackOptions } from \"../../types.js\";\nimport { cacheNames as privateCacheNames } from \"../../utils/cacheNames.js\";\nimport { getFriendlyURL } from \"../../utils/getFriendlyURL.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { BackgroundSyncPlugin } from \"../backgroundSync/BackgroundSyncPlugin.js\";\nimport type { BackgroundSyncQueue, BackgroundSyncQueueEntry } from \"../backgroundSync/BackgroundSyncQueue.js\";\nimport {\n  ANALYTICS_JS_PATH,\n  COLLECT_PATHS_REGEX,\n  GOOGLE_ANALYTICS_HOST,\n  GTAG_JS_PATH,\n  GTM_HOST,\n  GTM_JS_PATH,\n  MAX_RETENTION_TIME,\n  QUEUE_NAME,\n} from \"./constants.js\";\n\nexport interface GoogleAnalyticsInitializeOptions {\n  serwist: Serwist;\n  /**\n   * The cache name to store and retrieve analytics.js. Defaults to Serwist's default cache names.\n   */\n  cacheName?: string;\n  /**\n   * [Measurement Protocol parameters](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters),\n   * expressed as key/value pairs, to be added to replayed Google Analytics\n   * requests. This can be used to, e.g., set a custom dimension indicating\n   * that the request was replayed.\n   */\n  parameterOverrides?: { [paramName: string]: string };\n  /**\n   * A function that allows you to modify the hit parameters prior to replaying\n   * the hit. The function is invoked with the original hit's URLSearchParams\n   * object as its only argument.\n   */\n  hitFilter?: (params: URLSearchParams) => void;\n}\n\n/**\n * Creates the requestWillDequeue callback to be used with the background\n * sync plugin. The callback takes the failed request and adds the\n * `qt` param based on the current time, as well as applies any other\n * user-defined hit modifications.\n *\n * @param config\n * @returns The requestWillDequeue callback function.\n * @private\n */\nconst createOnSyncCallback = (config: Pick<GoogleAnalyticsInitializeOptions, \"parameterOverrides\" | \"hitFilter\">) => {\n  return async ({ queue }: { queue: BackgroundSyncQueue }) => {\n    let entry: BackgroundSyncQueueEntry | undefined;\n    while ((entry = await queue.shiftRequest())) {\n      const { request, timestamp } = entry;\n      const url = new URL(request.url);\n\n      try {\n        // Measurement protocol requests can set their payload parameters in\n        // either the URL query string (for GET requests) or the POST body.\n        const params = request.method === \"POST\" ? new URLSearchParams(await request.clone().text()) : url.searchParams;\n\n        // Calculate the qt param, accounting for the fact that an existing\n        // qt param may be present and should be updated rather than replaced.\n        const originalHitTime = timestamp! - (Number(params.get(\"qt\")) || 0);\n        const queueTime = Date.now() - originalHitTime;\n\n        // Set the qt param prior to applying hitFilter or parameterOverrides.\n        params.set(\"qt\", String(queueTime));\n\n        // Apply `parameterOverrides`, if set.\n        if (config.parameterOverrides) {\n          for (const param of Object.keys(config.parameterOverrides)) {\n            const value = config.parameterOverrides[param];\n            params.set(param, value);\n          }\n        }\n\n        // Apply `hitFilter`, if set.\n        if (typeof config.hitFilter === \"function\") {\n          config.hitFilter.call(null, params);\n        }\n\n        // Retry the fetch. Ignore URL search params from the URL as they're\n        // now in the post body.\n        await fetch(\n          new Request(url.origin + url.pathname, {\n            body: params.toString(),\n            method: \"POST\",\n            mode: \"cors\",\n            credentials: \"omit\",\n            headers: { \"Content-Type\": \"text/plain\" },\n          }),\n        );\n\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.log(`Request for '${getFriendlyURL(url.href)}' has been replayed`);\n        }\n      } catch (err) {\n        await queue.unshiftRequest(entry);\n\n        if (process.env.NODE_ENV !== \"production\") {\n          logger.log(`Request for '${getFriendlyURL(url.href)}' failed to replay, putting it back in the queue.`);\n        }\n        throw err;\n      }\n    }\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.log(\"All Google Analytics request successfully replayed; \" + \"the queue is now empty!\");\n    }\n  };\n};\n\n/**\n * Creates GET and POST routes to catch failed Measurement Protocol hits.\n *\n * @param bgSyncPlugin\n * @returns The created routes.\n * @private\n */\nconst createCollectRoutes = (bgSyncPlugin: BackgroundSyncPlugin) => {\n  const match = ({ url }: RouteMatchCallbackOptions) => url.hostname === GOOGLE_ANALYTICS_HOST && COLLECT_PATHS_REGEX.test(url.pathname);\n\n  const handler = new NetworkOnly({\n    plugins: [bgSyncPlugin],\n  });\n\n  return [new Route(match, handler, \"GET\"), new Route(match, handler, \"POST\")];\n};\n\n/**\n * Creates a route with a network first strategy for the analytics.js script.\n *\n * @param cacheName\n * @returns The created route.\n * @private\n */\nconst createAnalyticsJsRoute = (cacheName: string) => {\n  const match = ({ url }: RouteMatchCallbackOptions) => url.hostname === GOOGLE_ANALYTICS_HOST && url.pathname === ANALYTICS_JS_PATH;\n\n  const handler = new NetworkFirst({ cacheName });\n\n  return new Route(match, handler, \"GET\");\n};\n\n/**\n * Creates a route with a network first strategy for the gtag.js script.\n *\n * @param cacheName\n * @returns The created route.\n * @private\n */\nconst createGtagJsRoute = (cacheName: string) => {\n  const match = ({ url }: RouteMatchCallbackOptions) => url.hostname === GTM_HOST && url.pathname === GTAG_JS_PATH;\n\n  const handler = new NetworkFirst({ cacheName });\n\n  return new Route(match, handler, \"GET\");\n};\n\n/**\n * Creates a route with a network first strategy for the gtm.js script.\n *\n * @param cacheName\n * @returns The created route.\n * @private\n */\nconst createGtmJsRoute = (cacheName: string) => {\n  const match = ({ url }: RouteMatchCallbackOptions) => url.hostname === GTM_HOST && url.pathname === GTM_JS_PATH;\n\n  const handler = new NetworkFirst({ cacheName });\n\n  return new Route(match, handler, \"GET\");\n};\n\n/**\n * Initialize Serwist's offline Google Analytics v3 support.\n *\n * @param options\n */\nexport const initializeGoogleAnalytics = ({ serwist, cacheName, ...options }: GoogleAnalyticsInitializeOptions): void => {\n  const resolvedCacheName = privateCacheNames.getGoogleAnalyticsName(cacheName);\n\n  const bgSyncPlugin = new BackgroundSyncPlugin(QUEUE_NAME, {\n    maxRetentionTime: MAX_RETENTION_TIME,\n    onSync: createOnSyncCallback(options),\n  });\n\n  const routes = [\n    createGtmJsRoute(resolvedCacheName),\n    createAnalyticsJsRoute(resolvedCacheName),\n    createGtagJsRoute(resolvedCacheName),\n    ...createCollectRoutes(bgSyncPlugin),\n  ];\n\n  for (const route of routes) {\n    serwist.registerRoute(route);\n  }\n};\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { Serwist } from \"../../Serwist.js\";\nimport type { HandlerDidErrorCallbackParam, SerwistPlugin } from \"../../types.js\";\n\nexport interface PrecacheFallbackEntry {\n  /**\n   * A precached URL to be used as a fallback.\n   */\n  url: string;\n  /**\n   * A function that checks whether the fallback entry can be used\n   * for a request.\n   */\n  matcher: (param: HandlerDidErrorCallbackParam) => boolean;\n}\n\nexport interface PrecacheFallbackPluginOptions {\n  /**\n   * Precached URLs to be used as the fallback\n   * if the associated strategy can't generate a response.\n   */\n  fallbackUrls: (string | PrecacheFallbackEntry)[];\n  /**\n   * A {@linkcode Serwist} instance.\n   */\n  serwist: Serwist;\n}\n\n/**\n * Allows you to specify offline fallbacks to be used when a given strategy\n * is unable to generate a response.\n *\n * It does this by intercepting the `handlerDidError` plugin callback\n * and returning a precached response, taking the expected revision parameter\n * into account automatically.\n */\nexport class PrecacheFallbackPlugin implements SerwistPlugin {\n  private readonly _fallbackUrls: (string | PrecacheFallbackEntry)[];\n  private readonly _serwist: Serwist;\n\n  /**\n   * Constructs a new instance with the associated `fallbackUrls`.\n   *\n   * @param config\n   */\n  constructor({ fallbackUrls, serwist }: PrecacheFallbackPluginOptions) {\n    this._fallbackUrls = fallbackUrls;\n    this._serwist = serwist;\n  }\n\n  /**\n   * @returns The precache response for one of the fallback URLs, or `undefined` if\n   * nothing satisfies the conditions.\n   * @private\n   */\n  async handlerDidError(param: HandlerDidErrorCallbackParam) {\n    for (const fallback of this._fallbackUrls) {\n      if (typeof fallback === \"string\") {\n        const fallbackResponse = await this._serwist.matchPrecache(fallback);\n        if (fallbackResponse !== undefined) {\n          return fallbackResponse;\n        }\n      } else if (fallback.matcher(param)) {\n        const fallbackResponse = await this._serwist.matchPrecache(fallback.url);\n        if (fallbackResponse !== undefined) {\n          return fallbackResponse;\n        }\n      }\n    }\n    return undefined;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../../utils/assert.js\";\nimport { SerwistError } from \"../../../utils/SerwistError.js\";\n\n/**\n * @param blob A source blob.\n * @param start The offset to use as the start of the\n * slice.\n * @param end The offset to use as the end of the slice.\n * @returns An object with `start` and `end` properties, reflecting\n * the effective boundaries to use given the size of the blob.\n * @private\n */\nexport const calculateEffectiveBoundaries = (blob: Blob, start?: number, end?: number): { start: number; end: number } => {\n  if (process.env.NODE_ENV !== \"production\") {\n    assert!.isInstance(blob, Blob, {\n      moduleName: \"@serwist/range-requests\",\n      funcName: \"calculateEffectiveBoundaries\",\n      paramName: \"blob\",\n    });\n  }\n\n  const blobSize = blob.size;\n\n  if ((end && end > blobSize) || (start && start < 0)) {\n    throw new SerwistError(\"range-not-satisfiable\", {\n      size: blobSize,\n      end,\n      start,\n    });\n  }\n\n  let effectiveStart: number;\n  let effectiveEnd: number;\n\n  if (start !== undefined && end !== undefined) {\n    effectiveStart = start;\n    // Range values are inclusive, so add 1 to the value.\n    effectiveEnd = end + 1;\n  } else if (start !== undefined && end === undefined) {\n    effectiveStart = start;\n    effectiveEnd = blobSize;\n  } else if (end !== undefined && start === undefined) {\n    effectiveStart = blobSize - end;\n    effectiveEnd = blobSize;\n  }\n\n  return {\n    start: effectiveStart!,\n    end: effectiveEnd!,\n  };\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../../utils/assert.js\";\nimport { SerwistError } from \"../../../utils/SerwistError.js\";\n\n/**\n * @param rangeHeader A `Range` header value.\n * @returns An object with `start` and `end` properties, reflecting\n * the parsed value of the `Range` header. If either the `start` or `end` are\n * omitted, then `null` will be returned.\n * @private\n */\nexport const parseRangeHeader = (\n  rangeHeader: string,\n): {\n  start?: number;\n  end?: number;\n} => {\n  if (process.env.NODE_ENV !== \"production\") {\n    assert!.isType(rangeHeader, \"string\", {\n      moduleName: \"@serwist/range-requests\",\n      funcName: \"parseRangeHeader\",\n      paramName: \"rangeHeader\",\n    });\n  }\n\n  const normalizedRangeHeader = rangeHeader.trim().toLowerCase();\n  if (!normalizedRangeHeader.startsWith(\"bytes=\")) {\n    throw new SerwistError(\"unit-must-be-bytes\", { normalizedRangeHeader });\n  }\n\n  // Specifying multiple ranges separate by commas is valid syntax, but this\n  // library only attempts to handle a single, contiguous sequence of bytes.\n  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range#Syntax\n  if (normalizedRangeHeader.includes(\",\")) {\n    throw new SerwistError(\"single-range-only\", { normalizedRangeHeader });\n  }\n\n  const rangeParts = /(\\d*)-(\\d*)/.exec(normalizedRangeHeader);\n  // We need either at least one of the start or end values.\n  if (!rangeParts || !(rangeParts[1] || rangeParts[2])) {\n    throw new SerwistError(\"invalid-range-values\", { normalizedRangeHeader });\n  }\n\n  return {\n    start: rangeParts[1] === \"\" ? undefined : Number(rangeParts[1]),\n    end: rangeParts[2] === \"\" ? undefined : Number(rangeParts[2]),\n  };\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { calculateEffectiveBoundaries } from \"./utils/calculateEffectiveBoundaries.js\";\nimport { parseRangeHeader } from \"./utils/parseRangeHeader.js\";\n\n/**\n * Given a request and a response, this will return a\n * promise that resolves to a partial response.\n *\n * If the original response already contains partial content (i.e. it has\n * a status of 206), then this assumes it already fulfills the `Range`\n * requirements, and will return it as-is.\n *\n * @param request A request, which should contain a `Range`\n * header.\n * @param originalResponse A response.\n * @returns Either a `206 Partial Content` response, with\n * the response body set to the slice of content specified by the request's\n * `Range` header, or a `416 Range Not Satisfiable` response if the\n * conditions of the `Range` header can't be met.\n */\nexport const createPartialResponse = async (request: Request, originalResponse: Response): Promise<Response> => {\n  try {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"@serwist/range-requests\",\n        funcName: \"createPartialResponse\",\n        paramName: \"request\",\n      });\n\n      assert!.isInstance(originalResponse, Response, {\n        moduleName: \"@serwist/range-requests\",\n        funcName: \"createPartialResponse\",\n        paramName: \"originalResponse\",\n      });\n    }\n\n    if (originalResponse.status === 206) {\n      // If we already have a 206, then just pass it through as-is;\n      // see https://github.com/GoogleChrome/workbox/issues/1720\n      return originalResponse;\n    }\n\n    const rangeHeader = request.headers.get(\"range\");\n    if (!rangeHeader) {\n      throw new SerwistError(\"no-range-header\");\n    }\n\n    const boundaries = parseRangeHeader(rangeHeader);\n    const originalBlob = await originalResponse.blob();\n\n    const effectiveBoundaries = calculateEffectiveBoundaries(originalBlob, boundaries.start, boundaries.end);\n\n    const slicedBlob = originalBlob.slice(effectiveBoundaries.start, effectiveBoundaries.end);\n    const slicedBlobSize = slicedBlob.size;\n\n    const slicedResponse = new Response(slicedBlob, {\n      // Status code 206 is for a Partial Content response.\n      // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/206\n      status: 206,\n      statusText: \"Partial Content\",\n      headers: originalResponse.headers,\n    });\n\n    slicedResponse.headers.set(\"Content-Length\", String(slicedBlobSize));\n    slicedResponse.headers.set(\"Content-Range\", `bytes ${effectiveBoundaries.start}-${effectiveBoundaries.end - 1}/` + `${originalBlob.size}`);\n\n    return slicedResponse;\n  } catch (error) {\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.warn(\"Unable to construct a partial response; returning a \" + \"416 Range Not Satisfiable response instead.\");\n      logger.groupCollapsed(\"View details here.\");\n      logger.log(error);\n      logger.log(request);\n      logger.log(originalResponse);\n      logger.groupEnd();\n    }\n\n    return new Response(\"\", {\n      status: 416,\n      statusText: \"Range Not Satisfiable\",\n    });\n  }\n};\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { SerwistPlugin } from \"../../types.js\";\nimport { createPartialResponse } from \"./createPartialResponse.js\";\n\n/**\n * Makes it easy for a request with a `Range` header to be fulfilled by a cached response.\n *\n * It does this by intercepting the `cachedResponseWillBeUsed` plugin callback\n * and returning the appropriate subset of the cached response body.\n */\nexport class RangeRequestsPlugin implements SerwistPlugin {\n  /**\n   * @param options\n   * @returns If request contains a `Range` header, then a\n   * partial response whose body is a subset of `cachedResponse` is\n   * returned. Otherwise, `cachedResponse` is returned as-is.\n   * @private\n   */\n  cachedResponseWillBeUsed: SerwistPlugin[\"cachedResponseWillBeUsed\"] = async ({ request, cachedResponse }) => {\n    // Only return a sliced response if there's something valid in the cache,\n    // and there's a Range: header in the request.\n    if (cachedResponse && request.headers.has(\"range\")) {\n      return await createPartialResponse(request, cachedResponse);\n    }\n\n    // If there was no Range: header, or if cachedResponse wasn't valid, just\n    // pass it through as-is.\n    return cachedResponse;\n  };\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { Strategy } from \"./Strategy.js\";\nimport type { StrategyHandler } from \"./StrategyHandler.js\";\nimport { messages } from \"./utils/messages.js\";\n\n/**\n * An implementation of the [cache first](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#cache_first_falling_back_to_network)\n * request strategy.\n *\n * A cache first strategy is useful for assets that have been revisioned,\n * such as URLs like \"/styles/example.a8f5f1.css\", since they\n * can be cached for long periods of time.\n *\n * If the network request fails, and there is no cache match, this will throw\n * a {@linkcode SerwistError} exception.\n */\nexport class CacheFirst extends Strategy {\n  /**\n   * @private\n   * @param request A request to run this strategy for.\n   * @param handler The event that triggered the request.\n   * @returns\n   */\n  async _handle(request: Request, handler: StrategyHandler): Promise<Response> {\n    const logs = [];\n\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: this.constructor.name,\n        funcName: \"makeRequest\",\n        paramName: \"request\",\n      });\n    }\n\n    let response = await handler.cacheMatch(request);\n\n    let error: Error | undefined;\n    if (!response) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logs.push(`No response found in the '${this.cacheName}' cache. Will respond with a network request.`);\n      }\n      try {\n        response = await handler.fetchAndCachePut(request);\n      } catch (err) {\n        if (err instanceof Error) {\n          error = err;\n        }\n      }\n\n      if (process.env.NODE_ENV !== \"production\") {\n        if (response) {\n          logs.push(\"Got response from network.\");\n        } else {\n          logs.push(\"Unable to get a response from the network.\");\n        }\n      }\n    } else {\n      if (process.env.NODE_ENV !== \"production\") {\n        logs.push(`Found a cached response in the '${this.cacheName}' cache.`);\n      }\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));\n      for (const log of logs) {\n        logger.log(log);\n      }\n      messages.printFinalResponse(response);\n      logger.groupEnd();\n    }\n\n    if (!response) {\n      throw new SerwistError(\"no-response\", { url: request.url, error });\n    }\n    return response;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { Strategy } from \"./Strategy.js\";\nimport type { StrategyHandler } from \"./StrategyHandler.js\";\nimport { messages } from \"./utils/messages.js\";\n\n/**\n * An implementation of the [cache only](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#cache_only)\n * request strategy.\n *\n * This class is useful if you already have your own precaching step.\n *\n * If there is no cache match, this will throw a {@linkcode SerwistError} exception.\n */\nexport class CacheOnly extends Strategy {\n  /**\n   * @private\n   * @param request A request to run this strategy for.\n   * @param handler The event that triggered the request.\n   * @returns\n   */\n  async _handle(request: Request, handler: StrategyHandler): Promise<Response> {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: this.constructor.name,\n        funcName: \"makeRequest\",\n        paramName: \"request\",\n      });\n    }\n\n    const response = await handler.cacheMatch(request);\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));\n      if (response) {\n        logger.log(`Found a cached response in the '${this.cacheName}' cache.`);\n        messages.printFinalResponse(response);\n      } else {\n        logger.log(`No response found in the '${this.cacheName}' cache.`);\n      }\n      logger.groupEnd();\n    }\n\n    if (!response) {\n      throw new SerwistError(\"no-response\", { url: request.url });\n    }\n    return response;\n  }\n}\n", "/*\n  Copyright 2018 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { assert } from \"../../utils/assert.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { SerwistError } from \"../../utils/SerwistError.js\";\nimport { cacheOkAndOpaquePlugin } from \"./plugins/cacheOkAndOpaquePlugin.js\";\nimport type { StrategyOptions } from \"./Strategy.js\";\nimport { Strategy } from \"./Strategy.js\";\nimport type { StrategyHandler } from \"./StrategyHandler.js\";\nimport { messages } from \"./utils/messages.js\";\n\n/**\n * An implementation of the\n * [stale-while-revalidate](https://developer.chrome.com/docs/workbox/caching-strategies-overview/#stale_while_revalidate)\n * request strategy.\n *\n * Resources are requested from both the cache and the network in parallel.\n * The strategy will respond with the cached version if available, otherwise\n * wait for the network response. The cache is updated with the network response\n * with each successful request.\n *\n * By default, this strategy will cache responses with a 200 status code as\n * well as [opaque responses](https://developer.chrome.com/docs/workbox/caching-resources-during-runtime/#opaque-responses).\n * Opaque responses are cross-origin requests where the response doesn't\n * support [CORS](https://enable-cors.org/).\n *\n * If the network request fails, and there is no cache match, this will throw\n * a {@linkcode SerwistError} exception.\n */\nexport class StaleWhileRevalidate extends Strategy {\n  /**\n   * @param options\n   */\n  constructor(options: StrategyOptions = {}) {\n    super(options);\n\n    // If this instance contains no plugins with a 'cacheWillUpdate' callback,\n    // prepend the `cacheOkAndOpaquePlugin` plugin to the plugins list.\n    if (!this.plugins.some((p) => \"cacheWillUpdate\" in p)) {\n      this.plugins.unshift(cacheOkAndOpaquePlugin);\n    }\n  }\n\n  /**\n   * @private\n   * @param request A request to run this strategy for.\n   * @param handler The event that triggered the request.\n   * @returns\n   */\n  async _handle(request: Request, handler: StrategyHandler): Promise<Response> {\n    const logs = [];\n\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: this.constructor.name,\n        funcName: \"handle\",\n        paramName: \"request\",\n      });\n    }\n\n    const fetchAndCachePromise = handler.fetchAndCachePut(request).catch(() => {\n      // Swallow this error because a 'no-response' error will be thrown in\n      // main handler return flow. This will be in the `waitUntil()` flow.\n    });\n    void handler.waitUntil(fetchAndCachePromise);\n\n    let response = await handler.cacheMatch(request);\n\n    let error: Error | undefined;\n    if (response) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logs.push(`Found a cached response in the '${this.cacheName}' cache. Will update with the network response in the background.`);\n      }\n    } else {\n      if (process.env.NODE_ENV !== \"production\") {\n        logs.push(`No response found in the '${this.cacheName}' cache. Will wait for the network response.`);\n      }\n      try {\n        // NOTE(philipwalton): Really annoying that we have to type cast here.\n        // https://github.com/microsoft/TypeScript/issues/20006\n        response = (await fetchAndCachePromise) as Response | undefined;\n      } catch (err) {\n        if (err instanceof Error) {\n          error = err;\n        }\n      }\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      logger.groupCollapsed(messages.strategyStart(this.constructor.name, request));\n      for (const log of logs) {\n        logger.log(log);\n      }\n      messages.printFinalResponse(response);\n      logger.groupEnd();\n    }\n\n    if (!response) {\n      throw new SerwistError(\"no-response\", { url: request.url, error });\n    }\n    return response;\n  }\n}\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport { Route } from \"./Route.js\";\nimport type { Serwist } from \"./Serwist.js\";\nimport type { PrecacheRouteOptions, RouteMatchCallback, RouteMatchCallbackOptions } from \"./types.js\";\nimport { generateURLVariations } from \"./utils/generateURLVariations.js\";\nimport { getFriendlyURL } from \"./utils/getFriendlyURL.js\";\nimport { logger } from \"./utils/logger.js\";\n\n/**\n * A subclass of {@linkcode Route} that takes a {@linkcode Serwist} instance and uses it to match\n * incoming requests and handle fetching responses from the precache.\n */\nexport class PrecacheRoute extends Route {\n  /**\n   * @param serwist A {@linkcode Serwist} instance.\n   * @param options Options to control how requests are matched\n   * against the list of precached URLs.\n   */\n  constructor(serwist: Serwist, options?: PrecacheRouteOptions) {\n    const match: RouteMatchCallback = ({ request }: RouteMatchCallbackOptions) => {\n      const urlsToCacheKeys = serwist.getUrlsToPrecacheKeys();\n      for (const possibleURL of generateURLVariations(request.url, options)) {\n        const cacheKey = urlsToCacheKeys.get(possibleURL);\n        if (cacheKey) {\n          const integrity = serwist.getIntegrityForPrecacheKey(cacheKey);\n          return { cacheKey, integrity };\n        }\n      }\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.debug(`Precaching did not find a match for ${getFriendlyURL(request.url)}.`);\n      }\n      return;\n    };\n\n    super(match, serwist.precacheStrategy);\n  }\n}\n", "/*\n  Copyright 2020 Google LLC\n\n  Use of this source code is governed by an MIT-style\n  license that can be found in the LICENSE file or at\n  https://opensource.org/licenses/MIT.\n*/\n\nimport type { Serwist } from \"../Serwist.js\";\nimport type { SerwistPlugin, SerwistPluginCallbackParam } from \"../types.js\";\n\n/**\n * A plugin, designed to be used with PrecacheController, to translate URLs into\n * the corresponding cache key, based on the current revision info.\n *\n * @private\n */\nexport class PrecacheCacheKeyPlugin implements SerwistPlugin {\n  private readonly _precacheController: Serwist;\n\n  constructor({ precacheController }: { precacheController: Serwist }) {\n    this._precacheController = precacheController;\n  }\n\n  cacheKeyWillBeUsed: SerwistPlugin[\"cacheKeyWillBeUsed\"] = async ({ request, params }: SerwistPluginCallbackParam[\"cacheKeyWillBeUsed\"]) => {\n    // Params is type any, can't change right now.\n    const cacheKey = params?.cacheKey || this._precacheController.getPrecacheKeyForUrl(request.url);\n\n    return cacheKey ? new Request(cacheKey, { headers: request.headers }) : request;\n  };\n}\n", "import { privateCacheNames } from \"../index.internal.js\";\nimport type { PrecacheStrategyOptions } from \"../lib/strategies/PrecacheStrategy.js\";\nimport type { Serwist } from \"../Serwist.js\";\nimport type { PrecacheOptions, PrecacheRouteOptions } from \"../types.js\";\nimport { PrecacheCacheKeyPlugin } from \"./PrecacheCacheKeyPlugin.js\";\n\nexport const parsePrecacheOptions = (serwist: Serwist, precacheOptions: PrecacheOptions = {}) => {\n  const {\n    cacheName: precacheCacheName,\n    plugins: precachePlugins = [],\n    fetchOptions: precacheFetchOptions,\n    matchOptions: precacheMatchOptions,\n    fallbackToNetwork: precacheFallbackToNetwork,\n    directoryIndex: precacheDirectoryIndex,\n    ignoreURLParametersMatching: precacheIgnoreUrls,\n    cleanURLs: precacheCleanUrls,\n    urlManipulation: precacheUrlManipulation,\n    cleanupOutdatedCaches,\n    concurrency = 10,\n    navigateFallback,\n    navigateFallbackAllowlist,\n    navigateFallbackDenylist,\n  } = precacheOptions ?? {};\n\n  return {\n    precacheStrategyOptions: {\n      cacheName: privateCacheNames.getPrecacheName(precacheCacheName),\n      plugins: [...precachePlugins, new PrecacheCacheKeyPlugin({ precacheController: serwist })],\n      fetchOptions: precacheFetchOptions,\n      matchOptions: precacheMatchOptions,\n      fallbackToNetwork: precacheFallbackToNetwork,\n    } satisfies PrecacheStrategyOptions,\n    precacheRouteOptions: {\n      directoryIndex: precacheDirectoryIndex,\n      ignoreURLParametersMatching: precacheIgnoreUrls,\n      cleanURLs: precacheCleanUrls,\n      urlManipulation: precacheUrlManipulation,\n    } satisfies PrecacheRouteOptions,\n    precacheMiscOptions: {\n      cleanupOutdatedCaches,\n      concurrency,\n      navigateFallback,\n      navigateFallbackAllowlist,\n      navigateFallbackDenylist,\n    },\n  };\n};\n", "import { parallel } from \"@serwist/utils\";\nimport { defaultMethod, type HTTPMethod } from \"./constants.js\";\nimport { disableDevLogs as disableDevLogsImpl } from \"./disableDevLogs.js\";\nimport { type GoogleAnalyticsInitializeOptions, initializeGoogleAnalytics } from \"./lib/googleAnalytics/initializeGoogleAnalytics.js\";\nimport { type PrecacheFallbackEntry, PrecacheFallbackPlugin } from \"./lib/precaching/PrecacheFallbackPlugin.js\";\nimport { PrecacheStrategy } from \"./lib/strategies/PrecacheStrategy.js\";\nimport { Strategy } from \"./lib/strategies/Strategy.js\";\nimport { NavigationRoute } from \"./NavigationRoute.js\";\nimport { enableNavigationPreload } from \"./navigationPreload.js\";\nimport { PrecacheRoute } from \"./PrecacheRoute.js\";\nimport type { Route } from \"./Route.js\";\nimport { setCacheNameDetails } from \"./setCacheNameDetails.js\";\nimport type {\n  CleanupResult,\n  InstallEvent,\n  InstallResult,\n  PrecacheEntry,\n  PrecacheOptions,\n  RequestRule,\n  RouteHandler,\n  RouteHandlerCallback,\n  RouteHandlerCallbackOptions,\n  RouteHandlerObject,\n  RouteMatchCallback,\n  RouteMatchCallbackOptions,\n  RuntimeCaching,\n} from \"./types.js\";\nimport { assert } from \"./utils/assert.js\";\nimport { cleanupOutdatedCaches as cleanupOutdatedCachesImpl } from \"./utils/cleanupOutdatedCaches.js\";\nimport { clientsClaim as clientsClaimImpl } from \"./utils/clientsClaim.js\";\nimport { createCacheKey } from \"./utils/createCacheKey.js\";\nimport { getFriendlyURL } from \"./utils/getFriendlyURL.js\";\nimport { logger } from \"./utils/logger.js\";\nimport { normalizeHandler } from \"./utils/normalizeHandler.js\";\nimport { PrecacheInstallReportPlugin } from \"./utils/PrecacheInstallReportPlugin.js\";\nimport { parsePrecacheOptions } from \"./utils/parsePrecacheOptions.js\";\nimport { parseRoute } from \"./utils/parseRoute.js\";\nimport { printCleanupDetails } from \"./utils/printCleanupDetails.js\";\nimport { printInstallDetails } from \"./utils/printInstallDetails.js\";\nimport { SerwistError } from \"./utils/SerwistError.js\";\nimport { waitUntil } from \"./utils/waitUntil.js\";\n\ndeclare const self: ServiceWorkerGlobalScope;\n\nexport interface FallbackEntry extends PrecacheFallbackEntry {}\n\nexport interface FallbacksOptions {\n  /**\n   * A list of fallback entries.\n   */\n  entries: FallbackEntry[];\n}\n\nexport interface SerwistOptions {\n  /**\n   * A list of URLs that should be cached.\n   */\n  precacheEntries?: (PrecacheEntry | string)[];\n  /**\n   * Options to customize how Serwist precaches the URLs in the precache list.\n   */\n  precacheOptions?: PrecacheOptions;\n  /**\n   * Forces the waiting service worker to become the active one.\n   *\n   * @see https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/skipWaiting\n   */\n  skipWaiting?: boolean;\n  /**\n   * Imports external scripts. They are executed in the order they\n   * are passed.\n   *\n   * @see https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts\n   */\n  importScripts?: string[];\n  /**\n   * Enables navigation preloading if it is supported.\n   *\n   * @see https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/navigationPreload\n   */\n  navigationPreload?: boolean;\n  /**\n   * Modifies the prefix of the default cache names used by Serwist packages.\n   */\n  cacheId?: string | undefined;\n  /**\n   * Claims any currently available clients once the service worker\n   * becomes active. This is normally used in conjunction with `skipWaiting()`.\n   *\n   * @default false\n   */\n  clientsClaim?: boolean;\n  /**\n   * A list of caching strategies.\n   */\n  runtimeCaching?: RuntimeCaching[];\n  /**\n   * Request rules that define how certain resources should be fetched\n   * before the service worker starts up.\n   *\n   * @see https://developer.mozilla.org/en-US/docs/Web/API/InstallEvent/addRoutes\n   * @experimental\n   */\n  requestRules?: RequestRule | RequestRule[];\n  /**\n   * Your configuration for {@linkcode initializeGoogleAnalytics}. This plugin is\n   * only initialized when this option is not `undefined` or `false`.\n   */\n  offlineAnalyticsConfig?: Omit<GoogleAnalyticsInitializeOptions, \"serwist\"> | boolean;\n  /**\n   * Disables Serwist's logging in development mode.\n   *\n   * @default false\n   */\n  disableDevLogs?: boolean;\n  /**\n   * Precaches routes so that they can be used as a fallback when\n   * a {@linkcode Strategy} fails to generate a response.\n   *\n   * Note: This option mutates `runtimeCaching`. It also expects the URLs\n   * defined in `entries` to have been precached beforehand.\n   */\n  fallbacks?: FallbacksOptions;\n}\n\ntype RequestArgs = string | [string, RequestInit?];\n\ninterface CacheURLsMessageData {\n  type: string;\n  payload: {\n    urlsToCache: RequestArgs[];\n  };\n}\n\n/**\n * A class that helps bootstrap the service worker.\n *\n * @see https://serwist.pages.dev/docs/serwist/core/serwist\n */\nexport class Serwist {\n  private readonly _urlsToCacheKeys: Map<string, string> = new Map();\n  private readonly _urlsToCacheModes: Map<string, \"reload\" | \"default\" | \"no-store\" | \"no-cache\" | \"force-cache\" | \"only-if-cached\"> = new Map();\n  private readonly _cacheKeysToIntegrities: Map<string, string> = new Map();\n  private _concurrentPrecaching: number;\n  private readonly _precacheStrategy: Strategy;\n  private readonly _routes: Map<HTTPMethod, Route[]>;\n  private readonly _defaultHandlerMap: Map<HTTPMethod, RouteHandlerObject>;\n  private _catchHandler?: RouteHandlerObject;\n  private _requestRules?: RequestRule | RequestRule[];\n\n  constructor({\n    precacheEntries,\n    precacheOptions,\n    skipWaiting = false,\n    importScripts,\n    navigationPreload = false,\n    cacheId,\n    clientsClaim = false,\n    runtimeCaching,\n    offlineAnalyticsConfig,\n    disableDevLogs = false,\n    fallbacks,\n    requestRules,\n  }: SerwistOptions = {}) {\n    const { precacheStrategyOptions, precacheRouteOptions, precacheMiscOptions } = parsePrecacheOptions(this, precacheOptions);\n\n    this._concurrentPrecaching = precacheMiscOptions.concurrency;\n    this._precacheStrategy = new PrecacheStrategy(precacheStrategyOptions);\n    this._routes = new Map();\n    this._defaultHandlerMap = new Map();\n    this._requestRules = requestRules;\n\n    this.handleInstall = this.handleInstall.bind(this);\n    this.handleActivate = this.handleActivate.bind(this);\n    this.handleFetch = this.handleFetch.bind(this);\n    this.handleCache = this.handleCache.bind(this);\n\n    if (!!importScripts && importScripts.length > 0) self.importScripts(...importScripts);\n\n    if (navigationPreload) enableNavigationPreload();\n\n    if (cacheId !== undefined) {\n      setCacheNameDetails({\n        prefix: cacheId,\n      });\n    }\n\n    if (skipWaiting) {\n      self.skipWaiting();\n    } else {\n      self.addEventListener(\"message\", (event) => {\n        if (event.data && event.data.type === \"SKIP_WAITING\") {\n          self.skipWaiting();\n        }\n      });\n    }\n\n    if (clientsClaim) clientsClaimImpl();\n\n    if (!!precacheEntries && precacheEntries.length > 0) {\n      this.addToPrecacheList(precacheEntries);\n    }\n\n    if (precacheMiscOptions.cleanupOutdatedCaches) {\n      cleanupOutdatedCachesImpl(precacheStrategyOptions.cacheName);\n    }\n\n    this.registerRoute(new PrecacheRoute(this, precacheRouteOptions));\n\n    if (precacheMiscOptions.navigateFallback) {\n      this.registerRoute(\n        new NavigationRoute(this.createHandlerBoundToUrl(precacheMiscOptions.navigateFallback), {\n          allowlist: precacheMiscOptions.navigateFallbackAllowlist,\n          denylist: precacheMiscOptions.navigateFallbackDenylist,\n        }),\n      );\n    }\n\n    if (offlineAnalyticsConfig !== undefined) {\n      if (typeof offlineAnalyticsConfig === \"boolean\") {\n        offlineAnalyticsConfig && initializeGoogleAnalytics({ serwist: this });\n      } else {\n        initializeGoogleAnalytics({\n          ...offlineAnalyticsConfig,\n          serwist: this,\n        });\n      }\n    }\n\n    if (runtimeCaching !== undefined) {\n      if (fallbacks !== undefined) {\n        const fallbackPlugin = new PrecacheFallbackPlugin({\n          fallbackUrls: fallbacks.entries,\n          serwist: this,\n        });\n\n        runtimeCaching.forEach((cacheEntry) => {\n          if (\n            cacheEntry.handler instanceof Strategy &&\n            // This also filters entries with `PrecacheFallbackPlugin` as it also has `handlerDidError`.\n            !cacheEntry.handler.plugins.some((plugin) => \"handlerDidError\" in plugin)\n          ) {\n            cacheEntry.handler.plugins.push(fallbackPlugin);\n          }\n        });\n      }\n      for (const entry of runtimeCaching) {\n        this.registerCapture(entry.matcher, entry.handler, entry.method);\n      }\n    }\n\n    if (disableDevLogs) disableDevLogsImpl();\n  }\n\n  /**\n   * The strategy used to precache assets and respond to `fetch` events.\n   */\n  get precacheStrategy(): Strategy {\n    return this._precacheStrategy;\n  }\n  /**\n   * A `Map` of HTTP method name (`'GET'`, etc.) to an array of all corresponding registered {@linkcode Route}\n   * instances.\n   */\n  get routes(): Map<HTTPMethod, Route[]> {\n    return this._routes;\n  }\n\n  /**\n   * Adds Serwist's event listeners for you. Before calling it, add your own listeners should you need to.\n   */\n  addEventListeners() {\n    self.addEventListener(\"install\", this.handleInstall);\n    self.addEventListener(\"activate\", this.handleActivate);\n    self.addEventListener(\"fetch\", this.handleFetch);\n    self.addEventListener(\"message\", this.handleCache);\n  }\n\n  /**\n   * Adds items to the precache list, removing duplicates and ensuring the information is valid.\n   *\n   * @param entries Array of entries to precache.\n   */\n  addToPrecacheList(entries: (PrecacheEntry | string)[]): void {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isArray(entries, {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"addToCacheList\",\n        paramName: \"entries\",\n      });\n    }\n\n    const urlsToWarnAbout: string[] = [];\n    for (const entry of entries) {\n      // See https://github.com/GoogleChrome/workbox/issues/2259\n      if (typeof entry === \"string\") {\n        urlsToWarnAbout.push(entry);\n      } else if (entry && !entry.integrity && entry.revision === undefined) {\n        urlsToWarnAbout.push(entry.url);\n      }\n\n      const { cacheKey, url } = createCacheKey(entry);\n      const cacheMode = typeof entry !== \"string\" && entry.revision ? \"reload\" : \"default\";\n\n      if (this._urlsToCacheKeys.has(url) && this._urlsToCacheKeys.get(url) !== cacheKey) {\n        throw new SerwistError(\"add-to-cache-list-conflicting-entries\", {\n          firstEntry: this._urlsToCacheKeys.get(url),\n          secondEntry: cacheKey,\n        });\n      }\n\n      if (typeof entry !== \"string\" && entry.integrity) {\n        if (this._cacheKeysToIntegrities.has(cacheKey) && this._cacheKeysToIntegrities.get(cacheKey) !== entry.integrity) {\n          throw new SerwistError(\"add-to-cache-list-conflicting-integrities\", {\n            url,\n          });\n        }\n        this._cacheKeysToIntegrities.set(cacheKey, entry.integrity);\n      }\n\n      this._urlsToCacheKeys.set(url, cacheKey);\n      this._urlsToCacheModes.set(url, cacheMode);\n    }\n    if (urlsToWarnAbout.length > 0) {\n      const warningMessage = `Serwist is precaching URLs without revision info: ${urlsToWarnAbout.join(\n        \", \",\n      )}\\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;\n      if (process.env.NODE_ENV === \"production\") {\n        // Use console directly to display this warning without bloating\n        // bundle sizes by pulling in all of the logger codebase in prod.\n        console.warn(warningMessage);\n      } else {\n        logger.warn(warningMessage);\n      }\n    }\n  }\n\n  /**\n   * Precaches new and updated assets. Call this method from the service worker's\n   * `install` event.\n   *\n   * Note: this method calls `event.waitUntil()` for you, so you do not need\n   * to call it yourself in your event handlers.\n   *\n   * @param event\n   * @returns\n   */\n  handleInstall(event: InstallEvent): Promise<InstallResult> {\n    void this.registerRequestRules(event);\n\n    return waitUntil<InstallResult>(event, async () => {\n      const installReportPlugin = new PrecacheInstallReportPlugin();\n      this.precacheStrategy.plugins.push(installReportPlugin);\n\n      await parallel(this._concurrentPrecaching, Array.from(this._urlsToCacheKeys.entries()), async ([url, cacheKey]): Promise<void> => {\n        const integrity = this._cacheKeysToIntegrities.get(cacheKey);\n        const cacheMode = this._urlsToCacheModes.get(url);\n\n        const request = new Request(url, {\n          integrity,\n          cache: cacheMode,\n          credentials: \"same-origin\",\n        });\n\n        await Promise.all(\n          this.precacheStrategy.handleAll({\n            event,\n            request,\n            url: new URL(request.url),\n            params: { cacheKey },\n          }),\n        );\n      });\n\n      const { updatedURLs, notUpdatedURLs } = installReportPlugin;\n\n      if (process.env.NODE_ENV !== \"production\") {\n        printInstallDetails(updatedURLs, notUpdatedURLs);\n      }\n\n      return { updatedURLs, notUpdatedURLs };\n    });\n  }\n\n  /**\n   * Registers request rules using the experimental `InstallEvent.addRoutes()` API.\n   * These rules allow bypassing the service worker for specific requests to improve performance.\n   *\n   * @param event The event object of an `install` event handler.\n   * @throws {Error} When the route rules are invalid\n   */\n  async registerRequestRules(event: InstallEvent): Promise<void> {\n    if (!this._requestRules) {\n      return;\n    }\n\n    // Check if both the API and route rules are available\n    if (!event?.addRoutes) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.warn(\n          \"Request rules ignored as the Static Routing API is not supported in this browser. \" +\n            \"See https://caniuse.com/mdn-api_installevent_addroutes for more information.\",\n        );\n      }\n      return;\n    }\n\n    try {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.warn(\n          \"Request rules may not be supported in all browsers as the Static Routing API is experimental. \" +\n            \"This feature allows bypassing the service worker for specific requests to improve performance. \" +\n            \"See https://developer.mozilla.org/en-US/docs/Web/API/InstallEvent/addRoutes for more information.\",\n        );\n      }\n\n      await event.addRoutes(this._requestRules);\n\n      // Free up the rules object.\n      this._requestRules = undefined;\n    } catch (error) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.error(\n          `Failed to register request rules: ${error instanceof Error ? error.message : String(error)}. ` +\n            \"This may occur if the browser doesn't support the Static Routing API or if the request rules are invalid.\",\n        );\n      }\n\n      throw error;\n    }\n  }\n\n  /**\n   * Deletes assets that are no longer present in the current precache manifest.\n   * Call this method from the service worker's `activate` event.\n   *\n   * Note: this method calls `event.waitUntil()` for you, so you do not need\n   * to call it yourself in your event handlers.\n   *\n   * @param event\n   * @returns\n   */\n  handleActivate(event: ExtendableEvent): Promise<CleanupResult> {\n    return waitUntil<CleanupResult>(event, async () => {\n      const cache = await self.caches.open(this.precacheStrategy.cacheName);\n      const currentlyCachedRequests = await cache.keys();\n      const expectedCacheKeys = new Set(this._urlsToCacheKeys.values());\n\n      const deletedCacheRequests: string[] = [];\n\n      for (const request of currentlyCachedRequests) {\n        if (!expectedCacheKeys.has(request.url)) {\n          await cache.delete(request);\n          deletedCacheRequests.push(request.url);\n        }\n      }\n\n      if (process.env.NODE_ENV !== \"production\") {\n        printCleanupDetails(deletedCacheRequests);\n      }\n\n      return { deletedCacheRequests };\n    });\n  }\n\n  /**\n   * Gets a `Response` from an appropriate `Route`'s handler. Call this method\n   * from the service worker's `fetch` event.\n   * @param event\n   */\n  handleFetch(event: FetchEvent) {\n    const { request } = event;\n    const responsePromise = this.handleRequest({ request, event });\n    if (responsePromise) {\n      event.respondWith(responsePromise);\n    }\n  }\n\n  /**\n   * Caches new URLs on demand. Call this method from the service worker's\n   * `message` event. To trigger the handler, send a message of type `\"CACHE_URLS\"`\n   * alongside a list of URLs that should be cached as `urlsToCache`.\n   * @param event\n   */\n  handleCache(event: ExtendableMessageEvent) {\n    if (event.data && event.data.type === \"CACHE_URLS\") {\n      const { payload }: CacheURLsMessageData = event.data;\n\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.debug(\"Caching URLs from the window\", payload.urlsToCache);\n      }\n\n      const requestPromises = Promise.all(\n        payload.urlsToCache.map((entry: string | [string, RequestInit?]) => {\n          let request: Request;\n          if (typeof entry === \"string\") {\n            request = new Request(entry);\n          } else {\n            request = new Request(...entry);\n          }\n          return this.handleRequest({ request, event });\n        }),\n      );\n\n      event.waitUntil(requestPromises);\n\n      // If a MessageChannel was used, reply to the message on success.\n      if (event.ports?.[0]) {\n        void requestPromises.then(() => event.ports[0].postMessage(true));\n      }\n    }\n  }\n\n  /**\n   * Define a default handler that's called when no routes explicitly\n   * match the incoming request.\n   *\n   * Each HTTP method (`'GET'`, `'POST'`, etc.) gets its own default handler.\n   *\n   * Without a default handler, unmatched requests will go against the\n   * network as if there were no service worker present.\n   *\n   * @param handler A callback function that returns a `Promise` resulting in a `Response`.\n   * @param method The HTTP method to associate with this default handler. Each method\n   * has its own default. Defaults to `'GET'`.\n   */\n  setDefaultHandler(handler: RouteHandler, method: HTTPMethod = defaultMethod): void {\n    this._defaultHandlerMap.set(method, normalizeHandler(handler));\n  }\n\n  /**\n   * If a {@linkcode Route} throws an error while handling a request, this handler\n   * will be called and given a chance to provide a response.\n   *\n   * @param handler A callback function that returns a `Promise` resulting\n   * in a `Response`.\n   */\n  setCatchHandler(handler: RouteHandler): void {\n    this._catchHandler = normalizeHandler(handler);\n  }\n\n  /**\n   * Registers a `RegExp`, string, or function with a caching\n   * strategy to the router.\n   *\n   * @param capture If the capture param is a {@linkcode Route} object, all other arguments will be ignored.\n   * @param handler A callback function that returns a `Promise` resulting in a `Response`.\n   * This parameter is required if `capture` is not a {@linkcode Route} object.\n   * @param method The HTTP method to match the route against. Defaults to `'GET'`.\n   * @returns The generated {@linkcode Route} object.\n   */\n  registerCapture<T extends RegExp | string | RouteMatchCallback | Route>(\n    capture: T,\n    handler?: T extends Route ? never : RouteHandler,\n    method?: T extends Route ? never : HTTPMethod,\n  ): Route {\n    const route = parseRoute(capture, handler, method);\n    this.registerRoute(route);\n    return route;\n  }\n\n  /**\n   * Registers a {@linkcode Route} with the router.\n   *\n   * @param route The {@linkcode Route} to register.\n   */\n  registerRoute(route: Route): void {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isType(route, \"object\", {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"registerRoute\",\n        paramName: \"route\",\n      });\n\n      assert!.hasMethod(route, \"match\", {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"registerRoute\",\n        paramName: \"route\",\n      });\n\n      assert!.isType(route.handler, \"object\", {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"registerRoute\",\n        paramName: \"route\",\n      });\n\n      assert!.hasMethod(route.handler, \"handle\", {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"registerRoute\",\n        paramName: \"route.handler\",\n      });\n\n      assert!.isType(route.method, \"string\", {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"registerRoute\",\n        paramName: \"route.method\",\n      });\n    }\n\n    if (!this._routes.has(route.method)) {\n      this._routes.set(route.method, []);\n    }\n\n    // Give precedence to all of the earlier routes by adding this additional\n    // route to the end of the array.\n    this._routes.get(route.method)!.push(route);\n  }\n\n  /**\n   * Unregisters a route from the router.\n   *\n   * @param route The {@linkcode Route} object to unregister.\n   */\n  unregisterRoute(route: Route): void {\n    if (!this._routes.has(route.method)) {\n      throw new SerwistError(\"unregister-route-but-not-found-with-method\", {\n        method: route.method,\n      });\n    }\n\n    const routeIndex = this._routes.get(route.method)!.indexOf(route);\n    if (routeIndex > -1) {\n      this._routes.get(route.method)!.splice(routeIndex, 1);\n    } else {\n      throw new SerwistError(\"unregister-route-route-not-registered\");\n    }\n  }\n\n  /**\n   * Returns a mapping of a precached URL to the corresponding cache key, taking\n   * into account the revision information for the URL.\n   *\n   * @returns A URL to cache key mapping.\n   */\n  getUrlsToPrecacheKeys(): Map<string, string> {\n    return this._urlsToCacheKeys;\n  }\n\n  /**\n   * Returns a list of all the URLs that have been precached by the current\n   * service worker.\n   *\n   * @returns The precached URLs.\n   */\n  getPrecachedUrls(): string[] {\n    return [...this._urlsToCacheKeys.keys()];\n  }\n\n  /**\n   * Returns the cache key used for storing a given URL. If that URL is\n   * unversioned, like \"/index.html\", then the cache key will be the original\n   * URL with a search parameter appended to it.\n   *\n   * @param url A URL whose cache key you want to look up.\n   * @returns The versioned URL that corresponds to a cache key\n   * for the original URL, or undefined if that URL isn't precached.\n   */\n  getPrecacheKeyForUrl(url: string): string | undefined {\n    const urlObject = new URL(url, location.href);\n    return this._urlsToCacheKeys.get(urlObject.href);\n  }\n\n  /**\n   * @param url A cache key whose SRI you want to look up.\n   * @returns The subresource integrity associated with the cache key,\n   * or undefined if it's not set.\n   */\n  getIntegrityForPrecacheKey(cacheKey: string): string | undefined {\n    return this._cacheKeysToIntegrities.get(cacheKey);\n  }\n\n  /**\n   * This acts as a drop-in replacement for\n   * [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match)\n   * with the following differences:\n   *\n   * - It knows what the name of the precache is, and only checks in that cache.\n   * - It allows you to pass in an \"original\" URL without versioning parameters,\n   * and it will automatically look up the correct cache key for the currently\n   * active revision of that URL.\n   *\n   * E.g., `matchPrecache('index.html')` will find the correct precached\n   * response for the currently active service worker, even if the actual cache\n   * key is `'/index.html?__WB_REVISION__=1234abcd'`.\n   *\n   * @param request The key (without revisioning parameters)\n   * to look up in the precache.\n   * @returns\n   */\n  async matchPrecache(request: string | Request): Promise<Response | undefined> {\n    const url = request instanceof Request ? request.url : request;\n    const cacheKey = this.getPrecacheKeyForUrl(url);\n    if (cacheKey) {\n      const cache = await self.caches.open(this.precacheStrategy.cacheName);\n      return cache.match(cacheKey);\n    }\n    return undefined;\n  }\n\n  /**\n   * Returns a function that looks up `url` in the precache (taking into\n   * account revision information), and returns the corresponding `Response`.\n   *\n   * @param url The precached URL which will be used to lookup the response.\n   * @return\n   */\n  createHandlerBoundToUrl(url: string): RouteHandlerCallback {\n    const cacheKey = this.getPrecacheKeyForUrl(url);\n    if (!cacheKey) {\n      throw new SerwistError(\"non-precached-url\", { url });\n    }\n    return (options) => {\n      options.request = new Request(url);\n      options.params = { cacheKey, ...options.params };\n\n      return this.precacheStrategy.handle(options);\n    };\n  }\n\n  /**\n   * Applies the routing rules to a `FetchEvent` object to get a response from an\n   * appropriate route.\n   *\n   * @param options\n   * @returns A promise is returned if a registered route can handle the request.\n   * If there is no matching route and there's no default handler, `undefined`\n   * is returned.\n   */\n  handleRequest({\n    request,\n    event,\n  }: {\n    /**\n     * The request to handle.\n     */\n    request: Request;\n    /**\n     * The event that triggered the request.\n     */\n    event: ExtendableEvent;\n  }): Promise<Response> | undefined {\n    if (process.env.NODE_ENV !== \"production\") {\n      assert!.isInstance(request, Request, {\n        moduleName: \"serwist\",\n        className: \"Serwist\",\n        funcName: \"handleRequest\",\n        paramName: \"options.request\",\n      });\n    }\n\n    const url = new URL(request.url, location.href);\n    if (!url.protocol.startsWith(\"http\")) {\n      if (process.env.NODE_ENV !== \"production\") {\n        logger.debug(\"Router only supports URLs that start with 'http'.\");\n      }\n      return;\n    }\n\n    const sameOrigin = url.origin === location.origin;\n    const { params, route } = this.findMatchingRoute({\n      event,\n      request,\n      sameOrigin,\n      url,\n    });\n    let handler = route?.handler;\n\n    const debugMessages = [];\n    if (process.env.NODE_ENV !== \"production\") {\n      if (handler) {\n        debugMessages.push([\"Found a route to handle this request:\", route]);\n\n        if (params) {\n          debugMessages.push([`Passing the following params to the route's handler:`, params]);\n        }\n      }\n    }\n\n    // If we don't have a handler because there was no matching route, then\n    // fall back to defaultHandler if that's defined.\n    const method = request.method as HTTPMethod;\n    if (!handler && this._defaultHandlerMap.has(method)) {\n      if (process.env.NODE_ENV !== \"production\") {\n        debugMessages.push(`Failed to find a matching route. Falling back to the default handler for ${method}.`);\n      }\n      handler = this._defaultHandlerMap.get(method);\n    }\n\n    if (!handler) {\n      if (process.env.NODE_ENV !== \"production\") {\n        // No handler so Serwist will do nothing. If logs is set of debug\n        // i.e. verbose, we should print out this information.\n        logger.debug(`No route found for: ${getFriendlyURL(url)}`);\n      }\n      return;\n    }\n\n    if (process.env.NODE_ENV !== \"production\") {\n      // We have a handler, meaning Serwist is going to handle the route.\n      // print the routing details to the console.\n      logger.groupCollapsed(`Router is responding to: ${getFriendlyURL(url)}`);\n\n      for (const msg of debugMessages) {\n        if (Array.isArray(msg)) {\n          logger.log(...msg);\n        } else {\n          logger.log(msg);\n        }\n      }\n\n      logger.groupEnd();\n    }\n\n    // Wrap in try and catch in case the handle method throws a synchronous\n    // error. It should still callback to the catch handler.\n    let responsePromise: Promise<Response>;\n    try {\n      responsePromise = handler.handle({ url, request, event, params });\n    } catch (err) {\n      responsePromise = Promise.reject(err);\n    }\n\n    // Get route's catch handler, if it exists\n    const catchHandler = route?.catchHandler;\n\n    if (responsePromise instanceof Promise && (this._catchHandler || catchHandler)) {\n      responsePromise = responsePromise.catch(async (err) => {\n        // If there's a route catch handler, process that first\n        if (catchHandler) {\n          if (process.env.NODE_ENV !== \"production\") {\n            // Still include URL here as it will be async from the console group\n            // and may not make sense without the URL\n            logger.groupCollapsed(`Error thrown when responding to:  ${getFriendlyURL(url)}. Falling back to route's Catch Handler.`);\n            logger.error(\"Error thrown by:\", route);\n            logger.error(err);\n            logger.groupEnd();\n          }\n\n          try {\n            return await catchHandler.handle({ url, request, event, params });\n          } catch (catchErr) {\n            if (catchErr instanceof Error) {\n              err = catchErr;\n            }\n          }\n        }\n\n        if (this._catchHandler) {\n          if (process.env.NODE_ENV !== \"production\") {\n            // Still include URL here as it will be async from the console group\n            // and may not make sense without the URL\n            logger.groupCollapsed(`Error thrown when responding to:  ${getFriendlyURL(url)}. Falling back to global Catch Handler.`);\n            logger.error(\"Error thrown by:\", route);\n            logger.error(err);\n            logger.groupEnd();\n          }\n          return this._catchHandler.handle({ url, request, event });\n        }\n\n        throw err;\n      });\n    }\n\n    return responsePromise;\n  }\n\n  /**\n   * Checks a request and URL (and optionally an event) against the list of\n   * registered routes, and if there's a match, returns the corresponding\n   * route along with any params generated by the match.\n   *\n   * @param options\n   * @returns An object with `route` and `params` properties. They are populated\n   * if a matching route was found or `undefined` otherwise.\n   */\n  findMatchingRoute({ url, sameOrigin, request, event }: RouteMatchCallbackOptions): {\n    route?: Route;\n    params?: RouteHandlerCallbackOptions[\"params\"];\n  } {\n    const routes = this._routes.get(request.method as HTTPMethod) || [];\n    for (const route of routes) {\n      let params: Promise<any> | undefined;\n      // route.match returns type any, not possible to change right now.\n      const matchResult = route.match({ url, sameOrigin, request, event });\n      if (matchResult) {\n        if (process.env.NODE_ENV !== \"production\") {\n          // Warn developers that using an async matchCallback is almost always\n          // not the right thing to do.\n          if (matchResult instanceof Promise) {\n            logger.warn(\n              `While routing ${getFriendlyURL(\n                url,\n              )}, an async matchCallback function was used. Please convert the following route to use a synchronous matchCallback function:`,\n              route,\n            );\n          }\n        }\n\n        // See https://github.com/GoogleChrome/workbox/issues/2079\n        params = matchResult;\n        if (Array.isArray(params) && params.length === 0) {\n          // Instead of passing an empty array in as params, use undefined.\n          params = undefined;\n        } else if (matchResult.constructor === Object && Object.keys(matchResult).length === 0) {\n          // Instead of passing an empty object in as params, use undefined.\n          params = undefined;\n        } else if (typeof matchResult === \"boolean\") {\n          // For the boolean value true (rather than just something truth-y),\n          // don't set params.\n          // See https://github.com/GoogleChrome/workbox/pull/2134#issuecomment-513924353\n          params = undefined;\n        }\n\n        // Return early if have a match.\n        return { route, params };\n      }\n    }\n    // If no match was found above, return and empty object.\n    return {};\n  }\n}\n", "import type { RuntimeCaching } from \"serwist\";\nimport { CacheFirst, ExpirationPlugin, NetworkFirst, NetworkOnly, RangeRequestsPlugin, StaleWhileRevalidate } from \"serwist\";\n\nexport const PAGES_CACHE_NAME = {\n  rscPrefetch: \"pages-rsc-prefetch\",\n  rsc: \"pages-rsc\",\n  html: \"pages\",\n} as const;\n\n/**\n * The default, recommended list of caching strategies for applications\n * built with Next.js.\n *\n * @see https://serwist.pages.dev/docs/next/worker-exports#default-cache\n */\nexport const defaultCache: RuntimeCaching[] =\n  process.env.NODE_ENV !== \"production\"\n    ? [\n        {\n          matcher: /.*/i,\n          handler: new NetworkOnly(),\n        },\n      ]\n    : [\n        {\n          matcher: /^https:\\/\\/fonts\\.(?:gstatic)\\.com\\/.*/i,\n          handler: new CacheFirst({\n            cacheName: \"google-fonts-webfonts\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 4,\n                maxAgeSeconds: 365 * 24 * 60 * 60, // 365 days\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /^https:\\/\\/fonts\\.(?:googleapis)\\.com\\/.*/i,\n          handler: new StaleWhileRevalidate({\n            cacheName: \"google-fonts-stylesheets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 4,\n                maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,\n          handler: new StaleWhileRevalidate({\n            cacheName: \"static-font-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 4,\n                maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,\n          handler: new StaleWhileRevalidate({\n            cacheName: \"static-image-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 64,\n                maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\/_next\\/static.+\\.js$/i,\n          handler: new CacheFirst({\n            cacheName: \"next-static-js-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 64,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\/_next\\/image\\?url=.+$/i,\n          handler: new StaleWhileRevalidate({\n            cacheName: \"next-image\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 64,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:mp3|wav|ogg)$/i,\n          handler: new CacheFirst({\n            cacheName: \"static-audio-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n              new RangeRequestsPlugin(),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:mp4|webm)$/i,\n          handler: new CacheFirst({\n            cacheName: \"static-video-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n              new RangeRequestsPlugin(),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:js)$/i,\n          handler: new StaleWhileRevalidate({\n            cacheName: \"static-js-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 48,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:css|less)$/i,\n          handler: new StaleWhileRevalidate({\n            cacheName: \"static-style-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\/_next\\/data\\/.+\\/.+\\.json$/i,\n          handler: new NetworkFirst({\n            cacheName: \"next-data\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: /\\.(?:json|xml|csv)$/i,\n          handler: new NetworkFirst({\n            cacheName: \"static-data-assets\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n          }),\n        },\n        {\n          // Exclude /api/auth/* to fix auth callback\n          // https://github.com/serwist/serwist/discussions/28\n          matcher: /\\/api\\/auth\\/.*/,\n          handler: new NetworkOnly({\n            networkTimeoutSeconds: 10, // fallback to cache if API does not response within 10 seconds\n          }),\n        },\n        {\n          matcher: ({ sameOrigin, url: { pathname } }) => sameOrigin && pathname.startsWith(\"/api/\"),\n          method: \"GET\",\n          handler: new NetworkFirst({\n            cacheName: \"apis\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 16,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n                maxAgeFrom: \"last-used\",\n              }),\n            ],\n            networkTimeoutSeconds: 10, // fallback to cache if API does not response within 10 seconds\n          }),\n        },\n        {\n          matcher: ({ request, url: { pathname }, sameOrigin }) =>\n            request.headers.get(\"RSC\") === \"1\" && request.headers.get(\"Next-Router-Prefetch\") === \"1\" && sameOrigin && !pathname.startsWith(\"/api/\"),\n          handler: new NetworkFirst({\n            cacheName: PAGES_CACHE_NAME.rscPrefetch,\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: ({ request, url: { pathname }, sameOrigin }) => request.headers.get(\"RSC\") === \"1\" && sameOrigin && !pathname.startsWith(\"/api/\"),\n          handler: new NetworkFirst({\n            cacheName: PAGES_CACHE_NAME.rsc,\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: ({ request, url: { pathname }, sameOrigin }) =>\n            request.headers.get(\"Content-Type\")?.includes(\"text/html\") && sameOrigin && !pathname.startsWith(\"/api/\"),\n          handler: new NetworkFirst({\n            cacheName: PAGES_CACHE_NAME.html,\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: ({ url: { pathname }, sameOrigin }) => sameOrigin && !pathname.startsWith(\"/api/\"),\n          handler: new NetworkFirst({\n            cacheName: \"others\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 24 * 60 * 60, // 24 hours\n              }),\n            ],\n          }),\n        },\n        {\n          matcher: ({ sameOrigin }) => !sameOrigin,\n          handler: new NetworkFirst({\n            cacheName: \"cross-origin\",\n            plugins: [\n              new ExpirationPlugin({\n                maxEntries: 32,\n                maxAgeSeconds: 60 * 60, // 1 hour\n              }),\n            ],\n            networkTimeoutSeconds: 10,\n          }),\n        },\n        {\n          matcher: /.*/i,\n          method: \"GET\",\n          handler: new NetworkOnly(),\n        },\n      ];\n", "/// <reference lib=\"esnext\" />\n/// <reference lib=\"webworker\" />\n\n/**\n * Service-Worker-Quelle (Serwist).\n *\n * Ersetzt das fr\u00FChere `next-pwa`-Setup: next-pwa ist unmaintained und\n * webpack-basiert, was mit Turbopack (Next.js 16 Default) nicht mehr baut.\n * Serwist kompiliert diese Datei \u00FCber die Route `app/serwist/[path]/route.ts`\n * und liefert sie unter `/serwist/sw.js` aus.\n */\n\nimport { defaultCache } from '@serwist/turbopack/worker';\nimport type { PrecacheEntry, SerwistGlobalConfig } from 'serwist';\nimport { Serwist } from 'serwist';\n\ndeclare global {\n  interface WorkerGlobalScope extends SerwistGlobalConfig {\n    __SW_MANIFEST: (PrecacheEntry | string)[] | undefined;\n  }\n}\n\ndeclare const self: ServiceWorkerGlobalScope & WorkerGlobalScope;\n\nconst serwist = new Serwist({\n  precacheEntries: self.__SW_MANIFEST,\n  skipWaiting: true,\n  clientsClaim: true,\n  navigationPreload: true,\n  runtimeCaching: defaultCache,\n  fallbacks: {\n    entries: [\n      {\n        url: '/~offline',\n        matcher({ request }) {\n          return request.destination === 'document';\n        },\n      },\n    ],\n  },\n});\n\n/**\n * `/cdn-cgi/*` geh\u00F6rt Cloudflare und wird am Edge beantwortet (Zaraz,\n * Insights, Challenges). Diese Anfragen laufen am Service Worker vorbei.\n *\n * Der Listener steht bewusst *vor* `serwist.addEventListeners()` und ruft\n * `stopImmediatePropagation()`, ohne selbst zu antworten: damit kommt der\n * Serwist-Listener nicht mehr dran, niemand ruft `respondWith()`, und der\n * Browser holt die Datei ganz normal selbst.\n *\n * Vorher stand hier eine `NetworkOnly`-Route f\u00FCr denselben Pfad. Die\n * verhindert zwar das Cachen, wirft aber `no-response`, sobald der Abruf\n * scheitert \u2013 und bei `/cdn-cgi/zaraz/` ist genau das der Normalfall, weil\n * Inhaltsblocker den Pfad kennen. In der Konsole stand dann \"FetchEvent \u2026\n * resulted in a network error response: the promise was rejected\" plus eine\n * unbehandelte Promise-Ablehnung. Eine eigene Strategie hilft nicht: auch\n * ein zur\u00FCckgegebenes `Response.error()` gilt als Fehlerantwort des Service\n * Workers und wird protokolliert. Nur gar nicht zu antworten ist still.\n */\nself.addEventListener('fetch', (event) => {\n  const url = new URL(event.request.url);\n  if (\n    url.origin === self.location.origin &&\n    url.pathname.startsWith('/cdn-cgi/')\n  ) {\n    event.stopImmediatePropagation();\n  }\n});\n\nserwist.addEventListeners();\n"],
  "mappings": "AAAA,IAAAA,EAAA,CACE,CACE,IAAO,kDACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,yCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,wCACP,SAAY,IACd,EACA,CACE,IAAO,sDACP,SAAY,IACd,EACA,CACE,IAAO,mEACP,SAAY,IACd,EACA,CACE,IAAO,wDACP,SAAY,IACd,EACA,CACE,IAAO,uBACP,SAAY,kCACd,EACA,CACE,IAAO,mBACP,SAAY,kCACd,EACA,CACE,IAAO,eACP,SAAY,kCACd,EACA,CACE,IAAO,mBACP,SAAY,kCACd,EACA,CACE,IAAO,cACP,SAAY,kCACd,EACA,CACE,IAAO,iBACP,SAAY,kCACd,EACA,CACE,IAAO,iBACP,SAAY,kCACd,EACA,CACE,IAAO,qBACP,SAAY,kCACd,EACA,CACE,IAAO,aACP,SAAY,kCACd,EACA,CACE,IAAO,sBACP,SAAY,kCACd,EACA,CACE,IAAO,sBACP,SAAY,kCACd,EACA,CACE,IAAO,gBACP,SAAY,kCACd,EACA,CACE,IAAO,gBACP,SAAY,kCACd,EACA,CACE,IAAO,0BACP,SAAY,kCACd,EACA,CACE,IAAO,0BACP,SAAY,kCACd,EACA,CACE,IAAO,0BACP,SAAY,kCACd,EACA,CACE,SAAY,sBACZ,IAAO,WACT,CACF,EC1IA,IAAMC,EAAsC,CAC1C,gBAAiB,kBACjB,SAAU,cACV,OAAQ,UACR,QAAS,UACT,OAAQ,OAAO,aAAiB,IAAc,aAAa,MAAQ,IAG/DC,EAAoBC,GACjB,CAACF,EAAkB,OAAQE,EAAWF,EAAkB,QAAQ,OAAQG,GAAUA,GAASA,EAAM,OAAS,CAAA,EAAG,KAAK,GAAA,EAGrHC,GAAuBC,GAAkD,CAC7E,QAAWC,KAAO,OAAO,KAAKN,CAAA,EAC5BK,EAAGC,CAAA,GAIMC,EAAa,CACxB,cAAgBC,GAA2C,CACzDJ,GAAqBE,GAAoC,CACvD,IAAMG,EAASD,EAAQF,CAAA,EACnB,OAAOG,GAAW,WACpBT,EAAkBM,CAAA,EAAOG,MAI/B,uBAAyBC,GAChBA,GAAiBT,EAAiBD,EAAkB,eAAA,EAE7D,gBAAkBU,GACTA,GAAiBT,EAAiBD,EAAkB,QAAA,EAE7D,UAAA,IACSA,EAAkB,OAE3B,eAAiBU,GACRA,GAAiBT,EAAiBD,EAAkB,OAAA,EAE7D,UAAA,IACSA,EAAkB,QC3EzBW,EAUJ,SAASC,IAA8C,CACrD,GAAID,IAAkB,OAAW,CAC/B,IAAME,EAAe,IAAI,SAAS,EAAA,EAElC,GAAI,SAAUA,EACZ,GAAI,CACF,IAAI,SAASA,EAAa,IAAA,EAC1BF,EAAgB,QACV,CACNA,EAAgB,GAGpBA,EAAgB,GAGlB,OAAOA,EEtBT,IAAMG,GAAA,CAAYC,KAAiBC,IAAgB,CACjD,IAAIC,EAAMF,EACV,OAAIC,EAAK,OAAS,IAChBC,GAAO,OAAO,KAAK,UAAUD,CAAA,CAAK,IAE7BC,GAYT,IAAaC,GAA2DC,GCP3DC,EAAb,cAAkC,KAAM,CACtC,QAUA,YAAYC,EAAuBC,EAAyB,CAC1D,IAAMC,EAAUL,GAAiBG,EAAWC,CAAA,EAE5C,MAAMC,CAAA,EAEN,KAAK,KAAOF,EACZ,KAAK,QAAUC,IE9BnB,IAAME,GAAkBC,GAIf,IAHY,IAAI,OAAOA,CAAA,EAAM,SAAS,IAAA,EAG/B,KAAK,QAAQ,IAAI,OAAO,IAAI,SAAS,MAAA,EAAA,EAAW,EAAA,EEIhE,SAAgBC,EAAQC,EAA8B,CACpD,OAAO,IAAI,QAASC,GAAY,WAAWA,EAASD,CAAA,CAAG,ECPzD,IAAME,EAAqC,IAAI,ICH/C,SAASC,GAAYC,EAAiBC,EAAwB,CAC5D,IAAMC,EAAc,IAAI,IAAIF,CAAA,EAC5B,QAAWG,KAASF,EAClBC,EAAY,aAAa,OAAOC,CAAA,EAElC,OAAOD,EAAY,KAerB,eAAeE,GACbC,EACAC,EACAL,EACAM,EAC+B,CAC/B,IAAMC,EAAqBT,GAAYO,EAAQ,IAAKL,CAAA,EAGpD,GAAIK,EAAQ,MAAQE,EAClB,OAAOH,EAAM,MAAMC,EAASC,CAAA,EAI9B,IAAME,EAAc,CAAE,GAAGF,EAAc,aAAc,IAC/CG,EAAY,MAAML,EAAM,KAAKC,EAASG,CAAA,EAE5C,QAAWE,KAAYD,EAErB,GAAIF,IADwBT,GAAYY,EAAS,IAAKV,CAAA,EAEpD,OAAOI,EAAM,MAAMM,EAAUJ,CAAA,EC/BnC,IAAMK,GAAN,KAAkB,CAChB,QACA,QACA,OAKA,aAAc,CACZ,KAAK,QAAU,IAAI,QAAA,CAASf,EAASgB,IAAW,CAC9C,KAAK,QAAUhB,EACf,KAAK,OAASgB,MCVPC,GAA6B,SAA2B,CAKnE,QAAWC,KAAYjB,EACrB,MAAMiB,EAAA,GCZJC,GAAoB,aAkBbC,GAAuB,MAAOC,EAA6BC,EAA0BH,KAAyC,CAGzI,IAAMI,GAAqB,MAFF,KAAK,OAAO,KAAA,GAEC,OAAQC,GACrCA,EAAU,SAASF,CAAA,GAAoBE,EAAU,SAAS,KAAK,aAAa,KAAA,GAAUA,IAAcH,GAG7G,aAAM,QAAQ,IAAIE,EAAmB,IAAKC,GAAc,KAAK,OAAO,OAAOA,CAAA,CAAU,CAAC,EAE/ED,GCpBIE,GAAyBD,GAA6B,CACjE,KAAK,iBAAiB,WAAaE,GAA2B,CAC5DA,EAAM,UACJN,GAAqBO,EAAkB,gBAAgBH,CAAA,CAAU,EAAE,KAAMI,GAAkB,GAMzF,KCZKC,GAAA,IAA2B,CACtC,KAAK,iBAAiB,WAAA,IAAkB,KAAK,QAAQ,MAAA,CAAO,GCAjDC,EAAA,CAAsBJ,EAAwBK,IAA0C,CACnG,IAAMC,EAAgBD,EAAA,EACtB,OAAAL,EAAM,UAAUM,CAAA,EACTA,GCnBT,IAAMC,EAAgB,CAACC,EAAQC,IAAiBA,EAAa,KAAMC,GAAMF,aAAkBE,CAAC,EAExFC,GACAC,GAEJ,SAASC,IAAuB,CAC5B,OAAQF,KACHA,GAAoB,CACjB,YACA,eACA,SACA,UACA,cACJ,EACR,CAEA,SAASG,IAA0B,CAC/B,OAAQF,KACHA,GAAuB,CACpB,UAAU,UAAU,QACpB,UAAU,UAAU,SACpB,UAAU,UAAU,kBACxB,EACR,CACA,IAAMG,EAAqB,IAAI,QACzBC,EAAiB,IAAI,QACrBC,EAAwB,IAAI,QAClC,SAASC,GAAiBC,EAAS,CAC/B,IAAMC,EAAU,IAAI,QAAQ,CAACC,EAASC,IAAW,CAC7C,IAAMC,EAAW,IAAM,CACnBJ,EAAQ,oBAAoB,UAAWK,CAAO,EAC9CL,EAAQ,oBAAoB,QAASM,CAAK,CAC9C,EACMD,EAAU,IAAM,CAClBH,EAAQK,EAAKP,EAAQ,MAAM,CAAC,EAC5BI,EAAS,CACb,EACME,EAAQ,IAAM,CAChBH,EAAOH,EAAQ,KAAK,EACpBI,EAAS,CACb,EACAJ,EAAQ,iBAAiB,UAAWK,CAAO,EAC3CL,EAAQ,iBAAiB,QAASM,CAAK,CAC3C,CAAC,EAGD,OAAAR,EAAsB,IAAIG,EAASD,CAAO,EACnCC,CACX,CACA,SAASO,GAA+BC,EAAI,CAExC,GAAIb,EAAmB,IAAIa,CAAE,EACzB,OACJ,IAAMC,EAAO,IAAI,QAAQ,CAACR,EAASC,IAAW,CAC1C,IAAMC,EAAW,IAAM,CACnBK,EAAG,oBAAoB,WAAYE,CAAQ,EAC3CF,EAAG,oBAAoB,QAASH,CAAK,EACrCG,EAAG,oBAAoB,QAASH,CAAK,CACzC,EACMK,EAAW,IAAM,CACnBT,EAAQ,EACRE,EAAS,CACb,EACME,EAAQ,IAAM,CAChBH,EAAOM,EAAG,OAAS,IAAI,aAAa,aAAc,YAAY,CAAC,EAC/DL,EAAS,CACb,EACAK,EAAG,iBAAiB,WAAYE,CAAQ,EACxCF,EAAG,iBAAiB,QAASH,CAAK,EAClCG,EAAG,iBAAiB,QAASH,CAAK,CACtC,CAAC,EAEDV,EAAmB,IAAIa,EAAIC,CAAI,CACnC,CACA,IAAIE,EAAgB,CAChB,IAAIC,EAAQC,EAAMC,EAAU,CACxB,GAAIF,aAAkB,eAAgB,CAElC,GAAIC,IAAS,OACT,OAAOlB,EAAmB,IAAIiB,CAAM,EAExC,GAAIC,IAAS,QACT,OAAOC,EAAS,iBAAiB,CAAC,EAC5B,OACAA,EAAS,YAAYA,EAAS,iBAAiB,CAAC,CAAC,CAE/D,CAEA,OAAOR,EAAKM,EAAOC,CAAI,CAAC,CAC5B,EACA,IAAID,EAAQC,EAAME,EAAO,CACrB,OAAAH,EAAOC,CAAI,EAAIE,EACR,EACX,EACA,IAAIH,EAAQC,EAAM,CACd,OAAID,aAAkB,iBACjBC,IAAS,QAAUA,IAAS,SACtB,GAEJA,KAAQD,CACnB,CACJ,EACA,SAASI,GAAaC,EAAU,CAC5BN,EAAgBM,EAASN,CAAa,CAC1C,CACA,SAASO,GAAaC,EAAM,CAQxB,OAAIzB,GAAwB,EAAE,SAASyB,CAAI,EAChC,YAAaC,EAAM,CAGtB,OAAAD,EAAK,MAAME,EAAO,IAAI,EAAGD,CAAI,EACtBd,EAAK,KAAK,OAAO,CAC5B,EAEG,YAAac,EAAM,CAGtB,OAAOd,EAAKa,EAAK,MAAME,EAAO,IAAI,EAAGD,CAAI,CAAC,CAC9C,CACJ,CACA,SAASE,GAAuBP,EAAO,CACnC,OAAI,OAAOA,GAAU,WACVG,GAAaH,CAAK,GAGzBA,aAAiB,gBACjBR,GAA+BQ,CAAK,EACpC5B,EAAc4B,EAAOtB,GAAqB,CAAC,EACpC,IAAI,MAAMsB,EAAOJ,CAAa,EAElCI,EACX,CACA,SAAST,EAAKS,EAAO,CAGjB,GAAIA,aAAiB,WACjB,OAAOjB,GAAiBiB,CAAK,EAGjC,GAAInB,EAAe,IAAImB,CAAK,EACxB,OAAOnB,EAAe,IAAImB,CAAK,EACnC,IAAMQ,EAAWD,GAAuBP,CAAK,EAG7C,OAAIQ,IAAaR,IACbnB,EAAe,IAAImB,EAAOQ,CAAQ,EAClC1B,EAAsB,IAAI0B,EAAUR,CAAK,GAEtCQ,CACX,CACA,IAAMF,EAAUN,GAAUlB,EAAsB,IAAIkB,CAAK,EASzD,SAASS,EAAOC,EAAMC,EAAS,CAAE,QAAAC,EAAS,QAAAC,EAAS,SAAAC,EAAU,WAAAC,CAAW,EAAI,CAAC,EAAG,CAC5E,IAAM/B,EAAU,UAAU,KAAK0B,EAAMC,CAAO,EACtCK,EAAczB,EAAKP,CAAO,EAChC,OAAI6B,GACA7B,EAAQ,iBAAiB,gBAAkBiC,GAAU,CACjDJ,EAAQtB,EAAKP,EAAQ,MAAM,EAAGiC,EAAM,WAAYA,EAAM,WAAY1B,EAAKP,EAAQ,WAAW,EAAGiC,CAAK,CACtG,CAAC,EAEDL,GACA5B,EAAQ,iBAAiB,UAAYiC,GAAUL,EAE/CK,EAAM,WAAYA,EAAM,WAAYA,CAAK,CAAC,EAE9CD,EACK,KAAME,GAAO,CACVH,GACAG,EAAG,iBAAiB,QAAS,IAAMH,EAAW,CAAC,EAC/CD,GACAI,EAAG,iBAAiB,gBAAkBD,GAAUH,EAASG,EAAM,WAAYA,EAAM,WAAYA,CAAK,CAAC,CAE3G,CAAC,EACI,MAAM,IAAM,CAAE,CAAC,EACbD,CACX,CAMA,SAASG,GAAST,EAAM,CAAE,QAAAE,CAAQ,EAAI,CAAC,EAAG,CACtC,IAAM5B,EAAU,UAAU,eAAe0B,CAAI,EAC7C,OAAIE,GACA5B,EAAQ,iBAAiB,UAAYiC,GAAUL,EAE/CK,EAAM,WAAYA,CAAK,CAAC,EAErB1B,EAAKP,CAAO,EAAE,KAAK,IAAG,EAAY,CAC7C,CAEA,IAAMoC,GAAc,CAAC,MAAO,SAAU,SAAU,aAAc,OAAO,EAC/DC,GAAe,CAAC,MAAO,MAAO,SAAU,OAAO,EAC/CC,EAAgB,IAAI,IAC1B,SAASC,GAAU1B,EAAQC,EAAM,CAC7B,GAAI,EAAED,aAAkB,aACpB,EAAEC,KAAQD,IACV,OAAOC,GAAS,UAChB,OAEJ,GAAIwB,EAAc,IAAIxB,CAAI,EACtB,OAAOwB,EAAc,IAAIxB,CAAI,EACjC,IAAM0B,EAAiB1B,EAAK,QAAQ,aAAc,EAAE,EAC9C2B,EAAW3B,IAAS0B,EACpBE,EAAUL,GAAa,SAASG,CAAc,EACpD,GAEA,EAAEA,KAAmBC,EAAW,SAAW,gBAAgB,YACvD,EAAEC,GAAWN,GAAY,SAASI,CAAc,GAChD,OAEJ,IAAMG,EAAS,eAAgBC,KAAcvB,EAAM,CAE/C,IAAMZ,EAAK,KAAK,YAAYmC,EAAWF,EAAU,YAAc,UAAU,EACrE7B,EAASJ,EAAG,MAChB,OAAIgC,IACA5B,EAASA,EAAO,MAAMQ,EAAK,MAAM,CAAC,IAM9B,MAAM,QAAQ,IAAI,CACtBR,EAAO2B,CAAc,EAAE,GAAGnB,CAAI,EAC9BqB,GAAWjC,EAAG,IAClB,CAAC,GAAG,CAAC,CACT,EACA,OAAA6B,EAAc,IAAIxB,EAAM6B,CAAM,EACvBA,CACX,CACA1B,GAAc4B,IAAc,CACxB,GAAGA,EACH,IAAK,CAAChC,EAAQC,EAAMC,IAAawB,GAAU1B,EAAQC,CAAI,GAAK+B,EAAS,IAAIhC,EAAQC,EAAMC,CAAQ,EAC/F,IAAK,CAACF,EAAQC,IAAS,CAAC,CAACyB,GAAU1B,EAAQC,CAAI,GAAK+B,EAAS,IAAIhC,EAAQC,CAAI,CACjF,EAAE,EAEF,IAAMgC,GAAqB,CAAC,WAAY,qBAAsB,SAAS,EACjEC,GAAY,CAAC,EACbC,EAAiB,IAAI,QACrBC,GAAmC,IAAI,QACvCC,GAAsB,CACxB,IAAIrC,EAAQC,EAAM,CACd,GAAI,CAACgC,GAAmB,SAAShC,CAAI,EACjC,OAAOD,EAAOC,CAAI,EACtB,IAAIqC,EAAaJ,GAAUjC,CAAI,EAC/B,OAAKqC,IACDA,EAAaJ,GAAUjC,CAAI,EAAI,YAAaO,EAAM,CAC9C2B,EAAe,IAAI,KAAMC,GAAiC,IAAI,IAAI,EAAEnC,CAAI,EAAE,GAAGO,CAAI,CAAC,CACtF,GAEG8B,CACX,CACJ,EACA,eAAgBC,MAAW/B,EAAM,CAE7B,IAAIgC,EAAS,KAIb,GAHMA,aAAkB,YACpBA,EAAS,MAAMA,EAAO,WAAW,GAAGhC,CAAI,GAExC,CAACgC,EACD,OACJA,EAASA,EACT,IAAMC,EAAgB,IAAI,MAAMD,EAAQH,EAAmB,EAI3D,IAHAD,GAAiC,IAAIK,EAAeD,CAAM,EAE1DvD,EAAsB,IAAIwD,EAAehC,EAAO+B,CAAM,CAAC,EAChDA,GACH,MAAMC,EAEND,EAAS,MAAOL,EAAe,IAAIM,CAAa,GAAKD,EAAO,SAAS,GACrEL,EAAe,OAAOM,CAAa,CAE3C,CACA,SAASC,GAAe1C,EAAQC,EAAM,CAClC,OAASA,IAAS,OAAO,eACrB1B,EAAcyB,EAAQ,CAAC,SAAU,eAAgB,SAAS,CAAC,GAC1DC,IAAS,WAAa1B,EAAcyB,EAAQ,CAAC,SAAU,cAAc,CAAC,CAC/E,CACAI,GAAc4B,IAAc,CACxB,GAAGA,EACH,IAAIhC,EAAQC,EAAMC,EAAU,CACxB,OAAIwC,GAAe1C,EAAQC,CAAI,EACpBsC,GACJP,EAAS,IAAIhC,EAAQC,EAAMC,CAAQ,CAC9C,EACA,IAAIF,EAAQC,EAAM,CACd,OAAOyC,GAAe1C,EAAQC,CAAI,GAAK+B,EAAS,IAAIhC,EAAQC,CAAI,CACpE,CACJ,EAAE,ECnRF,IAAa0C,GAAe,MAAOC,EAAoBC,IAA+E,CACpI,IAAIC,EAAS,KAOb,GALIF,EAAS,MAEXE,EAAS,IADe,IAAIF,EAAS,GAAA,EAChB,QAGnBE,IAAW,KAAK,SAAS,OAC3B,MAAM,IAAIC,EAAa,6BAA8B,CAAE,OAAAD,CAAA,CAAQ,EAGjE,IAAME,EAAiBJ,EAAS,MAAA,EAG1BK,EAA6B,CACjC,QAAS,IAAI,QAAQD,EAAe,OAAA,EACpC,OAAQA,EAAe,OACvB,WAAYA,EAAe,YAIvBE,EAAuBL,EAAWA,EAASI,CAAA,EAAgBA,EAK3DE,EAAOC,GAAA,EAAuCJ,EAAe,KAAO,MAAMA,EAAe,KAAA,EAE/F,OAAO,IAAI,SAASG,EAAMD,CAAA,GCjDfG,GAAA,IAA6B,CACxC,KAAK,sBAAwB,ICazBC,GAA6B,EAC7BC,GAA0B,0BAC1BC,EAA4B,WAC5BC,EAAmB,YAsBZC,GAAb,KAAmC,CACjC,IAAgE,KAOhE,MAAM,SAASC,EAAmD,CAEhE,IAAMC,GAAK,MADM,KAAK,MAAA,GACR,YAAYJ,EAA2B,YAAa,CAChE,WAAY,SAAA,CACb,EACD,MAAMI,EAAG,MAAM,IAAID,CAAA,EACnB,MAAMC,EAAG,KAQX,MAAM,iBAA+C,CAGnD,OAAO,MADc,MADJ,KAAK,MAAA,GACE,YAAYJ,CAAA,EAA2B,MAAM,WAAA,IACtD,MAAM,GASvB,MAAM,yBAAyBK,EAA6D,CAE1F,IAAMC,EAAU,MAAM,MADL,KAAK,MAAA,GACG,gBAAgBN,EAA2BC,EAAkB,YAAY,KAAKI,CAAA,CAAU,EACjH,OAAOC,GAAqB,CAAA,EAS9B,MAAM,yBAAyBD,EAAoC,CAEjE,OAAO,MADU,KAAK,MAAA,GACZ,eAAeL,EAA2BC,EAAkB,YAAY,KAAKI,CAAA,CAAU,EAQnG,MAAM,YAAYE,EAA2B,CAE3C,MAAM,MADW,KAAK,MAAA,GACb,OAAOP,EAA2BO,CAAA,EAQ7C,MAAM,yBAAyBF,EAAuE,CACpG,OAAO,MAAM,KAAK,qBAAqB,YAAY,KAAKA,CAAA,EAAY,MAAA,EAQtE,MAAM,wBAAwBA,EAAuE,CACnG,OAAO,MAAM,KAAK,qBAAqB,YAAY,KAAKA,CAAA,EAAY,MAAA,EAYtE,MAAM,qBAAqBG,EAAoBC,EAAmF,CAIhI,OAAO,MADc,MAFJ,KAAK,MAAA,GAEE,YAAYT,CAAA,EAA2B,MAAM,MAAMC,CAAA,EAAkB,WAAWO,EAAOC,CAAA,IAChG,MAQjB,MAAc,OAAQ,CACpB,OAAK,KAAK,MACR,KAAK,IAAM,MAAMC,EAAOX,GAAyBD,GAA4B,CAC3E,QAAS,KAAK,UAAA,CACf,GAEI,KAAK,IAUd,WAAmBa,EAA+CC,EAAoB,CAChFA,EAAa,GAAKA,EAAad,IAC7Ba,EAAG,iBAAiB,SAASX,CAAA,GAC/BW,EAAG,kBAAkBX,CAAA,EAIRW,EAAG,kBAAkBX,EAA2B,CAC/D,cAAe,GACf,QAAS,KACV,EACQ,YAAYC,EAAkBA,EAAkB,CAAE,OAAQ,EAAA,CAAO,IC3JjEY,GAAb,KAAsC,CACpC,WACA,SAQA,YAAYR,EAAmB,CAC7B,KAAK,WAAaA,EAClB,KAAK,SAAW,IAAIH,GAQtB,MAAM,UAAUC,EAAmD,CAgBjE,OAAOA,EAAM,GACbA,EAAM,UAAY,KAAK,WAEvB,MAAM,KAAK,SAAS,SAASA,CAAA,EAQ/B,MAAM,aAAaA,EAAmD,CAgBpE,IAAMW,EAAU,MAAM,KAAK,SAAS,gBAAA,EAEhCA,EAEFX,EAAM,GAAKW,EAAU,EAErB,OAAOX,EAAM,GAEfA,EAAM,UAAY,KAAK,WAEvB,MAAM,KAAK,SAAS,SAASA,CAAA,EAQ/B,MAAM,UAA+D,CACnE,OAAO,KAAK,aAAa,MAAM,KAAK,SAAS,wBAAwB,KAAK,UAAA,CAAW,EAQvF,MAAM,YAAiE,CACrE,OAAO,KAAK,aAAa,MAAM,KAAK,SAAS,yBAAyB,KAAK,UAAA,CAAW,EAQxF,MAAM,QAAmD,CACvD,OAAO,MAAM,KAAK,SAAS,yBAAyB,KAAK,UAAA,EAQ3D,MAAM,MAAwB,CAC5B,OAAO,MAAM,KAAK,SAAS,yBAAyB,KAAK,UAAA,EAa3D,MAAM,YAAYI,EAA2B,CAC3C,MAAM,KAAK,SAAS,YAAYA,CAAA,EAUlC,MAAM,aAAaJ,EAA2F,CAC5G,OAAIA,GACF,MAAM,KAAK,YAAYA,EAAM,EAAA,EAExBA,IC9ILY,GAAmD,CACvD,SACA,WACA,iBACA,OACA,cACA,QACA,WACA,YACA,aAgBWC,EAAb,MAAaA,CAAgB,CAC3B,aASA,aAAa,YAAYC,EAA4C,CACnE,IAAMC,EAA2B,CAC/B,IAAKD,EAAQ,IACb,QAAS,CAAA,GAIPA,EAAQ,SAAW,QAKrBC,EAAY,KAAO,MAAMD,EAAQ,MAAA,EAAQ,YAAA,GAG3CA,EAAQ,QAAQ,QAAA,CAASE,EAAOC,IAAQ,CACtCF,EAAY,QAAQE,CAAA,EAAOD,IAI7B,QAAWE,KAAQN,GACbE,EAAQI,CAAA,IAAU,SACpBH,EAAYG,CAAA,EAAQJ,EAAQI,CAAA,GAIhC,OAAO,IAAIL,EAAgBE,CAAA,EAU7B,YAAYA,EAA0B,CAkBhCA,EAAY,OAAS,aACvBA,EAAY,KAAO,eAGrB,KAAK,aAAeA,EAQtB,UAAwB,CACtB,IAAMA,EAAc,OAAO,OAAO,CAAA,EAAI,KAAK,YAAA,EAC3C,OAAAA,EAAY,QAAU,OAAO,OAAO,CAAA,EAAI,KAAK,aAAa,OAAA,EACtDA,EAAY,OACdA,EAAY,KAAOA,EAAY,KAAK,MAAM,CAAA,GAGrCA,EAQT,WAAqB,CACnB,OAAO,IAAI,QAAQ,KAAK,aAAa,IAAK,KAAK,YAAA,EAQjD,OAAyB,CACvB,OAAO,IAAIF,EAAgB,KAAK,SAAA,CAAU,IC7CxCM,GAAa,0BACbC,GAAqB,KAAU,EAE/BC,EAAa,IAAI,IAWjBC,GAAgBC,GAA2E,CAC/F,IAAMC,EAAuC,CAC3C,QAAS,IAAIX,EAAgBU,EAAgB,WAAA,EAAa,UAAA,EAC1D,UAAWA,EAAgB,WAE7B,OAAIA,EAAgB,WAClBC,EAAW,SAAWD,EAAgB,UAEjCC,GAQIC,GAAb,KAAiC,CAC/B,MACA,QACA,kBACA,YACA,mBACA,gBAA0B,GAC1B,yBAAmC,GAWnC,YAAYC,EAAc,CAAE,kBAAAC,EAAmB,OAAAC,EAAQ,iBAAAC,CAAA,EAAiD,CAAA,EAAI,CAE1G,GAAIR,EAAW,IAAIK,CAAA,EACjB,MAAM,IAAItC,EAAa,uBAAwB,CAAE,KAAAsC,CAAA,CAAM,EAEzDL,EAAW,IAAIK,CAAA,EAEf,KAAK,MAAQA,EACb,KAAK,QAAUE,GAAU,KAAK,eAC9B,KAAK,kBAAoBC,GAAoBT,GAC7C,KAAK,mBAAqB,EAAQO,EAClC,KAAK,YAAc,IAAIjB,GAAyB,KAAK,KAAA,EAErD,KAAK,iBAAA,EAMP,IAAI,MAAe,CACjB,OAAO,KAAK,MASd,MAAM,YAAYV,EAAgD,CAgBhE,MAAM,KAAK,YAAYA,EAAO,MAAA,EAShC,MAAM,eAAeA,EAAgD,CAgBnE,MAAM,KAAK,YAAYA,EAAO,SAAA,EAShC,MAAM,YAA4D,CAChE,OAAO,KAAK,eAAe,KAAA,EAS7B,MAAM,cAA8D,CAClE,OAAO,KAAK,eAAe,OAAA,EAS7B,MAAM,QAA8C,CAClD,IAAM8B,EAAa,MAAM,KAAK,YAAY,OAAA,EACpCC,EAAM,KAAK,IAAA,EAEXC,EAAmB,CAAA,EACzB,QAAWhC,KAAS8B,EAAY,CAG9B,IAAMG,EAAuB,KAAK,kBAAoB,GAAK,IACvDF,EAAM/B,EAAM,UAAYiC,EAC1B,MAAM,KAAK,YAAY,YAAYjC,EAAM,EAAA,EAEzCgC,EAAiB,KAAKV,GAAatB,CAAA,CAAM,EAI7C,OAAOgC,EAST,MAAM,MAAwB,CAC5B,OAAO,MAAM,KAAK,YAAY,KAAA,EAUhC,MAAM,YAAY,CAAE,QAAAlB,EAAS,SAAAoB,EAAU,UAAAC,EAAY,KAAK,IAAA,CAAK,EAA8BC,EAA8C,CAEvI,IAAMpC,EAAqC,CACzC,aAAa,MAFea,EAAgB,YAAYC,EAAQ,MAAA,CAAO,GAE1C,SAAA,EAC7B,UAAAqB,GAQF,OAJID,IACFlC,EAAM,SAAWkC,GAGXE,EAAR,CACE,IAAK,OACH,MAAM,KAAK,YAAY,UAAUpC,CAAA,EACjC,MACF,IAAK,UACH,MAAM,KAAK,YAAY,aAAaA,CAAA,EACpC,MAUA,KAAK,gBACP,KAAK,yBAA2B,GAEhC,MAAM,KAAK,aAAA,EAYf,MAAM,eAAeoC,EAA2E,CAC9F,IAAML,EAAM,KAAK,IAAA,EACb/B,EACJ,OAAQoC,EAAR,CACE,IAAK,MACHpC,EAAQ,MAAM,KAAK,YAAY,SAAA,EAC/B,MACF,IAAK,QACHA,EAAQ,MAAM,KAAK,YAAY,WAAA,EAC/B,MAGJ,GAAIA,EAAO,CAGT,IAAMiC,EAAuB,KAAK,kBAAoB,GAAK,IAC3D,OAAIF,EAAM/B,EAAM,UAAYiC,EACnB,KAAK,eAAeG,CAAA,EAGtBd,GAAatB,CAAA,GAWxB,MAAM,gBAAgC,CACpC,IAAIA,EACJ,KAAQA,EAAQ,MAAM,KAAK,aAAA,GACzB,GAAI,CACF,MAAM,MAAMA,EAAM,QAAQ,MAAA,CAAO,OAK3B,CACN,YAAM,KAAK,eAAeA,CAAA,EAKpB,IAAIZ,EAAa,sBAAuB,CAAE,KAAM,KAAK,KAAA,CAAO,GAWxE,MAAM,cAA8B,CAElC,GAAI,SAAU,KAAK,cAAgB,CAAC,KAAK,mBACvC,GAAI,CACF,MAAM,KAAK,aAAa,KAAK,SAAS,GAAG+B,EAAA,IAAc,KAAK,KAAA,EAAA,OAChD,GAiBlB,kBAA2B,CAErB,SAAU,KAAK,cAAgB,CAAC,KAAK,mBACvC,KAAK,iBAAiB,OAASkB,GAAqB,CAClD,GAAIA,EAAM,MAAQ,GAAGlB,EAAA,IAAc,KAAK,KAAA,GAAS,CAK/C,IAAMmB,EAAe,SAAY,CAC/B,KAAK,gBAAkB,GAEvB,IAAIC,EACJ,GAAI,CACF,MAAM,KAAK,QAAQ,CAAE,MAAO,IAAA,CAAM,QAC3BC,EAAO,CACd,GAAIA,aAAiB,MACnB,MAAAD,EAAYC,EAIND,UAQJ,KAAK,0BAA4B,EAAEA,GAAa,CAACF,EAAM,aACzD,MAAM,KAAK,aAAA,EAGb,KAAK,gBAAkB,GACvB,KAAK,yBAA2B,KAGpCA,EAAM,UAAUC,EAAA,CAAc,KAU7B,KAAK,QAAQ,CAAE,MAAO,IAAA,CAAM,EAWrC,WAAW,aAA2B,CACpC,OAAOjB,IC1bEoB,GAAb,KAA2D,CACzD,OASA,YAAYf,EAAcgB,EAAsC,CAC9D,KAAK,OAAS,IAAIjB,GAAoBC,EAAMgB,CAAA,EAO9C,MAAM,aAAa,CAAE,QAAA5B,CAAA,EAAsC,CACzD,MAAM,KAAK,OAAO,YAAY,CAAE,QAAAA,CAAA,CAAS,ICzBhC6B,EAAwC,CASnD,gBAAiB,MAAO,CAAE,SAAA1D,CAAA,IACpBA,EAAS,SAAW,KAAOA,EAAS,SAAW,EAC1CA,EAEF,MCHX,SAAS2D,EAAUC,EAAoB,CACrC,OAAO,OAAOA,GAAU,SAAW,IAAI,QAAQA,CAAA,EAASA,EAS1D,IAAaC,GAAb,KAA6B,CAI3B,MAKA,QAOA,IASA,OAEA,WAA8C,CAAA,EAC9C,UACA,iBACA,wBACA,SACA,gBAYA,YACEC,EACAL,EAGA,CAgBA,KAAK,MAAQA,EAAQ,MACrB,KAAK,QAAUA,EAAQ,QACnBA,EAAQ,MACV,KAAK,IAAMA,EAAQ,IACnB,KAAK,OAASA,EAAQ,QAExB,KAAK,UAAYK,EACjB,KAAK,iBAAmB,IAAIC,GAC5B,KAAK,wBAA0B,CAAA,EAI/B,KAAK,SAAW,CAAC,GAAGD,EAAS,OAAA,EAC7B,KAAK,gBAAkB,IAAI,IAC3B,QAAWE,KAAU,KAAK,SACxB,KAAK,gBAAgB,IAAIA,EAAQ,CAAA,CAAE,EAGrC,KAAK,MAAM,UAAU,KAAK,iBAAiB,OAAA,EAgB7C,MAAM,MAAMJ,EAAuC,CACjD,GAAM,CAAE,MAAAR,CAAA,EAAU,KACdvB,EAAmB8B,EAAUC,CAAA,EAE3BK,EAAkB,MAAM,KAAK,mBAAA,EAEnC,GAAIA,EACF,OAAOA,EAMT,IAAMC,EAAkB,KAAK,YAAY,cAAA,EAAkBrC,EAAQ,MAAA,EAAU,KAE7E,GAAI,CACF,QAAWsC,KAAM,KAAK,iBAAiB,kBAAA,EACrCtC,EAAU,MAAMsC,EAAG,CAAE,QAAStC,EAAQ,MAAA,EAAS,MAAAuB,EAAO,QAEjDgB,EAAK,CACZ,GAAIA,aAAe,MACjB,MAAM,IAAIjE,EAAa,kCAAmC,CACxD,mBAAoBiE,EAAI,OAAA,CACzB,EAOL,IAAMC,EAAiCxC,EAAQ,MAAA,EAE/C,GAAI,CACF,IAAIyC,EAGJA,EAAgB,MAAM,MAAMzC,EAASA,EAAQ,OAAS,WAAa,OAAY,KAAK,UAAU,YAAA,EAM9F,QAAW0C,KAAY,KAAK,iBAAiB,iBAAA,EAC3CD,EAAgB,MAAMC,EAAS,CAC7B,MAAAnB,EACA,QAASiB,EACT,SAAUC,EACX,EAEH,OAAOA,QACAf,EAAO,CAOd,MAAIW,GACF,MAAM,KAAK,aAAa,eAAgB,CAC/B,MAAAX,EACP,MAAAH,EACA,gBAAiBc,EAAgB,MAAA,EACjC,QAASG,EAAsB,MAAA,EAChC,EAEGd,GAaV,MAAM,iBAAiBK,EAAuC,CAC5D,IAAM5D,EAAW,MAAM,KAAK,MAAM4D,CAAA,EAC5BY,EAAgBxE,EAAS,MAAA,EAE1B,YAAK,UAAU,KAAK,SAAS4D,EAAOY,CAAA,CAAc,EAEhDxE,EAeT,MAAM,WAAWgC,EAAiD,CAChE,IAAMH,EAAmB8B,EAAU3B,CAAA,EAC/ByC,EACE,CAAE,UAAAC,EAAW,aAAAC,CAAA,EAAiB,KAAK,UAEnCC,EAAmB,MAAM,KAAK,YAAY/C,EAAS,MAAA,EACnDgD,EAAoB,CAAE,GAAGF,EAAmB,UAAAD,GAElDD,EAAiB,MAAM,OAAO,MAAMG,EAAkBC,CAAA,EAUtD,QAAWN,KAAY,KAAK,iBAAiB,0BAAA,EAC3CE,EACG,MAAMF,EAAS,CACd,UAAAG,EACA,aAAAC,EACA,eAAAF,EACA,QAASG,EACT,MAAO,KAAK,MACb,GAAM,OAEX,OAAOH,EAkBT,MAAM,SAASzC,EAAkBhC,EAAsC,CACrE,IAAM6B,EAAmB8B,EAAU3B,CAAA,EAInC,MAAM8C,EAAQ,CAAA,EAEd,IAAMF,EAAmB,MAAM,KAAK,YAAY/C,EAAS,OAAA,EAWzD,GAAI,CAAC7B,EAKH,MAAM,IAAIG,EAAa,6BAA8B,CACnD,IAAK4E,GAAeH,EAAiB,GAAA,CAAI,CAC1C,EAGH,IAAMI,EAAkB,MAAM,KAAK,2BAA2BhF,CAAA,EAE9D,GAAI,CAACgF,EAIH,MAAO,GAGT,GAAM,CAAE,UAAAN,EAAW,aAAAC,CAAA,EAAiB,KAAK,UACnCM,EAAQ,MAAM,KAAK,OAAO,KAAKP,CAAA,EAc/BQ,EAAyB,KAAK,YAAY,gBAAA,EAC1CC,EAAcD,EAChB,MAAME,GAIJH,EACAL,EAAiB,MAAA,EACjB,CAAC,iBAAA,EACDD,CAAA,EAEF,KAMJ,GAAI,CACF,MAAMM,EAAM,IAAIL,EAAkBM,EAAyBF,EAAgB,MAAA,EAAUA,CAAA,QAC9EzB,EAAO,CACd,GAAIA,aAAiB,MAEnB,MAAIA,EAAM,OAAS,sBACjB,MAAM8B,GAAA,EAEF9B,EAIV,QAAWgB,KAAY,KAAK,iBAAiB,gBAAA,EAC3C,MAAMA,EAAS,CACb,UAAAG,EACA,YAAAS,EACA,YAAaH,EAAgB,MAAA,EAC7B,QAASJ,EACT,MAAO,KAAK,MACb,EAGH,MAAO,GAcT,MAAM,YAAY/C,EAAkByD,EAA0C,CAC5E,IAAMtD,EAAM,GAAGH,EAAQ,GAAA,MAASyD,CAAA,GAChC,GAAI,CAAC,KAAK,WAAWtD,CAAA,EAAM,CACzB,IAAI4C,EAAmB/C,EAEvB,QAAW0C,KAAY,KAAK,iBAAiB,oBAAA,EAC3CK,EAAmBjB,EACjB,MAAMY,EAAS,CACb,KAAAe,EACA,QAASV,EACT,MAAO,KAAK,MACZ,OAAQ,KAAK,OACd,CAAC,EAIN,KAAK,WAAW5C,CAAA,EAAO4C,EAEzB,OAAO,KAAK,WAAW5C,CAAA,EAUzB,YAA2CS,EAAkB,CAC3D,QAAWuB,KAAU,KAAK,UAAU,QAClC,GAAIvB,KAAQuB,EACV,MAAO,GAGX,MAAO,GAeT,MAAM,aAAyDvB,EAAS8C,EAAoE,CAC1I,QAAWhB,KAAY,KAAK,iBAAiB9B,CAAA,EAG3C,MAAM8B,EAASgB,CAAA,EAUnB,CAAC,iBAAgD9C,EAAmD,CAClG,QAAWuB,KAAU,KAAK,UAAU,QAClC,GAAI,OAAOA,EAAOvB,CAAA,GAAU,WAAY,CACtC,IAAM+C,EAAQ,KAAK,gBAAgB,IAAIxB,CAAA,EAQvC,MAP0BuB,GAAwD,CAChF,IAAME,EAAgB,CAAE,GAAGF,EAAO,MAAAC,GAIlC,OAAOxB,EAAOvB,CAAA,EAAOgD,CAAA,IAiB7B,UAAaC,EAAiC,CAC5C,YAAK,wBAAwB,KAAKA,CAAA,EAC3BA,EAWT,MAAM,aAA6B,CACjC,IAAIA,EACJ,KAAQA,EAAU,KAAK,wBAAwB,MAAA,GAC7C,MAAMA,EAQV,SAAgB,CACd,KAAK,iBAAiB,QAAQ,IAAA,EAUhC,MAAM,oBAAoD,CACxD,GAAI,KAAK,iBAAiB,YAAc,KAAK,MAAM,QAAQ,OAAS,YAAc,oBAAqB,KAAK,MAC1G,GAAI,CACF,IAAMC,EAA2B,MAAM,KAAK,MAAM,gBAClD,GAAIA,EAIF,OAAOA,OAEK,CAId,QAcN,MAAM,2BAA2B3F,EAAmD,CAClF,IAAIgF,EAAwChF,EACxC4F,EAAc,GAElB,QAAWrB,KAAY,KAAK,iBAAiB,iBAAA,EAS3C,GARAS,EACG,MAAMT,EAAS,CACd,QAAS,KAAK,QACd,SAAUS,EACV,MAAO,KAAK,MACb,GAAM,OACTY,EAAc,GAEV,CAACZ,EACH,MAIJ,OAAKY,GACCZ,GAAmBA,EAAgB,SAAW,MAUhDA,EAAkB,QAIfA,IC1gBWa,EAAtB,KAA6D,CAC3D,UACA,QACA,aACA,aAcA,YAAYpC,EAA2B,CAAA,EAAI,CACzC,KAAK,UAAYqC,EAAkB,eAAerC,EAAQ,SAAA,EAC1D,KAAK,QAAUA,EAAQ,SAAW,CAAA,EAClC,KAAK,aAAeA,EAAQ,aAC5B,KAAK,aAAeA,EAAQ,aAmB9B,OAAOA,EAAiE,CACtE,GAAM,CAACsC,CAAA,EAAgB,KAAK,UAAUtC,CAAA,EACtC,OAAOsC,EAiBT,UAAUtC,EAAkF,CAEtFA,aAAmB,aACrBA,EAAU,CACR,MAAOA,EACP,QAASA,EAAQ,UAIrB,IAAML,EAAQK,EAAQ,MAChB5B,EAAU,OAAO4B,EAAQ,SAAY,SAAW,IAAI,QAAQA,EAAQ,OAAA,EAAWA,EAAQ,QAEvFuC,EAAU,IAAInC,GAAgB,KAAMJ,EAAQ,IAAM,CAAE,MAAAL,EAAO,QAAAvB,EAAS,IAAK4B,EAAQ,IAAK,OAAQA,EAAQ,QAAW,CAAE,MAAAL,EAAO,QAAAvB,EAAS,EAEnIkE,EAAe,KAAK,aAAaC,EAASnE,EAASuB,CAAA,EAIzD,MAAO,CAAC2C,EAHY,KAAK,eAAeA,EAAcC,EAASnE,EAASuB,CAAA,CAGvC,EAGnC,MAAM,aAAa4C,EAA0BnE,EAAkBuB,EAA2C,CACxG,MAAM4C,EAAQ,aAAa,mBAAoB,CAAE,MAAA5C,EAAO,QAAAvB,EAAS,EAEjE,IAAI7B,EACJ,GAAI,CAKF,GAJAA,EAAW,MAAM,KAAK,QAAQ6B,EAASmE,CAAA,EAInChG,IAAa,QAAaA,EAAS,OAAS,QAC9C,MAAM,IAAIG,EAAa,cAAe,CAAE,IAAK0B,EAAQ,GAAA,CAAK,QAErD0B,EAAO,CACd,GAAIA,aAAiB,OACnB,QAAWgB,KAAYyB,EAAQ,iBAAiB,iBAAA,EAE9C,GADAhG,EAAW,MAAMuE,EAAS,CAAE,MAAAhB,EAAO,MAAAH,EAAO,QAAAvB,EAAS,EAC/C7B,IAAa,OACf,MAKN,GAAI,CAACA,EACH,MAAMuD,EAWV,QAAWgB,KAAYyB,EAAQ,iBAAiB,oBAAA,EAC9ChG,EAAY,MAAMuE,EAAS,CAAE,MAAAnB,EAAO,QAAAvB,EAAS,SAAA7B,EAAU,EAGzD,OAAOA,EAGT,MAAM,eAAe+F,EAAiCC,EAA0BnE,EAAkBuB,EAAuC,CACvI,IAAIpD,EACAuD,EAEJ,GAAI,CACFvD,EAAW,MAAM+F,OACX,CAAA,CAMR,GAAI,CACF,MAAMC,EAAQ,aAAa,oBAAqB,CAC9C,MAAA5C,EACA,QAAAvB,EACA,SAAA7B,EACD,EACD,MAAMgG,EAAQ,YAAA,QACPC,EAAgB,CACnBA,aAA0B,QAC5B1C,EAAQ0C,GAYZ,GARA,MAAMD,EAAQ,aAAa,qBAAsB,CAC/C,MAAA5C,EACA,QAAAvB,EACA,SAAA7B,EACA,MAAAuD,EACD,EACDyC,EAAQ,QAAA,EAEJzC,EACF,MAAMA,IElKZ,IAAa2C,EAAb,cAAkCC,CAAS,CACzC,uBAOA,YAAYC,EAA+B,CAAA,EAAI,CAC7C,MAAMA,CAAA,EAID,KAAK,QAAQ,KAAMC,GAAM,oBAAqBA,CAAA,GACjD,KAAK,QAAQ,QAAQC,CAAA,EAGvB,KAAK,uBAAyBF,EAAQ,uBAAyB,EAmBjE,MAAM,QAAQG,EAAkBC,EAA6C,CAC3E,IAAMC,EAAc,CAAA,EAWdC,EAA4C,CAAA,EAC9CC,EAEJ,GAAI,KAAK,uBAAwB,CAC/B,GAAM,CAAE,GAAAC,EAAI,QAAAC,CAAA,EAAY,KAAK,mBAAmB,CAC9C,QAAAN,EACA,KAAAE,EACA,QAAAD,EACD,EACDG,EAAYC,EACZF,EAAS,KAAKG,CAAA,EAGhB,IAAMC,EAAiB,KAAK,mBAAmB,CAC7C,UAAAH,EACA,QAAAJ,EACA,KAAAE,EACA,QAAAD,EACD,EAEDE,EAAS,KAAKI,CAAA,EAEd,IAAMC,EAAW,MAAMP,EAAQ,WAC5B,SAGI,MAAMA,EAAQ,UAAU,QAAQ,KAAKE,CAAA,CAAS,GAM9C,MAAMI,IAEP,EAYN,GAAI,CAACC,EACH,MAAM,IAAIC,EAAa,cAAe,CAAE,IAAKT,EAAQ,GAAA,CAAK,EAE5D,OAAOQ,EAQT,mBAA2B,CACzB,QAAAR,EACA,KAAAE,EACA,QAAAD,CAAA,EAQ0D,CAE1D,IAAIG,EAWJ,MAAO,CACL,QAAS,IAX+C,QAASM,GAAY,CAO7EN,EAAY,WANa,SAAY,CAInCM,EAAQ,MAAMT,EAAQ,WAAWD,CAAA,CAAQ,GAEF,KAAK,uBAAyB,GAAA,IAKvE,GAAII,GAcR,MAAM,mBAAmB,CACvB,UAAAA,EACA,QAAAJ,EACA,KAAAE,EACA,QAAAD,CAAA,EAMgC,CAChC,IAAIU,EACAH,EACJ,GAAI,CACFA,EAAW,MAAMP,EAAQ,iBAAiBD,CAAA,QACnCY,EAAY,CACfA,aAAsB,QACxBD,EAAQC,GAIZ,OAAIR,GACF,aAAaA,CAAA,GAWXO,GAAS,CAACH,KACZA,EAAW,MAAMP,EAAQ,WAAWD,CAAA,GAW/BQ,IClMEK,EAAb,cAAiCjB,CAAS,CACxC,uBAKA,YAAYC,EAA8B,CAAA,EAAI,CAC5C,MAAMA,CAAA,EAEN,KAAK,uBAAyBA,EAAQ,uBAAyB,EASjE,MAAM,QAAQG,EAAkBC,EAA6C,CAU3E,IAAIU,EACAH,EAEJ,GAAI,CACF,IAAML,EAA4C,CAACF,EAAQ,MAAMD,CAAA,CAAQ,EAEzE,GAAI,KAAK,uBAAwB,CAC/B,IAAMc,EAAiBC,EAAQ,KAAK,uBAAyB,GAAA,EAC7DZ,EAAS,KAAKW,CAAA,EAIhB,GADAN,EAAW,MAAM,QAAQ,KAAKL,CAAA,EAC1B,CAACK,EACH,MAAM,IAAI,MAAM,wCAAwC,KAAK,sBAAA,WAAuB,QAE/EQ,EAAK,CACRA,aAAe,QACjBL,EAAQK,GAeZ,GAAI,CAACR,EACH,MAAM,IAAIC,EAAa,cAAe,CAAE,IAAKT,EAAQ,IAAK,MAAAW,EAAO,EAEnE,OAAOH,IE7EX,IAAaS,EAAoBC,GAC3BA,GAAW,OAAOA,GAAY,SASzBA,EAUF,CAAE,OAAQA,CAAA,ECjBNC,EAAb,KAAmB,CACjB,QACA,MACA,OACA,aAYA,YAAYC,EAA2BF,EAAuBG,EAAA,MAAoC,CAgBhG,KAAK,QAAUJ,EAAiBC,CAAA,EAChC,KAAK,MAAQE,EACb,KAAK,OAASC,EAQhB,gBAAgBH,EAA6B,CAC3C,KAAK,aAAeD,EAAiBC,CAAA,IC1B5BI,GAAb,MAAaA,UAAyBC,CAAS,CAC7C,mBAEA,OAAgB,kCAAmD,CACjE,MAAM,gBAAgB,CAAE,SAAAC,CAAA,EAAY,CAClC,MAAI,CAACA,GAAYA,EAAS,QAAU,IAC3B,KAGFA,IAIX,OAAgB,uCAAwD,CACtE,MAAM,gBAAgB,CAAE,SAAAA,CAAA,EAAY,CAClC,OAAOA,EAAS,WAAa,MAAMC,GAAaD,CAAA,EAAYA,IAOhE,YAAYE,EAAmC,CAAA,EAAI,CACjDA,EAAQ,UAAYC,EAAkB,gBAAgBD,EAAQ,SAAA,EAE9D,MAAMA,CAAA,EAEN,KAAK,mBAAqBA,EAAQ,oBAAsB,GAMxD,KAAK,QAAQ,KAAKJ,EAAiB,sCAAA,EASrC,MAAM,QAAQM,EAAkBV,EAA6C,CAC3E,IAAMW,EAAkB,MAAMX,EAAQ,mBAAA,EAEtC,GAAIW,EACF,OAAOA,EAGT,IAAML,EAAW,MAAMN,EAAQ,WAAWU,CAAA,EAE1C,OAAIJ,IAMAN,EAAQ,OAASA,EAAQ,MAAM,OAAS,UACnC,MAAM,KAAK,eAAeU,EAASV,CAAA,EAKrC,MAAM,KAAK,aAAaU,EAASV,CAAA,GAG1C,MAAM,aAAaU,EAAkBV,EAA6C,CAChF,IAAIM,EAEEM,EAAUZ,EAAQ,QAAU,CAAA,EAMlC,GAAI,KAAK,mBAAoB,CAK3B,IAAMa,EAAsBD,EAAO,UAC7BE,EAAqBJ,EAAQ,UAC7BK,EAAsB,CAACD,GAAsBA,IAAuBD,EAiB1E,GAbAP,EAAW,MAAMN,EAAQ,MACvB,IAAI,QAAQU,EAAS,CACnB,UAAWA,EAAQ,OAAS,UAAYI,GAAsBD,EAAsB,MAAA,CACrF,CAAC,EAUAA,GAAuBE,GAAuBL,EAAQ,OAAS,UAAW,CAC5E,KAAK,sCAAA,EACL,IAAMM,EAAY,MAAMhB,EAAQ,SAASU,EAASJ,EAAS,MAAA,CAAO,OAUpE,OAAM,IAAIW,EAAa,yBAA0B,CAC/C,UAAW,KAAK,UAChB,IAAKP,EAAQ,IACd,EAsBH,OAAOJ,EAGT,MAAM,eAAeI,EAAkBV,EAA6C,CAClF,KAAK,sCAAA,EAEL,IAAMM,EAAW,MAAMN,EAAQ,MAAMU,CAAA,EAMrC,GAAI,CAAC,MAFmBV,EAAQ,SAASU,EAASJ,EAAS,MAAA,CAAO,EAKhE,MAAM,IAAIW,EAAa,0BAA2B,CAChD,IAAKP,EAAQ,IACb,OAAQJ,EAAS,OAClB,EAGH,OAAOA,EA8BT,uCAA8C,CAC5C,IAAIY,EAAoC,KACpCC,EAA6B,EAEjC,OAAW,CAACC,EAAOC,CAAA,IAAW,KAAK,QAAQ,QAAA,EAErCA,IAAWjB,EAAiB,yCAK5BiB,IAAWjB,EAAiB,oCAC9Bc,EAAqBE,GAGnBC,EAAO,iBACTF,KAIAA,IAA+B,EACjC,KAAK,QAAQ,KAAKf,EAAiB,iCAAA,EAC1Be,EAA6B,GAAKD,IAAuB,MAElE,KAAK,QAAQ,OAAOA,EAAoB,CAAA,ICrNjCI,GAAb,cAAqCrB,CAAM,CACzC,WACA,UAoBA,YAAYD,EAAuB,CAAE,UAAAuB,EAAY,CAAC,GAAA,EAAM,SAAAC,EAAW,CAAA,CAAE,EAAkC,CAAA,EAAI,CAgBzG,MAAOhB,GAAuC,KAAK,OAAOA,CAAA,EAAUR,CAAA,EAEpE,KAAK,WAAauB,EAClB,KAAK,UAAYC,EAUnB,OAAe,CAAE,IAAAC,EAAK,QAAAf,CAAA,EAA+C,CACnE,GAAIA,GAAWA,EAAQ,OAAS,WAC9B,MAAO,GAGT,IAAMgB,EAAoBD,EAAI,SAAWA,EAAI,OAE7C,QAAWE,KAAU,KAAK,UACxB,GAAIA,EAAO,KAAKD,CAAA,EAMd,MAAO,GAIX,MAAI,OAAK,WAAW,KAAMC,GAAWA,EAAO,KAAKD,CAAA,CAAkB,IC9F1DE,GAAA,IACJ,EAAQ,KAAK,cAAc,kBAWvBC,GAA2BC,GAA+B,CACjEF,GAAA,GACF,KAAK,iBAAiB,WAAaG,GAAU,CAC3CA,EAAM,UACJ,KAAK,aAAa,kBAAkB,OAAA,EAAS,KAAA,IAAW,CAElDD,GACG,KAAK,aAAa,kBAAkB,eAAeA,CAAA,GAM1D,KClBV,IAAaE,GAAA,CAA6BC,EAAgBC,EAAwC,CAAA,IAAY,CAG5G,QAAWC,IAAa,CAAC,GAAGF,EAAU,aAAa,KAAA,CAAM,EACnDC,EAA4B,KAAME,GAAWA,EAAO,KAAKD,CAAA,CAAU,GACrEF,EAAU,aAAa,OAAOE,CAAA,EAIlC,OAAOF,GCPT,SAAiBI,GACfC,EACA,CACE,eAAAC,EAAiB,aACjB,4BAAAL,EAA8B,CAAC,QAAS,UAAA,EACxC,UAAAM,EAAY,GACZ,gBAAAC,CAAA,EACwB,CAAA,EACQ,CAClC,IAAMR,EAAY,IAAI,IAAIK,EAAK,SAAS,IAAA,EACxCL,EAAU,KAAO,GACjB,MAAMA,EAAU,KAEhB,IAAMS,EAA0BV,GAA0BC,EAAWC,CAAA,EAGrE,GAFA,MAAMQ,EAAwB,KAE1BH,GAAkBG,EAAwB,SAAS,SAAS,GAAA,EAAM,CACpE,IAAMC,EAAe,IAAI,IAAID,EAAwB,IAAA,EACrDC,EAAa,UAAYJ,EACzB,MAAMI,EAAa,KAGrB,GAAIH,EAAW,CACb,IAAMI,EAAW,IAAI,IAAIF,EAAwB,IAAA,EACjDE,EAAS,UAAY,QACrB,MAAMA,EAAS,KAGjB,GAAIH,EAAiB,CACnB,IAAMI,EAAiBJ,EAAgB,CAAE,IAAKR,CAAA,CAAW,EACzD,QAAWa,KAAgBD,EACzB,MAAMC,EAAa,MC9BzB,IAAaC,GAAb,cAAiCC,CAAM,CAWrC,YAAYZ,EAAgBa,EAAuBC,EAAqB,CAUtE,IAAMC,EAAA,CAA6B,CAAE,IAAAb,CAAA,IAAqC,CACxE,IAAMc,EAAShB,EAAO,KAAKE,EAAI,IAAA,EAG/B,GAAKc,GAQD,EAAAd,EAAI,SAAW,SAAS,QAAUc,EAAO,QAAU,GAcvD,OAAOA,EAAO,MAAM,CAAA,GAGtB,MAAMD,EAAOF,EAASC,CAAA,ICpDbG,GAAuBC,GAA2C,CAgC7EC,EAAW,cAAcD,CAAA,GClCrBE,GAAwB,kBAUjBC,GAAkBC,GAA4C,CACzE,GAAI,CAACA,EACH,MAAM,IAAIC,EAAa,oCAAqC,CAAE,MAAAD,CAAA,CAAO,EAKvE,GAAI,OAAOA,GAAU,SAAU,CAC7B,IAAMzB,EAAY,IAAI,IAAIyB,EAAO,SAAS,IAAA,EAC1C,MAAO,CACL,SAAUzB,EAAU,KACpB,IAAKA,EAAU,MAInB,GAAM,CAAE,SAAA2B,EAAU,IAAAtB,CAAA,EAAQoB,EAC1B,GAAI,CAACpB,EACH,MAAM,IAAIqB,EAAa,oCAAqC,CAAE,MAAAD,CAAA,CAAO,EAKvE,GAAI,CAACE,EAAU,CACb,IAAM3B,EAAY,IAAI,IAAIK,EAAK,SAAS,IAAA,EACxC,MAAO,CACL,SAAUL,EAAU,KACpB,IAAKA,EAAU,MAMnB,IAAM4B,EAAc,IAAI,IAAIvB,EAAK,SAAS,IAAA,EACpCwB,EAAc,IAAI,IAAIxB,EAAK,SAAS,IAAA,EAC1C,OAAAuB,EAAY,aAAa,IAAIL,GAAuBI,CAAA,EAC7C,CACL,SAAUC,EAAY,KACtB,IAAKC,EAAY,OChDRC,GAAb,KAAkE,CAChE,YAAwB,CAAA,EACxB,eAA2B,CAAA,EAE3B,iBAAsD,MAAO,CAAE,QAAAC,EAAS,MAAAC,CAAA,IAA4D,CAE9HA,IACFA,EAAM,gBAAkBD,IAI5B,yBAAsE,MAAO,CAC3E,MAAAE,EACA,MAAAD,EACA,eAAAE,CAAA,IAC4D,CAC5D,GAAID,EAAM,OAAS,WACbD,GAAO,iBAAmBA,EAAM,2BAA2B,QAAS,CAEtE,IAAM3B,EAAM2B,EAAM,gBAAgB,IAE9BE,EACF,KAAK,eAAe,KAAK7B,CAAA,EAEzB,KAAK,YAAY,KAAKA,CAAA,EAI5B,OAAO6B,IC1BEC,GAAA,CAAcC,EAAuDpB,EAAwBC,IAA+B,CACvI,GAAI,OAAOmB,GAAY,SAAU,CAC/B,IAAMC,EAAa,IAAI,IAAID,EAAS,SAAS,IAAA,EAwBvCE,EAAA,CAAqC,CAAE,IAAAjC,CAAA,IASpCA,EAAI,OAASgC,EAAW,KAIjC,OAAO,IAAItB,EAAMuB,EAAetB,EAAUC,CAAA,EAE5C,GAAImB,aAAmB,OAErB,OAAO,IAAItB,GAAYsB,EAASpB,EAAUC,CAAA,EAE5C,GAAI,OAAOmB,GAAY,WAErB,OAAO,IAAIrB,EAAMqB,EAASpB,EAAUC,CAAA,EAEtC,GAAImB,aAAmBrB,EACrB,OAAOqB,EAET,MAAM,IAAIV,EAAa,yBAA0B,CAC/C,WAAY,UACZ,SAAU,aACV,UAAW,UACZ,GI7DH,IAAaa,GAAW,MAAaC,EAAeC,EAAqBC,IAAgD,CACvH,IAAMC,EAAOF,EAAM,IAAA,CAAKG,EAAMC,KAAW,CACvC,MAAAA,EACA,KAAAD,GACD,EAEKE,EAAY,MAAOC,GAA0C,CACjE,IAAMC,EAA2B,CAAA,EACjC,OAAa,CACX,IAAMC,EAAON,EAAK,IAAA,EAClB,GAAI,CAACM,EACH,OAAOF,EAAIC,CAAA,EAEb,IAAME,EAAS,MAAMR,EAAKO,EAAK,IAAA,EAC/BD,EAAQ,KAAK,CACH,OAAAE,EACR,MAAOD,EAAK,MACb,IAICE,EAAS,MAAM,KAAK,CAAE,OAAQX,CAAA,EAAO,IAAQ,IAAI,QAAQM,CAAA,CAAU,EAMzE,OAJiB,MAAM,QAAQ,IAAIK,CAAA,GAChC,KAAA,EACA,KAAA,CAAMC,EAAGC,IAAOD,EAAE,MAAQC,EAAE,MAAQ,GAAK,CAAA,EACzC,IAAKN,GAAQA,EAAI,MAAA,GSdtB,IAAMO,GAAW,OAAO,UAAc,KAAe,iCAAiC,KAAK,UAAU,SAAA,EIdrG,IAAMC,GAAU,qBACVC,EAAqB,gBAErBC,GAAgBC,GAA4B,CAChD,IAAMC,EAAM,IAAI,IAAID,EAAiB,SAAS,IAAA,EAC9C,OAAAC,EAAI,KAAO,GAEJA,EAAI,MAuBAC,GAAb,KAAkC,CAChC,WACA,IAAkD,KAQlD,YAAYC,EAAmB,CAC7B,KAAK,WAAaA,EAUpB,OAAeF,EAAqB,CAClC,MAAO,GAAG,KAAK,UAAA,IAAcF,GAAaE,CAAA,CAAI,GAUhD,WAAmBG,EAAiC,CAClD,IAAMC,EAAWD,EAAG,kBAAkBN,EAAoB,CACxD,QAAS,IAAA,CACV,EAKDO,EAAS,YAAY,YAAa,YAAa,CAAE,OAAQ,EAAA,CAAO,EAChEA,EAAS,YAAY,YAAa,YAAa,CAAE,OAAQ,EAAA,CAAO,EAUlE,0BAAkCD,EAAiC,CACjE,KAAK,WAAWA,CAAA,EACZ,KAAK,YACFE,GAAS,KAAK,UAAA,EAUvB,MAAM,aAAaL,EAAaM,EAAkC,CAChEN,EAAMF,GAAaE,CAAA,EAEnB,IAAMO,EAAQ,CACZ,GAAI,KAAK,OAAOP,CAAA,EAChB,UAAW,KAAK,WAChB,IAAAA,EACA,UAAAM,GAGIE,GAAK,MADM,KAAK,MAAA,GACR,YAAYX,EAAoB,YAAa,CACzD,WAAY,SAAA,CACb,EACD,MAAMW,EAAG,MAAM,IAAID,CAAA,EACnB,MAAMC,EAAG,KAUX,MAAM,aAAaR,EAA0C,CAG3D,OAAO,MADa,MADH,KAAK,MAAA,GACC,IAAIH,EAAoB,KAAK,OAAOG,CAAA,CAAI,IACjD,UAahB,MAAM,cAAcS,EAAsBC,EAAsC,CAE9E,IAAIC,EAAS,MAAM,MADF,KAAK,MAAA,GACA,YAAYd,EAAoB,WAAA,EAAa,MAAM,MAAM,WAAA,EAAa,WAAW,KAAM,MAAA,EACvGe,EAAwB,CAAA,EAC1BC,EAAyB,EAC7B,KAAOF,GAAQ,CACb,IAAMG,EAASH,EAAO,MAGlBG,EAAO,YAAc,KAAK,aAGvBL,GAAgBK,EAAO,UAAYL,GAAkBC,GAAYG,GAA0BH,GAC9FC,EAAO,OAAA,EACPC,EAAY,KAAKE,EAAO,GAAA,GAExBD,KAGJF,EAAS,MAAMA,EAAO,SAAA,EAGxB,OAAOC,EAQT,MAAc,OAAQ,CACpB,OAAK,KAAK,MACR,KAAK,IAAM,MAAMG,EAAOnB,GAAS,EAAG,CAClC,QAAS,KAAK,0BAA0B,KAAK,IAAA,CAAK,CACnD,GAEI,KAAK,MCnJHoB,GAAb,KAA6B,CAC3B,WAAqB,GACrB,gBAA0B,GAC1B,YACA,eACA,cACA,WACA,gBASA,YAAYd,EAAmBe,EAAgC,CAAA,EAAI,CAoCjE,KAAK,YAAcA,EAAO,WAC1B,KAAK,eAAiBA,EAAO,cAC7B,KAAK,cAAgBA,EAAO,aAC5B,KAAK,WAAaf,EAClB,KAAK,gBAAkB,IAAID,GAAqBC,CAAA,EAMlD,MAAM,eAA+B,CACnC,GAAI,KAAK,WAAY,CACnB,KAAK,gBAAkB,GACvB,OAEF,KAAK,WAAa,GAElB,IAAMO,EAAe,KAAK,eAAiB,KAAK,IAAA,EAAQ,KAAK,eAAiB,IAAO,EAE/ES,EAAc,MAAM,KAAK,gBAAgB,cAAcT,EAAc,KAAK,WAAA,EAG1EU,EAAQ,MAAM,KAAK,OAAO,KAAK,KAAK,UAAA,EAC1C,QAAWnB,KAAOkB,EAChB,MAAMC,EAAM,OAAOnB,EAAK,KAAK,aAAA,EAqB/B,KAAK,WAAa,GACd,KAAK,kBACP,KAAK,gBAAkB,GAClB,KAAK,cAAA,GAUd,MAAM,gBAAgBA,EAA4B,CAUhD,MAAM,KAAK,gBAAgB,aAAaA,EAAK,KAAK,IAAA,CAAK,EAczD,MAAM,aAAaA,EAA+B,CAChD,GAAI,CAAC,KAAK,eAOR,MAAO,GAET,IAAMM,EAAY,MAAM,KAAK,gBAAgB,aAAaN,CAAA,EACpDoB,EAAkB,KAAK,IAAA,EAAQ,KAAK,eAAiB,IAC3D,OAAOd,IAAc,OAAYA,EAAYc,EAAkB,GAMjE,MAAM,QAAwB,CAG5B,KAAK,gBAAkB,GACvB,MAAM,KAAK,gBAAgB,cAAc,OAAO,iBAAA,IC3KvCC,GAA8BC,GAA6B,CAStEC,EAAoB,IAAID,CAAA,GCwCbE,EAAb,KAAuD,CACrD,QACA,kBAKA,YAAYP,EAAkC,CAAA,EAAI,CAsChD,KAAK,QAAUA,EACf,KAAK,kBAAoB,IAAI,IAExB,KAAK,QAAQ,aAChB,KAAK,QAAQ,WAAa,gBAGxB,KAAK,QAAQ,mBACfI,GAAA,IAAiC,KAAK,uBAAA,CAAwB,EAYlE,oBAA4BnB,EAAoC,CAC9D,GAAIA,IAAcuB,EAAkB,eAAA,EAClC,MAAM,IAAIC,EAAa,2BAAA,EAGzB,IAAIC,EAAkB,KAAK,kBAAkB,IAAIzB,CAAA,EACjD,OAAKyB,IACHA,EAAkB,IAAIX,GAAgBd,EAAW,KAAK,OAAA,EACtD,KAAK,kBAAkB,IAAIA,EAAWyB,CAAA,GAEjCA,EAeT,yBAAyB,CAAE,MAAAC,EAAO,UAAA1B,EAAW,QAAA2B,EAAS,eAAAC,CAAA,EAAyD,CAC7G,GAAI,CAACA,EACH,OAAO,KAGT,IAAMC,EAAU,KAAK,qBAAqBD,CAAA,EAIpCH,EAAkB,KAAK,oBAAoBzB,CAAA,EAE3C8B,EAAuB,KAAK,QAAQ,aAAe,YAEnDC,GAAQ,SAAY,CAMpBD,GACF,MAAML,EAAgB,gBAAgBE,EAAQ,GAAA,EAEhD,MAAMF,EAAgB,cAAA,MAExB,GAAI,CACFC,EAAM,UAAUK,CAAA,OACV,EAQR,OAAOF,EAAUD,EAAiB,KAQpC,qBAA6BA,EAAmC,CAI9D,GAH6B,KAAK,QAAQ,aAAe,YAIvD,MAAO,GAET,IAAMI,EAAM,KAAK,IAAA,EACjB,GAAI,CAAC,KAAK,QAAQ,cAChB,MAAO,GAKT,IAAMC,EAAsB,KAAK,wBAAwBL,CAAA,EACzD,OAAIK,IAAwB,KAEnB,GAIFA,GAAuBD,EAAM,KAAK,QAAQ,cAAgB,IAUnE,wBAAgCJ,EAAyC,CACvE,GAAI,CAACA,EAAe,QAAQ,IAAI,MAAA,EAC9B,OAAO,KAGT,IAAMM,EAAaN,EAAe,QAAQ,IAAI,MAAA,EAExCO,EAAa,IADI,KAAKD,CAAA,EACE,QAAA,EAI9B,OAAI,OAAO,MAAMC,CAAA,EACR,KAGFA,EAUT,MAAM,eAAe,CAAE,UAAAnC,EAAW,QAAA2B,CAAA,EAAwC,CAgBxE,IAAMF,EAAkB,KAAK,oBAAoBzB,CAAA,EACjD,MAAMyB,EAAgB,gBAAgBE,EAAQ,GAAA,EAC9C,MAAMF,EAAgB,cAAA,EAexB,MAAM,wBAAwC,CAG5C,OAAW,CAACzB,EAAWyB,CAAA,IAAoB,KAAK,kBAC9C,MAAM,KAAK,OAAO,OAAOzB,CAAA,EACzB,MAAMyB,EAAgB,OAAA,EAIxB,KAAK,kBAAoB,IAAI,MClSpBW,GAAa,2BACbC,GAAqB,KAYrBC,GAAsB,qBCuC7BC,GAAwBxB,GACrB,MAAO,CAAE,MAAAyB,CAAA,IAA4C,CAC1D,IAAInC,EACJ,KAAQA,EAAQ,MAAMmC,EAAM,aAAA,GAAiB,CAC3C,GAAM,CAAE,QAAAb,EAAS,UAAAvB,CAAA,EAAcC,EACzBP,EAAM,IAAI,IAAI6B,EAAQ,GAAA,EAE5B,GAAI,CAGF,IAAMc,EAASd,EAAQ,SAAW,OAAS,IAAI,gBAAgB,MAAMA,EAAQ,MAAA,EAAQ,KAAA,CAAM,EAAI7B,EAAI,aAI7F4C,EAAkBtC,GAAc,OAAOqC,EAAO,IAAI,IAAA,CAAK,GAAK,GAC5DE,EAAY,KAAK,IAAA,EAAQD,EAM/B,GAHAD,EAAO,IAAI,KAAM,OAAOE,CAAA,CAAU,EAG9B5B,EAAO,mBACT,QAAW6B,KAAS,OAAO,KAAK7B,EAAO,kBAAA,EAAqB,CAC1D,IAAM8B,EAAQ9B,EAAO,mBAAmB6B,CAAA,EACxCH,EAAO,IAAIG,EAAOC,CAAA,EAKlB,OAAO9B,EAAO,WAAc,YAC9BA,EAAO,UAAU,KAAK,KAAM0B,CAAA,EAK9B,MAAM,MACJ,IAAI,QAAQ3C,EAAI,OAASA,EAAI,SAAU,CACrC,KAAM2C,EAAO,SAAA,EACb,OAAQ,OACR,KAAM,OACN,YAAa,OACb,QAAS,CAAE,eAAgB,YAAA,EAC5B,CAAC,QAMGK,EAAK,CACZ,YAAMN,EAAM,eAAenC,CAAA,EAKrByC,KAgBRC,GAAuBC,GAAuC,CAClE,IAAMC,EAAA,CAAS,CAAE,IAAAnD,CAAA,IAAqCA,EAAI,WAAA,4BAAsCwC,GAAoB,KAAKxC,EAAI,QAAA,EAEvHoD,EAAU,IAAIC,EAAY,CAC9B,QAAS,CAACH,CAAA,CAAa,CACxB,EAED,MAAO,CAAC,IAAII,EAAMH,EAAOC,EAAS,KAAA,EAAQ,IAAIE,EAAMH,EAAOC,EAAS,MAAA,CAAO,GAUvEG,GAA0BrD,GAAsB,CACpD,IAAMiD,EAAA,CAAS,CAAE,IAAAnD,CAAA,IAAqCA,EAAI,WAAA,4BAAsCA,EAAI,WAAA,gBAIpG,OAAO,IAAIsD,EAAMH,EAAO,IAFJK,EAAa,CAAE,UAAAtD,CAAA,CAAW,EAEb,KAAA,GAU7BuD,GAAqBvD,GAAsB,CAC/C,IAAMiD,EAAA,CAAS,CAAE,IAAAnD,CAAA,IAAqCA,EAAI,WAAA,4BAAyBA,EAAI,WAAA,WAIvF,OAAO,IAAIsD,EAAMH,EAAO,IAFJK,EAAa,CAAE,UAAAtD,CAAA,CAAW,EAEb,KAAA,GAU7BwD,GAAoBxD,GAAsB,CAC9C,IAAMiD,EAAA,CAAS,CAAE,IAAAnD,CAAA,IAAqCA,EAAI,WAAA,4BAAyBA,EAAI,WAAA,UAIvF,OAAO,IAAIsD,EAAMH,EAAO,IAFJK,EAAa,CAAE,UAAAtD,CAAA,CAAW,EAEb,KAAA,GAQtByD,GAAA,CAA6B,CAAE,QAAAC,EAAS,UAAA1D,EAAW,GAAG2D,CAAA,IAAsD,CACvH,IAAMC,EAAoBrC,EAAkB,uBAAuBvB,CAAA,EAE7DgD,EAAe,IAAIa,GAAqBzB,GAAY,CACxD,iBAAkBC,GAClB,OAAQE,GAAqBoB,CAAA,EAC9B,EAEKG,EAAS,CACbN,GAAiBI,CAAA,EACjBP,GAAuBO,CAAA,EACvBL,GAAkBK,CAAA,EAClB,GAAGb,GAAoBC,CAAA,GAGzB,QAAWe,KAASD,EAClBJ,EAAQ,cAAcK,CAAA,GCnKbC,GAAb,KAA6D,CAC3D,cACA,SAOA,YAAY,CAAE,aAAAC,EAAc,QAAAP,CAAA,EAA0C,CACpE,KAAK,cAAgBO,EACrB,KAAK,SAAWP,EAQlB,MAAM,gBAAgBd,EAAqC,CACzD,QAAWsB,KAAY,KAAK,cAC1B,GAAI,OAAOA,GAAa,SAAU,CAChC,IAAMC,EAAmB,MAAM,KAAK,SAAS,cAAcD,CAAA,EAC3D,GAAIC,IAAqB,OACvB,OAAOA,UAEAD,EAAS,QAAQtB,CAAA,EAAQ,CAClC,IAAMuB,EAAmB,MAAM,KAAK,SAAS,cAAcD,EAAS,GAAA,EACpE,GAAIC,IAAqB,OACvB,OAAOA,KCpDJC,GAAA,CAAgCC,EAAYC,EAAgBC,IAAiD,CASxH,IAAMC,EAAWH,EAAK,KAEtB,GAAKE,GAAOA,EAAMC,GAAcF,GAASA,EAAQ,EAC/C,MAAM,IAAI9C,EAAa,wBAAyB,CAC9C,KAAMgD,EACN,IAAAD,EACA,MAAAD,EACD,EAGH,IAAIG,EACAC,EAEJ,OAAIJ,IAAU,QAAaC,IAAQ,QACjCE,EAAiBH,EAEjBI,EAAeH,EAAM,GACZD,IAAU,QAAaC,IAAQ,QACxCE,EAAiBH,EACjBI,EAAeF,GACND,IAAQ,QAAaD,IAAU,SACxCG,EAAiBD,EAAWD,EAC5BG,EAAeF,GAGV,CACL,MAAOC,EACP,IAAKC,ICtCIC,GACXC,GAIG,CASH,IAAMC,EAAwBD,EAAY,KAAA,EAAO,YAAA,EACjD,GAAI,CAACC,EAAsB,WAAW,QAAA,EACpC,MAAM,IAAIrD,EAAa,qBAAsB,CAAE,sBAAAqD,CAAA,CAAuB,EAMxE,GAAIA,EAAsB,SAAS,GAAA,EACjC,MAAM,IAAIrD,EAAa,oBAAqB,CAAE,sBAAAqD,CAAA,CAAuB,EAGvE,IAAMC,EAAa,cAAc,KAAKD,CAAA,EAEtC,GAAI,CAACC,GAAc,EAAEA,EAAW,CAAA,GAAMA,EAAW,CAAA,GAC/C,MAAM,IAAItD,EAAa,uBAAwB,CAAE,sBAAAqD,CAAA,CAAuB,EAG1E,MAAO,CACL,MAAOC,EAAW,CAAA,IAAO,GAAK,OAAY,OAAOA,EAAW,CAAA,CAAA,EAC5D,IAAKA,EAAW,CAAA,IAAO,GAAK,OAAY,OAAOA,EAAW,CAAA,CAAA,ICtBjDC,GAAwB,MAAOpD,EAAkBqD,IAAkD,CAC9G,GAAI,CAeF,GAAIA,EAAiB,SAAW,IAG9B,OAAOA,EAGT,IAAMJ,EAAcjD,EAAQ,QAAQ,IAAI,OAAA,EACxC,GAAI,CAACiD,EACH,MAAM,IAAIpD,EAAa,iBAAA,EAGzB,IAAMyD,EAAaN,GAAiBC,CAAA,EAC9BM,EAAe,MAAMF,EAAiB,KAAA,EAEtCG,EAAsBf,GAA6Bc,EAAcD,EAAW,MAAOA,EAAW,GAAA,EAE9FG,EAAaF,EAAa,MAAMC,EAAoB,MAAOA,EAAoB,GAAA,EAC/EE,EAAiBD,EAAW,KAE5BE,EAAiB,IAAI,SAASF,EAAY,CAG9C,OAAQ,IACR,WAAY,kBACZ,QAASJ,EAAiB,QAC3B,EAED,OAAAM,EAAe,QAAQ,IAAI,iBAAkB,OAAOD,CAAA,CAAe,EACnEC,EAAe,QAAQ,IAAI,gBAAiB,SAASH,EAAoB,KAAA,IAASA,EAAoB,IAAM,CAAA,IAAUD,EAAa,IAAA,EAAA,EAE5HI,OACO,CAUd,OAAO,IAAI,SAAS,GAAI,CACtB,OAAQ,IACR,WAAY,wBACb,ICzEQC,EAAb,KAA0D,CAQxD,yBAAsE,MAAO,CAAE,QAAA5D,EAAS,eAAAC,CAAA,IAGlFA,GAAkBD,EAAQ,QAAQ,IAAI,OAAA,EACjC,MAAMoD,GAAsBpD,EAASC,CAAA,EAKvCA,GCRE4D,EAAb,cAAgCC,CAAS,CAOvC,MAAM,QAAQ9D,EAAkBuB,EAA6C,CAC3E,IAAMwC,EAAO,CAAA,EAWTC,EAAW,MAAMzC,EAAQ,WAAWvB,CAAA,EAEpCiE,EACJ,GAAI,CAACD,EAIH,GAAI,CACFA,EAAW,MAAMzC,EAAQ,iBAAiBvB,CAAA,QACnCmB,EAAK,CACRA,aAAe,QACjB8C,EAAQ9C,GA0Bd,GAAI,CAAC6C,EACH,MAAM,IAAInE,EAAa,cAAe,CAAE,IAAKG,EAAQ,IAAK,MAAAiE,EAAO,EAEnE,OAAOD,IElDX,IAAaE,EAAb,cAA0CC,CAAS,CAIjD,YAAYC,EAA2B,CAAA,EAAI,CACzC,MAAMA,CAAA,EAID,KAAK,QAAQ,KAAMC,GAAM,oBAAqBA,CAAA,GACjD,KAAK,QAAQ,QAAQC,CAAA,EAUzB,MAAM,QAAQC,EAAkBC,EAA6C,CAC3E,IAAMC,EAAO,CAAA,EAWPC,EAAuBF,EAAQ,iBAAiBD,CAAA,EAAS,MAAA,IAAY,CAAA,CAAA,EAItEC,EAAQ,UAAUE,CAAA,EAEvB,IAAIC,EAAW,MAAMH,EAAQ,WAAWD,CAAA,EAEpCK,EACJ,GAAI,CAAAD,EAQF,GAAI,CAGFA,EAAY,MAAMD,QACXG,EAAK,CACRA,aAAe,QACjBD,EAAQC,GAcd,GAAI,CAACF,EACH,MAAM,IAAIG,EAAa,cAAe,CAAE,IAAKP,EAAQ,IAAK,MAAAK,EAAO,EAEnE,OAAOD,ICxFEI,GAAb,cAAmCC,CAAM,CAMvC,YAAYC,EAAkBb,EAAgC,CAC5D,IAAMc,EAAA,CAA6B,CAAE,QAAAX,CAAA,IAAyC,CAC5E,IAAMY,EAAkBF,EAAQ,sBAAA,EAChC,QAAWG,KAAeC,GAAsBd,EAAQ,IAAKH,CAAA,EAAU,CACrE,IAAMkB,EAAWH,EAAgB,IAAIC,CAAA,EACrC,GAAIE,EAEF,MAAO,CAAE,SAAAA,EAAU,UADDL,EAAQ,2BAA2BK,CAAA,KAU3D,MAAMJ,EAAOD,EAAQ,gBAAA,ICxBZM,GAAb,KAA6D,CAC3D,oBAEA,YAAY,CAAE,mBAAAC,CAAA,EAAuD,CACnE,KAAK,oBAAsBA,EAG7B,mBAA0D,MAAO,CAAE,QAAAjB,EAAS,OAAAkB,CAAA,IAA+D,CAEzI,IAAMH,EAAWG,GAAQ,UAAY,KAAK,oBAAoB,qBAAqBlB,EAAQ,GAAA,EAE3F,OAAOe,EAAW,IAAI,QAAQA,EAAU,CAAE,QAASf,EAAQ,OAAA,CAAS,EAAIA,ICtB/DmB,GAAA,CAAwBT,EAAkBU,EAAmC,CAAA,IAAO,CAC/F,GAAM,CACJ,UAAWC,EACX,QAASC,EAAkB,CAAA,EAC3B,aAAcC,EACd,aAAcC,EACd,kBAAmBC,EACnB,eAAgBC,EAChB,4BAA6BC,EAC7B,UAAWC,EACX,gBAAiBC,EACjB,sBAAAC,EACA,YAAAC,EAAc,GACd,iBAAAC,EACA,0BAAAC,EACA,yBAAAC,CAAA,EACEd,GAAmB,CAAA,EAEvB,MAAO,CACL,wBAAyB,CACvB,UAAWe,EAAkB,gBAAgBd,CAAA,EAC7C,QAAS,CAAC,GAAGC,EAAiB,IAAIN,GAAuB,CAAE,mBAAoBN,CAAA,CAAS,CAAC,EACzF,aAAca,EACd,aAAcC,EACd,kBAAmBC,GAErB,qBAAsB,CACpB,eAAgBC,EAChB,4BAA6BC,EAC7B,UAAWC,EACX,gBAAiBC,GAEnB,oBAAqB,CACnB,sBAAAC,EACA,YAAAC,EACA,iBAAAC,EACA,0BAAAC,EACA,yBAAAC,KCgGOE,GAAb,KAAqB,CACnB,iBAAyD,IAAI,IAC7D,kBAAqI,IAAI,IACzI,wBAAgE,IAAI,IACpE,sBACA,kBACA,QACA,mBACA,cACA,cAEA,YAAY,CACV,gBAAAC,EACA,gBAAAjB,EACA,YAAAkB,EAAc,GACd,cAAAC,EACA,kBAAAC,EAAoB,GACpB,QAAAC,EACA,aAAAC,EAAe,GACf,eAAAC,EACA,uBAAAC,EACA,eAAAC,EAAiB,GACjB,UAAAC,EACA,aAAAC,CAAA,EACkB,CAAA,EAAI,CACtB,GAAM,CAAE,wBAAAC,EAAyB,qBAAAC,EAAsB,oBAAAC,CAAA,EAAwB/B,GAAqB,KAAMC,CAAA,EAiE1G,GA/DA,KAAK,sBAAwB8B,EAAoB,YACjD,KAAK,kBAAoB,IAAIC,GAAiBH,CAAA,EAC9C,KAAK,QAAU,IAAI,IACnB,KAAK,mBAAqB,IAAI,IAC9B,KAAK,cAAgBD,EAErB,KAAK,cAAgB,KAAK,cAAc,KAAK,IAAA,EAC7C,KAAK,eAAiB,KAAK,eAAe,KAAK,IAAA,EAC/C,KAAK,YAAc,KAAK,YAAY,KAAK,IAAA,EACzC,KAAK,YAAc,KAAK,YAAY,KAAK,IAAA,EAEnCR,GAAiBA,EAAc,OAAS,GAAG,KAAK,cAAc,GAAGA,CAAA,EAEnEC,GAAmBY,GAAA,EAEnBX,IAAY,QACdY,GAAoB,CAClB,OAAQZ,CAAA,CACT,EAGCH,EACF,KAAK,YAAA,EAEL,KAAK,iBAAiB,UAAYgB,GAAU,CACtCA,EAAM,MAAQA,EAAM,KAAK,OAAS,gBACpC,KAAK,YAAA,IAKPC,GAAcA,GAAA,EAEZlB,GAAmBA,EAAgB,OAAS,GAChD,KAAK,kBAAkBA,CAAA,EAGrBa,EAAoB,uBACtBpB,GAA0BkB,EAAwB,SAAA,EAGpD,KAAK,cAAc,IAAIxC,GAAc,KAAMyC,CAAA,CAAqB,EAE5DC,EAAoB,kBACtB,KAAK,cACH,IAAIM,GAAgB,KAAK,wBAAwBN,EAAoB,gBAAA,EAAmB,CACtF,UAAWA,EAAoB,0BAC/B,SAAUA,EAAoB,yBAC/B,CAAC,EAIFN,IAA2B,SACzB,OAAOA,GAA2B,UACpCA,GAA0Ba,GAA0B,CAAE,QAAS,IAAA,CAAM,EAErEA,GAA0B,CACxB,GAAGb,EACH,QAAS,KACV,GAIDD,IAAmB,OAAW,CAChC,GAAIG,IAAc,OAAW,CAC3B,IAAMY,EAAiB,IAAIC,GAAuB,CAChD,aAAcb,EAAU,QACxB,QAAS,KACV,EAEDH,EAAe,QAASiB,GAAe,CAEnCA,EAAW,mBAAmBhE,GAE9B,CAACgE,EAAW,QAAQ,QAAQ,KAAMC,IAAW,oBAAqBA,EAAA,GAElED,EAAW,QAAQ,QAAQ,KAAKF,CAAA,IAItC,QAAWI,KAASnB,EAClB,KAAK,gBAAgBmB,EAAM,QAASA,EAAM,QAASA,EAAM,MAAA,EAIzDC,GAAgBA,GAAA,EAMtB,IAAI,kBAA6B,CAC/B,OAAO,KAAK,kBAMd,IAAI,QAAmC,CACrC,OAAO,KAAK,QAMd,mBAAoB,CAClB,KAAK,iBAAiB,UAAW,KAAK,aAAA,EACtC,KAAK,iBAAiB,WAAY,KAAK,cAAA,EACvC,KAAK,iBAAiB,QAAS,KAAK,WAAA,EACpC,KAAK,iBAAiB,UAAW,KAAK,WAAA,EAQxC,kBAAkBC,EAA2C,CAU3D,IAAMC,EAA4B,CAAA,EAClC,QAAWH,KAASE,EAAS,CAEvB,OAAOF,GAAU,SACnBG,EAAgB,KAAKH,CAAA,EACZA,GAAS,CAACA,EAAM,WAAaA,EAAM,WAAa,QACzDG,EAAgB,KAAKH,EAAM,GAAA,EAG7B,GAAM,CAAE,SAAA/C,EAAU,IAAAmD,CAAA,EAAQC,GAAeL,CAAA,EACnCM,EAAY,OAAON,GAAU,UAAYA,EAAM,SAAW,SAAW,UAE3E,GAAI,KAAK,iBAAiB,IAAII,CAAA,GAAQ,KAAK,iBAAiB,IAAIA,CAAA,IAASnD,EACvE,MAAM,IAAIR,EAAa,wCAAyC,CAC9D,WAAY,KAAK,iBAAiB,IAAI2D,CAAA,EACtC,YAAanD,EACd,EAGH,GAAI,OAAO+C,GAAU,UAAYA,EAAM,UAAW,CAChD,GAAI,KAAK,wBAAwB,IAAI/C,CAAA,GAAa,KAAK,wBAAwB,IAAIA,CAAA,IAAc+C,EAAM,UACrG,MAAM,IAAIvD,EAAa,4CAA6C,CAClE,IAAA2D,CAAA,CACD,EAEH,KAAK,wBAAwB,IAAInD,EAAU+C,EAAM,SAAA,EAGnD,KAAK,iBAAiB,IAAII,EAAKnD,CAAA,EAC/B,KAAK,kBAAkB,IAAImD,EAAKE,CAAA,EAElC,GAAIH,EAAgB,OAAS,EAAG,CAC9B,IAAMI,EAAiB,qDAAqDJ,EAAgB,KAC1F,IAAA,CACD;sEAIC,QAAQ,KAAKI,CAAA,GAiBnB,cAAcf,EAA6C,CACpD,YAAK,qBAAqBA,CAAA,EAExBgB,EAAyBhB,EAAO,SAAY,CACjD,IAAMiB,EAAsB,IAAIC,GAChC,KAAK,iBAAiB,QAAQ,KAAKD,CAAA,EAEnC,MAAME,GAAS,KAAK,sBAAuB,MAAM,KAAK,KAAK,iBAAiB,QAAA,CAAS,EAAG,MAAO,CAACP,EAAKnD,CAAA,IAA6B,CAChI,IAAM2D,EAAY,KAAK,wBAAwB,IAAI3D,CAAA,EAC7CqD,EAAY,KAAK,kBAAkB,IAAIF,CAAA,EAEvClE,EAAU,IAAI,QAAQkE,EAAK,CAC/B,UAAAQ,EACA,MAAON,EACP,YAAa,cACd,EAED,MAAM,QAAQ,IACZ,KAAK,iBAAiB,UAAU,CAC9B,MAAAd,EACA,QAAAtD,EACA,IAAK,IAAI,IAAIA,EAAQ,GAAA,EACrB,OAAQ,CAAE,SAAAe,CAAA,EACX,CAAC,IAIN,GAAM,CAAE,YAAA4D,EAAa,eAAAC,CAAA,EAAmBL,EAMxC,MAAO,CAAE,YAAAI,EAAa,eAAAC,KAW1B,MAAM,qBAAqBtB,EAAoC,CAC7D,GAAK,KAAK,eAKLA,GAAO,UAUZ,GAAI,CASF,MAAMA,EAAM,UAAU,KAAK,aAAA,EAG3B,KAAK,cAAgB,aACdjD,EAAO,CAQd,MAAMA,GAcV,eAAeiD,EAAgD,CAC7D,OAAOgB,EAAyBhB,EAAO,SAAY,CACjD,IAAMuB,EAAQ,MAAM,KAAK,OAAO,KAAK,KAAK,iBAAiB,SAAA,EACrDC,EAA0B,MAAMD,EAAM,KAAA,EACtCE,EAAoB,IAAI,IAAI,KAAK,iBAAiB,OAAA,CAAQ,EAE1DC,EAAiC,CAAA,EAEvC,QAAWhF,KAAW8E,EACfC,EAAkB,IAAI/E,EAAQ,GAAA,IACjC,MAAM6E,EAAM,OAAO7E,CAAA,EACnBgF,EAAqB,KAAKhF,EAAQ,GAAA,GAQtC,MAAO,CAAE,qBAAAgF,CAAA,IASb,YAAY1B,EAAmB,CAC7B,GAAM,CAAE,QAAAtD,CAAA,EAAYsD,EACd2B,EAAkB,KAAK,cAAc,CAAE,QAAAjF,EAAS,MAAAsD,EAAO,EACzD2B,GACF3B,EAAM,YAAY2B,CAAA,EAUtB,YAAY3B,EAA+B,CACzC,GAAIA,EAAM,MAAQA,EAAM,KAAK,OAAS,aAAc,CAClD,GAAM,CAAE,QAAA4B,CAAA,EAAkC5B,EAAM,KAM1C6B,EAAkB,QAAQ,IAC9BD,EAAQ,YAAY,IAAKpB,GAA2C,CAClE,IAAI9D,EACJ,OAAI,OAAO8D,GAAU,SACnB9D,EAAU,IAAI,QAAQ8D,CAAA,EAEtB9D,EAAU,IAAI,QAAQ,GAAG8D,CAAA,EAEpB,KAAK,cAAc,CAAE,QAAA9D,EAAS,MAAAsD,EAAO,GAC5C,EAGJA,EAAM,UAAU6B,CAAA,EAGZ7B,EAAM,QAAQ,CAAA,GACX6B,EAAgB,KAAA,IAAW7B,EAAM,MAAM,CAAA,EAAG,YAAY,EAAA,CAAK,GAkBtE,kBAAkBrD,EAAuBmF,EAAA,MAA0C,CACjF,KAAK,mBAAmB,IAAIA,EAAQC,EAAiBpF,CAAA,CAAQ,EAU/D,gBAAgBA,EAA6B,CAC3C,KAAK,cAAgBoF,EAAiBpF,CAAA,EAaxC,gBACEqF,EACArF,EACAmF,EACO,CACP,IAAMG,EAAQC,GAAWF,EAASrF,EAASmF,CAAA,EAC3C,YAAK,cAAcG,CAAA,EACZA,EAQT,cAAcA,EAAoB,CAsC3B,KAAK,QAAQ,IAAIA,EAAM,MAAA,GAC1B,KAAK,QAAQ,IAAIA,EAAM,OAAQ,CAAA,CAAE,EAKnC,KAAK,QAAQ,IAAIA,EAAM,MAAA,EAAS,KAAKA,CAAA,EAQvC,gBAAgBA,EAAoB,CAClC,GAAI,CAAC,KAAK,QAAQ,IAAIA,EAAM,MAAA,EAC1B,MAAM,IAAIhF,EAAa,6CAA8C,CACnE,OAAQgF,EAAM,MAAA,CACf,EAGH,IAAME,EAAa,KAAK,QAAQ,IAAIF,EAAM,MAAA,EAAS,QAAQA,CAAA,EAC3D,GAAIE,EAAa,GACf,KAAK,QAAQ,IAAIF,EAAM,MAAA,EAAS,OAAOE,EAAY,CAAA,MAEnD,OAAM,IAAIlF,EAAa,uCAAA,EAU3B,uBAA6C,CAC3C,OAAO,KAAK,iBASd,kBAA6B,CAC3B,MAAO,CAAC,GAAG,KAAK,iBAAiB,KAAA,CAAM,EAYzC,qBAAqB2D,EAAiC,CACpD,IAAMwB,EAAY,IAAI,IAAIxB,EAAK,SAAS,IAAA,EACxC,OAAO,KAAK,iBAAiB,IAAIwB,EAAU,IAAA,EAQ7C,2BAA2B3E,EAAsC,CAC/D,OAAO,KAAK,wBAAwB,IAAIA,CAAA,EAqB1C,MAAM,cAAcf,EAA0D,CAC5E,IAAMkE,EAAMlE,aAAmB,QAAUA,EAAQ,IAAMA,EACjDe,EAAW,KAAK,qBAAqBmD,CAAA,EAC3C,GAAInD,EAEF,OAAO,MADa,KAAK,OAAO,KAAK,KAAK,iBAAiB,SAAA,GAC9C,MAAMA,CAAA,EAYvB,wBAAwBmD,EAAmC,CACzD,IAAMnD,EAAW,KAAK,qBAAqBmD,CAAA,EAC3C,GAAI,CAACnD,EACH,MAAM,IAAIR,EAAa,oBAAqB,CAAE,IAAA2D,CAAA,CAAK,EAErD,OAAQrE,IACNA,EAAQ,QAAU,IAAI,QAAQqE,CAAA,EAC9BrE,EAAQ,OAAS,CAAE,SAAAkB,EAAU,GAAGlB,EAAQ,QAEjC,KAAK,iBAAiB,OAAOA,CAAA,GAaxC,cAAc,CACZ,QAAAG,EACA,MAAAsD,CAAA,EAUgC,CAUhC,IAAMY,EAAM,IAAI,IAAIlE,EAAQ,IAAK,SAAS,IAAA,EAC1C,GAAI,CAACkE,EAAI,SAAS,WAAW,MAAA,EAI3B,OAGF,IAAMyB,EAAazB,EAAI,SAAW,SAAS,OACrC,CAAE,OAAAhD,EAAQ,MAAAqE,CAAA,EAAU,KAAK,kBAAkB,CAC/C,MAAAjC,EACA,QAAAtD,EACA,WAAA2F,EACA,IAAAzB,EACD,EACGjE,EAAUsF,GAAO,QAEfK,EAAgB,CAAA,EAahBR,EAASpF,EAAQ,OAQvB,GAPI,CAACC,GAAW,KAAK,mBAAmB,IAAImF,CAAA,IAI1CnF,EAAU,KAAK,mBAAmB,IAAImF,CAAA,GAGpC,CAACnF,EAMH,OAqBF,IAAIgF,EACJ,GAAI,CACFA,EAAkBhF,EAAQ,OAAO,CAAE,IAAAiE,EAAK,QAAAlE,EAAS,MAAAsD,EAAO,OAAApC,EAAQ,QACzDZ,EAAK,CACZ2E,EAAkB,QAAQ,OAAO3E,CAAA,EAInC,IAAMuF,EAAeN,GAAO,aAE5B,OAAIN,aAA2B,UAAY,KAAK,eAAiBY,KAC/DZ,EAAkBA,EAAgB,MAAM,MAAO3E,GAAQ,CAErD,GAAIuF,EAUF,GAAI,CACF,OAAO,MAAMA,EAAa,OAAO,CAAE,IAAA3B,EAAK,QAAAlE,EAAS,MAAAsD,EAAO,OAAApC,EAAQ,QACzD4E,EAAU,CACbA,aAAoB,QACtBxF,EAAMwF,GAKZ,GAAI,KAAK,cASP,OAAO,KAAK,cAAc,OAAO,CAAE,IAAA5B,EAAK,QAAAlE,EAAS,MAAAsD,EAAO,EAG1D,MAAMhD,KAIH2E,EAYT,kBAAkB,CAAE,IAAAf,EAAK,WAAAyB,EAAY,QAAA3F,EAAS,MAAAsD,CAAA,EAG5C,CACA,IAAMyC,EAAS,KAAK,QAAQ,IAAI/F,EAAQ,MAAA,GAAyB,CAAA,EACjE,QAAWuF,KAASQ,EAAQ,CAC1B,IAAI7E,EAEE8E,EAAcT,EAAM,MAAM,CAAE,IAAArB,EAAK,WAAAyB,EAAY,QAAA3F,EAAS,MAAAsD,EAAO,EACnE,GAAI0C,EAeF,OAAA9E,EAAS8E,GACL,MAAM,QAAQ9E,CAAA,GAAWA,EAAO,SAAW,GAGpC8E,EAAY,cAAgB,QAAU,OAAO,KAAKA,CAAA,EAAa,SAAW,GAG1E,OAAOA,GAAgB,aAIhC9E,EAAS,QAIJ,CAAE,MAAAqE,EAAO,OAAArE,GAIpB,MAAO,CAAA,ICz5BX,IAAa+E,GAAmB,CAC9BC,YAAa,qBACbC,IAAK,YACLC,KAAM,SASKC,GAQP,CACE,CACEC,QAAS,0CACTC,QAAS,IAAIC,EAAW,CACtBC,UAAW,wBACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,EACZC,cAAe,IAAM,GAAK,GAAK,GAC/BC,WAAY,YACb,CAAC,EAEL,GAEH,CACER,QAAS,6CACTC,QAAS,IAAIQ,EAAqB,CAChCN,UAAW,2BACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,EACZC,cAAe,MAAc,GAC7BC,WAAY,YACb,CAAC,EAEL,GAEH,CACER,QAAS,8CACTC,QAAS,IAAIQ,EAAqB,CAChCN,UAAW,qBACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,EACZC,cAAe,MAAc,GAC7BC,WAAY,YACb,CAAC,EAEL,GAEH,CACER,QAAS,wCACTC,QAAS,IAAIQ,EAAqB,CAChCN,UAAW,sBACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,IAAU,GAAK,GAC9BC,WAAY,YACb,CAAC,EAEL,GAEH,CACER,QAAS,0BACTC,QAAS,IAAIC,EAAW,CACtBC,UAAW,wBACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GACzBC,WAAY,YACb,CAAC,EAEL,GAEH,CACER,QAAS,2BACTC,QAAS,IAAIQ,EAAqB,CAChCN,UAAW,aACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GACzBC,WAAY,YACb,CAAC,EAEL,GAEH,CACER,QAAS,sBACTC,QAAS,IAAIC,EAAW,CACtBC,UAAW,sBACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GACzBC,WAAY,YACb,EACD,IAAIE,CAAqB,EAE5B,GAEH,CACEV,QAAS,mBACTC,QAAS,IAAIC,EAAW,CACtBC,UAAW,sBACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GACzBC,WAAY,YACb,EACD,IAAIE,CAAqB,EAE5B,GAEH,CACEV,QAAS,aACTC,QAAS,IAAIQ,EAAqB,CAChCN,UAAW,mBACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GACzBC,WAAY,YACb,CAAC,EAEL,GAEH,CACER,QAAS,mBACTC,QAAS,IAAIQ,EAAqB,CAChCN,UAAW,sBACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GACzBC,WAAY,YACb,CAAC,EAEL,GAEH,CACER,QAAS,gCACTC,QAAS,IAAIU,EAAa,CACxBR,UAAW,YACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GACzBC,WAAY,YACb,CAAC,EAEL,GAEH,CACER,QAAS,uBACTC,QAAS,IAAIU,EAAa,CACxBR,UAAW,qBACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GACzBC,WAAY,YACb,CAAC,EAEL,GAEH,CAGER,QAAS,kBACTC,QAAS,IAAIW,EAAY,CACvBC,sBAAuB,EAAA,CACxB,GAEH,CACEb,QAAAA,CAAU,CAAEc,WAAAA,EAAYC,IAAK,CAAEC,SAAAA,CAAAA,CAAAA,IAAiBF,GAAcE,EAASC,WAAW,OAAA,EAClFC,OAAQ,MACRjB,QAAS,IAAIU,EAAa,CACxBR,UAAW,OACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GACzBC,WAAY,YACb,CAAC,EAEJK,sBAAuB,GACxB,GAEH,CACEb,QAAAA,CAAU,CAAEmB,QAAAA,EAASJ,IAAK,CAAEC,SAAAA,CAAAA,EAAYF,WAAAA,CAAAA,IACtCK,EAAQC,QAAQC,IAAI,KAAA,IAAW,KAAOF,EAAQC,QAAQC,IAAI,sBAAA,IAA4B,KAAOP,GAAc,CAACE,EAASC,WAAW,OAAA,EAClIhB,QAAS,IAAIU,EAAa,CACxBR,UAAWR,GAAiBC,YAC5BQ,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GAC1B,CAAC,EAEL,GAEH,CACEP,QAAAA,CAAU,CAAEmB,QAAAA,EAASJ,IAAK,CAAEC,SAAAA,CAAAA,EAAYF,WAAAA,CAAAA,IAAiBK,EAAQC,QAAQC,IAAI,KAAA,IAAW,KAAOP,GAAc,CAACE,EAASC,WAAW,OAAA,EAClIhB,QAAS,IAAIU,EAAa,CACxBR,UAAWR,GAAiBE,IAC5BO,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GAC1B,CAAC,EAEL,GAEH,CACEP,QAAAA,CAAU,CAAEmB,QAAAA,EAASJ,IAAK,CAAEC,SAAAA,CAAAA,EAAYF,WAAAA,CAAAA,IACtCK,EAAQC,QAAQC,IAAI,cAAA,GAAiBC,SAAS,WAAA,GAAgBR,GAAc,CAACE,EAASC,WAAW,OAAA,EACnGhB,QAAS,IAAIU,EAAa,CACxBR,UAAWR,GAAiBG,KAC5BM,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GAC1B,CAAC,EAEL,GAEH,CACEP,QAAAA,CAAU,CAAEe,IAAK,CAAEC,SAAAA,CAAAA,EAAYF,WAAAA,CAAAA,IAAiBA,GAAc,CAACE,EAASC,WAAW,OAAA,EACnFhB,QAAS,IAAIU,EAAa,CACxBR,UAAW,SACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAAU,GAC1B,CAAC,EAEL,GAEH,CACEP,QAAAA,CAAU,CAAEc,WAAAA,CAAAA,IAAiB,CAACA,EAC9Bb,QAAS,IAAIU,EAAa,CACxBR,UAAW,eACXC,QAAS,CACP,IAAIC,EAAiB,CACnBC,WAAY,GACZC,cAAe,KAChB,CAAC,EAEJM,sBAAuB,GACxB,GAEH,CACEb,QAAS,MACTkB,OAAQ,MACRjB,QAAS,IAAIW,ICvPvB,IAAMW,GAAU,IAAIC,GAAQ,CAC1B,gBAAiBC,EACjB,YAAa,GACb,aAAc,GACd,kBAAmB,GACnB,eAAgBC,GAChB,UAAW,CACT,QAAS,CACP,CACE,IAAK,YACL,QAAQ,CAAE,QAAAC,CAAQ,EAAG,CACnB,OAAOA,EAAQ,cAAgB,UACjC,CACF,CACF,CACF,CACF,CAAC,EAoBD,KAAK,iBAAiB,QAAUC,GAAU,CACxC,IAAMC,EAAM,IAAI,IAAID,EAAM,QAAQ,GAAG,EAEnCC,EAAI,SAAW,KAAK,SAAS,QAC7BA,EAAI,SAAS,WAAW,WAAW,GAEnCD,EAAM,yBAAyB,CAEnC,CAAC,EAEDL,GAAQ,kBAAkB",
  "names": ["define_self_SW_MANIFEST_default", "_cacheNameDetails", "_createCacheName", "cacheName", "value", "eachCacheNameDetail", "fn", "key", "cacheNames", "details", "detail", "userCacheName", "supportStatus", "canConstructResponseFromBodyStream", "testResponse", "fallback", "code", "args", "msg", "messageGenerator", "fallback", "SerwistError", "errorCode", "details", "message", "getFriendlyURL", "url", "timeout", "ms", "resolve", "quotaErrorCallbacks", "stripParams", "fullURL", "ignoreParams", "strippedURL", "param", "cacheMatchIgnoreParams", "cache", "request", "matchOptions", "strippedRequestURL", "keysOptions", "cacheKeys", "cacheKey", "Deferred", "reject", "executeQuotaErrorCallbacks", "callback", "SUBSTRING_TO_FIND", "deleteOutdatedCaches", "currentPrecacheName", "substringToFind", "cacheNamesToDelete", "cacheName", "cleanupOutdatedCaches", "event", "privateCacheNames", "cachesDeleted", "clientsClaim", "waitUntil", "asyncFn", "returnPromise", "instanceOfAny", "object", "constructors", "c", "idbProxyableTypes", "cursorAdvanceMethods", "getIdbProxyableTypes", "getCursorAdvanceMethods", "transactionDoneMap", "transformCache", "reverseTransformCache", "promisifyRequest", "request", "promise", "resolve", "reject", "unlisten", "success", "error", "wrap", "cacheDonePromiseForTransaction", "tx", "done", "complete", "idbProxyTraps", "target", "prop", "receiver", "value", "replaceTraps", "callback", "wrapFunction", "func", "args", "unwrap", "transformCachableValue", "newValue", "openDB", "name", "version", "blocked", "upgrade", "blocking", "terminated", "openPromise", "event", "db", "deleteDB", "readMethods", "writeMethods", "cachedMethods", "getMethod", "targetFuncName", "useIndex", "isWrite", "method", "storeName", "oldTraps", "advanceMethodProps", "methodMap", "advanceResults", "ittrProxiedCursorToOriginalProxy", "cursorIteratorTraps", "cachedFunc", "iterate", "cursor", "proxiedCursor", "isIteratorProp", "copyResponse", "response", "modifier", "origin", "SerwistError", "clonedResponse", "responseInit", "modifiedResponseInit", "body", "canConstructResponseFromBodyStream", "disableDevLogs", "BACKGROUND_SYNC_DB_VERSION", "BACKGROUND_SYNC_DB_NAME", "REQUEST_OBJECT_STORE_NAME", "QUEUE_NAME_INDEX", "BackgroundSyncQueueDb", "entry", "tx", "queueName", "results", "id", "query", "direction", "openDB", "db", "oldVersion", "BackgroundSyncQueueStore", "firstId", "serializableProperties", "StorableRequest", "request", "requestData", "value", "key", "prop", "TAG_PREFIX", "MAX_RETENTION_TIME", "queueNames", "convertEntry", "queueStoreEntry", "queueEntry", "BackgroundSyncQueue", "name", "forceSyncFallback", "onSync", "maxRetentionTime", "allEntries", "now", "unexpiredEntries", "maxRetentionTimeInMs", "metadata", "timestamp", "operation", "event", "syncComplete", "syncError", "error", "BackgroundSyncPlugin", "options", "cacheOkAndOpaquePlugin", "toRequest", "input", "StrategyHandler", "strategy", "Deferred", "plugin", "preloadResponse", "originalRequest", "cb", "err", "pluginFilteredRequest", "fetchResponse", "callback", "responseClone", "cachedResponse", "cacheName", "matchOptions", "effectiveRequest", "multiMatchOptions", "timeout", "getFriendlyURL", "responseToCache", "cache", "hasCacheUpdateCallback", "oldResponse", "cacheMatchIgnoreParams", "executeQuotaErrorCallbacks", "mode", "param", "state", "statefulParam", "promise", "possiblePreloadResponse", "pluginsUsed", "Strategy", "privateCacheNames", "responseDone", "handler", "waitUntilError", "NetworkFirst", "Strategy", "options", "p", "cacheOkAndOpaquePlugin", "request", "handler", "logs", "promises", "timeoutId", "id", "promise", "networkPromise", "response", "SerwistError", "resolve", "error", "fetchError", "NetworkOnly", "timeoutPromise", "timeout", "err", "normalizeHandler", "handler", "Route", "match", "method", "PrecacheStrategy", "Strategy", "response", "copyResponse", "options", "privateCacheNames", "request", "preloadResponse", "params", "integrityInManifest", "integrityInRequest", "noIntegrityConflict", "wasCached", "SerwistError", "defaultPluginIndex", "cacheWillUpdatePluginCount", "index", "plugin", "NavigationRoute", "allowlist", "denylist", "url", "pathnameAndSearch", "regExp", "isNavigationPreloadSupported", "enableNavigationPreload", "headerValue", "event", "removeIgnoredSearchParams", "urlObject", "ignoreURLParametersMatching", "paramName", "regExp", "generateURLVariations", "url", "directoryIndex", "cleanURLs", "urlManipulation", "urlWithoutIgnoredParams", "directoryURL", "cleanURL", "additionalURLs", "urlToAttempt", "RegExpRoute", "Route", "handler", "method", "match", "result", "setCacheNameDetails", "details", "cacheNames", "REVISION_SEARCH_PARAM", "createCacheKey", "entry", "SerwistError", "revision", "cacheKeyURL", "originalURL", "PrecacheInstallReportPlugin", "request", "state", "event", "cachedResponse", "parseRoute", "capture", "captureUrl", "matchCallback", "parallel", "limit", "array", "func", "work", "item", "index", "processor", "res", "results", "next", "result", "queues", "a", "b", "isSafari", "DB_NAME", "CACHE_OBJECT_STORE", "normalizeURL", "unNormalizedUrl", "url", "CacheTimestampsModel", "cacheName", "db", "objStore", "deleteDB", "timestamp", "entry", "tx", "minTimestamp", "maxCount", "cursor", "urlsDeleted", "entriesNotDeletedCount", "result", "openDB", "CacheExpiration", "config", "urlsExpired", "cache", "expireOlderThan", "registerQuotaErrorCallback", "callback", "quotaErrorCallbacks", "ExpirationPlugin", "privateCacheNames", "SerwistError", "cacheExpiration", "event", "request", "cachedResponse", "isFresh", "isMaxAgeFromLastUsed", "done", "now", "dateHeaderTimestamp", "dateHeader", "headerTime", "QUEUE_NAME", "MAX_RETENTION_TIME", "COLLECT_PATHS_REGEX", "createOnSyncCallback", "queue", "params", "originalHitTime", "queueTime", "param", "value", "err", "createCollectRoutes", "bgSyncPlugin", "match", "handler", "NetworkOnly", "Route", "createAnalyticsJsRoute", "NetworkFirst", "createGtagJsRoute", "createGtmJsRoute", "initializeGoogleAnalytics", "serwist", "options", "resolvedCacheName", "BackgroundSyncPlugin", "routes", "route", "PrecacheFallbackPlugin", "fallbackUrls", "fallback", "fallbackResponse", "calculateEffectiveBoundaries", "blob", "start", "end", "blobSize", "effectiveStart", "effectiveEnd", "parseRangeHeader", "rangeHeader", "normalizedRangeHeader", "rangeParts", "createPartialResponse", "originalResponse", "boundaries", "originalBlob", "effectiveBoundaries", "slicedBlob", "slicedBlobSize", "slicedResponse", "RangeRequestsPlugin", "CacheFirst", "Strategy", "logs", "response", "error", "StaleWhileRevalidate", "Strategy", "options", "p", "cacheOkAndOpaquePlugin", "request", "handler", "logs", "fetchAndCachePromise", "response", "error", "err", "SerwistError", "PrecacheRoute", "Route", "serwist", "match", "urlsToCacheKeys", "possibleURL", "generateURLVariations", "cacheKey", "PrecacheCacheKeyPlugin", "precacheController", "params", "parsePrecacheOptions", "precacheOptions", "precacheCacheName", "precachePlugins", "precacheFetchOptions", "precacheMatchOptions", "precacheFallbackToNetwork", "precacheDirectoryIndex", "precacheIgnoreUrls", "precacheCleanUrls", "precacheUrlManipulation", "cleanupOutdatedCaches", "concurrency", "navigateFallback", "navigateFallbackAllowlist", "navigateFallbackDenylist", "privateCacheNames", "Serwist", "precacheEntries", "skipWaiting", "importScripts", "navigationPreload", "cacheId", "clientsClaim$1", "runtimeCaching", "offlineAnalyticsConfig", "disableDevLogs$1", "fallbacks", "requestRules", "precacheStrategyOptions", "precacheRouteOptions", "precacheMiscOptions", "PrecacheStrategy", "enableNavigationPreload", "setCacheNameDetails", "event", "clientsClaim", "NavigationRoute", "initializeGoogleAnalytics", "fallbackPlugin", "PrecacheFallbackPlugin", "cacheEntry", "plugin", "entry", "disableDevLogs", "entries", "urlsToWarnAbout", "url", "createCacheKey", "cacheMode", "warningMessage", "waitUntil", "installReportPlugin", "PrecacheInstallReportPlugin", "parallel", "integrity", "updatedURLs", "notUpdatedURLs", "cache", "currentlyCachedRequests", "expectedCacheKeys", "deletedCacheRequests", "responsePromise", "payload", "requestPromises", "method", "normalizeHandler", "capture", "route", "parseRoute", "routeIndex", "urlObject", "sameOrigin", "debugMessages", "catchHandler", "catchErr", "routes", "matchResult", "PAGES_CACHE_NAME", "rscPrefetch", "rsc", "html", "defaultCache", "matcher", "handler", "CacheFirst", "cacheName", "plugins", "ExpirationPlugin", "maxEntries", "maxAgeSeconds", "maxAgeFrom", "StaleWhileRevalidate", "RangeRequestsPlugin", "NetworkFirst", "NetworkOnly", "networkTimeoutSeconds", "sameOrigin", "url", "pathname", "startsWith", "method", "request", "headers", "get", "includes", "serwist", "Serwist", "define_self_SW_MANIFEST_default", "defaultCache", "request", "event", "url"]
}
