UNPKG

overmind

Version:
105 lines (103 loc) 3.57 kB
import { isStateMachine } from "./utils.js"; import { PATH, PROXY_TREE, VALUE } from "proxy-state-tree"; import isPlainObject from "is-plain-obj"; //#region src/statemachine.ts 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"); function deepCopy(obj) { if (isStateMachine(obj)) 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; } var StateMachine = 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[TRANSITION_LISTENERS] = []; this[IS_DISPOSED] = false; this[STATE] = state; this[BASE_STATE] = baseState; this[INITIAL_STATE] = state.current; 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].root.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].previousState = this[VALUE].current; this[VALUE][CURRENT_KEYS].forEach((key) => { if (key !== "current") delete this[key]; }); this[VALUE][CURRENT_KEYS] = Object.keys(result); Object.assign(this, result); const devtools = tree.root.options.getDevtools?.(); if (devtools && typeof devtools.send === "function") devtools.send({ type: "machine:transition", data: { path: this[PATH], fromState: this[VALUE].previousState, toState: this[VALUE].current, eventType: type, payload: data, timestamp: Date.now() } }); 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); } }; function statemachine(transitions) { return { create(state, baseState) { return new StateMachine(transitions, state, baseState); } }; } //#endregion export { StateMachine, deepCopy, statemachine }; //# sourceMappingURL=statemachine.js.map