import { getParent, getType, isRoot, types } from "mobx-state-tree"; import Registry from "./Registry"; import { ConfigurationError } from "../utils/errors"; function _mixedArray(fn) { return (arr) => types.maybeNull(types.array(fn(arr))); } function _oneOf(lookup, err) { return (arr) => types.union({ dispatcher: (sn) => { if (arr.find((val) => sn.type === val)) { return lookup(sn.type); } throw new ConfigurationError(err + sn.type); }, }); } const oneOfTags = _oneOf(Registry.getModelByTag, "Not expecting tag: "); const tagsArray = _mixedArray(oneOfTags); function unionArray(arr) { const type = types.maybeNull(types.array(oneOfTags(arr))); type.value = arr; return type; } function unionTag(arr) { return types.maybeNull(types.enumeration("unionTag", arr)); } function tagsTypes(arr) { const type = types.frozen(arr.map((val) => val.toLowerCase())); type.describe = () => `(${arr.join("|")})`; type.value = arr; return type; } function allModelsTypes() { const args = [ { dispatcher: (sn) => { if (!sn) return types.literal(undefined); if (Registry.tags.includes(sn.type)) { return Registry.getModelByTag(sn.type); } throw new ConfigurationError(`Not expecting tag: ${sn.type}`); }, }, Registry.modelsArr(), ]; const results = [].concat.apply([], args); return types.union.apply(null, results); } function isType(node, types) { const nt = getType(node); for (const t of types) if (nt === t) return true; return false; } function getParentOfTypeString(node, str) { if (isRoot(node)) return null; // same as getParentOfType but checks models .name instead of type let parent = getParent(node); if (!Array.isArray(str)) str = [str]; while (parent) { const name = getType(parent).name; if (str.find((c) => c === name)) return parent; parent = isRoot(parent) ? null : getParent(parent); } return null; } function getParentTagOfTypeString(node, str) { // same as getParentOfType but checks models .name instead of type let parent = getParent(node); if (!Array.isArray(str)) str = [str]; while (parent) { const parentType = parent.type; if (str.find((c) => c === parentType)) return parent; parent = isRoot(parent) ? null : getParent(parent); } return null; } const oneOfTools = _oneOf(Registry.getTool, "Not expecting tool: "); const toolsArray = _mixedArray(oneOfTools); const Types = { unionArray, allModelsTypes, unionTag, tagsTypes, isType, getParentOfTypeString, getParentTagOfTypeString, tagsArray, toolsArray, }; export default Types;