{ "version": 3, "sources": ["indexed-db-kv-store.ts", "push-notifications-controller.ts", "push-notifications.ts"], "sourcesContent": ["// localStorage-like API, but based on IndexedDB, so that it is usable both from normal code and service workers\n//\n// written by claude.ai\n\nasync function done(tx: IDBTransaction){\n return new Promise((resolve, reject) => {\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n}\n\nexport async function set(key: string, value: string) {\n const db = await openDB();\n const tx = db.transaction(['kvStore'], 'readwrite');\n const store = tx.objectStore('kvStore');\n store.put({ key, value });\n await done(tx);\n db.close();\n}\n\nexport async function get(key: string): Promise {\n const db = await openDB();\n const tx = db.transaction(['kvStore'], 'readonly');\n const store = tx.objectStore('kvStore');\n const item = store.get(key);\n await done(tx);\n db.close();\n return item.result?.value;\n}\n\nexport async function remove(key: string) {\n const db = await openDB();\n const tx = db.transaction(['kvStore'], 'readwrite');\n const store = tx.objectStore('kvStore');\n store.delete(key);\n await done(tx);\n db.close();\n}\n\nasync function openDB() {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open('kvStore', 1);\n\n request.onupgradeneeded = _ => {\n const db = request.result;\n db.createObjectStore('kvStore', { keyPath: 'key' });\n };\n\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n", "\uFEFF// Based on https://github.com/tpeczek/Demo.AspNetCore.PushNotifications/blob/58f9c836651ce9d9f50d68f16cc55f9e312eb722/Demo.AspNetCore.PushNotifications/wwwroot/scripts/push-notifications-controller.js\n\nimport * as kvStore from \"./indexed-db-kv-store\";\n\nfunction urlB64ToUint8Array(base64String: string) {\n const padding = '='.repeat((4 - base64String.length % 4) % 4);\n const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');\n\n const rawData = window.atob(base64);\n const outputArray = new Uint8Array(rawData.length);\n\n for (let i = 0; i < rawData.length; ++i) {\n outputArray[i] = rawData.charCodeAt(i);\n }\n\n return outputArray;\n}\n\nexport async function unregisterPushEndpoint(endpoint: string) {\n await fetch('/api/push-subscriptions/' + encodeURIComponent(endpoint), {\n method: 'DELETE'\n });\n\n await kvStore.remove(\"pushEndpoint\")\n}\n\nexport async function registerPushSubscription(pushSubscription: PushSubscription) {\n const oldEndpoint = await kvStore.get(\"pushEndpoint\");\n if (oldEndpoint)\n await unregisterPushEndpoint(oldEndpoint);\n\n await fetch('/api/push-subscriptions', {\n method: 'PUT',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(pushSubscription)\n });\n\n await kvStore.set(\"pushEndpoint\", pushSubscription.endpoint);\n}\n\nexport async function retrievePublicKey() {\n let response = await fetch('/api/push-subscriptions/public-key');\n if (response.ok) {\n let applicationServerPublicKeyBase64 = await response.text();\n if (!applicationServerPublicKeyBase64)\n return null;\n return urlB64ToUint8Array(applicationServerPublicKeyBase64);\n } else {\n return Promise.reject(response.status + ' ' + response.statusText);\n }\n}\n", "\uFEFF// Based on https://github.com/tpeczek/Demo.AspNetCore.PushNotifications/blob/58f9c836651ce9d9f50d68f16cc55f9e312eb722/Demo.AspNetCore.PushNotifications/wwwroot/scripts/push-notifications.js\n\nimport {registerPushSubscription, retrievePublicKey, unregisterPushEndpoint} from \"./push-notifications-controller\";\nimport * as kvStore from \"./indexed-db-kv-store\";\n\nlet applicationServerPublicKey;\nlet serviceWorkerCache;\n\n// Keeps track of all push endpoints exposed by this browser since the page loaded.\nconst prevDeviceEndpoints = new Set();\n\nfunction getServiceWorker(): Promise {\n return serviceWorkerCache ??= navigator.serviceWorker\n .register('sw.js')\n // ensure the sw is always updated\n // https://github.com/firebase/firebase-js-sdk/blob/a9f844066045d8567ae143bae77d184ac227690d/packages/messaging/src/helpers/registerDefaultSw.ts#L34-L41\n // TODO: move sw update logic to blazor as it knows whether the sw has actually changed using @Assets[]\n .then(sw => sw.update())\n}\n\nasync function getPushSubscription(): Promise {\n const permission = Notification.permission;\n if (permission !== 'granted') return null;\n return await (await getServiceWorker()).pushManager.getSubscription();\n}\n\n// unregister invalid/outdated endpoints, so they don't show up in the active count\nasync function checkSubscriptionRegistration() {\n const subscription = await getPushSubscription();\n const registeredEndpoint = await kvStore.get(\"pushEndpoint\");\n\n if (registeredEndpoint)\n prevDeviceEndpoints.add(registeredEndpoint);\n if (subscription)\n prevDeviceEndpoints.add(subscription.endpoint);\n\n if (registeredEndpoint && subscription?.endpoint !== registeredEndpoint) {\n await unregisterPushEndpoint(registeredEndpoint);\n }\n}\n\nexport const getPushSubscriptionState = async (): Promise<{\n prevDeviceEndpoints: string[];\n currentEndpoint: string | undefined;\n permissionState: string;\n}> => {\n await checkSubscriptionRegistration();\n\n const permission = Notification.permission;\n const subscription = await getPushSubscription();\n return {\n permissionState: permission,\n currentEndpoint: subscription?.endpoint,\n prevDeviceEndpoints: [...prevDeviceEndpoints],\n };\n};\n\n// @ts-ignore\nwindow.getPushSubscriptionState = getPushSubscriptionState;\n\n// @ts-ignore\nwindow.subscribeToPushNotifications = async (): Promise => {\n document.cookie = 'No-Push=; Expires=Thu, 01 Jan 1970 00:00:00 UTC; SameSite=Lax; Path=/; Secure';\n\n const permissionState = await Notification.requestPermission();\n if (permissionState !== 'granted')\n return null;\n\n applicationServerPublicKey ??= await retrievePublicKey();\n const pushSubscription = await (await getServiceWorker()).pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: applicationServerPublicKey\n })\n await registerPushSubscription(pushSubscription)\n\n prevDeviceEndpoints.add(pushSubscription.endpoint);\n return pushSubscription.endpoint;\n};\n\nasync function unsubscribeFromPushNotifications() {\n const pushSubscription = await (await getServiceWorker()).pushManager.getSubscription();\n if (!pushSubscription)\n return;\n await pushSubscription.unsubscribe();\n await unregisterPushEndpoint(pushSubscription.endpoint)\n}\n\n// @ts-ignore\nwindow.unsubscribeFromPushNotifications = unsubscribeFromPushNotifications;\n\n// Used by LogInOrOut.razor\n// @ts-ignore\nwindow.beforeSignOut = async (event: SubmitEvent) => {\n event.preventDefault();\n\n await unsubscribeFromPushNotifications();\n document.cookie = 'No-Push=; Expires=Thu, 01 Jan 1970 00:00:00 UTC; SameSite=Lax; Path=/; Secure';\n\n (event.target as HTMLFormElement).submit();\n};"], "mappings": "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", "names": [] }