diff --git a/packages/core-api/src/apis/definitions/StorageApi.ts b/packages/core-api/src/apis/definitions/StorageApi.ts index e0bd2c7ed3..90c1961588 100644 --- a/packages/core-api/src/apis/definitions/StorageApi.ts +++ b/packages/core-api/src/apis/definitions/StorageApi.ts @@ -22,7 +22,14 @@ export type ObservableMessage = { 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$(key: string): Observable; -}; +} export const storageApiRef = createApiRef({ id: 'core.storage', diff --git a/packages/core-api/src/apis/implementations/StorageApi/WebStorage.test.ts b/packages/core-api/src/apis/implementations/StorageApi/WebStorage.test.ts index 85343d58ff..f28cb9e41b 100644 --- a/packages/core-api/src/apis/implementations/StorageApi/WebStorage.test.ts +++ b/packages/core-api/src/apis/implementations/StorageApi/WebStorage.test.ts @@ -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'); + }); }); diff --git a/packages/core-api/src/apis/implementations/StorageApi/WebStorage.ts b/packages/core-api/src/apis/implementations/StorageApi/WebStorage.ts index a6a646d3dc..a7150b3647 100644 --- a/packages/core-api/src/apis/implementations/StorageApi/WebStorage.ts +++ b/packages/core-api/src/apis/implementations/StorageApi/WebStorage.ts @@ -18,13 +18,11 @@ import { Observable } from '../../../types'; import ObservableImpl from 'zen-observable'; export class WebStorage implements StorageApi { - subscribers: Set< - ZenObservable.SubscriptionObserver - > = new Set(); + constructor(private readonly namespace: string = '') {} get(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(key: string, data: T): Promise { - 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 { - localStorage.removeItem(key); + localStorage.removeItem(this.getKeyName(key)); this.notifyChanges({ key, newValue: undefined }); } @@ -52,12 +54,20 @@ export class WebStorage implements StorageApi { ) as Observable; } + 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 + > = new Set(); + private readonly observable = new ObservableImpl( subscriber => { this.subscribers.add(subscriber);