UNPKG

mobx-keystone-mindreframer

Version:

A MobX powered state management solution based on data trees with first class support for Typescript, snapshots, patches and much more

59 lines (53 loc) 2.01 kB
import { isModelAutoTypeCheckingEnabled } from "../globalConfig/globalConfig" import type { AnyModel } from "../model/BaseModel" import { getModelMetadata } from "../model/getModelMetadata" import { isModel } from "../model/utils" import { dataToModelNode } from "../parent/core" import { findParent } from "../parent/findParent" import { internalApplyPatches } from "../patch/applyPatches" import { InternalPatchRecorder } from "../patch/emitPatch" import { invalidateCachedTypeCheckerResult } from "../typeChecking/TypeChecker" import { runWithoutSnapshotOrPatches } from "./core" /** * @ignore * @internal */ export function runTypeCheckingAfterChange(obj: object, patchRecorder: InternalPatchRecorder) { // invalidate type check cached result invalidateCachedTypeCheckerResult(obj) if (isModelAutoTypeCheckingEnabled()) { const parentModelWithTypeChecker = findNearestParentModelWithTypeChecker(obj) if (parentModelWithTypeChecker) { const err = parentModelWithTypeChecker.typeCheck() if (err) { // quietly apply inverse patches (do not generate patches, snapshots, actions, etc) runWithoutSnapshotOrPatches(() => { internalApplyPatches.call(obj, patchRecorder.invPatches, true) }) // at the end of apply patches it will be type checked again and its result cached once more err.throw(parentModelWithTypeChecker) } } } } /** * @ignore * * Finds the closest parent model that has a type checker defined. * * @param child * @returns */ function findNearestParentModelWithTypeChecker(child: object): AnyModel | undefined { // child might be .$, so we need to check the parent model in that case const actualChild = dataToModelNode(child) if (child !== actualChild) { child = actualChild if (isModel(child) && !!getModelMetadata(child).dataType) { return child } } return findParent(child, (parent) => { return isModel(parent) && !!getModelMetadata(parent).dataType }) }