pgadmin4/web/pgadmin/static/js/SchemaView/SchemaState/store.js

81 lines
1.9 KiB
JavaScript

import _ from 'lodash';
import { isValueEqual } from '../common';
import { flatPathGenerator } from './common';
export const createStore = (initialState) => {
let state = initialState;
const listeners = new Set();
const gen = flatPathGenerator('/');
const pathListeners = new Set();
// Exposed functions
// Don't attempt to manipulate the state directly.
const getState = () => state;
const setState = (nextState) => {
const prevState = state;
state = _.clone(nextState);
if (isValueEqual(state, prevState)) return;
listeners.forEach((listener) => {
listener();
});
const changeMemo = new Map();
pathListeners.forEach((pathListener) => {
const [ path, listener ] = pathListener;
const flatPath = gen.flatPath(path);
if (!changeMemo.has(flatPath)) {
const pathNextValue =
flatPath == '' ? nextState : _.get(nextState, path, undefined);
const pathPrevValue =
flatPath == '' ? prevState : _.get(prevState, path, undefined);
changeMemo.set(flatPath, [
isValueEqual(pathNextValue, pathPrevValue),
pathNextValue,
pathPrevValue,
]);
}
const [isSame, pathNextValue, pathPrevValue] = changeMemo.get(flatPath);
if (!isSame) {
listener(pathNextValue, pathPrevValue);
}
});
};
const get = (path = []) => (_.get(state, path));
const set = (arg) => {
let nextState = _.isFunction(arg) ? arg(_.cloneDeep(state)) : arg;
setState(nextState);
};
const subscribe = (listener) => {
listeners.add(listener);
return () => listeners.delete(listener);
};
const subscribeForPath = (path, listner) => {
const data = [path, listner];
pathListeners.add(data);
return () => {
return pathListeners.delete(data);
};
};
return {
getState,
setState,
get,
set,
subscribe,
subscribeForPath,
};
};