tack-up-now/app/worker.ts

115 lines
3.1 KiB
TypeScript

import Dexie, { EntityTable } from "dexie"
import urlB64ToUint8Array from "../b64ToUInt8"
import pushPublicKey from "../pushPublicKey"
interface SubscriptionRecord {
id: number
subscriptionId: number
}
export default function start(self: ServiceWorkerGlobalScope) {
self.addEventListener("install", (event) => {
event.waitUntil(self.skipWaiting())
})
self.addEventListener("activate", (event) => {
event.waitUntil(self.clients.claim())
})
// self.addEventListener("push", function (event: PushEvent) {
// console.log("[Service Worker] Push Received.")
// console.log(`[Service Worker] Push had this data: "${event.data?.text()}"`)
// const title = "Push Codelab"
// const options = {
// body: "Yay it works.",
// icon: "images/icon.png",
// badge: "images/badge.png",
// }
// event.waitUntil(self.registration.showNotification(title, options))
// })
// self.addEventListener("notificationclick", function (event) {
// console.log("[Service Worker] Notification click Received.")
// event.notification.close()
// event.waitUntil(
// self.clients.openWindow("https://developers.google.com/web/")
// )
// })
self.addEventListener("message", function (event) {
const waitEvent = event as ExtendableEvent
if ("type" in event.data && event.data.type === "subscribed") {
waitEvent.waitUntil(submitSubscription(event.data.subscription))
}
})
self.addEventListener("pushsubscriptionchange", function (event) {
const waitEvent = event as ExtendableEvent
waitEvent.waitUntil(
(async () => {
const applicationServerKey = urlB64ToUint8Array(pushPublicKey)
const newSubscription = await self.registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey,
})
await submitSubscription(newSubscription.toJSON())
})()
)
})
}
async function submitSubscription(subscription: PushSubscriptionJSON) {
const db = database()
const existingSubscriptionId = await db.subscriptions.get(1)
await (existingSubscriptionId === undefined
? postSubscription(subscription, db)
: putSubscription(subscription, existingSubscriptionId.subscriptionId))
}
async function postSubscription(
subscription: PushSubscriptionJSON,
db: ReturnType<typeof database>
) {
const response = await fetch(`${process.env.BASE_URL}/api/subscription/`, {
method: "POST",
body: JSON.stringify(subscription),
headers: {
"Content-Type": "application/json",
},
})
db.subscriptions.put({
id: 1,
subscriptionId: (await response.json()).subscriptionId,
})
}
function putSubscription(subscription: PushSubscriptionJSON, id: number) {
return fetch(`${process.env.BASE_URL}/api/subscription/${id}`, {
method: "PUT",
body: JSON.stringify(subscription),
headers: {
"Content-Type": "application/json",
},
})
}
function database() {
const db = new Dexie("tack-up-now", { indexedDB }) as Dexie & {
subscriptions: EntityTable<SubscriptionRecord, "id">
}
db.version(1).stores({ subscriptions: "id++, subscriptionId&" })
return db
}