feat(core-api/Storage): Add the simple storage API for now with some simpler tests
This commit is contained in:
@@ -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>;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user