feat(core-api/Storage): Be able to namespace with forBucket function
This commit is contained in:
@@ -22,7 +22,14 @@ export type ObservableMessage<T extends object = {}> = {
|
||||
newValue?: T;
|
||||
};
|
||||
|
||||
export type StorageApi = {
|
||||
export interface StorageApi {
|
||||
/**
|
||||
* The names
|
||||
* @param {String} name Namespace for the storage to be stored under,
|
||||
* will inherit previous namespaces too
|
||||
*/
|
||||
forBucket(name: string): StorageApi;
|
||||
|
||||
/**
|
||||
* Get persistent data.
|
||||
*
|
||||
@@ -50,7 +57,7 @@ export type StorageApi = {
|
||||
* @param {String} key Unique key associated with the data
|
||||
*/
|
||||
observe$<T>(key: string): Observable<T>;
|
||||
};
|
||||
}
|
||||
|
||||
export const storageApiRef = createApiRef<StorageApi>({
|
||||
id: 'core.storage',
|
||||
|
||||
@@ -102,4 +102,19 @@ describe('WebStorage Storage API', () => {
|
||||
newValue: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to create different buckets for different uses', async () => {
|
||||
const rootStorage = new WebStorage();
|
||||
|
||||
const firstStorage = rootStorage.forBucket('userSettings');
|
||||
const secondStorage = rootStorage.forBucket('profileSettings');
|
||||
const keyName = 'blobby';
|
||||
|
||||
await firstStorage.set(keyName, 'boop');
|
||||
await secondStorage.set(keyName, 'deerp');
|
||||
|
||||
expect(firstStorage.get(keyName)).not.toBe(secondStorage.get(keyName));
|
||||
expect(firstStorage.get(keyName)).toBe('boop');
|
||||
expect(secondStorage.get(keyName)).toBe('deerp');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -18,13 +18,11 @@ import { Observable } from '../../../types';
|
||||
import ObservableImpl from 'zen-observable';
|
||||
|
||||
export class WebStorage implements StorageApi {
|
||||
subscribers: Set<
|
||||
ZenObservable.SubscriptionObserver<ObservableMessage>
|
||||
> = new Set();
|
||||
constructor(private readonly namespace: string = '') {}
|
||||
|
||||
get<T>(key: string): T | undefined {
|
||||
try {
|
||||
const storage = JSON.parse(localStorage.getItem(key)!);
|
||||
const storage = JSON.parse(localStorage.getItem(this.getKeyName(key))!);
|
||||
return storage ?? undefined;
|
||||
} catch (e) {
|
||||
window.console.error(
|
||||
@@ -36,13 +34,17 @@ export class WebStorage implements StorageApi {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
forBucket(name: string): WebStorage {
|
||||
return new WebStorage(`${this.namespace}/${name}`);
|
||||
}
|
||||
|
||||
async set<T>(key: string, data: T): Promise<void> {
|
||||
localStorage.setItem(key, JSON.stringify(data, null, 2));
|
||||
localStorage.setItem(this.getKeyName(key), JSON.stringify(data, null, 2));
|
||||
this.notifyChanges({ key, newValue: data });
|
||||
}
|
||||
|
||||
async remove(key: string): Promise<void> {
|
||||
localStorage.removeItem(key);
|
||||
localStorage.removeItem(this.getKeyName(key));
|
||||
this.notifyChanges({ key, newValue: undefined });
|
||||
}
|
||||
|
||||
@@ -52,12 +54,20 @@ export class WebStorage implements StorageApi {
|
||||
) as Observable<T>;
|
||||
}
|
||||
|
||||
private getKeyName(key: string) {
|
||||
return `${this.namespace}/${key}`;
|
||||
}
|
||||
|
||||
private notifyChanges(message: ObservableMessage) {
|
||||
for (const subscription of this.subscribers) {
|
||||
subscription.next(message);
|
||||
}
|
||||
}
|
||||
|
||||
private subscribers: Set<
|
||||
ZenObservable.SubscriptionObserver<ObservableMessage>
|
||||
> = new Set();
|
||||
|
||||
private readonly observable = new ObservableImpl<ObservableMessage>(
|
||||
subscriber => {
|
||||
this.subscribers.add(subscriber);
|
||||
|
||||
Reference in New Issue
Block a user