db (IndexedDB)
基於 Dexie 的 IndexedDB 簡易封裝,framework 用它快取 .bnc 解密後的資源(SwImage / SwAsyncText / useDecryptedAsset 的持久快取層)。業務需要用戶端持久化大塊二進位 / 結構化資料時也可直接用。3 個函式全部 auto-import。
運作原理
- 模組載入時即建立 Dexie 實例(資料庫名
database,版本 1),固定包含兩個 store:image— 解密後的圖片二進位 / blob URL 快取text— 解密後的文字片段快取
- 每筆記錄帶自增
++id和updated_at索引,便於按時間淘汰。 - 每個 API 首次呼叫會懶開啟資料庫,Dexie 處理並行競爭;實例為模組級單例,同一分頁內多處呼叫共享連線。
dbPut自動覆寫updated_at(秒級時間戳),呼叫方無需手動維護。
API
| 函式 | 簽名 | 說明 |
|---|---|---|
dbPut | (data: object, storeName: string) => Promise<void> | 新增或更新一筆記錄(data 需含 id 欄位作主鍵),自動寫 updated_at |
dbGet | (id: string, storeName: string) => Promise<unknown> | 按 id 查詢單筆記錄,未命中回傳 undefined |
dbClear | (storeName: string) => Promise<void> | 清空指定 store |
使用範例
dbPut / dbGet 讀寫(重新整理仍在)
加载中...
// 快取解密後的圖片 blob URL
await dbPut({ id: 'cover.bnc', url: blobUrl }, 'image')
// 讀取快取,未命中則回源解密
const hit = await dbGet('cover.bnc', 'image')
const url = hit?.url ?? await decryptAndCache('cover.bnc')
// 登出時清空全部快取
await dbClear('image')
await dbClear('text')
注意事項
僅用戶端可用(DB-001,blocker)
IndexedDB 是瀏覽器 API,Node.js 端不存在 —— SSR 期呼叫直接報錯。所有 db API 必須在 onMounted / IS_CLIENT 守衛 / client-only 元件內呼叫:
// ❌ setup 頂層呼叫,SSR 期 indexedDB is not defined
const hit = await dbGet('cover.bnc', 'image')
// ✅ onMounted 內呼叫
onMounted(async () => {
const hit = await dbGet('cover.bnc', 'image')
})
storeName 只能是 'image' / 'text'(DB-002,warning)
schema 固定只有這兩個 store,但 storeName 參數類型是裸 string、無編譯校驗。傳未定義的表名(如 'user' / 'cover'),Dexie 回傳「幽靈 table」 —— 寫入成功不報錯,但資料進虛空、永遠讀不回來,排查極難:
// ❌ 'cover' 不是 framework 建的 store → 寫入成功但讀不回
await dbPut({ id: 'x', url }, 'cover')
const hit = await dbGet('x', 'cover') // 永遠 undefined
// ✅ 只用框架建的兩個表名
await dbPut({ id: 'x', url }, 'image')
需要業務自有表結構時,請在業務層另建自己的 Dexie 實例,不要複用 framework 的 database。