UNPKG

mobx-bonsai

Version:

A fast lightweight alternative to MobX-State-Tree + Y.js two-way binding

1,587 lines 349 kB
var __defProp = Object.defineProperty; var __typeError = (msg) => { throw TypeError(msg); }; 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 __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg); var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var _a, _b, _c, _d, _e, _f, _undoAction, _redoAction, _g; import * as mobx from "mobx"; import { isObservableArray, isObservableMap, isObservableSet, isObservableObject, remove, set, action, createAtom, toJS, observable, intercept, observe, computed, reaction, runInAction, transaction, untracked, keys, get, has, entries, values, _getGlobalState, when, isObservable } from "mobx"; class MobxBonsaiError extends Error { constructor(msg) { super(msg); Object.setPrototypeOf(this, MobxBonsaiError.prototype); } } function mitt(n) { return { all: n = n || /* @__PURE__ */ new Map(), on: function(t, e) { var i = n.get(t); i ? i.push(e) : n.set(t, [e]); }, off: function(t, e) { var i = n.get(t); i && (e ? i.splice(i.indexOf(e) >>> 0, 1) : n.set(t, [])); }, emit: function(t, e) { var i = n.get(t); i && i.slice().map(function(n2) { n2(e); }), (i = n.get("*")) && i.slice().map(function(n2) { n2(t, e); }); } }; } function failure(msg) { return new MobxBonsaiError(msg); } 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; }; let localId = 0; const localBaseId = nanoid(); const defaultNodeKeyGenerator = () => { const id = localId.toString(36) + "-" + localBaseId; localId++; return id; }; let globalConfig = { keyGenerator: defaultNodeKeyGenerator, checkCircularReferences: false }; function getGlobalConfig() { return globalConfig; } function disposeOnce(fn) { let disposed = false; return (...args) => { if (disposed) { return; } disposed = true; fn(...args); }; } function getDefaultExportFromCjs(x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x; } var deepFreeze$1; var hasRequiredDeepFreeze; function requireDeepFreeze() { if (hasRequiredDeepFreeze) return deepFreeze$1; hasRequiredDeepFreeze = 1; deepFreeze$1 = function deepFreeze2(o) { Object.freeze(o); Object.getOwnPropertyNames(o).forEach(function(prop) { if (o.hasOwnProperty(prop) && o[prop] !== null && (typeof o[prop] === "object" || typeof o[prop] === "function") && !Object.isFrozen(o[prop])) { deepFreeze2(o[prop]); } }); return o; }; return deepFreeze$1; } var deepFreezeExports = requireDeepFreeze(); const deepFreeze = /* @__PURE__ */ getDefaultExportFromCjs(deepFreezeExports); function isPrimitive(v) { const t = typeof v; return t === "string" || t === "number" || t === "boolean" || v === null || v === void 0; } function isObject(value) { return value !== null && typeof value === "object"; } function assertIsObject(value, argName) { if (!isObject(value)) { throw failure(`${argName} must be an object`); } } function isPlainObject(v) { return isObject(v) && v.constructor === Object; } function isArray(v) { return Array.isArray(v) || isObservableArray(v); } function isMap(val) { return val instanceof Map || isObservableMap(val); } function isSet(val) { return val instanceof Set || isObservableSet(val); } function isObservablePlainStructure(target) { return isObservableObject(target) || isObservableArray(target); } function assertIsObservablePlainStructure(target, argName) { const valid = isObservablePlainStructure(target); if (!valid) { throw failure(`${argName} must be an observable object or array`); } } function assertIsFunction(value, argName) { if (typeof value !== "function") { throw failure(`${argName} must be a function`); } } const inDevMode = process.env.NODE_ENV !== "production"; function setIfDifferent(target, key, value) { if (target[key] !== value || !(key in target)) { set(target, key, value); } } function reconcileData(oldValue, newValue, reconciliationRoot) { var _a2, _b2; if (oldValue === newValue) { return oldValue; } if (isPrimitive(newValue) || isPrimitive(oldValue)) { return newValue; } const oldIsArray = isArray(oldValue); const newIsArray = isArray(newValue); if (oldIsArray !== newIsArray) { return newValue; } if (newIsArray) { const oldArray = oldValue; const newArray = newValue; if (oldArray.length > newArray.length) { oldArray.splice(newArray.length, oldArray.length - newArray.length); } for (let i = 0; i < oldArray.length; i++) { const oldV = oldArray[i]; const newV = reconcileData(oldV, newArray[i]); setIfDifferent(oldArray, i, newV); } for (let i = oldArray.length; i < newArray.length; i++) { oldArray.push(reconcileData(void 0, newArray[i])); } return oldArray; } else if (isMap(newValue)) { throw failure("a value must not contain maps"); } else if (isSet(newValue)) { throw failure("a value must not contain sets"); } else { const oldObject = oldValue; const newObject = newValue; const newNodeTypeAndKey = getNodeTypeAndKey(newObject); const oldNodeTypeAndKey = getNodeTypeAndKey(oldObject); if (newNodeTypeAndKey.type !== oldNodeTypeAndKey.type || newNodeTypeAndKey.key !== oldNodeTypeAndKey.key) { return newValue; } if (((_a2 = newNodeTypeAndKey.type) == null ? void 0 : _a2.isFrozen) || ((_b2 = oldNodeTypeAndKey.type) == null ? void 0 : _b2.isFrozen)) { return newValue; } const oldObjectKeys = Object.keys(oldObject); const oldObjectKeysLen = oldObjectKeys.length; for (let i = 0; i < oldObjectKeysLen; i++) { const k = oldObjectKeys[i]; if (!(k in newObject)) { remove(oldObject, k); } } const newObjectKeys = Object.keys(newObject); const newObjectKeysLen = newObjectKeys.length; for (let i = 0; i < newObjectKeysLen; i++) { const k = newObjectKeys[i]; const v = newObject[k]; const oldV = oldObject[k]; const newV = reconcileData(oldV, v); setIfDifferent(oldObject, k, newV); } return oldObject; } } function getParentPath(node2) { const nodeData = getNodeData(node2); const ret = nodeData.parent ? { parent: nodeData.parent.object, path: nodeData.parent.path } : void 0; reportNodeParentObserved(node2); return ret; } const snapshots = /* @__PURE__ */ new WeakMap(); const snapshotAtoms = /* @__PURE__ */ new WeakMap(); const invalidateSnapshotTreeToRoot = action((node2) => { var _a2, _b2; assertIsNode(node2, "node"); let current = node2; while (current) { const hadSnapshot = snapshots.delete(current); if (!hadSnapshot) { break; } (_a2 = snapshotAtoms.get(current)) == null ? void 0 : _a2.reportChanged(); current = (_b2 = getParentPath(current)) == null ? void 0 : _b2.parent; } }); const createSnapshot = action((node2) => { assertIsNode(node2, "node"); if (isFrozenNode(node2)) { return node2; } if (isObservableArray(node2)) { return node2.map((v) => getSnapshotOrPrimitive(v, true)); } if (isObservableObject(node2)) { const obj = {}; Object.entries(node2).forEach(([key, v]) => { obj[key] = getSnapshotOrPrimitive(v, true); }); return obj; } throw failure(`only observable objects, observable arrays and primitives are supported`); }); function getSnapshotOrPrimitive(value, acceptPrimitives) { if (acceptPrimitives && isPrimitive(value)) { return value; } const node2 = value; assertIsNode(node2, "value"); let existingSnapshot = snapshots.get(node2); if (!existingSnapshot) { existingSnapshot = createSnapshot(node2); snapshots.set(node2, existingSnapshot); } let atom = snapshotAtoms.get(node2); if (!atom) { atom = createAtom("snapshot"); snapshotAtoms.set(node2, atom); } atom.reportObserved(); return existingSnapshot; } function getSnapshot(node2) { return getSnapshotOrPrimitive(node2, false); } function getParent(node2) { var _a2; return (_a2 = getParentPath(node2)) == null ? void 0 : _a2.parent; } function buildNodeFullPath(node2, subPath) { const fullPath = []; let current = node2; while (current) { const parent = getParentPath(current); if (parent) { fullPath.push(parent.path); } current = parent == null ? void 0 : parent.parent; } fullPath.reverse(); if (subPath) { fullPath.push(subPath); } return fullPath; } function getNodeData(node2) { assertIsNode(node2, "node"); return nodes.get(node2); } function reportNodeParentObserved(node2) { const data = getNodeData(node2); if (!data.parentAtom) { data.parentAtom = createAtom("parent"); } data.parentAtom.reportObserved(); } const nodes = /* @__PURE__ */ new WeakMap(); function setParentNode(node2, parentNode) { var _a2; const nodeData = getNodeData(node2); const oldParent = nodeData.parent; if (oldParent && !parentNode) { if (shouldHaveChangeListeners(oldParent.object)) { decrementAncestorChangeListenerRefCount(node2); } } else if (!oldParent && parentNode) { if (shouldHaveChangeListeners(parentNode.object)) { incrementAncestorChangeListenerRefCount(node2); } } else if (oldParent && parentNode && oldParent.object !== parentNode.object) { throw failure( "assertion failed: node moved from one parent to another without being detached first" ); } nodeData.parent = parentNode; (_a2 = nodeData.parentAtom) == null ? void 0 : _a2.reportChanged(); } function isNode(struct) { return nodes.has(struct); } function isFrozenNode(node2) { return getNodeData(node2).frozen; } function assertIsNode(node2, argName) { if (!isNode(node2)) { throw failure(`${argName} must be a mobx-bonsai node`); } } function emitToListeners(listeners, change) { if (listeners && listeners.length > 0) { listeners.forEach((listener) => { listener(change); }); } } function emitChangeToRoot(eventTarget, change) { let currentTarget = eventTarget; while (currentTarget) { const changeListeners = getNodeData(currentTarget).onChangeListeners; emitToListeners(changeListeners, change); currentTarget = getParent(currentTarget); } } function emitInterceptedChangeToRoot(eventTarget, change) { let currentChange = change; let currentTarget = eventTarget; while (currentTarget) { const interceptedChangeListeners = getNodeData(currentTarget).onInterceptedChangeListeners; if (interceptedChangeListeners && interceptedChangeListeners.length > 0) { for (const listener of interceptedChangeListeners) { const result = listener(currentChange); if (result === void 0) { throw failure( "onDeepInterceptedChange listener must return either the change object or null, but returned undefined" ); } if (result === null) { return null; } currentChange = result; } } currentTarget = getParent(currentTarget); } return currentChange; } function registerListener(node2, listener, listenersProperty) { const nodeData = getNodeData(node2); let listeners = nodeData[listenersProperty]; const wasEmpty = !listeners || listeners.length === 0; if (!listeners) { listeners = []; nodeData[listenersProperty] = listeners; } listeners.push(listener); if (wasEmpty && listenersProperty === "onChangeListeners") { incrementAncestorChangeListenerRefCount(node2); } return disposeOnce(() => { const currentListeners = nodeData[listenersProperty]; if (currentListeners) { const index = currentListeners.indexOf(listener); if (index !== -1) { currentListeners.splice(index, 1); const isEmpty = currentListeners.length === 0; if (isEmpty) { nodeData[listenersProperty] = void 0; if (listenersProperty === "onChangeListeners") { decrementAncestorChangeListenerRefCount(node2); } } } } }); } function onDeepInterceptedChange(node2, listener) { return registerListener(node2, listener, "onInterceptedChangeListeners"); } function onDeepChange(node2, listener) { return registerListener(node2, listener, "onChangeListeners"); } function attachObserveHook(node2) { const nodeData = getNodeData(node2); if (!nodeData.observeDisposer) { nodeData.observeDisposer = observe(node2, (change) => { emitChangeToRoot(node2, change); }); } } function detachObserveHook(node2) { const nodeData = getNodeData(node2); if (nodeData.observeDisposer) { nodeData.observeDisposer(); nodeData.observeDisposer = void 0; } } function incrementAncestorChangeListenerRefCount(node2) { const nodeData = getNodeData(node2); if (nodeData.frozen) { return; } nodeData.ancestorChangeListenerRefCount++; if (nodeData.ancestorChangeListenerRefCount === 1) { attachObserveHook(node2); } if (nodeData.childrenObjects) { nodeData.childrenObjects.forEach((child) => { incrementAncestorChangeListenerRefCount(child); }); } } function decrementAncestorChangeListenerRefCount(node2) { const nodeData = getNodeData(node2); if (nodeData.frozen) { return; } nodeData.ancestorChangeListenerRefCount--; if (nodeData.ancestorChangeListenerRefCount === 0) { detachObserveHook(node2); } if (nodeData.childrenObjects) { nodeData.childrenObjects.forEach((child) => { decrementAncestorChangeListenerRefCount(child); }); } } function shouldHaveChangeListeners(node2) { return getNodeData(node2).ancestorChangeListenerRefCount > 0; } let detachDuplicatedNodes = 0; const runDetachingDuplicatedNodes = (fn) => { detachDuplicatedNodes++; try { fn(); } finally { detachDuplicatedNodes--; } }; const node = action( (struct, options) => { var _a2; if (isNode(struct)) { return struct; } const { type, key } = getNodeTypeAndKey(struct); const keyProp = type && "key" in type ? type.key : void 0; if (type !== void 0 && key !== void 0) { const existingNode = "findByKey" in type ? type.findByKey(key) : void 0; if (existingNode) { const result = reconcileData(existingNode, struct); if (result !== existingNode) { throw failure("reconciliation should not create a new object"); } return existingNode; } } const frozen = type && "isFrozen" in type ? type.isFrozen : false; const nodeData = { parent: void 0, parentAtom: void 0, onChangeListeners: void 0, onInterceptedChangeListeners: void 0, childrenObjects: void 0, frozen, observeDisposer: void 0, ancestorChangeListenerRefCount: 0 }; let nodeStruct; const registerNode = () => { if (!nodeStruct) { throw failure("nodeStruct is not defined"); } nodes.set(nodeStruct, nodeData); tryRegisterNodeByTypeAndKey(nodeStruct); }; if (frozen) { const plainStruct = toJS(struct); if (inDevMode) { deepFreeze(plainStruct); } nodeStruct = plainStruct; registerNode(); } else { const observableStruct = (() => { if (isObservablePlainStructure(struct)) { return struct; } return Array.isArray(struct) ? observable.array(struct, { deep: false }) : observable.object(struct, void 0, { deep: false }); })(); nodeStruct = observableStruct; registerNode(); const attachAsChildNode = (v, path, setIfConverted) => { if (isPrimitive(v)) { return; } let n = v; if (isNode(n)) { const parent = getNodeData(n).parent; if (parent && (parent.object !== observableStruct || parent.path !== path)) { if (detachDuplicatedNodes > 0) { set(parent.object, parent.path, void 0); } else { throw failure( `The same node cannot appear twice in the same or different trees, trying to assign it to ${JSON.stringify(buildNodeFullPath(observableStruct, path))}, but it already exists at ${JSON.stringify(buildNodeFullPath(parent.object, parent.path))}. If you are moving the node then remove it from the tree first before moving it. If you are copying the node then use 'clone' to make a clone first.` ); } } } else { n = node(v); const parent = getNodeData(n).parent; if (parent && (parent.object !== observableStruct || parent.path !== path)) { set(parent.object, parent.path, void 0); } if (n !== v) { setIfConverted(n); } } if (!nodeData.childrenObjects) { nodeData.childrenObjects = observable.set([], { deep: false }); } nodeData.childrenObjects.add(n); setParentNode(n, { object: observableStruct, path }); }; const detachAsChildNode = (v) => { if (!isPrimitive(v) && isNode(v)) { setParentNode(v, void 0); if (nodeData.childrenObjects) { nodeData.childrenObjects.delete(v); } } }; const isArrayNode = isArray(observableStruct); if (isArrayNode) { const array = observableStruct; array.forEach((v, i) => { attachAsChildNode(v, i.toString(), (n) => { set(array, i, n); }); }); } else { const object = observableStruct; Object.entries(object).forEach(([key2, v]) => { attachAsChildNode(v, key2, (n) => { set(object, key2, n); }); }); } if (isArrayNode) { const array = observableStruct; intercept(array, (change) => { const wrappedChange = emitInterceptedChangeToRoot(array, change); if (wrappedChange === null) { return null; } let changed = false; switch (change.type) { case "update": { const oldValue = array[change.index]; changed = oldValue !== change.newValue; if (changed) { detachAsChildNode(oldValue); attachAsChildNode(change.newValue, "" + change.index, (n) => { change.newValue = n; }); } break; } case "splice": { for (let i = 0; i < change.removedCount; i++) { const removedValue = array[change.index + i]; detachAsChildNode(removedValue); } for (let i = 0; i < change.added.length; i++) { attachAsChildNode(change.added[i], "" + (change.index + i), (n) => { change.added[i] = n; }); } changed = change.removedCount > 0 || change.added.length > 0; const oldNextIndex = change.index + change.removedCount; const newNextIndex = change.index + change.added.length; if (oldNextIndex !== newNextIndex) { for (let i = oldNextIndex, j = newNextIndex; i < array.length; i++, j++) { const value = array[i]; if (isPrimitive(value)) { continue; } if (!isNode(value)) { throw failure("node expected"); } setParentNode( value, { object: array, path: "" + j } // parentPath ); } } break; } default: throw failure(`unsupported change type`); } if (changed) { invalidateSnapshotTreeToRoot(observableStruct); return change; } return null; }); } else { const object = observableStruct; intercept(object, (change) => { const wrappedChange = emitInterceptedChangeToRoot(object, change); if (wrappedChange === null) { return null; } if (typeof change.name === "symbol") { throw failure("symbol keys are not supported on a mobx-bonsai node"); } const propKey = "" + change.name; if (propKey === nodeTypeKey || keyProp !== void 0 && propKey === keyProp) { throw failure(`the property ${change.name} cannot be modified`); } let changed = false; switch (change.type) { case "add": { changed = true; attachAsChildNode(change.newValue, propKey, (n) => { change.newValue = n; }); break; } case "update": { const oldValue = object[propKey]; changed = oldValue !== change.newValue; if (changed) { detachAsChildNode(oldValue); attachAsChildNode(change.newValue, propKey, (n) => { change.newValue = n; }); } break; } case "remove": { changed = true; const oldValue = object[propKey]; detachAsChildNode(oldValue); break; } default: throw failure(`unsupported change type`); } if (changed) { invalidateSnapshotTreeToRoot(observableStruct); return change; } return null; }); } } const skipInit = (_a2 = options == null ? void 0 : options.skipInit) != null ? _a2 : false; if (!skipInit) { type == null ? void 0 : type._initNode(nodeStruct); } return nodeStruct; } ); function volatileProp(defaultValueGen) { const volatileValueAdmins = /* @__PURE__ */ new WeakMap(); const getOrCreateValueAdmin = (target) => { let valueAdmin = volatileValueAdmins.get(target); if (!valueAdmin) { const initialValue = defaultValueGen(); valueAdmin = { valueBox: observable.box(initialValue, { deep: false }), initialValue }; volatileValueAdmins.set(target, valueAdmin); } return valueAdmin; }; const vProp = [ (target) => { assertIsObservablePlainStructure(target, "target"); const valueAdmin = getOrCreateValueAdmin(target); return valueAdmin.valueBox.get(); }, action((target, value) => { assertIsObservablePlainStructure(target, "target"); const valueAdmin = getOrCreateValueAdmin(target); valueAdmin.valueBox.set(value); }), action((target) => { assertIsObservablePlainStructure(target, "target"); const valueAdmin = volatileValueAdmins.get(target); if (valueAdmin) { valueAdmin.valueBox.set(valueAdmin.initialValue); } }) ]; return vProp; } const nodeTypeKey = "$$type"; const nodeByTypeAndKey = /* @__PURE__ */ new Map(); const finalizationRegistry = new FinalizationRegistry( ({ typeId, key }) => { const typeMap = nodeByTypeAndKey.get(typeId); if (!typeMap) { return; } const ref = typeMap.get(key); if (!ref) { return; } if (ref.deref()) { return; } typeMap.delete(key); if (typeMap.size === 0) { nodeByTypeAndKey.delete(typeId); } } ); function tryRegisterNodeByTypeAndKey(node2) { assertIsNode(node2, "node"); const { type, key } = getNodeTypeAndKey(node2); if (type === void 0 || key === void 0) { return false; } const { typeId } = type; let typeMap = nodeByTypeAndKey.get(typeId); if (!typeMap) { typeMap = /* @__PURE__ */ new Map(); nodeByTypeAndKey.set(typeId, typeMap); } typeMap.set(key, new WeakRef(node2)); finalizationRegistry.register(node2, { typeId, key }); return true; } const registeredNodeTypes = /* @__PURE__ */ new Map(); function findNodeTypeById(typeId) { return registeredNodeTypes.get(typeId); } function getNodeTypeId(node2) { return node2[nodeTypeKey]; } function getNodeTypeAndKey(node2) { const typeValue = getNodeTypeId(node2); if (typeValue === void 0) { return { type: void 0, key: void 0 }; } const type = findNodeTypeById(typeValue); if (type === void 0) { throw failure(`a node with type '${typeValue}' was found, but such type is not registered`); } return { type, key: "getKey" in type ? type.getKey(node2) : void 0 }; } function nodeType(type) { return type !== void 0 ? typedNodeType(type) : untypedNodeType(); } function addNodeTypeExtensionMethods(nodeTypeObj) { const addKey = (key, value) => { nodeTypeObj[key] = value; nodeTypeObj._extendsKeys.add(key); }; nodeTypeObj.volatile = (volatiles) => { for (const volatileKey of Object.keys(volatiles)) { const defaultValueGen = volatiles[volatileKey]; const [getter, setter, resetter] = volatileProp(defaultValueGen); const capitalizedVolatileKey = volatileKey.charAt(0).toUpperCase() + volatileKey.slice(1); addKey(`get${capitalizedVolatileKey}`, getter); addKey(`set${capitalizedVolatileKey}`, setter); addKey(`reset${capitalizedVolatileKey}`, resetter); } return nodeTypeObj; }; nodeTypeObj.actions = (actions) => { for (const key of Object.keys(actions)) { addKey( key, action((n, ...args) => actions[key].apply(n, args)) ); } return nodeTypeObj; }; nodeTypeObj.getters = (getters) => { for (const key of Object.keys(getters)) { addKey(key, (n, ...args) => getters[key].apply(n, args)); } return nodeTypeObj; }; nodeTypeObj.computeds = (computeds) => { const cachedComputedsByNode = /* @__PURE__ */ new WeakMap(); function getOrCreateNodeCachedComputed(n, key) { let nodeCachedComputeds = cachedComputedsByNode.get(n); if (!nodeCachedComputeds) { nodeCachedComputeds = /* @__PURE__ */ new Map(); cachedComputedsByNode.set(n, nodeCachedComputeds); } let cachedComputed = nodeCachedComputeds.get(key); if (!cachedComputed) { const value = computeds[key]; if (typeof value === "function") { cachedComputed = computed(() => value.call(n)); } else if (typeof value === "object" && "get" in value && typeof value.get === "function") { const options = { ...value, get: void 0 }; cachedComputed = computed(() => value.get.call(n), options); } else { throw failure( `computed property '${key}' must be a function or a configuration object with a 'get' method` ); } nodeCachedComputeds.set(key, cachedComputed); } return cachedComputed; } for (const key of Object.keys(computeds)) { addKey(key, (n) => getOrCreateNodeCachedComputed(n, key).get()); } return nodeTypeObj; }; nodeTypeObj.settersFor = (...properties) => { for (const prop of properties) { const capitalizedProp = prop.charAt(0).toUpperCase() + prop.slice(1); addKey( `set${capitalizedProp}`, action((node2, value) => { set(node2, prop, value); }) ); } return nodeTypeObj; }; nodeTypeObj.defaults = (defaultGenerators) => { nodeTypeObj.defaultGenerators = { ...nodeTypeObj.defaultGenerators, ...defaultGenerators }; return nodeTypeObj; }; nodeTypeObj.extends = (otherNodeType) => { if ("typeId" in otherNodeType && otherNodeType.typeId !== void 0) { throw failure(`cannot extend from a typed node type`); } for (const key of otherNodeType._extendsKeys) { if (!(key in otherNodeType)) { throw failure( `assertion error: '${key}' was expected to be in the extended node type, but it was not found` ); } if (key in nodeTypeObj) { throw failure( `cannot extend from node type since the current key '${key}' would be overwritten` ); } addKey(key, otherNodeType[key]); } if (otherNodeType.defaultGenerators) { nodeTypeObj.defaults(otherNodeType.defaultGenerators); } return nodeTypeObj; }; } function applyDefaultGenerators(data, defaultGenerators) { if (!defaultGenerators) { return data; } if (typeof data !== "object" || data === null) { throw failure(`data must be an object`); } const copy = { ...data }; for (const [key, gen] of Object.entries(defaultGenerators)) { if (copy[key] === void 0) { copy[key] = gen(); } } return copy; } function typedNodeType(type) { if (type && registeredNodeTypes.has(type)) { throw failure(`node type '${type}' is already registered`); } const events = mitt(); const snapshot = (data) => { let sn = applyDefaultGenerators(data, nodeTypeObj.defaultGenerators); if (data === sn) { sn = { ...data, [nodeTypeKey]: type }; } else { sn[nodeTypeKey] = type; } if (keyedNodeTypeObj.key !== void 0) { const key = keyedNodeTypeObj.getKey(sn); if (key === void 0) { sn[keyedNodeTypeObj.key] = getGlobalConfig().keyGenerator(); } } return sn; }; const nodeTypeObj = (data) => { return node(snapshot(data)); }; const keyedNodeTypeObj = nodeTypeObj; nodeTypeObj._extendsKeys = /* @__PURE__ */ new Set(); nodeTypeObj.snapshot = snapshot; nodeTypeObj.typeId = type; nodeTypeObj.isFrozen = false; nodeTypeObj.frozen = () => { nodeTypeObj.isFrozen = true; return nodeTypeObj; }; nodeTypeObj.withKey = (key) => { if (keyedNodeTypeObj.key !== void 0) { throw failure(`node type already has a key`); } keyedNodeTypeObj.key = key; keyedNodeTypeObj.getKey = (node2) => { return keyedNodeTypeObj.key === void 0 ? void 0 : node2[keyedNodeTypeObj.key]; }; keyedNodeTypeObj.findByKey = (key2) => { const typeMap = nodeByTypeAndKey.get(type); if (!typeMap) { return void 0; } const ref = typeMap.get(key2); return ref == null ? void 0 : ref.deref(); }; keyedNodeTypeObj.defaults({ [key]: () => getGlobalConfig().keyGenerator() }); return keyedNodeTypeObj; }; nodeTypeObj.nodeIsOfType = (node2) => { return isNode(node2) && node2[nodeTypeKey] === type; }; nodeTypeObj.unregister = disposeOnce(() => { registeredNodeTypes.delete(type); }); nodeTypeObj[Symbol.dispose] = () => { nodeTypeObj.unregister(); }; nodeTypeObj._addOnInit = (callback) => { const actionCallback = action(callback); events.on("init", actionCallback); return disposeOnce(() => { events.off("init", actionCallback); }); }; nodeTypeObj.onInit = (callback) => { nodeTypeObj._addOnInit(callback); return nodeTypeObj; }; nodeTypeObj._initNode = (node2) => { events.emit("init", node2); }; addNodeTypeExtensionMethods(nodeTypeObj); registeredNodeTypes.set(type, nodeTypeObj); return nodeTypeObj; } function onInit(nodeType2, callback) { return nodeType2._addOnInit(callback); } function untypedNodeType() { const snapshot = (data) => applyDefaultGenerators(data, nodeTypeObj.defaultGenerators); const nodeTypeObj = (data) => node(snapshot(data)); nodeTypeObj._extendsKeys = /* @__PURE__ */ new Set(); nodeTypeObj.snapshot = snapshot; addNodeTypeExtensionMethods(nodeTypeObj); return nodeTypeObj; } function computedProp(fn, options) { const computedFns = /* @__PURE__ */ new WeakMap(); const getFn = (obj) => { if (!isObservablePlainStructure(obj)) { return fn(obj); } let computedFn = computedFns.get(obj); if (!computedFn) { computedFn = computed(() => fn(obj), options); computedFns.set(obj, computedFn); } return computedFn.get(); }; getFn.getComputedFor = (obj) => computedFns.get(obj); return getFn; } function getChildrenNodesWithTargetSet(node2, targetSet) { getShallowChildren(node2).forEach((child) => { targetSet.add(child); const deepChildren = getComputedDeepChildren(child); deepChildren.forEach((deepChild) => { targetSet.add(deepChild); }); }); } const getShallowChildren = (node2) => { const nodeData = getNodeData(node2); if (!nodeData.childrenObjects) { nodeData.childrenObjects = observable.set([], { deep: false }); } return nodeData.childrenObjects; }; const getComputedDeepChildren = computedProp((node2) => { const children = /* @__PURE__ */ new Set(); getChildrenNodesWithTargetSet(node2, children); return children; }); function getChildrenNodes(node2, options) { var _a2; assertIsNode(node2, "node"); const deep = (_a2 = options == null ? void 0 : options.deep) != null ? _a2 : false; if (!deep) { return getShallowChildren(node2); } return getComputedDeepChildren(node2); } function findChildren(root, predicate, options) { const children = getChildrenNodes(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 findParentPath(child, predicate, maxDepth = 0) { assertIsNode(child, "child"); const path = []; let current = child; let depth = 0; let parentPath; while (parentPath = getParentPath(current)) { 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 findParent(child, predicate, maxDepth = 0) { const foundParentPath = findParentPath(child, predicate, maxDepth); return foundParentPath ? foundParentPath.parent : void 0; } function getParentToChildPath(fromParent, toChild) { assertIsNode(fromParent, "fromParent"); assertIsNode(toChild, "toChild"); if (fromParent === toChild) { return []; } const path = []; let current = toChild; let parentPath; while (parentPath = getParentPath(current)) { path.unshift(parentPath.path); current = parentPath.parent; if (current === fromParent) { return path; } } return void 0; } function getRootPath(node2) { assertIsNode(node2, "node"); let root = node2; const path = []; const pathObjects = [node2]; let parentPath; while (parentPath = getParentPath(root)) { root = parentPath.parent; path.unshift(parentPath.path); pathObjects.unshift(parentPath.parent); } const rootPath = { root, path, pathObjects }; return rootPath; } function getRoot(node2) { return getRootPath(node2).root; } function isChildOfParent(child, parent) { assertIsNode(child, "child"); assertIsNode(parent, "parent"); let currentParent = getParent(child); while (currentParent) { if (currentParent === parent) { return true; } currentParent = getParent(currentParent); } return false; } function isParentOfChild(parent, child) { return isChildOfParent(child, parent); } function isRoot(node2) { return !getParent(node2); } function onChildAttachedTo({ target, childNodeType, onChildAttached, deep, fireForCurrentChildren }) { assertIsFunction(target, "target"); assertIsFunction(onChildAttached, "onChildAttached"); deep != null ? deep : deep = false; fireForCurrentChildren != null ? fireForCurrentChildren : fireForCurrentChildren = true; const convertToChildNodeTypeSet = () => { if (!childNodeType) { return void 0; } return new Set(Array.isArray(childNodeType) ? childNodeType : [childNodeType]); }; const childNodeTypeSet = convertToChildNodeTypeSet(); const detachDisposers = /* @__PURE__ */ new WeakMap(); const runDetachDisposer = (n) => { const detachDisposer = detachDisposers.get(n); if (detachDisposer) { detachDisposers.delete(n); detachDisposer(); } }; const addDetachDisposer = (n, disposer) => { if (disposer) { detachDisposers.set(n, action(disposer)); } }; const getChildrenObjectOpts = { deep }; const getCurrentChildren = () => { const t = target(); assertIsNode(t, "target()"); const children = getChildrenNodes(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 = fireForCurrentChildren ? /* @__PURE__ */ new Set() : getCurrentChildren(); const disposeReaction = 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); runInAction(() => { const { type } = getNodeTypeAndKey(n); if (!childNodeTypeSet || childNodeTypeSet.has(type)) { const detachAction = onChildAttached(n); addDetachDisposer(n, detachAction); } }); } newChildrenCur = newChildrenIter.next(); } }, { fireImmediately: true } ); return disposeOnce((runDetachDisposers) => { disposeReaction(); if (runDetachDisposers) { const currentChildrenIter = currentChildren.values(); let currentChildrenCur = currentChildrenIter.next(); while (!currentChildrenCur.done) { const n = currentChildrenCur.value; runDetachDisposer(n); currentChildrenCur = currentChildrenIter.next(); } } currentChildren.clear(); }); } const unresolved = { resolved: false }; function resolvePath(pathRootNode, path) { assertIsNode(pathRootNode, "pathRootNode"); let current = pathRootNode; const len = path.length; for (let i = 0; i < len; i++) { if (current === null || typeof current !== "object") { return unresolved; } const p = path[i]; if (isArray(current) && +p >= current.length) { return unresolved; } if (!(p in current)) { return unresolved; } current = current[p]; } return { resolved: true, value: current }; } var WalkTreeMode = /* @__PURE__ */ ((WalkTreeMode2) => { WalkTreeMode2["ParentFirst"] = "parentFirst"; WalkTreeMode2["ChildrenFirst"] = "childrenFirst"; return WalkTreeMode2; })(WalkTreeMode || {}); function walkTree(root, visit, mode) { assertIsNode(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 node2 = stack.pop(); const ret = visit(node2); if (ret !== void 0) { return ret; } const children = getChildrenNodes(node2); 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 = getChildrenNodes(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; } const applySnapshot = action((node2, snapshot) => { assertIsNode(node2, "node"); assertIsObject(snapshot, "snapshot"); const reconcile = () => { const ret = reconcileData(node2, snapshot); if (ret !== node2) { throw failure("assertion failed: reconciled object has to be the same"); } }; if (isArray(snapshot)) { if (!isArray(node2)) { throw failure("if the snapshot is an array the target must be an array too"); } reconcile(); return; } if (isPlainObject(snapshot)) { if (isFrozenNode(node2)) { if (node2 === snapshot) { return; } else { throw failure("applySnapshot does not work on frozen nodes"); } } if (!isObservableObject(node2)) { throw failure("if the snapshot is an object the target must be an object too"); } const typeKey = getNodeTypeAndKey(node2); const newTypeKey = getNodeTypeAndKey(snapshot); if (typeKey.type !== newTypeKey.type) { throw failure( `applySnapshot does not allow changes to the '${nodeTypeKey}' property of the node the snapshot is being applied to` ); } if (typeKey.key !== newTypeKey.key) { const keyProp = typeKey.type && "key" in typeKey.type ? typeKey.type.key : void 0; throw failure( `applySnapshot does not allow changes to the '${keyProp}' property of the node the snapshot is being applied to` ); } reconcile(); return; } if (isMap(snapshot)) { throw failure("a snapshot must not contain maps"); } if (isSet(snapshot)) { throw failure("a snapshot must not contain sets"); } throw failure(`unsupported snapshot - ${snapshot}`); }); function onSnapshot(nodeOrFn, listener) { const nodeFn = typeof nodeOrFn === "function" ? nodeOrFn : () => nodeOrFn; const node2 = nodeFn(); assertIsNode(node2, "node"); let currentSnapshot = getSnapshot(node2); const disposeReaction = reaction( () => getSnapshot(nodeFn()), (newSnapshot) => { const prevSn = currentSnapshot; currentSnapshot = newSnapshot; listener(newSnapshot, prevSn); } ); return disposeOnce(disposeReaction); } function substituteNodeKeys(value, newNodeKeyGenerator = getGlobalConfig().keyGenerator) { if (isPrimitive(value)) { return value; } if (Array.isArray(value)) { return value.map((v) => substituteNodeKeys(v, newNodeKeyGenerator)); } if (isPlainObject(value)) { const typeAndKey = getNodeTypeAndKey(value); const keyProp = typeAndKey.type && "key" in typeAndKey.type ? typeAndKey.type.key : void 0; const newValue = {}; for (const key in value) { if (key === keyProp) { newValue[key] = newNodeKeyGenerator(value[key]); } else { newValue[key] = substituteNodeKeys(value[key], newNodeKeyGenerator); } } return newValue; } throw failure("unsupported value type"); } function clone(nodeToClone) { const snapshotWithChangedKeys = substituteNodeKeys(getSnapshot(nodeToClone)); return node(snapshotWithChangedKeys); } function getOrCreate(map, key, create) { let value = map.get(key); if (value === void 0) { value = create(); map.set(key, value); } return value; } function resolveContextValue(contextValue) { if (contextValue.type === "value") { return contextValue.value; } else { return contextValue.value.get(); } } const createContextValueAtom = () => createAtom("contextValue"); class ContextClass { constructor(defaultValue) { __publicField(this, "defaultContextValue", observable.box(void 0, { deep: false })); __publicField(this, "overrideContextValue", observable.box(void 0, { deep: false })); __publicField(this, "nodeContextValue", /* @__PURE__ */ new WeakMap()); __publicField(this, "nodeAtom", /* @__PURE__ */ new WeakMap()); __publicField(this, "setDefault", action((value) => { this.defaultContextValue.set({ type: "value", value }); })); __publicField(this, "setDefaultComputed", action((valueFn) => { this.defaultContextValue.set({ type: "computed", value: computed(valueFn) }); })); __publicField(this, "set", action((node2, value) => { assertIsNode(node2, "node"); this.nodeContextValue.set(node2, { type: "value", value }); this.reportNodeAtomChanged(node2); })); __publicField(this, "setComputed", action((node2, valueFn) => { this._setComputed(node2, computed(valueFn)); })); __publicField(this, "unset", action((node2) => { assertIsNode(node2, "node"); this.nodeContextValue.delete(node2); this.reportNodeAtomChanged(node2); })); __publicField(this, "apply", action((fn, value) => { const old = this.overrideContextValue.get(); this.overrideContextValue.set({ type: "value", value }); try { const ret = fn(); if (isNode(ret)) { this.set(ret, value); } return ret; } finally { this.overrideContextValue.set(old); } })); __publicField(this, "applyComputed", action((fn, valueFn) => { const computedValueFn = computed(valueFn); const old = this.overrideContextValue.get(); this.overrideContextValue.set({ type: "computed", value: computedValueFn }); try { const ret = fn(); if (isNode(ret)) { this._setComputed(ret, computedValueFn); } return ret; } finally { this.overrideContextValue.set(old); } })); this.setDefault(defaultValue); } reportNodeAtomObserved(node2) { getOrCreate(this.nodeAtom, node2, createContextValueAtom).reportObserved(); } reportNodeAtomChanged(node2) { var _a2; (_a2 = this.nodeAtom.get(node2)) == null ? void 0 : _a2.reportChanged(); } internalGet(node2) { this.reportNodeAtomObserved(node2); const obsForNode = this.nodeContextValue.get(node2); if (obsForNode) { return resolveContextValue(obsForNode); } const parent = getParent(node2); if (!parent) { const overrideValue = this.overrideContextValue.get(); if (overrideValue) { return resolveContextValue(overrideValue); } return this.getDefault(); } return this.internalGet(parent); } get(node2) { assertIsNode(node2, "node"); return this.internalGet(node2); } internalGetProviderNode(node2) { this.reportNodeAtomObserved(node2); const obsForNode = this.nodeContextValue.get(node2); if (obsForNode) { return node2; } const parent = getParent(node2); if (!parent) { return void 0; } return this.internalGetProviderNode(parent); } getProviderNode(node2) { assertIsNode(node2, "node"); return this.internalGetProviderNode(node2); } getDefault() { return resolveContextValue(this.defaultContextValue.get()); } _setComputed(node2, computedValueFn) { assertIsNode(node2, "node"); this.nodeContextValue.set(node2, { type: "computed", value: computedValueFn }); this.reportNodeAtomChanged(node2); } } function createContext(defaultValue) { return new ContextClass(defaultValue); } function asReduxStore(target) { assertIsNode(target, "target"); const store = { getState() { return getSnapshot(target); }, subscribe(listener) { return onSnapshot(target, listener); } }; return store; } function connectReduxDevTools(remotedevPackage, remotedevConnection, target) { assertIsNode(target, "target"); let handlingMonitorAction = 0; remotedevConnection.subscribe((message) => { if (message.type === "DISPATCH") { handleMonitorActions(remotedevConnection, target, message); } }); const initialState = getSnapshot(target); remotedevConnection.init(initialState); let lastLoggedSnapshot = initialState; onSnapshot(target, (sn) => { if (handlingMonitorAction) { return; } if (sn === lastLoggedSnapshot) { return; } lastLoggedSnapshot = sn; const copy = { type: "onSnapshot" }; remotedevConnection.send(copy, sn); }); function handleMonitorActions(remotedev2, target2, message) { try { handlingMonitorAction++; switch (message.payload.type) { case "RESET": { applySnapshot(target2, initialState); return remotedev2.init(initialState); } case "COMMIT": return remotedev2.init(getSnapshot(target2)); case "ROLLBACK": { const state = remotedevPackage.extractState(message); applySnapshot(target2, state); return remotedev2.init(state); } case "JUMP_TO_STATE": case "JUMP_TO_ACTION": { applySnapshot(target2, remotedevPackage.extractState(message