import { useSyncExternalStore } from 'react'; import type { BaseStorage } from '@extension/storage'; type WrappedPromise = ReturnType; // eslint-disable-next-line @typescript-eslint/no-explicit-any const storageMap: Map, WrappedPromise> = new Map(); export function useStorage< Storage extends BaseStorage, Data = Storage extends BaseStorage ? Data : unknown, >(storage: Storage) { const _data = useSyncExternalStore(storage.subscribe, storage.getSnapshot); if (!storageMap.has(storage)) { storageMap.set(storage, wrapPromise(storage.get())); } if (_data !== null) { storageMap.set(storage, { read: () => _data }); } return (_data ?? storageMap.get(storage)!.read()) as Exclude>; } function wrapPromise(promise: Promise) { let status = 'pending'; let result: R; const suspender = promise.then( r => { status = 'success'; result = r; }, e => { status = 'error'; result = e; }, ); return { read() { switch (status) { case 'pending': throw suspender; case 'error': throw result; default: return result; } }, }; }