@forgerock/storage 1.2.0 → 1.3.0
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.
- package/CHANGELOG.md +20 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/coverage-final.json +3 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +131 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/coverage/src/index.html +116 -0
- package/coverage/src/index.ts.html +106 -0
- package/coverage/src/lib/index.html +116 -0
- package/coverage/src/lib/storage.effects.ts.html +472 -0
- package/dist/src/lib/storage.effects.d.ts +16 -16
- package/dist/src/lib/storage.effects.d.ts.map +1 -1
- package/dist/src/lib/storage.effects.js +57 -70
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/eslint.config.mjs +2 -2
- package/package.json +2 -2
- package/src/lib/storage.effects.test.ts +112 -52
- package/src/lib/storage.effects.ts +85 -87
- package/vite.config.ts +0 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
1
|
/*
|
|
3
2
|
* Copyright (c) 2025 Ping Identity Corporation. All rights reserved.
|
|
4
3
|
*
|
|
5
4
|
* This software may be modified and distributed under the terms
|
|
6
5
|
* of the MIT license. See the LICENSE file for details.
|
|
7
6
|
*/
|
|
8
|
-
import { describe, it, expect, vi, beforeEach
|
|
7
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
9
8
|
import { createStorage, type StorageConfig } from './storage.effects.js';
|
|
10
|
-
import type { CustomStorageObject } from '@forgerock/sdk-types';
|
|
9
|
+
import type { CustomStorageObject, GenericError } from '@forgerock/sdk-types';
|
|
11
10
|
|
|
12
11
|
const localStorageMock = (() => {
|
|
13
12
|
let store: Record<string, string> = {};
|
|
@@ -19,7 +18,7 @@ const localStorageMock = (() => {
|
|
|
19
18
|
}
|
|
20
19
|
return Promise.resolve(value);
|
|
21
20
|
}),
|
|
22
|
-
setItem: vi.fn((key: string, value:
|
|
21
|
+
setItem: vi.fn((key: string, value: unknown) => {
|
|
23
22
|
const valueIsString = typeof value === 'string';
|
|
24
23
|
store[key] = valueIsString ? value : JSON.stringify(value);
|
|
25
24
|
return Promise.resolve();
|
|
@@ -76,16 +75,47 @@ const sessionStorageMock = (() => {
|
|
|
76
75
|
|
|
77
76
|
Object.defineProperty(global, 'sessionStorage', { value: sessionStorageMock });
|
|
78
77
|
|
|
78
|
+
let customStore: Record<string, string> = {};
|
|
79
79
|
const mockCustomStore: CustomStorageObject = {
|
|
80
|
-
get: vi.fn((key: string)
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
get: vi.fn(async (key: string): Promise<string | GenericError> => {
|
|
81
|
+
const keys = Object.keys(customStore);
|
|
82
|
+
if (!keys.includes(key)) {
|
|
83
|
+
return {
|
|
84
|
+
error: 'Retrieving_error',
|
|
85
|
+
message: 'Key not found',
|
|
86
|
+
type: 'unknown_error',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return customStore[key];
|
|
90
|
+
}),
|
|
91
|
+
set: vi.fn(async (key: string, valueToSet: unknown): Promise<void | GenericError> => {
|
|
92
|
+
if (valueToSet === `"bad-value"` || typeof valueToSet !== 'string') {
|
|
93
|
+
return {
|
|
94
|
+
error: 'Storing_error',
|
|
95
|
+
message: 'Value is bad',
|
|
96
|
+
type: 'unknown_error',
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
customStore[key] = valueToSet;
|
|
100
|
+
}),
|
|
101
|
+
remove: vi.fn(async (key: string): Promise<void | GenericError> => {
|
|
102
|
+
const keys = Object.keys(customStore);
|
|
103
|
+
if (!keys.includes(key)) {
|
|
104
|
+
return {
|
|
105
|
+
error: 'Removing_error',
|
|
106
|
+
message: 'Key not found',
|
|
107
|
+
type: 'unknown_error',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
delete customStore[key];
|
|
111
|
+
}),
|
|
83
112
|
};
|
|
84
113
|
|
|
85
114
|
describe('storage Effect', () => {
|
|
86
115
|
const storageName = 'MyStorage';
|
|
87
116
|
const baseConfig: Omit<StorageConfig, 'tokenStore'> = {
|
|
88
|
-
|
|
117
|
+
type: 'localStorage',
|
|
118
|
+
name: storageName,
|
|
89
119
|
prefix: 'testPrefix',
|
|
90
120
|
};
|
|
91
121
|
const expectedKey = `${baseConfig.prefix}-${storageName}`;
|
|
@@ -96,21 +126,20 @@ describe('storage Effect', () => {
|
|
|
96
126
|
sessionStorageMock.clear();
|
|
97
127
|
vi.clearAllMocks();
|
|
98
128
|
|
|
99
|
-
|
|
100
|
-
(mockCustomStore.set as Mock).mockResolvedValue(undefined);
|
|
101
|
-
(mockCustomStore.remove as Mock).mockResolvedValue(undefined);
|
|
129
|
+
customStore = {};
|
|
102
130
|
});
|
|
103
131
|
|
|
104
132
|
describe('with localStorage', () => {
|
|
105
133
|
const config: StorageConfig = {
|
|
106
134
|
...baseConfig,
|
|
107
|
-
|
|
135
|
+
name: storageName,
|
|
136
|
+
type: 'localStorage',
|
|
108
137
|
};
|
|
109
138
|
|
|
110
|
-
const storageInstance = createStorage(config
|
|
139
|
+
const storageInstance = createStorage(config);
|
|
111
140
|
|
|
112
141
|
it('should call localStorage.getItem with the correct key and return value', async () => {
|
|
113
|
-
localStorageMock.setItem(expectedKey, JSON.stringify(testValue));
|
|
142
|
+
await localStorageMock.setItem(expectedKey, JSON.stringify(testValue));
|
|
114
143
|
const result = await storageInstance.get();
|
|
115
144
|
expect(localStorageMock.getItem).toHaveBeenCalledTimes(1);
|
|
116
145
|
expect(localStorageMock.getItem).toHaveBeenCalledWith(expectedKey);
|
|
@@ -127,7 +156,8 @@ describe('storage Effect', () => {
|
|
|
127
156
|
});
|
|
128
157
|
|
|
129
158
|
it('should call localStorage.setItem with the correct key and value', async () => {
|
|
130
|
-
await storageInstance.set(testValue);
|
|
159
|
+
const result = await storageInstance.set(testValue);
|
|
160
|
+
expect(result).toBeNull();
|
|
131
161
|
expect(localStorageMock.setItem).toHaveBeenCalledTimes(1);
|
|
132
162
|
expect(localStorageMock.setItem).toHaveBeenCalledWith(expectedKey, JSON.stringify(testValue));
|
|
133
163
|
expect(await localStorageMock.getItem(expectedKey)).toBe(JSON.stringify(testValue));
|
|
@@ -146,8 +176,9 @@ describe('storage Effect', () => {
|
|
|
146
176
|
});
|
|
147
177
|
|
|
148
178
|
it('should call localStorage.removeItem with the correct key', async () => {
|
|
149
|
-
localStorageMock.setItem(expectedKey, testValue);
|
|
150
|
-
await storageInstance.remove();
|
|
179
|
+
await localStorageMock.setItem(expectedKey, testValue);
|
|
180
|
+
const result = await storageInstance.remove();
|
|
181
|
+
expect(result).toBeNull();
|
|
151
182
|
expect(localStorageMock.removeItem).toHaveBeenCalledTimes(1);
|
|
152
183
|
expect(localStorageMock.removeItem).toHaveBeenCalledWith(expectedKey);
|
|
153
184
|
expect(await localStorageMock.getItem(expectedKey)).toBeNull();
|
|
@@ -156,28 +187,28 @@ describe('storage Effect', () => {
|
|
|
156
187
|
|
|
157
188
|
it('should parse objects/arrays when calling localStorage.getItem', async () => {
|
|
158
189
|
const testObject = { a: 1, b: 'test' };
|
|
159
|
-
storageInstance.set(testObject);
|
|
190
|
+
await storageInstance.set(testObject);
|
|
160
191
|
|
|
161
192
|
const result = await storageInstance.get();
|
|
162
|
-
console.log(result);
|
|
163
193
|
|
|
164
194
|
expect(localStorageMock.getItem).toHaveBeenCalledTimes(1);
|
|
165
195
|
expect(localStorageMock.getItem).toHaveBeenCalledWith(expectedKey);
|
|
166
|
-
|
|
167
|
-
|
|
196
|
+
expect(result).toEqual(testObject);
|
|
197
|
+
expect(mockCustomStore.remove).not.toHaveBeenCalled();
|
|
168
198
|
});
|
|
169
199
|
});
|
|
170
200
|
|
|
171
201
|
describe('with sessionStorage', () => {
|
|
202
|
+
const storageName = 'MyStorage';
|
|
172
203
|
const config: StorageConfig = {
|
|
173
204
|
...baseConfig,
|
|
174
|
-
|
|
205
|
+
name: storageName,
|
|
206
|
+
type: 'sessionStorage',
|
|
175
207
|
};
|
|
176
|
-
const
|
|
177
|
-
const storageInstance = createStorage(config, storageName);
|
|
208
|
+
const storageInstance = createStorage(config);
|
|
178
209
|
|
|
179
210
|
it('should call sessionStorage.getItem with the correct key and return value', async () => {
|
|
180
|
-
sessionStorageMock.setItem(expectedKey, JSON.stringify(testValue));
|
|
211
|
+
await sessionStorageMock.setItem(expectedKey, JSON.stringify(testValue));
|
|
181
212
|
const result = await storageInstance.get();
|
|
182
213
|
expect(sessionStorageMock.getItem).toHaveBeenCalledTimes(1);
|
|
183
214
|
expect(sessionStorageMock.getItem).toHaveBeenCalledWith(expectedKey);
|
|
@@ -196,16 +227,14 @@ describe('storage Effect', () => {
|
|
|
196
227
|
const obj = { tokens: 123 };
|
|
197
228
|
await storageInstance.set(obj);
|
|
198
229
|
const result = await storageInstance.get();
|
|
199
|
-
|
|
200
|
-
// we should not hit this expect
|
|
201
|
-
expect(false).toBe(true);
|
|
202
|
-
}
|
|
230
|
+
|
|
203
231
|
expect(result).toStrictEqual(obj);
|
|
204
232
|
expect(sessionStorageMock.getItem).toHaveBeenCalledTimes(1);
|
|
205
233
|
expect(sessionStorageMock.getItem).toHaveBeenCalledWith(expectedKey);
|
|
206
234
|
});
|
|
207
235
|
it('should call sessionStorage.setItem with the correct key and value', async () => {
|
|
208
|
-
await storageInstance.set(testValue);
|
|
236
|
+
const result = await storageInstance.set(testValue);
|
|
237
|
+
expect(result).toBeNull();
|
|
209
238
|
expect(sessionStorageMock.setItem).toHaveBeenCalledTimes(1);
|
|
210
239
|
expect(sessionStorageMock.setItem).toHaveBeenCalledWith(
|
|
211
240
|
expectedKey,
|
|
@@ -215,9 +244,10 @@ describe('storage Effect', () => {
|
|
|
215
244
|
expect(localStorageMock.setItem).not.toHaveBeenCalled();
|
|
216
245
|
expect(mockCustomStore.set).not.toHaveBeenCalled();
|
|
217
246
|
});
|
|
218
|
-
it('should call sessionStorage.setItem with the correct key and value', async () => {
|
|
247
|
+
it('should call sessionStorage.setItem with the correct key and value and stringify objects', async () => {
|
|
219
248
|
const obj = { tokens: 123 };
|
|
220
|
-
await storageInstance.set(obj);
|
|
249
|
+
const result = await storageInstance.set(obj);
|
|
250
|
+
expect(result).toBeNull();
|
|
221
251
|
expect(sessionStorageMock.setItem).toHaveBeenCalledTimes(1);
|
|
222
252
|
expect(sessionStorageMock.setItem).toHaveBeenCalledWith(expectedKey, JSON.stringify(obj));
|
|
223
253
|
expect(await sessionStorageMock.getItem(expectedKey)).toBe(JSON.stringify(obj));
|
|
@@ -225,7 +255,8 @@ describe('storage Effect', () => {
|
|
|
225
255
|
expect(mockCustomStore.set).not.toHaveBeenCalled();
|
|
226
256
|
});
|
|
227
257
|
it('should call sessionStorage.removeItem with the correct key', async () => {
|
|
228
|
-
await storageInstance.remove();
|
|
258
|
+
const result = await storageInstance.remove();
|
|
259
|
+
expect(result).toBeNull();
|
|
229
260
|
expect(sessionStorageMock.removeItem).toHaveBeenCalledTimes(1);
|
|
230
261
|
expect(sessionStorageMock.removeItem).toHaveBeenCalledWith(expectedKey);
|
|
231
262
|
expect(await sessionStorageMock.getItem(expectedKey)).toBeNull();
|
|
@@ -234,16 +265,16 @@ describe('storage Effect', () => {
|
|
|
234
265
|
});
|
|
235
266
|
});
|
|
236
267
|
|
|
237
|
-
describe('with custom
|
|
268
|
+
describe('with custom storage', () => {
|
|
238
269
|
const config: StorageConfig = {
|
|
239
270
|
...baseConfig,
|
|
240
|
-
|
|
271
|
+
type: 'custom',
|
|
272
|
+
custom: mockCustomStore,
|
|
241
273
|
};
|
|
242
|
-
const
|
|
243
|
-
const storageInstance = createStorage(config, myStorage, mockCustomStore);
|
|
274
|
+
const storageInstance = createStorage(config);
|
|
244
275
|
|
|
245
276
|
it('should call customStore.get with the correct key and return its value', async () => {
|
|
246
|
-
|
|
277
|
+
await storageInstance.set(testValue);
|
|
247
278
|
const result = await storageInstance.get();
|
|
248
279
|
expect(mockCustomStore.get).toHaveBeenCalledTimes(1);
|
|
249
280
|
expect(mockCustomStore.get).toHaveBeenCalledWith(expectedKey);
|
|
@@ -252,32 +283,37 @@ describe('storage Effect', () => {
|
|
|
252
283
|
expect(sessionStorageMock.getItem).not.toHaveBeenCalled();
|
|
253
284
|
});
|
|
254
285
|
|
|
255
|
-
it('should
|
|
256
|
-
|
|
286
|
+
it('should parse objects/arrays returned from customStore.get', async () => {
|
|
287
|
+
const testObject = { token: 'abc', user: 'xyz' };
|
|
288
|
+
await storageInstance.set(testObject);
|
|
289
|
+
|
|
257
290
|
const result = await storageInstance.get();
|
|
291
|
+
|
|
258
292
|
expect(mockCustomStore.get).toHaveBeenCalledTimes(1);
|
|
259
293
|
expect(mockCustomStore.get).toHaveBeenCalledWith(expectedKey);
|
|
294
|
+
expect(result).toEqual(testObject); // Verify it was parsed
|
|
260
295
|
});
|
|
261
296
|
|
|
262
|
-
it('should
|
|
263
|
-
const testObject = { token: 'abc', user: 'xyz' };
|
|
264
|
-
const jsonString = JSON.stringify(testObject);
|
|
265
|
-
(mockCustomStore.get as Mock).mockResolvedValueOnce(jsonString); // Mock returns JSON string
|
|
266
|
-
|
|
297
|
+
it('should return an error if customStore.get errors', async () => {
|
|
267
298
|
const result = await storageInstance.get();
|
|
268
|
-
|
|
299
|
+
expect(result).toStrictEqual({
|
|
300
|
+
error: 'Retrieving_error',
|
|
301
|
+
message: 'Key not found',
|
|
302
|
+
type: 'unknown_error',
|
|
303
|
+
});
|
|
269
304
|
expect(mockCustomStore.get).toHaveBeenCalledTimes(1);
|
|
270
305
|
expect(mockCustomStore.get).toHaveBeenCalledWith(expectedKey);
|
|
271
|
-
expect(result).toEqual(testObject); // Verify it was parsed
|
|
272
306
|
});
|
|
273
307
|
|
|
274
308
|
it('should call customStore.set with the correct key and value', async () => {
|
|
275
|
-
await storageInstance.set(testValue);
|
|
309
|
+
const result = await storageInstance.set(testValue);
|
|
310
|
+
expect(result).toBeNull();
|
|
276
311
|
expect(mockCustomStore.set).toHaveBeenCalledTimes(1);
|
|
277
312
|
expect(mockCustomStore.set).toHaveBeenCalledWith(expectedKey, JSON.stringify(testValue));
|
|
278
313
|
expect(localStorageMock.setItem).not.toHaveBeenCalled();
|
|
279
314
|
expect(sessionStorageMock.setItem).not.toHaveBeenCalled();
|
|
280
315
|
});
|
|
316
|
+
|
|
281
317
|
it('should call customStore.set with the correct key and value and stringify objects', async () => {
|
|
282
318
|
await storageInstance.set({ test: { tokens: '123' } });
|
|
283
319
|
expect(mockCustomStore.set).toHaveBeenCalledTimes(1);
|
|
@@ -288,19 +324,43 @@ describe('storage Effect', () => {
|
|
|
288
324
|
expect(localStorageMock.setItem).not.toHaveBeenCalled();
|
|
289
325
|
expect(sessionStorageMock.setItem).not.toHaveBeenCalled();
|
|
290
326
|
});
|
|
327
|
+
|
|
328
|
+
it('should return an error if customStore.set errors', async () => {
|
|
329
|
+
const result = await storageInstance.set('bad-value');
|
|
330
|
+
expect(result).toStrictEqual({
|
|
331
|
+
error: 'Storing_error',
|
|
332
|
+
message: 'Value is bad',
|
|
333
|
+
type: 'unknown_error',
|
|
334
|
+
});
|
|
335
|
+
expect(mockCustomStore.set).toHaveBeenCalledTimes(1);
|
|
336
|
+
expect(mockCustomStore.set).toHaveBeenCalledWith(expectedKey, JSON.stringify('bad-value'));
|
|
337
|
+
});
|
|
338
|
+
|
|
291
339
|
it('should call customStore.remove with the correct key', async () => {
|
|
292
|
-
await storageInstance.
|
|
340
|
+
await storageInstance.set(testValue);
|
|
341
|
+
const result = await storageInstance.remove();
|
|
342
|
+
expect(result).toBeNull();
|
|
293
343
|
expect(mockCustomStore.remove).toHaveBeenCalledTimes(1);
|
|
294
344
|
expect(mockCustomStore.remove).toHaveBeenCalledWith(expectedKey);
|
|
295
345
|
expect(localStorageMock.removeItem).not.toHaveBeenCalled();
|
|
296
346
|
expect(sessionStorageMock.removeItem).not.toHaveBeenCalled();
|
|
297
347
|
});
|
|
348
|
+
|
|
349
|
+
it('should return an error if customStore.remove errors', async () => {
|
|
350
|
+
const result = await storageInstance.remove();
|
|
351
|
+
expect(result).toStrictEqual({
|
|
352
|
+
error: 'Removing_error',
|
|
353
|
+
message: 'Key not found',
|
|
354
|
+
type: 'unknown_error',
|
|
355
|
+
});
|
|
356
|
+
expect(mockCustomStore.remove).toHaveBeenCalledTimes(1);
|
|
357
|
+
expect(mockCustomStore.remove).toHaveBeenCalledWith(expectedKey);
|
|
358
|
+
});
|
|
298
359
|
});
|
|
299
360
|
|
|
300
361
|
it('should return a function that returns the storage interface', () => {
|
|
301
|
-
const config: StorageConfig = { ...baseConfig,
|
|
302
|
-
const
|
|
303
|
-
const storageInterface = createStorage(config, myStorage);
|
|
362
|
+
const config: StorageConfig = { ...baseConfig, type: 'localStorage' };
|
|
363
|
+
const storageInterface = createStorage(config);
|
|
304
364
|
expect(storageInterface).toHaveProperty('get');
|
|
305
365
|
expect(storageInterface).toHaveProperty('set');
|
|
306
366
|
expect(storageInterface).toHaveProperty('remove');
|
|
@@ -4,128 +4,126 @@
|
|
|
4
4
|
* This software may be modified and distributed under the terms
|
|
5
5
|
* of the MIT license. See the LICENSE file for details.
|
|
6
6
|
*/
|
|
7
|
-
import { CustomStorageObject } from '@forgerock/sdk-types';
|
|
7
|
+
import { CustomStorageObject, GenericError } from '@forgerock/sdk-types';
|
|
8
8
|
|
|
9
|
-
export interface
|
|
10
|
-
|
|
9
|
+
export interface StorageClient<Value> {
|
|
10
|
+
get: () => Promise<Value | GenericError | null>;
|
|
11
|
+
set: (value: Value) => Promise<GenericError | null>;
|
|
12
|
+
remove: () => Promise<GenericError | null>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type StorageConfig = BrowserStorageConfig | CustomStorageConfig;
|
|
16
|
+
|
|
17
|
+
export interface BrowserStorageConfig {
|
|
18
|
+
type: 'localStorage' | 'sessionStorage';
|
|
11
19
|
prefix?: string;
|
|
20
|
+
name: string;
|
|
12
21
|
}
|
|
13
22
|
|
|
14
|
-
export interface
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
| 'davinci_error'
|
|
20
|
-
| 'internal_error'
|
|
21
|
-
| 'network_error'
|
|
22
|
-
| 'state_error'
|
|
23
|
-
| 'unknown_error';
|
|
23
|
+
export interface CustomStorageConfig {
|
|
24
|
+
type: 'custom';
|
|
25
|
+
prefix?: string;
|
|
26
|
+
name: string;
|
|
27
|
+
custom: CustomStorageObject;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
function createStorageError(
|
|
31
|
+
storeType: 'localStorage' | 'sessionStorage' | 'custom',
|
|
32
|
+
action: 'Storing' | 'Retrieving' | 'Removing' | 'Parsing',
|
|
33
|
+
): GenericError {
|
|
34
|
+
let storageName;
|
|
35
|
+
switch (storeType) {
|
|
36
|
+
case 'localStorage':
|
|
37
|
+
storageName = 'local';
|
|
38
|
+
break;
|
|
39
|
+
case 'sessionStorage':
|
|
40
|
+
storageName = 'session';
|
|
41
|
+
break;
|
|
42
|
+
case 'custom':
|
|
43
|
+
storageName = 'custom';
|
|
44
|
+
break;
|
|
45
|
+
default:
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
error: `${action}_error`,
|
|
51
|
+
message: `Error ${action.toLowerCase()} value from ${storageName} storage`,
|
|
52
|
+
type: action === 'Parsing' ? 'parse_error' : 'unknown_error',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function createStorage<Value>(config: StorageConfig): StorageClient<Value> {
|
|
57
|
+
const { type: storeType, prefix = 'pic', name } = config;
|
|
58
|
+
const key = `${prefix}-${name}`;
|
|
59
|
+
const storageTypes = {
|
|
60
|
+
sessionStorage,
|
|
61
|
+
localStorage,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
if (storeType === 'custom' && !('custom' in config)) {
|
|
65
|
+
throw new Error('Custom storage configuration must include a custom storage object');
|
|
66
|
+
}
|
|
32
67
|
|
|
33
|
-
const key = `${prefix}-${storageName}`;
|
|
34
68
|
return {
|
|
35
69
|
get: async function storageGet(): Promise<Value | GenericError | null> {
|
|
36
|
-
if (
|
|
37
|
-
const value = await
|
|
38
|
-
if (value === null) {
|
|
70
|
+
if (storeType === 'custom') {
|
|
71
|
+
const value = await config.custom.get(key);
|
|
72
|
+
if (value === null || (typeof value === 'object' && 'error' in value)) {
|
|
39
73
|
return value;
|
|
40
74
|
}
|
|
75
|
+
|
|
41
76
|
try {
|
|
42
77
|
const parsed = JSON.parse(value);
|
|
43
78
|
return parsed as Value;
|
|
44
79
|
} catch {
|
|
45
|
-
return
|
|
46
|
-
code: 'Parse_Error',
|
|
47
|
-
message: 'Eror parsing value from provided storage',
|
|
48
|
-
type: 'unknown_error',
|
|
49
|
-
};
|
|
80
|
+
return createStorageError(storeType, 'Parsing');
|
|
50
81
|
}
|
|
51
82
|
}
|
|
52
|
-
|
|
53
|
-
|
|
83
|
+
|
|
84
|
+
let value: string | null;
|
|
85
|
+
try {
|
|
86
|
+
value = await storageTypes[storeType].getItem(key);
|
|
54
87
|
if (value === null) {
|
|
55
88
|
return value;
|
|
56
89
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return parsed as Value;
|
|
60
|
-
} catch {
|
|
61
|
-
return {
|
|
62
|
-
code: 'Parse_Error',
|
|
63
|
-
message: 'Eror parsing value from session storage',
|
|
64
|
-
type: 'unknown_error',
|
|
65
|
-
};
|
|
66
|
-
}
|
|
90
|
+
} catch {
|
|
91
|
+
return createStorageError(storeType, 'Retrieving');
|
|
67
92
|
}
|
|
68
|
-
const value = await localStorage.getItem(key);
|
|
69
93
|
|
|
70
|
-
if (value === null) {
|
|
71
|
-
return value;
|
|
72
|
-
}
|
|
73
94
|
try {
|
|
74
95
|
const parsed = JSON.parse(value);
|
|
75
96
|
return parsed as Value;
|
|
76
97
|
} catch {
|
|
77
|
-
return
|
|
78
|
-
code: 'Parse_Error',
|
|
79
|
-
message: 'Eror parsing value from local storage',
|
|
80
|
-
type: 'unknown_error',
|
|
81
|
-
};
|
|
98
|
+
return createStorageError(storeType, 'Parsing');
|
|
82
99
|
}
|
|
83
100
|
},
|
|
84
|
-
set: async function storageSet(value: Value) {
|
|
101
|
+
set: async function storageSet(value: Value): Promise<GenericError | null> {
|
|
85
102
|
const valueToStore = JSON.stringify(value);
|
|
86
|
-
if (
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return Promise.resolve();
|
|
90
|
-
} catch {
|
|
91
|
-
return {
|
|
92
|
-
code: 'Storing_Error',
|
|
93
|
-
message: 'Eror storing value in custom storage',
|
|
94
|
-
type: 'unknown_error',
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
if (storeType === 'sessionStorage') {
|
|
99
|
-
try {
|
|
100
|
-
await sessionStorage.setItem(key, valueToStore);
|
|
101
|
-
return Promise.resolve();
|
|
102
|
-
} catch {
|
|
103
|
-
return {
|
|
104
|
-
code: 'Storing_Error',
|
|
105
|
-
message: 'Eror storing value in session storage',
|
|
106
|
-
type: 'unknown_error',
|
|
107
|
-
};
|
|
108
|
-
}
|
|
103
|
+
if (storeType === 'custom') {
|
|
104
|
+
const value = await config.custom.set(key, valueToStore);
|
|
105
|
+
return Promise.resolve(value ?? null);
|
|
109
106
|
}
|
|
107
|
+
|
|
110
108
|
try {
|
|
111
|
-
await
|
|
112
|
-
return Promise.resolve();
|
|
109
|
+
await storageTypes[storeType].setItem(key, valueToStore);
|
|
110
|
+
return Promise.resolve(null);
|
|
113
111
|
} catch {
|
|
114
|
-
return
|
|
115
|
-
code: 'Storing_Error',
|
|
116
|
-
message: 'Eror storing value in local storage',
|
|
117
|
-
type: 'unknown_error',
|
|
118
|
-
};
|
|
112
|
+
return createStorageError(storeType, 'Storing');
|
|
119
113
|
}
|
|
120
114
|
},
|
|
121
|
-
remove: async function
|
|
122
|
-
if (
|
|
123
|
-
|
|
115
|
+
remove: async function storageRemove(): Promise<GenericError | null> {
|
|
116
|
+
if (storeType === 'custom') {
|
|
117
|
+
const value = await config.custom.remove(key);
|
|
118
|
+
return Promise.resolve(value ?? null);
|
|
124
119
|
}
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
await storageTypes[storeType].removeItem(key);
|
|
123
|
+
return Promise.resolve(null);
|
|
124
|
+
} catch {
|
|
125
|
+
return createStorageError(storeType, 'Removing');
|
|
127
126
|
}
|
|
128
|
-
return await localStorage.removeItem(key);
|
|
129
127
|
},
|
|
130
|
-
}
|
|
128
|
+
} as StorageClient<Value>;
|
|
131
129
|
}
|
package/vite.config.ts
CHANGED
|
Binary file
|