@lobehub/lobehub 2.0.0-next.59 → 2.0.0-next.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,341 +0,0 @@
1
- import { afterEach, describe, expect, it, vi } from 'vitest';
2
-
3
- import { createHyperStorage } from './index';
4
- import { createIndexedDB } from './indexedDB';
5
- import { createKeyMapper } from './keyMapper';
6
- import { createLocalStorage } from './localStorage';
7
- import { creatUrlStorage } from './urlStorage';
8
-
9
- // Mock the dependent modules
10
- vi.mock('./indexedDB', () => {
11
- return {
12
- createIndexedDB: vi.fn(),
13
- };
14
- });
15
-
16
- vi.mock('./localStorage', () => ({
17
- createLocalStorage: vi.fn(),
18
- }));
19
-
20
- vi.mock('./urlStorage', () => ({
21
- creatUrlStorage: vi.fn(),
22
- }));
23
-
24
- vi.mock('./keyMapper', () => ({
25
- createKeyMapper: vi.fn().mockReturnValue({
26
- mapStateKeyToStorageKey: vi.fn((k) => k),
27
- getStateKeyFromStorageKey: vi.fn((k) => k),
28
- }),
29
- }));
30
-
31
- afterEach(() => {
32
- vi.mocked(createKeyMapper).mockClear();
33
- });
34
-
35
- describe('createHyperStorage', () => {
36
- it('should create storage with default configuration if no options provided', async () => {
37
- const storage = createHyperStorage({});
38
- expect(storage).toBeDefined();
39
- // Add more assertions to verify default behavior
40
- });
41
-
42
- it('should skip local storage if explicitly disabled', async () => {
43
- const storage = createHyperStorage({ localStorage: false });
44
- await storage.setItem('key', { state: {}, version: 1 });
45
-
46
- // The setItem should not call the local storage functions
47
- const indexDBSetItemMock = vi.fn();
48
-
49
- vi.mocked(createIndexedDB).mockImplementation(() => ({
50
- getItem: vi.fn(),
51
- removeItem: vi.fn(),
52
- setItem: indexDBSetItemMock,
53
- }));
54
-
55
- const localStorageSetItemMock = vi.fn();
56
-
57
- vi.mocked(createLocalStorage).mockImplementation(() => ({
58
- getItem: vi.fn(),
59
- removeItem: vi.fn(),
60
- setItem: localStorageSetItemMock,
61
- }));
62
-
63
- expect(indexDBSetItemMock).not.toHaveBeenCalled();
64
- expect(localStorageSetItemMock).not.toHaveBeenCalled();
65
- });
66
-
67
- it('should use indexedDB mode if set in local storage options', async () => {
68
- // The setItem should call the indexedDB functions
69
- // The setItem should not call the local storage functions
70
- const indexDBSetItemMock = vi.fn();
71
-
72
- vi.mocked(createIndexedDB).mockImplementation(() => ({
73
- getItem: vi.fn(),
74
- removeItem: vi.fn(),
75
- setItem: indexDBSetItemMock,
76
- }));
77
-
78
- const storage = createHyperStorage({
79
- localStorage: { mode: 'indexedDB', dbName: 'testDB', selectors: [] },
80
- });
81
-
82
- await storage.setItem('key', { state: {}, version: 1 });
83
-
84
- expect(indexDBSetItemMock).toHaveBeenCalled();
85
- });
86
-
87
- it('should use the provided dbName for indexedDB', async () => {
88
- const dbName = 'customDB';
89
- createHyperStorage({ localStorage: { mode: 'indexedDB', dbName, selectors: [] } });
90
-
91
- expect(vi.mocked(createIndexedDB)).toHaveBeenCalledWith(dbName);
92
- });
93
-
94
- it('should handle URL storage if URL options are provided', async () => {
95
- const urlMode = 'hash';
96
- const setItemMock = vi.fn();
97
-
98
- vi.mocked(creatUrlStorage).mockImplementation(() => ({
99
- getItem: vi.fn(),
100
- removeItem: vi.fn(),
101
- setItem: setItemMock,
102
- }));
103
-
104
- const storage = createHyperStorage({ url: { mode: urlMode, selectors: [] } });
105
-
106
- await storage.setItem('key', { state: {}, version: 1 });
107
-
108
- expect(creatUrlStorage).toHaveBeenCalledWith(urlMode);
109
- // The setItem should call the urlStorage functions
110
- expect(setItemMock).toHaveBeenCalled();
111
- });
112
-
113
- describe('getItem method', () => {
114
- it('should retrieve item from indexedDB when useIndexedDB is true', async () => {
115
- const indexedDBGetItemMock = vi
116
- .fn()
117
- .mockResolvedValue({ state: { key: 'value' }, version: 1 });
118
- vi.mocked(createIndexedDB).mockImplementation(() => ({
119
- getItem: indexedDBGetItemMock,
120
- removeItem: vi.fn(),
121
- setItem: vi.fn(),
122
- }));
123
-
124
- const storage = createHyperStorage({ localStorage: { mode: 'indexedDB', selectors: [] } });
125
- const item = await storage.getItem('key');
126
-
127
- expect(indexedDBGetItemMock).toHaveBeenCalledWith('key');
128
- expect(item).toEqual({ state: { key: 'value' }, version: 1 });
129
- });
130
-
131
- it('should fallback to localStorage if item not found in indexedDB', async () => {
132
- const indexedDBGetItemMock = vi.fn().mockResolvedValue(undefined);
133
- const localStorageGetItemMock = vi
134
- .fn()
135
- .mockReturnValue({ state: { key: 'value' }, version: 1 });
136
-
137
- vi.mocked(createIndexedDB).mockImplementation(() => ({
138
- getItem: indexedDBGetItemMock,
139
- removeItem: vi.fn(),
140
- setItem: vi.fn(),
141
- }));
142
-
143
- vi.mocked(createLocalStorage).mockImplementation(() => ({
144
- getItem: localStorageGetItemMock,
145
- removeItem: vi.fn(),
146
- setItem: vi.fn(),
147
- }));
148
-
149
- const storage = createHyperStorage({ localStorage: { mode: 'indexedDB', selectors: [] } });
150
- const item = await storage.getItem('key');
151
-
152
- expect(indexedDBGetItemMock).toHaveBeenCalledWith('key');
153
- expect(localStorageGetItemMock).toHaveBeenCalledWith('key');
154
- expect(item).toEqual({ state: { key: 'value' }, version: 1 });
155
- });
156
-
157
- it('should not attempt to retrieve from any storage if skipLocalStorage is true', async () => {
158
- const storage = createHyperStorage({ localStorage: false });
159
- const item = await storage.getItem('key');
160
-
161
- const indexedDBGetItemMock = vi.fn().mockResolvedValue(undefined);
162
- const localStorageGetItemMock = vi
163
- .fn()
164
- .mockReturnValue({ state: { key: 'value' }, version: 1 });
165
-
166
- vi.mocked(createIndexedDB).mockImplementation(() => ({
167
- getItem: indexedDBGetItemMock,
168
- removeItem: vi.fn(),
169
- setItem: vi.fn(),
170
- }));
171
-
172
- vi.mocked(createLocalStorage).mockImplementation(() => ({
173
- getItem: localStorageGetItemMock,
174
- removeItem: vi.fn(),
175
- setItem: vi.fn(),
176
- }));
177
-
178
- expect(indexedDBGetItemMock).not.toHaveBeenCalled();
179
- expect(localStorageGetItemMock).not.toHaveBeenCalled();
180
- expect(item).toEqual({ state: {}, version: undefined });
181
- });
182
-
183
- describe('getItem method with URL storage', () => {
184
- it('should override state from URL storage if hasUrl is true', async () => {
185
- const urlStorageGetItemMock = vi.fn().mockReturnValue({ state: { urlKey: 'urlValue' } });
186
- vi.mocked(creatUrlStorage).mockImplementation(() => ({
187
- getItem: urlStorageGetItemMock,
188
- removeItem: vi.fn(),
189
- setItem: vi.fn(),
190
- }));
191
-
192
- // Mock createKeyMapper to simulate state key mapping from URL storage keys
193
- vi.mocked(createKeyMapper).mockReturnValue({
194
- mapStateKeyToStorageKey: vi.fn((k) => k),
195
- getStateKeyFromStorageKey: vi.fn((k) => (k === 'urlKey' ? 'mappedKey' : undefined)),
196
- });
197
-
198
- const storage = createHyperStorage({
199
- url: { mode: 'hash', selectors: [] },
200
- localStorage: false,
201
- });
202
- const item = await storage.getItem('key');
203
-
204
- expect(urlStorageGetItemMock).toHaveBeenCalled();
205
- expect(item?.state).toEqual({ mappedKey: 'urlValue' });
206
- });
207
-
208
- it('should not include URL storage state if key mapping is undefined', async () => {
209
- const urlStorageGetItemMock = vi.fn().mockReturnValue({ state: { urlKey: 'urlValue' } });
210
- vi.mocked(creatUrlStorage).mockImplementation(() => ({
211
- getItem: urlStorageGetItemMock,
212
- removeItem: vi.fn(),
213
- setItem: vi.fn(),
214
- }));
215
-
216
- // Mock createKeyMapper to simulate state key mapping from URL storage keys
217
- vi.mocked(createKeyMapper).mockReturnValue({
218
- mapStateKeyToStorageKey: vi.fn((k) => k),
219
- getStateKeyFromStorageKey: vi.fn(() => undefined), // No key will be mapped
220
- });
221
-
222
- const storage = createHyperStorage({
223
- url: { mode: 'hash', selectors: [] },
224
- localStorage: false,
225
- });
226
- const item = await storage.getItem('key');
227
-
228
- expect(urlStorageGetItemMock).toHaveBeenCalled();
229
- expect(item?.state).toEqual({}); // No state from URL storage should be included
230
- });
231
-
232
- it('should not attempt to retrieve from URL storage if hasUrl is false', async () => {
233
- const urlStorageGetItemMock = vi.fn();
234
- vi.mocked(creatUrlStorage).mockImplementation(() => ({
235
- getItem: urlStorageGetItemMock,
236
- removeItem: vi.fn(),
237
- setItem: vi.fn(),
238
- }));
239
-
240
- const storage = createHyperStorage({ localStorage: false }); // No URL options provided
241
- await storage.getItem('key');
242
-
243
- expect(urlStorageGetItemMock).not.toHaveBeenCalled();
244
- });
245
- });
246
- });
247
-
248
- describe('removeItem method', () => {
249
- it('should remove item from indexedDB when useIndexedDB is true', async () => {
250
- const indexedDBRemoveItemMock = vi.fn().mockResolvedValue(undefined);
251
- vi.mocked(createIndexedDB).mockImplementation(() => ({
252
- getItem: vi.fn(),
253
- removeItem: indexedDBRemoveItemMock,
254
- setItem: vi.fn(),
255
- }));
256
-
257
- const storage = createHyperStorage({ localStorage: { mode: 'indexedDB', selectors: [] } });
258
- await storage.removeItem('key');
259
-
260
- expect(indexedDBRemoveItemMock).toHaveBeenCalledWith('key');
261
- });
262
-
263
- it('should remove item from localStorage when useIndexedDB is false', async () => {
264
- const localStorageRemoveItemMock = vi.fn().mockResolvedValue(undefined);
265
- vi.mocked(createLocalStorage).mockImplementation(() => ({
266
- getItem: vi.fn(),
267
- removeItem: localStorageRemoveItemMock,
268
- setItem: vi.fn(),
269
- }));
270
-
271
- const storage = createHyperStorage({});
272
- await storage.removeItem('key');
273
-
274
- expect(localStorageRemoveItemMock).toHaveBeenCalledWith('key');
275
- });
276
-
277
- it('should remove item from URL storage if URL options provided', async () => {
278
- const urlStorageRemoveItemMock = vi.fn();
279
-
280
- vi.mocked(creatUrlStorage).mockImplementation(() => ({
281
- getItem: vi.fn(),
282
- removeItem: urlStorageRemoveItemMock,
283
- setItem: vi.fn(),
284
- }));
285
- // Mock createKeyMapper to simulate state key mapping from URL storage keys
286
- vi.mocked(createKeyMapper).mockReturnValue({
287
- mapStateKeyToStorageKey: vi.fn((k) => k),
288
- getStateKeyFromStorageKey: vi.fn((k) => k), // No key will be mapped
289
- });
290
-
291
- const storage = createHyperStorage({ url: { mode: 'hash', selectors: ['key'] } });
292
- await storage.removeItem('key');
293
-
294
- expect(urlStorageRemoveItemMock).toHaveBeenCalledWith('key');
295
- });
296
- });
297
-
298
- describe('setItem method', () => {
299
- it('should save item to indexedDB when useIndexedDB is true', async () => {
300
- const indexedDBSetItemMock = vi.fn().mockResolvedValue(undefined);
301
- vi.mocked(createIndexedDB).mockImplementation(() => ({
302
- getItem: vi.fn(),
303
- removeItem: vi.fn(),
304
- setItem: indexedDBSetItemMock,
305
- }));
306
-
307
- const storage = createHyperStorage({ localStorage: { mode: 'indexedDB', selectors: [] } });
308
- await storage.setItem('key', { state: { key: 'value' }, version: 1 });
309
-
310
- expect(indexedDBSetItemMock).toHaveBeenCalledWith('key', { key: 'value' }, 1);
311
- });
312
-
313
- it('should save item to localStorage when useIndexedDB is false', async () => {
314
- const localStorageSetItemMock = vi.fn().mockResolvedValue(undefined);
315
- vi.mocked(createLocalStorage).mockImplementation(() => ({
316
- getItem: vi.fn(),
317
- removeItem: vi.fn(),
318
- setItem: localStorageSetItemMock,
319
- }));
320
-
321
- const storage = createHyperStorage({});
322
- await storage.setItem('key', { state: { key: 'value' }, version: 1 });
323
-
324
- expect(localStorageSetItemMock).toHaveBeenCalledWith('key', { key: 'value' }, 1);
325
- });
326
-
327
- it('should save state to URL storage if URL options provided', async () => {
328
- const urlStorageSetItemMock = vi.fn().mockResolvedValue(undefined);
329
- vi.mocked(creatUrlStorage).mockImplementation(() => ({
330
- getItem: vi.fn(),
331
- removeItem: vi.fn(),
332
- setItem: urlStorageSetItemMock,
333
- }));
334
-
335
- const storage = createHyperStorage({ url: { mode: 'hash', selectors: [] } });
336
- await storage.setItem('key', { state: { key: 'value' }, version: 1 });
337
-
338
- expect(urlStorageSetItemMock).toHaveBeenCalled();
339
- });
340
- });
341
- });
@@ -1,126 +0,0 @@
1
- import { PersistStorage, StorageValue } from 'zustand/middleware';
2
-
3
- import { createIndexedDB } from './indexedDB';
4
- import { createKeyMapper } from './keyMapper';
5
- import { createLocalStorage } from './localStorage';
6
- import { HyperStorageOptions } from './type';
7
- import { creatUrlStorage } from './urlStorage';
8
-
9
- export const createHyperStorage = <T extends object>(
10
- options: HyperStorageOptions,
11
- ): PersistStorage<T> => {
12
- const optionsObj = typeof options === 'function' ? options() : options;
13
-
14
- const getLocalStorageConfig = () => {
15
- if (optionsObj.localStorage === false) {
16
- return { dbName: '', skipLocalStorage: true, useIndexedDB: false };
17
- }
18
-
19
- const useIndexedDB = optionsObj.localStorage?.mode === 'indexedDB';
20
- const dbName = optionsObj.localStorage?.dbName || 'indexedDB';
21
-
22
- return { dbName, skipLocalStorage: false, useIndexedDB };
23
- };
24
-
25
- const hasUrl = !!optionsObj.url;
26
-
27
- const { skipLocalStorage, useIndexedDB, dbName } = getLocalStorageConfig();
28
-
29
- const { mapStateKeyToStorageKey, getStateKeyFromStorageKey } = createKeyMapper(optionsObj);
30
-
31
- const indexedDB = createIndexedDB(dbName);
32
- const localStorage = createLocalStorage();
33
- const urlStorage = creatUrlStorage(optionsObj.url?.mode);
34
- return {
35
- getItem: async (name): Promise<StorageValue<T>> => {
36
- const state: any = {};
37
- let version: number | undefined;
38
-
39
- // ============== 处理 Local Storage ============== //
40
- if (!skipLocalStorage) {
41
- let localState: StorageValue<T> | undefined;
42
-
43
- // 如果使用 indexedDB,优先从 indexedDB 中获取
44
- if (useIndexedDB) {
45
- localState = await indexedDB.getItem(name);
46
- }
47
- // 如果 indexedDB 中不存在,则再试试 localStorage
48
- if (!localState) localState = localStorage.getItem(name);
49
-
50
- if (localState) {
51
- version = localState.version;
52
- for (const [k, v] of Object.entries(localState.state)) {
53
- const key = getStateKeyFromStorageKey(k, 'localStorage');
54
- if (key) state[key] = v;
55
- }
56
- }
57
- }
58
-
59
- // ============== 处理 URL Storage ============== //
60
- // 不从 URL 中获取 version,由于 url 状态是临时态 不作为版本控制的依据
61
- if (hasUrl) {
62
- const urlState = urlStorage.getItem();
63
-
64
- if (urlState) {
65
- for (const [k, v] of Object.entries(urlState.state)) {
66
- const key = getStateKeyFromStorageKey(k, 'url');
67
- // 当存在 UrlSelector 逻辑,且 key 有效时,才将状态加入终态 state
68
- if (hasUrl && key) {
69
- state[key] = v;
70
- }
71
- }
72
- }
73
- }
74
-
75
- return { state, version };
76
- },
77
- removeItem: async (key) => {
78
- // ============== 处理 Local Storage ============== //
79
- if (!skipLocalStorage) {
80
- if (useIndexedDB) {
81
- await indexedDB.removeItem(key);
82
- } else {
83
- localStorage.removeItem(key);
84
- }
85
- }
86
-
87
- // ============== 处理 URL Storage ============== //
88
- if (hasUrl) {
89
- const storageKey = getStateKeyFromStorageKey(key, 'url');
90
-
91
- urlStorage.removeItem(storageKey);
92
- }
93
- },
94
-
95
- setItem: async (name, newValue) => {
96
- // ============== 处理 Local Storage ============== //
97
- const localState: Record<string, any> = {};
98
- for (const [k, v] of Object.entries(newValue.state)) {
99
- const localKey = mapStateKeyToStorageKey(k, 'localStorage');
100
- if (localKey) localState[localKey] = v;
101
- }
102
-
103
- if (!skipLocalStorage) {
104
- if (useIndexedDB) {
105
- await indexedDB.setItem(name, localState, newValue.version);
106
- } else {
107
- localStorage.setItem(name, localState, newValue.version);
108
- }
109
- }
110
-
111
- // ============== 处理 URL Storage ============== //
112
- if (hasUrl) {
113
- // 转换 key 为目标 key
114
- const finalEntries = Object.entries(newValue.state)
115
- .map(([k, v]) => {
116
- const urlKey = mapStateKeyToStorageKey(k, 'url');
117
- if (!urlKey) return undefined;
118
- return [urlKey, v];
119
- })
120
- .filter(Boolean) as [string, any][];
121
-
122
- urlStorage.setItem(name, Object.fromEntries(finalEntries));
123
- }
124
- },
125
- };
126
- };
@@ -1,64 +0,0 @@
1
- import { delMany, getMany, setMany } from 'idb-keyval';
2
- import { beforeEach, describe, expect, it, vi } from 'vitest';
3
-
4
- import { createIndexedDB } from './indexedDB';
5
-
6
- // Mock idb-keyval methods
7
- vi.mock('idb-keyval', () => ({
8
- createStore: vi.fn().mockImplementation(() => 'abc'),
9
- getMany: vi.fn(),
10
- setMany: vi.fn(),
11
- delMany: vi.fn(),
12
- }));
13
-
14
- describe('createIndexedDB', () => {
15
- const dbName = 'testDB';
16
- const storeName = 'testStore';
17
- const indexedDB = createIndexedDB(dbName);
18
-
19
- beforeEach(() => {
20
- // Reset all mocks before each test
21
- vi.resetAllMocks();
22
- });
23
-
24
- it('getItem should return the correct state and version', async () => {
25
- const mockState = { key: 'value' };
26
- const mockVersion = 1;
27
-
28
- // Setup mock behavior for getMany
29
- vi.mocked(getMany).mockResolvedValue([mockVersion, mockState]);
30
-
31
- const result = await indexedDB.getItem(storeName);
32
-
33
- expect(vi.mocked(getMany).mock.calls[0][0]).toEqual(['version', 'state']);
34
- expect(result).toEqual({ state: mockState, version: mockVersion });
35
- });
36
-
37
- it('getItem should return undefined if state does not exist', async () => {
38
- // Setup mock behavior for getMany
39
- vi.mocked(getMany).mockResolvedValue([undefined, undefined]);
40
-
41
- const result = await indexedDB.getItem(storeName);
42
-
43
- expect(vi.mocked(getMany).mock.calls[0][0]).toEqual(['version', 'state']);
44
- expect(result).toBeUndefined();
45
- });
46
-
47
- it('removeItem should call delMany with the correct keys', async () => {
48
- await indexedDB.removeItem(storeName);
49
-
50
- expect(vi.mocked(delMany).mock.calls[0][0]).toEqual(['version', 'state']);
51
- });
52
-
53
- it('setItem should call setMany with the correct keys and values', async () => {
54
- const mockState = { key: 'value' };
55
- const mockVersion = 1;
56
-
57
- await indexedDB.setItem(storeName, mockState, mockVersion);
58
-
59
- expect(vi.mocked(setMany).mock.calls[0][0]).toEqual([
60
- ['version', mockVersion],
61
- ['state', mockState],
62
- ]);
63
- });
64
- });
@@ -1,26 +0,0 @@
1
- import { createStore, delMany, getMany, setMany } from 'idb-keyval';
2
- import { StorageValue } from 'zustand/middleware';
3
-
4
- export const createIndexedDB = <State extends any>(dbName: string = 'indexedDB') => ({
5
- getItem: async <T extends State>(name: string): Promise<StorageValue<T> | undefined> => {
6
- const [version, state] = await getMany(['version', 'state'], createStore(dbName, name));
7
-
8
- if (!state) return undefined;
9
-
10
- return { state, version };
11
- },
12
- removeItem: async (name: string) => {
13
- await delMany(['version', 'state'], createStore(dbName, name));
14
- },
15
- setItem: async (name: string, state: any, version: number | undefined) => {
16
- const store = createStore(dbName, name);
17
-
18
- await setMany(
19
- [
20
- ['version', version],
21
- ['state', state],
22
- ],
23
- store,
24
- );
25
- },
26
- });
@@ -1,57 +0,0 @@
1
- import { HyperStorageOptionsObj } from './type';
2
-
3
- export const createKeyMapper = (options: HyperStorageOptionsObj) => {
4
- const mapStateKeyToStorageKey = (
5
- key: string,
6
- mode: keyof HyperStorageOptionsObj = 'localStorage',
7
- ) => {
8
- const media = options[mode];
9
- if (media === false) return key;
10
-
11
- const selectors = media?.selectors;
12
- if (!selectors) return key;
13
-
14
- let storageKey: string | undefined;
15
-
16
- for (const selector of selectors) {
17
- if (typeof selector === 'string') {
18
- if (selector === key) storageKey = key;
19
- } else {
20
- if (selector[key]) storageKey = selector[key];
21
- }
22
- }
23
-
24
- return storageKey;
25
- };
26
-
27
- const getStateKeyFromStorageKey = (
28
- key: string,
29
- mode: keyof HyperStorageOptionsObj = 'localStorage',
30
- ) => {
31
- const media = options[mode];
32
- if (media === false) return key;
33
-
34
- const selectors = media?.selectors;
35
- if (!selectors) return key;
36
-
37
- let stateKey: string | undefined;
38
-
39
- for (const item of selectors) {
40
- // 对象如果是 字符串,直接返回该 item key
41
- if (typeof item === 'string') {
42
- if (item === key) stateKey = key;
43
- } else {
44
- for (const [k, v] of Object.entries(item)) {
45
- if (v === key) stateKey = k;
46
- }
47
- }
48
- }
49
-
50
- return stateKey;
51
- };
52
-
53
- return {
54
- getStateKeyFromStorageKey,
55
- mapStateKeyToStorageKey,
56
- };
57
- };
@@ -1,18 +0,0 @@
1
- import { StorageValue } from 'zustand/middleware';
2
-
3
- export const createLocalStorage = <State extends any>() => ({
4
- getItem: <T extends State>(name: string): StorageValue<T> | undefined => {
5
- if (!global.localStorage) return undefined;
6
- const string = localStorage.getItem(name);
7
-
8
- if (string) return JSON.parse(string) as StorageValue<T>;
9
-
10
- return undefined;
11
- },
12
- removeItem: (name: string) => {
13
- if (global.localStorage) localStorage.removeItem(name);
14
- },
15
- setItem: <T extends State>(name: string, state: T, version: number | undefined) => {
16
- if (global.localStorage) localStorage.setItem(name, JSON.stringify({ state, version }));
17
- },
18
- });
@@ -1,25 +0,0 @@
1
- export type StorageSelector = string | Record<string, string>;
2
-
3
- export interface LocalStorageOptions {
4
- dbName?: string;
5
- /**
6
- * @default 'localStorage'
7
- */
8
- mode?: 'indexedDB' | 'localStorage';
9
- selectors: StorageSelector[];
10
- }
11
-
12
- export type HyperStorageOptionsObj = {
13
- localStorage?: LocalStorageOptions | false;
14
- url?: {
15
- /**
16
- * @default 'hash'
17
- */
18
- mode?: 'hash' | 'search';
19
- selectors: StorageSelector[];
20
- };
21
- };
22
-
23
- export type HyperStorageOptionsFn = () => HyperStorageOptionsObj;
24
-
25
- export type HyperStorageOptions = HyperStorageOptionsObj | HyperStorageOptionsFn;