overmind
Version:
Frictionless state management
110 lines • 3.89 kB
JavaScript
var _a, _b;
import isPlainObject from 'is-plain-obj';
import { PATH, PROXY_TREE, VALUE } from 'proxy-state-tree';
const INITIAL_STATE = Symbol('INITIAL_STATE');
const TRANSITIONS = Symbol('TRANSITIONS');
const STATE = Symbol('STATE');
const IS_DISPOSED = Symbol('IS_DISPOSED');
const CURRENT_KEYS = Symbol('CURRENT_KEYS');
const BASE_STATE = Symbol('BASE_STATE');
const TRANSITION_LISTENERS = Symbol('TRANSITION_LISTENERS');
// We have to export here to avoid a circular dependency issue with "utils"
export function deepCopy(obj) {
if (obj instanceof StateMachine) {
return obj.clone();
}
else if (isPlainObject(obj)) {
return Object.keys(obj).reduce((aggr, key) => {
if (key === '__esModule') {
return aggr;
}
const originalDescriptor = Object.getOwnPropertyDescriptor(obj, key);
const isAGetter = originalDescriptor && 'get' in originalDescriptor;
const value = obj[key];
if (isAGetter) {
Object.defineProperty(aggr, key, originalDescriptor);
}
else {
aggr[key] = deepCopy(value);
}
return aggr;
}, {});
}
else if (Array.isArray(obj)) {
return obj.map((item) => deepCopy(item));
}
return obj;
}
export class StateMachine {
clone() {
return new StateMachine(this[TRANSITIONS], deepCopy(this[STATE]), deepCopy(this[BASE_STATE]));
}
dispose() {
this[VALUE][TRANSITION_LISTENERS] = [];
Object.keys(this[VALUE]).forEach((key) => {
if (this[VALUE][key] instanceof StateMachine) {
this[key].dispose();
}
});
this[VALUE][IS_DISPOSED] = true;
}
constructor(transitions, state, baseState) {
this[_a] = [];
this[_b] = false;
this[STATE] = state;
this[BASE_STATE] = baseState;
this[INITIAL_STATE] = state.current;
this[BASE_STATE] = baseState;
this[TRANSITIONS] = transitions;
this[CURRENT_KEYS] = Object.keys(state);
Object.assign(this, state, baseState);
}
send(type, data) {
if (this[VALUE][IS_DISPOSED]) {
if (process.env.NODE_ENV === 'development') {
console.warn(`Overmind - The statemachine at "${this[PATH]}" has been disposed, but you tried to transition on it`);
}
return this;
}
const tree = this[PROXY_TREE].master.mutationTree || this[PROXY_TREE];
tree.enableMutations();
let result;
if (typeof this[VALUE][TRANSITIONS] === 'function') {
const transition = this[VALUE][TRANSITIONS];
result = transition({ type, data }, this);
}
else if (this[VALUE][TRANSITIONS][this[VALUE].current][type]) {
const transition = this[VALUE][TRANSITIONS][this[VALUE].current][type];
result = transition(data, this);
}
if (result) {
this[VALUE][CURRENT_KEYS].forEach((key) => {
if (key !== 'current') {
delete this[key];
}
});
this[VALUE][CURRENT_KEYS] = Object.keys(result);
Object.assign(this, result);
this[VALUE][TRANSITION_LISTENERS].forEach((listener) => listener(this));
}
tree.blockMutations();
return this;
}
matches(state) {
if (this.current === state) {
return this;
}
}
onTransition(listener) {
this[VALUE][TRANSITION_LISTENERS].push(listener);
}
}
_a = TRANSITION_LISTENERS, _b = IS_DISPOSED;
export function statemachine(transitions) {
return {
create(state, baseState) {
return new StateMachine(transitions, state, baseState);
},
};
}
//# sourceMappingURL=statemachine.js.map