返回 AiToEarn
indexedDBStorage.ts
根目录 / project / aitoearn-web / src / utils / storage / indexedDBStorage.ts
1 import type { StateStorage } from 'zustand/middleware'
2
3 /**
4 * 检查是否在浏览器环境中
5 * 用于避免在 SSR 环境下访问浏览器 API
6 */
7 const isBrowser = typeof window !== 'undefined' && typeof indexedDB !== 'undefined'
8
9 /**
10 * 动态导入 idb-keyval,仅在浏览器环境中使用
11 * 避免 SSR 时报错:indexedDB is not defined
12 */
13 async function getIdbKeyval() {
14 if (!isBrowser) {
15 return null
16 }
17 return import('idb-keyval')
18 }
19
20 /**
21 * IndexedDB 存储类
22 * 实现 zustand 的 StateStorage 接口
23 * 在 SSR 环境下会 fallback 到 localStorage 或返回空值
24 */
25 class IndexedDBStorage implements StateStorage {
26 public async getItem(name: string): Promise<string | null> {
27 // SSR 环境下直接返回 null
28 if (!isBrowser) {
29 return null
30 }
31
32 try {
33 const idb = await getIdbKeyval()
34 if (idb) {
35 const value = (await idb.get(name)) || localStorage.getItem(name)
36 return value
37 }
38 return localStorage.getItem(name)
39 }
40 catch (error) {
41 console.error('[IndexedDBStorage] getItem error:', error)
42 return localStorage.getItem(name)
43 }
44 }
45
46 public async setItem(name: string, value: string): Promise<void> {
47 // SSR 环境下不执行存储操作
48 if (!isBrowser) {
49 return
50 }
51
52 try {
53 const _value = JSON.parse(value)
54 if (!_value?.state?._hasHydrated) {
55 return
56 }
57 const idb = await getIdbKeyval()
58 if (idb) {
59 await idb.set(name, value)
60 }
61 }
62 catch (error) {
63 console.error('[IndexedDBStorage] setItem error:', error)
64 if (isBrowser) {
65 localStorage.setItem(name, value)
66 }
67 }
68 }
69
70 public async removeItem(name: string): Promise<void> {
71 // SSR 环境下不执行删除操作
72 if (!isBrowser) {
73 return
74 }
75
76 try {
77 const idb = await getIdbKeyval()
78 if (idb) {
79 await idb.del(name)
80 }
81 }
82 catch (error) {
83 console.error('[IndexedDBStorage] removeItem error:', error)
84 localStorage.removeItem(name)
85 }
86 }
87
88 public async clear(): Promise<void> {
89 // SSR 环境下不执行清除操作
90 if (!isBrowser) {
91 return
92 }
93
94 try {
95 const idb = await getIdbKeyval()
96 if (idb) {
97 await idb.clear()
98 }
99 }
100 catch (error) {
101 console.error('[IndexedDBStorage] clear error:', error)
102 localStorage.clear()
103 }
104 }
105 }
106
107 export const indexedDBStorage = new IndexedDBStorage()
108
108 lines TYPESCRIPT