diff --git a/storix-fe/next.config.ts b/storix-fe/next.config.ts index 8081a79..38dbbda 100644 --- a/storix-fe/next.config.ts +++ b/storix-fe/next.config.ts @@ -1,5 +1,6 @@ // next.config.ts import crypto from 'node:crypto' +import path from 'node:path' import { spawnSync } from 'node:child_process' import type { NextConfig } from 'next' import withSerwistInit from '@serwist/next' @@ -17,6 +18,7 @@ const withSerwist = withSerwistInit({ }) const nextConfig: NextConfig = { + outputFileTracingRoot: path.resolve(__dirname), // PWA/정적 자산 캐시 헤더 추가 async headers() { return [ diff --git a/storix-fe/public/icons/icon-share.svg b/storix-fe/public/icons/icon-share.svg new file mode 100644 index 0000000..63aaa89 --- /dev/null +++ b/storix-fe/public/icons/icon-share.svg @@ -0,0 +1,3 @@ + + + diff --git a/storix-fe/public/sw.js b/storix-fe/public/sw.js index 11de64b..cb4247c 100644 --- a/storix-fe/public/sw.js +++ b/storix-fe/public/sw.js @@ -1,2360 +1,2 @@ -;(() => { - 'use strict' - let e, - t, - a, - s, - r, - n = { - googleAnalytics: 'googleAnalytics', - precache: 'precache-v2', - prefix: 'serwist', - runtime: 'runtime', - suffix: 'undefined' != typeof registration ? registration.scope : '', - }, - i = (e) => - [n.prefix, e, n.suffix].filter((e) => e && e.length > 0).join('-'), - c = (e) => e || i(n.precache), - o = (e) => e || i(n.runtime) - class l extends Error { - details - constructor(e, t) { - ;(super( - ((e, ...t) => { - let a = e - return (t.length > 0 && (a += ` :: ${JSON.stringify(t)}`), a) - })(e, t), - ), - (this.name = e), - (this.details = t)) - } - } - function h(e) { - return new Promise((t) => setTimeout(t, e)) - } - let u = new Set() - function d(e, t) { - let a = new URL(e) - for (let e of t) a.searchParams.delete(e) - return a.href - } - async function m(e, t, a, s) { - let r = d(t.url, a) - if (t.url === r) return e.match(t, s) - let n = { ...s, ignoreSearch: !0 } - for (let i of await e.keys(t, n)) - if (r === d(i.url, a)) return e.match(i, s) - } - class f { - promise - resolve - reject - constructor() { - this.promise = new Promise((e, t) => { - ;((this.resolve = e), (this.reject = t)) - }) - } - } - let g = async () => { - for (let e of u) await e() - }, - w = '-precache-', - p = async (e, t = w) => { - let a = (await self.caches.keys()).filter( - (a) => a.includes(t) && a.includes(self.registration.scope) && a !== e, - ) - return (await Promise.all(a.map((e) => self.caches.delete(e))), a) - }, - y = (e, t) => { - let a = t() - return (e.waitUntil(a), a) - }, - _ = (e, t) => t.some((t) => e instanceof t), - x = new WeakMap(), - b = new WeakMap(), - E = new WeakMap(), - R = { - get(e, t, a) { - if (e instanceof IDBTransaction) { - if ('done' === t) return x.get(e) - if ('store' === t) - return a.objectStoreNames[1] - ? void 0 - : a.objectStore(a.objectStoreNames[0]) - } - return v(e[t]) - }, - set: (e, t, a) => ((e[t] = a), !0), - has: (e, t) => - (e instanceof IDBTransaction && ('done' === t || 'store' === t)) || - t in e, - } - function v(e) { - if (e instanceof IDBRequest) { - let t - return ( - (t = new Promise((t, a) => { - let s = () => { - ;(e.removeEventListener('success', r), - e.removeEventListener('error', n)) - }, - r = () => { - ;(t(v(e.result)), s()) - }, - n = () => { - ;(a(e.error), s()) - } - ;(e.addEventListener('success', r), e.addEventListener('error', n)) - })), - E.set(t, e), - t - ) - } - if (b.has(e)) return b.get(e) - let t = (function (e) { - if ('function' == typeof e) - return ( - r || - (r = [ - IDBCursor.prototype.advance, - IDBCursor.prototype.continue, - IDBCursor.prototype.continuePrimaryKey, - ]) - ).includes(e) - ? function (...t) { - return (e.apply(q(this), t), v(this.request)) - } - : function (...t) { - return v(e.apply(q(this), t)) - } - return (e instanceof IDBTransaction && - (function (e) { - if (x.has(e)) return - let t = new Promise((t, a) => { - let s = () => { - ;(e.removeEventListener('complete', r), - e.removeEventListener('error', n), - e.removeEventListener('abort', n)) - }, - r = () => { - ;(t(), s()) - }, - n = () => { - ;(a(e.error || new DOMException('AbortError', 'AbortError')), - s()) - } - ;(e.addEventListener('complete', r), - e.addEventListener('error', n), - e.addEventListener('abort', n)) - }) - x.set(e, t) - })(e), - _( - e, - s || - (s = [ - IDBDatabase, - IDBObjectStore, - IDBIndex, - IDBCursor, - IDBTransaction, - ]), - )) - ? new Proxy(e, R) - : e - })(e) - return (t !== e && (b.set(e, t), E.set(t, e)), t) - } - let q = (e) => E.get(e) - function S( - e, - t, - { blocked: a, upgrade: s, blocking: r, terminated: n } = {}, - ) { - let i = indexedDB.open(e, t), - c = v(i) - return ( - s && - i.addEventListener('upgradeneeded', (e) => { - s(v(i.result), e.oldVersion, e.newVersion, v(i.transaction), e) - }), - a && - i.addEventListener('blocked', (e) => a(e.oldVersion, e.newVersion, e)), - c - .then((e) => { - ;(n && e.addEventListener('close', () => n()), - r && - e.addEventListener('versionchange', (e) => - r(e.oldVersion, e.newVersion, e), - )) - }) - .catch(() => {}), - c - ) - } - let D = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'], - N = ['put', 'add', 'delete', 'clear'], - C = new Map() - function T(e, t) { - if (!(e instanceof IDBDatabase && !(t in e) && 'string' == typeof t)) return - if (C.get(t)) return C.get(t) - let a = t.replace(/FromIndex$/, ''), - s = t !== a, - r = N.includes(a) - if ( - !(a in (s ? IDBIndex : IDBObjectStore).prototype) || - !(r || D.includes(a)) - ) - return - let n = async function (e, ...t) { - let n = this.transaction(e, r ? 'readwrite' : 'readonly'), - i = n.store - return ( - s && (i = i.index(t.shift())), - (await Promise.all([i[a](...t), r && n.done]))[0] - ) - } - return (C.set(t, n), n) - } - R = { - ...(e = R), - get: (t, a, s) => T(t, a) || e.get(t, a, s), - has: (t, a) => !!T(t, a) || e.has(t, a), - } - let P = ['continue', 'continuePrimaryKey', 'advance'], - k = {}, - A = new WeakMap(), - I = new WeakMap(), - U = { - get(e, t) { - if (!P.includes(t)) return e[t] - let a = k[t] - return ( - a || - (a = k[t] = - function (...e) { - A.set(this, I.get(this)[t](...e)) - }), - a - ) - }, - } - async function* L(...e) { - let t = this - if ((t instanceof IDBCursor || (t = await t.openCursor(...e)), !t)) return - let a = new Proxy(t, U) - for (I.set(a, t), E.set(a, q(t)); t; ) - (yield a, (t = await (A.get(a) || t.continue())), A.delete(a)) - } - function F(e, t) { - return ( - (t === Symbol.asyncIterator && - _(e, [IDBIndex, IDBObjectStore, IDBCursor])) || - ('iterate' === t && _(e, [IDBIndex, IDBObjectStore])) - ) - } - R = { - ...(t = R), - get: (e, a, s) => (F(e, a) ? L : t.get(e, a, s)), - has: (e, a) => F(e, a) || t.has(e, a), - } - let M = async (e, t) => { - let s = null - if ((e.url && (s = new URL(e.url).origin), s !== self.location.origin)) - throw new l('cross-origin-copy-response', { origin: s }) - let r = e.clone(), - n = { - headers: new Headers(r.headers), - status: r.status, - statusText: r.statusText, - }, - i = t ? t(n) : n, - c = !(function () { - if (void 0 === a) { - let e = new Response('') - if ('body' in e) - try { - ;(new Response(e.body), (a = !0)) - } catch { - a = !1 - } - a = !1 - } - return a - })() - ? await r.blob() - : r.body - return new Response(c, i) - }, - O = 'requests', - B = 'queueName' - class K { - _db = null - async addEntry(e) { - let t = (await this.getDb()).transaction(O, 'readwrite', { - durability: 'relaxed', - }) - ;(await t.store.add(e), await t.done) - } - async getFirstEntryId() { - let e = await this.getDb(), - t = await e.transaction(O).store.openCursor() - return t?.value.id - } - async getAllEntriesByQueueName(e) { - let t = await this.getDb() - return (await t.getAllFromIndex(O, B, IDBKeyRange.only(e))) || [] - } - async getEntryCountByQueueName(e) { - return (await this.getDb()).countFromIndex(O, B, IDBKeyRange.only(e)) - } - async deleteEntry(e) { - let t = await this.getDb() - await t.delete(O, e) - } - async getFirstEntryByQueueName(e) { - return await this.getEndEntryFromIndex(IDBKeyRange.only(e), 'next') - } - async getLastEntryByQueueName(e) { - return await this.getEndEntryFromIndex(IDBKeyRange.only(e), 'prev') - } - async getEndEntryFromIndex(e, t) { - let a = await this.getDb(), - s = await a.transaction(O).store.index(B).openCursor(e, t) - return s?.value - } - async getDb() { - return ( - this._db || - (this._db = await S('serwist-background-sync', 3, { - upgrade: this._upgradeDb, - })), - this._db - ) - } - _upgradeDb(e, t) { - ;(t > 0 && - t < 3 && - e.objectStoreNames.contains(O) && - e.deleteObjectStore(O), - e - .createObjectStore(O, { autoIncrement: !0, keyPath: 'id' }) - .createIndex(B, B, { unique: !1 })) - } - } - class W { - _queueName - _queueDb - constructor(e) { - ;((this._queueName = e), (this._queueDb = new K())) - } - async pushEntry(e) { - ;(delete e.id, - (e.queueName = this._queueName), - await this._queueDb.addEntry(e)) - } - async unshiftEntry(e) { - let t = await this._queueDb.getFirstEntryId() - ;(t ? (e.id = t - 1) : delete e.id, - (e.queueName = this._queueName), - await this._queueDb.addEntry(e)) - } - async popEntry() { - return this._removeEntry( - await this._queueDb.getLastEntryByQueueName(this._queueName), - ) - } - async shiftEntry() { - return this._removeEntry( - await this._queueDb.getFirstEntryByQueueName(this._queueName), - ) - } - async getAll() { - return await this._queueDb.getAllEntriesByQueueName(this._queueName) - } - async size() { - return await this._queueDb.getEntryCountByQueueName(this._queueName) - } - async deleteEntry(e) { - await this._queueDb.deleteEntry(e) - } - async _removeEntry(e) { - return (e && (await this.deleteEntry(e.id)), e) - } - } - let j = [ - 'method', - 'referrer', - 'referrerPolicy', - 'mode', - 'credentials', - 'cache', - 'redirect', - 'integrity', - 'keepalive', - ] - class $ { - _requestData - static async fromRequest(e) { - let t = { url: e.url, headers: {} } - for (let a of ('GET' !== e.method && - (t.body = await e.clone().arrayBuffer()), - e.headers.forEach((e, a) => { - t.headers[a] = e - }), - j)) - void 0 !== e[a] && (t[a] = e[a]) - return new $(t) - } - constructor(e) { - ;('navigate' === e.mode && (e.mode = 'same-origin'), - (this._requestData = e)) - } - toObject() { - let e = Object.assign({}, this._requestData) - return ( - (e.headers = Object.assign({}, this._requestData.headers)), - e.body && (e.body = e.body.slice(0)), - e - ) - } - toRequest() { - return new Request(this._requestData.url, this._requestData) - } - clone() { - return new $(this.toObject()) - } - } - let H = 'serwist-background-sync', - G = new Set(), - Q = (e) => { - let t = { - request: new $(e.requestData).toRequest(), - timestamp: e.timestamp, - } - return (e.metadata && (t.metadata = e.metadata), t) - } - class V { - _name - _onSync - _maxRetentionTime - _queueStore - _forceSyncFallback - _syncInProgress = !1 - _requestsAddedDuringSync = !1 - constructor( - e, - { forceSyncFallback: t, onSync: a, maxRetentionTime: s } = {}, - ) { - if (G.has(e)) throw new l('duplicate-queue-name', { name: e }) - ;(G.add(e), - (this._name = e), - (this._onSync = a || this.replayRequests), - (this._maxRetentionTime = s || 10080), - (this._forceSyncFallback = !!t), - (this._queueStore = new W(this._name)), - this._addSyncListener()) - } - get name() { - return this._name - } - async pushRequest(e) { - await this._addRequest(e, 'push') - } - async unshiftRequest(e) { - await this._addRequest(e, 'unshift') - } - async popRequest() { - return this._removeRequest('pop') - } - async shiftRequest() { - return this._removeRequest('shift') - } - async getAll() { - let e = await this._queueStore.getAll(), - t = Date.now(), - a = [] - for (let s of e) { - let e = 60 * this._maxRetentionTime * 1e3 - t - s.timestamp > e - ? await this._queueStore.deleteEntry(s.id) - : a.push(Q(s)) - } - return a - } - async size() { - return await this._queueStore.size() - } - async _addRequest( - { request: e, metadata: t, timestamp: a = Date.now() }, - s, - ) { - let r = { - requestData: (await $.fromRequest(e.clone())).toObject(), - timestamp: a, - } - switch ((t && (r.metadata = t), s)) { - case 'push': - await this._queueStore.pushEntry(r) - break - case 'unshift': - await this._queueStore.unshiftEntry(r) - } - this._syncInProgress - ? (this._requestsAddedDuringSync = !0) - : await this.registerSync() - } - async _removeRequest(e) { - let t, - a = Date.now() - switch (e) { - case 'pop': - t = await this._queueStore.popEntry() - break - case 'shift': - t = await this._queueStore.shiftEntry() - } - if (t) { - let s = 60 * this._maxRetentionTime * 1e3 - return a - t.timestamp > s ? this._removeRequest(e) : Q(t) - } - } - async replayRequests() { - let e - for (; (e = await this.shiftRequest()); ) - try { - await fetch(e.request.clone()) - } catch { - throw ( - await this.unshiftRequest(e), - new l('queue-replay-failed', { name: this._name }) - ) - } - } - async registerSync() { - if ('sync' in self.registration && !this._forceSyncFallback) - try { - await self.registration.sync.register(`${H}:${this._name}`) - } catch (e) {} - } - _addSyncListener() { - 'sync' in self.registration && !this._forceSyncFallback - ? self.addEventListener('sync', (e) => { - if (e.tag === `${H}:${this._name}`) { - let t = async () => { - let t - this._syncInProgress = !0 - try { - await this._onSync({ queue: this }) - } catch (e) { - if (e instanceof Error) throw e - } finally { - ;(this._requestsAddedDuringSync && - !(t && !e.lastChance) && - (await this.registerSync()), - (this._syncInProgress = !1), - (this._requestsAddedDuringSync = !1)) - } - } - e.waitUntil(t()) - } - }) - : this._onSync({ queue: this }) - } - static get _queueNames() { - return G - } - } - class z { - _queue - constructor(e, t) { - this._queue = new V(e, t) - } - async fetchDidFail({ request: e }) { - await this._queue.pushRequest({ request: e }) - } - } - let J = { - cacheWillUpdate: async ({ response: e }) => - 200 === e.status || 0 === e.status ? e : null, - } - function X(e) { - return 'string' == typeof e ? new Request(e) : e - } - class Y { - event - request - url - params - _cacheKeys = {} - _strategy - _handlerDeferred - _extendLifetimePromises - _plugins - _pluginStateMap - constructor(e, t) { - for (const a of ((this.event = t.event), - (this.request = t.request), - t.url && ((this.url = t.url), (this.params = t.params)), - (this._strategy = e), - (this._handlerDeferred = new f()), - (this._extendLifetimePromises = []), - (this._plugins = [...e.plugins]), - (this._pluginStateMap = new Map()), - this._plugins)) - this._pluginStateMap.set(a, {}) - this.event.waitUntil(this._handlerDeferred.promise) - } - async fetch(e) { - let { event: t } = this, - a = X(e), - s = await this.getPreloadResponse() - if (s) return s - let r = this.hasCallback('fetchDidFail') ? a.clone() : null - try { - for (let e of this.iterateCallbacks('requestWillFetch')) - a = await e({ request: a.clone(), event: t }) - } catch (e) { - if (e instanceof Error) - throw new l('plugin-error-request-will-fetch', { - thrownErrorMessage: e.message, - }) - } - let n = a.clone() - try { - let e - for (let s of ((e = await fetch( - a, - 'navigate' === a.mode ? void 0 : this._strategy.fetchOptions, - )), - this.iterateCallbacks('fetchDidSucceed'))) - e = await s({ event: t, request: n, response: e }) - return e - } catch (e) { - throw ( - r && - (await this.runCallbacks('fetchDidFail', { - error: e, - event: t, - originalRequest: r.clone(), - request: n.clone(), - })), - e - ) - } - } - async fetchAndCachePut(e) { - let t = await this.fetch(e), - a = t.clone() - return (this.waitUntil(this.cachePut(e, a)), t) - } - async cacheMatch(e) { - let t, - a = X(e), - { cacheName: s, matchOptions: r } = this._strategy, - n = await this.getCacheKey(a, 'read'), - i = { ...r, cacheName: s } - for (let e of ((t = await caches.match(n, i)), - this.iterateCallbacks('cachedResponseWillBeUsed'))) - t = - (await e({ - cacheName: s, - matchOptions: r, - cachedResponse: t, - request: n, - event: this.event, - })) || void 0 - return t - } - async cachePut(e, t) { - let a = X(e) - await h(0) - let s = await this.getCacheKey(a, 'write') - if (!t) - throw new l('cache-put-with-no-response', { - url: new URL(String(s.url), location.href).href.replace( - RegExp(`^${location.origin}`), - '', - ), - }) - let r = await this._ensureResponseSafeToCache(t) - if (!r) return !1 - let { cacheName: n, matchOptions: i } = this._strategy, - c = await self.caches.open(n), - o = this.hasCallback('cacheDidUpdate'), - u = o ? await m(c, s.clone(), ['__WB_REVISION__'], i) : null - try { - await c.put(s, o ? r.clone() : r) - } catch (e) { - if (e instanceof Error) - throw ('QuotaExceededError' === e.name && (await g()), e) - } - for (let e of this.iterateCallbacks('cacheDidUpdate')) - await e({ - cacheName: n, - oldResponse: u, - newResponse: r.clone(), - request: s, - event: this.event, - }) - return !0 - } - async getCacheKey(e, t) { - let a = `${e.url} | ${t}` - if (!this._cacheKeys[a]) { - let s = e - for (let e of this.iterateCallbacks('cacheKeyWillBeUsed')) - s = X( - await e({ - mode: t, - request: s, - event: this.event, - params: this.params, - }), - ) - this._cacheKeys[a] = s - } - return this._cacheKeys[a] - } - hasCallback(e) { - for (let t of this._strategy.plugins) if (e in t) return !0 - return !1 - } - async runCallbacks(e, t) { - for (let a of this.iterateCallbacks(e)) await a(t) - } - *iterateCallbacks(e) { - for (let t of this._strategy.plugins) - if ('function' == typeof t[e]) { - let a = this._pluginStateMap.get(t), - s = (s) => { - let r = { ...s, state: a } - return t[e](r) - } - yield s - } - } - waitUntil(e) { - return (this._extendLifetimePromises.push(e), e) - } - async doneWaiting() { - let e - for (; (e = this._extendLifetimePromises.shift()); ) await e - } - destroy() { - this._handlerDeferred.resolve(null) - } - async getPreloadResponse() { - if ( - this.event instanceof FetchEvent && - 'navigate' === this.event.request.mode && - 'preloadResponse' in this.event - ) - try { - let e = await this.event.preloadResponse - if (e) return e - } catch (e) {} - } - async _ensureResponseSafeToCache(e) { - let t = e, - a = !1 - for (let e of this.iterateCallbacks('cacheWillUpdate')) - if ( - ((t = - (await e({ - request: this.request, - response: t, - event: this.event, - })) || void 0), - (a = !0), - !t) - ) - break - return (!a && t && 200 !== t.status && (t = void 0), t) - } - } - class Z { - cacheName - plugins - fetchOptions - matchOptions - constructor(e = {}) { - ;((this.cacheName = o(e.cacheName)), - (this.plugins = e.plugins || []), - (this.fetchOptions = e.fetchOptions), - (this.matchOptions = e.matchOptions)) - } - handle(e) { - let [t] = this.handleAll(e) - return t - } - handleAll(e) { - e instanceof FetchEvent && (e = { event: e, request: e.request }) - let t = e.event, - a = 'string' == typeof e.request ? new Request(e.request) : e.request, - s = new Y( - this, - e.url - ? { event: t, request: a, url: e.url, params: e.params } - : { event: t, request: a }, - ), - r = this._getResponse(s, a, t), - n = this._awaitComplete(r, s, a, t) - return [r, n] - } - async _getResponse(e, t, a) { - let s - await e.runCallbacks('handlerWillStart', { event: a, request: t }) - try { - if ( - ((s = await this._handle(t, e)), void 0 === s || 'error' === s.type) - ) - throw new l('no-response', { url: t.url }) - } catch (r) { - if (r instanceof Error) { - for (let n of e.iterateCallbacks('handlerDidError')) - if (void 0 !== (s = await n({ error: r, event: a, request: t }))) - break - } - if (!s) throw r - } - for (let r of e.iterateCallbacks('handlerWillRespond')) - s = await r({ event: a, request: t, response: s }) - return s - } - async _awaitComplete(e, t, a, s) { - let r, n - try { - r = await e - } catch {} - try { - ;(await t.runCallbacks('handlerDidRespond', { - event: s, - request: a, - response: r, - }), - await t.doneWaiting()) - } catch (e) { - e instanceof Error && (n = e) - } - if ( - (await t.runCallbacks('handlerDidComplete', { - event: s, - request: a, - response: r, - error: n, - }), - t.destroy(), - n) - ) - throw n - } - } - class ee extends Z { - _networkTimeoutSeconds - constructor(e = {}) { - ;(super(e), - this.plugins.some((e) => 'cacheWillUpdate' in e) || - this.plugins.unshift(J), - (this._networkTimeoutSeconds = e.networkTimeoutSeconds || 0)) - } - async _handle(e, t) { - let a, - s = [], - r = [] - if (this._networkTimeoutSeconds) { - let { id: n, promise: i } = this._getTimeoutPromise({ - request: e, - logs: s, - handler: t, - }) - ;((a = n), r.push(i)) - } - let n = this._getNetworkPromise({ - timeoutId: a, - request: e, - logs: s, - handler: t, - }) - r.push(n) - let i = await t.waitUntil( - (async () => (await t.waitUntil(Promise.race(r))) || (await n))(), - ) - if (!i) throw new l('no-response', { url: e.url }) - return i - } - _getTimeoutPromise({ request: e, logs: t, handler: a }) { - let s - return { - promise: new Promise((t) => { - s = setTimeout(async () => { - t(await a.cacheMatch(e)) - }, 1e3 * this._networkTimeoutSeconds) - }), - id: s, - } - } - async _getNetworkPromise({ - timeoutId: e, - request: t, - logs: a, - handler: s, - }) { - let r, n - try { - n = await s.fetchAndCachePut(t) - } catch (e) { - e instanceof Error && (r = e) - } - return (e && clearTimeout(e), (r || !n) && (n = await s.cacheMatch(t)), n) - } - } - class et extends Z { - _networkTimeoutSeconds - constructor(e = {}) { - ;(super(e), (this._networkTimeoutSeconds = e.networkTimeoutSeconds || 0)) - } - async _handle(e, t) { - let a, s - try { - let a = [t.fetch(e)] - if (this._networkTimeoutSeconds) { - let e = h(1e3 * this._networkTimeoutSeconds) - a.push(e) - } - if (!(s = await Promise.race(a))) - throw Error( - `Timed out the network response after ${this._networkTimeoutSeconds} seconds.`, - ) - } catch (e) { - e instanceof Error && (a = e) - } - if (!s) throw new l('no-response', { url: e.url, error: a }) - return s - } - } - let ea = (e) => (e && 'object' == typeof e ? e : { handle: e }) - class es { - handler - match - method - catchHandler - constructor(e, t, a = 'GET') { - ;((this.handler = ea(t)), (this.match = e), (this.method = a)) - } - setCatchHandler(e) { - this.catchHandler = ea(e) - } - } - class er extends Z { - _fallbackToNetwork - static defaultPrecacheCacheabilityPlugin = { - cacheWillUpdate: async ({ response: e }) => - !e || e.status >= 400 ? null : e, - } - static copyRedirectedCacheableResponsesPlugin = { - cacheWillUpdate: async ({ response: e }) => - e.redirected ? await M(e) : e, - } - constructor(e = {}) { - ;((e.cacheName = c(e.cacheName)), - super(e), - (this._fallbackToNetwork = !1 !== e.fallbackToNetwork), - this.plugins.push(er.copyRedirectedCacheableResponsesPlugin)) - } - async _handle(e, t) { - let a = await t.getPreloadResponse() - if (a) return a - let s = await t.cacheMatch(e) - return ( - s || - (t.event && 'install' === t.event.type - ? await this._handleInstall(e, t) - : await this._handleFetch(e, t)) - ) - } - async _handleFetch(e, t) { - let a, - s = t.params || {} - if (this._fallbackToNetwork) { - let r = s.integrity, - n = e.integrity, - i = !n || n === r - ;((a = await t.fetch( - new Request(e, { integrity: 'no-cors' !== e.mode ? n || r : void 0 }), - )), - r && - i && - 'no-cors' !== e.mode && - (this._useDefaultCacheabilityPluginIfNeeded(), - await t.cachePut(e, a.clone()))) - } else - throw new l('missing-precache-entry', { - cacheName: this.cacheName, - url: e.url, - }) - return a - } - async _handleInstall(e, t) { - this._useDefaultCacheabilityPluginIfNeeded() - let a = await t.fetch(e) - if (!(await t.cachePut(e, a.clone()))) - throw new l('bad-precaching-response', { url: e.url, status: a.status }) - return a - } - _useDefaultCacheabilityPluginIfNeeded() { - let e = null, - t = 0 - for (let [a, s] of this.plugins.entries()) - s !== er.copyRedirectedCacheableResponsesPlugin && - (s === er.defaultPrecacheCacheabilityPlugin && (e = a), - s.cacheWillUpdate && t++) - 0 === t - ? this.plugins.push(er.defaultPrecacheCacheabilityPlugin) - : t > 1 && null !== e && this.plugins.splice(e, 1) - } - } - class en extends es { - _allowlist - _denylist - constructor(e, { allowlist: t = [/./], denylist: a = [] } = {}) { - ;(super((e) => this._match(e), e), - (this._allowlist = t), - (this._denylist = a)) - } - _match({ url: e, request: t }) { - if (t && 'navigate' !== t.mode) return !1 - let a = e.pathname + e.search - for (let e of this._denylist) if (e.test(a)) return !1 - return !!this._allowlist.some((e) => e.test(a)) - } - } - class ei extends es { - constructor(e, t, a) { - super( - ({ url: t }) => { - let a = e.exec(t.href) - if (a) - return t.origin !== location.origin && 0 !== a.index - ? void 0 - : a.slice(1) - }, - t, - a, - ) - } - } - let ec = (e) => { - if (!e) throw new l('add-to-cache-list-unexpected-type', { entry: e }) - if ('string' == typeof e) { - let t = new URL(e, location.href) - return { cacheKey: t.href, url: t.href } - } - let { revision: t, url: a } = e - if (!a) throw new l('add-to-cache-list-unexpected-type', { entry: e }) - if (!t) { - let e = new URL(a, location.href) - return { cacheKey: e.href, url: e.href } - } - let s = new URL(a, location.href), - r = new URL(a, location.href) - return ( - s.searchParams.set('__WB_REVISION__', t), - { cacheKey: s.href, url: r.href } - ) - } - class eo { - updatedURLs = [] - notUpdatedURLs = [] - handlerWillStart = async ({ request: e, state: t }) => { - t && (t.originalRequest = e) - } - cachedResponseWillBeUsed = async ({ - event: e, - state: t, - cachedResponse: a, - }) => { - if ( - 'install' === e.type && - t?.originalRequest && - t.originalRequest instanceof Request - ) { - let e = t.originalRequest.url - a ? this.notUpdatedURLs.push(e) : this.updatedURLs.push(e) - } - return a - } - } - let el = async (e, t, a) => { - let s = t.map((e, t) => ({ index: t, item: e })), - r = async (e) => { - let t = [] - for (;;) { - let r = s.pop() - if (!r) return e(t) - let n = await a(r.item) - t.push({ result: n, index: r.index }) - } - }, - n = Array.from({ length: e }, () => new Promise(r)) - return (await Promise.all(n)) - .flat() - .sort((e, t) => (e.index < t.index ? -1 : 1)) - .map((e) => e.result) - } - 'undefined' != typeof navigator && - /^((?!chrome|android).)*safari/i.test(navigator.userAgent) - let eh = 'cache-entries', - eu = (e) => { - let t = new URL(e, location.href) - return ((t.hash = ''), t.href) - } - class ed { - _cacheName - _db = null - constructor(e) { - this._cacheName = e - } - _getId(e) { - return `${this._cacheName}|${eu(e)}` - } - _upgradeDb(e) { - let t = e.createObjectStore(eh, { keyPath: 'id' }) - ;(t.createIndex('cacheName', 'cacheName', { unique: !1 }), - t.createIndex('timestamp', 'timestamp', { unique: !1 })) - } - _upgradeDbAndDeleteOldDbs(e) { - ;(this._upgradeDb(e), - this._cacheName && - (function (e, { blocked: t } = {}) { - let a = indexedDB.deleteDatabase(e) - ;(t && a.addEventListener('blocked', (e) => t(e.oldVersion, e)), - v(a).then(() => void 0)) - })(this._cacheName)) - } - async setTimestamp(e, t) { - e = eu(e) - let a = { - id: this._getId(e), - cacheName: this._cacheName, - url: e, - timestamp: t, - }, - s = (await this.getDb()).transaction(eh, 'readwrite', { - durability: 'relaxed', - }) - ;(await s.store.put(a), await s.done) - } - async getTimestamp(e) { - let t = await this.getDb(), - a = await t.get(eh, this._getId(e)) - return a?.timestamp - } - async expireEntries(e, t) { - let a = await this.getDb(), - s = await a - .transaction(eh, 'readwrite') - .store.index('timestamp') - .openCursor(null, 'prev'), - r = [], - n = 0 - for (; s; ) { - let a = s.value - ;(a.cacheName === this._cacheName && - ((e && a.timestamp < e) || (t && n >= t) - ? (s.delete(), r.push(a.url)) - : n++), - (s = await s.continue())) - } - return r - } - async getDb() { - return ( - this._db || - (this._db = await S('serwist-expiration', 1, { - upgrade: this._upgradeDbAndDeleteOldDbs.bind(this), - })), - this._db - ) - } - } - class em { - _isRunning = !1 - _rerunRequested = !1 - _maxEntries - _maxAgeSeconds - _matchOptions - _cacheName - _timestampModel - constructor(e, t = {}) { - ;((this._maxEntries = t.maxEntries), - (this._maxAgeSeconds = t.maxAgeSeconds), - (this._matchOptions = t.matchOptions), - (this._cacheName = e), - (this._timestampModel = new ed(e))) - } - async expireEntries() { - if (this._isRunning) { - this._rerunRequested = !0 - return - } - this._isRunning = !0 - let e = this._maxAgeSeconds ? Date.now() - 1e3 * this._maxAgeSeconds : 0, - t = await this._timestampModel.expireEntries(e, this._maxEntries), - a = await self.caches.open(this._cacheName) - for (let e of t) await a.delete(e, this._matchOptions) - ;((this._isRunning = !1), - this._rerunRequested && - ((this._rerunRequested = !1), this.expireEntries())) - } - async updateTimestamp(e) { - await this._timestampModel.setTimestamp(e, Date.now()) - } - async isURLExpired(e) { - if (!this._maxAgeSeconds) return !1 - let t = await this._timestampModel.getTimestamp(e), - a = Date.now() - 1e3 * this._maxAgeSeconds - return void 0 === t || t < a - } - async delete() { - ;((this._rerunRequested = !1), - await this._timestampModel.expireEntries(1 / 0)) - } - } - class ef { - _config - _cacheExpirations - constructor(e = {}) { - var t - ;((this._config = e), - (this._cacheExpirations = new Map()), - this._config.maxAgeFrom || (this._config.maxAgeFrom = 'last-fetched'), - this._config.purgeOnQuotaError && - ((t = () => this.deleteCacheAndMetadata()), u.add(t))) - } - _getCacheExpiration(e) { - if (e === o()) throw new l('expire-custom-caches-only') - let t = this._cacheExpirations.get(e) - return ( - t || ((t = new em(e, this._config)), this._cacheExpirations.set(e, t)), - t - ) - } - cachedResponseWillBeUsed({ - event: e, - cacheName: t, - request: a, - cachedResponse: s, - }) { - if (!s) return null - let r = this._isResponseDateFresh(s), - n = this._getCacheExpiration(t), - i = 'last-used' === this._config.maxAgeFrom, - c = (async () => { - ;(i && (await n.updateTimestamp(a.url)), await n.expireEntries()) - })() - try { - e.waitUntil(c) - } catch {} - return r ? s : null - } - _isResponseDateFresh(e) { - if ('last-used' === this._config.maxAgeFrom) return !0 - let t = Date.now() - if (!this._config.maxAgeSeconds) return !0 - let a = this._getDateHeaderTimestamp(e) - return null === a || a >= t - 1e3 * this._config.maxAgeSeconds - } - _getDateHeaderTimestamp(e) { - if (!e.headers.has('date')) return null - let t = new Date(e.headers.get('date')).getTime() - return Number.isNaN(t) ? null : t - } - async cacheDidUpdate({ cacheName: e, request: t }) { - let a = this._getCacheExpiration(e) - ;(await a.updateTimestamp(t.url), await a.expireEntries()) - } - async deleteCacheAndMetadata() { - for (let [e, t] of this._cacheExpirations) - (await self.caches.delete(e), await t.delete()) - this._cacheExpirations = new Map() - } - } - let eg = 'www.google-analytics.com', - ew = 'www.googletagmanager.com', - ep = /^\/(\w+\/)?collect/, - ey = ({ serwist: e, cacheName: t, ...a }) => { - let s, - r, - c = t || i(n.googleAnalytics), - o = new z('serwist-google-analytics', { - maxRetentionTime: 2880, - onSync: async ({ queue: e }) => { - let t - for (; (t = await e.shiftRequest()); ) { - let { request: s, timestamp: r } = t, - n = new URL(s.url) - try { - let e = - 'POST' === s.method - ? new URLSearchParams(await s.clone().text()) - : n.searchParams, - t = r - (Number(e.get('qt')) || 0), - i = Date.now() - t - if ((e.set('qt', String(i)), a.parameterOverrides)) - for (let t of Object.keys(a.parameterOverrides)) { - let s = a.parameterOverrides[t] - e.set(t, s) - } - ;('function' == typeof a.hitFilter && a.hitFilter.call(null, e), - await fetch( - new Request(n.origin + n.pathname, { - body: e.toString(), - method: 'POST', - mode: 'cors', - credentials: 'omit', - headers: { 'Content-Type': 'text/plain' }, - }), - )) - } catch (a) { - throw (await e.unshiftRequest(t), a) - } - } - }, - }) - for (let t of [ - new es( - ({ url: e }) => e.hostname === ew && '/gtm.js' === e.pathname, - new ee({ cacheName: c }), - 'GET', - ), - new es( - ({ url: e }) => e.hostname === eg && '/analytics.js' === e.pathname, - new ee({ cacheName: c }), - 'GET', - ), - new es( - ({ url: e }) => e.hostname === ew && '/gtag/js' === e.pathname, - new ee({ cacheName: c }), - 'GET', - ), - new es( - (s = ({ url: e }) => e.hostname === eg && ep.test(e.pathname)), - (r = new et({ plugins: [o] })), - 'GET', - ), - new es(s, r, 'POST'), - ]) - e.registerRoute(t) - } - class e_ { - _fallbackUrls - _serwist - constructor({ fallbackUrls: e, serwist: t }) { - ;((this._fallbackUrls = e), (this._serwist = t)) - } - async handlerDidError(e) { - for (let t of this._fallbackUrls) - if ('string' == typeof t) { - let e = await this._serwist.matchPrecache(t) - if (void 0 !== e) return e - } else if (t.matcher(e)) { - let e = await this._serwist.matchPrecache(t.url) - if (void 0 !== e) return e - } - } - } - let ex = async (e, t) => { - try { - if (206 === t.status) return t - let a = e.headers.get('range') - if (!a) throw new l('no-range-header') - let s = ((e) => { - let t = e.trim().toLowerCase() - if (!t.startsWith('bytes=')) - throw new l('unit-must-be-bytes', { normalizedRangeHeader: t }) - if (t.includes(',')) - throw new l('single-range-only', { normalizedRangeHeader: t }) - let a = /(\d*)-(\d*)/.exec(t) - if (!a || !(a[1] || a[2])) - throw new l('invalid-range-values', { normalizedRangeHeader: t }) - return { - start: '' === a[1] ? void 0 : Number(a[1]), - end: '' === a[2] ? void 0 : Number(a[2]), - } - })(a), - r = await t.blob(), - n = ((e, t, a) => { - let s, - r, - n = e.size - if ((a && a > n) || (t && t < 0)) - throw new l('range-not-satisfiable', { size: n, end: a, start: t }) - return ( - void 0 !== t && void 0 !== a - ? ((s = t), (r = a + 1)) - : void 0 !== t && void 0 === a - ? ((s = t), (r = n)) - : void 0 !== a && void 0 === t && ((s = n - a), (r = n)), - { start: s, end: r } - ) - })(r, s.start, s.end), - i = r.slice(n.start, n.end), - c = i.size, - o = new Response(i, { - status: 206, - statusText: 'Partial Content', - headers: t.headers, - }) - return ( - o.headers.set('Content-Length', String(c)), - o.headers.set( - 'Content-Range', - `bytes ${n.start}-${n.end - 1}/${r.size}`, - ), - o - ) - } catch (e) { - return new Response('', { - status: 416, - statusText: 'Range Not Satisfiable', - }) - } - } - class eb { - cachedResponseWillBeUsed = async ({ request: e, cachedResponse: t }) => - t && e.headers.has('range') ? await ex(e, t) : t - } - class eE extends Z { - async _handle(e, t) { - let a, - s = await t.cacheMatch(e) - if (!s) - try { - s = await t.fetchAndCachePut(e) - } catch (e) { - e instanceof Error && (a = e) - } - if (!s) throw new l('no-response', { url: e.url, error: a }) - return s - } - } - class eR extends Z { - constructor(e = {}) { - ;(super(e), - this.plugins.some((e) => 'cacheWillUpdate' in e) || - this.plugins.unshift(J)) - } - async _handle(e, t) { - let a, - s = t.fetchAndCachePut(e).catch(() => {}) - t.waitUntil(s) - let r = await t.cacheMatch(e) - if (r); - else - try { - r = await s - } catch (e) { - e instanceof Error && (a = e) - } - if (!r) throw new l('no-response', { url: e.url, error: a }) - return r - } - } - class ev extends es { - constructor(e, t) { - super(({ request: a }) => { - let s = e.getUrlsToPrecacheKeys() - for (let r of (function* ( - e, - { - directoryIndex: t = 'index.html', - ignoreURLParametersMatching: a = [/^utm_/, /^fbclid$/], - cleanURLs: s = !0, - urlManipulation: r, - } = {}, - ) { - let n = new URL(e, location.href) - ;((n.hash = ''), yield n.href) - let i = ((e, t = []) => { - for (let a of [...e.searchParams.keys()]) - t.some((e) => e.test(a)) && e.searchParams.delete(a) - return e - })(n, a) - if ((yield i.href, t && i.pathname.endsWith('/'))) { - let e = new URL(i.href) - ;((e.pathname += t), yield e.href) - } - if (s) { - let e = new URL(i.href) - ;((e.pathname += '.html'), yield e.href) - } - if (r) for (let e of r({ url: n })) yield e.href - })(a.url, t)) { - let t = s.get(r) - if (t) { - let a = e.getIntegrityForPrecacheKey(t) - return { cacheKey: t, integrity: a } - } - } - }, e.precacheStrategy) - } - } - class eq { - _precacheController - constructor({ precacheController: e }) { - this._precacheController = e - } - cacheKeyWillBeUsed = async ({ request: e, params: t }) => { - let a = - t?.cacheKey || this._precacheController.getPrecacheKeyForUrl(e.url) - return a ? new Request(a, { headers: e.headers }) : e - } - } - class eS { - _urlsToCacheKeys = new Map() - _urlsToCacheModes = new Map() - _cacheKeysToIntegrities = new Map() - _concurrentPrecaching - _precacheStrategy - _routes - _defaultHandlerMap - _catchHandler - _requestRules - constructor({ - precacheEntries: e, - precacheOptions: t, - skipWaiting: a = !1, - importScripts: s, - navigationPreload: r = !1, - cacheId: i, - clientsClaim: o = !1, - runtimeCaching: l, - offlineAnalyticsConfig: h, - disableDevLogs: u = !1, - fallbacks: d, - requestRules: m, - } = {}) { - var f - const { - precacheStrategyOptions: g, - precacheRouteOptions: w, - precacheMiscOptions: y, - } = ((e, t = {}) => { - let { - cacheName: a, - plugins: s = [], - fetchOptions: r, - matchOptions: n, - fallbackToNetwork: i, - directoryIndex: o, - ignoreURLParametersMatching: l, - cleanURLs: h, - urlManipulation: u, - cleanupOutdatedCaches: d, - concurrency: m = 10, - navigateFallback: f, - navigateFallbackAllowlist: g, - navigateFallbackDenylist: w, - } = t ?? {} - return { - precacheStrategyOptions: { - cacheName: c(a), - plugins: [...s, new eq({ precacheController: e })], - fetchOptions: r, - matchOptions: n, - fallbackToNetwork: i, - }, - precacheRouteOptions: { - directoryIndex: o, - ignoreURLParametersMatching: l, - cleanURLs: h, - urlManipulation: u, - }, - precacheMiscOptions: { - cleanupOutdatedCaches: d, - concurrency: m, - navigateFallback: f, - navigateFallbackAllowlist: g, - navigateFallbackDenylist: w, - }, - } - })(this, t) - if ( - ((this._concurrentPrecaching = y.concurrency), - (this._precacheStrategy = new er(g)), - (this._routes = new Map()), - (this._defaultHandlerMap = new Map()), - (this._requestRules = m), - (this.handleInstall = this.handleInstall.bind(this)), - (this.handleActivate = this.handleActivate.bind(this)), - (this.handleFetch = this.handleFetch.bind(this)), - (this.handleCache = this.handleCache.bind(this)), - s && s.length > 0 && self.importScripts(...s), - r && - self.registration?.navigationPreload && - self.addEventListener('activate', (e) => { - e.waitUntil( - self.registration.navigationPreload.enable().then(() => {}), - ) - }), - void 0 !== i && - ((e) => { - var t = (t) => { - let a = e[t] - 'string' == typeof a && (n[t] = a) - } - for (let e of Object.keys(n)) t(e) - })({ prefix: i }), - a - ? self.skipWaiting() - : self.addEventListener('message', (e) => { - e.data && 'SKIP_WAITING' === e.data.type && self.skipWaiting() - }), - o && self.addEventListener('activate', () => self.clients.claim()), - e && e.length > 0 && this.addToPrecacheList(e), - y.cleanupOutdatedCaches && - ((f = g.cacheName), - self.addEventListener('activate', (e) => { - e.waitUntil(p(c(f)).then((e) => {})) - })), - this.registerRoute(new ev(this, w)), - y.navigateFallback && - this.registerRoute( - new en(this.createHandlerBoundToUrl(y.navigateFallback), { - allowlist: y.navigateFallbackAllowlist, - denylist: y.navigateFallbackDenylist, - }), - ), - void 0 !== h && - ('boolean' == typeof h - ? h && ey({ serwist: this }) - : ey({ ...h, serwist: this })), - void 0 !== l) - ) { - if (void 0 !== d) { - const e = new e_({ fallbackUrls: d.entries, serwist: this }) - l.forEach((t) => { - t.handler instanceof Z && - !t.handler.plugins.some((e) => 'handlerDidError' in e) && - t.handler.plugins.push(e) - }) - } - for (const e of l) this.registerCapture(e.matcher, e.handler, e.method) - } - u && (self.__WB_DISABLE_DEV_LOGS = !0) - } - get precacheStrategy() { - return this._precacheStrategy - } - get routes() { - return this._routes - } - addEventListeners() { - ;(self.addEventListener('install', this.handleInstall), - self.addEventListener('activate', this.handleActivate), - self.addEventListener('fetch', this.handleFetch), - self.addEventListener('message', this.handleCache)) - } - addToPrecacheList(e) { - let t = [] - for (let a of e) { - 'string' == typeof a - ? t.push(a) - : a && !a.integrity && void 0 === a.revision && t.push(a.url) - let { cacheKey: e, url: s } = ec(a), - r = 'string' != typeof a && a.revision ? 'reload' : 'default' - if (this._urlsToCacheKeys.has(s) && this._urlsToCacheKeys.get(s) !== e) - throw new l('add-to-cache-list-conflicting-entries', { - firstEntry: this._urlsToCacheKeys.get(s), - secondEntry: e, - }) - if ('string' != typeof a && a.integrity) { - if ( - this._cacheKeysToIntegrities.has(e) && - this._cacheKeysToIntegrities.get(e) !== a.integrity - ) - throw new l('add-to-cache-list-conflicting-integrities', { url: s }) - this._cacheKeysToIntegrities.set(e, a.integrity) - } - ;(this._urlsToCacheKeys.set(s, e), this._urlsToCacheModes.set(s, r)) - } - t.length > 0 && - console.warn(`Serwist is precaching URLs without revision info: ${t.join(', ')} -This is generally NOT safe. Learn more at https://bit.ly/wb-precache`) - } - handleInstall(e) { - return ( - this.registerRequestRules(e), - y(e, async () => { - let t = new eo() - ;(this.precacheStrategy.plugins.push(t), - await el( - this._concurrentPrecaching, - Array.from(this._urlsToCacheKeys.entries()), - async ([t, a]) => { - let s = this._cacheKeysToIntegrities.get(a), - r = this._urlsToCacheModes.get(t), - n = new Request(t, { - integrity: s, - cache: r, - credentials: 'same-origin', - }) - await Promise.all( - this.precacheStrategy.handleAll({ - event: e, - request: n, - url: new URL(n.url), - params: { cacheKey: a }, - }), - ) - }, - )) - let { updatedURLs: a, notUpdatedURLs: s } = t - return { updatedURLs: a, notUpdatedURLs: s } - }) - ) - } - async registerRequestRules(e) { - if (this._requestRules && e?.addRoutes) - try { - ;(await e.addRoutes(this._requestRules), - (this._requestRules = void 0)) - } catch (e) { - throw e - } - } - handleActivate(e) { - return y(e, async () => { - let e = await self.caches.open(this.precacheStrategy.cacheName), - t = await e.keys(), - a = new Set(this._urlsToCacheKeys.values()), - s = [] - for (let r of t) a.has(r.url) || (await e.delete(r), s.push(r.url)) - return { deletedCacheRequests: s } - }) - } - handleFetch(e) { - let { request: t } = e, - a = this.handleRequest({ request: t, event: e }) - a && e.respondWith(a) - } - handleCache(e) { - if (e.data && 'CACHE_URLS' === e.data.type) { - let { payload: t } = e.data, - a = Promise.all( - t.urlsToCache.map((t) => { - let a - return ( - (a = 'string' == typeof t ? new Request(t) : new Request(...t)), - this.handleRequest({ request: a, event: e }) - ) - }), - ) - ;(e.waitUntil(a), - e.ports?.[0] && a.then(() => e.ports[0].postMessage(!0))) - } - } - setDefaultHandler(e, t = 'GET') { - this._defaultHandlerMap.set(t, ea(e)) - } - setCatchHandler(e) { - this._catchHandler = ea(e) - } - registerCapture(e, t, a) { - let s = ((e, t, a) => { - if ('string' == typeof e) { - let s = new URL(e, location.href) - return new es(({ url: e }) => e.href === s.href, t, a) - } - if (e instanceof RegExp) return new ei(e, t, a) - if ('function' == typeof e) return new es(e, t, a) - if (e instanceof es) return e - throw new l('unsupported-route-type', { - moduleName: 'serwist', - funcName: 'parseRoute', - paramName: 'capture', - }) - })(e, t, a) - return (this.registerRoute(s), s) - } - registerRoute(e) { - ;(this._routes.has(e.method) || this._routes.set(e.method, []), - this._routes.get(e.method).push(e)) - } - unregisterRoute(e) { - if (!this._routes.has(e.method)) - throw new l('unregister-route-but-not-found-with-method', { - method: e.method, - }) - let t = this._routes.get(e.method).indexOf(e) - if (t > -1) this._routes.get(e.method).splice(t, 1) - else throw new l('unregister-route-route-not-registered') - } - getUrlsToPrecacheKeys() { - return this._urlsToCacheKeys - } - getPrecachedUrls() { - return [...this._urlsToCacheKeys.keys()] - } - getPrecacheKeyForUrl(e) { - let t = new URL(e, location.href) - return this._urlsToCacheKeys.get(t.href) - } - getIntegrityForPrecacheKey(e) { - return this._cacheKeysToIntegrities.get(e) - } - async matchPrecache(e) { - let t = e instanceof Request ? e.url : e, - a = this.getPrecacheKeyForUrl(t) - if (a) - return (await self.caches.open(this.precacheStrategy.cacheName)).match( - a, - ) - } - createHandlerBoundToUrl(e) { - let t = this.getPrecacheKeyForUrl(e) - if (!t) throw new l('non-precached-url', { url: e }) - return (a) => ( - (a.request = new Request(e)), - (a.params = { cacheKey: t, ...a.params }), - this.precacheStrategy.handle(a) - ) - } - handleRequest({ request: e, event: t }) { - let a, - s = new URL(e.url, location.href) - if (!s.protocol.startsWith('http')) return - let r = s.origin === location.origin, - { params: n, route: i } = this.findMatchingRoute({ - event: t, - request: e, - sameOrigin: r, - url: s, - }), - c = i?.handler, - o = e.method - if ( - (!c && - this._defaultHandlerMap.has(o) && - (c = this._defaultHandlerMap.get(o)), - !c) - ) - return - try { - a = c.handle({ url: s, request: e, event: t, params: n }) - } catch (e) { - a = Promise.reject(e) - } - let l = i?.catchHandler - return ( - a instanceof Promise && - (this._catchHandler || l) && - (a = a.catch(async (a) => { - if (l) - try { - return await l.handle({ - url: s, - request: e, - event: t, - params: n, - }) - } catch (e) { - e instanceof Error && (a = e) - } - if (this._catchHandler) - return this._catchHandler.handle({ url: s, request: e, event: t }) - throw a - })), - a - ) - } - findMatchingRoute({ url: e, sameOrigin: t, request: a, event: s }) { - for (let r of this._routes.get(a.method) || []) { - let n, - i = r.match({ url: e, sameOrigin: t, request: a, event: s }) - if (i) - return ( - (Array.isArray((n = i)) && 0 === n.length) || - (i.constructor === Object && 0 === Object.keys(i).length) - ? (n = void 0) - : 'boolean' == typeof i && (n = void 0), - { route: r, params: n } - ) - } - return {} - } - } - let eD = [ - { - matcher: /^https:\/\/fonts\.(?:gstatic)\.com\/.*/i, - handler: new eE({ - cacheName: 'google-fonts-webfonts', - plugins: [ - new ef({ - maxEntries: 4, - maxAgeSeconds: 31536e3, - maxAgeFrom: 'last-used', - }), - ], - }), - }, - { - matcher: /^https:\/\/fonts\.(?:googleapis)\.com\/.*/i, - handler: new eR({ - cacheName: 'google-fonts-stylesheets', - plugins: [ - new ef({ - maxEntries: 4, - maxAgeSeconds: 604800, - maxAgeFrom: 'last-used', - }), - ], - }), - }, - { - matcher: /\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i, - handler: new eR({ - cacheName: 'static-font-assets', - plugins: [ - new ef({ - maxEntries: 4, - maxAgeSeconds: 604800, - maxAgeFrom: 'last-used', - }), - ], - }), - }, - { - matcher: /\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i, - handler: new eR({ - cacheName: 'static-image-assets', - plugins: [ - new ef({ - maxEntries: 64, - maxAgeSeconds: 2592e3, - maxAgeFrom: 'last-used', - }), - ], - }), - }, - { - matcher: /\/_next\/static.+\.js$/i, - handler: new eE({ - cacheName: 'next-static-js-assets', - plugins: [ - new ef({ - maxEntries: 64, - maxAgeSeconds: 86400, - maxAgeFrom: 'last-used', - }), - ], - }), - }, - { - matcher: /\/_next\/image\?url=.+$/i, - handler: new eR({ - cacheName: 'next-image', - plugins: [ - new ef({ - maxEntries: 64, - maxAgeSeconds: 86400, - maxAgeFrom: 'last-used', - }), - ], - }), - }, - { - matcher: /\.(?:mp3|wav|ogg)$/i, - handler: new eE({ - cacheName: 'static-audio-assets', - plugins: [ - new ef({ - maxEntries: 32, - maxAgeSeconds: 86400, - maxAgeFrom: 'last-used', - }), - new eb(), - ], - }), - }, - { - matcher: /\.(?:mp4|webm)$/i, - handler: new eE({ - cacheName: 'static-video-assets', - plugins: [ - new ef({ - maxEntries: 32, - maxAgeSeconds: 86400, - maxAgeFrom: 'last-used', - }), - new eb(), - ], - }), - }, - { - matcher: /\.(?:js)$/i, - handler: new eR({ - cacheName: 'static-js-assets', - plugins: [ - new ef({ - maxEntries: 48, - maxAgeSeconds: 86400, - maxAgeFrom: 'last-used', - }), - ], - }), - }, - { - matcher: /\.(?:css|less)$/i, - handler: new eR({ - cacheName: 'static-style-assets', - plugins: [ - new ef({ - maxEntries: 32, - maxAgeSeconds: 86400, - maxAgeFrom: 'last-used', - }), - ], - }), - }, - { - matcher: /\/_next\/data\/.+\/.+\.json$/i, - handler: new ee({ - cacheName: 'next-data', - plugins: [ - new ef({ - maxEntries: 32, - maxAgeSeconds: 86400, - maxAgeFrom: 'last-used', - }), - ], - }), - }, - { - matcher: /\.(?:json|xml|csv)$/i, - handler: new ee({ - cacheName: 'static-data-assets', - plugins: [ - new ef({ - maxEntries: 32, - maxAgeSeconds: 86400, - maxAgeFrom: 'last-used', - }), - ], - }), - }, - { - matcher: /\/api\/auth\/.*/, - handler: new et({ networkTimeoutSeconds: 10 }), - }, - { - matcher: ({ sameOrigin: e, url: { pathname: t } }) => - e && t.startsWith('/api/'), - method: 'GET', - handler: new ee({ - cacheName: 'apis', - plugins: [ - new ef({ - maxEntries: 16, - maxAgeSeconds: 86400, - maxAgeFrom: 'last-used', - }), - ], - networkTimeoutSeconds: 10, - }), - }, - { - matcher: ({ request: e, url: { pathname: t }, sameOrigin: a }) => - '1' === e.headers.get('RSC') && - '1' === e.headers.get('Next-Router-Prefetch') && - a && - !t.startsWith('/api/'), - handler: new ee({ - cacheName: 'pages-rsc-prefetch', - plugins: [new ef({ maxEntries: 32, maxAgeSeconds: 86400 })], - }), - }, - { - matcher: ({ request: e, url: { pathname: t }, sameOrigin: a }) => - '1' === e.headers.get('RSC') && a && !t.startsWith('/api/'), - handler: new ee({ - cacheName: 'pages-rsc', - plugins: [new ef({ maxEntries: 32, maxAgeSeconds: 86400 })], - }), - }, - { - matcher: ({ request: e, url: { pathname: t }, sameOrigin: a }) => - e.headers.get('Content-Type')?.includes('text/html') && - a && - !t.startsWith('/api/'), - handler: new ee({ - cacheName: 'pages', - plugins: [new ef({ maxEntries: 32, maxAgeSeconds: 86400 })], - }), - }, - { - matcher: ({ url: { pathname: e }, sameOrigin: t }) => - t && !e.startsWith('/api/'), - handler: new ee({ - cacheName: 'others', - plugins: [new ef({ maxEntries: 32, maxAgeSeconds: 86400 })], - }), - }, - { - matcher: ({ sameOrigin: e }) => !e, - handler: new ee({ - cacheName: 'cross-origin', - plugins: [new ef({ maxEntries: 32, maxAgeSeconds: 3600 })], - networkTimeoutSeconds: 10, - }), - }, - { matcher: /.*/i, method: 'GET', handler: new et() }, - ] - new eS({ - precacheEntries: [ - { - revision: 'cf272778e12f5bf80f2f1709a0960823', - url: '/_next/static/1oroKdiAEOMVm2o-tw4uG/_buildManifest.js', - }, - { - revision: 'b6652df95db52feb4daf4eca35380933', - url: '/_next/static/1oroKdiAEOMVm2o-tw4uG/_ssgManifest.js', - }, - { revision: null, url: '/_next/static/chunks/1027-acb32e80c2d2cdaa.js' }, - { revision: null, url: '/_next/static/chunks/1076-c34b0a131dbb5fca.js' }, - { revision: null, url: '/_next/static/chunks/1966.1560d0f43ac9a41a.js' }, - { revision: null, url: '/_next/static/chunks/2176-4acdf7766fb9c08b.js' }, - { revision: null, url: '/_next/static/chunks/2753-a8718780f38ee5c0.js' }, - { revision: null, url: '/_next/static/chunks/318-093fd0dc885ef4e3.js' }, - { revision: null, url: '/_next/static/chunks/3899.cf10152d8085e352.js' }, - { - revision: null, - url: '/_next/static/chunks/4bd1b696-183c3d94a1e703cf.js', - }, - { revision: null, url: '/_next/static/chunks/5772-ad0dd98a68301d1f.js' }, - { revision: null, url: '/_next/static/chunks/583-945d8a6c5ddf0961.js' }, - { revision: null, url: '/_next/static/chunks/6511-5624961f68381161.js' }, - { revision: null, url: '/_next/static/chunks/7173-a9b8cd8c03911115.js' }, - { revision: null, url: '/_next/static/chunks/7196-44f131b92787eadb.js' }, - { revision: null, url: '/_next/static/chunks/7747-268b40c30f7e5995.js' }, - { revision: null, url: '/_next/static/chunks/8500-27ab90e35aa7c15c.js' }, - { revision: null, url: '/_next/static/chunks/8563-9430ff60b594e767.js' }, - { - revision: null, - url: '/_next/static/chunks/app/_global-error/page-421219b80afcb10b.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/_not-found/page-5a5a9eb8db73e824.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/agreement/page-2dbc4e863de83e29.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/api/auth/kakao/authorization-url/route-421219b80afcb10b.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/feed/article/%5Bid%5D/page-7d50c2c79587fb8d.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/feed/page-9b04054e87c5f858.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/feed/payPost/manual/page-e3e4b05d44f70f8a.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/feed/payPost/page-44d7530cf9e15602.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/feed/review/write/%5Bid%5D/page-6fb620ba4d474174.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/feed/write/%5Bid%5D/page-72119b36117cc0a3.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/home/demo/page-c908b5ae6044e6b3.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/home/notify/page-3545b477ab1c204d.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/home/page-287d942ed4b1293c.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/home/search/page-4c119dcb54fcc52d.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/home/search/result/artists/page-99fcf00ccc755803.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/home/search/result/page-5508367b1d983c2d.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/home/search/result/works/page-9b63f0a11349e5b8.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/home/topicroom/page-029d776a06f65211.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/layout-1ea8f427addc98b2.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/library/gallery/page-eafa1624f382ec9e.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/library/list/page-356a41e90eac5b9d.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/login/page-2183d8b4575b360a.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/manifest.webmanifest/route-421219b80afcb10b.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/manual/page-b9fa3f2c7098cd93.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/onboarding/page-7ca41947709188bf.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/page-3a216cc60a192b18.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/pending/page-f69efaeda6e5fba0.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/profile/fix/page-d5c86e001d44c7e7.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/profile/likes/page-f150bcbe1fe3411b.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/profile/myActivity/page-f8e197859dbf666a.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/profile/page-3b020cc72968f032.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/profile/settings/page-aee40c466db7eb3a.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/writers/feed/page-02dee2fa0dab2dc5.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/writers/login/page-421219b80afcb10b.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/writers/login/pending/page-6e5cf34b73d32c42.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/writers/profile/dashboard/page-a232230e989bdc66.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/writers/profile/page-3c1af4b3fdc0fc9b.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/writers/signup/page-2ff934a87ed107e0.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/writers/verify/page-d8fc232411866903.js', - }, - { - revision: null, - url: '/_next/static/chunks/app/offline/page-421219b80afcb10b.js', - }, - { - revision: null, - url: '/_next/static/chunks/framework-ec21dd808c5d3f81.js', - }, - { - revision: null, - url: '/_next/static/chunks/main-app-b5936a24e0441149.js', - }, - { revision: null, url: '/_next/static/chunks/main-d74c3f225dad621c.js' }, - { - revision: null, - url: '/_next/static/chunks/next/dist/client/components/builtin/app-error-421219b80afcb10b.js', - }, - { - revision: null, - url: '/_next/static/chunks/next/dist/client/components/builtin/forbidden-421219b80afcb10b.js', - }, - { - revision: null, - url: '/_next/static/chunks/next/dist/client/components/builtin/global-error-af9e52799384baf8.js', - }, - { - revision: null, - url: '/_next/static/chunks/next/dist/client/components/builtin/not-found-421219b80afcb10b.js', - }, - { - revision: null, - url: '/_next/static/chunks/next/dist/client/components/builtin/unauthorized-421219b80afcb10b.js', - }, - { - revision: '846118c33b2c0e922d7b3a7676f81f6f', - url: '/_next/static/chunks/polyfills-42372ed130431b0a.js', - }, - { - revision: null, - url: '/_next/static/chunks/webpack-1969adce0ef29a13.js', - }, - { revision: null, url: '/_next/static/css/36f523d8697381bc.css' }, - { - revision: '13b67eadd6bbeabc6e9a65501dafe1ae', - url: '/_next/static/media/b471035bc347e80a-s.p.woff2', - }, - { revision: 'acf0b5cc42232bd74259b17c2565ea670fd15ba8', url: '/offline' }, - ], - skipWaiting: !0, - clientsClaim: !0, - navigationPreload: !0, - runtimeCaching: eD, - fallbacks: { - entries: [ - { - url: '/offline', - matcher: ({ request: e }) => 'document' === e.destination, - }, - ], - }, - }).addEventListeners() -})() +(()=>{"use strict";let e,t,a,s,r,n={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"serwist",runtime:"runtime",suffix:"undefined"!=typeof registration?registration.scope:""},i=e=>[n.prefix,e,n.suffix].filter(e=>e&&e.length>0).join("-"),c=e=>e||i(n.precache),o=e=>e||i(n.runtime);class l extends Error{details;constructor(e,t){super(((e,...t)=>{let a=e;return t.length>0&&(a+=` :: ${JSON.stringify(t)}`),a})(e,t)),this.name=e,this.details=t}}function h(e){return new Promise(t=>setTimeout(t,e))}let u=new Set;function d(e,t){let a=new URL(e);for(let e of t)a.searchParams.delete(e);return a.href}async function m(e,t,a,s){let r=d(t.url,a);if(t.url===r)return e.match(t,s);let n={...s,ignoreSearch:!0};for(let i of(await e.keys(t,n)))if(r===d(i.url,a))return e.match(i,s)}class f{promise;resolve;reject;constructor(){this.promise=new Promise((e,t)=>{this.resolve=e,this.reject=t})}}let g=async()=>{for(let e of u)await e()},w="-precache-",p=async(e,t=w)=>{let a=(await self.caches.keys()).filter(a=>a.includes(t)&&a.includes(self.registration.scope)&&a!==e);return await Promise.all(a.map(e=>self.caches.delete(e))),a},y=(e,t)=>{let a=t();return e.waitUntil(a),a},_=(e,t)=>t.some(t=>e instanceof t),x=new WeakMap,b=new WeakMap,E=new WeakMap,R={get(e,t,a){if(e instanceof IDBTransaction){if("done"===t)return x.get(e);if("store"===t)return a.objectStoreNames[1]?void 0:a.objectStore(a.objectStoreNames[0])}return v(e[t])},set:(e,t,a)=>(e[t]=a,!0),has:(e,t)=>e instanceof IDBTransaction&&("done"===t||"store"===t)||t in e};function v(e){if(e instanceof IDBRequest){let t;return t=new Promise((t,a)=>{let s=()=>{e.removeEventListener("success",r),e.removeEventListener("error",n)},r=()=>{t(v(e.result)),s()},n=()=>{a(e.error),s()};e.addEventListener("success",r),e.addEventListener("error",n)}),E.set(t,e),t}if(b.has(e))return b.get(e);let t=function(e){if("function"==typeof e)return(r||(r=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])).includes(e)?function(...t){return e.apply(q(this),t),v(this.request)}:function(...t){return v(e.apply(q(this),t))};return(e instanceof IDBTransaction&&function(e){if(x.has(e))return;let t=new Promise((t,a)=>{let s=()=>{e.removeEventListener("complete",r),e.removeEventListener("error",n),e.removeEventListener("abort",n)},r=()=>{t(),s()},n=()=>{a(e.error||new DOMException("AbortError","AbortError")),s()};e.addEventListener("complete",r),e.addEventListener("error",n),e.addEventListener("abort",n)});x.set(e,t)}(e),_(e,s||(s=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])))?new Proxy(e,R):e}(e);return t!==e&&(b.set(e,t),E.set(t,e)),t}let q=e=>E.get(e);function S(e,t,{blocked:a,upgrade:s,blocking:r,terminated:n}={}){let i=indexedDB.open(e,t),c=v(i);return s&&i.addEventListener("upgradeneeded",e=>{s(v(i.result),e.oldVersion,e.newVersion,v(i.transaction),e)}),a&&i.addEventListener("blocked",e=>a(e.oldVersion,e.newVersion,e)),c.then(e=>{n&&e.addEventListener("close",()=>n()),r&&e.addEventListener("versionchange",e=>r(e.oldVersion,e.newVersion,e))}).catch(()=>{}),c}let D=["get","getKey","getAll","getAllKeys","count"],N=["put","add","delete","clear"],C=new Map;function T(e,t){if(!(e instanceof IDBDatabase&&!(t in e)&&"string"==typeof t))return;if(C.get(t))return C.get(t);let a=t.replace(/FromIndex$/,""),s=t!==a,r=N.includes(a);if(!(a in(s?IDBIndex:IDBObjectStore).prototype)||!(r||D.includes(a)))return;let n=async function(e,...t){let n=this.transaction(e,r?"readwrite":"readonly"),i=n.store;return s&&(i=i.index(t.shift())),(await Promise.all([i[a](...t),r&&n.done]))[0]};return C.set(t,n),n}R={...e=R,get:(t,a,s)=>T(t,a)||e.get(t,a,s),has:(t,a)=>!!T(t,a)||e.has(t,a)};let P=["continue","continuePrimaryKey","advance"],k={},A=new WeakMap,I=new WeakMap,U={get(e,t){if(!P.includes(t))return e[t];let a=k[t];return a||(a=k[t]=function(...e){A.set(this,I.get(this)[t](...e))}),a}};async function*L(...e){let t=this;if(t instanceof IDBCursor||(t=await t.openCursor(...e)),!t)return;let a=new Proxy(t,U);for(I.set(a,t),E.set(a,q(t));t;)yield a,t=await (A.get(a)||t.continue()),A.delete(a)}function F(e,t){return t===Symbol.asyncIterator&&_(e,[IDBIndex,IDBObjectStore,IDBCursor])||"iterate"===t&&_(e,[IDBIndex,IDBObjectStore])}R={...t=R,get:(e,a,s)=>F(e,a)?L:t.get(e,a,s),has:(e,a)=>F(e,a)||t.has(e,a)};let M=async(e,t)=>{let s=null;if(e.url&&(s=new URL(e.url).origin),s!==self.location.origin)throw new l("cross-origin-copy-response",{origin:s});let r=e.clone(),n={headers:new Headers(r.headers),status:r.status,statusText:r.statusText},i=t?t(n):n,c=!function(){if(void 0===a){let e=new Response("");if("body"in e)try{new Response(e.body),a=!0}catch{a=!1}a=!1}return a}()?await r.blob():r.body;return new Response(c,i)},O="requests",B="queueName";class K{_db=null;async addEntry(e){let t=(await this.getDb()).transaction(O,"readwrite",{durability:"relaxed"});await t.store.add(e),await t.done}async getFirstEntryId(){let e=await this.getDb(),t=await e.transaction(O).store.openCursor();return t?.value.id}async getAllEntriesByQueueName(e){let t=await this.getDb();return await t.getAllFromIndex(O,B,IDBKeyRange.only(e))||[]}async getEntryCountByQueueName(e){return(await this.getDb()).countFromIndex(O,B,IDBKeyRange.only(e))}async deleteEntry(e){let t=await this.getDb();await t.delete(O,e)}async getFirstEntryByQueueName(e){return await this.getEndEntryFromIndex(IDBKeyRange.only(e),"next")}async getLastEntryByQueueName(e){return await this.getEndEntryFromIndex(IDBKeyRange.only(e),"prev")}async getEndEntryFromIndex(e,t){let a=await this.getDb(),s=await a.transaction(O).store.index(B).openCursor(e,t);return s?.value}async getDb(){return this._db||(this._db=await S("serwist-background-sync",3,{upgrade:this._upgradeDb})),this._db}_upgradeDb(e,t){t>0&&t<3&&e.objectStoreNames.contains(O)&&e.deleteObjectStore(O),e.createObjectStore(O,{autoIncrement:!0,keyPath:"id"}).createIndex(B,B,{unique:!1})}}class W{_queueName;_queueDb;constructor(e){this._queueName=e,this._queueDb=new K}async pushEntry(e){delete e.id,e.queueName=this._queueName,await this._queueDb.addEntry(e)}async unshiftEntry(e){let t=await this._queueDb.getFirstEntryId();t?e.id=t-1:delete e.id,e.queueName=this._queueName,await this._queueDb.addEntry(e)}async popEntry(){return this._removeEntry(await this._queueDb.getLastEntryByQueueName(this._queueName))}async shiftEntry(){return this._removeEntry(await this._queueDb.getFirstEntryByQueueName(this._queueName))}async getAll(){return await this._queueDb.getAllEntriesByQueueName(this._queueName)}async size(){return await this._queueDb.getEntryCountByQueueName(this._queueName)}async deleteEntry(e){await this._queueDb.deleteEntry(e)}async _removeEntry(e){return e&&await this.deleteEntry(e.id),e}}let j=["method","referrer","referrerPolicy","mode","credentials","cache","redirect","integrity","keepalive"];class ${_requestData;static async fromRequest(e){let t={url:e.url,headers:{}};for(let a of("GET"!==e.method&&(t.body=await e.clone().arrayBuffer()),e.headers.forEach((e,a)=>{t.headers[a]=e}),j))void 0!==e[a]&&(t[a]=e[a]);return new $(t)}constructor(e){"navigate"===e.mode&&(e.mode="same-origin"),this._requestData=e}toObject(){let e=Object.assign({},this._requestData);return e.headers=Object.assign({},this._requestData.headers),e.body&&(e.body=e.body.slice(0)),e}toRequest(){return new Request(this._requestData.url,this._requestData)}clone(){return new $(this.toObject())}}let H="serwist-background-sync",G=new Set,Q=e=>{let t={request:new $(e.requestData).toRequest(),timestamp:e.timestamp};return e.metadata&&(t.metadata=e.metadata),t};class V{_name;_onSync;_maxRetentionTime;_queueStore;_forceSyncFallback;_syncInProgress=!1;_requestsAddedDuringSync=!1;constructor(e,{forceSyncFallback:t,onSync:a,maxRetentionTime:s}={}){if(G.has(e))throw new l("duplicate-queue-name",{name:e});G.add(e),this._name=e,this._onSync=a||this.replayRequests,this._maxRetentionTime=s||10080,this._forceSyncFallback=!!t,this._queueStore=new W(this._name),this._addSyncListener()}get name(){return this._name}async pushRequest(e){await this._addRequest(e,"push")}async unshiftRequest(e){await this._addRequest(e,"unshift")}async popRequest(){return this._removeRequest("pop")}async shiftRequest(){return this._removeRequest("shift")}async getAll(){let e=await this._queueStore.getAll(),t=Date.now(),a=[];for(let s of e){let e=60*this._maxRetentionTime*1e3;t-s.timestamp>e?await this._queueStore.deleteEntry(s.id):a.push(Q(s))}return a}async size(){return await this._queueStore.size()}async _addRequest({request:e,metadata:t,timestamp:a=Date.now()},s){let r={requestData:(await $.fromRequest(e.clone())).toObject(),timestamp:a};switch(t&&(r.metadata=t),s){case"push":await this._queueStore.pushEntry(r);break;case"unshift":await this._queueStore.unshiftEntry(r)}this._syncInProgress?this._requestsAddedDuringSync=!0:await this.registerSync()}async _removeRequest(e){let t,a=Date.now();switch(e){case"pop":t=await this._queueStore.popEntry();break;case"shift":t=await this._queueStore.shiftEntry()}if(t){let s=60*this._maxRetentionTime*1e3;return a-t.timestamp>s?this._removeRequest(e):Q(t)}}async replayRequests(){let e;for(;e=await this.shiftRequest();)try{await fetch(e.request.clone())}catch{throw await this.unshiftRequest(e),new l("queue-replay-failed",{name:this._name})}}async registerSync(){if("sync"in self.registration&&!this._forceSyncFallback)try{await self.registration.sync.register(`${H}:${this._name}`)}catch(e){}}_addSyncListener(){"sync"in self.registration&&!this._forceSyncFallback?self.addEventListener("sync",e=>{if(e.tag===`${H}:${this._name}`){let t=async()=>{let t;this._syncInProgress=!0;try{await this._onSync({queue:this})}catch(e){if(e instanceof Error)throw e}finally{this._requestsAddedDuringSync&&!(t&&!e.lastChance)&&await this.registerSync(),this._syncInProgress=!1,this._requestsAddedDuringSync=!1}};e.waitUntil(t())}}):this._onSync({queue:this})}static get _queueNames(){return G}}class z{_queue;constructor(e,t){this._queue=new V(e,t)}async fetchDidFail({request:e}){await this._queue.pushRequest({request:e})}}let J={cacheWillUpdate:async({response:e})=>200===e.status||0===e.status?e:null};function X(e){return"string"==typeof e?new Request(e):e}class Y{event;request;url;params;_cacheKeys={};_strategy;_handlerDeferred;_extendLifetimePromises;_plugins;_pluginStateMap;constructor(e,t){for(const a of(this.event=t.event,this.request=t.request,t.url&&(this.url=t.url,this.params=t.params),this._strategy=e,this._handlerDeferred=new f,this._extendLifetimePromises=[],this._plugins=[...e.plugins],this._pluginStateMap=new Map,this._plugins))this._pluginStateMap.set(a,{});this.event.waitUntil(this._handlerDeferred.promise)}async fetch(e){let{event:t}=this,a=X(e),s=await this.getPreloadResponse();if(s)return s;let r=this.hasCallback("fetchDidFail")?a.clone():null;try{for(let e of this.iterateCallbacks("requestWillFetch"))a=await e({request:a.clone(),event:t})}catch(e){if(e instanceof Error)throw new l("plugin-error-request-will-fetch",{thrownErrorMessage:e.message})}let n=a.clone();try{let e;for(let s of(e=await fetch(a,"navigate"===a.mode?void 0:this._strategy.fetchOptions),this.iterateCallbacks("fetchDidSucceed")))e=await s({event:t,request:n,response:e});return e}catch(e){throw r&&await this.runCallbacks("fetchDidFail",{error:e,event:t,originalRequest:r.clone(),request:n.clone()}),e}}async fetchAndCachePut(e){let t=await this.fetch(e),a=t.clone();return this.waitUntil(this.cachePut(e,a)),t}async cacheMatch(e){let t,a=X(e),{cacheName:s,matchOptions:r}=this._strategy,n=await this.getCacheKey(a,"read"),i={...r,cacheName:s};for(let e of(t=await caches.match(n,i),this.iterateCallbacks("cachedResponseWillBeUsed")))t=await e({cacheName:s,matchOptions:r,cachedResponse:t,request:n,event:this.event})||void 0;return t}async cachePut(e,t){let a=X(e);await h(0);let s=await this.getCacheKey(a,"write");if(!t)throw new l("cache-put-with-no-response",{url:new URL(String(s.url),location.href).href.replace(RegExp(`^${location.origin}`),"")});let r=await this._ensureResponseSafeToCache(t);if(!r)return!1;let{cacheName:n,matchOptions:i}=this._strategy,c=await self.caches.open(n),o=this.hasCallback("cacheDidUpdate"),u=o?await m(c,s.clone(),["__WB_REVISION__"],i):null;try{await c.put(s,o?r.clone():r)}catch(e){if(e instanceof Error)throw"QuotaExceededError"===e.name&&await g(),e}for(let e of this.iterateCallbacks("cacheDidUpdate"))await e({cacheName:n,oldResponse:u,newResponse:r.clone(),request:s,event:this.event});return!0}async getCacheKey(e,t){let a=`${e.url} | ${t}`;if(!this._cacheKeys[a]){let s=e;for(let e of this.iterateCallbacks("cacheKeyWillBeUsed"))s=X(await e({mode:t,request:s,event:this.event,params:this.params}));this._cacheKeys[a]=s}return this._cacheKeys[a]}hasCallback(e){for(let t of this._strategy.plugins)if(e in t)return!0;return!1}async runCallbacks(e,t){for(let a of this.iterateCallbacks(e))await a(t)}*iterateCallbacks(e){for(let t of this._strategy.plugins)if("function"==typeof t[e]){let a=this._pluginStateMap.get(t),s=s=>{let r={...s,state:a};return t[e](r)};yield s}}waitUntil(e){return this._extendLifetimePromises.push(e),e}async doneWaiting(){let e;for(;e=this._extendLifetimePromises.shift();)await e}destroy(){this._handlerDeferred.resolve(null)}async getPreloadResponse(){if(this.event instanceof FetchEvent&&"navigate"===this.event.request.mode&&"preloadResponse"in this.event)try{let e=await this.event.preloadResponse;if(e)return e}catch(e){}}async _ensureResponseSafeToCache(e){let t=e,a=!1;for(let e of this.iterateCallbacks("cacheWillUpdate"))if(t=await e({request:this.request,response:t,event:this.event})||void 0,a=!0,!t)break;return!a&&t&&200!==t.status&&(t=void 0),t}}class Z{cacheName;plugins;fetchOptions;matchOptions;constructor(e={}){this.cacheName=o(e.cacheName),this.plugins=e.plugins||[],this.fetchOptions=e.fetchOptions,this.matchOptions=e.matchOptions}handle(e){let[t]=this.handleAll(e);return t}handleAll(e){e instanceof FetchEvent&&(e={event:e,request:e.request});let t=e.event,a="string"==typeof e.request?new Request(e.request):e.request,s=new Y(this,e.url?{event:t,request:a,url:e.url,params:e.params}:{event:t,request:a}),r=this._getResponse(s,a,t),n=this._awaitComplete(r,s,a,t);return[r,n]}async _getResponse(e,t,a){let s;await e.runCallbacks("handlerWillStart",{event:a,request:t});try{if(s=await this._handle(t,e),void 0===s||"error"===s.type)throw new l("no-response",{url:t.url})}catch(r){if(r instanceof Error){for(let n of e.iterateCallbacks("handlerDidError"))if(void 0!==(s=await n({error:r,event:a,request:t})))break}if(!s)throw r}for(let r of e.iterateCallbacks("handlerWillRespond"))s=await r({event:a,request:t,response:s});return s}async _awaitComplete(e,t,a,s){let r,n;try{r=await e}catch{}try{await t.runCallbacks("handlerDidRespond",{event:s,request:a,response:r}),await t.doneWaiting()}catch(e){e instanceof Error&&(n=e)}if(await t.runCallbacks("handlerDidComplete",{event:s,request:a,response:r,error:n}),t.destroy(),n)throw n}}class ee extends Z{_networkTimeoutSeconds;constructor(e={}){super(e),this.plugins.some(e=>"cacheWillUpdate"in e)||this.plugins.unshift(J),this._networkTimeoutSeconds=e.networkTimeoutSeconds||0}async _handle(e,t){let a,s=[],r=[];if(this._networkTimeoutSeconds){let{id:n,promise:i}=this._getTimeoutPromise({request:e,logs:s,handler:t});a=n,r.push(i)}let n=this._getNetworkPromise({timeoutId:a,request:e,logs:s,handler:t});r.push(n);let i=await t.waitUntil((async()=>await t.waitUntil(Promise.race(r))||await n)());if(!i)throw new l("no-response",{url:e.url});return i}_getTimeoutPromise({request:e,logs:t,handler:a}){let s;return{promise:new Promise(t=>{s=setTimeout(async()=>{t(await a.cacheMatch(e))},1e3*this._networkTimeoutSeconds)}),id:s}}async _getNetworkPromise({timeoutId:e,request:t,logs:a,handler:s}){let r,n;try{n=await s.fetchAndCachePut(t)}catch(e){e instanceof Error&&(r=e)}return e&&clearTimeout(e),(r||!n)&&(n=await s.cacheMatch(t)),n}}class et extends Z{_networkTimeoutSeconds;constructor(e={}){super(e),this._networkTimeoutSeconds=e.networkTimeoutSeconds||0}async _handle(e,t){let a,s;try{let a=[t.fetch(e)];if(this._networkTimeoutSeconds){let e=h(1e3*this._networkTimeoutSeconds);a.push(e)}if(!(s=await Promise.race(a)))throw Error(`Timed out the network response after ${this._networkTimeoutSeconds} seconds.`)}catch(e){e instanceof Error&&(a=e)}if(!s)throw new l("no-response",{url:e.url,error:a});return s}}let ea=e=>e&&"object"==typeof e?e:{handle:e};class es{handler;match;method;catchHandler;constructor(e,t,a="GET"){this.handler=ea(t),this.match=e,this.method=a}setCatchHandler(e){this.catchHandler=ea(e)}}class er extends Z{_fallbackToNetwork;static defaultPrecacheCacheabilityPlugin={cacheWillUpdate:async({response:e})=>!e||e.status>=400?null:e};static copyRedirectedCacheableResponsesPlugin={cacheWillUpdate:async({response:e})=>e.redirected?await M(e):e};constructor(e={}){e.cacheName=c(e.cacheName),super(e),this._fallbackToNetwork=!1!==e.fallbackToNetwork,this.plugins.push(er.copyRedirectedCacheableResponsesPlugin)}async _handle(e,t){let a=await t.getPreloadResponse();if(a)return a;let s=await t.cacheMatch(e);return s||(t.event&&"install"===t.event.type?await this._handleInstall(e,t):await this._handleFetch(e,t))}async _handleFetch(e,t){let a,s=t.params||{};if(this._fallbackToNetwork){let r=s.integrity,n=e.integrity,i=!n||n===r;a=await t.fetch(new Request(e,{integrity:"no-cors"!==e.mode?n||r:void 0})),r&&i&&"no-cors"!==e.mode&&(this._useDefaultCacheabilityPluginIfNeeded(),await t.cachePut(e,a.clone()))}else throw new l("missing-precache-entry",{cacheName:this.cacheName,url:e.url});return a}async _handleInstall(e,t){this._useDefaultCacheabilityPluginIfNeeded();let a=await t.fetch(e);if(!await t.cachePut(e,a.clone()))throw new l("bad-precaching-response",{url:e.url,status:a.status});return a}_useDefaultCacheabilityPluginIfNeeded(){let e=null,t=0;for(let[a,s]of this.plugins.entries())s!==er.copyRedirectedCacheableResponsesPlugin&&(s===er.defaultPrecacheCacheabilityPlugin&&(e=a),s.cacheWillUpdate&&t++);0===t?this.plugins.push(er.defaultPrecacheCacheabilityPlugin):t>1&&null!==e&&this.plugins.splice(e,1)}}class en extends es{_allowlist;_denylist;constructor(e,{allowlist:t=[/./],denylist:a=[]}={}){super(e=>this._match(e),e),this._allowlist=t,this._denylist=a}_match({url:e,request:t}){if(t&&"navigate"!==t.mode)return!1;let a=e.pathname+e.search;for(let e of this._denylist)if(e.test(a))return!1;return!!this._allowlist.some(e=>e.test(a))}}class ei extends es{constructor(e,t,a){super(({url:t})=>{let a=e.exec(t.href);if(a)return t.origin!==location.origin&&0!==a.index?void 0:a.slice(1)},t,a)}}let ec=e=>{if(!e)throw new l("add-to-cache-list-unexpected-type",{entry:e});if("string"==typeof e){let t=new URL(e,location.href);return{cacheKey:t.href,url:t.href}}let{revision:t,url:a}=e;if(!a)throw new l("add-to-cache-list-unexpected-type",{entry:e});if(!t){let e=new URL(a,location.href);return{cacheKey:e.href,url:e.href}}let s=new URL(a,location.href),r=new URL(a,location.href);return s.searchParams.set("__WB_REVISION__",t),{cacheKey:s.href,url:r.href}};class eo{updatedURLs=[];notUpdatedURLs=[];handlerWillStart=async({request:e,state:t})=>{t&&(t.originalRequest=e)};cachedResponseWillBeUsed=async({event:e,state:t,cachedResponse:a})=>{if("install"===e.type&&t?.originalRequest&&t.originalRequest instanceof Request){let e=t.originalRequest.url;a?this.notUpdatedURLs.push(e):this.updatedURLs.push(e)}return a}}let el=async(e,t,a)=>{let s=t.map((e,t)=>({index:t,item:e})),r=async e=>{let t=[];for(;;){let r=s.pop();if(!r)return e(t);let n=await a(r.item);t.push({result:n,index:r.index})}},n=Array.from({length:e},()=>new Promise(r));return(await Promise.all(n)).flat().sort((e,t)=>e.indexe.result)};"undefined"!=typeof navigator&&/^((?!chrome|android).)*safari/i.test(navigator.userAgent);let eh="cache-entries",eu=e=>{let t=new URL(e,location.href);return t.hash="",t.href};class ed{_cacheName;_db=null;constructor(e){this._cacheName=e}_getId(e){return`${this._cacheName}|${eu(e)}`}_upgradeDb(e){let t=e.createObjectStore(eh,{keyPath:"id"});t.createIndex("cacheName","cacheName",{unique:!1}),t.createIndex("timestamp","timestamp",{unique:!1})}_upgradeDbAndDeleteOldDbs(e){this._upgradeDb(e),this._cacheName&&function(e,{blocked:t}={}){let a=indexedDB.deleteDatabase(e);t&&a.addEventListener("blocked",e=>t(e.oldVersion,e)),v(a).then(()=>void 0)}(this._cacheName)}async setTimestamp(e,t){e=eu(e);let a={id:this._getId(e),cacheName:this._cacheName,url:e,timestamp:t},s=(await this.getDb()).transaction(eh,"readwrite",{durability:"relaxed"});await s.store.put(a),await s.done}async getTimestamp(e){let t=await this.getDb(),a=await t.get(eh,this._getId(e));return a?.timestamp}async expireEntries(e,t){let a=await this.getDb(),s=await a.transaction(eh,"readwrite").store.index("timestamp").openCursor(null,"prev"),r=[],n=0;for(;s;){let a=s.value;a.cacheName===this._cacheName&&(e&&a.timestamp=t?(s.delete(),r.push(a.url)):n++),s=await s.continue()}return r}async getDb(){return this._db||(this._db=await S("serwist-expiration",1,{upgrade:this._upgradeDbAndDeleteOldDbs.bind(this)})),this._db}}class em{_isRunning=!1;_rerunRequested=!1;_maxEntries;_maxAgeSeconds;_matchOptions;_cacheName;_timestampModel;constructor(e,t={}){this._maxEntries=t.maxEntries,this._maxAgeSeconds=t.maxAgeSeconds,this._matchOptions=t.matchOptions,this._cacheName=e,this._timestampModel=new ed(e)}async expireEntries(){if(this._isRunning){this._rerunRequested=!0;return}this._isRunning=!0;let e=this._maxAgeSeconds?Date.now()-1e3*this._maxAgeSeconds:0,t=await this._timestampModel.expireEntries(e,this._maxEntries),a=await self.caches.open(this._cacheName);for(let e of t)await a.delete(e,this._matchOptions);this._isRunning=!1,this._rerunRequested&&(this._rerunRequested=!1,this.expireEntries())}async updateTimestamp(e){await this._timestampModel.setTimestamp(e,Date.now())}async isURLExpired(e){if(!this._maxAgeSeconds)return!1;let t=await this._timestampModel.getTimestamp(e),a=Date.now()-1e3*this._maxAgeSeconds;return void 0===t||tthis.deleteCacheAndMetadata(),u.add(t))}_getCacheExpiration(e){if(e===o())throw new l("expire-custom-caches-only");let t=this._cacheExpirations.get(e);return t||(t=new em(e,this._config),this._cacheExpirations.set(e,t)),t}cachedResponseWillBeUsed({event:e,cacheName:t,request:a,cachedResponse:s}){if(!s)return null;let r=this._isResponseDateFresh(s),n=this._getCacheExpiration(t),i="last-used"===this._config.maxAgeFrom,c=(async()=>{i&&await n.updateTimestamp(a.url),await n.expireEntries()})();try{e.waitUntil(c)}catch{}return r?s:null}_isResponseDateFresh(e){if("last-used"===this._config.maxAgeFrom)return!0;let t=Date.now();if(!this._config.maxAgeSeconds)return!0;let a=this._getDateHeaderTimestamp(e);return null===a||a>=t-1e3*this._config.maxAgeSeconds}_getDateHeaderTimestamp(e){if(!e.headers.has("date"))return null;let t=new Date(e.headers.get("date")).getTime();return Number.isNaN(t)?null:t}async cacheDidUpdate({cacheName:e,request:t}){let a=this._getCacheExpiration(e);await a.updateTimestamp(t.url),await a.expireEntries()}async deleteCacheAndMetadata(){for(let[e,t]of this._cacheExpirations)await self.caches.delete(e),await t.delete();this._cacheExpirations=new Map}}let eg="www.google-analytics.com",ew="www.googletagmanager.com",ep=/^\/(\w+\/)?collect/,ey=({serwist:e,cacheName:t,...a})=>{let s,r,c=t||i(n.googleAnalytics),o=new z("serwist-google-analytics",{maxRetentionTime:2880,onSync:async({queue:e})=>{let t;for(;t=await e.shiftRequest();){let{request:s,timestamp:r}=t,n=new URL(s.url);try{let e="POST"===s.method?new URLSearchParams(await s.clone().text()):n.searchParams,t=r-(Number(e.get("qt"))||0),i=Date.now()-t;if(e.set("qt",String(i)),a.parameterOverrides)for(let t of Object.keys(a.parameterOverrides)){let s=a.parameterOverrides[t];e.set(t,s)}"function"==typeof a.hitFilter&&a.hitFilter.call(null,e),await fetch(new Request(n.origin+n.pathname,{body:e.toString(),method:"POST",mode:"cors",credentials:"omit",headers:{"Content-Type":"text/plain"}}))}catch(a){throw await e.unshiftRequest(t),a}}}});for(let t of[new es(({url:e})=>e.hostname===ew&&"/gtm.js"===e.pathname,new ee({cacheName:c}),"GET"),new es(({url:e})=>e.hostname===eg&&"/analytics.js"===e.pathname,new ee({cacheName:c}),"GET"),new es(({url:e})=>e.hostname===ew&&"/gtag/js"===e.pathname,new ee({cacheName:c}),"GET"),new es(s=({url:e})=>e.hostname===eg&&ep.test(e.pathname),r=new et({plugins:[o]}),"GET"),new es(s,r,"POST")])e.registerRoute(t)};class e_{_fallbackUrls;_serwist;constructor({fallbackUrls:e,serwist:t}){this._fallbackUrls=e,this._serwist=t}async handlerDidError(e){for(let t of this._fallbackUrls)if("string"==typeof t){let e=await this._serwist.matchPrecache(t);if(void 0!==e)return e}else if(t.matcher(e)){let e=await this._serwist.matchPrecache(t.url);if(void 0!==e)return e}}}let ex=async(e,t)=>{try{if(206===t.status)return t;let a=e.headers.get("range");if(!a)throw new l("no-range-header");let s=(e=>{let t=e.trim().toLowerCase();if(!t.startsWith("bytes="))throw new l("unit-must-be-bytes",{normalizedRangeHeader:t});if(t.includes(","))throw new l("single-range-only",{normalizedRangeHeader:t});let a=/(\d*)-(\d*)/.exec(t);if(!a||!(a[1]||a[2]))throw new l("invalid-range-values",{normalizedRangeHeader:t});return{start:""===a[1]?void 0:Number(a[1]),end:""===a[2]?void 0:Number(a[2])}})(a),r=await t.blob(),n=((e,t,a)=>{let s,r,n=e.size;if(a&&a>n||t&&t<0)throw new l("range-not-satisfiable",{size:n,end:a,start:t});return void 0!==t&&void 0!==a?(s=t,r=a+1):void 0!==t&&void 0===a?(s=t,r=n):void 0!==a&&void 0===t&&(s=n-a,r=n),{start:s,end:r}})(r,s.start,s.end),i=r.slice(n.start,n.end),c=i.size,o=new Response(i,{status:206,statusText:"Partial Content",headers:t.headers});return o.headers.set("Content-Length",String(c)),o.headers.set("Content-Range",`bytes ${n.start}-${n.end-1}/${r.size}`),o}catch(e){return new Response("",{status:416,statusText:"Range Not Satisfiable"})}};class eb{cachedResponseWillBeUsed=async({request:e,cachedResponse:t})=>t&&e.headers.has("range")?await ex(e,t):t}class eE extends Z{async _handle(e,t){let a,s=await t.cacheMatch(e);if(!s)try{s=await t.fetchAndCachePut(e)}catch(e){e instanceof Error&&(a=e)}if(!s)throw new l("no-response",{url:e.url,error:a});return s}}class eR extends Z{constructor(e={}){super(e),this.plugins.some(e=>"cacheWillUpdate"in e)||this.plugins.unshift(J)}async _handle(e,t){let a,s=t.fetchAndCachePut(e).catch(()=>{});t.waitUntil(s);let r=await t.cacheMatch(e);if(r);else try{r=await s}catch(e){e instanceof Error&&(a=e)}if(!r)throw new l("no-response",{url:e.url,error:a});return r}}class ev extends es{constructor(e,t){super(({request:a})=>{let s=e.getUrlsToPrecacheKeys();for(let r of function*(e,{directoryIndex:t="index.html",ignoreURLParametersMatching:a=[/^utm_/,/^fbclid$/],cleanURLs:s=!0,urlManipulation:r}={}){let n=new URL(e,location.href);n.hash="",yield n.href;let i=((e,t=[])=>{for(let a of[...e.searchParams.keys()])t.some(e=>e.test(a))&&e.searchParams.delete(a);return e})(n,a);if(yield i.href,t&&i.pathname.endsWith("/")){let e=new URL(i.href);e.pathname+=t,yield e.href}if(s){let e=new URL(i.href);e.pathname+=".html",yield e.href}if(r)for(let e of r({url:n}))yield e.href}(a.url,t)){let t=s.get(r);if(t){let a=e.getIntegrityForPrecacheKey(t);return{cacheKey:t,integrity:a}}}},e.precacheStrategy)}}class eq{_precacheController;constructor({precacheController:e}){this._precacheController=e}cacheKeyWillBeUsed=async({request:e,params:t})=>{let a=t?.cacheKey||this._precacheController.getPrecacheKeyForUrl(e.url);return a?new Request(a,{headers:e.headers}):e}}class eS{_urlsToCacheKeys=new Map;_urlsToCacheModes=new Map;_cacheKeysToIntegrities=new Map;_concurrentPrecaching;_precacheStrategy;_routes;_defaultHandlerMap;_catchHandler;_requestRules;constructor({precacheEntries:e,precacheOptions:t,skipWaiting:a=!1,importScripts:s,navigationPreload:r=!1,cacheId:i,clientsClaim:o=!1,runtimeCaching:l,offlineAnalyticsConfig:h,disableDevLogs:u=!1,fallbacks:d,requestRules:m}={}){var f;const{precacheStrategyOptions:g,precacheRouteOptions:w,precacheMiscOptions:y}=((e,t={})=>{let{cacheName:a,plugins:s=[],fetchOptions:r,matchOptions:n,fallbackToNetwork:i,directoryIndex:o,ignoreURLParametersMatching:l,cleanURLs:h,urlManipulation:u,cleanupOutdatedCaches:d,concurrency:m=10,navigateFallback:f,navigateFallbackAllowlist:g,navigateFallbackDenylist:w}=t??{};return{precacheStrategyOptions:{cacheName:c(a),plugins:[...s,new eq({precacheController:e})],fetchOptions:r,matchOptions:n,fallbackToNetwork:i},precacheRouteOptions:{directoryIndex:o,ignoreURLParametersMatching:l,cleanURLs:h,urlManipulation:u},precacheMiscOptions:{cleanupOutdatedCaches:d,concurrency:m,navigateFallback:f,navigateFallbackAllowlist:g,navigateFallbackDenylist:w}}})(this,t);if(this._concurrentPrecaching=y.concurrency,this._precacheStrategy=new er(g),this._routes=new Map,this._defaultHandlerMap=new Map,this._requestRules=m,this.handleInstall=this.handleInstall.bind(this),this.handleActivate=this.handleActivate.bind(this),this.handleFetch=this.handleFetch.bind(this),this.handleCache=this.handleCache.bind(this),s&&s.length>0&&self.importScripts(...s),r&&self.registration?.navigationPreload&&self.addEventListener("activate",e=>{e.waitUntil(self.registration.navigationPreload.enable().then(()=>{}))}),void 0!==i&&(e=>{var t=t=>{let a=e[t];"string"==typeof a&&(n[t]=a)};for(let e of Object.keys(n))t(e)})({prefix:i}),a?self.skipWaiting():self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),o&&self.addEventListener("activate",()=>self.clients.claim()),e&&e.length>0&&this.addToPrecacheList(e),y.cleanupOutdatedCaches&&(f=g.cacheName,self.addEventListener("activate",e=>{e.waitUntil(p(c(f)).then(e=>{}))})),this.registerRoute(new ev(this,w)),y.navigateFallback&&this.registerRoute(new en(this.createHandlerBoundToUrl(y.navigateFallback),{allowlist:y.navigateFallbackAllowlist,denylist:y.navigateFallbackDenylist})),void 0!==h&&("boolean"==typeof h?h&&ey({serwist:this}):ey({...h,serwist:this})),void 0!==l){if(void 0!==d){const e=new e_({fallbackUrls:d.entries,serwist:this});l.forEach(t=>{t.handler instanceof Z&&!t.handler.plugins.some(e=>"handlerDidError"in e)&&t.handler.plugins.push(e)})}for(const e of l)this.registerCapture(e.matcher,e.handler,e.method)}u&&(self.__WB_DISABLE_DEV_LOGS=!0)}get precacheStrategy(){return this._precacheStrategy}get routes(){return this._routes}addEventListeners(){self.addEventListener("install",this.handleInstall),self.addEventListener("activate",this.handleActivate),self.addEventListener("fetch",this.handleFetch),self.addEventListener("message",this.handleCache)}addToPrecacheList(e){let t=[];for(let a of e){"string"==typeof a?t.push(a):a&&!a.integrity&&void 0===a.revision&&t.push(a.url);let{cacheKey:e,url:s}=ec(a),r="string"!=typeof a&&a.revision?"reload":"default";if(this._urlsToCacheKeys.has(s)&&this._urlsToCacheKeys.get(s)!==e)throw new l("add-to-cache-list-conflicting-entries",{firstEntry:this._urlsToCacheKeys.get(s),secondEntry:e});if("string"!=typeof a&&a.integrity){if(this._cacheKeysToIntegrities.has(e)&&this._cacheKeysToIntegrities.get(e)!==a.integrity)throw new l("add-to-cache-list-conflicting-integrities",{url:s});this._cacheKeysToIntegrities.set(e,a.integrity)}this._urlsToCacheKeys.set(s,e),this._urlsToCacheModes.set(s,r)}t.length>0&&console.warn(`Serwist is precaching URLs without revision info: ${t.join(", ")} +This is generally NOT safe. Learn more at https://bit.ly/wb-precache`)}handleInstall(e){return this.registerRequestRules(e),y(e,async()=>{let t=new eo;this.precacheStrategy.plugins.push(t),await el(this._concurrentPrecaching,Array.from(this._urlsToCacheKeys.entries()),async([t,a])=>{let s=this._cacheKeysToIntegrities.get(a),r=this._urlsToCacheModes.get(t),n=new Request(t,{integrity:s,cache:r,credentials:"same-origin"});await Promise.all(this.precacheStrategy.handleAll({event:e,request:n,url:new URL(n.url),params:{cacheKey:a}}))});let{updatedURLs:a,notUpdatedURLs:s}=t;return{updatedURLs:a,notUpdatedURLs:s}})}async registerRequestRules(e){if(this._requestRules&&e?.addRoutes)try{await e.addRoutes(this._requestRules),this._requestRules=void 0}catch(e){throw e}}handleActivate(e){return y(e,async()=>{let e=await self.caches.open(this.precacheStrategy.cacheName),t=await e.keys(),a=new Set(this._urlsToCacheKeys.values()),s=[];for(let r of t)a.has(r.url)||(await e.delete(r),s.push(r.url));return{deletedCacheRequests:s}})}handleFetch(e){let{request:t}=e,a=this.handleRequest({request:t,event:e});a&&e.respondWith(a)}handleCache(e){if(e.data&&"CACHE_URLS"===e.data.type){let{payload:t}=e.data,a=Promise.all(t.urlsToCache.map(t=>{let a;return a="string"==typeof t?new Request(t):new Request(...t),this.handleRequest({request:a,event:e})}));e.waitUntil(a),e.ports?.[0]&&a.then(()=>e.ports[0].postMessage(!0))}}setDefaultHandler(e,t="GET"){this._defaultHandlerMap.set(t,ea(e))}setCatchHandler(e){this._catchHandler=ea(e)}registerCapture(e,t,a){let s=((e,t,a)=>{if("string"==typeof e){let s=new URL(e,location.href);return new es(({url:e})=>e.href===s.href,t,a)}if(e instanceof RegExp)return new ei(e,t,a);if("function"==typeof e)return new es(e,t,a);if(e instanceof es)return e;throw new l("unsupported-route-type",{moduleName:"serwist",funcName:"parseRoute",paramName:"capture"})})(e,t,a);return this.registerRoute(s),s}registerRoute(e){this._routes.has(e.method)||this._routes.set(e.method,[]),this._routes.get(e.method).push(e)}unregisterRoute(e){if(!this._routes.has(e.method))throw new l("unregister-route-but-not-found-with-method",{method:e.method});let t=this._routes.get(e.method).indexOf(e);if(t>-1)this._routes.get(e.method).splice(t,1);else throw new l("unregister-route-route-not-registered")}getUrlsToPrecacheKeys(){return this._urlsToCacheKeys}getPrecachedUrls(){return[...this._urlsToCacheKeys.keys()]}getPrecacheKeyForUrl(e){let t=new URL(e,location.href);return this._urlsToCacheKeys.get(t.href)}getIntegrityForPrecacheKey(e){return this._cacheKeysToIntegrities.get(e)}async matchPrecache(e){let t=e instanceof Request?e.url:e,a=this.getPrecacheKeyForUrl(t);if(a)return(await self.caches.open(this.precacheStrategy.cacheName)).match(a)}createHandlerBoundToUrl(e){let t=this.getPrecacheKeyForUrl(e);if(!t)throw new l("non-precached-url",{url:e});return a=>(a.request=new Request(e),a.params={cacheKey:t,...a.params},this.precacheStrategy.handle(a))}handleRequest({request:e,event:t}){let a,s=new URL(e.url,location.href);if(!s.protocol.startsWith("http"))return;let r=s.origin===location.origin,{params:n,route:i}=this.findMatchingRoute({event:t,request:e,sameOrigin:r,url:s}),c=i?.handler,o=e.method;if(!c&&this._defaultHandlerMap.has(o)&&(c=this._defaultHandlerMap.get(o)),!c)return;try{a=c.handle({url:s,request:e,event:t,params:n})}catch(e){a=Promise.reject(e)}let l=i?.catchHandler;return a instanceof Promise&&(this._catchHandler||l)&&(a=a.catch(async a=>{if(l)try{return await l.handle({url:s,request:e,event:t,params:n})}catch(e){e instanceof Error&&(a=e)}if(this._catchHandler)return this._catchHandler.handle({url:s,request:e,event:t});throw a})),a}findMatchingRoute({url:e,sameOrigin:t,request:a,event:s}){for(let r of this._routes.get(a.method)||[]){let n,i=r.match({url:e,sameOrigin:t,request:a,event:s});if(i)return Array.isArray(n=i)&&0===n.length||i.constructor===Object&&0===Object.keys(i).length?n=void 0:"boolean"==typeof i&&(n=void 0),{route:r,params:n}}return{}}}let eD=[{matcher:/^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,handler:new eE({cacheName:"google-fonts-webfonts",plugins:[new ef({maxEntries:4,maxAgeSeconds:31536e3,maxAgeFrom:"last-used"})]})},{matcher:/^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,handler:new eR({cacheName:"google-fonts-stylesheets",plugins:[new ef({maxEntries:4,maxAgeSeconds:604800,maxAgeFrom:"last-used"})]})},{matcher:/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,handler:new eR({cacheName:"static-font-assets",plugins:[new ef({maxEntries:4,maxAgeSeconds:604800,maxAgeFrom:"last-used"})]})},{matcher:/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,handler:new eR({cacheName:"static-image-assets",plugins:[new ef({maxEntries:64,maxAgeSeconds:2592e3,maxAgeFrom:"last-used"})]})},{matcher:/\/_next\/static.+\.js$/i,handler:new eE({cacheName:"next-static-js-assets",plugins:[new ef({maxEntries:64,maxAgeSeconds:86400,maxAgeFrom:"last-used"})]})},{matcher:/\/_next\/image\?url=.+$/i,handler:new eR({cacheName:"next-image",plugins:[new ef({maxEntries:64,maxAgeSeconds:86400,maxAgeFrom:"last-used"})]})},{matcher:/\.(?:mp3|wav|ogg)$/i,handler:new eE({cacheName:"static-audio-assets",plugins:[new ef({maxEntries:32,maxAgeSeconds:86400,maxAgeFrom:"last-used"}),new eb]})},{matcher:/\.(?:mp4|webm)$/i,handler:new eE({cacheName:"static-video-assets",plugins:[new ef({maxEntries:32,maxAgeSeconds:86400,maxAgeFrom:"last-used"}),new eb]})},{matcher:/\.(?:js)$/i,handler:new eR({cacheName:"static-js-assets",plugins:[new ef({maxEntries:48,maxAgeSeconds:86400,maxAgeFrom:"last-used"})]})},{matcher:/\.(?:css|less)$/i,handler:new eR({cacheName:"static-style-assets",plugins:[new ef({maxEntries:32,maxAgeSeconds:86400,maxAgeFrom:"last-used"})]})},{matcher:/\/_next\/data\/.+\/.+\.json$/i,handler:new ee({cacheName:"next-data",plugins:[new ef({maxEntries:32,maxAgeSeconds:86400,maxAgeFrom:"last-used"})]})},{matcher:/\.(?:json|xml|csv)$/i,handler:new ee({cacheName:"static-data-assets",plugins:[new ef({maxEntries:32,maxAgeSeconds:86400,maxAgeFrom:"last-used"})]})},{matcher:/\/api\/auth\/.*/,handler:new et({networkTimeoutSeconds:10})},{matcher:({sameOrigin:e,url:{pathname:t}})=>e&&t.startsWith("/api/"),method:"GET",handler:new ee({cacheName:"apis",plugins:[new ef({maxEntries:16,maxAgeSeconds:86400,maxAgeFrom:"last-used"})],networkTimeoutSeconds:10})},{matcher:({request:e,url:{pathname:t},sameOrigin:a})=>"1"===e.headers.get("RSC")&&"1"===e.headers.get("Next-Router-Prefetch")&&a&&!t.startsWith("/api/"),handler:new ee({cacheName:"pages-rsc-prefetch",plugins:[new ef({maxEntries:32,maxAgeSeconds:86400})]})},{matcher:({request:e,url:{pathname:t},sameOrigin:a})=>"1"===e.headers.get("RSC")&&a&&!t.startsWith("/api/"),handler:new ee({cacheName:"pages-rsc",plugins:[new ef({maxEntries:32,maxAgeSeconds:86400})]})},{matcher:({request:e,url:{pathname:t},sameOrigin:a})=>e.headers.get("Content-Type")?.includes("text/html")&&a&&!t.startsWith("/api/"),handler:new ee({cacheName:"pages",plugins:[new ef({maxEntries:32,maxAgeSeconds:86400})]})},{matcher:({url:{pathname:e},sameOrigin:t})=>t&&!e.startsWith("/api/"),handler:new ee({cacheName:"others",plugins:[new ef({maxEntries:32,maxAgeSeconds:86400})]})},{matcher:({sameOrigin:e})=>!e,handler:new ee({cacheName:"cross-origin",plugins:[new ef({maxEntries:32,maxAgeSeconds:3600})],networkTimeoutSeconds:10})},{matcher:/.*/i,method:"GET",handler:new et}];new eS({precacheEntries:[{'revision':'d31821b97db5567931e97c96e8f66e36','url':'/_next/static/0yoW-ZTMf9TG4U6I6ir-D/_buildManifest.js'},{'revision':'b6652df95db52feb4daf4eca35380933','url':'/_next/static/0yoW-ZTMf9TG4U6I6ir-D/_ssgManifest.js'},{'revision':null,'url':'/_next/static/chunks/1861-7ec060ee520cfca0.js'},{'revision':null,'url':'/_next/static/chunks/1966.1560d0f43ac9a41a.js'},{'revision':null,'url':'/_next/static/chunks/2052-c5b09dcc230e1531.js'},{'revision':null,'url':'/_next/static/chunks/2169-7b7b0d438daffc87.js'},{'revision':null,'url':'/_next/static/chunks/2791-95e8780c6416dd23.js'},{'revision':null,'url':'/_next/static/chunks/3747-249503e5adc75f01.js'},{'revision':null,'url':'/_next/static/chunks/3899.cf10152d8085e352.js'},{'revision':null,'url':'/_next/static/chunks/398-b7ab3cf18ccdb442.js'},{'revision':null,'url':'/_next/static/chunks/4650-f35a60e4944a08a7.js'},{'revision':null,'url':'/_next/static/chunks/4851-21c595d4280900cd.js'},{'revision':null,'url':'/_next/static/chunks/4bd1b696-1791e0ff31dc82df.js'},{'revision':null,'url':'/_next/static/chunks/5772-742636133f6ef6a4.js'},{'revision':null,'url':'/_next/static/chunks/6511-9bb898be772a2499.js'},{'revision':null,'url':'/_next/static/chunks/6691-d6127ed52a9478dc.js'},{'revision':null,'url':'/_next/static/chunks/6917-e62576dd9e45033f.js'},{'revision':null,'url':'/_next/static/chunks/7173-6bdd52d819422d10.js'},{'revision':null,'url':'/_next/static/chunks/7232-21c595d4280900cd.js'},{'revision':null,'url':'/_next/static/chunks/7690-52add58139bb2b1d.js'},{'revision':null,'url':'/_next/static/chunks/7896-51f0cc3573865c3e.js'},{'revision':null,'url':'/_next/static/chunks/7963-95724eaaf323c35c.js'},{'revision':null,'url':'/_next/static/chunks/8480-e626e206d6dab40e.js'},{'revision':null,'url':'/_next/static/chunks/8500-27ab90e35aa7c15c.js'},{'revision':null,'url':'/_next/static/chunks/8527-46010897141dda56.js'},{'revision':null,'url':'/_next/static/chunks/9108-a7fbdf33d1ef67bb.js'},{'revision':null,'url':'/_next/static/chunks/9441-f97a001a2df0bc11.js'},{'revision':null,'url':'/_next/static/chunks/9547-6f47e5674536543c.js'},{'revision':null,'url':'/_next/static/chunks/app/_global-error/page-188170a60634d965.js'},{'revision':null,'url':'/_next/static/chunks/app/_not-found/page-2c935516de82acf6.js'},{'revision':null,'url':'/_next/static/chunks/app/agreement/page-29259bc7f91f97ae.js'},{'revision':null,'url':'/_next/static/chunks/app/api/auth/kakao/authorization-url/route-188170a60634d965.js'},{'revision':null,'url':'/_next/static/chunks/app/feed/article/%5Bid%5D/page-fa68aaee051279ea.js'},{'revision':null,'url':'/_next/static/chunks/app/feed/page-52f9b70a758c3e6c.js'},{'revision':null,'url':'/_next/static/chunks/app/feed/payPost/manual/page-edbbba62eedfd298.js'},{'revision':null,'url':'/_next/static/chunks/app/feed/payPost/page-7ee9a63f35f606c9.js'},{'revision':null,'url':'/_next/static/chunks/app/feed/review/write/%5Bid%5D/page-27fca1beeff598c3.js'},{'revision':null,'url':'/_next/static/chunks/app/feed/write/%5Bid%5D/page-188170a60634d965.js'},{'revision':null,'url':'/_next/static/chunks/app/feed/write/page-566613d555182ce6.js'},{'revision':null,'url':'/_next/static/chunks/app/home/demo/page-d54281478291e62b.js'},{'revision':null,'url':'/_next/static/chunks/app/home/notify/page-05f5684f79681a50.js'},{'revision':null,'url':'/_next/static/chunks/app/home/page-07f9b9e3763e7a32.js'},{'revision':null,'url':'/_next/static/chunks/app/home/preference/complete/page-e673b5c056b289fa.js'},{'revision':null,'url':'/_next/static/chunks/app/home/preference/finish/page-b168d6f0ee832430.js'},{'revision':null,'url':'/_next/static/chunks/app/home/preference/layout-c90523e574e948eb.js'},{'revision':null,'url':'/_next/static/chunks/app/home/preference/list/page-796fcf86ab8595ca.js'},{'revision':null,'url':'/_next/static/chunks/app/home/preference/page-e673b5c056b289fa.js'},{'revision':null,'url':'/_next/static/chunks/app/home/preference/swipe/page-92134be58b86556e.js'},{'revision':null,'url':'/_next/static/chunks/app/home/search/page-13a2f320e2cad6e3.js'},{'revision':null,'url':'/_next/static/chunks/app/home/search/result/artists/page-c834ffe75c4cfdbe.js'},{'revision':null,'url':'/_next/static/chunks/app/home/search/result/page-43862f48863588fe.js'},{'revision':null,'url':'/_next/static/chunks/app/home/search/result/works/page-609458b32b43ed46.js'},{'revision':null,'url':'/_next/static/chunks/app/home/topicroom/%5Bid%5D/page-eaa3355e6c52bf0c.js'},{'revision':null,'url':'/_next/static/chunks/app/home/topicroom/%5Bid%5D/report/page-73d26c2daa43f8af.js'},{'revision':null,'url':'/_next/static/chunks/app/home/topicroom/page-9a6b8aea3bcdc663.js'},{'revision':null,'url':'/_next/static/chunks/app/home/topicroom/search/page-9de9e885c648c9cd.js'},{'revision':null,'url':'/_next/static/chunks/app/layout-e274159159125125.js'},{'revision':null,'url':'/_next/static/chunks/app/library/gallery/page-bf51312aa70c277d.js'},{'revision':null,'url':'/_next/static/chunks/app/library/list/page-69d2e89f6ce1e1cb.js'},{'revision':null,'url':'/_next/static/chunks/app/library/search/page-a46cfeef92e70c33.js'},{'revision':null,'url':'/_next/static/chunks/app/library/search/result/page-0bf13b3e8dd2e163.js'},{'revision':null,'url':'/_next/static/chunks/app/library/works/%5Bid%5D/page-ca803d50c4ea78ee.js'},{'revision':null,'url':'/_next/static/chunks/app/library/works/%5Bid%5D/topicroom/page-35cdb3b4d142af7e.js'},{'revision':null,'url':'/_next/static/chunks/app/library/works/review/%5Bid%5D/page-5a0c39afecb42d6e.js'},{'revision':null,'url':'/_next/static/chunks/app/login/page-8f491e27103d53a3.js'},{'revision':null,'url':'/_next/static/chunks/app/manifest.webmanifest/route-188170a60634d965.js'},{'revision':null,'url':'/_next/static/chunks/app/manual/page-98a525638c9a592e.js'},{'revision':null,'url':'/_next/static/chunks/app/offline/page-188170a60634d965.js'},{'revision':null,'url':'/_next/static/chunks/app/onboarding/page-a22376b5d880cc4d.js'},{'revision':null,'url':'/_next/static/chunks/app/page-ecd34954e8268515.js'},{'revision':null,'url':'/_next/static/chunks/app/pending/page-7dadadc86b581d74.js'},{'revision':null,'url':'/_next/static/chunks/app/profile/fix/page-84b56c39fbfc385f.js'},{'revision':null,'url':'/_next/static/chunks/app/profile/likes/page-83637a21671f114b.js'},{'revision':null,'url':'/_next/static/chunks/app/profile/myActivity/page-9fc68dae1efc9577.js'},{'revision':null,'url':'/_next/static/chunks/app/profile/page-0aba4704108378dc.js'},{'revision':null,'url':'/_next/static/chunks/app/profile/settings/page-18b366561c10f847.js'},{'revision':null,'url':'/_next/static/chunks/app/writers/feed/page-d611c4020719c2b7.js'},{'revision':null,'url':'/_next/static/chunks/app/writers/login/page-ea315a593174228d.js'},{'revision':null,'url':'/_next/static/chunks/app/writers/profile/dashboard/page-0cca092990cb80c4.js'},{'revision':null,'url':'/_next/static/chunks/app/writers/profile/page-d4fb8c814fc940f2.js'},{'revision':null,'url':'/_next/static/chunks/app/writers/signup/page-61bb0b459ce6dbc6.js'},{'revision':null,'url':'/_next/static/chunks/app/writers/verify/page-70dc6ee949749a4e.js'},{'revision':null,'url':'/_next/static/chunks/framework-ec21dd808c5d3f81.js'},{'revision':null,'url':'/_next/static/chunks/main-app-9476e77d7dacdfe2.js'},{'revision':null,'url':'/_next/static/chunks/main-deb716b09225ac12.js'},{'revision':null,'url':'/_next/static/chunks/next/dist/client/components/builtin/app-error-188170a60634d965.js'},{'revision':null,'url':'/_next/static/chunks/next/dist/client/components/builtin/forbidden-188170a60634d965.js'},{'revision':null,'url':'/_next/static/chunks/next/dist/client/components/builtin/global-error-49f7f4a5b75d2624.js'},{'revision':null,'url':'/_next/static/chunks/next/dist/client/components/builtin/not-found-188170a60634d965.js'},{'revision':null,'url':'/_next/static/chunks/next/dist/client/components/builtin/unauthorized-188170a60634d965.js'},{'revision':'846118c33b2c0e922d7b3a7676f81f6f','url':'/_next/static/chunks/polyfills-42372ed130431b0a.js'},{'revision':null,'url':'/_next/static/chunks/webpack-1969adce0ef29a13.js'},{'revision':null,'url':'/_next/static/css/d9b9c610fc122fd9.css'},{'revision':'13b67eadd6bbeabc6e9a65501dafe1ae','url':'/_next/static/media/b471035bc347e80a-s.p.woff2'},{'revision':'adfd0f17b104d1863b70d7ed82f60e8da806d438','url':'/offline'}],skipWaiting:!0,clientsClaim:!0,navigationPreload:!0,runtimeCaching:eD,fallbacks:{entries:[{url:"/~offline",matcher:({request:e})=>"document"===e.destination}]}}).addEventListeners()})(); \ No newline at end of file diff --git a/storix-fe/src/app/home/page.tsx b/storix-fe/src/app/home/page.tsx index 7a6b562..c3d053d 100644 --- a/storix-fe/src/app/home/page.tsx +++ b/storix-fe/src/app/home/page.tsx @@ -89,7 +89,11 @@ export default function Home() {
- +
@@ -13,7 +13,7 @@ export default function PreferenceFinishPage() {
축하해요!
- {likedWorks.length}개의 새로운 관심 작품이 등록됐어요!
+ {likedSuccessCount}개의 새로운 관심 작품이 등록됐어요!
피드에서 작품의 소식을 확인해봐요!
diff --git a/storix-fe/src/app/home/topicroom/page.tsx b/storix-fe/src/app/home/topicroom/page.tsx index 5e6f7b3..1716df3 100644 --- a/storix-fe/src/app/home/topicroom/page.tsx +++ b/storix-fe/src/app/home/topicroom/page.tsx @@ -8,6 +8,7 @@ import ParticipationChat, { ParticipationChatItem, } from '@/components/topicroom/ParticipationChat' import { formatTopicRoomSubtitle } from '@/lib/api/topicroom/formatTopicRoomSubtitle' +import { formatTimeAgo } from '@/lib/utils/formatTimeAgo' import { CardTopicroomInsideCoverSlider } from '@/components/topicroom/CardTopicroomInsideCoverSlider' import { TopicRoomData } from '@/components/home/todayTopicRoom/TopicroomCoverCard' import { useMyTopicRoomsAll } from '@/hooks/topicroom/useMyTopicRoomsAll' // @@ -16,20 +17,6 @@ import { useProfileStore } from '@/store/profile.store' import { getMyProfile } from '@/lib/api/profile/profile.api' export default function TopicRoom() { - const formatTimeAgo = (iso?: string | null) => { - if (!iso) return '' - const t = new Date(iso).getTime() - if (Number.isNaN(t)) return '' - const diff = Date.now() - t - if (diff < 60_000) return '방금 전' - const min = Math.floor(diff / 60_000) - if (min < 60) return `${min}분 전` - const hour = Math.floor(min / 60) - if (hour < 24) return `${hour}시간 전` - const day = Math.floor(hour / 24) - return `${day}일 전` - } - const router = useRouter() // const goSearch = (raw: string) => { diff --git a/storix-fe/src/app/home/topicroom/search/ResultClient.tsx b/storix-fe/src/app/home/topicroom/search/ResultClient.tsx index bde4ce5..10be59e 100644 --- a/storix-fe/src/app/home/topicroom/search/ResultClient.tsx +++ b/storix-fe/src/app/home/topicroom/search/ResultClient.tsx @@ -10,6 +10,7 @@ import TopicRoomSearchList from '@/components/topicroom/TopicRoomSearchList' import { useTopicRoomSearchInfinite } from '@/hooks/topicroom/useTopicRoomSearchInfinite' import { useJoinTopicRoom } from '@/hooks/topicroom/useJoinTopicRoom' import { formatTopicRoomSubtitle } from '@/lib/api/topicroom/formatTopicRoomSubtitle' +import { formatTimeAgo } from '@/lib/utils/formatTimeAgo' export default function ResultClient() { const router = useRouter() @@ -25,26 +26,13 @@ export default function ResultClient() { isFetchingNextPage, } = useTopicRoomSearchInfinite(keyword, 20) - const formatTimeAgo = (iso?: string | null) => { - if (!iso) return '' - const t = new Date(iso).getTime() - if (Number.isNaN(t)) return '' - const diff = Date.now() - t - if (diff < 60_000) return '방금 전' - const min = Math.floor(diff / 60_000) - if (min < 60) return `${min}분 전` - const hour = Math.floor(min / 60) - if (hour < 24) return `${hour}시간 전` - const day = Math.floor(hour / 24) - return `${day}일 전` - } - // isJoined 체크 + join 후 이동 const joinMut = useJoinTopicRoom() // const pendingJoinRef = useRef<{ roomId: number worksName: string } | null>(null) // + const sentinelRef = useRef(null) const items = useMemo(() => { const pages = data?.pages ?? [] // @@ -117,10 +105,6 @@ export default function ResultClient() { pushToRoom(roomId, worksName) return } - if (!found.isJoined) { - pushToRoom(roomId, worksName) - return - } // join 진행 중이면 중복 클릭 방지 if (joinMut.isPending) return @@ -130,9 +114,6 @@ export default function ResultClient() { joinMut.mutate(roomId) // } - // 무한스크롤 트리거 - const sentinelRef = useRef(null) // - return (
router.push(href)} className="h-6 w-6 cursor-pointer" > - 뒤로가기 + 뒤로가기
diff --git a/storix-fe/src/components/home/search/SearchResultWorks.tsx b/storix-fe/src/components/home/search/SearchResultWorks.tsx index deb4879..e94c9e6 100644 --- a/storix-fe/src/components/home/search/SearchResultWorks.tsx +++ b/storix-fe/src/components/home/search/SearchResultWorks.tsx @@ -44,6 +44,7 @@ export default function SearchResultWorks({ src={w.thumbnailUrl} alt={w.worksName} fill + sizes="87px" className="object-cover" /> ) : null} @@ -67,7 +68,6 @@ export default function SearchResultWorks({ width={9} height={10} className="inline-block mr-1 mb-0.5" - priority /> {Number(w.avgRating).toFixed(1)} diff --git a/storix-fe/src/components/home/todayTopicRoom/CardNav.tsx b/storix-fe/src/components/home/todayTopicRoom/CardNav.tsx index 4e7837a..e5e7610 100644 --- a/storix-fe/src/components/home/todayTopicRoom/CardNav.tsx +++ b/storix-fe/src/components/home/todayTopicRoom/CardNav.tsx @@ -7,9 +7,12 @@ import Image from 'next/image' interface CardNavProps { header?: string roomName?: string + onNavigate?: () => void | Promise } -export const CardNav = ({ header, roomName }: CardNavProps) => { +export const CardNav = ({ header, roomName, onNavigate }: CardNavProps) => { + const href = roomName ?? '#' + return (
@@ -19,9 +22,14 @@ export const CardNav = ({ header, roomName }: CardNavProps) => { {/* 오른쪽 아이콘 그룹 */}
{ + if (!onNavigate) return + e.preventDefault() + onNavigate() + }} >
- -
- - - -
diff --git a/storix-fe/src/components/library/works/WorkTapContent.tsx b/storix-fe/src/components/library/works/WorkTapContent.tsx index 4e34a78..b0fbf59 100644 --- a/storix-fe/src/components/library/works/WorkTapContent.tsx +++ b/storix-fe/src/components/library/works/WorkTapContent.tsx @@ -39,7 +39,9 @@ type Props = { tab: TabKey onChangeTab: (tab: TabKey) => void ui: UIData + isCheckingRoom: boolean onReviewWrite: () => void + onTopicroomEnter: () => void } export default function WorkTabContent({ @@ -47,7 +49,9 @@ export default function WorkTabContent({ tab, onChangeTab, ui, + isCheckingRoom, onReviewWrite, + onTopicroomEnter, }: Props) { const router = useRouter() const { data: myReview } = useWorksMyReview(worksId) @@ -116,7 +120,7 @@ export default function WorkTabContent({
{/* Tab Content */} -
+
{tab === 'info' ? (
@@ -208,6 +212,41 @@ export default function WorkTabContent({
)}
+
+
+ + + +
+
) } diff --git a/storix-fe/src/components/preference/PreferenceList.tsx b/storix-fe/src/components/preference/PreferenceList.tsx index ce96f19..988ac59 100644 --- a/storix-fe/src/components/preference/PreferenceList.tsx +++ b/storix-fe/src/components/preference/PreferenceList.tsx @@ -4,9 +4,14 @@ import Image from 'next/image' import type { PreferenceWork } from './PreferenceProvider' import { useFavoriteWork } from '@/hooks/favorite/useFavoriteWork' +import { usePreference } from './PreferenceProvider' function PreferenceListRow({ w }: { w: PreferenceWork }) { - const { isFavorite, isMutating, toggleFavorite } = useFavoriteWork(w.id) + const { onFavoriteAdded, onFavoriteRemoved } = usePreference() + const { isFavorite, isMutating, toggleFavorite } = useFavoriteWork(w.id, { + onAdded: onFavoriteAdded, // addMutation 성공만 카운트 + onRemoved: onFavoriteRemoved, // 취소하면 카운트에서 제외 + }) return (
diff --git a/storix-fe/src/components/preference/PreferenceProvider.tsx b/storix-fe/src/components/preference/PreferenceProvider.tsx index e323b73..a2f2530 100644 --- a/storix-fe/src/components/preference/PreferenceProvider.tsx +++ b/storix-fe/src/components/preference/PreferenceProvider.tsx @@ -9,6 +9,7 @@ import React, { useRef, useState, } from 'react' +import { useQueryClient } from '@tanstack/react-query' import { usePreferenceAnalyze, usePreferenceExploration, @@ -19,7 +20,6 @@ import type { PreferenceResultWork, } from '@/lib/api/preference' import { z } from 'zod' -import axios from 'axios' export type PreferenceWork = { id: number @@ -45,6 +45,9 @@ type PreferenceContextValue = { reset: () => void likedWorks: PreferenceWork[] dislikedWorks: PreferenceWork[] + likedSuccessCount: number + onFavoriteAdded: (worksId: number) => void + onFavoriteRemoved: (worksId: number) => void isDone: boolean } @@ -93,6 +96,7 @@ export default function PreferenceProvider({ }: { children: React.ReactNode }) { + const queryClient = useQueryClient() const explorationQuery = usePreferenceExploration() const resultsQuery = usePreferenceResults(true) const analyzeMutation = usePreferenceAnalyze() @@ -150,8 +154,8 @@ export default function PreferenceProvider({ const didInitRef = useRef(false) + // 최초 1회 저장값 읽기(리마운트/리로드 대비) useEffect(() => { - // 최초 1회 저장값 읽기(리마운트/리로드 대비) if (savedStateRef.current) return try { const raw = window.localStorage.getItem(STORAGE_KEY) @@ -162,8 +166,8 @@ export default function PreferenceProvider({ } }, []) + // works가 처음 채워질 때만 초기화 + 저장된 진행상태 merge useEffect(() => { - // works가 처음 채워질 때만 초기화 + 저장된 진행상태 merge if (didInitRef.current) return if (!works || works.length === 0) return @@ -181,8 +185,8 @@ export default function PreferenceProvider({ didInitRef.current = true }, [works]) + //: 진행상태 persist (리마운트돼도 복구 가능) useEffect(() => { - //: 진행상태 persist (리마운트돼도 복구 가능) if (!didInitRef.current) return try { window.localStorage.setItem(STORAGE_KEY, JSON.stringify(state)) @@ -199,18 +203,6 @@ export default function PreferenceProvider({ const isDone = currentWork == null // 결과 API 있으면 결과 기준으로 리스트 구성(제한 걸린 날에도 리스트 보여줄 수 있음) - const likedWorksFromResult = useMemo(() => { - const r = resultsQuery.data?.result - if (!r) return null - return r.likedWorks.map(mapResultToWork) - }, [resultsQuery.data]) - - const dislikedWorksFromResult = useMemo(() => { - const r = resultsQuery.data?.result - if (!r) return null - return r.dislikedWorks.map(mapResultToWork) - }, [resultsQuery.data]) - const likedWorksLocal = useMemo( () => works.filter((w) => state[w.id] === 'like'), [works, state], @@ -220,8 +212,90 @@ export default function PreferenceProvider({ [works, state], ) - const likedWorks = likedWorksFromResult ?? likedWorksLocal - const dislikedWorks = dislikedWorksFromResult ?? dislikedWorksLocal + // results가 "존재"만 한다고 바로 쓰면(빈 배열이어도) 로컬 결과를 덮어써서 리스트가 비어 보일 수 있음 + const result = resultsQuery.data?.result + + // results가 실제로 의미 있는 결과를 가진 경우에만 results를 사용 + const hasResultLists = + !!result && result.likedWorks.length + result.dislikedWorks.length > 0 + + // "하루 1회 제한"으로 exploration이 빈 리스트인 날엔 results를 우선 사용(과거 결과 보여주기) + const explorationList = explorationQuery.data?.result ?? [] + const isLimitedDay = + explorationQuery.isSuccess && + Array.isArray(explorationList) && + explorationList.length === 0 + + const useServerResults = hasResultLists || isLimitedDay + + // DEBUG: "2개 눌렀는데 12로 뜨는" 원인 추적 로그 + useEffect(() => { + // 필요하면 false로 꺼도 됨 + const DEBUG = true + if (!DEBUG) return + + const resultLikedLen = result?.likedWorks?.length ?? 0 + const resultDislikedLen = result?.dislikedWorks?.length ?? 0 + + console.group('[Preference DEBUG] source check') + console.log('explorationQuery.isSuccess:', explorationQuery.isSuccess) + console.log('exploration works length:', works.length) + console.log('likedWorksLocal length:', likedWorksLocal.length) + console.log('dislikedWorksLocal length:', dislikedWorksLocal.length) + + console.log('resultsQuery.status:', resultsQuery.status) + console.log('result exists:', !!result) + console.log('result.likedWorks length:', resultLikedLen) + console.log('result.dislikedWorks length:', resultDislikedLen) + + console.log('hasResultLists:', hasResultLists) + console.log('isLimitedDay:', isLimitedDay) + console.log('useServerResults:', useServerResults) + console.groupEnd() + }, [ + explorationQuery.isSuccess, + works.length, + likedWorksLocal.length, + dislikedWorksLocal.length, + resultsQuery.status, + result, + hasResultLists, + isLimitedDay, + useServerResults, + ]) + + const [likedSuccessIds, setLikedSuccessIds] = useState>( + () => new Set(), + ) + + const onFavoriteAdded = (worksId: number) => { + setLikedSuccessIds((prev) => { + const next = new Set(prev) + next.add(worksId) + return next + }) + } + + const onFavoriteRemoved = (worksId: number) => { + setLikedSuccessIds((prev) => { + if (!prev.has(worksId)) return prev + const next = new Set(prev) + next.delete(worksId) + return next + }) + } + + const likedWorks = useMemo(() => { + if (useServerResults && result) + return result.likedWorks.map(mapResultToWork) + return likedWorksLocal + }, [useServerResults, result, likedWorksLocal]) + + const dislikedWorks = useMemo(() => { + if (useServerResults && result) + return result.dislikedWorks.map(mapResultToWork) + return dislikedWorksLocal + }, [useServerResults, result, dislikedWorksLocal]) const submitChoice = async (choice: Choice) => { if (!currentWork) return @@ -237,12 +311,25 @@ export default function PreferenceProvider({ worksId, isLiked: choice === 'like', }) + + // "관심작품 등록(POST) 성공"한 like만 카운트 + if (choice === 'like') { + setLikedSuccessIds((prev) => { + const next = new Set(prev) + next.add(worksId) + return next + }) + } } catch (e) { - // 서버 동기화 실패 시에도 진행은 유지하고 토스트만 표시 - const serverMsg = - (e as any)?.response?.data?.message ?? - (e as any)?.message ?? - '요청 처리 중 오류가 발생했어요.' + // 실패 시: 진행은 유지하되(정책 유지), 성공 카운트에는 포함되면 안 됨 + if (choice === 'like') { + setLikedSuccessIds((prev) => { + if (!prev.has(worksId)) return prev + const next = new Set(prev) + next.delete(worksId) + return next + }) + } } } @@ -251,6 +338,7 @@ export default function PreferenceProvider({ const reset = () => { setState(buildInitialState(works)) + setLikedSuccessIds(new Set()) } const value: PreferenceContextValue = { @@ -263,6 +351,9 @@ export default function PreferenceProvider({ reset, likedWorks, dislikedWorks, + likedSuccessCount: likedSuccessIds.size, + onFavoriteAdded, + onFavoriteRemoved, isDone, } diff --git a/storix-fe/src/hooks/favorite/useFavoriteWork.ts b/storix-fe/src/hooks/favorite/useFavoriteWork.ts index 116891b..e460c8d 100644 --- a/storix-fe/src/hooks/favorite/useFavoriteWork.ts +++ b/storix-fe/src/hooks/favorite/useFavoriteWork.ts @@ -9,7 +9,15 @@ import { unfavoriteWork, } from '@/lib/api/favorite' -export function useFavoriteWork(worksId?: number) { +type UseFavoriteWorkOptions = { + onAdded?: (worksId: number) => void + onRemoved?: (worksId: number) => void +} + +export function useFavoriteWork( + worksId?: number, + options?: UseFavoriteWorkOptions, +) { const queryClient = useQueryClient() const enabled = @@ -22,26 +30,38 @@ export function useFavoriteWork(worksId?: number) { const statusQuery = useQuery({ queryKey, - queryFn: () => getFavoriteWorkStatus(worksId!), // enabled로 가드 + queryFn: () => getFavoriteWorkStatus(worksId!), // enabled로 가드 enabled: !!enabled, }) const addMutation = useMutation({ - mutationFn: () => favoriteWork(worksId!), // enabled로 가드 + mutationFn: () => favoriteWork(worksId!), // enabled로 가드 }) const removeMutation = useMutation({ - mutationFn: () => unfavoriteWork(worksId!), // enabled로 가드 + mutationFn: () => unfavoriteWork(worksId!), // enabled로 가드 }) - // mutation 성공 시 invalidateQueries (onSuccess 금지 규칙 준수) + // mutation 성공 감지 (onSuccess 금지 규칙 준수: useEffect로 처리) useEffect(() => { + if (!enabled) return + + if (addMutation.isSuccess) { + options?.onAdded?.(worksId!) + } + if (removeMutation.isSuccess) { + options?.onRemoved?.(worksId!) + } + if (addMutation.isSuccess || removeMutation.isSuccess) { - queryClient.invalidateQueries({ queryKey }) // - addMutation.reset() // - removeMutation.reset() // + queryClient.invalidateQueries({ queryKey }) + addMutation.reset() + removeMutation.reset() } }, [ + enabled, + worksId, + options, addMutation.isSuccess, removeMutation.isSuccess, queryClient, diff --git a/storix-fe/src/lib/utils/formatTimeAgo.ts b/storix-fe/src/lib/utils/formatTimeAgo.ts new file mode 100644 index 0000000..61b7a53 --- /dev/null +++ b/storix-fe/src/lib/utils/formatTimeAgo.ts @@ -0,0 +1,13 @@ +export function formatTimeAgo(iso?: string | null): string { + if (!iso) return '' + const t = new Date(iso).getTime() + if (Number.isNaN(t)) return '' + const diff = Date.now() - t + if (diff < 60_000) return '방금 전' + const min = Math.floor(diff / 60_000) + if (min < 60) return `${min}분 전` + const hour = Math.floor(min / 60) + if (hour < 24) return `${hour}시간 전` + const day = Math.floor(hour / 24) + return `${day}일 전` +}