UNPKG

mobx-keystone

Version:

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

1,623 lines (1,622 loc) 1.23 MB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j; import * as mobx from "mobx"; import { isObservableMap, isObservableSet, isObservableArray, isObservableObject, createAtom, runInAction, action, computed, isAction, set, reaction, isObservable, toJS, remove, observable, intercept, observe, when, untracked, transaction as transaction$1, values, get, has, keys, entries } from "mobx"; const dataModelActionRegistry = /* @__PURE__ */ new Map(); function getDataModelAction(fullActionName) { return dataModelActionRegistry.get(fullActionName); } function setDataModelAction(fullActionName, modelClass2, fnName) { dataModelActionRegistry.set(fullActionName, { modelClass: modelClass2, fnName }); } var BuiltInAction = /* @__PURE__ */ ((BuiltInAction2) => { BuiltInAction2["ApplyPatches"] = "$$applyPatches"; BuiltInAction2["ApplySnapshot"] = "$$applySnapshot"; BuiltInAction2["Detach"] = "$$detach"; BuiltInAction2["ApplySet"] = "$$applySet"; BuiltInAction2["ApplyDelete"] = "$$applyDelete"; BuiltInAction2["ApplyMethodCall"] = "$$applyMethodCall"; return BuiltInAction2; })(BuiltInAction || {}); const builtInActionValues = new Set(Object.values(BuiltInAction)); function isBuiltInAction(actionName) { return builtInActionValues.has(actionName); } var ActionContextActionType = /* @__PURE__ */ ((ActionContextActionType2) => { ActionContextActionType2["Sync"] = "sync"; ActionContextActionType2["Async"] = "async"; return ActionContextActionType2; })(ActionContextActionType || {}); var ActionContextAsyncStepType = /* @__PURE__ */ ((ActionContextAsyncStepType2) => { ActionContextAsyncStepType2["Spawn"] = "spawn"; ActionContextAsyncStepType2["Return"] = "return"; ActionContextAsyncStepType2["Resume"] = "resume"; ActionContextAsyncStepType2["ResumeError"] = "resumeError"; ActionContextAsyncStepType2["Throw"] = "throw"; return ActionContextAsyncStepType2; })(ActionContextAsyncStepType || {}); let currentActionContext; function getCurrentActionContext() { return currentActionContext; } function setCurrentActionContext(ctx) { currentActionContext = ctx; } const modelActionSymbol = Symbol("modelAction"); function isModelAction(fn) { return typeof fn === "function" && modelActionSymbol in fn; } const modelTypeKey = "$modelType"; const modelIdKey = "$modelId"; function isReservedModelKey(key) { return key === modelTypeKey; } class MobxKeystoneError extends Error { constructor(msg) { super(msg); Object.setPrototypeOf(this, MobxKeystoneError.prototype); } } function failure(msg) { return new MobxKeystoneError(msg); } const writableHiddenPropDescriptor = { enumerable: false, writable: true, configurable: false, value: void 0 }; function addHiddenProp(object, propName, value, writable = true) { if (writable) { Object.defineProperty(object, propName, writableHiddenPropDescriptor); object[propName] = value; } else { Object.defineProperty(object, propName, { enumerable: false, writable, configurable: true, value }); } } function makePropReadonly(object, propName, enumerable) { const propDesc = Object.getOwnPropertyDescriptor(object, propName); if (propDesc) { propDesc.enumerable = enumerable; if (propDesc.get) { delete propDesc.set; } else { propDesc.writable = false; } Object.defineProperty(object, propName, propDesc); } } function isPlainObject(value) { if (!isObject(value)) { return false; } const proto = Object.getPrototypeOf(value); return proto === Object.prototype || proto === null; } function isObject(value) { return value !== null && typeof value === "object"; } function isPrimitive(value) { switch (typeof value) { case "number": case "string": case "boolean": case "undefined": case "bigint": return true; default: return value === null; } } function isJSONPrimitive(value) { switch (typeof value) { case "number": return Number.isFinite(value); case "string": case "boolean": return true; default: return value === null; } } function deleteFromArray(array, value) { const index = array.indexOf(value); if (index >= 0) { array.splice(index, 1); return true; } return false; } function isMap(val) { return val instanceof Map || isObservableMap(val); } function isSet(val) { return val instanceof Set || isObservableSet(val); } function isArray(val) { return Array.isArray(val) || isObservableArray(val); } const inDevMode = process.env.NODE_ENV !== "production"; function assertIsObject(value, argName) { if (!isObject(value)) { throw failure(`${argName} must be an object`); } } function assertIsPlainObject(value, argName) { if (!isPlainObject(value)) { throw failure(`${argName} must be a plain object`); } } function assertIsObservableObject(value, argName) { if (!isObservableObject(value)) { throw failure(`${argName} must be an observable object`); } } function assertIsObservableArray(value, argName) { if (!isObservableArray(value)) { throw failure(`${argName} must be an observable array`); } } function assertIsMap(value, argName) { if (!isMap(value)) { throw failure(`${argName} must be a map`); } } function assertIsSet(value, argName) { if (!isSet(value)) { throw failure(`${argName} must be a set`); } } function assertIsFunction(value, argName) { if (typeof value !== "function") { throw failure(`${argName} must be a function`); } } function assertIsPrimitive(value, argName) { if (!isPrimitive(value)) { throw failure(`${argName} must be a primitive`); } } function assertIsString(value, argName) { if (typeof value !== "string") { throw failure(`${argName} must be a string`); } } const runAfterNewSymbol = Symbol("runAfterNew"); const runBeforeOnInitSymbol = Symbol("runBeforeOnInit"); function addLateInitializationFunction(target, symbol, fn) { let array = target[symbol]; if (!(array && Object.prototype.hasOwnProperty.call(target, symbol))) { array = array ? array.slice() : []; addHiddenProp(target, symbol, array); } array.push(fn); } function runLateInitializationFunctions(target, symbol) { const fns = target[symbol]; if (fns) { for (const fn of fns) { fn(target); } } } const warningsAlreadyDisplayed = /* @__PURE__ */ new Set(); function logWarning(type, msg, uniqueKey) { if (uniqueKey) { if (warningsAlreadyDisplayed.has(uniqueKey)) { return; } warningsAlreadyDisplayed.add(uniqueKey); } msg = "[mobx-keystone] " + msg; switch (type) { case "warn": console.warn(msg); break; case "error": console.error(msg); break; default: throw failure(`unknown log type - ${type}`); } } function lazy(getter) { let memoizedValue; let memoized = false; return (...args) => { if (!memoized) { memoizedValue = getter(...args); memoized = true; } return memoizedValue; }; } const identityFn = (x) => x; const mobx6 = { makeObservable: mobx[ // just to ensure import * is kept properly String.fromCharCode("l".charCodeAt(0) + 1) + "akeObservable" ] }; function propNameToSetterName(propName) { return `set${propName[0].toUpperCase()}${propName.slice(1)}`; } function getMobxVersion() { if (mobx6.makeObservable) { return 6; } else { return 5; } } const namespace$2 = "mobx-keystone"; const propsTypeSymbol = Symbol("propsType"); const fromSnapshotOverrideTypeSymbol = Symbol("fromSnapshotOverrideType"); const toSnapshotOverrideTypeSymbol = Symbol("toSnapshotOverrideType"); const modelInitializedSymbol = Symbol("modelInitialized"); function modelClass(type) { return type; } const modelInfoByName = {}; const modelInfoByClass = /* @__PURE__ */ new WeakMap(); function getModelInfoForName(name) { return modelInfoByName[name]; } function getOrCreate(map, key, create) { let value = map.get(key); if (value === void 0) { value = create(); map.set(key, value); } return value; } const objectParents = /* @__PURE__ */ new WeakMap(); const objectParentsAtoms = /* @__PURE__ */ new WeakMap(); function parentPathEquals(parentPath1, parentPath2) { if (!(parentPath1 || parentPath2)) { return true; } if (!(parentPath1 && parentPath2)) { return false; } return parentPath1.parent === parentPath2.parent && parentPath1.path === parentPath2.path; } function createParentPathAtom() { return createAtom("parentAtom"); } function reportParentPathObserved(node) { getOrCreate(objectParentsAtoms, node, createParentPathAtom).reportObserved(); } function reportParentPathChanged(node) { var _a2; (_a2 = objectParentsAtoms.get(node)) == null ? void 0 : _a2.reportChanged(); } const dataObjectParent = /* @__PURE__ */ new WeakMap(); function dataToModelNode(node) { const modelNode = dataObjectParent.get(node); return modelNode != null ? modelNode : node; } function modelToDataNode(node) { return isModel(node) ? node.$ : node; } const tweakedObjects = /* @__PURE__ */ new WeakMap(); function isTweakedObject(value, canBeDataObject) { if (!canBeDataObject && dataObjectParent.has(value)) { return false; } return tweakedObjects.has(value); } function isTreeNode(value) { return !isPrimitive(value) && isTweakedObject(value, false); } function assertTweakedObject(treeNode, argName, canBeDataObject = false) { if (!canBeDataObject && dataObjectParent.has(treeNode)) { throw failure(`${argName} must be the model object instance instead of the '$' sub-object`); } if (isPrimitive(treeNode) || !isTweakedObject(treeNode, true)) { throw failure( `${argName} must be a tree node (usually a model or a shallow / deep child part of a model 'data' object)` ); } } function assertIsTreeNode(value, argName = "argument") { assertTweakedObject(value, argName, false); } let runningWithoutSnapshotOrPatches = false; function runWithoutSnapshotOrPatches(fn) { const old = runningWithoutSnapshotOrPatches; runningWithoutSnapshotOrPatches = true; try { runInAction(() => { fn(); }); } finally { runningWithoutSnapshotOrPatches = old; } } const modelMetadataSymbol = Symbol("modelMetadata"); const modelUnwrappedClassSymbol = Symbol("modelUnwrappedClass"); const runAfterModelDecoratorSymbol = Symbol("runAfterModelDecorator"); const modelPropertiesSymbol = Symbol("modelProperties"); function getInternalModelClassPropsInfo(modelClass2) { return modelClass2[modelPropertiesSymbol]; } function setInternalModelClassPropsInfo(modelClass2, props) { modelClass2[modelPropertiesSymbol] = props; } const noDefaultValue = Symbol("noDefaultValue"); const idProp = { _setter: false, _isId: true, withSetter(mode) { const obj = Object.create(this); obj._setter = mode != null ? mode : true; return obj; }, typedAs() { return idProp; } }; const baseProp = { ...{}, _defaultFn: noDefaultValue, _defaultValue: noDefaultValue, _typeChecker: void 0, _setter: false, _isId: false, _transform: void 0, _fromSnapshotProcessor: void 0, _toSnapshotProcessor: void 0, withSetter(mode) { const obj = Object.create(this); obj._setter = mode != null ? mode : true; return obj; }, withTransform(transform) { const obj = Object.create(this); obj._transform = toFullTransform(transform); return obj; }, withSnapshotProcessor({ fromSnapshot: fromSnapshot2, toSnapshot }) { let newFromSnapshot; if (this._fromSnapshotProcessor && fromSnapshot2) { const oldFn = this._fromSnapshotProcessor; const newFn = fromSnapshot2; newFromSnapshot = (sn) => oldFn(newFn(sn)); } else if (fromSnapshot2) { newFromSnapshot = fromSnapshot2; } else { newFromSnapshot = this._fromSnapshotProcessor; } let newToSnapshot; if (this._toSnapshotProcessor && toSnapshot) { const oldFn = this._toSnapshotProcessor; const newFn = toSnapshot; newToSnapshot = (sn) => newFn(oldFn(sn)); } else if (toSnapshot) { newToSnapshot = toSnapshot; } else { newToSnapshot = this._toSnapshotProcessor; } const obj = Object.create(this); obj._fromSnapshotProcessor = newFromSnapshot; obj._toSnapshotProcessor = newToSnapshot; return obj; } }; function prop(def) { const hasDefaultValue = arguments.length > 0; if (!hasDefaultValue) { return baseProp; } let p = propCache.get(def); if (!p) { p = Object.create(baseProp); if (typeof def === "function") { p._defaultFn = def; } else { p._defaultValue = def; } propCache.set(def, p); } return p; } const propCache = /* @__PURE__ */ new Map(); let cacheTransformResult = false; const cacheTransformedValueFn = () => { cacheTransformResult = true; }; function toFullTransform(transformObject) { const cache = /* @__PURE__ */ new WeakMap(); const transform = (params) => params.originalValue == null ? params.originalValue : transformObject.transform(params); const untransform = (params) => params.transformedValue == null ? params.transformedValue : transformObject.untransform(params); return { transform(originalValue, model2, propName, setOriginalValue) { const modelCache = getOrCreate(cache, model2, () => /* @__PURE__ */ new Map()); let propCache2 = modelCache.get(propName); if ((propCache2 == null ? void 0 : propCache2.originalValue) !== originalValue) { modelCache.delete(propName); propCache2 = void 0; } const transformedValue = transform({ originalValue, cachedTransformedValue: propCache2 == null ? void 0 : propCache2.transformedValue, setOriginalValue }); modelCache.set(propName, { originalValue, transformedValue }); return transformedValue; }, untransform(transformedValue, model2, propName) { const modelCache = getOrCreate(cache, model2, () => /* @__PURE__ */ new Map()); cacheTransformResult = false; const originalValue = untransform({ transformedValue, cacheTransformedValue: cacheTransformedValueFn }); if (cacheTransformResult) { modelCache.set(propName, { originalValue, transformedValue }); } else { modelCache.delete(propName); } return originalValue; } }; } function getModelPropDefaultValue(propData) { if (propData._defaultFn !== noDefaultValue) { return propData._defaultFn(); } if (propData._defaultValue !== noDefaultValue) { return propData._defaultValue; } return noDefaultValue; } let urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"; let nanoid = (size = 21) => { let id = ""; let i = size | 0; while (i--) { id += urlAlphabet[Math.random() * 64 | 0]; } return id; }; var ModelAutoTypeCheckingMode = /* @__PURE__ */ ((ModelAutoTypeCheckingMode2) => { ModelAutoTypeCheckingMode2["DevModeOnly"] = "devModeOnly"; ModelAutoTypeCheckingMode2["AlwaysOn"] = "alwaysOn"; ModelAutoTypeCheckingMode2["AlwaysOff"] = "alwaysOff"; return ModelAutoTypeCheckingMode2; })(ModelAutoTypeCheckingMode || {}); let localId = 0; const localBaseId = nanoid(); function defaultModelIdGenerator() { const id = localId.toString(36) + "-" + localBaseId; localId++; return id; } let globalConfig = { modelAutoTypeChecking: "devModeOnly", modelIdGenerator: defaultModelIdGenerator, allowUndefinedArrayElements: false, showDuplicateModelNameWarnings: true }; function setGlobalConfig(config) { globalConfig = Object.freeze({ ...globalConfig, ...config }); } function getGlobalConfig() { return globalConfig; } function isModelAutoTypeCheckingEnabled() { switch (getGlobalConfig().modelAutoTypeChecking) { case "devModeOnly": return inDevMode; case "alwaysOff": return false; case "alwaysOn": return true; default: throw failure( `invalid 'modelAutoTypeChecking' config value - ${globalConfig.modelAutoTypeChecking}` ); } } const objectChildren = /* @__PURE__ */ new WeakMap(); function getObjectChildrenObject(node) { let obj = objectChildren.get(node); if (!obj) { obj = { shallow: /* @__PURE__ */ new Set(), shallowAtom: void 0, // will be created when first observed deep: /* @__PURE__ */ new Set(), deepDirty: true, deepAtom: void 0, // will be created when first observed extensionsData: initExtensionsData() }; objectChildren.set(node, obj); } return obj; } function getObjectChildren(node) { const obj = getObjectChildrenObject(node); if (!obj.shallowAtom) { obj.shallowAtom = createAtom("shallowChildrenAtom"); } obj.shallowAtom.reportObserved(); return obj.shallow; } function getDeepObjectChildren(node) { const obj = getObjectChildrenObject(node); if (obj.deepDirty) { updateDeepObjectChildren(node); } if (!obj.deepAtom) { obj.deepAtom = createAtom("deepChildrenAtom"); } obj.deepAtom.reportObserved(); return obj; } function addNodeToDeepLists(node, data) { data.deep.add(node); extensions.forEach((extension, dataSymbol) => { extension.addNode(node, data.extensionsData.get(dataSymbol)); }); } const updateDeepObjectChildren = action((node) => { var _a2; const obj = getObjectChildrenObject(node); if (!obj.deepDirty) { return obj; } obj.deep = /* @__PURE__ */ new Set(); obj.extensionsData = initExtensionsData(); const childrenIterator = obj.shallow.values(); let childrenIteratorResult = childrenIterator.next(); while (!childrenIteratorResult.done) { addNodeToDeepLists(childrenIteratorResult.value, obj); const childDeepChildren = updateDeepObjectChildren(childrenIteratorResult.value).deep; const childDeepChildrenIterator = childDeepChildren.values(); let childDeepChildrenIteratorResult = childDeepChildrenIterator.next(); while (!childDeepChildrenIteratorResult.done) { addNodeToDeepLists(childDeepChildrenIteratorResult.value, obj); childDeepChildrenIteratorResult = childDeepChildrenIterator.next(); } childrenIteratorResult = childrenIterator.next(); } obj.deepDirty = false; (_a2 = obj.deepAtom) == null ? void 0 : _a2.reportChanged(); return obj; }); const addObjectChild = action((node, child) => { var _a2; const obj = getObjectChildrenObject(node); obj.shallow.add(child); (_a2 = obj.shallowAtom) == null ? void 0 : _a2.reportChanged(); invalidateDeepChildren(node, obj); }); const removeObjectChild = action((node, child) => { var _a2; const obj = getObjectChildrenObject(node); obj.shallow.delete(child); (_a2 = obj.shallowAtom) == null ? void 0 : _a2.reportChanged(); invalidateDeepChildren(node, obj); }); function invalidateDeepChildren(node, obj) { var _a2; let currentNode = node; let currentObj = obj; while (currentNode) { currentObj.deepDirty = true; (_a2 = currentObj.deepAtom) == null ? void 0 : _a2.reportChanged(); currentNode = fastGetParent(currentNode, false); if (currentNode) { currentObj = getObjectChildrenObject(currentNode); } } } const extensions = /* @__PURE__ */ new Map(); function registerDeepObjectChildrenExtension(extension) { const dataSymbol = {}; extensions.set(dataSymbol, extension); return (data) => { return data.extensionsData.get(dataSymbol); }; } function initExtensionsData() { const extensionsData = /* @__PURE__ */ new WeakMap(); extensions.forEach((extension, dataSymbol) => { extensionsData.set(dataSymbol, extension.initData()); }); return extensionsData; } function canWrite() { return !getActionProtection() || !!getCurrentActionContext(); } function assertCanWrite() { if (!canWrite()) { throw failure("data changes must be performed inside model actions"); } } let actionProtection = true; function getActionProtection() { return actionProtection; } function setActionProtection(protection) { actionProtection = protection; } const pendingActions = []; function isActionRunning() { return !getActionProtection() || !!getCurrentActionContext(); } function enqueuePendingAction(action2) { if (isActionRunning()) { pendingActions.push(action2); } else { action2(); } } let pendingActionsRunning = false; function tryRunPendingActions() { if (isActionRunning() || pendingActionsRunning) { return; } pendingActionsRunning = true; try { while (pendingActions.length > 0) { const nextAction = pendingActions.shift(); nextAction(); } } finally { pendingActionsRunning = false; } } function getModelMetadata(modelClassOrInstance) { if (isModel(modelClassOrInstance)) { return modelClassOrInstance.constructor[modelMetadataSymbol]; } else if (isModelClass(modelClassOrInstance)) { return modelClassOrInstance[modelMetadataSymbol]; } else { throw failure(`modelClassOrInstance must be a model class or instance`); } } const modelIdPropertyNameCache = /* @__PURE__ */ new WeakMap(); function getModelIdPropertyName(modelClass2) { return getOrCreate( modelIdPropertyNameCache, modelClass2, () => getModelMetadata(modelClass2).modelIdProperty ); } var HookAction = /* @__PURE__ */ ((HookAction2) => { HookAction2["OnInit"] = "$$onInit"; HookAction2["OnLazyInit"] = "$$onLazyInit"; HookAction2["OnAttachedToRootStore"] = "$$onAttachedToRootStore"; HookAction2["OnAttachedToRootStoreDisposer"] = "$$onAttachedToRootStoreDisposer"; return HookAction2; })(HookAction || {}); const hookActionValues = new Set(Object.values(HookAction)); function isHookAction(actionName) { return hookActionValues.has(actionName); } var WalkTreeMode = /* @__PURE__ */ ((WalkTreeMode2) => { WalkTreeMode2["ParentFirst"] = "parentFirst"; WalkTreeMode2["ChildrenFirst"] = "childrenFirst"; return WalkTreeMode2; })(WalkTreeMode || {}); function walkTree(root, visit, mode) { assertTweakedObject(root, "root"); if (mode === "parentFirst") { return walkTreeParentFirst(root, visit); } else { return walkTreeChildrenFirst(root, visit); } } function walkTreeParentFirst(root, visit) { const stack = [root]; while (stack.length > 0) { const node = stack.pop(); const ret = visit(node); if (ret !== void 0) { return ret; } const children = getObjectChildren(node); stack.length += children.size; let i = stack.length - 1; const childrenIter = children.values(); let ch = childrenIter.next(); while (!ch.done) { stack[i--] = ch.value; ch = childrenIter.next(); } } return void 0; } function walkTreeChildrenFirst(root, visit) { const childrenIter = getObjectChildren(root).values(); let ch = childrenIter.next(); while (!ch.done) { const ret2 = walkTreeChildrenFirst(ch.value, visit); if (ret2 !== void 0) { return ret2; } ch = childrenIter.next(); } const ret = visit(root); if (ret !== void 0) { return ret; } return void 0; } function getComputedTreeResult(computedFns, visit, tree) { let cmpted = computedFns.get(tree); if (!cmpted) { cmpted = computed(() => { return walkTreeAggregate(tree, visit, (ch) => getComputedTreeResult(computedFns, visit, ch)); }); computedFns.set(tree, cmpted); } return cmpted.get(); } function computedWalkTreeAggregate(visit) { const computedFns = /* @__PURE__ */ new WeakMap(); return { walk: (n) => getComputedTreeResult(computedFns, visit, n) }; } function walkTreeAggregate(target, visit, recurse) { let map; const rootVal = visit(target); const childrenMap = getObjectChildren(target); const childrenIter = childrenMap.values(); let ch = childrenIter.next(); if (rootVal === void 0 && childrenMap.size === 1) { return recurse(ch.value); } while (!ch.done) { const childMap = recurse(ch.value); if (childMap) { if (!map) { map = /* @__PURE__ */ new Map(); } const mapIter = childMap.keys(); let mapCur = mapIter.next(); while (!mapCur.done) { const key = mapCur.value; const val = childMap.get(key); map.set(key, val); mapCur = mapIter.next(); } } ch = childrenIter.next(); } if (rootVal !== void 0) { if (!map) { map = /* @__PURE__ */ new Map(); } map.set(rootVal, target); } return map; } const onAttachedDisposers = /* @__PURE__ */ new WeakMap(); const attachedToRootStore = /* @__PURE__ */ new WeakSet(); const attachToRootStore = action( "attachToRootStore", (rootStore, child) => { const childrenToCall = []; walkTree( child, (ch) => { if (attachedToRootStore.has(ch)) { return; } attachedToRootStore.add(ch); if (ch instanceof BaseModel && ch.onAttachedToRootStore) { wrapModelMethodInActionIfNeeded( ch, "onAttachedToRootStore", HookAction.OnAttachedToRootStore ); childrenToCall.push(ch); } }, WalkTreeMode.ParentFirst ); const childrenToCallLen = childrenToCall.length; for (let i = 0; i < childrenToCallLen; i++) { const ch = childrenToCall[i]; const disposer = ch.onAttachedToRootStore(rootStore); if (disposer) { onAttachedDisposers.set(ch, disposer); } } } ); const detachFromRootStore = action("detachFromRootStore", (child) => { const disposersToCall = []; walkTree( child, (ch) => { if (!attachedToRootStore.delete(ch)) { return; } const disposer = onAttachedDisposers.get(ch); if (disposer) { const disposerAction = wrapInAction({ nameOrNameFn: HookAction.OnAttachedToRootStoreDisposer, fn: disposer, actionType: ActionContextActionType.Sync }).bind(ch); onAttachedDisposers.delete(ch); disposersToCall.push(disposerAction); } }, WalkTreeMode.ChildrenFirst ); const disposersToCallLen = disposersToCall.length; for (let i = 0; i < disposersToCallLen; i++) { disposersToCall[i](); } }); const rootStoreRegistry = /* @__PURE__ */ new WeakMap(); function createRootStoreEntry() { return { atom: void 0, // will be created when first observed is: false }; } const getOrCreateRootStoreEntry = (node) => getOrCreate(rootStoreRegistry, node, createRootStoreEntry); const registerRootStore = action( "registerRootStore", (node) => { var _a2; assertTweakedObject(node, "node"); const entry = getOrCreateRootStoreEntry(node); if (entry.is) { throw failure("object already registered as root store"); } if (!isRoot(node)) { throw failure("a root store must not have a parent"); } entry.is = true; attachToRootStore(node, node); (_a2 = entry.atom) == null ? void 0 : _a2.reportChanged(); return node; } ); const unregisterRootStore = action("unregisterRootStore", (node) => { var _a2; if (!isRootStore(node)) { throw failure("not a root store"); } const entry = getOrCreateRootStoreEntry(node); entry.is = false; detachFromRootStore(node); (_a2 = entry.atom) == null ? void 0 : _a2.reportChanged(); }); function isRootStore(node) { assertTweakedObject(node, "node"); const entry = getOrCreateRootStoreEntry(node); if (!entry.atom) { entry.atom = createAtom("rootStore"); } entry.atom.reportObserved(); return entry.is; } function fastIsRootStoreNoAtom(node) { var _a2; return !!((_a2 = rootStoreRegistry.get(node)) == null ? void 0 : _a2.is); } function getRootStore(node) { assertTweakedObject(node, "node"); const root = fastGetRoot(node, true); return isRootStore(root) ? root : void 0; } class TypeCheckError { /** * Creates an instance of TypeError. * @param path Sub-path (where the root is the value being type checked) where the error occured. * @param expectedTypeName Name of the expected type. * @param actualValue Actual value. * @param typeCheckedValue The value where the type check was invoked. */ constructor(path, expectedTypeName, actualValue, typeCheckedValue) { /** * The type check error message. */ __publicField(this, "message"); this.path = path; this.expectedTypeName = expectedTypeName; this.actualValue = actualValue; this.typeCheckedValue = typeCheckedValue; let rootPath = []; if (this.typeCheckedValue && isTweakedObject(this.typeCheckedValue, true)) { rootPath = fastGetRootPath(this.typeCheckedValue, false).path; } const actualValueSnapshot = isTweakedObject(this.actualValue, true) ? getSnapshot(this.actualValue) : this.actualValue; this.message = `TypeCheckError: [/${[...rootPath, ...this.path].join( "/" )}] Expected a value of type <${this.expectedTypeName}> but got the value <${JSON.stringify( actualValueSnapshot )}> instead`; } /** * Throws the type check error as an actual error. */ throw() { throw failure(this.message); } } const emptyPath = []; const typeCheckersWithCachedResultsOfObject = /* @__PURE__ */ new WeakMap(); var TypeCheckerBaseType = /* @__PURE__ */ ((TypeCheckerBaseType2) => { TypeCheckerBaseType2["Object"] = "object"; TypeCheckerBaseType2["Array"] = "array"; TypeCheckerBaseType2["Primitive"] = "primitive"; TypeCheckerBaseType2["Any"] = "any"; return TypeCheckerBaseType2; })(TypeCheckerBaseType || {}); function getTypeCheckerBaseTypeFromValue(value) { if (isArray(value)) { return "array"; } if (isObject(value)) { return "object"; } if (isPrimitive(value)) { return "primitive"; } return "any"; } function invalidateCachedTypeCheckerResult(obj) { let current = obj; while (current) { const set2 = typeCheckersWithCachedResultsOfObject.get(current); if (set2) { typeCheckersWithCachedResultsOfObject.delete(current); set2.forEach((typeChecker) => { typeChecker.invalidateCachedResult(current); }); } current = fastGetParentIncludingDataObjects(current, false); } } const typeCheckersWithCachedSnapshotProcessorResultsOfObject = /* @__PURE__ */ new WeakMap(); function invalidateCachedToSnapshotProcessorResult(obj) { const set2 = typeCheckersWithCachedSnapshotProcessorResultsOfObject.get(obj); if (set2) { set2.forEach((typeChecker) => { typeChecker.invalidateSnapshotProcessorCachedResult(obj); }); typeCheckersWithCachedSnapshotProcessorResultsOfObject.delete(obj); } } class TypeChecker { constructor(baseType, _check, getTypeName, typeInfoGen, snapshotType, _fromSnapshotProcessor, _toSnapshotProcessor) { __publicField(this, "checkResultCache"); __publicField(this, "unchecked"); __publicField(this, "_cachedTypeInfoGen"); __publicField(this, "fromSnapshotProcessor", (sn) => { return this._fromSnapshotProcessor(sn); }); __publicField(this, "_toSnapshotProcessorCache", /* @__PURE__ */ new WeakMap()); __publicField(this, "toSnapshotProcessor", (sn) => { if (typeof sn !== "object" || sn === null) { return this._toSnapshotProcessor(sn); } if (this._toSnapshotProcessorCache.has(sn)) { return this._toSnapshotProcessorCache.get(sn); } const val = this._toSnapshotProcessor(sn); this._toSnapshotProcessorCache.set(sn, val); const typeCheckerSet = getOrCreate( typeCheckersWithCachedSnapshotProcessorResultsOfObject, sn, () => /* @__PURE__ */ new Set() ); typeCheckerSet.add(this); return val; }); this.baseType = baseType; this._check = _check; this.getTypeName = getTypeName; this.typeInfoGen = typeInfoGen; this.snapshotType = snapshotType; this._fromSnapshotProcessor = _fromSnapshotProcessor; this._toSnapshotProcessor = _toSnapshotProcessor; this.unchecked = !_check; this._cachedTypeInfoGen = lazy(typeInfoGen); } createCacheIfNeeded() { if (!this.checkResultCache) { this.checkResultCache = /* @__PURE__ */ new WeakMap(); } return this.checkResultCache; } setCachedResult(obj, newCacheValue) { this.createCacheIfNeeded().set(obj, newCacheValue); const typeCheckerSet = getOrCreate(typeCheckersWithCachedResultsOfObject, obj, () => /* @__PURE__ */ new Set()); typeCheckerSet.add(this); } invalidateCachedResult(obj) { var _a2; (_a2 = this.checkResultCache) == null ? void 0 : _a2.delete(obj); } getCachedResult(obj) { var _a2; return (_a2 = this.checkResultCache) == null ? void 0 : _a2.get(obj); } check(value, path, typeCheckedValue) { if (this.unchecked) { return null; } if (!isTweakedObject(value, true)) { return this._check(value, path, typeCheckedValue); } let cachedResult = this.getCachedResult(value); if (cachedResult === void 0) { cachedResult = this._check(value, emptyPath, void 0); this.setCachedResult(value, cachedResult); } if (cachedResult) { return new TypeCheckError( [...path, ...cachedResult.path], cachedResult.expectedTypeName, cachedResult.actualValue, typeCheckedValue ); } else { return null; } } get typeInfo() { return this._cachedTypeInfoGen(this); } invalidateSnapshotProcessorCachedResult(obj) { this._toSnapshotProcessorCache.delete(obj); } } const lateTypeCheckerSymbol = Symbol("lateTypeCheker"); function lateTypeChecker(fn, typeInfoGen) { let cached; const ltc = () => { if (cached) { return cached; } cached = fn(); return cached; }; ltc[lateTypeCheckerSymbol] = true; const cachedTypeInfoGen = lazy(typeInfoGen); Object.defineProperty(ltc, "typeInfo", { enumerable: true, configurable: false, get() { return cachedTypeInfoGen(ltc); } }); return ltc; } function isLateTypeChecker(ltc) { return typeof ltc === "function" && lateTypeCheckerSymbol in ltc; } class TypeInfo { constructor(thisType) { this.thisType = thisType; } } const snapshots = /* @__PURE__ */ new WeakMap(); const frozenState = /* @__PURE__ */ new WeakMap(); function getInternalSnapshot(value) { return snapshots.get(value); } function getInternalSnapshotParent(sn, parentPath) { if (!(parentPath && sn)) { return void 0; } const parentSn = getInternalSnapshot(parentPath.parent); if (!parentSn) { return void 0; } return { parentSnapshot: parentSn, parentPath }; } const unsetInternalSnapshot = action("unsetInternalSnapshot", (value) => { var _a2; const oldSn = getInternalSnapshot(value); if (oldSn) { snapshots.delete(value); (_a2 = oldSn.atom) == null ? void 0 : _a2.reportChanged(); } }); const setNewInternalSnapshot = action( "setNewInternalSnapshot", (value, untransformed, transformFn, markAsFrozen = false) => { var _a2; const transformed = transformFn ? transformFn(untransformed) : untransformed; const sn = { untransformed, transformFn, transformed, atom: void 0 // will be created when first observed }; frozenState.set(untransformed, markAsFrozen); if (transformed !== void 0 && transformed !== untransformed) { frozenState.set(transformed, markAsFrozen); } snapshots.set(value, sn); (_a2 = sn.atom) == null ? void 0 : _a2.reportChanged(); } ); const updateInternalSnapshot = action( "updateInternalSnapshot", (value, mutate) => { var _a2; const sn = getInternalSnapshot(value); let untransformed = sn.untransformed; const snFrozen = frozenState.get(untransformed); if (snFrozen) { if (Array.isArray(untransformed)) { untransformed = untransformed.slice(); } else { untransformed = Object.assign({}, untransformed); } } else { invalidateCachedToSnapshotProcessorResult(untransformed); } mutate(untransformed); sn.untransformed = untransformed; sn.transformed = sn.transformFn ? sn.transformFn(untransformed) : untransformed; frozenState.set(sn.untransformed, false); if (sn.transformed !== void 0) { frozenState.set(sn.transformed, false); } (_a2 = sn.atom) == null ? void 0 : _a2.reportChanged(); const parent = getInternalSnapshotParent(sn, fastGetParentPath(value, false)); if (parent) { const { parentSnapshot, parentPath } = parent; if (parentSnapshot) { const path = parentPath.path; updateInternalSnapshot(parentPath.parent, (objOrArray) => { objOrArray[path] = sn.transformed; }); } } } ); function reportInternalSnapshotObserved(sn) { if (!sn.atom) { sn.atom = createAtom("snapshot"); } sn.atom.reportObserved(); } function freezeInternalSnapshot(data) { if (isPrimitive(data)) { return data; } const isFrozen = frozenState.get(data); if (isFrozen === void 0 || isFrozen) { return data; } if (Array.isArray(data)) { for (let i = 0; i < data.length; i++) { freezeInternalSnapshot(data[i]); } } else { const keys2 = Object.keys(data); for (let i = 0; i < keys2.length; i++) { freezeInternalSnapshot(data[keys2[i]]); } } frozenState.set(data, true); return data; } const emptyPatchArray = []; class InternalPatchRecorder { constructor() { __publicField(this, "patches", emptyPatchArray); __publicField(this, "invPatches", emptyPatchArray); } reset() { this.patches = emptyPatchArray; this.invPatches = emptyPatchArray; } record(patches, invPatches) { this.patches = patches; this.invPatches = invPatches; } emit(obj) { emitPatches(obj, this.patches, this.invPatches); this.reset(); } } function emitPatches(obj, patches, invPatches) { if (patches.length > 0 || invPatches.length > 0) { emitGlobalPatch(obj, patches, invPatches); emitPatch(obj, patches, invPatches); } } const patchListeners = /* @__PURE__ */ new WeakMap(); const globalPatchListeners = []; function onPatches(subtreeRoot, listener) { assertTweakedObject(subtreeRoot, "subtreeRoot"); assertIsFunction(listener, "listener"); if (!isAction(listener)) { listener = action(listener.name || "onPatchesListener", listener); } let listenersForObject = patchListeners.get(subtreeRoot); if (!listenersForObject) { listenersForObject = []; patchListeners.set(subtreeRoot, listenersForObject); } listenersForObject.push(listener); return () => { deleteFromArray(listenersForObject, listener); }; } function onGlobalPatches(listener) { assertIsFunction(listener, "listener"); if (!isAction(listener)) { listener = action(listener.name || "onGlobalPatchesListener", listener); } globalPatchListeners.push(listener); return () => { deleteFromArray(globalPatchListeners, listener); }; } function emitGlobalPatch(obj, patches, inversePatches) { for (let i = 0; i < globalPatchListeners.length; i++) { const listener = globalPatchListeners[i]; listener(obj, patches, inversePatches); } } function emitPatchForTarget(obj, patches, inversePatches, pathPrefix) { const listenersForObject = patchListeners.get(obj); if (!listenersForObject || listenersForObject.length === 0) { return; } const fixPath = (patchesArray) => pathPrefix.length > 0 ? patchesArray.map((p) => addPathToPatch(p, pathPrefix)) : patchesArray; const patchesWithPathPrefix = fixPath(patches); const invPatchesWithPathPrefix = fixPath(inversePatches); for (let i = 0; i < listenersForObject.length; i++) { const listener = listenersForObject[i]; listener(patchesWithPathPrefix, invPatchesWithPathPrefix); } } function emitPatch(obj, patches, inversePatches) { const pathPrefix = []; emitPatchForTarget(obj, patches, inversePatches, pathPrefix); let parentPath = fastGetParentPath(obj, false); while (parentPath) { pathPrefix.unshift(parentPath.path); emitPatchForTarget(parentPath.parent, patches, inversePatches, pathPrefix); parentPath = fastGetParentPath(parentPath.parent, false); } } function addPathToPatch(patch, pathPrefix) { return { ...patch, path: [...pathPrefix, ...patch.path] }; } const getValueSnapshotForPatch = (v) => { if (isPrimitive(v)) { return v; } const internalSnapshot = getInternalSnapshot(v); if (!internalSnapshot) { return v; } return freezeInternalSnapshot(internalSnapshot.transformed); }; function createPatchForObjectValueChange(path, oldValue, newValue) { return newValue === void 0 ? { op: "remove", path } : oldValue === void 0 ? { op: "add", path, value: getValueSnapshotForPatch(newValue) } : { op: "replace", path, value: getValueSnapshotForPatch(newValue) }; } function setIfDifferent(target, key, value) { if (target[key] !== value || !(key in target)) { set(target, key, value); } } function setIfDifferentWithReturn(target, key, value) { if (target[key] !== value || !(key in target)) { set(target, key, value); return true; } return false; } var TweakerPriority = /* @__PURE__ */ ((TweakerPriority2) => { TweakerPriority2[TweakerPriority2["Model"] = 0] = "Model"; TweakerPriority2[TweakerPriority2["Array"] = 1] = "Array"; TweakerPriority2[TweakerPriority2["PlainObject"] = 2] = "PlainObject"; TweakerPriority2[TweakerPriority2["Frozen"] = 3] = "Frozen"; return TweakerPriority2; })(TweakerPriority || {}); function findParent(child, predicate, maxDepth = 0) { const foundParentPath = findParentPath(child, predicate, maxDepth); return foundParentPath ? foundParentPath.parent : void 0; } function findParentPath(child, predicate, maxDepth = 0) { assertTweakedObject(child, "child"); const path = []; let current = child; let depth = 0; let parentPath; while (parentPath = fastGetParentPath(current, true)) { path.unshift(parentPath.path); current = parentPath.parent; if (predicate(current)) { return { parent: current, path }; } depth++; if (maxDepth > 0 && depth === maxDepth) { break; } } return void 0; } function getChildrenObjects(node, options) { assertTweakedObject(node, "node"); if (options == null ? void 0 : options.deep) { return getDeepObjectChildren(node).deep; } else { return getObjectChildren(node); } } function findChildren(root, predicate, options) { const children = getChildrenObjects(root, options); const set2 = /* @__PURE__ */ new Set(); const iter = children.values(); let cur = iter.next(); while (!cur.done) { if (predicate(cur.value)) { set2.add(cur.value); } cur = iter.next(); } return set2; } function onChildAttachedTo(target, fn, options) { assertIsFunction(target, "target"); assertIsFunction(fn, "fn"); const opts = { deep: false, fireForCurrentChildren: true, ...options }; const detachDisposers = /* @__PURE__ */ new WeakMap(); const runDetachDisposer = (n) => { const detachDisposer = detachDisposers.get(n); if (detachDisposer) { detachDisposers.delete(n); detachDisposer(); } }; const addDetachDisposer = (n, disposer2) => { if (disposer2) { detachDisposers.set(n, action(disposer2)); } }; const getChildrenObjectOpts = { deep: opts.deep }; const getCurrentChildren = () => { const t = target(); assertTweakedObject(t, "target()"); const children = getChildrenObjects(t, getChildrenObjectOpts); const set2 = /* @__PURE__ */ new Set(); const iter = children.values(); let cur = iter.next(); while (!cur.done) { set2.add(cur.value); cur = iter.next(); } return set2; }; const currentChildren = opts.fireForCurrentChildren ? /* @__PURE__ */ new Set() : getCurrentChildren(); const disposer = reaction( () => getCurrentChildren(), (newChildren) => { const disposersToRun = []; const currentChildrenIter = currentChildren.values(); let currentChildrenCur = currentChildrenIter.next(); while (!currentChildrenCur.done) { const n = currentChildrenCur.value; if (!newChildren.has(n)) { currentChildren.delete(n); disposersToRun.push(n); } currentChildrenCur = currentChildrenIter.next(); } if (disposersToRun.length > 0) { for (let i = disposersToRun.length - 1; i >= 0; i--) { runDetachDisposer(disposersToRun[i]); } } const newChildrenIter = newChildren.values(); let newChildrenCur = newChildrenIter.next(); while (!newChildrenCur.done) { const n = newChildrenCur.value; if (!currentChildren.has(n)) { currentChildren.add(n); const detachAction = runInAction(() => fn(n)); addDetachDisposer(n, detachAction); } newChildrenCur = newChildrenIter.next(); } }, { fireImmediately: true } ); return (runDetachDisposers) => { disposer(); if (runDetachDisposers) { const currentChildrenIter = currentChildren.values(); let currentChildrenCur = currentChildrenIter.next(); while (!currentChildrenCur.done) { const n = currentChildrenCur.value; runDetachDisposer(n); currentChildrenCur = currentChildrenIter.next(); } } currentChildren.clear(); }; } function isChildOfParent(child, parent) { assertTweakedObject(child, "child"); assertTweakedObject(parent, "parent"); let currentParent = fastGetParent(child, true); while (currentParent) { if (currentParent === parent) { return true; } currentParent = fastGetParent(currentParent, true); } return false; } function isParentOfChild(parent, child) { return isChildOfParent(child, parent); } let typeCheckingAllowed = true; function withoutTypeChecking(fn) { const oldTypeCheckingAllowed = typeCheckingAllowed; typeCheckingAllowed = false; try { fn(); } finally { typeCheckingAllowed = oldTypeCheckingAllowed; } } function isTypeCheckingAllowed() { return typeCheckingAllowed; } var SnapshotterAndReconcilerPriority = /* @__PURE__ */ ((SnapshotterAndReconcilerPriority2) => { SnapshotterAndReconcilerPriority2[SnapshotterAndReconcilerPriority2["Array"] = 0] = "Array"; SnapshotterAndReconcilerPriority2[SnapshotterAndReconcilerPriority2["Frozen"] = 1] = "Frozen"; SnapshotterAndReconcilerPriority2[SnapshotterAndReconcilerPriority2["Model"] = 2] = "Model"; SnapshotterAndReconcilerPriority2[SnapshotterAndReconcilerPriority2["PlainObject"] = 3] = "PlainObject"; return SnapshotterAndReconcilerPriority2; })(SnapshotterAndReconcilerPriority || {}); function reconcileArraySnapshot(value, sn, modelPool) { if (!isArray(value)) { return fromSnapshot(sn); } const snapshotBeforeChanges = getSnapshot(value); withoutTypeChecking(() => { if (value.length > sn.length) { value.splice(sn.length, value.length - sn.length); } for (let i = 0; i < value.length; i++) { const oldValue = value[i]; const newValue = reconcileSnapshot(oldValue, sn[i], modelPool, value); detachIfNeeded(newValue, oldValue, modelPool); setIfDifferent(value, i, newValue); } for (let i = value.length; i < sn.length; i++) { const newValue = reconcileSnapshot(void 0, sn[i], modelPool, value); detachIfNeeded(newValue, void 0, modelPool); value.push(newValue); } }); runTypeCheckingAfterChange(value, void 0, snapshotBeforeChanges); return value; } function registerArraySnapshotReconciler() { registerReconciler(SnapshotterAndReconcilerPriority.Array, (value, sn, modelPool) => { if (isArray(sn)) { return reconcileArraySnapshot(value, sn, modelPool); } return void 0; }); } var FrozenCheckMode = /* @__PURE__ */ ((FrozenCheckMode2) => { FrozenCheckMode2["DevModeOnly"] = "devModeOnly"; FrozenCheckMode2["On"] = "on"; FrozenCheckMode2["Off"] = "off"; return FrozenCheckMode2; })(FrozenCheckMode || {}); const frozenKey = "$frozen"; class Frozen { /** * Creates an instance of Frozen. * Do not use directly, use `frozen` instead. * * @param dataToFreeze * @param checkMode */ constructor(dataToFreeze, checkMode = "devModeOnly") { /** * Frozen data, deeply immutable. */ __publicField(this, "data"); if (isObservable(dataToFreeze)) { dataToFreeze = toJS(dataToFreeze); } const check = checkMode === "on" || inDevMode && checkMode === "devModeOnly"; if (check) { checkDataIsSerializableAndFreeze(dataToFreeze); } this.data = dataToFreeze; if (check) { Object.freeze(this.data); } tweak(this, void 0); } } function frozen(data, checkMode = "devModeOnly") { return new Frozen(data, checkMode); } function checkDataIsSerializableAndFreeze(data) { if (isPrimitive(data)) { return; } if (Array.isArray(data)) { const arrLen = data.length; for (let i = 0; i < arrLen; i++) { const v = data[i]; if (v === void 0 && !getGlobalConfig().allowUndefinedArrayElements) { throw failure( "undefined is not supported inside arrays since it is not serializable in JSON, consider using null instead" ); } checkDataIsSerializableAndFreeze(v); } Object.freeze(data); return; } if (isPlainObject(data)) { const dataKeys = Object.keys(data); const dataKeysLen = dataKeys.length; for (let i = 0; i < dataKeysLen; i++) { const k = dataKeys[i]; const v = data[k]; checkDataIsSerializableAndFreeze(k); checkDataIsSerializableAndFreeze(v); }