feat(core-api/Storage): Be able to namespace with forBucket function

This commit is contained in:
blam
2020-06-03 17:21:15 +02:00
parent f1ba79fec0
commit fb32b09226
3 changed files with 40 additions and 8 deletions
@@ -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);