///
import { defaultCache } from "@serwist/next/worker"
import type { PrecacheEntry, SerwistGlobalConfig } from "serwist"
import { Serwist, NetworkFirst, CacheFirst, ExpirationPlugin } from "serwist"
declare global {
interface WorkerGlobalScope extends SerwistGlobalConfig {
__SW_MANIFEST: (PrecacheEntry | string)[] | undefined
}
}
declare const self: ServiceWorkerGlobalScope
let offlineReadingAllowed = false
self.addEventListener("message", (event) => {
if (event.data?.type === "SET_OFFLINE_ACCESS") {
offlineReadingAllowed = event.data.allowed === true
}
})
const offlineGatePlugin = {
cacheWillUpdate: async ({ response }: { response: Response }): Promise => {
if (!offlineReadingAllowed) return null
return response
},
}
const sameOriginCache = defaultCache.map((entry) => ({
...entry,
matcher: (parameters: Parameters>[0]) => {
if (!parameters.sameOrigin) return false
const original = entry.matcher
if (typeof original === "function") return original(parameters)
if (original instanceof RegExp) return original.test(parameters.url.href)
return false
},
}))
const serwist = new Serwist({
precacheEntries: self.__SW_MANIFEST,
skipWaiting: true,
clientsClaim: true,
navigationPreload: true,
runtimeCaching: [
{
matcher: ({ url, request }) =>
url.hostname.endsWith(".supabase.co") &&
url.pathname.startsWith("/rest/v1/") &&
request.method === "GET",
handler: new NetworkFirst({
cacheName: "supabase-rest-get",
networkTimeoutSeconds: 10,
plugins: [
offlineGatePlugin,
new ExpirationPlugin({
maxEntries: 200,
maxAgeSeconds: 60 * 60 * 24,
}),
],
}),
},
{
matcher: ({ request, sameOrigin }) =>
sameOrigin && request.destination === "image",
handler: new CacheFirst({
cacheName: "entry-images",
plugins: [
new ExpirationPlugin({
maxEntries: 500,
maxAgeSeconds: 60 * 60 * 24 * 7,
}),
],
}),
},
...sameOriginCache,
],
})
serwist.addEventListeners()