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

107 lines (88 loc) 2.91 kB
import { action, createAtom, IAtom } from "mobx" import { fastGetRoot, isRoot } from "../parent/path" import { assertTweakedObject } from "../tweaker/core" import { failure } from "../utils" import { getOrCreate } from "../utils/mapUtils" import { attachToRootStore, detachFromRootStore } from "./attachDetach" const rootStores = new WeakSet<object>() const rootStoreAtoms = new WeakMap<object, IAtom>() /** * Registers a model / tree node object as a root store tree. * Marking a model object as a root store tree serves several purposes: * - It allows the `onAttachedToRootStore` hook (plus disposer) to be invoked on models once they become part of this tree. * These hooks can be used for example to attach effects and serve as some sort of initialization. * - It allows auto detachable references to work properly. * * @typeparam T Object type. * @param node Node object to register as root store. * @returns The same model object that was passed. */ export const registerRootStore: <T extends object>(node: T) => T = action( "registerRootStore", (node) => { assertTweakedObject(node, "node") if (rootStores.has(node)) { throw failure("object already registered as root store") } if (!isRoot(node)) { throw failure("a root store must not have a parent") } rootStores.add(node) attachToRootStore(node, node) getOrCreateRootStoreAtom(node).reportChanged() return node } ) /** * Unregisters an object to mark it as no longer a root store. * * @param node Node object to unregister as root store. */ export const unregisterRootStore: (node: object) => void = action("unregisterRootStore", (node) => { if (!isRootStore(node)) { throw failure("not a root store") } rootStores.delete(node) detachFromRootStore(node) getOrCreateRootStoreAtom(node).reportChanged() }) /** * Checks if a given object is marked as a root store. * * @param node Object. * @returns */ export function isRootStore(node: object): boolean { assertTweakedObject(node, "node") return fastIsRootStore(node) } /** * @ignore * @internal */ export function fastIsRootStore(node: object): boolean { getOrCreateRootStoreAtom(node).reportObserved() return rootStores.has(node) } /** * Gets the root store of a given tree child, or undefined if none. * * @typeparam T Root store type. * @param node Target to find the root store for. * @returns */ export function getRootStore<T extends object>(node: object): T | undefined { assertTweakedObject(node, "node") return fastGetRootStore(node) } /** * @ignore * @internal */ export function fastGetRootStore<T extends object>(node: object): T | undefined { const root = fastGetRoot(node) return fastIsRootStore(root) ? root : undefined } function getOrCreateRootStoreAtom(node: object): IAtom { return getOrCreate(rootStoreAtoms, node, () => createAtom("rootStore")) }