feat(core-api/Storage): Add the simple storage API for now with some simpler tests

This commit is contained in:
blam
2020-06-02 23:12:32 +02:00
parent 4fd99fec25
commit 99a2387076
3 changed files with 74 additions and 24 deletions
@@ -17,6 +17,11 @@
import { createApiRef } from '../ApiRef';
import { Observable } from '@backstage/core-api';
export type ObservableMessage<T extends object = {}> = {
key: string;
newValue?: T;
};
export type StorageApi = {
/**
* Get persistent data.
@@ -37,9 +42,8 @@ export type StorageApi = {
* Save persistant data.
*
* @param {String} key Unique key associated with the data.
* @return
*/
save(key: string, data: any): Promise<void>;
set(key: string, data: any): Promise<void>;
/**
*
@@ -0,0 +1,48 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { WebStorage } from './WebStorage';
describe('WebStorage Storage API', () => {
it('should return undefined for values which are unset', async () => {
const storage = new WebStorage();
expect(storage.get('myfakekey')).toBeUndefined();
});
it('should allow the setting and getting of the simple data structures', async () => {
const storage = new WebStorage();
await storage.set('myfakekey', 'helloimastring');
await storage.set('mysecondfakekey', 1234);
await storage.set('mythirdfakekey', true);
expect(storage.get('myfakekey')).toBe('helloimastring');
expect(storage.get('mysecondfakekey')).toBe(1234);
expect(storage.get('mythirdfakekey')).toBe(true);
});
it('should allow setting of complex datastructures', async () => {
const storage = new WebStorage();
const mockData = {
something: 'here',
is: [{ super: { complex: [{ but: 'something', why: true }] } }],
};
await storage.set('myfakekey', mockData);
expect(storage.get('myfakekey')).toEqual(mockData);
});
});
@@ -13,39 +13,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { StorageApi } from '../../definitions';
import { StorageApi, ObservableMessage } from '../../definitions';
import { Observable } from '../../../types';
import ObservableImpl from 'zen-observable';
export class WebStorage implements StorageApi {
async getFromStore<T>(
storeName: string,
key: string = '',
defaultValue?: T,
): Promise<T | undefined> {
let store;
private readonly observable = new ObservableImpl<ObservableMessage>(() => {});
get<T>(key: string): T | undefined {
try {
store = JSON.parse(localStorage.getItem(storeName)!) || {};
const storage = JSON.parse(localStorage.getItem(key)!);
return storage ?? undefined;
} catch (e) {
window.console.error(
`Error when parsing JSON config from storage for: ${storeName}`,
`Error when parsing JSON config from storage for: ${key}`,
e,
);
return defaultValue;
}
if (key) {
return store[key] ?? defaultValue;
}
return store;
return undefined;
}
async saveToStore(storeName: string, key: string, data: any): Promise<void> {
const store = JSON.parse(localStorage.getItem(storeName)!) || {};
store[key] = data;
localStorage.setItem(storeName, JSON.stringify(store));
async set<T>(key: string, data: T): Promise<void> {
localStorage.setItem(key, JSON.stringify(data, null, 2));
}
async removeFromStore(storeName: string, key: string): Promise<void> {
const store = JSON.parse(localStorage.getItem(storeName)!) || {};
delete store[key];
localStorage.setItem(storeName, JSON.stringify(store));
async remove(key: string): Promise<void> {
localStorage.removeItem(key);
}
observe$<T>(key: string): Observable<T> {
return this.observable.filter(
({ key: messageKey }) => messageKey === key,
) as Observable<T>;
}
}