AppView in a box as a Vite plugin thing hatk.dev
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 64 lines 2.1 kB view raw
1// Namespaced browser storage for OAuth state and tokens 2// 3// sessionStorage: PKCE verifier, OAuth state (per-tab, cleared on callback) 4// localStorage: tokens, user DID (shared across tabs) 5 6export function createStorage(namespace) { 7 const key = (name) => `appview_${namespace}_${name}` 8 9 // sessionStorage keys (per-tab OAuth flow state) 10 const SESSION_KEYS = new Set(['codeVerifier', 'oauthState', 'redirectUri']) 11 12 return { 13 get(name) { 14 const store = SESSION_KEYS.has(name) ? sessionStorage : localStorage 15 return store.getItem(key(name)) 16 }, 17 set(name, value) { 18 const store = SESSION_KEYS.has(name) ? sessionStorage : localStorage 19 store.setItem(key(name), value) 20 }, 21 remove(name) { 22 const store = SESSION_KEYS.has(name) ? sessionStorage : localStorage 23 store.removeItem(key(name)) 24 }, 25 clear() { 26 for (const name of SESSION_KEYS) sessionStorage.removeItem(key(name)) 27 for (const name of ['accessToken', 'refreshToken', 'tokenExpiresAt', 'userDid', 'clientId']) { 28 localStorage.removeItem(key(name)) 29 } 30 }, 31 } 32} 33 34// Multi-tab lock for token refresh coordination 35const LOCK_TIMEOUT = 5000 36 37export async function acquireLock(namespace, lockName) { 38 const lockKey = `appview_${namespace}_lock_${lockName}` 39 const lockValue = `${Date.now()}_${Math.random()}` 40 const deadline = Date.now() + LOCK_TIMEOUT 41 42 while (Date.now() < deadline) { 43 const existing = localStorage.getItem(lockKey) 44 if (existing) { 45 const ts = parseInt(existing.split('_')[0]) 46 if (Date.now() - ts > LOCK_TIMEOUT) { 47 localStorage.removeItem(lockKey) 48 } else { 49 await new Promise((r) => setTimeout(r, 50)) 50 continue 51 } 52 } 53 54 localStorage.setItem(lockKey, lockValue) 55 await new Promise((r) => setTimeout(r, 10)) 56 if (localStorage.getItem(lockKey) === lockValue) return lockValue 57 } 58 return null 59} 60 61export function releaseLock(namespace, lockName, lockValue) { 62 const lockKey = `appview_${namespace}_lock_${lockName}` 63 if (localStorage.getItem(lockKey) === lockValue) localStorage.removeItem(lockKey) 64}