overmind
Version:
Frictionless state management
135 lines (133 loc) • 5.35 kB
JavaScript
import { StateMachine, deepCopy } from "./statemachine.js";
import { IS_PROXY, VALUE } from "proxy-state-tree";
import isPlainObject from "is-plain-obj";
//#region src/utils.ts
const createOnInitialize = () => {
return ({ actions }, instance) => {
const initializers = getActionsByName("onInitializeOvermind", actions);
return Promise.all(initializers.map((initialize) => initialize(instance)));
};
};
const ENVIRONMENT = (() => {
let env;
try {
env = process.env.NODE_ENV;
} catch {
console.warn("Overmind was unable to determine the NODE_ENV, which means it will run in DEVELOPMENT mode. If this is a production app, please configure your build tool to define NODE_ENV");
env = "development";
}
return env;
})();
const IS_TEST = ENVIRONMENT === "test";
const IS_OPERATOR = Symbol("operator");
const ORIGINAL_ACTIONS = Symbol("origina_actions");
const EXECUTION = Symbol("execution");
const MODE_DEFAULT = Symbol("MODE_DEFAULT");
const MODE_TEST = Symbol("MODE_TEST");
const MODE_SSR = Symbol("MODE_SSR");
var MockedEventEmitter = class {
emit() {}
emitAsync() {}
on() {}
once() {}
addListener() {}
};
const json = (obj) => {
return deepCopy(obj && obj[IS_PROXY] ? obj[VALUE] : obj);
};
function isPromise(maybePromise) {
return maybePromise instanceof Promise || maybePromise && typeof maybePromise.then === "function" && typeof maybePromise.catch === "function";
}
function processState(state) {
return Object.keys(state).reduce((aggr, key) => {
if (key === "__esModule") return aggr;
const originalDescriptor = Object.getOwnPropertyDescriptor(state, key);
if (originalDescriptor && "get" in originalDescriptor) {
Object.defineProperty(aggr, key, originalDescriptor);
return aggr;
}
const value = state[key];
if (isPlainObject(value)) aggr[key] = processState(value);
else Object.defineProperty(aggr, key, originalDescriptor);
return aggr;
}, isPlainObject(state) ? {} : state);
}
function getFunctionName(func) {
return func.name || func.displayName || "";
}
const getChangeMutationsDelimiter = ".";
function getChangeMutations(stateA, stateB, path = [], mutations = []) {
const stateAKeys = Object.keys(stateA);
const stateBKeys = Object.keys(stateB);
stateAKeys.forEach((key) => {
if (!stateBKeys.includes(key)) mutations.push({
delimiter: getChangeMutationsDelimiter,
args: [],
path: path.concat(key).join("."),
hasChangedValue: false,
method: "unset"
});
});
stateBKeys.forEach((key) => {
if (isPlainObject(stateA[key]) && isPlainObject(stateB[key])) getChangeMutations(stateA[key], stateB[key], path.concat(key), mutations);
else if (stateA[key] !== stateB[key]) mutations.push({
delimiter: getChangeMutationsDelimiter,
args: [stateB[key]],
path: path.concat(key).join("."),
hasChangedValue: false,
method: "set"
});
});
return mutations;
}
function getActionsByName(name, actions = {}, currentPath = []) {
return Object.keys(actions).reduce((aggr, key) => {
if (typeof actions[key] === "function" && key === name) return aggr.concat(actions[key]);
return aggr.concat(getActionsByName(name, actions[key], currentPath.concat(key)));
}, []);
}
function getActionPaths(actions = {}, currentPath = []) {
return Object.keys(actions).reduce((aggr, key) => {
if (typeof actions[key] === "function") return aggr.concat(currentPath.concat(key).join("."));
return aggr.concat(getActionPaths(actions[key], currentPath.concat(key)));
}, []);
}
function createActionsProxy(actions, cb) {
return new Proxy(actions, { get(target, prop) {
if (prop === ORIGINAL_ACTIONS) return actions;
if (typeof target[prop] === "function") return cb(target[prop]);
if (!target[prop]) return;
return createActionsProxy(target[prop], cb);
} });
}
function detectStateCharts(state) {
return traverseStateTree(state, hasStateChartStructure);
}
function traverseStateTree(state, checkFn, visited = /* @__PURE__ */ new Set()) {
if (!state || typeof state !== "object") return false;
if (visited.has(state)) return false;
visited.add(state);
if (checkFn(state)) return true;
if (state[IS_PROXY] && !Object.keys(state).some((key) => typeof state[key] === "object")) return false;
if (Array.isArray(state)) {
for (let i = 0; i < state.length; i++) {
const item = state[i];
if (item && typeof item === "object" && traverseStateTree(item, checkFn, visited)) return true;
}
return false;
}
for (const key in state) if (state.hasOwnProperty(key) && key !== "__proto__" && key !== "constructor") {
const value = state[key];
if (value && typeof value === "object" && traverseStateTree(value, checkFn, visited)) return true;
}
return false;
}
function hasStateChartStructure(state) {
return !!(state && typeof state === "object" && state.states && Array.isArray(state.states) && state.states.length > 0 && Array.isArray(state.states[0]) && typeof state.matches === "function" && state.actions && typeof state.actions === "object");
}
const isStateMachine = (obj) => {
return obj instanceof StateMachine;
};
//#endregion
export { ENVIRONMENT, EXECUTION, IS_OPERATOR, IS_TEST, MODE_DEFAULT, MODE_SSR, MODE_TEST, MockedEventEmitter, ORIGINAL_ACTIONS, createActionsProxy, createOnInitialize, detectStateCharts, getActionPaths, getChangeMutations, getFunctionName, isPromise, isStateMachine, json, processState };
//# sourceMappingURL=utils.js.map