Skip to content

Commit 5933d69

Browse files
committed
feat(web): use local storage when not in extension context
1 parent e00ec19 commit 5933d69

File tree

1 file changed

+33
-16
lines changed

1 file changed

+33
-16
lines changed

src/utils/browser/browser-storage.utils.ts

+33-16
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { RecursiveRecord } from '~/utils/typescript.utils';
2+
13
/**
24
* @see [chrome.storage.sync](https://developer.chrome.com/docs/extensions/reference/storage/#type-SyncStorageArea)
35
*/
@@ -21,23 +23,38 @@ const filterObject = (object: Record<string, unknown>, regex: string) =>
2123
* @param area The storage area to wrap.
2224
* @param name The name of the storage area.
2325
*/
24-
export const storageWrapper = (area: chrome.storage.StorageArea, name = crypto.randomUUID()) => {
26+
export const storageWrapper = (area: chrome.storage.StorageArea, name: string) => {
2527
if (!chrome?.storage) {
26-
console.warn('Storage API is not available, using in-memory storage instead.');
27-
const storage: Record<string, unknown> = {};
28-
window.trakt = { ...window.trakt, [name]: storage };
29-
return {
30-
getAll: async <T>(regex?: string): Promise<T> => (regex ? filterObject(storage, regex) : storage) as T,
31-
get: async <T>(key: string): Promise<T> => storage[key] as T,
32-
set: async <T>(key: string, value: T): Promise<void> => {
33-
storage[key] = value;
28+
console.warn('Storage API is not available, using local storage instead.');
29+
30+
const storage = {
31+
id: `trakt-${name}-storage`,
32+
get values(): RecursiveRecord {
33+
const _value = window.localStorage.getItem(this.id);
34+
if (!_value) return {};
35+
return JSON.parse(_value);
36+
},
37+
set values(value: unknown) {
38+
window.localStorage.setItem(this.id, JSON.stringify(value));
3439
},
35-
remove: async (key: string): Promise<void> => {
36-
delete storage[key];
40+
setItem(key: string, value: unknown) {
41+
this.values = { ...this.values, [key]: value };
3742
},
38-
clear: async (): Promise<void> => {
39-
Object.keys(storage).forEach(key => delete storage[key]);
43+
removeItem(key: string) {
44+
this.values = { ...this.values, [key]: undefined };
4045
},
46+
clear() {
47+
this.values = {};
48+
},
49+
};
50+
51+
window.trakt = { ...window.trakt, [name]: storage };
52+
return {
53+
getAll: async <T>(regex?: string): Promise<T> => (regex ? filterObject(storage.values, regex) : storage.values) as T,
54+
get: async <T>(key: string): Promise<T> => storage.values[key] as T,
55+
set: async <T>(key: string, value: T): Promise<void> => storage.setItem(key, value),
56+
remove: async (key: string): Promise<void> => storage.removeItem(key),
57+
clear: async (): Promise<void> => storage.clear(),
4158
};
4259
}
4360
return {
@@ -55,7 +72,7 @@ export type StorageArea = ReturnType<typeof storageWrapper>;
5572
* This object is used to access the storage areas.
5673
*/
5774
export const storage = {
58-
sync: storageWrapper(syncStorage),
59-
local: storageWrapper(localStorage),
60-
session: storageWrapper(sessionStorage),
75+
sync: storageWrapper(syncStorage, 'sync'),
76+
local: storageWrapper(localStorage, 'local'),
77+
session: storageWrapper(sessionStorage, 'session'),
6178
};

0 commit comments

Comments
 (0)