fix: WebSocket reconnect race, parse error tracking, RPC timeout reduction, vendor chunk split

- F8: Add isReconnecting flag to prevent parallel reconnection attempts
- F9: Track JSON parse errors, force reconnect after 3 consecutive failures
- F11: Reduce RPC timeout to 15s, add jitter to retry backoff
- F12: Add vendor chunk splitting for vue/router/pinia
- F13: DOMPurify already applied to QR SVGs — verified
- F14: Replace O(n) goals alias lookup with Map-based O(1)
- F15: Wrap 7 localStorage.setItem calls in try/catch across 5 stores

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-21 01:57:05 +00:00
co-authored by Claude Opus 4.6
parent f3976ba03a
commit 3b35b1bee0
9 changed files with 58 additions and 17 deletions
+13 -3
View File
@@ -13,10 +13,20 @@ const APP_ALIASES: Record<string, string[]> = {
'bitcoin-knots': ['bitcoin', 'bitcoin-core'],
}
/** Pre-built reverse lookup: variant pkgId → Set of canonical appIds it matches */
const ALIAS_REVERSE = new Map<string, Set<string>>()
for (const [canonical, aliases] of Object.entries(APP_ALIASES)) {
for (const alias of aliases) {
let set = ALIAS_REVERSE.get(alias)
if (!set) { set = new Set(); ALIAS_REVERSE.set(alias, set) }
set.add(canonical)
}
}
function matchesAppId(pkgId: string, appId: string): boolean {
if (pkgId === appId) return true
const aliases = APP_ALIASES[appId]
return aliases ? aliases.includes(pkgId) : false
const reverseHits = ALIAS_REVERSE.get(pkgId)
return reverseHits ? reverseHits.has(appId) : false
}
export const useGoalStore = defineStore('goals', () => {
@@ -32,7 +42,7 @@ export const useGoalStore = defineStore('goals', () => {
}
function save() {
localStorage.setItem(STORAGE_KEY, JSON.stringify(progress.value))
try { localStorage.setItem(STORAGE_KEY, JSON.stringify(progress.value)) } catch { /* localStorage full or unavailable */ }
}
function getGoalStatus(goalId: string): GoalStatus {