c11b71a0ef
postMessage is unreliable on first load — SW may not be active yet. IndexedDB is shared between page and SW, so the token is always available regardless of SW lifecycle timing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
46 lines
1.3 KiB
JavaScript
46 lines
1.3 KiB
JavaScript
const DB_NAME = 'furumi-sw'
|
|
const STORE = 'auth'
|
|
const KEY = 'bearer'
|
|
|
|
function openDB() {
|
|
return new Promise((resolve, reject) => {
|
|
const req = indexedDB.open(DB_NAME, 1)
|
|
req.onupgradeneeded = () => req.result.createObjectStore(STORE)
|
|
req.onsuccess = () => resolve(req.result)
|
|
req.onerror = () => reject(req.error)
|
|
})
|
|
}
|
|
|
|
async function getToken() {
|
|
try {
|
|
const db = await openDB()
|
|
return new Promise((resolve) => {
|
|
const tx = db.transaction(STORE, 'readonly')
|
|
const req = tx.objectStore(STORE).get(KEY)
|
|
req.onsuccess = () => resolve(req.result || null)
|
|
req.onerror = () => resolve(null)
|
|
})
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
self.addEventListener('fetch', (e) => {
|
|
const url = new URL(e.request.url)
|
|
if (url.origin !== self.location.origin || !url.pathname.startsWith('/api/')) return
|
|
|
|
e.respondWith(
|
|
(async () => {
|
|
const token = await getToken()
|
|
if (!token) return fetch(e.request)
|
|
|
|
const headers = new Headers(e.request.headers)
|
|
headers.set('Authorization', `Bearer ${token}`)
|
|
return fetch(new Request(e.request, { headers }))
|
|
})()
|
|
)
|
|
})
|
|
|
|
self.addEventListener('install', () => self.skipWaiting())
|
|
self.addEventListener('activate', (e) => e.waitUntil(self.clients.claim()))
|