import set from 'lodash/set'; import unset from 'lodash/unset'; import get from 'lodash/get'; import { Store } from './types'; type Subscription = { key: string; callback: (value: any) => void; }; /** * Store using memory * * @example * * import { memoryStore } from 'mv-tmp'; * * const App = () => ( * * ... * * ); */ export const memoryStore = (storage: any = {}): Store => { const subscriptions: { [key: string]: Subscription } = {}; const publish = (key: string, value: any) => { Object.keys(subscriptions).forEach(id => { if (!subscriptions[id]) return; // may happen if a component unmounts after a first subscriber was notified if (subscriptions[id].key === key) { subscriptions[id].callback(value); } }); }; return { setup: () => {}, teardown: () => { Object.keys(storage).forEach(key => delete storage[key]); }, getItem(key: string, defaultValue?: T): T { return get(storage, key, defaultValue); }, setItem(key: string, value: T): void { set(storage, key, value); publish(key, value); }, removeItem(key: string): void { unset(storage, key); publish(key, undefined); }, removeItems(keyPrefix: string): void { const flatStorage = flatten(storage); Object.keys(flatStorage).forEach(key => { if (!key.startsWith(keyPrefix)) { return; } unset(storage, key); publish(key, undefined); }); }, reset(): void { const flatStorage = flatten(storage); Object.keys(flatStorage).forEach(key => { unset(storage, key); publish(key, undefined); }); }, subscribe: (key: string, callback: (value: string) => void) => { const id = Math.random().toString(); subscriptions[id] = { key, callback, }; return () => { delete subscriptions[id]; }; }, }; }; // taken from https://stackoverflow.com/a/19101235/1333479 const flatten = (data: any) => { var result = {}; function doFlatten(current, prop) { if (Object(current) !== current) { // scalar value result[prop] = current; } else if (Array.isArray(current)) { // array result[prop] = current; } else { // object var isEmpty = true; for (var p in current) { isEmpty = false; doFlatten(current[p], prop ? prop + '.' + p : p); } if (isEmpty && prop) result[prop] = {}; } } doFlatten(data, ''); return result; };