UNPKG

297 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var mobx = require('mobx');
6
7var livelinessChecking = "warn";
8/**
9 * Defines what MST should do when running into reads / writes to objects that have died.
10 * By default it will print a warning.
11 * Use the `"error"` option to easy debugging to see where the error was thrown and when the offending read / write took place
12 *
13 * @param mode `"warn"`, `"error"` or `"ignore"`
14 */
15function setLivelinessChecking(mode) {
16 livelinessChecking = mode;
17}
18/**
19 * Returns the current liveliness checking mode.
20 *
21 * @returns `"warn"`, `"error"` or `"ignore"`
22 */
23function getLivelinessChecking() {
24 return livelinessChecking;
25}
26/**
27 * @deprecated use setLivelinessChecking instead
28 * @hidden
29 *
30 * Defines what MST should do when running into reads / writes to objects that have died.
31 * By default it will print a warning.
32 * Use the `"error"` option to easy debugging to see where the error was thrown and when the offending read / write took place
33 *
34 * @param mode `"warn"`, `"error"` or `"ignore"`
35 */
36function setLivelynessChecking(mode) {
37 setLivelinessChecking(mode);
38}
39
40/**
41 * @hidden
42 */
43var Hook;
44(function (Hook) {
45 Hook["afterCreate"] = "afterCreate";
46 Hook["afterAttach"] = "afterAttach";
47 Hook["afterCreationFinalization"] = "afterCreationFinalization";
48 Hook["beforeDetach"] = "beforeDetach";
49 Hook["beforeDestroy"] = "beforeDestroy";
50})(Hook || (Hook = {}));
51
52/*! *****************************************************************************
53Copyright (c) Microsoft Corporation.
54
55Permission to use, copy, modify, and/or distribute this software for any
56purpose with or without fee is hereby granted.
57
58THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
59REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
60AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
61INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
62LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
63OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
64PERFORMANCE OF THIS SOFTWARE.
65***************************************************************************** */
66/* global Reflect, Promise */
67
68var extendStatics = function(d, b) {
69 extendStatics = Object.setPrototypeOf ||
70 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
71 function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
72 return extendStatics(d, b);
73};
74
75function __extends(d, b) {
76 if (typeof b !== "function" && b !== null)
77 throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
78 extendStatics(d, b);
79 function __() { this.constructor = d; }
80 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
81}
82
83var __assign = function() {
84 __assign = Object.assign || function __assign(t) {
85 for (var s, i = 1, n = arguments.length; i < n; i++) {
86 s = arguments[i];
87 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
88 }
89 return t;
90 };
91 return __assign.apply(this, arguments);
92};
93
94function __rest(s, e) {
95 var t = {};
96 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
97 t[p] = s[p];
98 if (s != null && typeof Object.getOwnPropertySymbols === "function")
99 for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
100 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
101 t[p[i]] = s[p[i]];
102 }
103 return t;
104}
105
106function __generator(thisArg, body) {
107 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
108 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
109 function verb(n) { return function (v) { return step([n, v]); }; }
110 function step(op) {
111 if (f) throw new TypeError("Generator is already executing.");
112 while (_) try {
113 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
114 if (y = 0, t) op = [op[0] & 2, t.value];
115 switch (op[0]) {
116 case 0: case 1: t = op; break;
117 case 4: _.label++; return { value: op[1], done: false };
118 case 5: _.label++; y = op[1]; op = [0]; continue;
119 case 7: op = _.ops.pop(); _.trys.pop(); continue;
120 default:
121 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
122 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
123 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
124 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
125 if (t[2]) _.ops.pop();
126 _.trys.pop(); continue;
127 }
128 op = body.call(thisArg, _);
129 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
130 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
131 }
132}
133
134function __values(o) {
135 var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
136 if (m) return m.call(o);
137 if (o && typeof o.length === "number") return {
138 next: function () {
139 if (o && i >= o.length) o = void 0;
140 return { value: o && o[i++], done: !o };
141 }
142 };
143 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
144}
145
146function __read(o, n) {
147 var m = typeof Symbol === "function" && o[Symbol.iterator];
148 if (!m) return o;
149 var i = m.call(o), r, ar = [], e;
150 try {
151 while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
152 }
153 catch (error) { e = { error: error }; }
154 finally {
155 try {
156 if (r && !r.done && (m = i["return"])) m.call(i);
157 }
158 finally { if (e) throw e.error; }
159 }
160 return ar;
161}
162
163/** @deprecated */
164function __spread() {
165 for (var ar = [], i = 0; i < arguments.length; i++)
166 ar = ar.concat(__read(arguments[i]));
167 return ar;
168}
169
170/**
171 * Returns the _actual_ type of the given tree node. (Or throws)
172 *
173 * @param object
174 * @returns
175 */
176function getType(object) {
177 assertIsStateTreeNode(object, 1);
178 return getStateTreeNode(object).type;
179}
180/**
181 * Returns the _declared_ type of the given sub property of an object, array or map.
182 * In the case of arrays and maps the property name is optional and will be ignored.
183 *
184 * Example:
185 * ```ts
186 * const Box = types.model({ x: 0, y: 0 })
187 * const box = Box.create()
188 *
189 * console.log(getChildType(box, "x").name) // 'number'
190 * ```
191 *
192 * @param object
193 * @param propertyName
194 * @returns
195 */
196function getChildType(object, propertyName) {
197 assertIsStateTreeNode(object, 1);
198 return getStateTreeNode(object).getChildType(propertyName);
199}
200/**
201 * Registers a function that will be invoked for each mutation that is applied to the provided model instance, or to any of its children.
202 * See [patches](https://github.com/mobxjs/mobx-state-tree#patches) for more details. onPatch events are emitted immediately and will not await the end of a transaction.
203 * Patches can be used to deep observe a model tree.
204 *
205 * @param target the model instance from which to receive patches
206 * @param callback the callback that is invoked for each patch. The reversePatch is a patch that would actually undo the emitted patch
207 * @returns function to remove the listener
208 */
209function onPatch(target, callback) {
210 // check all arguments
211 assertIsStateTreeNode(target, 1);
212 assertIsFunction(callback, 2);
213 return getStateTreeNode(target).onPatch(callback);
214}
215/**
216 * Registers a function that is invoked whenever a new snapshot for the given model instance is available.
217 * The listener will only be fire at the end of the current MobX (trans)action.
218 * See [snapshots](https://github.com/mobxjs/mobx-state-tree#snapshots) for more details.
219 *
220 * @param target
221 * @param callback
222 * @returns
223 */
224function onSnapshot(target, callback) {
225 // check all arguments
226 assertIsStateTreeNode(target, 1);
227 assertIsFunction(callback, 2);
228 return getStateTreeNode(target).onSnapshot(callback);
229}
230/**
231 * Applies a JSON-patch to the given model instance or bails out if the patch couldn't be applied
232 * See [patches](https://github.com/mobxjs/mobx-state-tree#patches) for more details.
233 *
234 * Can apply a single past, or an array of patches.
235 *
236 * @param target
237 * @param patch
238 * @returns
239 */
240function applyPatch(target, patch) {
241 // check all arguments
242 assertIsStateTreeNode(target, 1);
243 assertArg(patch, function (p) { return typeof p === "object"; }, "object or array", 2);
244 getStateTreeNode(target).applyPatches(asArray(patch));
245}
246/**
247 * Small abstraction around `onPatch` and `applyPatch`, attaches a patch listener to a tree and records all the patches.
248 * Returns an recorder object with the following signature:
249 *
250 * Example:
251 * ```ts
252 * export interface IPatchRecorder {
253 * // the recorded patches
254 * patches: IJsonPatch[]
255 * // the inverse of the recorded patches
256 * inversePatches: IJsonPatch[]
257 * // true if currently recording
258 * recording: boolean
259 * // stop recording patches
260 * stop(): void
261 * // resume recording patches
262 * resume(): void
263 * // apply all the recorded patches on the given target (the original subject if omitted)
264 * replay(target?: IAnyStateTreeNode): void
265 * // reverse apply the recorded patches on the given target (the original subject if omitted)
266 * // stops the recorder if not already stopped
267 * undo(): void
268 * }
269 * ```
270 *
271 * The optional filter function allows to skip recording certain patches.
272 *
273 * @param subject
274 * @param filter
275 * @returns
276 */
277function recordPatches(subject, filter) {
278 // check all arguments
279 assertIsStateTreeNode(subject, 1);
280 var data = {
281 patches: [],
282 reversedInversePatches: []
283 };
284 // we will generate the immutable copy of patches on demand for public consumption
285 var publicData = {};
286 var disposer;
287 var recorder = {
288 get recording() {
289 return !!disposer;
290 },
291 get patches() {
292 if (!publicData.patches) {
293 publicData.patches = data.patches.slice();
294 }
295 return publicData.patches;
296 },
297 get reversedInversePatches() {
298 if (!publicData.reversedInversePatches) {
299 publicData.reversedInversePatches = data.reversedInversePatches.slice();
300 }
301 return publicData.reversedInversePatches;
302 },
303 get inversePatches() {
304 if (!publicData.inversePatches) {
305 publicData.inversePatches = data.reversedInversePatches.slice().reverse();
306 }
307 return publicData.inversePatches;
308 },
309 stop: function () {
310 if (disposer) {
311 disposer();
312 disposer = undefined;
313 }
314 },
315 resume: function () {
316 if (disposer)
317 return;
318 disposer = onPatch(subject, function (patch, inversePatch) {
319 // skip patches that are asked to be filtered if there's a filter in place
320 if (filter && !filter(patch, inversePatch, getRunningActionContext())) {
321 return;
322 }
323 data.patches.push(patch);
324 data.reversedInversePatches.unshift(inversePatch);
325 // mark immutable public patches as dirty
326 publicData.patches = undefined;
327 publicData.inversePatches = undefined;
328 publicData.reversedInversePatches = undefined;
329 });
330 },
331 replay: function (target) {
332 applyPatch(target || subject, data.patches);
333 },
334 undo: function (target) {
335 applyPatch(target || subject, data.reversedInversePatches);
336 }
337 };
338 recorder.resume();
339 return recorder;
340}
341/**
342 * The inverse of `unprotect`.
343 *
344 * @param target
345 */
346function protect(target) {
347 // check all arguments
348 assertIsStateTreeNode(target, 1);
349 var node = getStateTreeNode(target);
350 if (!node.isRoot)
351 throw fail$1("`protect` can only be invoked on root nodes");
352 node.isProtectionEnabled = true;
353}
354/**
355 * By default it is not allowed to directly modify a model. Models can only be modified through actions.
356 * However, in some cases you don't care about the advantages (like replayability, traceability, etc) this yields.
357 * For example because you are building a PoC or don't have any middleware attached to your tree.
358 *
359 * In that case you can disable this protection by calling `unprotect` on the root of your tree.
360 *
361 * Example:
362 * ```ts
363 * const Todo = types.model({
364 * done: false
365 * }).actions(self => ({
366 * toggle() {
367 * self.done = !self.done
368 * }
369 * }))
370 *
371 * const todo = Todo.create()
372 * todo.done = true // throws!
373 * todo.toggle() // OK
374 * unprotect(todo)
375 * todo.done = false // OK
376 * ```
377 */
378function unprotect(target) {
379 // check all arguments
380 assertIsStateTreeNode(target, 1);
381 var node = getStateTreeNode(target);
382 if (!node.isRoot)
383 throw fail$1("`unprotect` can only be invoked on root nodes");
384 node.isProtectionEnabled = false;
385}
386/**
387 * Returns true if the object is in protected mode, @see protect
388 */
389function isProtected(target) {
390 return getStateTreeNode(target).isProtected;
391}
392/**
393 * Applies a snapshot to a given model instances. Patch and snapshot listeners will be invoked as usual.
394 *
395 * @param target
396 * @param snapshot
397 * @returns
398 */
399function applySnapshot(target, snapshot) {
400 // check all arguments
401 assertIsStateTreeNode(target, 1);
402 return getStateTreeNode(target).applySnapshot(snapshot);
403}
404/**
405 * Calculates a snapshot from the given model instance. The snapshot will always reflect the latest state but use
406 * structural sharing where possible. Doesn't require MobX transactions to be completed.
407 *
408 * @param target
409 * @param applyPostProcess If true (the default) then postProcessSnapshot gets applied.
410 * @returns
411 */
412function getSnapshot(target, applyPostProcess) {
413 if (applyPostProcess === void 0) { applyPostProcess = true; }
414 // check all arguments
415 assertIsStateTreeNode(target, 1);
416 var node = getStateTreeNode(target);
417 if (applyPostProcess)
418 return node.snapshot;
419 return freeze(node.type.getSnapshot(node, false));
420}
421/**
422 * Given a model instance, returns `true` if the object has a parent, that is, is part of another object, map or array.
423 *
424 * @param target
425 * @param depth How far should we look upward? 1 by default.
426 * @returns
427 */
428function hasParent(target, depth) {
429 if (depth === void 0) { depth = 1; }
430 // check all arguments
431 assertIsStateTreeNode(target, 1);
432 assertIsNumber(depth, 2, 0);
433 var parent = getStateTreeNode(target).parent;
434 while (parent) {
435 if (--depth === 0)
436 return true;
437 parent = parent.parent;
438 }
439 return false;
440}
441/**
442 * Returns the immediate parent of this object, or throws.
443 *
444 * Note that the immediate parent can be either an object, map or array, and
445 * doesn't necessarily refer to the parent model.
446 *
447 * Please note that in child nodes access to the root is only possible
448 * once the `afterAttach` hook has fired.
449 *
450 * @param target
451 * @param depth How far should we look upward? 1 by default.
452 * @returns
453 */
454function getParent(target, depth) {
455 if (depth === void 0) { depth = 1; }
456 // check all arguments
457 assertIsStateTreeNode(target, 1);
458 assertIsNumber(depth, 2, 0);
459 var d = depth;
460 var parent = getStateTreeNode(target).parent;
461 while (parent) {
462 if (--d === 0)
463 return parent.storedValue;
464 parent = parent.parent;
465 }
466 throw fail$1("Failed to find the parent of " + getStateTreeNode(target) + " at depth " + depth);
467}
468/**
469 * Given a model instance, returns `true` if the object has a parent of given type, that is, is part of another object, map or array
470 *
471 * @param target
472 * @param type
473 * @returns
474 */
475function hasParentOfType(target, type) {
476 // check all arguments
477 assertIsStateTreeNode(target, 1);
478 assertIsType(type, 2);
479 var parent = getStateTreeNode(target).parent;
480 while (parent) {
481 if (type.is(parent.storedValue))
482 return true;
483 parent = parent.parent;
484 }
485 return false;
486}
487/**
488 * Returns the target's parent of a given type, or throws.
489 *
490 * @param target
491 * @param type
492 * @returns
493 */
494function getParentOfType(target, type) {
495 // check all arguments
496 assertIsStateTreeNode(target, 1);
497 assertIsType(type, 2);
498 var parent = getStateTreeNode(target).parent;
499 while (parent) {
500 if (type.is(parent.storedValue))
501 return parent.storedValue;
502 parent = parent.parent;
503 }
504 throw fail$1("Failed to find the parent of " + getStateTreeNode(target) + " of a given type");
505}
506/**
507 * Given an object in a model tree, returns the root object of that tree.
508 *
509 * Please note that in child nodes access to the root is only possible
510 * once the `afterAttach` hook has fired.
511 *
512 * @param target
513 * @returns
514 */
515function getRoot(target) {
516 // check all arguments
517 assertIsStateTreeNode(target, 1);
518 return getStateTreeNode(target).root.storedValue;
519}
520/**
521 * Returns the path of the given object in the model tree
522 *
523 * @param target
524 * @returns
525 */
526function getPath(target) {
527 // check all arguments
528 assertIsStateTreeNode(target, 1);
529 return getStateTreeNode(target).path;
530}
531/**
532 * Returns the path of the given object as unescaped string array.
533 *
534 * @param target
535 * @returns
536 */
537function getPathParts(target) {
538 // check all arguments
539 assertIsStateTreeNode(target, 1);
540 return splitJsonPath(getStateTreeNode(target).path);
541}
542/**
543 * Returns true if the given object is the root of a model tree.
544 *
545 * @param target
546 * @returns
547 */
548function isRoot(target) {
549 // check all arguments
550 assertIsStateTreeNode(target, 1);
551 return getStateTreeNode(target).isRoot;
552}
553/**
554 * Resolves a path relatively to a given object.
555 * Returns undefined if no value can be found.
556 *
557 * @param target
558 * @param path escaped json path
559 * @returns
560 */
561function resolvePath(target, path) {
562 // check all arguments
563 assertIsStateTreeNode(target, 1);
564 assertIsString(path, 2);
565 var node = resolveNodeByPath(getStateTreeNode(target), path);
566 return node ? node.value : undefined;
567}
568/**
569 * Resolves a model instance given a root target, the type and the identifier you are searching for.
570 * Returns undefined if no value can be found.
571 *
572 * @param type
573 * @param target
574 * @param identifier
575 * @returns
576 */
577function resolveIdentifier(type, target, identifier) {
578 // check all arguments
579 assertIsType(type, 1);
580 assertIsStateTreeNode(target, 2);
581 assertIsValidIdentifier(identifier, 3);
582 var node = getStateTreeNode(target).root.identifierCache.resolve(type, normalizeIdentifier(identifier));
583 return node === null || node === void 0 ? void 0 : node.value;
584}
585/**
586 * Returns the identifier of the target node.
587 * This is the *string normalized* identifier, which might not match the type of the identifier attribute
588 *
589 * @param target
590 * @returns
591 */
592function getIdentifier(target) {
593 // check all arguments
594 assertIsStateTreeNode(target, 1);
595 return getStateTreeNode(target).identifier;
596}
597/**
598 * Tests if a reference is valid (pointing to an existing node and optionally if alive) and returns such reference if it the check passes,
599 * else it returns undefined.
600 *
601 * @param getter Function to access the reference.
602 * @param checkIfAlive true to also make sure the referenced node is alive (default), false to skip this check.
603 * @returns
604 */
605function tryReference(getter, checkIfAlive) {
606 if (checkIfAlive === void 0) { checkIfAlive = true; }
607 try {
608 var node = getter();
609 if (node === undefined || node === null) {
610 return undefined;
611 }
612 else if (isStateTreeNode(node)) {
613 if (!checkIfAlive) {
614 return node;
615 }
616 else {
617 return isAlive(node) ? node : undefined;
618 }
619 }
620 else {
621 throw fail$1("The reference to be checked is not one of node, null or undefined");
622 }
623 }
624 catch (e) {
625 if (e instanceof InvalidReferenceError) {
626 return undefined;
627 }
628 throw e;
629 }
630}
631/**
632 * Tests if a reference is valid (pointing to an existing node and optionally if alive) and returns if the check passes or not.
633 *
634 * @param getter Function to access the reference.
635 * @param checkIfAlive true to also make sure the referenced node is alive (default), false to skip this check.
636 * @returns
637 */
638function isValidReference(getter, checkIfAlive) {
639 if (checkIfAlive === void 0) { checkIfAlive = true; }
640 try {
641 var node = getter();
642 if (node === undefined || node === null) {
643 return false;
644 }
645 else if (isStateTreeNode(node)) {
646 return checkIfAlive ? isAlive(node) : true;
647 }
648 else {
649 throw fail$1("The reference to be checked is not one of node, null or undefined");
650 }
651 }
652 catch (e) {
653 if (e instanceof InvalidReferenceError) {
654 return false;
655 }
656 throw e;
657 }
658}
659/**
660 * Try to resolve a given path relative to a given node.
661 *
662 * @param target
663 * @param path
664 * @returns
665 */
666function tryResolve(target, path) {
667 // check all arguments
668 assertIsStateTreeNode(target, 1);
669 assertIsString(path, 2);
670 var node = resolveNodeByPath(getStateTreeNode(target), path, false);
671 if (node === undefined)
672 return undefined;
673 try {
674 return node.value;
675 }
676 catch (e) {
677 // For what ever reason not resolvable (e.g. totally not existing path, or value that cannot be fetched)
678 // see test / issue: 'try resolve doesn't work #686'
679 return undefined;
680 }
681}
682/**
683 * Given two state tree nodes that are part of the same tree,
684 * returns the shortest jsonpath needed to navigate from the one to the other
685 *
686 * @param base
687 * @param target
688 * @returns
689 */
690function getRelativePath(base, target) {
691 // check all arguments
692 assertIsStateTreeNode(base, 1);
693 assertIsStateTreeNode(target, 2);
694 return getRelativePathBetweenNodes(getStateTreeNode(base), getStateTreeNode(target));
695}
696/**
697 * Returns a deep copy of the given state tree node as new tree.
698 * Short hand for `snapshot(x) = getType(x).create(getSnapshot(x))`
699 *
700 * _Tip: clone will create a literal copy, including the same identifiers. To modify identifiers etc during cloning, don't use clone but take a snapshot of the tree, modify it, and create new instance_
701 *
702 * @param source
703 * @param keepEnvironment indicates whether the clone should inherit the same environment (`true`, the default), or not have an environment (`false`). If an object is passed in as second argument, that will act as the environment for the cloned tree.
704 * @returns
705 */
706function clone(source, keepEnvironment) {
707 if (keepEnvironment === void 0) { keepEnvironment = true; }
708 // check all arguments
709 assertIsStateTreeNode(source, 1);
710 var node = getStateTreeNode(source);
711 return node.type.create(node.snapshot, keepEnvironment === true
712 ? node.root.environment
713 : keepEnvironment === false
714 ? undefined
715 : keepEnvironment); // it's an object or something else
716}
717/**
718 * Removes a model element from the state tree, and let it live on as a new state tree
719 */
720function detach(target) {
721 // check all arguments
722 assertIsStateTreeNode(target, 1);
723 getStateTreeNode(target).detach();
724 return target;
725}
726/**
727 * Removes a model element from the state tree, and mark it as end-of-life; the element should not be used anymore
728 */
729function destroy(target) {
730 // check all arguments
731 assertIsStateTreeNode(target, 1);
732 var node = getStateTreeNode(target);
733 if (node.isRoot)
734 node.die();
735 else
736 node.parent.removeChild(node.subpath);
737}
738/**
739 * Returns true if the given state tree node is not killed yet.
740 * This means that the node is still a part of a tree, and that `destroy`
741 * has not been called. If a node is not alive anymore, the only thing one can do with it
742 * is requesting it's last path and snapshot
743 *
744 * @param target
745 * @returns
746 */
747function isAlive(target) {
748 // check all arguments
749 assertIsStateTreeNode(target, 1);
750 return getStateTreeNode(target).observableIsAlive;
751}
752/**
753 * Use this utility to register a function that should be called whenever the
754 * targeted state tree node is destroyed. This is a useful alternative to managing
755 * cleanup methods yourself using the `beforeDestroy` hook.
756 *
757 * This methods returns the same disposer that was passed as argument.
758 *
759 * Example:
760 * ```ts
761 * const Todo = types.model({
762 * title: types.string
763 * }).actions(self => ({
764 * afterCreate() {
765 * const autoSaveDisposer = reaction(
766 * () => getSnapshot(self),
767 * snapshot => sendSnapshotToServerSomehow(snapshot)
768 * )
769 * // stop sending updates to server if this
770 * // instance is destroyed
771 * addDisposer(self, autoSaveDisposer)
772 * }
773 * }))
774 * ```
775 *
776 * @param target
777 * @param disposer
778 * @returns The same disposer that was passed as argument
779 */
780function addDisposer(target, disposer) {
781 // check all arguments
782 assertIsStateTreeNode(target, 1);
783 assertIsFunction(disposer, 2);
784 var node = getStateTreeNode(target);
785 node.addDisposer(disposer);
786 return disposer;
787}
788/**
789 * Returns the environment of the current state tree. For more info on environments,
790 * see [Dependency injection](https://github.com/mobxjs/mobx-state-tree#dependency-injection)
791 *
792 * Please note that in child nodes access to the root is only possible
793 * once the `afterAttach` hook has fired
794 *
795 * Returns an empty environment if the tree wasn't initialized with an environment
796 *
797 * @param target
798 * @returns
799 */
800function getEnv(target) {
801 // check all arguments
802 assertIsStateTreeNode(target, 1);
803 var node = getStateTreeNode(target);
804 var env = node.root.environment;
805 if (!env)
806 return EMPTY_OBJECT;
807 return env;
808}
809/**
810 * Performs a depth first walk through a tree.
811 */
812function walk(target, processor) {
813 // check all arguments
814 assertIsStateTreeNode(target, 1);
815 assertIsFunction(processor, 2);
816 var node = getStateTreeNode(target);
817 // tslint:disable-next-line:no_unused-variable
818 node.getChildren().forEach(function (child) {
819 if (isStateTreeNode(child.storedValue))
820 walk(child.storedValue, processor);
821 });
822 processor(node.storedValue);
823}
824/**
825 * Returns a reflection of the model type properties and name for either a model type or model node.
826 *
827 * @param typeOrNode
828 * @returns
829 */
830function getPropertyMembers(typeOrNode) {
831 var type;
832 if (isStateTreeNode(typeOrNode)) {
833 type = getType(typeOrNode);
834 }
835 else {
836 type = typeOrNode;
837 }
838 assertArg(type, function (t) { return isModelType(t); }, "model type or model instance", 1);
839 return {
840 name: type.name,
841 properties: __assign({}, type.properties)
842 };
843}
844/**
845 * Returns a reflection of the model node, including name, properties, views, volatile and actions.
846 *
847 * @param target
848 * @returns
849 */
850function getMembers(target) {
851 var type = getStateTreeNode(target).type;
852 var reflected = __assign(__assign({}, getPropertyMembers(type)), { actions: [], volatile: [], views: [] });
853 var props = Object.getOwnPropertyNames(target);
854 props.forEach(function (key) {
855 if (key in reflected.properties)
856 return;
857 var descriptor = Object.getOwnPropertyDescriptor(target, key);
858 if (descriptor.get) {
859 if (mobx.isComputedProp(target, key))
860 reflected.views.push(key);
861 else
862 reflected.volatile.push(key);
863 return;
864 }
865 if (descriptor.value._isMSTAction === true)
866 reflected.actions.push(key);
867 else if (mobx.isObservableProp(target, key))
868 reflected.volatile.push(key);
869 else
870 reflected.views.push(key);
871 });
872 return reflected;
873}
874/**
875 * Casts a node snapshot or instance type to an instance type so it can be assigned to a type instance.
876 * Note that this is just a cast for the type system, this is, it won't actually convert a snapshot to an instance,
877 * but just fool typescript into thinking so.
878 * Either way, casting when outside an assignation operation won't compile.
879 *
880 * Example:
881 * ```ts
882 * const ModelA = types.model({
883 * n: types.number
884 * }).actions(self => ({
885 * setN(aNumber: number) {
886 * self.n = aNumber
887 * }
888 * }))
889 *
890 * const ModelB = types.model({
891 * innerModel: ModelA
892 * }).actions(self => ({
893 * someAction() {
894 * // this will allow the compiler to assign a snapshot to the property
895 * self.innerModel = cast({ a: 5 })
896 * }
897 * }))
898 * ```
899 *
900 * @param snapshotOrInstance Snapshot or instance
901 * @returns The same object casted as an instance
902 */
903function cast(snapshotOrInstance) {
904 return snapshotOrInstance;
905}
906/**
907 * Casts a node instance type to an snapshot type so it can be assigned to a type snapshot (e.g. to be used inside a create call).
908 * Note that this is just a cast for the type system, this is, it won't actually convert an instance to a snapshot,
909 * but just fool typescript into thinking so.
910 *
911 * Example:
912 * ```ts
913 * const ModelA = types.model({
914 * n: types.number
915 * }).actions(self => ({
916 * setN(aNumber: number) {
917 * self.n = aNumber
918 * }
919 * }))
920 *
921 * const ModelB = types.model({
922 * innerModel: ModelA
923 * })
924 *
925 * const a = ModelA.create({ n: 5 });
926 * // this will allow the compiler to use a model as if it were a snapshot
927 * const b = ModelB.create({ innerModel: castToSnapshot(a)})
928 * ```
929 *
930 * @param snapshotOrInstance Snapshot or instance
931 * @returns The same object casted as an input (creation) snapshot
932 */
933function castToSnapshot(snapshotOrInstance) {
934 return snapshotOrInstance;
935}
936/**
937 * Casts a node instance type to a reference snapshot type so it can be assigned to a refernence snapshot (e.g. to be used inside a create call).
938 * Note that this is just a cast for the type system, this is, it won't actually convert an instance to a refererence snapshot,
939 * but just fool typescript into thinking so.
940 *
941 * Example:
942 * ```ts
943 * const ModelA = types.model({
944 * id: types.identifier,
945 * n: types.number
946 * }).actions(self => ({
947 * setN(aNumber: number) {
948 * self.n = aNumber
949 * }
950 * }))
951 *
952 * const ModelB = types.model({
953 * refA: types.reference(ModelA)
954 * })
955 *
956 * const a = ModelA.create({ id: 'someId', n: 5 });
957 * // this will allow the compiler to use a model as if it were a reference snapshot
958 * const b = ModelB.create({ refA: castToReferenceSnapshot(a)})
959 * ```
960 *
961 * @param instance Instance
962 * @returns The same object casted as an reference snapshot (string or number)
963 */
964function castToReferenceSnapshot(instance) {
965 return instance;
966}
967/**
968 * Returns the unique node id (not to be confused with the instance identifier) for a
969 * given instance.
970 * This id is a number that is unique for each instance.
971 *
972 * @export
973 * @param target
974 * @returns
975 */
976function getNodeId(target) {
977 assertIsStateTreeNode(target, 1);
978 return getStateTreeNode(target).nodeId;
979}
980
981/**
982 * @internal
983 * @hidden
984 */
985var BaseNode = /** @class */ (function () {
986 function BaseNode(type, parent, subpath, environment) {
987 Object.defineProperty(this, "type", {
988 enumerable: true,
989 configurable: true,
990 writable: true,
991 value: type
992 });
993 Object.defineProperty(this, "environment", {
994 enumerable: true,
995 configurable: true,
996 writable: true,
997 value: environment
998 });
999 Object.defineProperty(this, "_escapedSubpath", {
1000 enumerable: true,
1001 configurable: true,
1002 writable: true,
1003 value: void 0
1004 });
1005 Object.defineProperty(this, "_subpath", {
1006 enumerable: true,
1007 configurable: true,
1008 writable: true,
1009 value: void 0
1010 });
1011 Object.defineProperty(this, "_subpathUponDeath", {
1012 enumerable: true,
1013 configurable: true,
1014 writable: true,
1015 value: void 0
1016 });
1017 Object.defineProperty(this, "_pathUponDeath", {
1018 enumerable: true,
1019 configurable: true,
1020 writable: true,
1021 value: void 0
1022 });
1023 Object.defineProperty(this, "storedValue", {
1024 enumerable: true,
1025 configurable: true,
1026 writable: true,
1027 value: void 0
1028 }); // usually the same type as the value, but not always (such as with references)
1029 Object.defineProperty(this, "aliveAtom", {
1030 enumerable: true,
1031 configurable: true,
1032 writable: true,
1033 value: void 0
1034 });
1035 Object.defineProperty(this, "_state", {
1036 enumerable: true,
1037 configurable: true,
1038 writable: true,
1039 value: NodeLifeCycle.INITIALIZING
1040 });
1041 Object.defineProperty(this, "_hookSubscribers", {
1042 enumerable: true,
1043 configurable: true,
1044 writable: true,
1045 value: void 0
1046 });
1047 Object.defineProperty(this, "_parent", {
1048 enumerable: true,
1049 configurable: true,
1050 writable: true,
1051 value: void 0
1052 });
1053 Object.defineProperty(this, "pathAtom", {
1054 enumerable: true,
1055 configurable: true,
1056 writable: true,
1057 value: void 0
1058 });
1059 this.environment = environment;
1060 this.baseSetParent(parent, subpath);
1061 }
1062 Object.defineProperty(BaseNode.prototype, "subpath", {
1063 get: function () {
1064 return this._subpath;
1065 },
1066 enumerable: false,
1067 configurable: true
1068 });
1069 Object.defineProperty(BaseNode.prototype, "subpathUponDeath", {
1070 get: function () {
1071 return this._subpathUponDeath;
1072 },
1073 enumerable: false,
1074 configurable: true
1075 });
1076 Object.defineProperty(BaseNode.prototype, "pathUponDeath", {
1077 get: function () {
1078 return this._pathUponDeath;
1079 },
1080 enumerable: false,
1081 configurable: true
1082 });
1083 Object.defineProperty(BaseNode.prototype, "value", {
1084 get: function () {
1085 return this.type.getValue(this);
1086 },
1087 enumerable: false,
1088 configurable: true
1089 });
1090 Object.defineProperty(BaseNode.prototype, "state", {
1091 get: function () {
1092 return this._state;
1093 },
1094 set: function (val) {
1095 var wasAlive = this.isAlive;
1096 this._state = val;
1097 var isAlive = this.isAlive;
1098 if (this.aliveAtom && wasAlive !== isAlive) {
1099 this.aliveAtom.reportChanged();
1100 }
1101 },
1102 enumerable: false,
1103 configurable: true
1104 });
1105 Object.defineProperty(BaseNode.prototype, "fireInternalHook", {
1106 enumerable: false,
1107 configurable: true,
1108 writable: true,
1109 value: function (name) {
1110 if (this._hookSubscribers) {
1111 this._hookSubscribers.emit(name, this, name);
1112 }
1113 }
1114 });
1115 Object.defineProperty(BaseNode.prototype, "registerHook", {
1116 enumerable: false,
1117 configurable: true,
1118 writable: true,
1119 value: function (hook, hookHandler) {
1120 if (!this._hookSubscribers) {
1121 this._hookSubscribers = new EventHandlers();
1122 }
1123 return this._hookSubscribers.register(hook, hookHandler);
1124 }
1125 });
1126 Object.defineProperty(BaseNode.prototype, "parent", {
1127 get: function () {
1128 return this._parent;
1129 },
1130 enumerable: false,
1131 configurable: true
1132 });
1133 Object.defineProperty(BaseNode.prototype, "getReconciliationType", {
1134 enumerable: false,
1135 configurable: true,
1136 writable: true,
1137 value: function () {
1138 return this.type;
1139 }
1140 });
1141 Object.defineProperty(BaseNode.prototype, "baseSetParent", {
1142 enumerable: false,
1143 configurable: true,
1144 writable: true,
1145 value: function (parent, subpath) {
1146 this._parent = parent;
1147 this._subpath = subpath;
1148 this._escapedSubpath = undefined; // regenerate when needed
1149 if (this.pathAtom) {
1150 this.pathAtom.reportChanged();
1151 }
1152 }
1153 });
1154 Object.defineProperty(BaseNode.prototype, "path", {
1155 /*
1156 * Returns (escaped) path representation as string
1157 */
1158 get: function () {
1159 return this.getEscapedPath(true);
1160 },
1161 enumerable: false,
1162 configurable: true
1163 });
1164 Object.defineProperty(BaseNode.prototype, "getEscapedPath", {
1165 enumerable: false,
1166 configurable: true,
1167 writable: true,
1168 value: function (reportObserved) {
1169 if (reportObserved) {
1170 if (!this.pathAtom) {
1171 this.pathAtom = mobx.createAtom("path");
1172 }
1173 this.pathAtom.reportObserved();
1174 }
1175 if (!this.parent)
1176 return "";
1177 // regenerate escaped subpath if needed
1178 if (this._escapedSubpath === undefined) {
1179 this._escapedSubpath = !this._subpath ? "" : escapeJsonPath(this._subpath);
1180 }
1181 return this.parent.getEscapedPath(reportObserved) + "/" + this._escapedSubpath;
1182 }
1183 });
1184 Object.defineProperty(BaseNode.prototype, "isRoot", {
1185 get: function () {
1186 return this.parent === null;
1187 },
1188 enumerable: false,
1189 configurable: true
1190 });
1191 Object.defineProperty(BaseNode.prototype, "isAlive", {
1192 get: function () {
1193 return this.state !== NodeLifeCycle.DEAD;
1194 },
1195 enumerable: false,
1196 configurable: true
1197 });
1198 Object.defineProperty(BaseNode.prototype, "isDetaching", {
1199 get: function () {
1200 return this.state === NodeLifeCycle.DETACHING;
1201 },
1202 enumerable: false,
1203 configurable: true
1204 });
1205 Object.defineProperty(BaseNode.prototype, "observableIsAlive", {
1206 get: function () {
1207 if (!this.aliveAtom) {
1208 this.aliveAtom = mobx.createAtom("alive");
1209 }
1210 this.aliveAtom.reportObserved();
1211 return this.isAlive;
1212 },
1213 enumerable: false,
1214 configurable: true
1215 });
1216 Object.defineProperty(BaseNode.prototype, "baseFinalizeCreation", {
1217 enumerable: false,
1218 configurable: true,
1219 writable: true,
1220 value: function (whenFinalized) {
1221 if (devMode()) {
1222 if (!this.isAlive) {
1223 // istanbul ignore next
1224 throw fail("assertion failed: cannot finalize the creation of a node that is already dead");
1225 }
1226 }
1227 // goal: afterCreate hooks runs depth-first. After attach runs parent first, so on afterAttach the parent has completed already
1228 if (this.state === NodeLifeCycle.CREATED) {
1229 if (this.parent) {
1230 if (this.parent.state !== NodeLifeCycle.FINALIZED) {
1231 // parent not ready yet, postpone
1232 return;
1233 }
1234 this.fireHook(Hook.afterAttach);
1235 }
1236 this.state = NodeLifeCycle.FINALIZED;
1237 if (whenFinalized) {
1238 whenFinalized();
1239 }
1240 }
1241 }
1242 });
1243 Object.defineProperty(BaseNode.prototype, "baseFinalizeDeath", {
1244 enumerable: false,
1245 configurable: true,
1246 writable: true,
1247 value: function () {
1248 if (this._hookSubscribers) {
1249 this._hookSubscribers.clearAll();
1250 }
1251 this._subpathUponDeath = this._subpath;
1252 this._pathUponDeath = this.getEscapedPath(false);
1253 this.baseSetParent(null, "");
1254 this.state = NodeLifeCycle.DEAD;
1255 }
1256 });
1257 Object.defineProperty(BaseNode.prototype, "baseAboutToDie", {
1258 enumerable: false,
1259 configurable: true,
1260 writable: true,
1261 value: function () {
1262 this.fireHook(Hook.beforeDestroy);
1263 }
1264 });
1265 return BaseNode;
1266}());
1267
1268/**
1269 * @internal
1270 * @hidden
1271 */
1272var ScalarNode = /** @class */ (function (_super) {
1273 __extends(ScalarNode, _super);
1274 function ScalarNode(simpleType, parent, subpath, environment, initialSnapshot) {
1275 var _this = _super.call(this, simpleType, parent, subpath, environment) || this;
1276 try {
1277 _this.storedValue = simpleType.createNewInstance(initialSnapshot);
1278 }
1279 catch (e) {
1280 // short-cut to die the instance, to avoid the snapshot computed starting to throw...
1281 _this.state = NodeLifeCycle.DEAD;
1282 throw e;
1283 }
1284 _this.state = NodeLifeCycle.CREATED;
1285 // for scalar nodes there's no point in firing this event since it would fire on the constructor, before
1286 // anybody can actually register for/listen to it
1287 // this.fireHook(Hook.AfterCreate)
1288 _this.finalizeCreation();
1289 return _this;
1290 }
1291 Object.defineProperty(ScalarNode.prototype, "root", {
1292 get: function () {
1293 // future optimization: store root ref in the node and maintain it
1294 if (!this.parent)
1295 throw fail$1("This scalar node is not part of a tree");
1296 return this.parent.root;
1297 },
1298 enumerable: false,
1299 configurable: true
1300 });
1301 Object.defineProperty(ScalarNode.prototype, "setParent", {
1302 enumerable: false,
1303 configurable: true,
1304 writable: true,
1305 value: function (newParent, subpath) {
1306 var parentChanged = this.parent !== newParent;
1307 var subpathChanged = this.subpath !== subpath;
1308 if (!parentChanged && !subpathChanged) {
1309 return;
1310 }
1311 if (devMode()) {
1312 if (!subpath) {
1313 // istanbul ignore next
1314 throw fail$1("assertion failed: subpath expected");
1315 }
1316 if (!newParent) {
1317 // istanbul ignore next
1318 throw fail$1("assertion failed: parent expected");
1319 }
1320 if (parentChanged) {
1321 // istanbul ignore next
1322 throw fail$1("assertion failed: scalar nodes cannot change their parent");
1323 }
1324 }
1325 this.environment = undefined; // use parent's
1326 this.baseSetParent(this.parent, subpath);
1327 }
1328 });
1329 Object.defineProperty(ScalarNode.prototype, "snapshot", {
1330 get: function () {
1331 return freeze(this.getSnapshot());
1332 },
1333 enumerable: false,
1334 configurable: true
1335 });
1336 Object.defineProperty(ScalarNode.prototype, "getSnapshot", {
1337 enumerable: false,
1338 configurable: true,
1339 writable: true,
1340 value: function () {
1341 return this.type.getSnapshot(this);
1342 }
1343 });
1344 Object.defineProperty(ScalarNode.prototype, "toString", {
1345 enumerable: false,
1346 configurable: true,
1347 writable: true,
1348 value: function () {
1349 var path = (this.isAlive ? this.path : this.pathUponDeath) || "<root>";
1350 return this.type.name + "@" + path + (this.isAlive ? "" : " [dead]");
1351 }
1352 });
1353 Object.defineProperty(ScalarNode.prototype, "die", {
1354 enumerable: false,
1355 configurable: true,
1356 writable: true,
1357 value: function () {
1358 if (!this.isAlive || this.state === NodeLifeCycle.DETACHING)
1359 return;
1360 this.aboutToDie();
1361 this.finalizeDeath();
1362 }
1363 });
1364 Object.defineProperty(ScalarNode.prototype, "finalizeCreation", {
1365 enumerable: false,
1366 configurable: true,
1367 writable: true,
1368 value: function () {
1369 this.baseFinalizeCreation();
1370 }
1371 });
1372 Object.defineProperty(ScalarNode.prototype, "aboutToDie", {
1373 enumerable: false,
1374 configurable: true,
1375 writable: true,
1376 value: function () {
1377 this.baseAboutToDie();
1378 }
1379 });
1380 Object.defineProperty(ScalarNode.prototype, "finalizeDeath", {
1381 enumerable: false,
1382 configurable: true,
1383 writable: true,
1384 value: function () {
1385 this.baseFinalizeDeath();
1386 }
1387 });
1388 Object.defineProperty(ScalarNode.prototype, "fireHook", {
1389 enumerable: false,
1390 configurable: true,
1391 writable: true,
1392 value: function (name) {
1393 this.fireInternalHook(name);
1394 }
1395 });
1396 return ScalarNode;
1397}(BaseNode));
1398ScalarNode.prototype.die = mobx.action(ScalarNode.prototype.die);
1399
1400var nextNodeId = 1;
1401var snapshotReactionOptions = {
1402 onError: function (e) {
1403 throw e;
1404 }
1405};
1406/**
1407 * @internal
1408 * @hidden
1409 */
1410var ObjectNode = /** @class */ (function (_super) {
1411 __extends(ObjectNode, _super);
1412 function ObjectNode(complexType, parent, subpath, environment, initialValue) {
1413 var _this = _super.call(this, complexType, parent, subpath, environment) || this;
1414 Object.defineProperty(_this, "nodeId", {
1415 enumerable: true,
1416 configurable: true,
1417 writable: true,
1418 value: ++nextNodeId
1419 });
1420 Object.defineProperty(_this, "identifierAttribute", {
1421 enumerable: true,
1422 configurable: true,
1423 writable: true,
1424 value: void 0
1425 });
1426 Object.defineProperty(_this, "identifier", {
1427 enumerable: true,
1428 configurable: true,
1429 writable: true,
1430 value: void 0
1431 }); // Identifier is always normalized to string, even if the identifier property isn't
1432 Object.defineProperty(_this, "unnormalizedIdentifier", {
1433 enumerable: true,
1434 configurable: true,
1435 writable: true,
1436 value: void 0
1437 });
1438 Object.defineProperty(_this, "identifierCache", {
1439 enumerable: true,
1440 configurable: true,
1441 writable: true,
1442 value: void 0
1443 });
1444 Object.defineProperty(_this, "isProtectionEnabled", {
1445 enumerable: true,
1446 configurable: true,
1447 writable: true,
1448 value: true
1449 });
1450 Object.defineProperty(_this, "middlewares", {
1451 enumerable: true,
1452 configurable: true,
1453 writable: true,
1454 value: void 0
1455 });
1456 Object.defineProperty(_this, "_applyPatches", {
1457 enumerable: true,
1458 configurable: true,
1459 writable: true,
1460 value: void 0
1461 });
1462 Object.defineProperty(_this, "_applySnapshot", {
1463 enumerable: true,
1464 configurable: true,
1465 writable: true,
1466 value: void 0
1467 });
1468 Object.defineProperty(_this, "_autoUnbox", {
1469 enumerable: true,
1470 configurable: true,
1471 writable: true,
1472 value: true
1473 }); // unboxing is disabled when reading child nodes
1474 Object.defineProperty(_this, "_isRunningAction", {
1475 enumerable: true,
1476 configurable: true,
1477 writable: true,
1478 value: false
1479 }); // only relevant for root
1480 Object.defineProperty(_this, "_hasSnapshotReaction", {
1481 enumerable: true,
1482 configurable: true,
1483 writable: true,
1484 value: false
1485 });
1486 Object.defineProperty(_this, "_observableInstanceState", {
1487 enumerable: true,
1488 configurable: true,
1489 writable: true,
1490 value: 0 /* UNINITIALIZED */
1491 });
1492 Object.defineProperty(_this, "_childNodes", {
1493 enumerable: true,
1494 configurable: true,
1495 writable: true,
1496 value: void 0
1497 });
1498 Object.defineProperty(_this, "_initialSnapshot", {
1499 enumerable: true,
1500 configurable: true,
1501 writable: true,
1502 value: void 0
1503 });
1504 Object.defineProperty(_this, "_cachedInitialSnapshot", {
1505 enumerable: true,
1506 configurable: true,
1507 writable: true,
1508 value: void 0
1509 });
1510 Object.defineProperty(_this, "_cachedInitialSnapshotCreated", {
1511 enumerable: true,
1512 configurable: true,
1513 writable: true,
1514 value: false
1515 });
1516 Object.defineProperty(_this, "_snapshotComputed", {
1517 enumerable: true,
1518 configurable: true,
1519 writable: true,
1520 value: void 0
1521 });
1522 Object.defineProperty(_this, "_snapshotUponDeath", {
1523 enumerable: true,
1524 configurable: true,
1525 writable: true,
1526 value: void 0
1527 });
1528 // #region internal event handling
1529 Object.defineProperty(_this, "_internalEvents", {
1530 enumerable: true,
1531 configurable: true,
1532 writable: true,
1533 value: void 0
1534 });
1535 _this._snapshotComputed = mobx.computed(function () { return freeze(_this.getSnapshot()); });
1536 _this.unbox = _this.unbox.bind(_this);
1537 _this._initialSnapshot = freeze(initialValue);
1538 _this.identifierAttribute = complexType.identifierAttribute;
1539 if (!parent) {
1540 _this.identifierCache = new IdentifierCache();
1541 }
1542 _this._childNodes = complexType.initializeChildNodes(_this, _this._initialSnapshot);
1543 // identifier can not be changed during lifecycle of a node
1544 // so we safely can read it from initial snapshot
1545 _this.identifier = null;
1546 _this.unnormalizedIdentifier = null;
1547 if (_this.identifierAttribute && _this._initialSnapshot) {
1548 var id = _this._initialSnapshot[_this.identifierAttribute];
1549 if (id === undefined) {
1550 // try with the actual node if not (for optional identifiers)
1551 var childNode = _this._childNodes[_this.identifierAttribute];
1552 if (childNode) {
1553 id = childNode.value;
1554 }
1555 }
1556 if (typeof id !== "string" && typeof id !== "number") {
1557 throw fail$1("Instance identifier '" + _this.identifierAttribute + "' for type '" + _this.type.name + "' must be a string or a number");
1558 }
1559 // normalize internal identifier to string
1560 _this.identifier = normalizeIdentifier(id);
1561 _this.unnormalizedIdentifier = id;
1562 }
1563 if (!parent) {
1564 _this.identifierCache.addNodeToCache(_this);
1565 }
1566 else {
1567 parent.root.identifierCache.addNodeToCache(_this);
1568 }
1569 return _this;
1570 }
1571 Object.defineProperty(ObjectNode.prototype, "applyPatches", {
1572 enumerable: false,
1573 configurable: true,
1574 writable: true,
1575 value: function (patches) {
1576 this.createObservableInstanceIfNeeded();
1577 this._applyPatches(patches);
1578 }
1579 });
1580 Object.defineProperty(ObjectNode.prototype, "applySnapshot", {
1581 enumerable: false,
1582 configurable: true,
1583 writable: true,
1584 value: function (snapshot) {
1585 this.createObservableInstanceIfNeeded();
1586 this._applySnapshot(snapshot);
1587 }
1588 });
1589 Object.defineProperty(ObjectNode.prototype, "createObservableInstanceIfNeeded", {
1590 enumerable: false,
1591 configurable: true,
1592 writable: true,
1593 value: function () {
1594 if (this._observableInstanceState === 0 /* UNINITIALIZED */) {
1595 this.createObservableInstance();
1596 }
1597 }
1598 });
1599 Object.defineProperty(ObjectNode.prototype, "createObservableInstance", {
1600 enumerable: false,
1601 configurable: true,
1602 writable: true,
1603 value: function () {
1604 var e_1, _a;
1605 if (devMode()) {
1606 if (this.state !== NodeLifeCycle.INITIALIZING) {
1607 // istanbul ignore next
1608 throw fail$1("assertion failed: the creation of the observable instance must be done on the initializing phase");
1609 }
1610 }
1611 this._observableInstanceState = 1 /* CREATING */;
1612 // make sure the parent chain is created as well
1613 // array with parent chain from parent to child
1614 var parentChain = [];
1615 var parent = this.parent;
1616 // for performance reasons we never go back further than the most direct
1617 // uninitialized parent
1618 // this is done to avoid traversing the whole tree to the root when using
1619 // the same reference again
1620 while (parent &&
1621 parent._observableInstanceState === 0 /* UNINITIALIZED */) {
1622 parentChain.unshift(parent);
1623 parent = parent.parent;
1624 }
1625 try {
1626 // initialize the uninitialized parent chain from parent to child
1627 for (var parentChain_1 = __values(parentChain), parentChain_1_1 = parentChain_1.next(); !parentChain_1_1.done; parentChain_1_1 = parentChain_1.next()) {
1628 var p = parentChain_1_1.value;
1629 p.createObservableInstanceIfNeeded();
1630 }
1631 }
1632 catch (e_1_1) { e_1 = { error: e_1_1 }; }
1633 finally {
1634 try {
1635 if (parentChain_1_1 && !parentChain_1_1.done && (_a = parentChain_1.return)) _a.call(parentChain_1);
1636 }
1637 finally { if (e_1) throw e_1.error; }
1638 }
1639 var type = this.type;
1640 try {
1641 this.storedValue = type.createNewInstance(this._childNodes);
1642 this.preboot();
1643 this._isRunningAction = true;
1644 type.finalizeNewInstance(this, this.storedValue);
1645 }
1646 catch (e) {
1647 // short-cut to die the instance, to avoid the snapshot computed starting to throw...
1648 this.state = NodeLifeCycle.DEAD;
1649 throw e;
1650 }
1651 finally {
1652 this._isRunningAction = false;
1653 }
1654 this._observableInstanceState = 2 /* CREATED */;
1655 this._snapshotComputed.trackAndCompute();
1656 if (this.isRoot)
1657 this._addSnapshotReaction();
1658 this._childNodes = EMPTY_OBJECT;
1659 this.state = NodeLifeCycle.CREATED;
1660 this.fireHook(Hook.afterCreate);
1661 this.finalizeCreation();
1662 }
1663 });
1664 Object.defineProperty(ObjectNode.prototype, "root", {
1665 get: function () {
1666 var parent = this.parent;
1667 return parent ? parent.root : this;
1668 },
1669 enumerable: false,
1670 configurable: true
1671 });
1672 Object.defineProperty(ObjectNode.prototype, "clearParent", {
1673 enumerable: false,
1674 configurable: true,
1675 writable: true,
1676 value: function () {
1677 if (!this.parent)
1678 return;
1679 // detach if attached
1680 this.fireHook(Hook.beforeDetach);
1681 var previousState = this.state;
1682 this.state = NodeLifeCycle.DETACHING;
1683 var root = this.root;
1684 var newEnv = root.environment;
1685 var newIdCache = root.identifierCache.splitCache(this);
1686 try {
1687 this.parent.removeChild(this.subpath);
1688 this.baseSetParent(null, "");
1689 this.environment = newEnv;
1690 this.identifierCache = newIdCache;
1691 }
1692 finally {
1693 this.state = previousState;
1694 }
1695 }
1696 });
1697 Object.defineProperty(ObjectNode.prototype, "setParent", {
1698 enumerable: false,
1699 configurable: true,
1700 writable: true,
1701 value: function (newParent, subpath) {
1702 var parentChanged = newParent !== this.parent;
1703 var subpathChanged = subpath !== this.subpath;
1704 if (!parentChanged && !subpathChanged) {
1705 return;
1706 }
1707 if (devMode()) {
1708 if (!subpath) {
1709 // istanbul ignore next
1710 throw fail$1("assertion failed: subpath expected");
1711 }
1712 if (!newParent) {
1713 // istanbul ignore next
1714 throw fail$1("assertion failed: new parent expected");
1715 }
1716 if (this.parent && parentChanged) {
1717 throw fail$1("A node cannot exists twice in the state tree. Failed to add " + this + " to path '" + newParent.path + "/" + subpath + "'.");
1718 }
1719 if (!this.parent && newParent.root === this) {
1720 throw fail$1("A state tree is not allowed to contain itself. Cannot assign " + this + " to path '" + newParent.path + "/" + subpath + "'");
1721 }
1722 if (!this.parent &&
1723 !!this.environment &&
1724 this.environment !== newParent.root.environment) {
1725 throw fail$1("A state tree cannot be made part of another state tree as long as their environments are different.");
1726 }
1727 }
1728 if (parentChanged) {
1729 // attach to new parent
1730 this.environment = undefined; // will use root's
1731 newParent.root.identifierCache.mergeCache(this);
1732 this.baseSetParent(newParent, subpath);
1733 this.fireHook(Hook.afterAttach);
1734 }
1735 else if (subpathChanged) {
1736 // moving to a new subpath on the same parent
1737 this.baseSetParent(this.parent, subpath);
1738 }
1739 }
1740 });
1741 Object.defineProperty(ObjectNode.prototype, "fireHook", {
1742 enumerable: false,
1743 configurable: true,
1744 writable: true,
1745 value: function (name) {
1746 var _this = this;
1747 this.fireInternalHook(name);
1748 var fn = this.storedValue &&
1749 typeof this.storedValue === "object" &&
1750 this.storedValue[name];
1751 if (typeof fn === "function") {
1752 // we check for it to allow old mobx peer dependencies that don't have the method to work (even when still bugged)
1753 if (mobx._allowStateChangesInsideComputed) {
1754 mobx._allowStateChangesInsideComputed(function () {
1755 fn.apply(_this.storedValue);
1756 });
1757 }
1758 else {
1759 fn.apply(this.storedValue);
1760 }
1761 }
1762 }
1763 });
1764 Object.defineProperty(ObjectNode.prototype, "snapshot", {
1765 // advantage of using computed for a snapshot is that nicely respects transactions etc.
1766 get: function () {
1767 return this._snapshotComputed.get();
1768 },
1769 enumerable: false,
1770 configurable: true
1771 });
1772 // NOTE: we use this method to get snapshot without creating @computed overhead
1773 Object.defineProperty(ObjectNode.prototype, "getSnapshot", {
1774 enumerable: false,
1775 configurable: true,
1776 writable: true,
1777 value: function () {
1778 if (!this.isAlive)
1779 return this._snapshotUponDeath;
1780 return this._observableInstanceState === 2 /* CREATED */
1781 ? this._getActualSnapshot()
1782 : this._getCachedInitialSnapshot();
1783 }
1784 });
1785 Object.defineProperty(ObjectNode.prototype, "_getActualSnapshot", {
1786 enumerable: false,
1787 configurable: true,
1788 writable: true,
1789 value: function () {
1790 return this.type.getSnapshot(this);
1791 }
1792 });
1793 Object.defineProperty(ObjectNode.prototype, "_getCachedInitialSnapshot", {
1794 enumerable: false,
1795 configurable: true,
1796 writable: true,
1797 value: function () {
1798 if (!this._cachedInitialSnapshotCreated) {
1799 var type = this.type;
1800 var childNodes = this._childNodes;
1801 var snapshot = this._initialSnapshot;
1802 this._cachedInitialSnapshot = type.processInitialSnapshot(childNodes, snapshot);
1803 this._cachedInitialSnapshotCreated = true;
1804 }
1805 return this._cachedInitialSnapshot;
1806 }
1807 });
1808 Object.defineProperty(ObjectNode.prototype, "isRunningAction", {
1809 enumerable: false,
1810 configurable: true,
1811 writable: true,
1812 value: function () {
1813 if (this._isRunningAction)
1814 return true;
1815 if (this.isRoot)
1816 return false;
1817 return this.parent.isRunningAction();
1818 }
1819 });
1820 Object.defineProperty(ObjectNode.prototype, "assertAlive", {
1821 enumerable: false,
1822 configurable: true,
1823 writable: true,
1824 value: function (context) {
1825 var livelinessChecking = getLivelinessChecking();
1826 if (!this.isAlive && livelinessChecking !== "ignore") {
1827 var error = this._getAssertAliveError(context);
1828 switch (livelinessChecking) {
1829 case "error":
1830 throw fail$1(error);
1831 case "warn":
1832 warnError(error);
1833 }
1834 }
1835 }
1836 });
1837 Object.defineProperty(ObjectNode.prototype, "_getAssertAliveError", {
1838 enumerable: false,
1839 configurable: true,
1840 writable: true,
1841 value: function (context) {
1842 var escapedPath = this.getEscapedPath(false) || this.pathUponDeath || "";
1843 var subpath = (context.subpath && escapeJsonPath(context.subpath)) || "";
1844 var actionContext = context.actionContext || getCurrentActionContext();
1845 // try to use a real action context if possible since it includes the action name
1846 if (actionContext && actionContext.type !== "action" && actionContext.parentActionEvent) {
1847 actionContext = actionContext.parentActionEvent;
1848 }
1849 var actionFullPath = "";
1850 if (actionContext && actionContext.name != null) {
1851 // try to use the context, and if it not available use the node one
1852 var actionPath = (actionContext && actionContext.context && getPath(actionContext.context)) ||
1853 escapedPath;
1854 actionFullPath = actionPath + "." + actionContext.name + "()";
1855 }
1856 return "You are trying to read or write to an object that is no longer part of a state tree. (Object type: '" + this.type.name + "', Path upon death: '" + escapedPath + "', Subpath: '" + subpath + "', Action: '" + actionFullPath + "'). Either detach nodes first, or don't use objects after removing / replacing them in the tree.";
1857 }
1858 });
1859 Object.defineProperty(ObjectNode.prototype, "getChildNode", {
1860 enumerable: false,
1861 configurable: true,
1862 writable: true,
1863 value: function (subpath) {
1864 this.assertAlive({
1865 subpath: subpath
1866 });
1867 this._autoUnbox = false;
1868 try {
1869 return this._observableInstanceState === 2 /* CREATED */
1870 ? this.type.getChildNode(this, subpath)
1871 : this._childNodes[subpath];
1872 }
1873 finally {
1874 this._autoUnbox = true;
1875 }
1876 }
1877 });
1878 Object.defineProperty(ObjectNode.prototype, "getChildren", {
1879 enumerable: false,
1880 configurable: true,
1881 writable: true,
1882 value: function () {
1883 this.assertAlive(EMPTY_OBJECT);
1884 this._autoUnbox = false;
1885 try {
1886 return this._observableInstanceState === 2 /* CREATED */
1887 ? this.type.getChildren(this)
1888 : convertChildNodesToArray(this._childNodes);
1889 }
1890 finally {
1891 this._autoUnbox = true;
1892 }
1893 }
1894 });
1895 Object.defineProperty(ObjectNode.prototype, "getChildType", {
1896 enumerable: false,
1897 configurable: true,
1898 writable: true,
1899 value: function (propertyName) {
1900 return this.type.getChildType(propertyName);
1901 }
1902 });
1903 Object.defineProperty(ObjectNode.prototype, "isProtected", {
1904 get: function () {
1905 return this.root.isProtectionEnabled;
1906 },
1907 enumerable: false,
1908 configurable: true
1909 });
1910 Object.defineProperty(ObjectNode.prototype, "assertWritable", {
1911 enumerable: false,
1912 configurable: true,
1913 writable: true,
1914 value: function (context) {
1915 this.assertAlive(context);
1916 if (!this.isRunningAction() && this.isProtected) {
1917 throw fail$1("Cannot modify '" + this + "', the object is protected and can only be modified by using an action.");
1918 }
1919 }
1920 });
1921 Object.defineProperty(ObjectNode.prototype, "removeChild", {
1922 enumerable: false,
1923 configurable: true,
1924 writable: true,
1925 value: function (subpath) {
1926 this.type.removeChild(this, subpath);
1927 }
1928 });
1929 // bound on the constructor
1930 Object.defineProperty(ObjectNode.prototype, "unbox", {
1931 enumerable: false,
1932 configurable: true,
1933 writable: true,
1934 value: function (childNode) {
1935 if (!childNode)
1936 return childNode;
1937 this.assertAlive({
1938 subpath: childNode.subpath || childNode.subpathUponDeath
1939 });
1940 return this._autoUnbox ? childNode.value : childNode;
1941 }
1942 });
1943 Object.defineProperty(ObjectNode.prototype, "toString", {
1944 enumerable: false,
1945 configurable: true,
1946 writable: true,
1947 value: function () {
1948 var path = (this.isAlive ? this.path : this.pathUponDeath) || "<root>";
1949 var identifier = this.identifier ? "(id: " + this.identifier + ")" : "";
1950 return this.type.name + "@" + path + identifier + (this.isAlive ? "" : " [dead]");
1951 }
1952 });
1953 Object.defineProperty(ObjectNode.prototype, "finalizeCreation", {
1954 enumerable: false,
1955 configurable: true,
1956 writable: true,
1957 value: function () {
1958 var _this = this;
1959 this.baseFinalizeCreation(function () {
1960 var e_2, _a;
1961 try {
1962 for (var _b = __values(_this.getChildren()), _c = _b.next(); !_c.done; _c = _b.next()) {
1963 var child = _c.value;
1964 child.finalizeCreation();
1965 }
1966 }
1967 catch (e_2_1) { e_2 = { error: e_2_1 }; }
1968 finally {
1969 try {
1970 if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
1971 }
1972 finally { if (e_2) throw e_2.error; }
1973 }
1974 _this.fireInternalHook(Hook.afterCreationFinalization);
1975 });
1976 }
1977 });
1978 Object.defineProperty(ObjectNode.prototype, "detach", {
1979 enumerable: false,
1980 configurable: true,
1981 writable: true,
1982 value: function () {
1983 if (!this.isAlive)
1984 throw fail$1("Error while detaching, node is not alive.");
1985 this.clearParent();
1986 }
1987 });
1988 Object.defineProperty(ObjectNode.prototype, "preboot", {
1989 enumerable: false,
1990 configurable: true,
1991 writable: true,
1992 value: function () {
1993 var self = this;
1994 this._applyPatches = createActionInvoker(this.storedValue, "@APPLY_PATCHES", function (patches) {
1995 patches.forEach(function (patch) {
1996 if (!patch.path) {
1997 self.type.applySnapshot(self, patch.value);
1998 return;
1999 }
2000 var parts = splitJsonPath(patch.path);
2001 var node = resolveNodeByPathParts(self, parts.slice(0, -1));
2002 node.applyPatchLocally(parts[parts.length - 1], patch);
2003 });
2004 });
2005 this._applySnapshot = createActionInvoker(this.storedValue, "@APPLY_SNAPSHOT", function (snapshot) {
2006 // if the snapshot is the same as the current one, avoid performing a reconcile
2007 if (snapshot === self.snapshot)
2008 return;
2009 // else, apply it by calling the type logic
2010 return self.type.applySnapshot(self, snapshot);
2011 });
2012 addHiddenFinalProp(this.storedValue, "$treenode", this);
2013 addHiddenFinalProp(this.storedValue, "toJSON", toJSON);
2014 }
2015 });
2016 Object.defineProperty(ObjectNode.prototype, "die", {
2017 enumerable: false,
2018 configurable: true,
2019 writable: true,
2020 value: function () {
2021 if (!this.isAlive || this.state === NodeLifeCycle.DETACHING)
2022 return;
2023 this.aboutToDie();
2024 this.finalizeDeath();
2025 }
2026 });
2027 Object.defineProperty(ObjectNode.prototype, "aboutToDie", {
2028 enumerable: false,
2029 configurable: true,
2030 writable: true,
2031 value: function () {
2032 if (this._observableInstanceState === 0 /* UNINITIALIZED */) {
2033 return;
2034 }
2035 this.getChildren().forEach(function (node) {
2036 node.aboutToDie();
2037 });
2038 // beforeDestroy should run before the disposers since else we could end up in a situation where
2039 // a disposer added with addDisposer at this stage (beforeDestroy) is actually never released
2040 this.baseAboutToDie();
2041 this._internalEventsEmit("dispose" /* Dispose */);
2042 this._internalEventsClear("dispose" /* Dispose */);
2043 }
2044 });
2045 Object.defineProperty(ObjectNode.prototype, "finalizeDeath", {
2046 enumerable: false,
2047 configurable: true,
2048 writable: true,
2049 value: function () {
2050 // invariant: not called directly but from "die"
2051 this.getChildren().forEach(function (node) {
2052 node.finalizeDeath();
2053 });
2054 this.root.identifierCache.notifyDied(this);
2055 // "kill" the computed prop and just store the last snapshot
2056 var snapshot = this.snapshot;
2057 this._snapshotUponDeath = snapshot;
2058 this._internalEventsClearAll();
2059 this.baseFinalizeDeath();
2060 }
2061 });
2062 Object.defineProperty(ObjectNode.prototype, "onSnapshot", {
2063 enumerable: false,
2064 configurable: true,
2065 writable: true,
2066 value: function (onChange) {
2067 this._addSnapshotReaction();
2068 return this._internalEventsRegister("snapshot" /* Snapshot */, onChange);
2069 }
2070 });
2071 Object.defineProperty(ObjectNode.prototype, "emitSnapshot", {
2072 enumerable: false,
2073 configurable: true,
2074 writable: true,
2075 value: function (snapshot) {
2076 this._internalEventsEmit("snapshot" /* Snapshot */, snapshot);
2077 }
2078 });
2079 Object.defineProperty(ObjectNode.prototype, "onPatch", {
2080 enumerable: false,
2081 configurable: true,
2082 writable: true,
2083 value: function (handler) {
2084 return this._internalEventsRegister("patch" /* Patch */, handler);
2085 }
2086 });
2087 Object.defineProperty(ObjectNode.prototype, "emitPatch", {
2088 enumerable: false,
2089 configurable: true,
2090 writable: true,
2091 value: function (basePatch, source) {
2092 if (this._internalEventsHasSubscribers("patch" /* Patch */)) {
2093 var localizedPatch = extend({}, basePatch, {
2094 path: source.path.substr(this.path.length) + "/" + basePatch.path // calculate the relative path of the patch
2095 });
2096 var _a = __read(splitPatch(localizedPatch), 2), patch = _a[0], reversePatch = _a[1];
2097 this._internalEventsEmit("patch" /* Patch */, patch, reversePatch);
2098 }
2099 if (this.parent)
2100 this.parent.emitPatch(basePatch, source);
2101 }
2102 });
2103 Object.defineProperty(ObjectNode.prototype, "hasDisposer", {
2104 enumerable: false,
2105 configurable: true,
2106 writable: true,
2107 value: function (disposer) {
2108 return this._internalEventsHas("dispose" /* Dispose */, disposer);
2109 }
2110 });
2111 Object.defineProperty(ObjectNode.prototype, "addDisposer", {
2112 enumerable: false,
2113 configurable: true,
2114 writable: true,
2115 value: function (disposer) {
2116 if (!this.hasDisposer(disposer)) {
2117 this._internalEventsRegister("dispose" /* Dispose */, disposer, true);
2118 return;
2119 }
2120 throw fail$1("cannot add a disposer when it is already registered for execution");
2121 }
2122 });
2123 Object.defineProperty(ObjectNode.prototype, "removeDisposer", {
2124 enumerable: false,
2125 configurable: true,
2126 writable: true,
2127 value: function (disposer) {
2128 if (!this._internalEventsHas("dispose" /* Dispose */, disposer)) {
2129 throw fail$1("cannot remove a disposer which was never registered for execution");
2130 }
2131 this._internalEventsUnregister("dispose" /* Dispose */, disposer);
2132 }
2133 });
2134 Object.defineProperty(ObjectNode.prototype, "removeMiddleware", {
2135 enumerable: false,
2136 configurable: true,
2137 writable: true,
2138 value: function (middleware) {
2139 if (this.middlewares) {
2140 var index = this.middlewares.indexOf(middleware);
2141 if (index >= 0) {
2142 this.middlewares.splice(index, 1);
2143 }
2144 }
2145 }
2146 });
2147 Object.defineProperty(ObjectNode.prototype, "addMiddleWare", {
2148 enumerable: false,
2149 configurable: true,
2150 writable: true,
2151 value: function (handler, includeHooks) {
2152 var _this = this;
2153 if (includeHooks === void 0) { includeHooks = true; }
2154 var middleware = { handler: handler, includeHooks: includeHooks };
2155 if (!this.middlewares)
2156 this.middlewares = [middleware];
2157 else
2158 this.middlewares.push(middleware);
2159 return function () {
2160 _this.removeMiddleware(middleware);
2161 };
2162 }
2163 });
2164 Object.defineProperty(ObjectNode.prototype, "applyPatchLocally", {
2165 enumerable: false,
2166 configurable: true,
2167 writable: true,
2168 value: function (subpath, patch) {
2169 this.assertWritable({
2170 subpath: subpath
2171 });
2172 this.createObservableInstanceIfNeeded();
2173 this.type.applyPatchLocally(this, subpath, patch);
2174 }
2175 });
2176 Object.defineProperty(ObjectNode.prototype, "_addSnapshotReaction", {
2177 enumerable: false,
2178 configurable: true,
2179 writable: true,
2180 value: function () {
2181 var _this = this;
2182 if (!this._hasSnapshotReaction) {
2183 var snapshotDisposer = mobx.reaction(function () { return _this.snapshot; }, function (snapshot) { return _this.emitSnapshot(snapshot); }, snapshotReactionOptions);
2184 this.addDisposer(snapshotDisposer);
2185 this._hasSnapshotReaction = true;
2186 }
2187 }
2188 });
2189 // we proxy the methods to avoid creating an EventHandlers instance when it is not needed
2190 Object.defineProperty(ObjectNode.prototype, "_internalEventsHasSubscribers", {
2191 enumerable: false,
2192 configurable: true,
2193 writable: true,
2194 value: function (event) {
2195 return !!this._internalEvents && this._internalEvents.hasSubscribers(event);
2196 }
2197 });
2198 Object.defineProperty(ObjectNode.prototype, "_internalEventsRegister", {
2199 enumerable: false,
2200 configurable: true,
2201 writable: true,
2202 value: function (event, eventHandler, atTheBeginning) {
2203 if (atTheBeginning === void 0) { atTheBeginning = false; }
2204 if (!this._internalEvents) {
2205 this._internalEvents = new EventHandlers();
2206 }
2207 return this._internalEvents.register(event, eventHandler, atTheBeginning);
2208 }
2209 });
2210 Object.defineProperty(ObjectNode.prototype, "_internalEventsHas", {
2211 enumerable: false,
2212 configurable: true,
2213 writable: true,
2214 value: function (event, eventHandler) {
2215 return !!this._internalEvents && this._internalEvents.has(event, eventHandler);
2216 }
2217 });
2218 Object.defineProperty(ObjectNode.prototype, "_internalEventsUnregister", {
2219 enumerable: false,
2220 configurable: true,
2221 writable: true,
2222 value: function (event, eventHandler) {
2223 if (this._internalEvents) {
2224 this._internalEvents.unregister(event, eventHandler);
2225 }
2226 }
2227 });
2228 Object.defineProperty(ObjectNode.prototype, "_internalEventsEmit", {
2229 enumerable: false,
2230 configurable: true,
2231 writable: true,
2232 value: function (event) {
2233 var _a;
2234 var args = [];
2235 for (var _i = 1; _i < arguments.length; _i++) {
2236 args[_i - 1] = arguments[_i];
2237 }
2238 if (this._internalEvents) {
2239 (_a = this._internalEvents).emit.apply(_a, __spread([event], args));
2240 }
2241 }
2242 });
2243 Object.defineProperty(ObjectNode.prototype, "_internalEventsClear", {
2244 enumerable: false,
2245 configurable: true,
2246 writable: true,
2247 value: function (event) {
2248 if (this._internalEvents) {
2249 this._internalEvents.clear(event);
2250 }
2251 }
2252 });
2253 Object.defineProperty(ObjectNode.prototype, "_internalEventsClearAll", {
2254 enumerable: false,
2255 configurable: true,
2256 writable: true,
2257 value: function () {
2258 if (this._internalEvents) {
2259 this._internalEvents.clearAll();
2260 }
2261 }
2262 });
2263 return ObjectNode;
2264}(BaseNode));
2265ObjectNode.prototype.createObservableInstance = mobx.action(ObjectNode.prototype.createObservableInstance);
2266ObjectNode.prototype.detach = mobx.action(ObjectNode.prototype.detach);
2267ObjectNode.prototype.die = mobx.action(ObjectNode.prototype.die);
2268
2269var _a;
2270/**
2271 * @internal
2272 * @hidden
2273 */
2274var TypeFlags;
2275(function (TypeFlags) {
2276 TypeFlags[TypeFlags["String"] = 1] = "String";
2277 TypeFlags[TypeFlags["Number"] = 2] = "Number";
2278 TypeFlags[TypeFlags["Boolean"] = 4] = "Boolean";
2279 TypeFlags[TypeFlags["Date"] = 8] = "Date";
2280 TypeFlags[TypeFlags["Literal"] = 16] = "Literal";
2281 TypeFlags[TypeFlags["Array"] = 32] = "Array";
2282 TypeFlags[TypeFlags["Map"] = 64] = "Map";
2283 TypeFlags[TypeFlags["Object"] = 128] = "Object";
2284 TypeFlags[TypeFlags["Frozen"] = 256] = "Frozen";
2285 TypeFlags[TypeFlags["Optional"] = 512] = "Optional";
2286 TypeFlags[TypeFlags["Reference"] = 1024] = "Reference";
2287 TypeFlags[TypeFlags["Identifier"] = 2048] = "Identifier";
2288 TypeFlags[TypeFlags["Late"] = 4096] = "Late";
2289 TypeFlags[TypeFlags["Refinement"] = 8192] = "Refinement";
2290 TypeFlags[TypeFlags["Union"] = 16384] = "Union";
2291 TypeFlags[TypeFlags["Null"] = 32768] = "Null";
2292 TypeFlags[TypeFlags["Undefined"] = 65536] = "Undefined";
2293 TypeFlags[TypeFlags["Integer"] = 131072] = "Integer";
2294 TypeFlags[TypeFlags["Custom"] = 262144] = "Custom";
2295 TypeFlags[TypeFlags["SnapshotProcessor"] = 524288] = "SnapshotProcessor";
2296})(TypeFlags || (TypeFlags = {}));
2297/**
2298 * @internal
2299 * @hidden
2300 */
2301var cannotDetermineSubtype = "cannotDetermine";
2302/** @hidden */
2303var $type = Symbol("$type");
2304/**
2305 * A base type produces a MST node (Node in the state tree)
2306 *
2307 * @internal
2308 * @hidden
2309 */
2310var BaseType = /** @class */ (function () {
2311 function BaseType(name) {
2312 Object.defineProperty(this, _a, {
2313 enumerable: true,
2314 configurable: true,
2315 writable: true,
2316 value: void 0
2317 });
2318 // these are just to make inner types avaialable to inherited classes
2319 Object.defineProperty(this, "C", {
2320 enumerable: true,
2321 configurable: true,
2322 writable: true,
2323 value: void 0
2324 });
2325 Object.defineProperty(this, "S", {
2326 enumerable: true,
2327 configurable: true,
2328 writable: true,
2329 value: void 0
2330 });
2331 Object.defineProperty(this, "T", {
2332 enumerable: true,
2333 configurable: true,
2334 writable: true,
2335 value: void 0
2336 });
2337 Object.defineProperty(this, "N", {
2338 enumerable: true,
2339 configurable: true,
2340 writable: true,
2341 value: void 0
2342 });
2343 Object.defineProperty(this, "isType", {
2344 enumerable: true,
2345 configurable: true,
2346 writable: true,
2347 value: true
2348 });
2349 Object.defineProperty(this, "name", {
2350 enumerable: true,
2351 configurable: true,
2352 writable: true,
2353 value: void 0
2354 });
2355 this.name = name;
2356 }
2357 Object.defineProperty(BaseType.prototype, "create", {
2358 enumerable: false,
2359 configurable: true,
2360 writable: true,
2361 value: function (snapshot, environment) {
2362 typecheckInternal(this, snapshot);
2363 return this.instantiate(null, "", environment, snapshot).value;
2364 }
2365 });
2366 Object.defineProperty(BaseType.prototype, "getSnapshot", {
2367 enumerable: false,
2368 configurable: true,
2369 writable: true,
2370 value: function (node, applyPostProcess) {
2371 // istanbul ignore next
2372 throw fail$1("unimplemented method");
2373 }
2374 });
2375 Object.defineProperty(BaseType.prototype, "isAssignableFrom", {
2376 enumerable: false,
2377 configurable: true,
2378 writable: true,
2379 value: function (type) {
2380 return type === this;
2381 }
2382 });
2383 Object.defineProperty(BaseType.prototype, "validate", {
2384 enumerable: false,
2385 configurable: true,
2386 writable: true,
2387 value: function (value, context) {
2388 var node = getStateTreeNodeSafe(value);
2389 if (node) {
2390 var valueType = getType(value);
2391 return this.isAssignableFrom(valueType)
2392 ? typeCheckSuccess()
2393 : typeCheckFailure(context, value);
2394 // it is tempting to compare snapshots, but in that case we should always clone on assignments...
2395 }
2396 return this.isValidSnapshot(value, context);
2397 }
2398 });
2399 Object.defineProperty(BaseType.prototype, "is", {
2400 enumerable: false,
2401 configurable: true,
2402 writable: true,
2403 value: function (thing) {
2404 return this.validate(thing, [{ path: "", type: this }]).length === 0;
2405 }
2406 });
2407 Object.defineProperty(BaseType.prototype, "Type", {
2408 get: function () {
2409 // istanbul ignore next
2410 throw fail$1("Factory.Type should not be actually called. It is just a Type signature that can be used at compile time with Typescript, by using `typeof type.Type`");
2411 },
2412 enumerable: false,
2413 configurable: true
2414 });
2415 Object.defineProperty(BaseType.prototype, "TypeWithoutSTN", {
2416 get: function () {
2417 // istanbul ignore next
2418 throw fail$1("Factory.TypeWithoutSTN should not be actually called. It is just a Type signature that can be used at compile time with Typescript, by using `typeof type.TypeWithoutSTN`");
2419 },
2420 enumerable: false,
2421 configurable: true
2422 });
2423 Object.defineProperty(BaseType.prototype, "SnapshotType", {
2424 get: function () {
2425 // istanbul ignore next
2426 throw fail$1("Factory.SnapshotType should not be actually called. It is just a Type signature that can be used at compile time with Typescript, by using `typeof type.SnapshotType`");
2427 },
2428 enumerable: false,
2429 configurable: true
2430 });
2431 Object.defineProperty(BaseType.prototype, "CreationType", {
2432 get: function () {
2433 // istanbul ignore next
2434 throw fail$1("Factory.CreationType should not be actually called. It is just a Type signature that can be used at compile time with Typescript, by using `typeof type.CreationType`");
2435 },
2436 enumerable: false,
2437 configurable: true
2438 });
2439 return BaseType;
2440}());
2441_a = $type;
2442BaseType.prototype.create = mobx.action(BaseType.prototype.create);
2443/**
2444 * A complex type produces a MST node (Node in the state tree)
2445 *
2446 * @internal
2447 * @hidden
2448 */
2449var ComplexType = /** @class */ (function (_super) {
2450 __extends(ComplexType, _super);
2451 function ComplexType(name) {
2452 var _this = _super.call(this, name) || this;
2453 Object.defineProperty(_this, "identifierAttribute", {
2454 enumerable: true,
2455 configurable: true,
2456 writable: true,
2457 value: void 0
2458 });
2459 return _this;
2460 }
2461 Object.defineProperty(ComplexType.prototype, "create", {
2462 enumerable: false,
2463 configurable: true,
2464 writable: true,
2465 value: function (snapshot, environment) {
2466 if (snapshot === void 0) { snapshot = this.getDefaultSnapshot(); }
2467 return _super.prototype.create.call(this, snapshot, environment);
2468 }
2469 });
2470 Object.defineProperty(ComplexType.prototype, "getValue", {
2471 enumerable: false,
2472 configurable: true,
2473 writable: true,
2474 value: function (node) {
2475 node.createObservableInstanceIfNeeded();
2476 return node.storedValue;
2477 }
2478 });
2479 Object.defineProperty(ComplexType.prototype, "isMatchingSnapshotId", {
2480 enumerable: false,
2481 configurable: true,
2482 writable: true,
2483 value: function (current, snapshot) {
2484 return (!current.identifierAttribute ||
2485 current.identifier ===
2486 normalizeIdentifier(snapshot[current.identifierAttribute]));
2487 }
2488 });
2489 Object.defineProperty(ComplexType.prototype, "tryToReconcileNode", {
2490 enumerable: false,
2491 configurable: true,
2492 writable: true,
2493 value: function (current, newValue) {
2494 if (current.isDetaching)
2495 return false;
2496 if (current.snapshot === newValue) {
2497 // newValue is the current snapshot of the node, noop
2498 return true;
2499 }
2500 if (isStateTreeNode(newValue) && getStateTreeNode(newValue) === current) {
2501 // the current node is the same as the new one
2502 return true;
2503 }
2504 if (current.type === this &&
2505 isMutable(newValue) &&
2506 !isStateTreeNode(newValue) &&
2507 this.isMatchingSnapshotId(current, newValue)) {
2508 // the newValue has no node, so can be treated like a snapshot
2509 // we can reconcile
2510 current.applySnapshot(newValue);
2511 return true;
2512 }
2513 return false;
2514 }
2515 });
2516 Object.defineProperty(ComplexType.prototype, "reconcile", {
2517 enumerable: false,
2518 configurable: true,
2519 writable: true,
2520 value: function (current, newValue, parent, subpath) {
2521 var nodeReconciled = this.tryToReconcileNode(current, newValue);
2522 if (nodeReconciled) {
2523 current.setParent(parent, subpath);
2524 return current;
2525 }
2526 // current node cannot be recycled in any way
2527 current.die(); // noop if detaching
2528 // attempt to reuse the new one
2529 if (isStateTreeNode(newValue) && this.isAssignableFrom(getType(newValue))) {
2530 // newValue is a Node as well, move it here..
2531 var newNode = getStateTreeNode(newValue);
2532 newNode.setParent(parent, subpath);
2533 return newNode;
2534 }
2535 // nothing to do, we have to create a new node
2536 return this.instantiate(parent, subpath, undefined, newValue);
2537 }
2538 });
2539 Object.defineProperty(ComplexType.prototype, "getSubTypes", {
2540 enumerable: false,
2541 configurable: true,
2542 writable: true,
2543 value: function () {
2544 return null;
2545 }
2546 });
2547 return ComplexType;
2548}(BaseType));
2549ComplexType.prototype.create = mobx.action(ComplexType.prototype.create);
2550/**
2551 * @internal
2552 * @hidden
2553 */
2554var SimpleType = /** @class */ (function (_super) {
2555 __extends(SimpleType, _super);
2556 function SimpleType() {
2557 return _super !== null && _super.apply(this, arguments) || this;
2558 }
2559 Object.defineProperty(SimpleType.prototype, "createNewInstance", {
2560 enumerable: false,
2561 configurable: true,
2562 writable: true,
2563 value: function (snapshot) {
2564 return snapshot;
2565 }
2566 });
2567 Object.defineProperty(SimpleType.prototype, "getValue", {
2568 enumerable: false,
2569 configurable: true,
2570 writable: true,
2571 value: function (node) {
2572 // if we ever find a case where scalar nodes can be accessed without iterating through its parent
2573 // uncomment this to make sure the parent chain is created when this is accessed
2574 // if (node.parent) {
2575 // node.parent.createObservableInstanceIfNeeded()
2576 // }
2577 return node.storedValue;
2578 }
2579 });
2580 Object.defineProperty(SimpleType.prototype, "getSnapshot", {
2581 enumerable: false,
2582 configurable: true,
2583 writable: true,
2584 value: function (node) {
2585 return node.storedValue;
2586 }
2587 });
2588 Object.defineProperty(SimpleType.prototype, "reconcile", {
2589 enumerable: false,
2590 configurable: true,
2591 writable: true,
2592 value: function (current, newValue, parent, subpath) {
2593 // reconcile only if type and value are still the same, and only if the node is not detaching
2594 if (!current.isDetaching && current.type === this && current.storedValue === newValue) {
2595 return current;
2596 }
2597 var res = this.instantiate(parent, subpath, undefined, newValue);
2598 current.die(); // noop if detaching
2599 return res;
2600 }
2601 });
2602 Object.defineProperty(SimpleType.prototype, "getSubTypes", {
2603 enumerable: false,
2604 configurable: true,
2605 writable: true,
2606 value: function () {
2607 return null;
2608 }
2609 });
2610 return SimpleType;
2611}(BaseType));
2612/**
2613 * Returns if a given value represents a type.
2614 *
2615 * @param value Value to check.
2616 * @returns `true` if the value is a type.
2617 */
2618function isType(value) {
2619 return typeof value === "object" && value && value.isType === true;
2620}
2621/**
2622 * @internal
2623 * @hidden
2624 */
2625function assertIsType(type, argNumber) {
2626 assertArg(type, isType, "mobx-state-tree type", argNumber);
2627}
2628
2629var runningActions = new Map();
2630/**
2631 * Note: Consider migrating to `createActionTrackingMiddleware2`, it is easier to use.
2632 *
2633 * Convenience utility to create action based middleware that supports async processes more easily.
2634 * All hooks are called for both synchronous and asynchronous actions. Except that either `onSuccess` or `onFail` is called
2635 *
2636 * The create middleware tracks the process of an action (assuming it passes the `filter`).
2637 * `onResume` can return any value, which will be passed as second argument to any other hook. This makes it possible to keep state during a process.
2638 *
2639 * See the `atomic` middleware for an example
2640 *
2641 * @param hooks
2642 * @returns
2643 */
2644function createActionTrackingMiddleware(hooks) {
2645 return function actionTrackingMiddleware(call, next, abort) {
2646 switch (call.type) {
2647 case "action": {
2648 if (!hooks.filter || hooks.filter(call) === true) {
2649 var context = hooks.onStart(call);
2650 hooks.onResume(call, context);
2651 runningActions.set(call.id, {
2652 call: call,
2653 context: context,
2654 async: false
2655 });
2656 try {
2657 var res = next(call);
2658 hooks.onSuspend(call, context);
2659 if (runningActions.get(call.id).async === false) {
2660 runningActions.delete(call.id);
2661 hooks.onSuccess(call, context, res);
2662 }
2663 return res;
2664 }
2665 catch (e) {
2666 runningActions.delete(call.id);
2667 hooks.onFail(call, context, e);
2668 throw e;
2669 }
2670 }
2671 else {
2672 return next(call);
2673 }
2674 }
2675 case "flow_spawn": {
2676 var root = runningActions.get(call.rootId);
2677 root.async = true;
2678 return next(call);
2679 }
2680 case "flow_resume":
2681 case "flow_resume_error": {
2682 var root = runningActions.get(call.rootId);
2683 hooks.onResume(call, root.context);
2684 try {
2685 return next(call);
2686 }
2687 finally {
2688 hooks.onSuspend(call, root.context);
2689 }
2690 }
2691 case "flow_throw": {
2692 var root = runningActions.get(call.rootId);
2693 runningActions.delete(call.rootId);
2694 hooks.onFail(call, root.context, call.args[0]);
2695 return next(call);
2696 }
2697 case "flow_return": {
2698 var root = runningActions.get(call.rootId);
2699 runningActions.delete(call.rootId);
2700 hooks.onSuccess(call, root.context, call.args[0]);
2701 return next(call);
2702 }
2703 }
2704 };
2705}
2706
2707var RunningAction = /** @class */ (function () {
2708 function RunningAction(hooks, call) {
2709 Object.defineProperty(this, "hooks", {
2710 enumerable: true,
2711 configurable: true,
2712 writable: true,
2713 value: hooks
2714 });
2715 Object.defineProperty(this, "call", {
2716 enumerable: true,
2717 configurable: true,
2718 writable: true,
2719 value: call
2720 });
2721 Object.defineProperty(this, "flowsPending", {
2722 enumerable: true,
2723 configurable: true,
2724 writable: true,
2725 value: 0
2726 });
2727 Object.defineProperty(this, "running", {
2728 enumerable: true,
2729 configurable: true,
2730 writable: true,
2731 value: true
2732 });
2733 if (hooks) {
2734 hooks.onStart(call);
2735 }
2736 }
2737 Object.defineProperty(RunningAction.prototype, "finish", {
2738 enumerable: false,
2739 configurable: true,
2740 writable: true,
2741 value: function (error) {
2742 if (this.running) {
2743 this.running = false;
2744 if (this.hooks) {
2745 this.hooks.onFinish(this.call, error);
2746 }
2747 }
2748 }
2749 });
2750 Object.defineProperty(RunningAction.prototype, "incFlowsPending", {
2751 enumerable: false,
2752 configurable: true,
2753 writable: true,
2754 value: function () {
2755 this.flowsPending++;
2756 }
2757 });
2758 Object.defineProperty(RunningAction.prototype, "decFlowsPending", {
2759 enumerable: false,
2760 configurable: true,
2761 writable: true,
2762 value: function () {
2763 this.flowsPending--;
2764 }
2765 });
2766 Object.defineProperty(RunningAction.prototype, "hasFlowsPending", {
2767 get: function () {
2768 return this.flowsPending > 0;
2769 },
2770 enumerable: false,
2771 configurable: true
2772 });
2773 return RunningAction;
2774}());
2775/**
2776 * Convenience utility to create action based middleware that supports async processes more easily.
2777 * The flow is like this:
2778 * - for each action: if filter passes -> `onStart` -> (inner actions recursively) -> `onFinish`
2779 *
2780 * Example: if we had an action `a` that called inside an action `b1`, then `b2` the flow would be:
2781 * - `filter(a)`
2782 * - `onStart(a)`
2783 * - `filter(b1)`
2784 * - `onStart(b1)`
2785 * - `onFinish(b1)`
2786 * - `filter(b2)`
2787 * - `onStart(b2)`
2788 * - `onFinish(b2)`
2789 * - `onFinish(a)`
2790 *
2791 * The flow is the same no matter if the actions are sync or async.
2792 *
2793 * See the `atomic` middleware for an example
2794 *
2795 * @param hooks
2796 * @returns
2797 */
2798function createActionTrackingMiddleware2(middlewareHooks) {
2799 var runningActions = new WeakMap();
2800 return function actionTrackingMiddleware(call, next) {
2801 // find parentRunningAction
2802 var parentRunningAction = call.parentActionEvent
2803 ? runningActions.get(call.parentActionEvent)
2804 : undefined;
2805 if (call.type === "action") {
2806 var newCall = __assign(__assign({}, call), {
2807 // make a shallow copy of the parent action env
2808 env: parentRunningAction && parentRunningAction.call.env, parentCall: parentRunningAction && parentRunningAction.call });
2809 var passesFilter = !middlewareHooks.filter || middlewareHooks.filter(newCall);
2810 var hooks = passesFilter ? middlewareHooks : undefined;
2811 var runningAction = new RunningAction(hooks, newCall);
2812 runningActions.set(call, runningAction);
2813 var res = void 0;
2814 try {
2815 res = next(call);
2816 }
2817 catch (e) {
2818 runningAction.finish(e);
2819 throw e;
2820 }
2821 if (!runningAction.hasFlowsPending) {
2822 // sync action finished
2823 runningAction.finish();
2824 }
2825 return res;
2826 }
2827 else {
2828 if (!parentRunningAction) {
2829 return next(call);
2830 }
2831 switch (call.type) {
2832 case "flow_spawn": {
2833 parentRunningAction.incFlowsPending();
2834 return next(call);
2835 }
2836 case "flow_resume":
2837 case "flow_resume_error": {
2838 return next(call);
2839 }
2840 case "flow_throw": {
2841 var error = call.args[0];
2842 try {
2843 return next(call);
2844 }
2845 finally {
2846 parentRunningAction.decFlowsPending();
2847 if (!parentRunningAction.hasFlowsPending) {
2848 parentRunningAction.finish(error);
2849 }
2850 }
2851 }
2852 case "flow_return": {
2853 try {
2854 return next(call);
2855 }
2856 finally {
2857 parentRunningAction.decFlowsPending();
2858 if (!parentRunningAction.hasFlowsPending) {
2859 parentRunningAction.finish();
2860 }
2861 }
2862 }
2863 }
2864 }
2865 };
2866}
2867
2868function serializeArgument(node, actionName, index, arg) {
2869 if (arg instanceof Date)
2870 return { $MST_DATE: arg.getTime() };
2871 if (isPrimitive(arg))
2872 return arg;
2873 // We should not serialize MST nodes, even if we can, because we don't know if the receiving party can handle a raw snapshot instead of an
2874 // MST type instance. So if one wants to serialize a MST node that was pass in, either explitly pass: 1: an id, 2: a (relative) path, 3: a snapshot
2875 if (isStateTreeNode(arg))
2876 return serializeTheUnserializable("[MSTNode: " + getType(arg).name + "]");
2877 if (typeof arg === "function")
2878 return serializeTheUnserializable("[function]");
2879 if (typeof arg === "object" && !isPlainObject(arg) && !isArray(arg))
2880 return serializeTheUnserializable("[object " + ((arg && arg.constructor && arg.constructor.name) ||
2881 "Complex Object") + "]");
2882 try {
2883 // Check if serializable, cycle free etc...
2884 // MWE: there must be a better way....
2885 JSON.stringify(arg); // or throws
2886 return arg;
2887 }
2888 catch (e) {
2889 return serializeTheUnserializable("" + e);
2890 }
2891}
2892function deserializeArgument(adm, value) {
2893 if (value && typeof value === "object" && "$MST_DATE" in value)
2894 return new Date(value["$MST_DATE"]);
2895 return value;
2896}
2897function serializeTheUnserializable(baseType) {
2898 return {
2899 $MST_UNSERIALIZABLE: true,
2900 type: baseType
2901 };
2902}
2903/**
2904 * Applies an action or a series of actions in a single MobX transaction.
2905 * Does not return any value
2906 * Takes an action description as produced by the `onAction` middleware.
2907 *
2908 * @param target
2909 * @param actions
2910 */
2911function applyAction(target, actions) {
2912 // check all arguments
2913 assertIsStateTreeNode(target, 1);
2914 assertArg(actions, function (a) { return typeof a === "object"; }, "object or array", 2);
2915 mobx.runInAction(function () {
2916 asArray(actions).forEach(function (action) { return baseApplyAction(target, action); });
2917 });
2918}
2919function baseApplyAction(target, action) {
2920 var resolvedTarget = tryResolve(target, action.path || "");
2921 if (!resolvedTarget)
2922 throw fail$1("Invalid action path: " + (action.path || ""));
2923 var node = getStateTreeNode(resolvedTarget);
2924 // Reserved functions
2925 if (action.name === "@APPLY_PATCHES") {
2926 return applyPatch.call(null, resolvedTarget, action.args[0]);
2927 }
2928 if (action.name === "@APPLY_SNAPSHOT") {
2929 return applySnapshot.call(null, resolvedTarget, action.args[0]);
2930 }
2931 if (!(typeof resolvedTarget[action.name] === "function"))
2932 throw fail$1("Action '" + action.name + "' does not exist in '" + node.path + "'");
2933 return resolvedTarget[action.name].apply(resolvedTarget, action.args ? action.args.map(function (v) { return deserializeArgument(node, v); }) : []);
2934}
2935/**
2936 * Small abstraction around `onAction` and `applyAction`, attaches an action listener to a tree and records all the actions emitted.
2937 * Returns an recorder object with the following signature:
2938 *
2939 * Example:
2940 * ```ts
2941 * export interface IActionRecorder {
2942 * // the recorded actions
2943 * actions: ISerializedActionCall[]
2944 * // true if currently recording
2945 * recording: boolean
2946 * // stop recording actions
2947 * stop(): void
2948 * // resume recording actions
2949 * resume(): void
2950 * // apply all the recorded actions on the given object
2951 * replay(target: IAnyStateTreeNode): void
2952 * }
2953 * ```
2954 *
2955 * The optional filter function allows to skip recording certain actions.
2956 *
2957 * @param subject
2958 * @returns
2959 */
2960function recordActions(subject, filter) {
2961 // check all arguments
2962 assertIsStateTreeNode(subject, 1);
2963 var actions = [];
2964 var listener = function (call) {
2965 var recordThis = filter ? filter(call, getRunningActionContext()) : true;
2966 if (recordThis) {
2967 actions.push(call);
2968 }
2969 };
2970 var disposer;
2971 var recorder = {
2972 actions: actions,
2973 get recording() {
2974 return !!disposer;
2975 },
2976 stop: function () {
2977 if (disposer) {
2978 disposer();
2979 disposer = undefined;
2980 }
2981 },
2982 resume: function () {
2983 if (disposer)
2984 return;
2985 disposer = onAction(subject, listener);
2986 },
2987 replay: function (target) {
2988 applyAction(target, actions);
2989 }
2990 };
2991 recorder.resume();
2992 return recorder;
2993}
2994/**
2995 * Registers a function that will be invoked for each action that is called on the provided model instance, or to any of its children.
2996 * See [actions](https://github.com/mobxjs/mobx-state-tree#actions) for more details. onAction events are emitted only for the outermost called action in the stack.
2997 * Action can also be intercepted by middleware using addMiddleware to change the function call before it will be run.
2998 *
2999 * Not all action arguments might be serializable. For unserializable arguments, a struct like `{ $MST_UNSERIALIZABLE: true, type: "someType" }` will be generated.
3000 * MST Nodes are considered non-serializable as well (they could be serialized as there snapshot, but it is uncertain whether an replaying party will be able to handle such a non-instantiated snapshot).
3001 * Rather, when using `onAction` middleware, one should consider in passing arguments which are 1: an id, 2: a (relative) path, or 3: a snapshot. Instead of a real MST node.
3002 *
3003 * Example:
3004 * ```ts
3005 * const Todo = types.model({
3006 * task: types.string
3007 * })
3008 *
3009 * const TodoStore = types.model({
3010 * todos: types.array(Todo)
3011 * }).actions(self => ({
3012 * add(todo) {
3013 * self.todos.push(todo);
3014 * }
3015 * }))
3016 *
3017 * const s = TodoStore.create({ todos: [] })
3018 *
3019 * let disposer = onAction(s, (call) => {
3020 * console.log(call);
3021 * })
3022 *
3023 * s.add({ task: "Grab a coffee" })
3024 * // Logs: { name: "add", path: "", args: [{ task: "Grab a coffee" }] }
3025 * ```
3026 *
3027 * @param target
3028 * @param listener
3029 * @param attachAfter (default false) fires the listener *after* the action has executed instead of before.
3030 * @returns
3031 */
3032function onAction(target, listener, attachAfter) {
3033 if (attachAfter === void 0) { attachAfter = false; }
3034 // check all arguments
3035 assertIsStateTreeNode(target, 1);
3036 if (devMode()) {
3037 if (!isRoot(target))
3038 warnError("Warning: Attaching onAction listeners to non root nodes is dangerous: No events will be emitted for actions initiated higher up in the tree.");
3039 if (!isProtected(target))
3040 warnError("Warning: Attaching onAction listeners to non protected nodes is dangerous: No events will be emitted for direct modifications without action.");
3041 }
3042 return addMiddleware(target, function handler(rawCall, next) {
3043 if (rawCall.type === "action" && rawCall.id === rawCall.rootId) {
3044 var sourceNode_1 = getStateTreeNode(rawCall.context);
3045 var info = {
3046 name: rawCall.name,
3047 path: getRelativePathBetweenNodes(getStateTreeNode(target), sourceNode_1),
3048 args: rawCall.args.map(function (arg, index) {
3049 return serializeArgument(sourceNode_1, rawCall.name, index, arg);
3050 })
3051 };
3052 if (attachAfter) {
3053 var res = next(rawCall);
3054 listener(info);
3055 return res;
3056 }
3057 else {
3058 listener(info);
3059 return next(rawCall);
3060 }
3061 }
3062 else {
3063 return next(rawCall);
3064 }
3065 });
3066}
3067
3068var nextActionId = 1;
3069var currentActionContext;
3070/**
3071 * @internal
3072 * @hidden
3073 */
3074function getCurrentActionContext() {
3075 return currentActionContext;
3076}
3077/**
3078 * @internal
3079 * @hidden
3080 */
3081function getNextActionId() {
3082 return nextActionId++;
3083}
3084// TODO: optimize away entire action context if there is no middleware in tree?
3085/**
3086 * @internal
3087 * @hidden
3088 */
3089function runWithActionContext(context, fn) {
3090 var node = getStateTreeNode(context.context);
3091 if (context.type === "action") {
3092 node.assertAlive({
3093 actionContext: context
3094 });
3095 }
3096 var baseIsRunningAction = node._isRunningAction;
3097 node._isRunningAction = true;
3098 var previousContext = currentActionContext;
3099 currentActionContext = context;
3100 try {
3101 return runMiddleWares(node, context, fn);
3102 }
3103 finally {
3104 currentActionContext = previousContext;
3105 node._isRunningAction = baseIsRunningAction;
3106 }
3107}
3108/**
3109 * @internal
3110 * @hidden
3111 */
3112function getParentActionContext(parentContext) {
3113 if (!parentContext)
3114 return undefined;
3115 if (parentContext.type === "action")
3116 return parentContext;
3117 return parentContext.parentActionEvent;
3118}
3119/**
3120 * @internal
3121 * @hidden
3122 */
3123function createActionInvoker(target, name, fn) {
3124 var res = function () {
3125 var id = getNextActionId();
3126 var parentContext = currentActionContext;
3127 var parentActionContext = getParentActionContext(parentContext);
3128 return runWithActionContext({
3129 type: "action",
3130 name: name,
3131 id: id,
3132 args: argsToArray(arguments),
3133 context: target,
3134 tree: getRoot(target),
3135 rootId: parentContext ? parentContext.rootId : id,
3136 parentId: parentContext ? parentContext.id : 0,
3137 allParentIds: parentContext
3138 ? __spread(parentContext.allParentIds, [parentContext.id]) : [],
3139 parentEvent: parentContext,
3140 parentActionEvent: parentActionContext
3141 }, fn);
3142 };
3143 res._isMSTAction = true;
3144 return res;
3145}
3146/**
3147 * Middleware can be used to intercept any action is invoked on the subtree where it is attached.
3148 * If a tree is protected (by default), this means that any mutation of the tree will pass through your middleware.
3149 *
3150 * For more details, see the [middleware docs](concepts/middleware.md)
3151 *
3152 * @param target Node to apply the middleware to.
3153 * @param middleware Middleware to apply.
3154 * @returns A callable function to dispose the middleware.
3155 */
3156function addMiddleware(target, handler, includeHooks) {
3157 if (includeHooks === void 0) { includeHooks = true; }
3158 var node = getStateTreeNode(target);
3159 if (devMode()) {
3160 if (!node.isProtectionEnabled) {
3161 warnError("It is recommended to protect the state tree before attaching action middleware, as otherwise it cannot be guaranteed that all changes are passed through middleware. See `protect`");
3162 }
3163 }
3164 return node.addMiddleWare(handler, includeHooks);
3165}
3166/**
3167 * Binds middleware to a specific action.
3168 *
3169 * Example:
3170 * ```ts
3171 * type.actions(self => {
3172 * function takeA____() {
3173 * self.toilet.donate()
3174 * self.wipe()
3175 * self.wipe()
3176 * self.toilet.flush()
3177 * }
3178 * return {
3179 * takeA____: decorate(atomic, takeA____)
3180 * }
3181 * })
3182 * ```
3183 *
3184 * @param handler
3185 * @param fn
3186 * @param includeHooks
3187 * @returns The original function
3188 */
3189function decorate(handler, fn, includeHooks) {
3190 if (includeHooks === void 0) { includeHooks = true; }
3191 var middleware = { handler: handler, includeHooks: includeHooks };
3192 fn.$mst_middleware = fn.$mst_middleware || [];
3193 fn.$mst_middleware.push(middleware);
3194 return fn;
3195}
3196var CollectedMiddlewares = /** @class */ (function () {
3197 function CollectedMiddlewares(node, fn) {
3198 Object.defineProperty(this, "arrayIndex", {
3199 enumerable: true,
3200 configurable: true,
3201 writable: true,
3202 value: 0
3203 });
3204 Object.defineProperty(this, "inArrayIndex", {
3205 enumerable: true,
3206 configurable: true,
3207 writable: true,
3208 value: 0
3209 });
3210 Object.defineProperty(this, "middlewares", {
3211 enumerable: true,
3212 configurable: true,
3213 writable: true,
3214 value: []
3215 });
3216 // we just push middleware arrays into an array of arrays to avoid making copies
3217 if (fn.$mst_middleware) {
3218 this.middlewares.push(fn.$mst_middleware);
3219 }
3220 var n = node;
3221 // Find all middlewares. Optimization: cache this?
3222 while (n) {
3223 if (n.middlewares)
3224 this.middlewares.push(n.middlewares);
3225 n = n.parent;
3226 }
3227 }
3228 Object.defineProperty(CollectedMiddlewares.prototype, "isEmpty", {
3229 get: function () {
3230 return this.middlewares.length <= 0;
3231 },
3232 enumerable: false,
3233 configurable: true
3234 });
3235 Object.defineProperty(CollectedMiddlewares.prototype, "getNextMiddleware", {
3236 enumerable: false,
3237 configurable: true,
3238 writable: true,
3239 value: function () {
3240 var array = this.middlewares[this.arrayIndex];
3241 if (!array)
3242 return undefined;
3243 var item = array[this.inArrayIndex++];
3244 if (!item) {
3245 this.arrayIndex++;
3246 this.inArrayIndex = 0;
3247 return this.getNextMiddleware();
3248 }
3249 return item;
3250 }
3251 });
3252 return CollectedMiddlewares;
3253}());
3254function runMiddleWares(node, baseCall, originalFn) {
3255 var middlewares = new CollectedMiddlewares(node, originalFn);
3256 // Short circuit
3257 if (middlewares.isEmpty)
3258 return mobx.action(originalFn).apply(null, baseCall.args);
3259 var result = null;
3260 function runNextMiddleware(call) {
3261 var middleware = middlewares.getNextMiddleware();
3262 var handler = middleware && middleware.handler;
3263 if (!handler) {
3264 return mobx.action(originalFn).apply(null, call.args);
3265 }
3266 // skip hooks if asked to
3267 if (!middleware.includeHooks && Hook[call.name]) {
3268 return runNextMiddleware(call);
3269 }
3270 var nextInvoked = false;
3271 function next(call2, callback) {
3272 nextInvoked = true;
3273 // the result can contain
3274 // - the non manipulated return value from an action
3275 // - the non manipulated abort value
3276 // - one of the above but manipulated through the callback function
3277 result = runNextMiddleware(call2);
3278 if (callback) {
3279 result = callback(result);
3280 }
3281 }
3282 var abortInvoked = false;
3283 function abort(value) {
3284 abortInvoked = true;
3285 // overwrite the result
3286 // can be manipulated through middlewares earlier in the queue using the callback fn
3287 result = value;
3288 }
3289 handler(call, next, abort);
3290 if (devMode()) {
3291 if (!nextInvoked && !abortInvoked) {
3292 var node2 = getStateTreeNode(call.tree);
3293 throw fail$1("Neither the next() nor the abort() callback within the middleware " + handler.name + " for the action: \"" + call.name + "\" on the node: " + node2.type.name + " was invoked.");
3294 }
3295 else if (nextInvoked && abortInvoked) {
3296 var node2 = getStateTreeNode(call.tree);
3297 throw fail$1("The next() and abort() callback within the middleware " + handler.name + " for the action: \"" + call.name + "\" on the node: " + node2.type.name + " were invoked.");
3298 }
3299 }
3300 return result;
3301 }
3302 return runNextMiddleware(baseCall);
3303}
3304
3305/**
3306 * Returns the currently executing MST action context, or undefined if none.
3307 */
3308function getRunningActionContext() {
3309 var current = getCurrentActionContext();
3310 while (current && current.type !== "action") {
3311 current = current.parentActionEvent;
3312 }
3313 return current;
3314}
3315function _isActionContextThisOrChildOf(actionContext, sameOrParent, includeSame) {
3316 var parentId = typeof sameOrParent === "number" ? sameOrParent : sameOrParent.id;
3317 var current = includeSame
3318 ? actionContext
3319 : actionContext.parentActionEvent;
3320 while (current) {
3321 if (current.id === parentId) {
3322 return true;
3323 }
3324 current = current.parentActionEvent;
3325 }
3326 return false;
3327}
3328/**
3329 * Returns if the given action context is a parent of this action context.
3330 */
3331function isActionContextChildOf(actionContext, parent) {
3332 return _isActionContextThisOrChildOf(actionContext, parent, false);
3333}
3334/**
3335 * Returns if the given action context is this or a parent of this action context.
3336 */
3337function isActionContextThisOrChildOf(actionContext, parentOrThis) {
3338 return _isActionContextThisOrChildOf(actionContext, parentOrThis, true);
3339}
3340
3341function safeStringify(value) {
3342 try {
3343 return JSON.stringify(value);
3344 }
3345 catch (e) {
3346 // istanbul ignore next
3347 return "<Unserializable: " + e + ">";
3348 }
3349}
3350/**
3351 * @internal
3352 * @hidden
3353 */
3354function prettyPrintValue(value) {
3355 return typeof value === "function"
3356 ? "<function" + (value.name ? " " + value.name : "") + ">"
3357 : isStateTreeNode(value)
3358 ? "<" + value + ">"
3359 : "`" + safeStringify(value) + "`";
3360}
3361function shortenPrintValue(valueInString) {
3362 return valueInString.length < 280
3363 ? valueInString
3364 : valueInString.substring(0, 272) + "......" + valueInString.substring(valueInString.length - 8);
3365}
3366function toErrorString(error) {
3367 var value = error.value;
3368 var type = error.context[error.context.length - 1].type;
3369 var fullPath = error.context
3370 .map(function (_a) {
3371 var path = _a.path;
3372 return path;
3373 })
3374 .filter(function (path) { return path.length > 0; })
3375 .join("/");
3376 var pathPrefix = fullPath.length > 0 ? "at path \"/" + fullPath + "\" " : "";
3377 var currentTypename = isStateTreeNode(value)
3378 ? "value of type " + getStateTreeNode(value).type.name + ":"
3379 : isPrimitive(value)
3380 ? "value"
3381 : "snapshot";
3382 var isSnapshotCompatible = type && isStateTreeNode(value) && type.is(getStateTreeNode(value).snapshot);
3383 return ("" + pathPrefix + currentTypename + " " + prettyPrintValue(value) + " is not assignable " + (type ? "to type: `" + type.name + "`" : "") +
3384 (error.message ? " (" + error.message + ")" : "") +
3385 (type
3386 ? isPrimitiveType(type) || isPrimitive(value)
3387 ? "."
3388 : ", expected an instance of `" + type.name + "` or a snapshot like `" + type.describe() + "` instead." +
3389 (isSnapshotCompatible
3390 ? " (Note that a snapshot of the provided value is compatible with the targeted type)"
3391 : "")
3392 : "."));
3393}
3394/**
3395 * @internal
3396 * @hidden
3397 */
3398function getContextForPath(context, path, type) {
3399 return context.concat([{ path: path, type: type }]);
3400}
3401/**
3402 * @internal
3403 * @hidden
3404 */
3405function typeCheckSuccess() {
3406 return EMPTY_ARRAY;
3407}
3408/**
3409 * @internal
3410 * @hidden
3411 */
3412function typeCheckFailure(context, value, message) {
3413 return [{ context: context, value: value, message: message }];
3414}
3415/**
3416 * @internal
3417 * @hidden
3418 */
3419function flattenTypeErrors(errors) {
3420 return errors.reduce(function (a, i) { return a.concat(i); }, []);
3421}
3422// TODO; doublecheck: typecheck should only needed to be invoked from: type.create and array / map / value.property will change
3423/**
3424 * @internal
3425 * @hidden
3426 */
3427function typecheckInternal(type, value) {
3428 // runs typeChecking if it is in dev-mode or through a process.env.ENABLE_TYPE_CHECK flag
3429 if (isTypeCheckingEnabled()) {
3430 typecheck(type, value);
3431 }
3432}
3433/**
3434 * Run's the typechecker for the given type on the given value, which can be a snapshot or an instance.
3435 * Throws if the given value is not according the provided type specification.
3436 * Use this if you need typechecks even in a production build (by default all automatic runtime type checks will be skipped in production builds)
3437 *
3438 * @param type Type to check against.
3439 * @param value Value to be checked, either a snapshot or an instance.
3440 */
3441function typecheck(type, value) {
3442 var errors = type.validate(value, [{ path: "", type: type }]);
3443 if (errors.length > 0) {
3444 throw fail$1(validationErrorsToString(type, value, errors));
3445 }
3446}
3447function validationErrorsToString(type, value, errors) {
3448 if (errors.length === 0) {
3449 return undefined;
3450 }
3451 return ("Error while converting " + shortenPrintValue(prettyPrintValue(value)) + " to `" + type.name + "`:\n\n " + errors.map(toErrorString).join("\n "));
3452}
3453
3454var identifierCacheId = 0;
3455/**
3456 * @internal
3457 * @hidden
3458 */
3459var IdentifierCache = /** @class */ (function () {
3460 function IdentifierCache() {
3461 Object.defineProperty(this, "cacheId", {
3462 enumerable: true,
3463 configurable: true,
3464 writable: true,
3465 value: identifierCacheId++
3466 });
3467 // n.b. in cache all identifiers are normalized to strings
3468 Object.defineProperty(this, "cache", {
3469 enumerable: true,
3470 configurable: true,
3471 writable: true,
3472 value: mobx.observable.map()
3473 });
3474 // last time the cache (array) for a given time changed
3475 // n.b. it is not really the time, but just an integer that gets increased after each modification to the array
3476 Object.defineProperty(this, "lastCacheModificationPerId", {
3477 enumerable: true,
3478 configurable: true,
3479 writable: true,
3480 value: mobx.observable.map()
3481 });
3482 }
3483 Object.defineProperty(IdentifierCache.prototype, "updateLastCacheModificationPerId", {
3484 enumerable: false,
3485 configurable: true,
3486 writable: true,
3487 value: function (identifier) {
3488 var lcm = this.lastCacheModificationPerId.get(identifier);
3489 // we start at 1 since 0 means no update since cache creation
3490 this.lastCacheModificationPerId.set(identifier, lcm === undefined ? 1 : lcm + 1);
3491 }
3492 });
3493 Object.defineProperty(IdentifierCache.prototype, "getLastCacheModificationPerId", {
3494 enumerable: false,
3495 configurable: true,
3496 writable: true,
3497 value: function (identifier) {
3498 var modificationId = this.lastCacheModificationPerId.get(identifier) || 0;
3499 return this.cacheId + "-" + modificationId;
3500 }
3501 });
3502 Object.defineProperty(IdentifierCache.prototype, "addNodeToCache", {
3503 enumerable: false,
3504 configurable: true,
3505 writable: true,
3506 value: function (node, lastCacheUpdate) {
3507 if (lastCacheUpdate === void 0) { lastCacheUpdate = true; }
3508 if (node.identifierAttribute) {
3509 var identifier = node.identifier;
3510 if (!this.cache.has(identifier)) {
3511 this.cache.set(identifier, mobx.observable.array([], mobxShallow));
3512 }
3513 var set = this.cache.get(identifier);
3514 if (set.indexOf(node) !== -1)
3515 throw fail$1("Already registered");
3516 set.push(node);
3517 if (lastCacheUpdate) {
3518 this.updateLastCacheModificationPerId(identifier);
3519 }
3520 }
3521 }
3522 });
3523 Object.defineProperty(IdentifierCache.prototype, "mergeCache", {
3524 enumerable: false,
3525 configurable: true,
3526 writable: true,
3527 value: function (node) {
3528 var _this = this;
3529 mobx.values(node.identifierCache.cache).forEach(function (nodes) {
3530 return nodes.forEach(function (child) {
3531 _this.addNodeToCache(child);
3532 });
3533 });
3534 }
3535 });
3536 Object.defineProperty(IdentifierCache.prototype, "notifyDied", {
3537 enumerable: false,
3538 configurable: true,
3539 writable: true,
3540 value: function (node) {
3541 if (node.identifierAttribute) {
3542 var id = node.identifier;
3543 var set = this.cache.get(id);
3544 if (set) {
3545 set.remove(node);
3546 // remove empty sets from cache
3547 if (!set.length) {
3548 this.cache.delete(id);
3549 }
3550 this.updateLastCacheModificationPerId(node.identifier);
3551 }
3552 }
3553 }
3554 });
3555 Object.defineProperty(IdentifierCache.prototype, "splitCache", {
3556 enumerable: false,
3557 configurable: true,
3558 writable: true,
3559 value: function (node) {
3560 var _this = this;
3561 var res = new IdentifierCache();
3562 var basePath = node.path;
3563 mobx.entries(this.cache).forEach(function (_a) {
3564 var _b = __read(_a, 2), id = _b[0], nodes = _b[1];
3565 var modified = false;
3566 for (var i = nodes.length - 1; i >= 0; i--) {
3567 if (nodes[i].path.indexOf(basePath) === 0) {
3568 res.addNodeToCache(nodes[i], false); // no need to update lastUpdated since it is a whole new cache
3569 nodes.splice(i, 1);
3570 modified = true;
3571 }
3572 }
3573 if (modified) {
3574 _this.updateLastCacheModificationPerId(id);
3575 }
3576 });
3577 return res;
3578 }
3579 });
3580 Object.defineProperty(IdentifierCache.prototype, "has", {
3581 enumerable: false,
3582 configurable: true,
3583 writable: true,
3584 value: function (type, identifier) {
3585 var set = this.cache.get(identifier);
3586 if (!set)
3587 return false;
3588 return set.some(function (candidate) { return type.isAssignableFrom(candidate.type); });
3589 }
3590 });
3591 Object.defineProperty(IdentifierCache.prototype, "resolve", {
3592 enumerable: false,
3593 configurable: true,
3594 writable: true,
3595 value: function (type, identifier) {
3596 var set = this.cache.get(identifier);
3597 if (!set)
3598 return null;
3599 var matches = set.filter(function (candidate) { return type.isAssignableFrom(candidate.type); });
3600 switch (matches.length) {
3601 case 0:
3602 return null;
3603 case 1:
3604 return matches[0];
3605 default:
3606 throw fail$1("Cannot resolve a reference to type '" + type.name + "' with id: '" + identifier + "' unambigously, there are multiple candidates: " + matches
3607 .map(function (n) { return n.path; })
3608 .join(", "));
3609 }
3610 }
3611 });
3612 return IdentifierCache;
3613}());
3614
3615/**
3616 * @internal
3617 * @hidden
3618 */
3619function createObjectNode(type, parent, subpath, environment, initialValue) {
3620 var existingNode = getStateTreeNodeSafe(initialValue);
3621 if (existingNode) {
3622 if (existingNode.parent) {
3623 // istanbul ignore next
3624 throw fail$1("Cannot add an object to a state tree if it is already part of the same or another state tree. Tried to assign an object to '" + (parent ? parent.path : "") + "/" + subpath + "', but it lives already at '" + existingNode.path + "'");
3625 }
3626 if (parent) {
3627 existingNode.setParent(parent, subpath);
3628 }
3629 // else it already has no parent since it is a pre-requisite
3630 return existingNode;
3631 }
3632 // not a node, a snapshot
3633 return new ObjectNode(type, parent, subpath, environment, initialValue);
3634}
3635/**
3636 * @internal
3637 * @hidden
3638 */
3639function createScalarNode(type, parent, subpath, environment, initialValue) {
3640 return new ScalarNode(type, parent, subpath, environment, initialValue);
3641}
3642/**
3643 * @internal
3644 * @hidden
3645 */
3646function isNode(value) {
3647 return value instanceof ScalarNode || value instanceof ObjectNode;
3648}
3649
3650/**
3651 * @internal
3652 * @hidden
3653 */
3654var NodeLifeCycle;
3655(function (NodeLifeCycle) {
3656 NodeLifeCycle[NodeLifeCycle["INITIALIZING"] = 0] = "INITIALIZING";
3657 NodeLifeCycle[NodeLifeCycle["CREATED"] = 1] = "CREATED";
3658 NodeLifeCycle[NodeLifeCycle["FINALIZED"] = 2] = "FINALIZED";
3659 NodeLifeCycle[NodeLifeCycle["DETACHING"] = 3] = "DETACHING";
3660 NodeLifeCycle[NodeLifeCycle["DEAD"] = 4] = "DEAD"; // no coming back from this one
3661})(NodeLifeCycle || (NodeLifeCycle = {}));
3662/**
3663 * Returns true if the given value is a node in a state tree.
3664 * More precisely, that is, if the value is an instance of a
3665 * `types.model`, `types.array` or `types.map`.
3666 *
3667 * @param value
3668 * @returns true if the value is a state tree node.
3669 */
3670function isStateTreeNode(value) {
3671 return !!(value && value.$treenode);
3672}
3673/**
3674 * @internal
3675 * @hidden
3676 */
3677function assertIsStateTreeNode(value, argNumber) {
3678 assertArg(value, isStateTreeNode, "mobx-state-tree node", argNumber);
3679}
3680/**
3681 * @internal
3682 * @hidden
3683 */
3684function getStateTreeNode(value) {
3685 if (!isStateTreeNode(value)) {
3686 // istanbul ignore next
3687 throw fail$1("Value " + value + " is no MST Node");
3688 }
3689 return value.$treenode;
3690}
3691/**
3692 * @internal
3693 * @hidden
3694 */
3695function getStateTreeNodeSafe(value) {
3696 return (value && value.$treenode) || null;
3697}
3698/**
3699 * @internal
3700 * @hidden
3701 */
3702function toJSON() {
3703 return getStateTreeNode(this).snapshot;
3704}
3705var doubleDot = function (_) { return ".."; };
3706/**
3707 * @internal
3708 * @hidden
3709 */
3710function getRelativePathBetweenNodes(base, target) {
3711 // PRE condition target is (a child of) base!
3712 if (base.root !== target.root) {
3713 throw fail$1("Cannot calculate relative path: objects '" + base + "' and '" + target + "' are not part of the same object tree");
3714 }
3715 var baseParts = splitJsonPath(base.path);
3716 var targetParts = splitJsonPath(target.path);
3717 var common = 0;
3718 for (; common < baseParts.length; common++) {
3719 if (baseParts[common] !== targetParts[common])
3720 break;
3721 }
3722 // TODO: assert that no targetParts paths are "..", "." or ""!
3723 return (baseParts.slice(common).map(doubleDot).join("/") + joinJsonPath(targetParts.slice(common)));
3724}
3725/**
3726 * @internal
3727 * @hidden
3728 */
3729function resolveNodeByPath(base, path, failIfResolveFails) {
3730 if (failIfResolveFails === void 0) { failIfResolveFails = true; }
3731 return resolveNodeByPathParts(base, splitJsonPath(path), failIfResolveFails);
3732}
3733/**
3734 * @internal
3735 * @hidden
3736 */
3737function resolveNodeByPathParts(base, pathParts, failIfResolveFails) {
3738 if (failIfResolveFails === void 0) { failIfResolveFails = true; }
3739 var current = base;
3740 for (var i = 0; i < pathParts.length; i++) {
3741 var part = pathParts[i];
3742 if (part === "..") {
3743 current = current.parent;
3744 if (current)
3745 continue; // not everything has a parent
3746 }
3747 else if (part === ".") {
3748 continue;
3749 }
3750 else if (current) {
3751 if (current instanceof ScalarNode) {
3752 // check if the value of a scalar resolves to a state tree node (e.g. references)
3753 // then we can continue resolving...
3754 try {
3755 var value = current.value;
3756 if (isStateTreeNode(value)) {
3757 current = getStateTreeNode(value);
3758 // fall through
3759 }
3760 }
3761 catch (e) {
3762 if (!failIfResolveFails) {
3763 return undefined;
3764 }
3765 throw e;
3766 }
3767 }
3768 if (current instanceof ObjectNode) {
3769 var subType = current.getChildType(part);
3770 if (subType) {
3771 current = current.getChildNode(part);
3772 if (current)
3773 continue;
3774 }
3775 }
3776 }
3777 if (failIfResolveFails)
3778 throw fail$1("Could not resolve '" + part + "' in path '" + (joinJsonPath(pathParts.slice(0, i)) || "/") + "' while resolving '" + joinJsonPath(pathParts) + "'");
3779 else
3780 return undefined;
3781 }
3782 return current;
3783}
3784/**
3785 * @internal
3786 * @hidden
3787 */
3788function convertChildNodesToArray(childNodes) {
3789 if (!childNodes)
3790 return EMPTY_ARRAY;
3791 var keys = Object.keys(childNodes);
3792 if (!keys.length)
3793 return EMPTY_ARRAY;
3794 var result = new Array(keys.length);
3795 keys.forEach(function (key, index) {
3796 result[index] = childNodes[key];
3797 });
3798 return result;
3799}
3800
3801// based on: https://github.com/mobxjs/mobx-utils/blob/master/src/async-action.ts
3802/*
3803 All contents of this file are deprecated.
3804
3805 The term `process` has been replaced with `flow` to avoid conflicts with the
3806 global `process` object.
3807
3808 Refer to `flow.ts` for any further changes to this implementation.
3809*/
3810var DEPRECATION_MESSAGE = "See https://github.com/mobxjs/mobx-state-tree/issues/399 for more information. " +
3811 "Note that the middleware event types starting with `process` now start with `flow`.";
3812/**
3813 * @hidden
3814 *
3815 * @deprecated has been renamed to `flow()`.
3816 * See https://github.com/mobxjs/mobx-state-tree/issues/399 for more information.
3817 * Note that the middleware event types starting with `process` now start with `flow`.
3818 *
3819 * @returns {Promise}
3820 */
3821function process$1(asyncAction) {
3822 deprecated("process", "`process()` has been renamed to `flow()`. " + DEPRECATION_MESSAGE);
3823 return flow(asyncAction);
3824}
3825
3826var plainObjectString = Object.toString();
3827/**
3828 * @internal
3829 * @hidden
3830 */
3831var EMPTY_ARRAY = Object.freeze([]);
3832/**
3833 * @internal
3834 * @hidden
3835 */
3836var EMPTY_OBJECT = Object.freeze({});
3837/**
3838 * @internal
3839 * @hidden
3840 */
3841var mobxShallow = mobx._getGlobalState().useProxies
3842 ? { deep: false }
3843 : { deep: false, proxy: false };
3844Object.freeze(mobxShallow);
3845/**
3846 * @internal
3847 * @hidden
3848 */
3849function fail$1(message) {
3850 if (message === void 0) { message = "Illegal state"; }
3851 return new Error("[mobx-state-tree] " + message);
3852}
3853/**
3854 * @internal
3855 * @hidden
3856 */
3857function identity(_) {
3858 return _;
3859}
3860/**
3861 * pollyfill (for IE) suggested in MDN:
3862 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
3863 * @internal
3864 * @hidden
3865 */
3866var isInteger = Number.isInteger ||
3867 function (value) {
3868 return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
3869 };
3870/**
3871 * @internal
3872 * @hidden
3873 */
3874function isArray(val) {
3875 return Array.isArray(val) || mobx.isObservableArray(val);
3876}
3877/**
3878 * @internal
3879 * @hidden
3880 */
3881function asArray(val) {
3882 if (!val)
3883 return EMPTY_ARRAY;
3884 if (isArray(val))
3885 return val;
3886 return [val];
3887}
3888/**
3889 * @internal
3890 * @hidden
3891 */
3892function extend(a) {
3893 var b = [];
3894 for (var _i = 1; _i < arguments.length; _i++) {
3895 b[_i - 1] = arguments[_i];
3896 }
3897 for (var i = 0; i < b.length; i++) {
3898 var current = b[i];
3899 for (var key in current)
3900 a[key] = current[key];
3901 }
3902 return a;
3903}
3904/**
3905 * @internal
3906 * @hidden
3907 */
3908function isPlainObject(value) {
3909 var _a;
3910 if (value === null || typeof value !== "object")
3911 return false;
3912 var proto = Object.getPrototypeOf(value);
3913 if (proto == null)
3914 return true;
3915 return ((_a = proto.constructor) === null || _a === void 0 ? void 0 : _a.toString()) === plainObjectString;
3916}
3917/**
3918 * @internal
3919 * @hidden
3920 */
3921function isMutable(value) {
3922 return (value !== null &&
3923 typeof value === "object" &&
3924 !(value instanceof Date) &&
3925 !(value instanceof RegExp));
3926}
3927/**
3928 * @internal
3929 * @hidden
3930 */
3931function isPrimitive(value, includeDate) {
3932 if (includeDate === void 0) { includeDate = true; }
3933 return (value === null ||
3934 value === undefined ||
3935 typeof value === "string" ||
3936 typeof value === "number" ||
3937 typeof value === "boolean" ||
3938 (includeDate && value instanceof Date));
3939}
3940/**
3941 * @internal
3942 * @hidden
3943 * Freeze a value and return it (if not in production)
3944 */
3945function freeze(value) {
3946 if (!devMode())
3947 return value;
3948 return isPrimitive(value) || mobx.isObservableArray(value) ? value : Object.freeze(value);
3949}
3950/**
3951 * @internal
3952 * @hidden
3953 * Recursively freeze a value (if not in production)
3954 */
3955function deepFreeze(value) {
3956 if (!devMode())
3957 return value;
3958 freeze(value);
3959 if (isPlainObject(value)) {
3960 Object.keys(value).forEach(function (propKey) {
3961 if (!isPrimitive(value[propKey]) &&
3962 !Object.isFrozen(value[propKey])) {
3963 deepFreeze(value[propKey]);
3964 }
3965 });
3966 }
3967 return value;
3968}
3969/**
3970 * @internal
3971 * @hidden
3972 */
3973function isSerializable(value) {
3974 return typeof value !== "function";
3975}
3976/**
3977 * @internal
3978 * @hidden
3979 */
3980function defineProperty(object, key, descriptor) {
3981 mobx.isObservableObject(object)
3982 ? mobx.defineProperty(object, key, descriptor)
3983 : Object.defineProperty(object, key, descriptor);
3984}
3985/**
3986 * @internal
3987 * @hidden
3988 */
3989function addHiddenFinalProp(object, propName, value) {
3990 defineProperty(object, propName, {
3991 enumerable: false,
3992 writable: false,
3993 configurable: true,
3994 value: value
3995 });
3996}
3997/**
3998 * @internal
3999 * @hidden
4000 */
4001function addHiddenWritableProp(object, propName, value) {
4002 defineProperty(object, propName, {
4003 enumerable: false,
4004 writable: true,
4005 configurable: true,
4006 value: value
4007 });
4008}
4009/**
4010 * @internal
4011 * @hidden
4012 */
4013var EventHandler = /** @class */ (function () {
4014 function EventHandler() {
4015 Object.defineProperty(this, "handlers", {
4016 enumerable: true,
4017 configurable: true,
4018 writable: true,
4019 value: []
4020 });
4021 }
4022 Object.defineProperty(EventHandler.prototype, "hasSubscribers", {
4023 get: function () {
4024 return this.handlers.length > 0;
4025 },
4026 enumerable: false,
4027 configurable: true
4028 });
4029 Object.defineProperty(EventHandler.prototype, "register", {
4030 enumerable: false,
4031 configurable: true,
4032 writable: true,
4033 value: function (fn, atTheBeginning) {
4034 var _this = this;
4035 if (atTheBeginning === void 0) { atTheBeginning = false; }
4036 if (atTheBeginning) {
4037 this.handlers.unshift(fn);
4038 }
4039 else {
4040 this.handlers.push(fn);
4041 }
4042 return function () {
4043 _this.unregister(fn);
4044 };
4045 }
4046 });
4047 Object.defineProperty(EventHandler.prototype, "has", {
4048 enumerable: false,
4049 configurable: true,
4050 writable: true,
4051 value: function (fn) {
4052 return this.handlers.indexOf(fn) >= 0;
4053 }
4054 });
4055 Object.defineProperty(EventHandler.prototype, "unregister", {
4056 enumerable: false,
4057 configurable: true,
4058 writable: true,
4059 value: function (fn) {
4060 var index = this.handlers.indexOf(fn);
4061 if (index >= 0) {
4062 this.handlers.splice(index, 1);
4063 }
4064 }
4065 });
4066 Object.defineProperty(EventHandler.prototype, "clear", {
4067 enumerable: false,
4068 configurable: true,
4069 writable: true,
4070 value: function () {
4071 this.handlers.length = 0;
4072 }
4073 });
4074 Object.defineProperty(EventHandler.prototype, "emit", {
4075 enumerable: false,
4076 configurable: true,
4077 writable: true,
4078 value: function () {
4079 var args = [];
4080 for (var _i = 0; _i < arguments.length; _i++) {
4081 args[_i] = arguments[_i];
4082 }
4083 // make a copy just in case it changes
4084 var handlers = this.handlers.slice();
4085 handlers.forEach(function (f) { return f.apply(void 0, __spread(args)); });
4086 }
4087 });
4088 return EventHandler;
4089}());
4090/**
4091 * @internal
4092 * @hidden
4093 */
4094var EventHandlers = /** @class */ (function () {
4095 function EventHandlers() {
4096 Object.defineProperty(this, "eventHandlers", {
4097 enumerable: true,
4098 configurable: true,
4099 writable: true,
4100 value: void 0
4101 });
4102 }
4103 Object.defineProperty(EventHandlers.prototype, "hasSubscribers", {
4104 enumerable: false,
4105 configurable: true,
4106 writable: true,
4107 value: function (event) {
4108 var handler = this.eventHandlers && this.eventHandlers[event];
4109 return !!handler && handler.hasSubscribers;
4110 }
4111 });
4112 Object.defineProperty(EventHandlers.prototype, "register", {
4113 enumerable: false,
4114 configurable: true,
4115 writable: true,
4116 value: function (event, fn, atTheBeginning) {
4117 if (atTheBeginning === void 0) { atTheBeginning = false; }
4118 if (!this.eventHandlers) {
4119 this.eventHandlers = {};
4120 }
4121 var handler = this.eventHandlers[event];
4122 if (!handler) {
4123 handler = this.eventHandlers[event] = new EventHandler();
4124 }
4125 return handler.register(fn, atTheBeginning);
4126 }
4127 });
4128 Object.defineProperty(EventHandlers.prototype, "has", {
4129 enumerable: false,
4130 configurable: true,
4131 writable: true,
4132 value: function (event, fn) {
4133 var handler = this.eventHandlers && this.eventHandlers[event];
4134 return !!handler && handler.has(fn);
4135 }
4136 });
4137 Object.defineProperty(EventHandlers.prototype, "unregister", {
4138 enumerable: false,
4139 configurable: true,
4140 writable: true,
4141 value: function (event, fn) {
4142 var handler = this.eventHandlers && this.eventHandlers[event];
4143 if (handler) {
4144 handler.unregister(fn);
4145 }
4146 }
4147 });
4148 Object.defineProperty(EventHandlers.prototype, "clear", {
4149 enumerable: false,
4150 configurable: true,
4151 writable: true,
4152 value: function (event) {
4153 if (this.eventHandlers) {
4154 delete this.eventHandlers[event];
4155 }
4156 }
4157 });
4158 Object.defineProperty(EventHandlers.prototype, "clearAll", {
4159 enumerable: false,
4160 configurable: true,
4161 writable: true,
4162 value: function () {
4163 this.eventHandlers = undefined;
4164 }
4165 });
4166 Object.defineProperty(EventHandlers.prototype, "emit", {
4167 enumerable: false,
4168 configurable: true,
4169 writable: true,
4170 value: function (event) {
4171 var _a;
4172 var args = [];
4173 for (var _i = 1; _i < arguments.length; _i++) {
4174 args[_i - 1] = arguments[_i];
4175 }
4176 var handler = this.eventHandlers && this.eventHandlers[event];
4177 if (handler) {
4178 (_a = handler).emit.apply(_a, __spread(args));
4179 }
4180 }
4181 });
4182 return EventHandlers;
4183}());
4184/**
4185 * @internal
4186 * @hidden
4187 */
4188function argsToArray(args) {
4189 var res = new Array(args.length);
4190 for (var i = 0; i < args.length; i++)
4191 res[i] = args[i];
4192 return res;
4193}
4194/**
4195 * @internal
4196 * @hidden
4197 */
4198function stringStartsWith(str, beginning) {
4199 return str.indexOf(beginning) === 0;
4200}
4201/**
4202 * @internal
4203 * @hidden
4204 */
4205var deprecated = function (id, message) {
4206 // skip if running production
4207 if (!devMode())
4208 return;
4209 // warn if hasn't been warned before
4210 if (deprecated.ids && !deprecated.ids.hasOwnProperty(id)) {
4211 warnError("Deprecation warning: " + message);
4212 }
4213 // mark as warned to avoid duplicate warn message
4214 if (deprecated.ids)
4215 deprecated.ids[id] = true;
4216};
4217deprecated.ids = {};
4218/**
4219 * @internal
4220 * @hidden
4221 */
4222function warnError(msg) {
4223 console.warn(new Error("[mobx-state-tree] " + msg));
4224}
4225/**
4226 * @internal
4227 * @hidden
4228 */
4229function isTypeCheckingEnabled() {
4230 return (devMode() ||
4231 (typeof process !== "undefined" && process.env && process.env.ENABLE_TYPE_CHECK === "true"));
4232}
4233/**
4234 * @internal
4235 * @hidden
4236 */
4237function devMode() {
4238 return process.env.NODE_ENV !== "production";
4239}
4240/**
4241 * @internal
4242 * @hidden
4243 */
4244function assertArg(value, fn, typeName, argNumber) {
4245 if (devMode()) {
4246 if (!fn(value)) {
4247 // istanbul ignore next
4248 throw fail$1("expected " + typeName + " as argument " + asArray(argNumber).join(" or ") + ", got " + value + " instead");
4249 }
4250 }
4251}
4252/**
4253 * @internal
4254 * @hidden
4255 */
4256function assertIsFunction(value, argNumber) {
4257 assertArg(value, function (fn) { return typeof fn === "function"; }, "function", argNumber);
4258}
4259/**
4260 * @internal
4261 * @hidden
4262 */
4263function assertIsNumber(value, argNumber, min, max) {
4264 assertArg(value, function (n) { return typeof n === "number"; }, "number", argNumber);
4265 if (min !== undefined) {
4266 assertArg(value, function (n) { return n >= min; }, "number greater than " + min, argNumber);
4267 }
4268 if (max !== undefined) {
4269 assertArg(value, function (n) { return n <= max; }, "number lesser than " + max, argNumber);
4270 }
4271}
4272/**
4273 * @internal
4274 * @hidden
4275 */
4276function assertIsString(value, argNumber, canBeEmpty) {
4277 if (canBeEmpty === void 0) { canBeEmpty = true; }
4278 assertArg(value, function (s) { return typeof s === "string"; }, "string", argNumber);
4279 if (!canBeEmpty) {
4280 assertArg(value, function (s) { return s !== ""; }, "not empty string", argNumber);
4281 }
4282}
4283/**
4284 * @internal
4285 * @hidden
4286 */
4287function setImmediateWithFallback(fn) {
4288 if (typeof queueMicrotask === "function") {
4289 queueMicrotask(fn);
4290 }
4291 else if (typeof setImmediate === "function") {
4292 setImmediate(fn);
4293 }
4294 else {
4295 setTimeout(fn, 1);
4296 }
4297}
4298
4299/**
4300 * See [asynchronous actions](concepts/async-actions.md).
4301 *
4302 * @returns The flow as a promise.
4303 */
4304function flow(generator) {
4305 return createFlowSpawner(generator.name, generator);
4306}
4307/**
4308 * @deprecated Not needed since TS3.6.
4309 * Used for TypeScript to make flows that return a promise return the actual promise result.
4310 *
4311 * @param val
4312 * @returns
4313 */
4314function castFlowReturn(val) {
4315 return val;
4316}
4317/**
4318 * @experimental
4319 * experimental api - might change on minor/patch releases
4320 *
4321 * Convert a promise-returning function to a generator-returning one.
4322 * This is intended to allow for usage of `yield*` in async actions to
4323 * retain the promise return type.
4324 *
4325 * Example:
4326 * ```ts
4327 * function getDataAsync(input: string): Promise<number> { ... }
4328 * const getDataGen = toGeneratorFunction(getDataAsync);
4329 *
4330 * const someModel.actions(self => ({
4331 * someAction: flow(function*() {
4332 * // value is typed as number
4333 * const value = yield* getDataGen("input value");
4334 * ...
4335 * })
4336 * }))
4337 * ```
4338 */
4339function toGeneratorFunction(p) {
4340 return function () {
4341 var _i;
4342 var args = [];
4343 for (_i = 0; _i < arguments.length; _i++) {
4344 args[_i] = arguments[_i];
4345 }
4346 return __generator(this, function (_a) {
4347 switch (_a.label) {
4348 case 0: return [4 /*yield*/, p.apply(void 0, __spread(args))];
4349 case 1: return [2 /*return*/, (_a.sent())];
4350 }
4351 });
4352 };
4353}
4354/**
4355 * @experimental
4356 * experimental api - might change on minor/patch releases
4357 *
4358 * Convert a promise to a generator yielding that promise
4359 * This is intended to allow for usage of `yield*` in async actions to
4360 * retain the promise return type.
4361 *
4362 * Example:
4363 * ```ts
4364 * function getDataAsync(input: string): Promise<number> { ... }
4365 *
4366 * const someModel.actions(self => ({
4367 * someAction: flow(function*() {
4368 * // value is typed as number
4369 * const value = yield* toGenerator(getDataAsync("input value"));
4370 * ...
4371 * })
4372 * }))
4373 * ```
4374 */
4375function toGenerator(p) {
4376 return __generator(this, function (_a) {
4377 switch (_a.label) {
4378 case 0: return [4 /*yield*/, p];
4379 case 1: return [2 /*return*/, (_a.sent())];
4380 }
4381 });
4382}
4383/**
4384 * @internal
4385 * @hidden
4386 */
4387function createFlowSpawner(name, generator) {
4388 var spawner = function flowSpawner() {
4389 // Implementation based on https://github.com/tj/co/blob/master/index.js
4390 var runId = getNextActionId();
4391 var parentContext = getCurrentActionContext();
4392 if (!parentContext) {
4393 throw fail$1("a mst flow must always have a parent context");
4394 }
4395 var parentActionContext = getParentActionContext(parentContext);
4396 if (!parentActionContext) {
4397 throw fail$1("a mst flow must always have a parent action context");
4398 }
4399 var contextBase = {
4400 name: name,
4401 id: runId,
4402 tree: parentContext.tree,
4403 context: parentContext.context,
4404 parentId: parentContext.id,
4405 allParentIds: __spread(parentContext.allParentIds, [parentContext.id]),
4406 rootId: parentContext.rootId,
4407 parentEvent: parentContext,
4408 parentActionEvent: parentActionContext
4409 };
4410 var args = arguments;
4411 function wrap(fn, type, arg) {
4412 fn.$mst_middleware = spawner.$mst_middleware; // pick up any middleware attached to the flow
4413 runWithActionContext(__assign(__assign({}, contextBase), { type: type, args: [arg] }), fn);
4414 }
4415 return new Promise(function (resolve, reject) {
4416 var gen;
4417 var init = function asyncActionInit() {
4418 gen = generator.apply(null, arguments);
4419 onFulfilled(undefined); // kick off the flow
4420 };
4421 init.$mst_middleware = spawner.$mst_middleware;
4422 runWithActionContext(__assign(__assign({}, contextBase), { type: "flow_spawn", args: argsToArray(args) }), init);
4423 function onFulfilled(res) {
4424 var ret;
4425 try {
4426 // prettier-ignore
4427 wrap(function (r) { ret = gen.next(r); }, "flow_resume", res);
4428 }
4429 catch (e) {
4430 // prettier-ignore
4431 setImmediateWithFallback(function () {
4432 wrap(function (r) { reject(e); }, "flow_throw", e);
4433 });
4434 return;
4435 }
4436 next(ret);
4437 return;
4438 }
4439 function onRejected(err) {
4440 var ret;
4441 try {
4442 // prettier-ignore
4443 wrap(function (r) { ret = gen.throw(r); }, "flow_resume_error", err); // or yieldError?
4444 }
4445 catch (e) {
4446 // prettier-ignore
4447 setImmediateWithFallback(function () {
4448 wrap(function (r) { reject(e); }, "flow_throw", e);
4449 });
4450 return;
4451 }
4452 next(ret);
4453 }
4454 function next(ret) {
4455 if (ret.done) {
4456 // prettier-ignore
4457 setImmediateWithFallback(function () {
4458 wrap(function (r) { resolve(r); }, "flow_return", ret.value);
4459 });
4460 return;
4461 }
4462 // TODO: support more type of values? See https://github.com/tj/co/blob/249bbdc72da24ae44076afd716349d2089b31c4c/index.js#L100
4463 if (!ret.value || typeof ret.value.then !== "function") {
4464 // istanbul ignore next
4465 throw fail$1("Only promises can be yielded to `async`, got: " + ret);
4466 }
4467 return ret.value.then(onFulfilled, onRejected);
4468 }
4469 });
4470 };
4471 return spawner;
4472}
4473
4474/**
4475 * @internal
4476 * @hidden
4477 */
4478function splitPatch(patch) {
4479 if (!("oldValue" in patch))
4480 throw fail$1("Patches without `oldValue` field cannot be inversed");
4481 return [stripPatch(patch), invertPatch(patch)];
4482}
4483/**
4484 * @internal
4485 * @hidden
4486 */
4487function stripPatch(patch) {
4488 // strips `oldvalue` information from the patch, so that it becomes a patch conform the json-patch spec
4489 // this removes the ability to undo the patch
4490 switch (patch.op) {
4491 case "add":
4492 return { op: "add", path: patch.path, value: patch.value };
4493 case "remove":
4494 return { op: "remove", path: patch.path };
4495 case "replace":
4496 return { op: "replace", path: patch.path, value: patch.value };
4497 }
4498}
4499function invertPatch(patch) {
4500 switch (patch.op) {
4501 case "add":
4502 return {
4503 op: "remove",
4504 path: patch.path
4505 };
4506 case "remove":
4507 return {
4508 op: "add",
4509 path: patch.path,
4510 value: patch.oldValue
4511 };
4512 case "replace":
4513 return {
4514 op: "replace",
4515 path: patch.path,
4516 value: patch.oldValue
4517 };
4518 }
4519}
4520/**
4521 * Simple simple check to check it is a number.
4522 */
4523function isNumber(x) {
4524 return typeof x === "number";
4525}
4526/**
4527 * Escape slashes and backslashes.
4528 *
4529 * http://tools.ietf.org/html/rfc6901
4530 */
4531function escapeJsonPath(path) {
4532 if (isNumber(path) === true) {
4533 return "" + path;
4534 }
4535 if (path.indexOf("/") === -1 && path.indexOf("~") === -1)
4536 return path;
4537 return path.replace(/~/g, "~0").replace(/\//g, "~1");
4538}
4539/**
4540 * Unescape slashes and backslashes.
4541 */
4542function unescapeJsonPath(path) {
4543 return path.replace(/~1/g, "/").replace(/~0/g, "~");
4544}
4545/**
4546 * Generates a json-path compliant json path from path parts.
4547 *
4548 * @param path
4549 * @returns
4550 */
4551function joinJsonPath(path) {
4552 // `/` refers to property with an empty name, while `` refers to root itself!
4553 if (path.length === 0)
4554 return "";
4555 var getPathStr = function (p) { return p.map(escapeJsonPath).join("/"); };
4556 if (path[0] === "." || path[0] === "..") {
4557 // relative
4558 return getPathStr(path);
4559 }
4560 else {
4561 // absolute
4562 return "/" + getPathStr(path);
4563 }
4564}
4565/**
4566 * Splits and decodes a json path into several parts.
4567 *
4568 * @param path
4569 * @returns
4570 */
4571function splitJsonPath(path) {
4572 // `/` refers to property with an empty name, while `` refers to root itself!
4573 var parts = path.split("/").map(unescapeJsonPath);
4574 var valid = path === "" ||
4575 path === "." ||
4576 path === ".." ||
4577 stringStartsWith(path, "/") ||
4578 stringStartsWith(path, "./") ||
4579 stringStartsWith(path, "../");
4580 if (!valid) {
4581 throw fail$1("a json path must be either rooted, empty or relative, but got '" + path + "'");
4582 }
4583 // '/a/b/c' -> ["a", "b", "c"]
4584 // '../../b/c' -> ["..", "..", "b", "c"]
4585 // '' -> []
4586 // '/' -> ['']
4587 // './a' -> [".", "a"]
4588 // /./a' -> [".", "a"] equivalent to './a'
4589 if (parts[0] === "") {
4590 parts.shift();
4591 }
4592 return parts;
4593}
4594
4595/** @hidden */
4596var $preProcessorFailed = Symbol("$preProcessorFailed");
4597var SnapshotProcessor = /** @class */ (function (_super) {
4598 __extends(SnapshotProcessor, _super);
4599 function SnapshotProcessor(_subtype, _processors, name) {
4600 var _this = _super.call(this, name || _subtype.name) || this;
4601 Object.defineProperty(_this, "_subtype", {
4602 enumerable: true,
4603 configurable: true,
4604 writable: true,
4605 value: _subtype
4606 });
4607 Object.defineProperty(_this, "_processors", {
4608 enumerable: true,
4609 configurable: true,
4610 writable: true,
4611 value: _processors
4612 });
4613 return _this;
4614 }
4615 Object.defineProperty(SnapshotProcessor.prototype, "flags", {
4616 get: function () {
4617 return this._subtype.flags | TypeFlags.SnapshotProcessor;
4618 },
4619 enumerable: false,
4620 configurable: true
4621 });
4622 Object.defineProperty(SnapshotProcessor.prototype, "describe", {
4623 enumerable: false,
4624 configurable: true,
4625 writable: true,
4626 value: function () {
4627 return "snapshotProcessor(" + this._subtype.describe() + ")";
4628 }
4629 });
4630 Object.defineProperty(SnapshotProcessor.prototype, "preProcessSnapshot", {
4631 enumerable: false,
4632 configurable: true,
4633 writable: true,
4634 value: function (sn) {
4635 if (this._processors.preProcessor) {
4636 return this._processors.preProcessor.call(null, sn);
4637 }
4638 return sn;
4639 }
4640 });
4641 Object.defineProperty(SnapshotProcessor.prototype, "preProcessSnapshotSafe", {
4642 enumerable: false,
4643 configurable: true,
4644 writable: true,
4645 value: function (sn) {
4646 try {
4647 return this.preProcessSnapshot(sn);
4648 }
4649 catch (e) {
4650 return $preProcessorFailed;
4651 }
4652 }
4653 });
4654 Object.defineProperty(SnapshotProcessor.prototype, "postProcessSnapshot", {
4655 enumerable: false,
4656 configurable: true,
4657 writable: true,
4658 value: function (sn) {
4659 if (this._processors.postProcessor) {
4660 return this._processors.postProcessor.call(null, sn);
4661 }
4662 return sn;
4663 }
4664 });
4665 Object.defineProperty(SnapshotProcessor.prototype, "_fixNode", {
4666 enumerable: false,
4667 configurable: true,
4668 writable: true,
4669 value: function (node) {
4670 var _this = this;
4671 // the node has to use these methods rather than the original type ones
4672 proxyNodeTypeMethods(node.type, this, "create");
4673 var oldGetSnapshot = node.getSnapshot;
4674 node.getSnapshot = function () {
4675 return _this.postProcessSnapshot(oldGetSnapshot.call(node));
4676 };
4677 if (!isUnionType(this._subtype)) {
4678 node.getReconciliationType = function () {
4679 return _this;
4680 };
4681 }
4682 }
4683 });
4684 Object.defineProperty(SnapshotProcessor.prototype, "instantiate", {
4685 enumerable: false,
4686 configurable: true,
4687 writable: true,
4688 value: function (parent, subpath, environment, initialValue) {
4689 var processedInitialValue = isStateTreeNode(initialValue)
4690 ? initialValue
4691 : this.preProcessSnapshot(initialValue);
4692 var node = this._subtype.instantiate(parent, subpath, environment, processedInitialValue);
4693 this._fixNode(node);
4694 return node;
4695 }
4696 });
4697 Object.defineProperty(SnapshotProcessor.prototype, "reconcile", {
4698 enumerable: false,
4699 configurable: true,
4700 writable: true,
4701 value: function (current, newValue, parent, subpath) {
4702 var node = this._subtype.reconcile(current, isStateTreeNode(newValue) ? newValue : this.preProcessSnapshot(newValue), parent, subpath);
4703 if (node !== current) {
4704 this._fixNode(node);
4705 }
4706 return node;
4707 }
4708 });
4709 Object.defineProperty(SnapshotProcessor.prototype, "getSnapshot", {
4710 enumerable: false,
4711 configurable: true,
4712 writable: true,
4713 value: function (node, applyPostProcess) {
4714 if (applyPostProcess === void 0) { applyPostProcess = true; }
4715 var sn = this._subtype.getSnapshot(node);
4716 return applyPostProcess ? this.postProcessSnapshot(sn) : sn;
4717 }
4718 });
4719 Object.defineProperty(SnapshotProcessor.prototype, "isValidSnapshot", {
4720 enumerable: false,
4721 configurable: true,
4722 writable: true,
4723 value: function (value, context) {
4724 var processedSn = this.preProcessSnapshotSafe(value);
4725 if (processedSn === $preProcessorFailed) {
4726 return typeCheckFailure(context, value, "Failed to preprocess value");
4727 }
4728 return this._subtype.validate(processedSn, context);
4729 }
4730 });
4731 Object.defineProperty(SnapshotProcessor.prototype, "getSubTypes", {
4732 enumerable: false,
4733 configurable: true,
4734 writable: true,
4735 value: function () {
4736 return this._subtype;
4737 }
4738 });
4739 Object.defineProperty(SnapshotProcessor.prototype, "is", {
4740 enumerable: false,
4741 configurable: true,
4742 writable: true,
4743 value: function (thing) {
4744 var value = isType(thing)
4745 ? this._subtype
4746 : isStateTreeNode(thing)
4747 ? getSnapshot(thing, false)
4748 : this.preProcessSnapshotSafe(thing);
4749 if (value === $preProcessorFailed) {
4750 return false;
4751 }
4752 return this._subtype.validate(value, [{ path: "", type: this._subtype }]).length === 0;
4753 }
4754 });
4755 Object.defineProperty(SnapshotProcessor.prototype, "isAssignableFrom", {
4756 enumerable: false,
4757 configurable: true,
4758 writable: true,
4759 value: function (type) {
4760 return this._subtype.isAssignableFrom(type);
4761 }
4762 });
4763 Object.defineProperty(SnapshotProcessor.prototype, "isMatchingSnapshotId", {
4764 enumerable: false,
4765 configurable: true,
4766 writable: true,
4767 value: function (current, snapshot) {
4768 if (!(this._subtype instanceof ComplexType)) {
4769 return false;
4770 }
4771 var processedSn = this.preProcessSnapshot(snapshot);
4772 return this._subtype.isMatchingSnapshotId(current, processedSn);
4773 }
4774 });
4775 return SnapshotProcessor;
4776}(BaseType));
4777function proxyNodeTypeMethods(nodeType, snapshotProcessorType) {
4778 var e_1, _a;
4779 var methods = [];
4780 for (var _i = 2; _i < arguments.length; _i++) {
4781 methods[_i - 2] = arguments[_i];
4782 }
4783 try {
4784 for (var methods_1 = __values(methods), methods_1_1 = methods_1.next(); !methods_1_1.done; methods_1_1 = methods_1.next()) {
4785 var method = methods_1_1.value;
4786 nodeType[method] = snapshotProcessorType[method].bind(snapshotProcessorType);
4787 }
4788 }
4789 catch (e_1_1) { e_1 = { error: e_1_1 }; }
4790 finally {
4791 try {
4792 if (methods_1_1 && !methods_1_1.done && (_a = methods_1.return)) _a.call(methods_1);
4793 }
4794 finally { if (e_1) throw e_1.error; }
4795 }
4796}
4797/**
4798 * `types.snapshotProcessor` - Runs a pre/post snapshot processor before/after serializing a given type.
4799 *
4800 * Example:
4801 * ```ts
4802 * const Todo1 = types.model({ text: types.string })
4803 * // in the backend the text type must be null when empty
4804 * interface BackendTodo {
4805 * text: string | null
4806 * }
4807 * const Todo2 = types.snapshotProcessor(Todo1, {
4808 * // from snapshot to instance
4809 * preProcessor(sn: BackendTodo) {
4810 * return {
4811 * text: sn.text || "";
4812 * }
4813 * },
4814 * // from instance to snapshot
4815 * postProcessor(sn): BackendTodo {
4816 * return {
4817 * text: !sn.text ? null : sn.text
4818 * }
4819 * }
4820 * })
4821 * ```
4822 *
4823 * @param type Type to run the processors over.
4824 * @param processors Processors to run.
4825 * @param name Type name, or undefined to inherit the inner type one.
4826 * @returns
4827 */
4828function snapshotProcessor(type, processors, name) {
4829 assertIsType(type, 1);
4830 if (devMode()) {
4831 if (processors.postProcessor && typeof processors.postProcessor !== "function") {
4832 // istanbul ignore next
4833 throw fail("postSnapshotProcessor must be a function");
4834 }
4835 if (processors.preProcessor && typeof processors.preProcessor !== "function") {
4836 // istanbul ignore next
4837 throw fail("preSnapshotProcessor must be a function");
4838 }
4839 }
4840 return new SnapshotProcessor(type, processors, name);
4841}
4842
4843var needsIdentifierError = "Map.put can only be used to store complex values that have an identifier type attribute";
4844function tryCollectModelTypes(type, modelTypes) {
4845 var e_1, _a;
4846 var subtypes = type.getSubTypes();
4847 if (subtypes === cannotDetermineSubtype) {
4848 return false;
4849 }
4850 if (subtypes) {
4851 var subtypesArray = asArray(subtypes);
4852 try {
4853 for (var subtypesArray_1 = __values(subtypesArray), subtypesArray_1_1 = subtypesArray_1.next(); !subtypesArray_1_1.done; subtypesArray_1_1 = subtypesArray_1.next()) {
4854 var subtype = subtypesArray_1_1.value;
4855 if (!tryCollectModelTypes(subtype, modelTypes))
4856 return false;
4857 }
4858 }
4859 catch (e_1_1) { e_1 = { error: e_1_1 }; }
4860 finally {
4861 try {
4862 if (subtypesArray_1_1 && !subtypesArray_1_1.done && (_a = subtypesArray_1.return)) _a.call(subtypesArray_1);
4863 }
4864 finally { if (e_1) throw e_1.error; }
4865 }
4866 }
4867 if (type instanceof ModelType) {
4868 modelTypes.push(type);
4869 }
4870 return true;
4871}
4872/**
4873 * @internal
4874 * @hidden
4875 */
4876var MapIdentifierMode;
4877(function (MapIdentifierMode) {
4878 MapIdentifierMode[MapIdentifierMode["UNKNOWN"] = 0] = "UNKNOWN";
4879 MapIdentifierMode[MapIdentifierMode["YES"] = 1] = "YES";
4880 MapIdentifierMode[MapIdentifierMode["NO"] = 2] = "NO";
4881})(MapIdentifierMode || (MapIdentifierMode = {}));
4882var MSTMap = /** @class */ (function (_super) {
4883 __extends(MSTMap, _super);
4884 function MSTMap(initialData) {
4885 return _super.call(this, initialData, mobx.observable.ref.enhancer) || this;
4886 }
4887 Object.defineProperty(MSTMap.prototype, "get", {
4888 enumerable: false,
4889 configurable: true,
4890 writable: true,
4891 value: function (key) {
4892 // maybe this is over-enthousiastic? normalize numeric keys to strings
4893 return _super.prototype.get.call(this, "" + key);
4894 }
4895 });
4896 Object.defineProperty(MSTMap.prototype, "has", {
4897 enumerable: false,
4898 configurable: true,
4899 writable: true,
4900 value: function (key) {
4901 return _super.prototype.has.call(this, "" + key);
4902 }
4903 });
4904 Object.defineProperty(MSTMap.prototype, "delete", {
4905 enumerable: false,
4906 configurable: true,
4907 writable: true,
4908 value: function (key) {
4909 return _super.prototype.delete.call(this, "" + key);
4910 }
4911 });
4912 Object.defineProperty(MSTMap.prototype, "set", {
4913 enumerable: false,
4914 configurable: true,
4915 writable: true,
4916 value: function (key, value) {
4917 return _super.prototype.set.call(this, "" + key, value);
4918 }
4919 });
4920 Object.defineProperty(MSTMap.prototype, "put", {
4921 enumerable: false,
4922 configurable: true,
4923 writable: true,
4924 value: function (value) {
4925 if (!value)
4926 throw fail$1("Map.put cannot be used to set empty values");
4927 if (isStateTreeNode(value)) {
4928 var node = getStateTreeNode(value);
4929 if (devMode()) {
4930 if (!node.identifierAttribute) {
4931 throw fail$1(needsIdentifierError);
4932 }
4933 }
4934 if (node.identifier === null) {
4935 throw fail$1(needsIdentifierError);
4936 }
4937 this.set(node.identifier, value);
4938 return value;
4939 }
4940 else if (!isMutable(value)) {
4941 throw fail$1("Map.put can only be used to store complex values");
4942 }
4943 else {
4944 var mapNode = getStateTreeNode(this);
4945 var mapType = mapNode.type;
4946 if (mapType.identifierMode !== MapIdentifierMode.YES) {
4947 throw fail$1(needsIdentifierError);
4948 }
4949 var idAttr = mapType.mapIdentifierAttribute;
4950 var id = value[idAttr];
4951 if (!isValidIdentifier(id)) {
4952 // try again but this time after creating a node for the value
4953 // since it might be an optional identifier
4954 var newNode = this.put(mapType.getChildType().create(value, mapNode.environment));
4955 return this.put(getSnapshot(newNode));
4956 }
4957 var key = normalizeIdentifier(id);
4958 this.set(key, value);
4959 return this.get(key);
4960 }
4961 }
4962 });
4963 return MSTMap;
4964}(mobx.ObservableMap));
4965/**
4966 * @internal
4967 * @hidden
4968 */
4969var MapType = /** @class */ (function (_super) {
4970 __extends(MapType, _super);
4971 function MapType(name, _subType, hookInitializers) {
4972 if (hookInitializers === void 0) { hookInitializers = []; }
4973 var _this = _super.call(this, name) || this;
4974 Object.defineProperty(_this, "_subType", {
4975 enumerable: true,
4976 configurable: true,
4977 writable: true,
4978 value: _subType
4979 });
4980 Object.defineProperty(_this, "identifierMode", {
4981 enumerable: true,
4982 configurable: true,
4983 writable: true,
4984 value: MapIdentifierMode.UNKNOWN
4985 });
4986 Object.defineProperty(_this, "mapIdentifierAttribute", {
4987 enumerable: true,
4988 configurable: true,
4989 writable: true,
4990 value: undefined
4991 });
4992 Object.defineProperty(_this, "flags", {
4993 enumerable: true,
4994 configurable: true,
4995 writable: true,
4996 value: TypeFlags.Map
4997 });
4998 Object.defineProperty(_this, "hookInitializers", {
4999 enumerable: true,
5000 configurable: true,
5001 writable: true,
5002 value: []
5003 });
5004 _this._determineIdentifierMode();
5005 _this.hookInitializers = hookInitializers;
5006 return _this;
5007 }
5008 Object.defineProperty(MapType.prototype, "hooks", {
5009 enumerable: false,
5010 configurable: true,
5011 writable: true,
5012 value: function (hooks) {
5013 var hookInitializers = this.hookInitializers.length > 0 ? this.hookInitializers.concat(hooks) : [hooks];
5014 return new MapType(this.name, this._subType, hookInitializers);
5015 }
5016 });
5017 Object.defineProperty(MapType.prototype, "instantiate", {
5018 enumerable: false,
5019 configurable: true,
5020 writable: true,
5021 value: function (parent, subpath, environment, initialValue) {
5022 this._determineIdentifierMode();
5023 return createObjectNode(this, parent, subpath, environment, initialValue);
5024 }
5025 });
5026 Object.defineProperty(MapType.prototype, "_determineIdentifierMode", {
5027 enumerable: false,
5028 configurable: true,
5029 writable: true,
5030 value: function () {
5031 if (this.identifierMode !== MapIdentifierMode.UNKNOWN) {
5032 return;
5033 }
5034 var modelTypes = [];
5035 if (tryCollectModelTypes(this._subType, modelTypes)) {
5036 var identifierAttribute = modelTypes.reduce(function (current, type) {
5037 if (!type.identifierAttribute)
5038 return current;
5039 if (current && current !== type.identifierAttribute) {
5040 throw fail$1("The objects in a map should all have the same identifier attribute, expected '" + current + "', but child of type '" + type.name + "' declared attribute '" + type.identifierAttribute + "' as identifier");
5041 }
5042 return type.identifierAttribute;
5043 }, undefined);
5044 if (identifierAttribute) {
5045 this.identifierMode = MapIdentifierMode.YES;
5046 this.mapIdentifierAttribute = identifierAttribute;
5047 }
5048 else {
5049 this.identifierMode = MapIdentifierMode.NO;
5050 }
5051 }
5052 }
5053 });
5054 Object.defineProperty(MapType.prototype, "initializeChildNodes", {
5055 enumerable: false,
5056 configurable: true,
5057 writable: true,
5058 value: function (objNode, initialSnapshot) {
5059 if (initialSnapshot === void 0) { initialSnapshot = {}; }
5060 var subType = objNode.type._subType;
5061 var result = {};
5062 Object.keys(initialSnapshot).forEach(function (name) {
5063 result[name] = subType.instantiate(objNode, name, undefined, initialSnapshot[name]);
5064 });
5065 return result;
5066 }
5067 });
5068 Object.defineProperty(MapType.prototype, "createNewInstance", {
5069 enumerable: false,
5070 configurable: true,
5071 writable: true,
5072 value: function (childNodes) {
5073 return new MSTMap(childNodes);
5074 }
5075 });
5076 Object.defineProperty(MapType.prototype, "finalizeNewInstance", {
5077 enumerable: false,
5078 configurable: true,
5079 writable: true,
5080 value: function (node, instance) {
5081 mobx._interceptReads(instance, node.unbox);
5082 var type = node.type;
5083 type.hookInitializers.forEach(function (initializer) {
5084 var hooks = initializer(instance);
5085 Object.keys(hooks).forEach(function (name) {
5086 var hook = hooks[name];
5087 var actionInvoker = createActionInvoker(instance, name, hook);
5088 (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(instance, name, actionInvoker);
5089 });
5090 });
5091 mobx.intercept(instance, this.willChange);
5092 mobx.observe(instance, this.didChange);
5093 }
5094 });
5095 Object.defineProperty(MapType.prototype, "describe", {
5096 enumerable: false,
5097 configurable: true,
5098 writable: true,
5099 value: function () {
5100 return "Map<string, " + this._subType.describe() + ">";
5101 }
5102 });
5103 Object.defineProperty(MapType.prototype, "getChildren", {
5104 enumerable: false,
5105 configurable: true,
5106 writable: true,
5107 value: function (node) {
5108 // return (node.storedValue as ObservableMap<any>).values()
5109 return mobx.values(node.storedValue);
5110 }
5111 });
5112 Object.defineProperty(MapType.prototype, "getChildNode", {
5113 enumerable: false,
5114 configurable: true,
5115 writable: true,
5116 value: function (node, key) {
5117 var childNode = node.storedValue.get("" + key);
5118 if (!childNode)
5119 throw fail$1("Not a child " + key);
5120 return childNode;
5121 }
5122 });
5123 Object.defineProperty(MapType.prototype, "willChange", {
5124 enumerable: false,
5125 configurable: true,
5126 writable: true,
5127 value: function (change) {
5128 var node = getStateTreeNode(change.object);
5129 var key = change.name;
5130 node.assertWritable({ subpath: key });
5131 var mapType = node.type;
5132 var subType = mapType._subType;
5133 switch (change.type) {
5134 case "update":
5135 {
5136 var newValue = change.newValue;
5137 var oldValue = change.object.get(key);
5138 if (newValue === oldValue)
5139 return null;
5140 typecheckInternal(subType, newValue);
5141 change.newValue = subType.reconcile(node.getChildNode(key), change.newValue, node, key);
5142 mapType.processIdentifier(key, change.newValue);
5143 }
5144 break;
5145 case "add":
5146 {
5147 typecheckInternal(subType, change.newValue);
5148 change.newValue = subType.instantiate(node, key, undefined, change.newValue);
5149 mapType.processIdentifier(key, change.newValue);
5150 }
5151 break;
5152 }
5153 return change;
5154 }
5155 });
5156 Object.defineProperty(MapType.prototype, "processIdentifier", {
5157 enumerable: false,
5158 configurable: true,
5159 writable: true,
5160 value: function (expected, node) {
5161 if (this.identifierMode === MapIdentifierMode.YES && node instanceof ObjectNode) {
5162 var identifier = node.identifier;
5163 if (identifier !== expected)
5164 throw fail$1("A map of objects containing an identifier should always store the object under their own identifier. Trying to store key '" + identifier + "', but expected: '" + expected + "'");
5165 }
5166 }
5167 });
5168 Object.defineProperty(MapType.prototype, "getSnapshot", {
5169 enumerable: false,
5170 configurable: true,
5171 writable: true,
5172 value: function (node) {
5173 var res = {};
5174 node.getChildren().forEach(function (childNode) {
5175 res[childNode.subpath] = childNode.snapshot;
5176 });
5177 return res;
5178 }
5179 });
5180 Object.defineProperty(MapType.prototype, "processInitialSnapshot", {
5181 enumerable: false,
5182 configurable: true,
5183 writable: true,
5184 value: function (childNodes) {
5185 var processed = {};
5186 Object.keys(childNodes).forEach(function (key) {
5187 processed[key] = childNodes[key].getSnapshot();
5188 });
5189 return processed;
5190 }
5191 });
5192 Object.defineProperty(MapType.prototype, "didChange", {
5193 enumerable: false,
5194 configurable: true,
5195 writable: true,
5196 value: function (change) {
5197 var node = getStateTreeNode(change.object);
5198 switch (change.type) {
5199 case "update":
5200 return void node.emitPatch({
5201 op: "replace",
5202 path: escapeJsonPath(change.name),
5203 value: change.newValue.snapshot,
5204 oldValue: change.oldValue ? change.oldValue.snapshot : undefined
5205 }, node);
5206 case "add":
5207 return void node.emitPatch({
5208 op: "add",
5209 path: escapeJsonPath(change.name),
5210 value: change.newValue.snapshot,
5211 oldValue: undefined
5212 }, node);
5213 case "delete":
5214 // a node got deleted, get the old snapshot and make the node die
5215 var oldSnapshot = change.oldValue.snapshot;
5216 change.oldValue.die();
5217 // emit the patch
5218 return void node.emitPatch({
5219 op: "remove",
5220 path: escapeJsonPath(change.name),
5221 oldValue: oldSnapshot
5222 }, node);
5223 }
5224 }
5225 });
5226 Object.defineProperty(MapType.prototype, "applyPatchLocally", {
5227 enumerable: false,
5228 configurable: true,
5229 writable: true,
5230 value: function (node, subpath, patch) {
5231 var target = node.storedValue;
5232 switch (patch.op) {
5233 case "add":
5234 case "replace":
5235 target.set(subpath, patch.value);
5236 break;
5237 case "remove":
5238 target.delete(subpath);
5239 break;
5240 }
5241 }
5242 });
5243 Object.defineProperty(MapType.prototype, "applySnapshot", {
5244 enumerable: false,
5245 configurable: true,
5246 writable: true,
5247 value: function (node, snapshot) {
5248 typecheckInternal(this, snapshot);
5249 var target = node.storedValue;
5250 var currentKeys = {};
5251 Array.from(target.keys()).forEach(function (key) {
5252 currentKeys[key] = false;
5253 });
5254 if (snapshot) {
5255 // Don't use target.replace, as it will throw away all existing items first
5256 for (var key in snapshot) {
5257 target.set(key, snapshot[key]);
5258 currentKeys["" + key] = true;
5259 }
5260 }
5261 Object.keys(currentKeys).forEach(function (key) {
5262 if (currentKeys[key] === false)
5263 target.delete(key);
5264 });
5265 }
5266 });
5267 Object.defineProperty(MapType.prototype, "getChildType", {
5268 enumerable: false,
5269 configurable: true,
5270 writable: true,
5271 value: function () {
5272 return this._subType;
5273 }
5274 });
5275 Object.defineProperty(MapType.prototype, "isValidSnapshot", {
5276 enumerable: false,
5277 configurable: true,
5278 writable: true,
5279 value: function (value, context) {
5280 var _this = this;
5281 if (!isPlainObject(value)) {
5282 return typeCheckFailure(context, value, "Value is not a plain object");
5283 }
5284 return flattenTypeErrors(Object.keys(value).map(function (path) {
5285 return _this._subType.validate(value[path], getContextForPath(context, path, _this._subType));
5286 }));
5287 }
5288 });
5289 Object.defineProperty(MapType.prototype, "getDefaultSnapshot", {
5290 enumerable: false,
5291 configurable: true,
5292 writable: true,
5293 value: function () {
5294 return EMPTY_OBJECT;
5295 }
5296 });
5297 Object.defineProperty(MapType.prototype, "removeChild", {
5298 enumerable: false,
5299 configurable: true,
5300 writable: true,
5301 value: function (node, subpath) {
5302 node.storedValue.delete(subpath);
5303 }
5304 });
5305 return MapType;
5306}(ComplexType));
5307MapType.prototype.applySnapshot = mobx.action(MapType.prototype.applySnapshot);
5308/**
5309 * `types.map` - Creates a key based collection type who's children are all of a uniform declared type.
5310 * If the type stored in a map has an identifier, it is mandatory to store the child under that identifier in the map.
5311 *
5312 * This type will always produce [observable maps](https://mobx.js.org/api.html#observablemap)
5313 *
5314 * Example:
5315 * ```ts
5316 * const Todo = types.model({
5317 * id: types.identifier,
5318 * task: types.string
5319 * })
5320 *
5321 * const TodoStore = types.model({
5322 * todos: types.map(Todo)
5323 * })
5324 *
5325 * const s = TodoStore.create({ todos: {} })
5326 * unprotect(s)
5327 * s.todos.set(17, { task: "Grab coffee", id: 17 })
5328 * s.todos.put({ task: "Grab cookie", id: 18 }) // put will infer key from the identifier
5329 * console.log(s.todos.get(17).task) // prints: "Grab coffee"
5330 * ```
5331 *
5332 * @param subtype
5333 * @returns
5334 */
5335function map(subtype) {
5336 return new MapType("map<string, " + subtype.name + ">", subtype);
5337}
5338/**
5339 * Returns if a given value represents a map type.
5340 *
5341 * @param type
5342 * @returns `true` if it is a map type.
5343 */
5344function isMapType(type) {
5345 return isType(type) && (type.flags & TypeFlags.Map) > 0;
5346}
5347
5348/**
5349 * @internal
5350 * @hidden
5351 */
5352var ArrayType = /** @class */ (function (_super) {
5353 __extends(ArrayType, _super);
5354 function ArrayType(name, _subType, hookInitializers) {
5355 if (hookInitializers === void 0) { hookInitializers = []; }
5356 var _this = _super.call(this, name) || this;
5357 Object.defineProperty(_this, "_subType", {
5358 enumerable: true,
5359 configurable: true,
5360 writable: true,
5361 value: _subType
5362 });
5363 Object.defineProperty(_this, "flags", {
5364 enumerable: true,
5365 configurable: true,
5366 writable: true,
5367 value: TypeFlags.Array
5368 });
5369 Object.defineProperty(_this, "hookInitializers", {
5370 enumerable: true,
5371 configurable: true,
5372 writable: true,
5373 value: []
5374 });
5375 _this.hookInitializers = hookInitializers;
5376 return _this;
5377 }
5378 Object.defineProperty(ArrayType.prototype, "hooks", {
5379 enumerable: false,
5380 configurable: true,
5381 writable: true,
5382 value: function (hooks) {
5383 var hookInitializers = this.hookInitializers.length > 0 ? this.hookInitializers.concat(hooks) : [hooks];
5384 return new ArrayType(this.name, this._subType, hookInitializers);
5385 }
5386 });
5387 Object.defineProperty(ArrayType.prototype, "instantiate", {
5388 enumerable: false,
5389 configurable: true,
5390 writable: true,
5391 value: function (parent, subpath, environment, initialValue) {
5392 return createObjectNode(this, parent, subpath, environment, initialValue);
5393 }
5394 });
5395 Object.defineProperty(ArrayType.prototype, "initializeChildNodes", {
5396 enumerable: false,
5397 configurable: true,
5398 writable: true,
5399 value: function (objNode, snapshot) {
5400 if (snapshot === void 0) { snapshot = []; }
5401 var subType = objNode.type._subType;
5402 var result = {};
5403 snapshot.forEach(function (item, index) {
5404 var subpath = "" + index;
5405 result[subpath] = subType.instantiate(objNode, subpath, undefined, item);
5406 });
5407 return result;
5408 }
5409 });
5410 Object.defineProperty(ArrayType.prototype, "createNewInstance", {
5411 enumerable: false,
5412 configurable: true,
5413 writable: true,
5414 value: function (childNodes) {
5415 return mobx.observable.array(convertChildNodesToArray(childNodes), mobxShallow);
5416 }
5417 });
5418 Object.defineProperty(ArrayType.prototype, "finalizeNewInstance", {
5419 enumerable: false,
5420 configurable: true,
5421 writable: true,
5422 value: function (node, instance) {
5423 mobx._getAdministration(instance).dehancer = node.unbox;
5424 var type = node.type;
5425 type.hookInitializers.forEach(function (initializer) {
5426 var hooks = initializer(instance);
5427 Object.keys(hooks).forEach(function (name) {
5428 var hook = hooks[name];
5429 var actionInvoker = createActionInvoker(instance, name, hook);
5430 (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(instance, name, actionInvoker);
5431 });
5432 });
5433 mobx.intercept(instance, this.willChange);
5434 mobx.observe(instance, this.didChange);
5435 }
5436 });
5437 Object.defineProperty(ArrayType.prototype, "describe", {
5438 enumerable: false,
5439 configurable: true,
5440 writable: true,
5441 value: function () {
5442 return this._subType.describe() + "[]";
5443 }
5444 });
5445 Object.defineProperty(ArrayType.prototype, "getChildren", {
5446 enumerable: false,
5447 configurable: true,
5448 writable: true,
5449 value: function (node) {
5450 return node.storedValue.slice();
5451 }
5452 });
5453 Object.defineProperty(ArrayType.prototype, "getChildNode", {
5454 enumerable: false,
5455 configurable: true,
5456 writable: true,
5457 value: function (node, key) {
5458 var index = Number(key);
5459 if (index < node.storedValue.length)
5460 return node.storedValue[index];
5461 throw fail$1("Not a child: " + key);
5462 }
5463 });
5464 Object.defineProperty(ArrayType.prototype, "willChange", {
5465 enumerable: false,
5466 configurable: true,
5467 writable: true,
5468 value: function (change) {
5469 var node = getStateTreeNode(change.object);
5470 node.assertWritable({ subpath: "" + change.index });
5471 var subType = node.type._subType;
5472 var childNodes = node.getChildren();
5473 switch (change.type) {
5474 case "update":
5475 {
5476 if (change.newValue === change.object[change.index])
5477 return null;
5478 var updatedNodes = reconcileArrayChildren(node, subType, [childNodes[change.index]], [change.newValue], [change.index]);
5479 if (!updatedNodes) {
5480 return null;
5481 }
5482 change.newValue = updatedNodes[0];
5483 }
5484 break;
5485 case "splice":
5486 {
5487 var index_1 = change.index, removedCount = change.removedCount, added = change.added;
5488 var addedNodes = reconcileArrayChildren(node, subType, childNodes.slice(index_1, index_1 + removedCount), added, added.map(function (_, i) { return index_1 + i; }));
5489 if (!addedNodes) {
5490 return null;
5491 }
5492 change.added = addedNodes;
5493 // update paths of remaining items
5494 for (var i = index_1 + removedCount; i < childNodes.length; i++) {
5495 childNodes[i].setParent(node, "" + (i + added.length - removedCount));
5496 }
5497 }
5498 break;
5499 }
5500 return change;
5501 }
5502 });
5503 Object.defineProperty(ArrayType.prototype, "getSnapshot", {
5504 enumerable: false,
5505 configurable: true,
5506 writable: true,
5507 value: function (node) {
5508 return node.getChildren().map(function (childNode) { return childNode.snapshot; });
5509 }
5510 });
5511 Object.defineProperty(ArrayType.prototype, "processInitialSnapshot", {
5512 enumerable: false,
5513 configurable: true,
5514 writable: true,
5515 value: function (childNodes) {
5516 var processed = [];
5517 Object.keys(childNodes).forEach(function (key) {
5518 processed.push(childNodes[key].getSnapshot());
5519 });
5520 return processed;
5521 }
5522 });
5523 Object.defineProperty(ArrayType.prototype, "didChange", {
5524 enumerable: false,
5525 configurable: true,
5526 writable: true,
5527 value: function (change) {
5528 var node = getStateTreeNode(change.object);
5529 switch (change.type) {
5530 case "update":
5531 return void node.emitPatch({
5532 op: "replace",
5533 path: "" + change.index,
5534 value: change.newValue.snapshot,
5535 oldValue: change.oldValue ? change.oldValue.snapshot : undefined
5536 }, node);
5537 case "splice":
5538 for (var i = change.removedCount - 1; i >= 0; i--)
5539 node.emitPatch({
5540 op: "remove",
5541 path: "" + (change.index + i),
5542 oldValue: change.removed[i].snapshot
5543 }, node);
5544 for (var i = 0; i < change.addedCount; i++)
5545 node.emitPatch({
5546 op: "add",
5547 path: "" + (change.index + i),
5548 value: node.getChildNode("" + (change.index + i)).snapshot,
5549 oldValue: undefined
5550 }, node);
5551 return;
5552 }
5553 }
5554 });
5555 Object.defineProperty(ArrayType.prototype, "applyPatchLocally", {
5556 enumerable: false,
5557 configurable: true,
5558 writable: true,
5559 value: function (node, subpath, patch) {
5560 var target = node.storedValue;
5561 var index = subpath === "-" ? target.length : Number(subpath);
5562 switch (patch.op) {
5563 case "replace":
5564 target[index] = patch.value;
5565 break;
5566 case "add":
5567 target.splice(index, 0, patch.value);
5568 break;
5569 case "remove":
5570 target.splice(index, 1);
5571 break;
5572 }
5573 }
5574 });
5575 Object.defineProperty(ArrayType.prototype, "applySnapshot", {
5576 enumerable: false,
5577 configurable: true,
5578 writable: true,
5579 value: function (node, snapshot) {
5580 typecheckInternal(this, snapshot);
5581 var target = node.storedValue;
5582 target.replace(snapshot);
5583 }
5584 });
5585 Object.defineProperty(ArrayType.prototype, "getChildType", {
5586 enumerable: false,
5587 configurable: true,
5588 writable: true,
5589 value: function () {
5590 return this._subType;
5591 }
5592 });
5593 Object.defineProperty(ArrayType.prototype, "isValidSnapshot", {
5594 enumerable: false,
5595 configurable: true,
5596 writable: true,
5597 value: function (value, context) {
5598 var _this = this;
5599 if (!isArray(value)) {
5600 return typeCheckFailure(context, value, "Value is not an array");
5601 }
5602 return flattenTypeErrors(value.map(function (item, index) {
5603 return _this._subType.validate(item, getContextForPath(context, "" + index, _this._subType));
5604 }));
5605 }
5606 });
5607 Object.defineProperty(ArrayType.prototype, "getDefaultSnapshot", {
5608 enumerable: false,
5609 configurable: true,
5610 writable: true,
5611 value: function () {
5612 return EMPTY_ARRAY;
5613 }
5614 });
5615 Object.defineProperty(ArrayType.prototype, "removeChild", {
5616 enumerable: false,
5617 configurable: true,
5618 writable: true,
5619 value: function (node, subpath) {
5620 node.storedValue.splice(Number(subpath), 1);
5621 }
5622 });
5623 return ArrayType;
5624}(ComplexType));
5625ArrayType.prototype.applySnapshot = mobx.action(ArrayType.prototype.applySnapshot);
5626/**
5627 * `types.array` - Creates an index based collection type who's children are all of a uniform declared type.
5628 *
5629 * This type will always produce [observable arrays](https://mobx.js.org/api.html#observablearray)
5630 *
5631 * Example:
5632 * ```ts
5633 * const Todo = types.model({
5634 * task: types.string
5635 * })
5636 *
5637 * const TodoStore = types.model({
5638 * todos: types.array(Todo)
5639 * })
5640 *
5641 * const s = TodoStore.create({ todos: [] })
5642 * unprotect(s) // needed to allow modifying outside of an action
5643 * s.todos.push({ task: "Grab coffee" })
5644 * console.log(s.todos[0]) // prints: "Grab coffee"
5645 * ```
5646 *
5647 * @param subtype
5648 * @returns
5649 */
5650function array(subtype) {
5651 assertIsType(subtype, 1);
5652 return new ArrayType(subtype.name + "[]", subtype);
5653}
5654function reconcileArrayChildren(parent, childType, oldNodes, newValues, newPaths) {
5655 var nothingChanged = true;
5656 for (var i = 0;; i++) {
5657 var hasNewNode = i <= newValues.length - 1;
5658 var oldNode = oldNodes[i];
5659 var newValue = hasNewNode ? newValues[i] : undefined;
5660 var newPath = "" + newPaths[i];
5661 // for some reason, instead of newValue we got a node, fallback to the storedValue
5662 // TODO: https://github.com/mobxjs/mobx-state-tree/issues/340#issuecomment-325581681
5663 if (isNode(newValue))
5664 newValue = newValue.storedValue;
5665 if (!oldNode && !hasNewNode) {
5666 // both are empty, end
5667 break;
5668 }
5669 else if (!hasNewNode) {
5670 // new one does not exists
5671 nothingChanged = false;
5672 oldNodes.splice(i, 1);
5673 if (oldNode instanceof ObjectNode) {
5674 // since it is going to be returned by pop/splice/shift better create it before killing it
5675 // so it doesn't end up in an undead state
5676 oldNode.createObservableInstanceIfNeeded();
5677 }
5678 oldNode.die();
5679 i--;
5680 }
5681 else if (!oldNode) {
5682 // there is no old node, create it
5683 // check if already belongs to the same parent. if so, avoid pushing item in. only swapping can occur.
5684 if (isStateTreeNode(newValue) && getStateTreeNode(newValue).parent === parent) {
5685 // this node is owned by this parent, but not in the reconcilable set, so it must be double
5686 throw fail$1("Cannot add an object to a state tree if it is already part of the same or another state tree. Tried to assign an object to '" + parent.path + "/" + newPath + "', but it lives already at '" + getStateTreeNode(newValue).path + "'");
5687 }
5688 nothingChanged = false;
5689 var newNode = valueAsNode(childType, parent, newPath, newValue);
5690 oldNodes.splice(i, 0, newNode);
5691 }
5692 else if (areSame(oldNode, newValue)) {
5693 // both are the same, reconcile
5694 oldNodes[i] = valueAsNode(childType, parent, newPath, newValue, oldNode);
5695 }
5696 else {
5697 // nothing to do, try to reorder
5698 var oldMatch = undefined;
5699 // find a possible candidate to reuse
5700 for (var j = i; j < oldNodes.length; j++) {
5701 if (areSame(oldNodes[j], newValue)) {
5702 oldMatch = oldNodes.splice(j, 1)[0];
5703 break;
5704 }
5705 }
5706 nothingChanged = false;
5707 var newNode = valueAsNode(childType, parent, newPath, newValue, oldMatch);
5708 oldNodes.splice(i, 0, newNode);
5709 }
5710 }
5711 return nothingChanged ? null : oldNodes;
5712}
5713/**
5714 * Convert a value to a node at given parent and subpath. Attempts to reuse old node if possible and given.
5715 */
5716function valueAsNode(childType, parent, subpath, newValue, oldNode) {
5717 // ensure the value is valid-ish
5718 typecheckInternal(childType, newValue);
5719 function getNewNode() {
5720 // the new value has a MST node
5721 if (isStateTreeNode(newValue)) {
5722 var childNode = getStateTreeNode(newValue);
5723 childNode.assertAlive(EMPTY_OBJECT);
5724 // the node lives here
5725 if (childNode.parent !== null && childNode.parent === parent) {
5726 childNode.setParent(parent, subpath);
5727 return childNode;
5728 }
5729 }
5730 // there is old node and new one is a value/snapshot
5731 if (oldNode) {
5732 return childType.reconcile(oldNode, newValue, parent, subpath);
5733 }
5734 // nothing to do, create from scratch
5735 return childType.instantiate(parent, subpath, undefined, newValue);
5736 }
5737 var newNode = getNewNode();
5738 if (oldNode && oldNode !== newNode) {
5739 if (oldNode instanceof ObjectNode) {
5740 // since it is going to be returned by pop/splice/shift better create it before killing it
5741 // so it doesn't end up in an undead state
5742 oldNode.createObservableInstanceIfNeeded();
5743 }
5744 oldNode.die();
5745 }
5746 return newNode;
5747}
5748/**
5749 * Check if a node holds a value.
5750 */
5751function areSame(oldNode, newValue) {
5752 // never consider dead old nodes for reconciliation
5753 if (!oldNode.isAlive) {
5754 return false;
5755 }
5756 // the new value has the same node
5757 if (isStateTreeNode(newValue)) {
5758 var newNode = getStateTreeNode(newValue);
5759 return newNode.isAlive && newNode === oldNode;
5760 }
5761 // the provided value is the snapshot of the old node
5762 if (oldNode.snapshot === newValue) {
5763 return true;
5764 }
5765 // Non object nodes don't get reconciled
5766 if (!(oldNode instanceof ObjectNode)) {
5767 return false;
5768 }
5769 var oldNodeType = oldNode.getReconciliationType();
5770 // new value is a snapshot with the correct identifier
5771 return (oldNode.identifier !== null &&
5772 oldNode.identifierAttribute &&
5773 isPlainObject(newValue) &&
5774 oldNodeType.is(newValue) &&
5775 oldNodeType.isMatchingSnapshotId(oldNode, newValue));
5776}
5777/**
5778 * Returns if a given value represents an array type.
5779 *
5780 * @param type
5781 * @returns `true` if the type is an array type.
5782 */
5783function isArrayType(type) {
5784 return isType(type) && (type.flags & TypeFlags.Array) > 0;
5785}
5786
5787var PRE_PROCESS_SNAPSHOT = "preProcessSnapshot";
5788var POST_PROCESS_SNAPSHOT = "postProcessSnapshot";
5789function objectTypeToString() {
5790 return getStateTreeNode(this).toString();
5791}
5792var defaultObjectOptions = {
5793 name: "AnonymousModel",
5794 properties: {},
5795 initializers: EMPTY_ARRAY
5796};
5797function toPropertiesObject(declaredProps) {
5798 // loop through properties and ensures that all items are types
5799 return Object.keys(declaredProps).reduce(function (props, key) {
5800 var _a, _b, _c;
5801 // warn if user intended a HOOK
5802 if (key in Hook)
5803 throw fail$1("Hook '" + key + "' was defined as property. Hooks should be defined as part of the actions");
5804 // the user intended to use a view
5805 var descriptor = Object.getOwnPropertyDescriptor(props, key);
5806 if ("get" in descriptor) {
5807 throw fail$1("Getters are not supported as properties. Please use views instead");
5808 }
5809 // undefined and null are not valid
5810 var value = descriptor.value;
5811 if (value === null || value === undefined) {
5812 throw fail$1("The default value of an attribute cannot be null or undefined as the type cannot be inferred. Did you mean `types.maybe(someType)`?");
5813 // its a primitive, convert to its type
5814 }
5815 else if (isPrimitive(value)) {
5816 return Object.assign({}, props, (_a = {},
5817 _a[key] = optional(getPrimitiveFactoryFromValue(value), value),
5818 _a));
5819 // map defaults to empty object automatically for models
5820 }
5821 else if (value instanceof MapType) {
5822 return Object.assign({}, props, (_b = {},
5823 _b[key] = optional(value, {}),
5824 _b));
5825 }
5826 else if (value instanceof ArrayType) {
5827 return Object.assign({}, props, (_c = {}, _c[key] = optional(value, []), _c));
5828 // its already a type
5829 }
5830 else if (isType(value)) {
5831 return props;
5832 // its a function, maybe the user wanted a view?
5833 }
5834 else if (devMode() && typeof value === "function") {
5835 throw fail$1("Invalid type definition for property '" + key + "', it looks like you passed a function. Did you forget to invoke it, or did you intend to declare a view / action?");
5836 // no other complex values
5837 }
5838 else if (devMode() && typeof value === "object") {
5839 throw fail$1("Invalid type definition for property '" + key + "', it looks like you passed an object. Try passing another model type or a types.frozen.");
5840 // WTF did you pass in mate?
5841 }
5842 else {
5843 throw fail$1("Invalid type definition for property '" + key + "', cannot infer a type from a value like '" + value + "' (" + typeof value + ")");
5844 }
5845 }, declaredProps);
5846}
5847/**
5848 * @internal
5849 * @hidden
5850 */
5851var ModelType = /** @class */ (function (_super) {
5852 __extends(ModelType, _super);
5853 function ModelType(opts) {
5854 var _this = _super.call(this, opts.name || defaultObjectOptions.name) || this;
5855 Object.defineProperty(_this, "flags", {
5856 enumerable: true,
5857 configurable: true,
5858 writable: true,
5859 value: TypeFlags.Object
5860 });
5861 /*
5862 * The original object definition
5863 */
5864 Object.defineProperty(_this, "initializers", {
5865 enumerable: true,
5866 configurable: true,
5867 writable: true,
5868 value: void 0
5869 });
5870 Object.defineProperty(_this, "properties", {
5871 enumerable: true,
5872 configurable: true,
5873 writable: true,
5874 value: void 0
5875 });
5876 Object.defineProperty(_this, "preProcessor", {
5877 enumerable: true,
5878 configurable: true,
5879 writable: true,
5880 value: void 0
5881 });
5882 Object.defineProperty(_this, "postProcessor", {
5883 enumerable: true,
5884 configurable: true,
5885 writable: true,
5886 value: void 0
5887 });
5888 Object.defineProperty(_this, "propertyNames", {
5889 enumerable: true,
5890 configurable: true,
5891 writable: true,
5892 value: void 0
5893 });
5894 Object.defineProperty(_this, "named", {
5895 enumerable: true,
5896 configurable: true,
5897 writable: true,
5898 value: function (name) {
5899 return _this.cloneAndEnhance({ name: name });
5900 }
5901 });
5902 Object.defineProperty(_this, "props", {
5903 enumerable: true,
5904 configurable: true,
5905 writable: true,
5906 value: function (properties) {
5907 return _this.cloneAndEnhance({ properties: properties });
5908 }
5909 });
5910 Object.defineProperty(_this, "preProcessSnapshot", {
5911 enumerable: true,
5912 configurable: true,
5913 writable: true,
5914 value: function (preProcessor) {
5915 var currentPreprocessor = _this.preProcessor;
5916 if (!currentPreprocessor)
5917 return _this.cloneAndEnhance({ preProcessor: preProcessor });
5918 else
5919 return _this.cloneAndEnhance({
5920 preProcessor: function (snapshot) { return currentPreprocessor(preProcessor(snapshot)); }
5921 });
5922 }
5923 });
5924 Object.defineProperty(_this, "postProcessSnapshot", {
5925 enumerable: true,
5926 configurable: true,
5927 writable: true,
5928 value: function (postProcessor) {
5929 var currentPostprocessor = _this.postProcessor;
5930 if (!currentPostprocessor)
5931 return _this.cloneAndEnhance({ postProcessor: postProcessor });
5932 else
5933 return _this.cloneAndEnhance({
5934 postProcessor: function (snapshot) { return postProcessor(currentPostprocessor(snapshot)); }
5935 });
5936 }
5937 });
5938 Object.assign(_this, defaultObjectOptions, opts);
5939 // ensures that any default value gets converted to its related type
5940 _this.properties = toPropertiesObject(_this.properties);
5941 freeze(_this.properties); // make sure nobody messes with it
5942 _this.propertyNames = Object.keys(_this.properties);
5943 _this.identifierAttribute = _this._getIdentifierAttribute();
5944 return _this;
5945 }
5946 Object.defineProperty(ModelType.prototype, "_getIdentifierAttribute", {
5947 enumerable: false,
5948 configurable: true,
5949 writable: true,
5950 value: function () {
5951 var identifierAttribute = undefined;
5952 this.forAllProps(function (propName, propType) {
5953 if (propType.flags & TypeFlags.Identifier) {
5954 if (identifierAttribute)
5955 throw fail$1("Cannot define property '" + propName + "' as object identifier, property '" + identifierAttribute + "' is already defined as identifier property");
5956 identifierAttribute = propName;
5957 }
5958 });
5959 return identifierAttribute;
5960 }
5961 });
5962 Object.defineProperty(ModelType.prototype, "cloneAndEnhance", {
5963 enumerable: false,
5964 configurable: true,
5965 writable: true,
5966 value: function (opts) {
5967 return new ModelType({
5968 name: opts.name || this.name,
5969 properties: Object.assign({}, this.properties, opts.properties),
5970 initializers: this.initializers.concat(opts.initializers || []),
5971 preProcessor: opts.preProcessor || this.preProcessor,
5972 postProcessor: opts.postProcessor || this.postProcessor
5973 });
5974 }
5975 });
5976 Object.defineProperty(ModelType.prototype, "actions", {
5977 enumerable: false,
5978 configurable: true,
5979 writable: true,
5980 value: function (fn) {
5981 var _this = this;
5982 var actionInitializer = function (self) {
5983 _this.instantiateActions(self, fn(self));
5984 return self;
5985 };
5986 return this.cloneAndEnhance({ initializers: [actionInitializer] });
5987 }
5988 });
5989 Object.defineProperty(ModelType.prototype, "instantiateActions", {
5990 enumerable: false,
5991 configurable: true,
5992 writable: true,
5993 value: function (self, actions) {
5994 // check if return is correct
5995 if (!isPlainObject(actions))
5996 throw fail$1("actions initializer should return a plain object containing actions");
5997 // bind actions to the object created
5998 Object.keys(actions).forEach(function (name) {
5999 // warn if preprocessor was given
6000 if (name === PRE_PROCESS_SNAPSHOT)
6001 throw fail$1("Cannot define action '" + PRE_PROCESS_SNAPSHOT + "', it should be defined using 'type.preProcessSnapshot(fn)' instead");
6002 // warn if postprocessor was given
6003 if (name === POST_PROCESS_SNAPSHOT)
6004 throw fail$1("Cannot define action '" + POST_PROCESS_SNAPSHOT + "', it should be defined using 'type.postProcessSnapshot(fn)' instead");
6005 var action2 = actions[name];
6006 // apply hook composition
6007 var baseAction = self[name];
6008 if (name in Hook && baseAction) {
6009 var specializedAction_1 = action2;
6010 action2 = function () {
6011 baseAction.apply(null, arguments);
6012 specializedAction_1.apply(null, arguments);
6013 };
6014 }
6015 // the goal of this is to make sure actions using "this" can call themselves,
6016 // while still allowing the middlewares to register them
6017 var middlewares = action2.$mst_middleware; // make sure middlewares are not lost
6018 var boundAction = action2.bind(actions);
6019 boundAction.$mst_middleware = middlewares;
6020 var actionInvoker = createActionInvoker(self, name, boundAction);
6021 actions[name] = actionInvoker;
6022 (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(self, name, actionInvoker);
6023 });
6024 }
6025 });
6026 Object.defineProperty(ModelType.prototype, "volatile", {
6027 enumerable: false,
6028 configurable: true,
6029 writable: true,
6030 value: function (fn) {
6031 var _this = this;
6032 if (typeof fn !== "function") {
6033 throw fail$1("You passed an " + typeof fn + " to volatile state as an argument, when function is expected");
6034 }
6035 var stateInitializer = function (self) {
6036 _this.instantiateVolatileState(self, fn(self));
6037 return self;
6038 };
6039 return this.cloneAndEnhance({ initializers: [stateInitializer] });
6040 }
6041 });
6042 Object.defineProperty(ModelType.prototype, "instantiateVolatileState", {
6043 enumerable: false,
6044 configurable: true,
6045 writable: true,
6046 value: function (self, state) {
6047 // check views return
6048 if (!isPlainObject(state))
6049 throw fail$1("volatile state initializer should return a plain object containing state");
6050 mobx.set(self, state);
6051 }
6052 });
6053 Object.defineProperty(ModelType.prototype, "extend", {
6054 enumerable: false,
6055 configurable: true,
6056 writable: true,
6057 value: function (fn) {
6058 var _this = this;
6059 var initializer = function (self) {
6060 var _a = fn(self), actions = _a.actions, views = _a.views, state = _a.state, rest = __rest(_a, ["actions", "views", "state"]);
6061 for (var key in rest)
6062 throw fail$1("The `extend` function should return an object with a subset of the fields 'actions', 'views' and 'state'. Found invalid key '" + key + "'");
6063 if (state)
6064 _this.instantiateVolatileState(self, state);
6065 if (views)
6066 _this.instantiateViews(self, views);
6067 if (actions)
6068 _this.instantiateActions(self, actions);
6069 return self;
6070 };
6071 return this.cloneAndEnhance({ initializers: [initializer] });
6072 }
6073 });
6074 Object.defineProperty(ModelType.prototype, "views", {
6075 enumerable: false,
6076 configurable: true,
6077 writable: true,
6078 value: function (fn) {
6079 var _this = this;
6080 var viewInitializer = function (self) {
6081 _this.instantiateViews(self, fn(self));
6082 return self;
6083 };
6084 return this.cloneAndEnhance({ initializers: [viewInitializer] });
6085 }
6086 });
6087 Object.defineProperty(ModelType.prototype, "instantiateViews", {
6088 enumerable: false,
6089 configurable: true,
6090 writable: true,
6091 value: function (self, views) {
6092 // check views return
6093 if (!isPlainObject(views))
6094 throw fail$1("views initializer should return a plain object containing views");
6095 Object.getOwnPropertyNames(views).forEach(function (key) {
6096 var _a;
6097 // is this a computed property?
6098 var descriptor = Object.getOwnPropertyDescriptor(views, key);
6099 if ("get" in descriptor) {
6100 mobx.defineProperty(self, key, descriptor);
6101 mobx.makeObservable(self, (_a = {}, _a[key] = mobx.computed, _a));
6102 }
6103 else if (typeof descriptor.value === "function") {
6104 (!devMode() ? addHiddenFinalProp : addHiddenWritableProp)(self, key, descriptor.value);
6105 }
6106 else {
6107 throw fail$1("A view member should either be a function or getter based property");
6108 }
6109 });
6110 }
6111 });
6112 Object.defineProperty(ModelType.prototype, "instantiate", {
6113 enumerable: false,
6114 configurable: true,
6115 writable: true,
6116 value: function (parent, subpath, environment, initialValue) {
6117 var value = isStateTreeNode(initialValue)
6118 ? initialValue
6119 : this.applySnapshotPreProcessor(initialValue);
6120 return createObjectNode(this, parent, subpath, environment, value);
6121 // Optimization: record all prop- view- and action names after first construction, and generate an optimal base class
6122 // that pre-reserves all these fields for fast object-member lookups
6123 }
6124 });
6125 Object.defineProperty(ModelType.prototype, "initializeChildNodes", {
6126 enumerable: false,
6127 configurable: true,
6128 writable: true,
6129 value: function (objNode, initialSnapshot) {
6130 if (initialSnapshot === void 0) { initialSnapshot = {}; }
6131 var type = objNode.type;
6132 var result = {};
6133 type.forAllProps(function (name, childType) {
6134 result[name] = childType.instantiate(objNode, name, undefined, initialSnapshot[name]);
6135 });
6136 return result;
6137 }
6138 });
6139 Object.defineProperty(ModelType.prototype, "createNewInstance", {
6140 enumerable: false,
6141 configurable: true,
6142 writable: true,
6143 value: function (childNodes) {
6144 return mobx.observable.object(childNodes, EMPTY_OBJECT, mobxShallow);
6145 }
6146 });
6147 Object.defineProperty(ModelType.prototype, "finalizeNewInstance", {
6148 enumerable: false,
6149 configurable: true,
6150 writable: true,
6151 value: function (node, instance) {
6152 addHiddenFinalProp(instance, "toString", objectTypeToString);
6153 this.forAllProps(function (name) {
6154 mobx._interceptReads(instance, name, node.unbox);
6155 });
6156 this.initializers.reduce(function (self, fn) { return fn(self); }, instance);
6157 mobx.intercept(instance, this.willChange);
6158 mobx.observe(instance, this.didChange);
6159 }
6160 });
6161 Object.defineProperty(ModelType.prototype, "willChange", {
6162 enumerable: false,
6163 configurable: true,
6164 writable: true,
6165 value: function (chg) {
6166 // TODO: mobx typings don't seem to take into account that newValue can be set even when removing a prop
6167 var change = chg;
6168 var node = getStateTreeNode(change.object);
6169 var subpath = change.name;
6170 node.assertWritable({ subpath: subpath });
6171 var childType = node.type.properties[subpath];
6172 // only properties are typed, state are stored as-is references
6173 if (childType) {
6174 typecheckInternal(childType, change.newValue);
6175 change.newValue = childType.reconcile(node.getChildNode(subpath), change.newValue, node, subpath);
6176 }
6177 return change;
6178 }
6179 });
6180 Object.defineProperty(ModelType.prototype, "didChange", {
6181 enumerable: false,
6182 configurable: true,
6183 writable: true,
6184 value: function (chg) {
6185 // TODO: mobx typings don't seem to take into account that newValue can be set even when removing a prop
6186 var change = chg;
6187 var childNode = getStateTreeNode(change.object);
6188 var childType = childNode.type.properties[change.name];
6189 if (!childType) {
6190 // don't emit patches for volatile state
6191 return;
6192 }
6193 var oldChildValue = change.oldValue ? change.oldValue.snapshot : undefined;
6194 childNode.emitPatch({
6195 op: "replace",
6196 path: escapeJsonPath(change.name),
6197 value: change.newValue.snapshot,
6198 oldValue: oldChildValue
6199 }, childNode);
6200 }
6201 });
6202 Object.defineProperty(ModelType.prototype, "getChildren", {
6203 enumerable: false,
6204 configurable: true,
6205 writable: true,
6206 value: function (node) {
6207 var _this = this;
6208 var res = [];
6209 this.forAllProps(function (name) {
6210 res.push(_this.getChildNode(node, name));
6211 });
6212 return res;
6213 }
6214 });
6215 Object.defineProperty(ModelType.prototype, "getChildNode", {
6216 enumerable: false,
6217 configurable: true,
6218 writable: true,
6219 value: function (node, key) {
6220 if (!(key in this.properties))
6221 throw fail$1("Not a value property: " + key);
6222 var adm = mobx._getAdministration(node.storedValue, key);
6223 var childNode = adm.raw();
6224 if (!childNode)
6225 throw fail$1("Node not available for property " + key);
6226 return childNode;
6227 }
6228 });
6229 Object.defineProperty(ModelType.prototype, "getSnapshot", {
6230 enumerable: false,
6231 configurable: true,
6232 writable: true,
6233 value: function (node, applyPostProcess) {
6234 var _this = this;
6235 if (applyPostProcess === void 0) { applyPostProcess = true; }
6236 var res = {};
6237 this.forAllProps(function (name, type) {
6238 mobx.getAtom(node.storedValue, name).reportObserved();
6239 res[name] = _this.getChildNode(node, name).snapshot;
6240 });
6241 if (applyPostProcess) {
6242 return this.applySnapshotPostProcessor(res);
6243 }
6244 return res;
6245 }
6246 });
6247 Object.defineProperty(ModelType.prototype, "processInitialSnapshot", {
6248 enumerable: false,
6249 configurable: true,
6250 writable: true,
6251 value: function (childNodes) {
6252 var processed = {};
6253 Object.keys(childNodes).forEach(function (key) {
6254 processed[key] = childNodes[key].getSnapshot();
6255 });
6256 return this.applySnapshotPostProcessor(processed);
6257 }
6258 });
6259 Object.defineProperty(ModelType.prototype, "applyPatchLocally", {
6260 enumerable: false,
6261 configurable: true,
6262 writable: true,
6263 value: function (node, subpath, patch) {
6264 if (!(patch.op === "replace" || patch.op === "add")) {
6265 throw fail$1("object does not support operation " + patch.op);
6266 }
6267 node.storedValue[subpath] = patch.value;
6268 }
6269 });
6270 Object.defineProperty(ModelType.prototype, "applySnapshot", {
6271 enumerable: false,
6272 configurable: true,
6273 writable: true,
6274 value: function (node, snapshot) {
6275 var preProcessedSnapshot = this.applySnapshotPreProcessor(snapshot);
6276 typecheckInternal(this, preProcessedSnapshot);
6277 this.forAllProps(function (name) {
6278 node.storedValue[name] = preProcessedSnapshot[name];
6279 });
6280 }
6281 });
6282 Object.defineProperty(ModelType.prototype, "applySnapshotPreProcessor", {
6283 enumerable: false,
6284 configurable: true,
6285 writable: true,
6286 value: function (snapshot) {
6287 var processor = this.preProcessor;
6288 return processor ? processor.call(null, snapshot) : snapshot;
6289 }
6290 });
6291 Object.defineProperty(ModelType.prototype, "applySnapshotPostProcessor", {
6292 enumerable: false,
6293 configurable: true,
6294 writable: true,
6295 value: function (snapshot) {
6296 var postProcessor = this.postProcessor;
6297 if (postProcessor)
6298 return postProcessor.call(null, snapshot);
6299 return snapshot;
6300 }
6301 });
6302 Object.defineProperty(ModelType.prototype, "getChildType", {
6303 enumerable: false,
6304 configurable: true,
6305 writable: true,
6306 value: function (propertyName) {
6307 assertIsString(propertyName, 1);
6308 return this.properties[propertyName];
6309 }
6310 });
6311 Object.defineProperty(ModelType.prototype, "isValidSnapshot", {
6312 enumerable: false,
6313 configurable: true,
6314 writable: true,
6315 value: function (value, context) {
6316 var _this = this;
6317 var snapshot = this.applySnapshotPreProcessor(value);
6318 if (!isPlainObject(snapshot)) {
6319 return typeCheckFailure(context, snapshot, "Value is not a plain object");
6320 }
6321 return flattenTypeErrors(this.propertyNames.map(function (key) {
6322 return _this.properties[key].validate(snapshot[key], getContextForPath(context, key, _this.properties[key]));
6323 }));
6324 }
6325 });
6326 Object.defineProperty(ModelType.prototype, "forAllProps", {
6327 enumerable: false,
6328 configurable: true,
6329 writable: true,
6330 value: function (fn) {
6331 var _this = this;
6332 this.propertyNames.forEach(function (key) { return fn(key, _this.properties[key]); });
6333 }
6334 });
6335 Object.defineProperty(ModelType.prototype, "describe", {
6336 enumerable: false,
6337 configurable: true,
6338 writable: true,
6339 value: function () {
6340 var _this = this;
6341 // optimization: cache
6342 return ("{ " +
6343 this.propertyNames
6344 .map(function (key) { return key + ": " + _this.properties[key].describe(); })
6345 .join("; ") +
6346 " }");
6347 }
6348 });
6349 Object.defineProperty(ModelType.prototype, "getDefaultSnapshot", {
6350 enumerable: false,
6351 configurable: true,
6352 writable: true,
6353 value: function () {
6354 return EMPTY_OBJECT;
6355 }
6356 });
6357 Object.defineProperty(ModelType.prototype, "removeChild", {
6358 enumerable: false,
6359 configurable: true,
6360 writable: true,
6361 value: function (node, subpath) {
6362 node.storedValue[subpath] = undefined;
6363 }
6364 });
6365 return ModelType;
6366}(ComplexType));
6367ModelType.prototype.applySnapshot = mobx.action(ModelType.prototype.applySnapshot);
6368/**
6369 * `types.model` - Creates a new model type by providing a name, properties, volatile state and actions.
6370 *
6371 * See the [model type](/concepts/trees#creating-models) description or the [getting started](intro/getting-started.md#getting-started-1) tutorial.
6372 */
6373function model() {
6374 var args = [];
6375 for (var _i = 0; _i < arguments.length; _i++) {
6376 args[_i] = arguments[_i];
6377 }
6378 var name = typeof args[0] === "string" ? args.shift() : "AnonymousModel";
6379 var properties = args.shift() || {};
6380 return new ModelType({ name: name, properties: properties });
6381}
6382/**
6383 * `types.compose` - Composes a new model from one or more existing model types.
6384 * This method can be invoked in two forms:
6385 * Given 2 or more model types, the types are composed into a new Type.
6386 * Given first parameter as a string and 2 or more model types,
6387 * the types are composed into a new Type with the given name
6388 */
6389function compose() {
6390 var args = [];
6391 for (var _i = 0; _i < arguments.length; _i++) {
6392 args[_i] = arguments[_i];
6393 }
6394 // TODO: just join the base type names if no name is provided
6395 var hasTypename = typeof args[0] === "string";
6396 var typeName = hasTypename ? args[0] : "AnonymousModel";
6397 if (hasTypename) {
6398 args.shift();
6399 }
6400 // check all parameters
6401 if (devMode()) {
6402 args.forEach(function (type, i) {
6403 assertArg(type, isModelType, "mobx-state-tree model type", hasTypename ? i + 2 : i + 1);
6404 });
6405 }
6406 return args
6407 .reduce(function (prev, cur) {
6408 return prev.cloneAndEnhance({
6409 name: prev.name + "_" + cur.name,
6410 properties: cur.properties,
6411 initializers: cur.initializers,
6412 preProcessor: function (snapshot) {
6413 return cur.applySnapshotPreProcessor(prev.applySnapshotPreProcessor(snapshot));
6414 },
6415 postProcessor: function (snapshot) {
6416 return cur.applySnapshotPostProcessor(prev.applySnapshotPostProcessor(snapshot));
6417 }
6418 });
6419 })
6420 .named(typeName);
6421}
6422/**
6423 * Returns if a given value represents a model type.
6424 *
6425 * @param type
6426 * @returns
6427 */
6428function isModelType(type) {
6429 return isType(type) && (type.flags & TypeFlags.Object) > 0;
6430}
6431
6432// TODO: implement CoreType using types.custom ?
6433/**
6434 * @internal
6435 * @hidden
6436 */
6437var CoreType = /** @class */ (function (_super) {
6438 __extends(CoreType, _super);
6439 function CoreType(name, flags, checker, initializer) {
6440 if (initializer === void 0) { initializer = identity; }
6441 var _this = _super.call(this, name) || this;
6442 Object.defineProperty(_this, "flags", {
6443 enumerable: true,
6444 configurable: true,
6445 writable: true,
6446 value: flags
6447 });
6448 Object.defineProperty(_this, "checker", {
6449 enumerable: true,
6450 configurable: true,
6451 writable: true,
6452 value: checker
6453 });
6454 Object.defineProperty(_this, "initializer", {
6455 enumerable: true,
6456 configurable: true,
6457 writable: true,
6458 value: initializer
6459 });
6460 _this.flags = flags;
6461 return _this;
6462 }
6463 Object.defineProperty(CoreType.prototype, "describe", {
6464 enumerable: false,
6465 configurable: true,
6466 writable: true,
6467 value: function () {
6468 return this.name;
6469 }
6470 });
6471 Object.defineProperty(CoreType.prototype, "instantiate", {
6472 enumerable: false,
6473 configurable: true,
6474 writable: true,
6475 value: function (parent, subpath, environment, initialValue) {
6476 return createScalarNode(this, parent, subpath, environment, initialValue);
6477 }
6478 });
6479 Object.defineProperty(CoreType.prototype, "createNewInstance", {
6480 enumerable: false,
6481 configurable: true,
6482 writable: true,
6483 value: function (snapshot) {
6484 return this.initializer(snapshot);
6485 }
6486 });
6487 Object.defineProperty(CoreType.prototype, "isValidSnapshot", {
6488 enumerable: false,
6489 configurable: true,
6490 writable: true,
6491 value: function (value, context) {
6492 if (isPrimitive(value) && this.checker(value)) {
6493 return typeCheckSuccess();
6494 }
6495 var typeName = this.name === "Date" ? "Date or a unix milliseconds timestamp" : this.name;
6496 return typeCheckFailure(context, value, "Value is not a " + typeName);
6497 }
6498 });
6499 return CoreType;
6500}(SimpleType));
6501/**
6502 * `types.string` - Creates a type that can only contain a string value.
6503 * This type is used for string values by default
6504 *
6505 * Example:
6506 * ```ts
6507 * const Person = types.model({
6508 * firstName: types.string,
6509 * lastName: "Doe"
6510 * })
6511 * ```
6512 */
6513// tslint:disable-next-line:variable-name
6514var string = new CoreType("string", TypeFlags.String, function (v) { return typeof v === "string"; });
6515/**
6516 * `types.number` - Creates a type that can only contain a numeric value.
6517 * This type is used for numeric values by default
6518 *
6519 * Example:
6520 * ```ts
6521 * const Vector = types.model({
6522 * x: types.number,
6523 * y: 1.5
6524 * })
6525 * ```
6526 */
6527// tslint:disable-next-line:variable-name
6528var number = new CoreType("number", TypeFlags.Number, function (v) { return typeof v === "number"; });
6529/**
6530 * `types.integer` - Creates a type that can only contain an integer value.
6531 * This type is used for integer values by default
6532 *
6533 * Example:
6534 * ```ts
6535 * const Size = types.model({
6536 * width: types.integer,
6537 * height: 10
6538 * })
6539 * ```
6540 */
6541// tslint:disable-next-line:variable-name
6542var integer = new CoreType("integer", TypeFlags.Integer, function (v) { return isInteger(v); });
6543/**
6544 * `types.boolean` - Creates a type that can only contain a boolean value.
6545 * This type is used for boolean values by default
6546 *
6547 * Example:
6548 * ```ts
6549 * const Thing = types.model({
6550 * isCool: types.boolean,
6551 * isAwesome: false
6552 * })
6553 * ```
6554 */
6555// tslint:disable-next-line:variable-name
6556var boolean = new CoreType("boolean", TypeFlags.Boolean, function (v) { return typeof v === "boolean"; });
6557/**
6558 * `types.null` - The type of the value `null`
6559 */
6560var nullType = new CoreType("null", TypeFlags.Null, function (v) { return v === null; });
6561/**
6562 * `types.undefined` - The type of the value `undefined`
6563 */
6564var undefinedType = new CoreType("undefined", TypeFlags.Undefined, function (v) { return v === undefined; });
6565var _DatePrimitive = new CoreType("Date", TypeFlags.Date, function (v) { return typeof v === "number" || v instanceof Date; }, function (v) { return (v instanceof Date ? v : new Date(v)); });
6566_DatePrimitive.getSnapshot = function (node) {
6567 return node.storedValue.getTime();
6568};
6569/**
6570 * `types.Date` - Creates a type that can only contain a javascript Date value.
6571 *
6572 * Example:
6573 * ```ts
6574 * const LogLine = types.model({
6575 * timestamp: types.Date,
6576 * })
6577 *
6578 * LogLine.create({ timestamp: new Date() })
6579 * ```
6580 */
6581var DatePrimitive = _DatePrimitive;
6582/**
6583 * @internal
6584 * @hidden
6585 */
6586function getPrimitiveFactoryFromValue(value) {
6587 switch (typeof value) {
6588 case "string":
6589 return string;
6590 case "number":
6591 return number; // In the future, isInteger(value) ? integer : number would be interesting, but would be too breaking for now
6592 case "boolean":
6593 return boolean;
6594 case "object":
6595 if (value instanceof Date)
6596 return DatePrimitive;
6597 }
6598 throw fail$1("Cannot determine primitive type from value " + value);
6599}
6600/**
6601 * Returns if a given value represents a primitive type.
6602 *
6603 * @param type
6604 * @returns
6605 */
6606function isPrimitiveType(type) {
6607 return (isType(type) &&
6608 (type.flags &
6609 (TypeFlags.String |
6610 TypeFlags.Number |
6611 TypeFlags.Integer |
6612 TypeFlags.Boolean |
6613 TypeFlags.Date)) >
6614 0);
6615}
6616
6617/**
6618 * @internal
6619 * @hidden
6620 */
6621var Literal = /** @class */ (function (_super) {
6622 __extends(Literal, _super);
6623 function Literal(value) {
6624 var _this = _super.call(this, JSON.stringify(value)) || this;
6625 Object.defineProperty(_this, "value", {
6626 enumerable: true,
6627 configurable: true,
6628 writable: true,
6629 value: void 0
6630 });
6631 Object.defineProperty(_this, "flags", {
6632 enumerable: true,
6633 configurable: true,
6634 writable: true,
6635 value: TypeFlags.Literal
6636 });
6637 _this.value = value;
6638 return _this;
6639 }
6640 Object.defineProperty(Literal.prototype, "instantiate", {
6641 enumerable: false,
6642 configurable: true,
6643 writable: true,
6644 value: function (parent, subpath, environment, initialValue) {
6645 return createScalarNode(this, parent, subpath, environment, initialValue);
6646 }
6647 });
6648 Object.defineProperty(Literal.prototype, "describe", {
6649 enumerable: false,
6650 configurable: true,
6651 writable: true,
6652 value: function () {
6653 return JSON.stringify(this.value);
6654 }
6655 });
6656 Object.defineProperty(Literal.prototype, "isValidSnapshot", {
6657 enumerable: false,
6658 configurable: true,
6659 writable: true,
6660 value: function (value, context) {
6661 if (isPrimitive(value) && value === this.value) {
6662 return typeCheckSuccess();
6663 }
6664 return typeCheckFailure(context, value, "Value is not a literal " + JSON.stringify(this.value));
6665 }
6666 });
6667 return Literal;
6668}(SimpleType));
6669/**
6670 * `types.literal` - The literal type will return a type that will match only the exact given type.
6671 * The given value must be a primitive, in order to be serialized to a snapshot correctly.
6672 * You can use literal to match exact strings for example the exact male or female string.
6673 *
6674 * Example:
6675 * ```ts
6676 * const Person = types.model({
6677 * name: types.string,
6678 * gender: types.union(types.literal('male'), types.literal('female'))
6679 * })
6680 * ```
6681 *
6682 * @param value The value to use in the strict equal check
6683 * @returns
6684 */
6685function literal(value) {
6686 // check that the given value is a primitive
6687 assertArg(value, isPrimitive, "primitive", 1);
6688 return new Literal(value);
6689}
6690/**
6691 * Returns if a given value represents a literal type.
6692 *
6693 * @param type
6694 * @returns
6695 */
6696function isLiteralType(type) {
6697 return isType(type) && (type.flags & TypeFlags.Literal) > 0;
6698}
6699
6700var Refinement = /** @class */ (function (_super) {
6701 __extends(Refinement, _super);
6702 function Refinement(name, _subtype, _predicate, _message) {
6703 var _this = _super.call(this, name) || this;
6704 Object.defineProperty(_this, "_subtype", {
6705 enumerable: true,
6706 configurable: true,
6707 writable: true,
6708 value: _subtype
6709 });
6710 Object.defineProperty(_this, "_predicate", {
6711 enumerable: true,
6712 configurable: true,
6713 writable: true,
6714 value: _predicate
6715 });
6716 Object.defineProperty(_this, "_message", {
6717 enumerable: true,
6718 configurable: true,
6719 writable: true,
6720 value: _message
6721 });
6722 return _this;
6723 }
6724 Object.defineProperty(Refinement.prototype, "flags", {
6725 get: function () {
6726 return this._subtype.flags | TypeFlags.Refinement;
6727 },
6728 enumerable: false,
6729 configurable: true
6730 });
6731 Object.defineProperty(Refinement.prototype, "describe", {
6732 enumerable: false,
6733 configurable: true,
6734 writable: true,
6735 value: function () {
6736 return this.name;
6737 }
6738 });
6739 Object.defineProperty(Refinement.prototype, "instantiate", {
6740 enumerable: false,
6741 configurable: true,
6742 writable: true,
6743 value: function (parent, subpath, environment, initialValue) {
6744 // create the child type
6745 return this._subtype.instantiate(parent, subpath, environment, initialValue);
6746 }
6747 });
6748 Object.defineProperty(Refinement.prototype, "isAssignableFrom", {
6749 enumerable: false,
6750 configurable: true,
6751 writable: true,
6752 value: function (type) {
6753 return this._subtype.isAssignableFrom(type);
6754 }
6755 });
6756 Object.defineProperty(Refinement.prototype, "isValidSnapshot", {
6757 enumerable: false,
6758 configurable: true,
6759 writable: true,
6760 value: function (value, context) {
6761 var subtypeErrors = this._subtype.validate(value, context);
6762 if (subtypeErrors.length > 0)
6763 return subtypeErrors;
6764 var snapshot = isStateTreeNode(value) ? getStateTreeNode(value).snapshot : value;
6765 if (!this._predicate(snapshot)) {
6766 return typeCheckFailure(context, value, this._message(value));
6767 }
6768 return typeCheckSuccess();
6769 }
6770 });
6771 Object.defineProperty(Refinement.prototype, "reconcile", {
6772 enumerable: false,
6773 configurable: true,
6774 writable: true,
6775 value: function (current, newValue, parent, subpath) {
6776 return this._subtype.reconcile(current, newValue, parent, subpath);
6777 }
6778 });
6779 Object.defineProperty(Refinement.prototype, "getSubTypes", {
6780 enumerable: false,
6781 configurable: true,
6782 writable: true,
6783 value: function () {
6784 return this._subtype;
6785 }
6786 });
6787 return Refinement;
6788}(BaseType));
6789/**
6790 * `types.refinement` - Creates a type that is more specific than the base type, e.g. `types.refinement(types.string, value => value.length > 5)` to create a type of strings that can only be longer then 5.
6791 *
6792 * @param name
6793 * @param type
6794 * @param predicate
6795 * @returns
6796 */
6797function refinement() {
6798 var args = [];
6799 for (var _i = 0; _i < arguments.length; _i++) {
6800 args[_i] = arguments[_i];
6801 }
6802 var name = typeof args[0] === "string" ? args.shift() : isType(args[0]) ? args[0].name : null;
6803 var type = args[0];
6804 var predicate = args[1];
6805 var message = args[2]
6806 ? args[2]
6807 : function (v) { return "Value does not respect the refinement predicate"; };
6808 // ensures all parameters are correct
6809 assertIsType(type, [1, 2]);
6810 assertIsString(name, 1);
6811 assertIsFunction(predicate, [2, 3]);
6812 assertIsFunction(message, [3, 4]);
6813 return new Refinement(name, type, predicate, message);
6814}
6815/**
6816 * Returns if a given value is a refinement type.
6817 *
6818 * @param type
6819 * @returns
6820 */
6821function isRefinementType(type) {
6822 return (type.flags & TypeFlags.Refinement) > 0;
6823}
6824
6825/**
6826 * `types.enumeration` - Can be used to create an string based enumeration.
6827 * (note: this methods is just sugar for a union of string literals)
6828 *
6829 * Example:
6830 * ```ts
6831 * const TrafficLight = types.model({
6832 * color: types.enumeration("Color", ["Red", "Orange", "Green"])
6833 * })
6834 * ```
6835 *
6836 * @param name descriptive name of the enumeration (optional)
6837 * @param options possible values this enumeration can have
6838 * @returns
6839 */
6840function enumeration(name, options) {
6841 var realOptions = typeof name === "string" ? options : name;
6842 // check all options
6843 if (devMode()) {
6844 realOptions.forEach(function (option, i) {
6845 assertIsString(option, i + 1);
6846 });
6847 }
6848 var type = union.apply(void 0, __spread(realOptions.map(function (option) { return literal("" + option); })));
6849 if (typeof name === "string")
6850 type.name = name;
6851 return type;
6852}
6853
6854/**
6855 * @internal
6856 * @hidden
6857 */
6858var Union = /** @class */ (function (_super) {
6859 __extends(Union, _super);
6860 function Union(name, _types, options) {
6861 var _this = _super.call(this, name) || this;
6862 Object.defineProperty(_this, "_types", {
6863 enumerable: true,
6864 configurable: true,
6865 writable: true,
6866 value: _types
6867 });
6868 Object.defineProperty(_this, "_dispatcher", {
6869 enumerable: true,
6870 configurable: true,
6871 writable: true,
6872 value: void 0
6873 });
6874 Object.defineProperty(_this, "_eager", {
6875 enumerable: true,
6876 configurable: true,
6877 writable: true,
6878 value: true
6879 });
6880 options = __assign({ eager: true, dispatcher: undefined }, options);
6881 _this._dispatcher = options.dispatcher;
6882 if (!options.eager)
6883 _this._eager = false;
6884 return _this;
6885 }
6886 Object.defineProperty(Union.prototype, "flags", {
6887 get: function () {
6888 var result = TypeFlags.Union;
6889 this._types.forEach(function (type) {
6890 result |= type.flags;
6891 });
6892 return result;
6893 },
6894 enumerable: false,
6895 configurable: true
6896 });
6897 Object.defineProperty(Union.prototype, "isAssignableFrom", {
6898 enumerable: false,
6899 configurable: true,
6900 writable: true,
6901 value: function (type) {
6902 return this._types.some(function (subType) { return subType.isAssignableFrom(type); });
6903 }
6904 });
6905 Object.defineProperty(Union.prototype, "describe", {
6906 enumerable: false,
6907 configurable: true,
6908 writable: true,
6909 value: function () {
6910 return "(" + this._types.map(function (factory) { return factory.describe(); }).join(" | ") + ")";
6911 }
6912 });
6913 Object.defineProperty(Union.prototype, "instantiate", {
6914 enumerable: false,
6915 configurable: true,
6916 writable: true,
6917 value: function (parent, subpath, environment, initialValue) {
6918 var type = this.determineType(initialValue, undefined);
6919 if (!type)
6920 throw fail$1("No matching type for union " + this.describe()); // can happen in prod builds
6921 return type.instantiate(parent, subpath, environment, initialValue);
6922 }
6923 });
6924 Object.defineProperty(Union.prototype, "reconcile", {
6925 enumerable: false,
6926 configurable: true,
6927 writable: true,
6928 value: function (current, newValue, parent, subpath) {
6929 var type = this.determineType(newValue, current.getReconciliationType());
6930 if (!type)
6931 throw fail$1("No matching type for union " + this.describe()); // can happen in prod builds
6932 return type.reconcile(current, newValue, parent, subpath);
6933 }
6934 });
6935 Object.defineProperty(Union.prototype, "determineType", {
6936 enumerable: false,
6937 configurable: true,
6938 writable: true,
6939 value: function (value, reconcileCurrentType) {
6940 // try the dispatcher, if defined
6941 if (this._dispatcher) {
6942 return this._dispatcher(value);
6943 }
6944 // find the most accomodating type
6945 // if we are using reconciliation try the current node type first (fix for #1045)
6946 if (reconcileCurrentType) {
6947 if (reconcileCurrentType.is(value)) {
6948 return reconcileCurrentType;
6949 }
6950 return this._types
6951 .filter(function (t) { return t !== reconcileCurrentType; })
6952 .find(function (type) { return type.is(value); });
6953 }
6954 else {
6955 return this._types.find(function (type) { return type.is(value); });
6956 }
6957 }
6958 });
6959 Object.defineProperty(Union.prototype, "isValidSnapshot", {
6960 enumerable: false,
6961 configurable: true,
6962 writable: true,
6963 value: function (value, context) {
6964 if (this._dispatcher) {
6965 return this._dispatcher(value).validate(value, context);
6966 }
6967 var allErrors = [];
6968 var applicableTypes = 0;
6969 for (var i = 0; i < this._types.length; i++) {
6970 var type = this._types[i];
6971 var errors = type.validate(value, context);
6972 if (errors.length === 0) {
6973 if (this._eager)
6974 return typeCheckSuccess();
6975 else
6976 applicableTypes++;
6977 }
6978 else {
6979 allErrors.push(errors);
6980 }
6981 }
6982 if (applicableTypes === 1)
6983 return typeCheckSuccess();
6984 return typeCheckFailure(context, value, "No type is applicable for the union").concat(flattenTypeErrors(allErrors));
6985 }
6986 });
6987 Object.defineProperty(Union.prototype, "getSubTypes", {
6988 enumerable: false,
6989 configurable: true,
6990 writable: true,
6991 value: function () {
6992 return this._types;
6993 }
6994 });
6995 return Union;
6996}(BaseType));
6997/**
6998 * `types.union` - Create a union of multiple types. If the correct type cannot be inferred unambiguously from a snapshot, provide a dispatcher function of the form `(snapshot) => Type`.
6999 *
7000 * @param optionsOrType
7001 * @param otherTypes
7002 * @returns
7003 */
7004function union(optionsOrType) {
7005 var otherTypes = [];
7006 for (var _i = 1; _i < arguments.length; _i++) {
7007 otherTypes[_i - 1] = arguments[_i];
7008 }
7009 var options = isType(optionsOrType) ? undefined : optionsOrType;
7010 var types = isType(optionsOrType) ? __spread([optionsOrType], otherTypes) : otherTypes;
7011 var name = "(" + types.map(function (type) { return type.name; }).join(" | ") + ")";
7012 // check all options
7013 if (devMode()) {
7014 if (options) {
7015 assertArg(options, function (o) { return isPlainObject(o); }, "object { eager?: boolean, dispatcher?: Function }", 1);
7016 }
7017 types.forEach(function (type, i) {
7018 assertIsType(type, options ? i + 2 : i + 1);
7019 });
7020 }
7021 return new Union(name, types, options);
7022}
7023/**
7024 * Returns if a given value represents a union type.
7025 *
7026 * @param type
7027 * @returns
7028 */
7029function isUnionType(type) {
7030 return (type.flags & TypeFlags.Union) > 0;
7031}
7032
7033/**
7034 * @hidden
7035 * @internal
7036 */
7037var OptionalValue = /** @class */ (function (_super) {
7038 __extends(OptionalValue, _super);
7039 function OptionalValue(_subtype, _defaultValue, optionalValues) {
7040 var _this = _super.call(this, _subtype.name) || this;
7041 Object.defineProperty(_this, "_subtype", {
7042 enumerable: true,
7043 configurable: true,
7044 writable: true,
7045 value: _subtype
7046 });
7047 Object.defineProperty(_this, "_defaultValue", {
7048 enumerable: true,
7049 configurable: true,
7050 writable: true,
7051 value: _defaultValue
7052 });
7053 Object.defineProperty(_this, "optionalValues", {
7054 enumerable: true,
7055 configurable: true,
7056 writable: true,
7057 value: optionalValues
7058 });
7059 return _this;
7060 }
7061 Object.defineProperty(OptionalValue.prototype, "flags", {
7062 get: function () {
7063 return this._subtype.flags | TypeFlags.Optional;
7064 },
7065 enumerable: false,
7066 configurable: true
7067 });
7068 Object.defineProperty(OptionalValue.prototype, "describe", {
7069 enumerable: false,
7070 configurable: true,
7071 writable: true,
7072 value: function () {
7073 return this._subtype.describe() + "?";
7074 }
7075 });
7076 Object.defineProperty(OptionalValue.prototype, "instantiate", {
7077 enumerable: false,
7078 configurable: true,
7079 writable: true,
7080 value: function (parent, subpath, environment, initialValue) {
7081 if (this.optionalValues.indexOf(initialValue) >= 0) {
7082 var defaultInstanceOrSnapshot = this.getDefaultInstanceOrSnapshot();
7083 return this._subtype.instantiate(parent, subpath, environment, defaultInstanceOrSnapshot);
7084 }
7085 return this._subtype.instantiate(parent, subpath, environment, initialValue);
7086 }
7087 });
7088 Object.defineProperty(OptionalValue.prototype, "reconcile", {
7089 enumerable: false,
7090 configurable: true,
7091 writable: true,
7092 value: function (current, newValue, parent, subpath) {
7093 return this._subtype.reconcile(current, this.optionalValues.indexOf(newValue) < 0 && this._subtype.is(newValue)
7094 ? newValue
7095 : this.getDefaultInstanceOrSnapshot(), parent, subpath);
7096 }
7097 });
7098 Object.defineProperty(OptionalValue.prototype, "getDefaultInstanceOrSnapshot", {
7099 enumerable: false,
7100 configurable: true,
7101 writable: true,
7102 value: function () {
7103 var defaultInstanceOrSnapshot = typeof this._defaultValue === "function"
7104 ? this._defaultValue()
7105 : this._defaultValue;
7106 // while static values are already snapshots and checked on types.optional
7107 // generator functions must always be rechecked just in case
7108 if (typeof this._defaultValue === "function") {
7109 typecheckInternal(this, defaultInstanceOrSnapshot);
7110 }
7111 return defaultInstanceOrSnapshot;
7112 }
7113 });
7114 Object.defineProperty(OptionalValue.prototype, "isValidSnapshot", {
7115 enumerable: false,
7116 configurable: true,
7117 writable: true,
7118 value: function (value, context) {
7119 // defaulted values can be skipped
7120 if (this.optionalValues.indexOf(value) >= 0) {
7121 return typeCheckSuccess();
7122 }
7123 // bounce validation to the sub-type
7124 return this._subtype.validate(value, context);
7125 }
7126 });
7127 Object.defineProperty(OptionalValue.prototype, "isAssignableFrom", {
7128 enumerable: false,
7129 configurable: true,
7130 writable: true,
7131 value: function (type) {
7132 return this._subtype.isAssignableFrom(type);
7133 }
7134 });
7135 Object.defineProperty(OptionalValue.prototype, "getSubTypes", {
7136 enumerable: false,
7137 configurable: true,
7138 writable: true,
7139 value: function () {
7140 return this._subtype;
7141 }
7142 });
7143 return OptionalValue;
7144}(BaseType));
7145function checkOptionalPreconditions(type, defaultValueOrFunction) {
7146 // make sure we never pass direct instances
7147 if (typeof defaultValueOrFunction !== "function" && isStateTreeNode(defaultValueOrFunction)) {
7148 throw fail$1("default value cannot be an instance, pass a snapshot or a function that creates an instance/snapshot instead");
7149 }
7150 assertIsType(type, 1);
7151 if (devMode()) {
7152 // we only check default values if they are passed directly
7153 // if they are generator functions they will be checked once they are generated
7154 // we don't check generator function results here to avoid generating a node just for type-checking purposes
7155 // which might generate side-effects
7156 if (typeof defaultValueOrFunction !== "function") {
7157 typecheckInternal(type, defaultValueOrFunction);
7158 }
7159 }
7160}
7161/**
7162 * `types.optional` - Can be used to create a property with a default value.
7163 *
7164 * Depending on the third argument (`optionalValues`) there are two ways of operation:
7165 * - If the argument is not provided, then if a value is not provided in the snapshot (`undefined` or missing),
7166 * it will default to the provided `defaultValue`
7167 * - If the argument is provided, then if the value in the snapshot matches one of the optional values inside the array then it will
7168 * default to the provided `defaultValue`. Additionally, if one of the optional values inside the array is `undefined` then a missing
7169 * property is also valid.
7170 *
7171 * Note that it is also possible to include values of the same type as the intended subtype as optional values,
7172 * in this case the optional value will be transformed into the `defaultValue` (e.g. `types.optional(types.string, "unnamed", [undefined, ""])`
7173 * will transform the snapshot values `undefined` (and therefore missing) and empty strings into the string `"unnamed"` when it gets
7174 * instantiated).
7175 *
7176 * If `defaultValue` is a function, the function will be invoked for every new instance.
7177 * Applying a snapshot in which the optional value is one of the optional values (or `undefined`/_not_ present if none are provided) causes the
7178 * value to be reset.
7179 *
7180 * Example:
7181 * ```ts
7182 * const Todo = types.model({
7183 * title: types.string,
7184 * subtitle1: types.optional(types.string, "", [null]),
7185 * subtitle2: types.optional(types.string, "", [null, undefined]),
7186 * done: types.optional(types.boolean, false),
7187 * created: types.optional(types.Date, () => new Date()),
7188 * })
7189 *
7190 * // if done is missing / undefined it will become false
7191 * // if created is missing / undefined it will get a freshly generated timestamp
7192 * // if subtitle1 is null it will default to "", but it cannot be missing or undefined
7193 * // if subtitle2 is null or undefined it will default to ""; since it can be undefined it can also be missing
7194 * const todo = Todo.create({ title: "Get coffee", subtitle1: null })
7195 * ```
7196 *
7197 * @param type
7198 * @param defaultValueOrFunction
7199 * @param optionalValues an optional array with zero or more primitive values (string, number, boolean, null or undefined)
7200 * that will be converted into the default. `[ undefined ]` is assumed when none is provided
7201 * @returns
7202 */
7203function optional(type, defaultValueOrFunction, optionalValues) {
7204 checkOptionalPreconditions(type, defaultValueOrFunction);
7205 return new OptionalValue(type, defaultValueOrFunction, optionalValues ? optionalValues : undefinedAsOptionalValues);
7206}
7207var undefinedAsOptionalValues = [undefined];
7208/**
7209 * Returns if a value represents an optional type.
7210 *
7211 * @template IT
7212 * @param type
7213 * @returns
7214 */
7215function isOptionalType(type) {
7216 return isType(type) && (type.flags & TypeFlags.Optional) > 0;
7217}
7218
7219var optionalUndefinedType = optional(undefinedType, undefined);
7220var optionalNullType = optional(nullType, null);
7221/**
7222 * `types.maybe` - Maybe will make a type nullable, and also optional.
7223 * The value `undefined` will be used to represent nullability.
7224 *
7225 * @param type
7226 * @returns
7227 */
7228function maybe(type) {
7229 assertIsType(type, 1);
7230 return union(type, optionalUndefinedType);
7231}
7232/**
7233 * `types.maybeNull` - Maybe will make a type nullable, and also optional.
7234 * The value `null` will be used to represent no value.
7235 *
7236 * @param type
7237 * @returns
7238 */
7239function maybeNull(type) {
7240 assertIsType(type, 1);
7241 return union(type, optionalNullType);
7242}
7243
7244var Late = /** @class */ (function (_super) {
7245 __extends(Late, _super);
7246 function Late(name, _definition) {
7247 var _this = _super.call(this, name) || this;
7248 Object.defineProperty(_this, "_definition", {
7249 enumerable: true,
7250 configurable: true,
7251 writable: true,
7252 value: _definition
7253 });
7254 Object.defineProperty(_this, "_subType", {
7255 enumerable: true,
7256 configurable: true,
7257 writable: true,
7258 value: void 0
7259 });
7260 return _this;
7261 }
7262 Object.defineProperty(Late.prototype, "flags", {
7263 get: function () {
7264 return (this._subType ? this._subType.flags : 0) | TypeFlags.Late;
7265 },
7266 enumerable: false,
7267 configurable: true
7268 });
7269 Object.defineProperty(Late.prototype, "getSubType", {
7270 enumerable: false,
7271 configurable: true,
7272 writable: true,
7273 value: function (mustSucceed) {
7274 if (!this._subType) {
7275 var t = undefined;
7276 try {
7277 t = this._definition();
7278 }
7279 catch (e) {
7280 if (e instanceof ReferenceError)
7281 // can happen in strict ES5 code when a definition is self refering
7282 t = undefined;
7283 else
7284 throw e;
7285 }
7286 if (mustSucceed && t === undefined)
7287 throw fail$1("Late type seems to be used too early, the definition (still) returns undefined");
7288 if (t) {
7289 if (devMode() && !isType(t))
7290 throw fail$1("Failed to determine subtype, make sure types.late returns a type definition.");
7291 this._subType = t;
7292 }
7293 }
7294 return this._subType;
7295 }
7296 });
7297 Object.defineProperty(Late.prototype, "instantiate", {
7298 enumerable: false,
7299 configurable: true,
7300 writable: true,
7301 value: function (parent, subpath, environment, initialValue) {
7302 return this.getSubType(true).instantiate(parent, subpath, environment, initialValue);
7303 }
7304 });
7305 Object.defineProperty(Late.prototype, "reconcile", {
7306 enumerable: false,
7307 configurable: true,
7308 writable: true,
7309 value: function (current, newValue, parent, subpath) {
7310 return this.getSubType(true).reconcile(current, newValue, parent, subpath);
7311 }
7312 });
7313 Object.defineProperty(Late.prototype, "describe", {
7314 enumerable: false,
7315 configurable: true,
7316 writable: true,
7317 value: function () {
7318 var t = this.getSubType(false);
7319 return t ? t.name : "<uknown late type>";
7320 }
7321 });
7322 Object.defineProperty(Late.prototype, "isValidSnapshot", {
7323 enumerable: false,
7324 configurable: true,
7325 writable: true,
7326 value: function (value, context) {
7327 var t = this.getSubType(false);
7328 if (!t) {
7329 // See #916; the variable the definition closure is pointing to wasn't defined yet, so can't be evaluted yet here
7330 return typeCheckSuccess();
7331 }
7332 return t.validate(value, context);
7333 }
7334 });
7335 Object.defineProperty(Late.prototype, "isAssignableFrom", {
7336 enumerable: false,
7337 configurable: true,
7338 writable: true,
7339 value: function (type) {
7340 var t = this.getSubType(false);
7341 return t ? t.isAssignableFrom(type) : false;
7342 }
7343 });
7344 Object.defineProperty(Late.prototype, "getSubTypes", {
7345 enumerable: false,
7346 configurable: true,
7347 writable: true,
7348 value: function () {
7349 var subtype = this.getSubType(false);
7350 return subtype ? subtype : cannotDetermineSubtype;
7351 }
7352 });
7353 return Late;
7354}(BaseType));
7355/**
7356 * `types.late` - Defines a type that gets implemented later. This is useful when you have to deal with circular dependencies.
7357 * Please notice that when defining circular dependencies TypeScript isn't smart enough to inference them.
7358 *
7359 * Example:
7360 * ```ts
7361 * // TypeScript isn't smart enough to infer self referencing types.
7362 * const Node = types.model({
7363 * children: types.array(types.late((): IAnyModelType => Node)) // then typecast each array element to Instance<typeof Node>
7364 * })
7365 * ```
7366 *
7367 * @param name The name to use for the type that will be returned.
7368 * @param type A function that returns the type that will be defined.
7369 * @returns
7370 */
7371function late(nameOrType, maybeType) {
7372 var name = typeof nameOrType === "string" ? nameOrType : "late(" + nameOrType.toString() + ")";
7373 var type = typeof nameOrType === "string" ? maybeType : nameOrType;
7374 // checks that the type is actually a late type
7375 if (devMode()) {
7376 if (!(typeof type === "function" && type.length === 0))
7377 throw fail$1("Invalid late type, expected a function with zero arguments that returns a type, got: " +
7378 type);
7379 }
7380 return new Late(name, type);
7381}
7382/**
7383 * Returns if a given value represents a late type.
7384 *
7385 * @param type
7386 * @returns
7387 */
7388function isLateType(type) {
7389 return isType(type) && (type.flags & TypeFlags.Late) > 0;
7390}
7391
7392/**
7393 * @internal
7394 * @hidden
7395 */
7396var Frozen = /** @class */ (function (_super) {
7397 __extends(Frozen, _super);
7398 function Frozen(subType) {
7399 var _this = _super.call(this, subType ? "frozen(" + subType.name + ")" : "frozen") || this;
7400 Object.defineProperty(_this, "subType", {
7401 enumerable: true,
7402 configurable: true,
7403 writable: true,
7404 value: subType
7405 });
7406 Object.defineProperty(_this, "flags", {
7407 enumerable: true,
7408 configurable: true,
7409 writable: true,
7410 value: TypeFlags.Frozen
7411 });
7412 return _this;
7413 }
7414 Object.defineProperty(Frozen.prototype, "describe", {
7415 enumerable: false,
7416 configurable: true,
7417 writable: true,
7418 value: function () {
7419 return "<any immutable value>";
7420 }
7421 });
7422 Object.defineProperty(Frozen.prototype, "instantiate", {
7423 enumerable: false,
7424 configurable: true,
7425 writable: true,
7426 value: function (parent, subpath, environment, value) {
7427 // create the node
7428 return createScalarNode(this, parent, subpath, environment, deepFreeze(value));
7429 }
7430 });
7431 Object.defineProperty(Frozen.prototype, "isValidSnapshot", {
7432 enumerable: false,
7433 configurable: true,
7434 writable: true,
7435 value: function (value, context) {
7436 if (!isSerializable(value)) {
7437 return typeCheckFailure(context, value, "Value is not serializable and cannot be frozen");
7438 }
7439 if (this.subType)
7440 return this.subType.validate(value, context);
7441 return typeCheckSuccess();
7442 }
7443 });
7444 return Frozen;
7445}(SimpleType));
7446var untypedFrozenInstance = new Frozen();
7447/**
7448 * `types.frozen` - Frozen can be used to store any value that is serializable in itself (that is valid JSON).
7449 * Frozen values need to be immutable or treated as if immutable. They need be serializable as well.
7450 * Values stored in frozen will snapshotted as-is by MST, and internal changes will not be tracked.
7451 *
7452 * This is useful to store complex, but immutable values like vectors etc. It can form a powerful bridge to parts of your application that should be immutable, or that assume data to be immutable.
7453 *
7454 * Note: if you want to store free-form state that is mutable, or not serializeable, consider using volatile state instead.
7455 *
7456 * Frozen properties can be defined in three different ways
7457 * 1. `types.frozen(SubType)` - provide a valid MST type and frozen will check if the provided data conforms the snapshot for that type
7458 * 2. `types.frozen({ someDefaultValue: true})` - provide a primitive value, object or array, and MST will infer the type from that object, and also make it the default value for the field
7459 * 3. `types.frozen<TypeScriptType>()` - provide a typescript type, to help in strongly typing the field (design time only)
7460 *
7461 * Example:
7462 * ```ts
7463 * const GameCharacter = types.model({
7464 * name: string,
7465 * location: types.frozen({ x: 0, y: 0})
7466 * })
7467 *
7468 * const hero = GameCharacter.create({
7469 * name: "Mario",
7470 * location: { x: 7, y: 4 }
7471 * })
7472 *
7473 * hero.location = { x: 10, y: 2 } // OK
7474 * hero.location.x = 7 // Not ok!
7475 * ```
7476 *
7477 * ```ts
7478 * type Point = { x: number, y: number }
7479 * const Mouse = types.model({
7480 * loc: types.frozen<Point>()
7481 * })
7482 * ```
7483 *
7484 * @param defaultValueOrType
7485 * @returns
7486 */
7487function frozen(arg) {
7488 if (arguments.length === 0)
7489 return untypedFrozenInstance;
7490 else if (isType(arg))
7491 return new Frozen(arg);
7492 else
7493 return optional(untypedFrozenInstance, arg);
7494}
7495/**
7496 * Returns if a given value represents a frozen type.
7497 *
7498 * @param type
7499 * @returns
7500 */
7501function isFrozenType(type) {
7502 return isType(type) && (type.flags & TypeFlags.Frozen) > 0;
7503}
7504
7505function getInvalidationCause(hook) {
7506 switch (hook) {
7507 case Hook.beforeDestroy:
7508 return "destroy";
7509 case Hook.beforeDetach:
7510 return "detach";
7511 default:
7512 return undefined;
7513 }
7514}
7515var StoredReference = /** @class */ (function () {
7516 function StoredReference(value, targetType) {
7517 Object.defineProperty(this, "targetType", {
7518 enumerable: true,
7519 configurable: true,
7520 writable: true,
7521 value: targetType
7522 });
7523 Object.defineProperty(this, "identifier", {
7524 enumerable: true,
7525 configurable: true,
7526 writable: true,
7527 value: void 0
7528 });
7529 Object.defineProperty(this, "node", {
7530 enumerable: true,
7531 configurable: true,
7532 writable: true,
7533 value: void 0
7534 });
7535 Object.defineProperty(this, "resolvedReference", {
7536 enumerable: true,
7537 configurable: true,
7538 writable: true,
7539 value: void 0
7540 });
7541 if (isValidIdentifier(value)) {
7542 this.identifier = value;
7543 }
7544 else if (isStateTreeNode(value)) {
7545 var targetNode = getStateTreeNode(value);
7546 if (!targetNode.identifierAttribute)
7547 throw fail$1("Can only store references with a defined identifier attribute.");
7548 var id = targetNode.unnormalizedIdentifier;
7549 if (id === null || id === undefined) {
7550 throw fail$1("Can only store references to tree nodes with a defined identifier.");
7551 }
7552 this.identifier = id;
7553 }
7554 else {
7555 throw fail$1("Can only store references to tree nodes or identifiers, got: '" + value + "'");
7556 }
7557 }
7558 Object.defineProperty(StoredReference.prototype, "updateResolvedReference", {
7559 enumerable: false,
7560 configurable: true,
7561 writable: true,
7562 value: function (node) {
7563 var normalizedId = normalizeIdentifier(this.identifier);
7564 var root = node.root;
7565 var lastCacheModification = root.identifierCache.getLastCacheModificationPerId(normalizedId);
7566 if (!this.resolvedReference ||
7567 this.resolvedReference.lastCacheModification !== lastCacheModification) {
7568 var targetType = this.targetType;
7569 // reference was initialized with the identifier of the target
7570 var target = root.identifierCache.resolve(targetType, normalizedId);
7571 if (!target) {
7572 throw new InvalidReferenceError("[mobx-state-tree] Failed to resolve reference '" + this.identifier + "' to type '" + this.targetType.name + "' (from node: " + node.path + ")");
7573 }
7574 this.resolvedReference = {
7575 node: target,
7576 lastCacheModification: lastCacheModification
7577 };
7578 }
7579 }
7580 });
7581 Object.defineProperty(StoredReference.prototype, "resolvedValue", {
7582 get: function () {
7583 this.updateResolvedReference(this.node);
7584 return this.resolvedReference.node.value;
7585 },
7586 enumerable: false,
7587 configurable: true
7588 });
7589 return StoredReference;
7590}());
7591/**
7592 * @internal
7593 * @hidden
7594 */
7595var InvalidReferenceError = /** @class */ (function (_super) {
7596 __extends(InvalidReferenceError, _super);
7597 function InvalidReferenceError(m) {
7598 var _this = _super.call(this, m) || this;
7599 Object.setPrototypeOf(_this, InvalidReferenceError.prototype);
7600 return _this;
7601 }
7602 return InvalidReferenceError;
7603}(Error));
7604/**
7605 * @internal
7606 * @hidden
7607 */
7608var BaseReferenceType = /** @class */ (function (_super) {
7609 __extends(BaseReferenceType, _super);
7610 function BaseReferenceType(targetType, onInvalidated) {
7611 var _this = _super.call(this, "reference(" + targetType.name + ")") || this;
7612 Object.defineProperty(_this, "targetType", {
7613 enumerable: true,
7614 configurable: true,
7615 writable: true,
7616 value: targetType
7617 });
7618 Object.defineProperty(_this, "onInvalidated", {
7619 enumerable: true,
7620 configurable: true,
7621 writable: true,
7622 value: onInvalidated
7623 });
7624 Object.defineProperty(_this, "flags", {
7625 enumerable: true,
7626 configurable: true,
7627 writable: true,
7628 value: TypeFlags.Reference
7629 });
7630 return _this;
7631 }
7632 Object.defineProperty(BaseReferenceType.prototype, "describe", {
7633 enumerable: false,
7634 configurable: true,
7635 writable: true,
7636 value: function () {
7637 return this.name;
7638 }
7639 });
7640 Object.defineProperty(BaseReferenceType.prototype, "isAssignableFrom", {
7641 enumerable: false,
7642 configurable: true,
7643 writable: true,
7644 value: function (type) {
7645 return this.targetType.isAssignableFrom(type);
7646 }
7647 });
7648 Object.defineProperty(BaseReferenceType.prototype, "isValidSnapshot", {
7649 enumerable: false,
7650 configurable: true,
7651 writable: true,
7652 value: function (value, context) {
7653 return isValidIdentifier(value)
7654 ? typeCheckSuccess()
7655 : typeCheckFailure(context, value, "Value is not a valid identifier, which is a string or a number");
7656 }
7657 });
7658 Object.defineProperty(BaseReferenceType.prototype, "fireInvalidated", {
7659 enumerable: false,
7660 configurable: true,
7661 writable: true,
7662 value: function (cause, storedRefNode, referenceId, refTargetNode) {
7663 // to actually invalidate a reference we need an alive parent,
7664 // since it is a scalar value (immutable-ish) and we need to change it
7665 // from the parent
7666 var storedRefParentNode = storedRefNode.parent;
7667 if (!storedRefParentNode || !storedRefParentNode.isAlive) {
7668 return;
7669 }
7670 var storedRefParentValue = storedRefParentNode.storedValue;
7671 if (!storedRefParentValue) {
7672 return;
7673 }
7674 this.onInvalidated({
7675 cause: cause,
7676 parent: storedRefParentValue,
7677 invalidTarget: refTargetNode ? refTargetNode.storedValue : undefined,
7678 invalidId: referenceId,
7679 replaceRef: function (newRef) {
7680 applyPatch(storedRefNode.root.storedValue, {
7681 op: "replace",
7682 value: newRef,
7683 path: storedRefNode.path
7684 });
7685 },
7686 removeRef: function () {
7687 if (isModelType(storedRefParentNode.type)) {
7688 this.replaceRef(undefined);
7689 }
7690 else {
7691 applyPatch(storedRefNode.root.storedValue, {
7692 op: "remove",
7693 path: storedRefNode.path
7694 });
7695 }
7696 }
7697 });
7698 }
7699 });
7700 Object.defineProperty(BaseReferenceType.prototype, "addTargetNodeWatcher", {
7701 enumerable: false,
7702 configurable: true,
7703 writable: true,
7704 value: function (storedRefNode, referenceId) {
7705 var _this = this;
7706 // this will make sure the target node becomes created
7707 var refTargetValue = this.getValue(storedRefNode);
7708 if (!refTargetValue) {
7709 return undefined;
7710 }
7711 var refTargetNode = getStateTreeNode(refTargetValue);
7712 var hookHandler = function (_, refTargetNodeHook) {
7713 var cause = getInvalidationCause(refTargetNodeHook);
7714 if (!cause) {
7715 return;
7716 }
7717 _this.fireInvalidated(cause, storedRefNode, referenceId, refTargetNode);
7718 };
7719 var refTargetDetachHookDisposer = refTargetNode.registerHook(Hook.beforeDetach, hookHandler);
7720 var refTargetDestroyHookDisposer = refTargetNode.registerHook(Hook.beforeDestroy, hookHandler);
7721 return function () {
7722 refTargetDetachHookDisposer();
7723 refTargetDestroyHookDisposer();
7724 };
7725 }
7726 });
7727 Object.defineProperty(BaseReferenceType.prototype, "watchTargetNodeForInvalidations", {
7728 enumerable: false,
7729 configurable: true,
7730 writable: true,
7731 value: function (storedRefNode, identifier, customGetSet) {
7732 var _this = this;
7733 if (!this.onInvalidated) {
7734 return;
7735 }
7736 var onRefTargetDestroyedHookDisposer;
7737 // get rid of the watcher hook when the stored ref node is destroyed
7738 // detached is ignored since scalar nodes (where the reference resides) cannot be detached
7739 storedRefNode.registerHook(Hook.beforeDestroy, function () {
7740 if (onRefTargetDestroyedHookDisposer) {
7741 onRefTargetDestroyedHookDisposer();
7742 }
7743 });
7744 var startWatching = function (sync) {
7745 // re-create hook in case the stored ref gets reattached
7746 if (onRefTargetDestroyedHookDisposer) {
7747 onRefTargetDestroyedHookDisposer();
7748 }
7749 // make sure the target node is actually there and initialized
7750 var storedRefParentNode = storedRefNode.parent;
7751 var storedRefParentValue = storedRefParentNode && storedRefParentNode.storedValue;
7752 if (storedRefParentNode && storedRefParentNode.isAlive && storedRefParentValue) {
7753 var refTargetNodeExists = void 0;
7754 if (customGetSet) {
7755 refTargetNodeExists = !!customGetSet.get(identifier, storedRefParentValue);
7756 }
7757 else {
7758 refTargetNodeExists = storedRefNode.root.identifierCache.has(_this.targetType, normalizeIdentifier(identifier));
7759 }
7760 if (!refTargetNodeExists) {
7761 // we cannot change the reference in sync mode
7762 // since we are in the middle of a reconciliation/instantiation and the change would be overwritten
7763 // for those cases just let the wrong reference be assigned and fail upon usage
7764 // (like current references do)
7765 // this means that effectively this code will only run when it is created from a snapshot
7766 if (!sync) {
7767 _this.fireInvalidated("invalidSnapshotReference", storedRefNode, identifier, null);
7768 }
7769 }
7770 else {
7771 onRefTargetDestroyedHookDisposer = _this.addTargetNodeWatcher(storedRefNode, identifier);
7772 }
7773 }
7774 };
7775 if (storedRefNode.state === NodeLifeCycle.FINALIZED) {
7776 // already attached, so the whole tree is ready
7777 startWatching(true);
7778 }
7779 else {
7780 if (!storedRefNode.isRoot) {
7781 // start watching once the whole tree is ready
7782 storedRefNode.root.registerHook(Hook.afterCreationFinalization, function () {
7783 // make sure to attach it so it can start listening
7784 if (storedRefNode.parent) {
7785 storedRefNode.parent.createObservableInstanceIfNeeded();
7786 }
7787 });
7788 }
7789 // start watching once the node is attached somewhere / parent changes
7790 storedRefNode.registerHook(Hook.afterAttach, function () {
7791 startWatching(false);
7792 });
7793 }
7794 }
7795 });
7796 return BaseReferenceType;
7797}(SimpleType));
7798/**
7799 * @internal
7800 * @hidden
7801 */
7802var IdentifierReferenceType = /** @class */ (function (_super) {
7803 __extends(IdentifierReferenceType, _super);
7804 function IdentifierReferenceType(targetType, onInvalidated) {
7805 return _super.call(this, targetType, onInvalidated) || this;
7806 }
7807 Object.defineProperty(IdentifierReferenceType.prototype, "getValue", {
7808 enumerable: false,
7809 configurable: true,
7810 writable: true,
7811 value: function (storedRefNode) {
7812 if (!storedRefNode.isAlive)
7813 return undefined;
7814 var storedRef = storedRefNode.storedValue;
7815 return storedRef.resolvedValue;
7816 }
7817 });
7818 Object.defineProperty(IdentifierReferenceType.prototype, "getSnapshot", {
7819 enumerable: false,
7820 configurable: true,
7821 writable: true,
7822 value: function (storedRefNode) {
7823 var ref = storedRefNode.storedValue;
7824 return ref.identifier;
7825 }
7826 });
7827 Object.defineProperty(IdentifierReferenceType.prototype, "instantiate", {
7828 enumerable: false,
7829 configurable: true,
7830 writable: true,
7831 value: function (parent, subpath, environment, initialValue) {
7832 var identifier = isStateTreeNode(initialValue)
7833 ? getIdentifier(initialValue)
7834 : initialValue;
7835 var storedRef = new StoredReference(initialValue, this.targetType);
7836 var storedRefNode = createScalarNode(this, parent, subpath, environment, storedRef);
7837 storedRef.node = storedRefNode;
7838 this.watchTargetNodeForInvalidations(storedRefNode, identifier, undefined);
7839 return storedRefNode;
7840 }
7841 });
7842 Object.defineProperty(IdentifierReferenceType.prototype, "reconcile", {
7843 enumerable: false,
7844 configurable: true,
7845 writable: true,
7846 value: function (current, newValue, parent, subpath) {
7847 if (!current.isDetaching && current.type === this) {
7848 var compareByValue = isStateTreeNode(newValue);
7849 var ref = current.storedValue;
7850 if ((!compareByValue && ref.identifier === newValue) ||
7851 (compareByValue && ref.resolvedValue === newValue)) {
7852 current.setParent(parent, subpath);
7853 return current;
7854 }
7855 }
7856 var newNode = this.instantiate(parent, subpath, undefined, newValue);
7857 current.die(); // noop if detaching
7858 return newNode;
7859 }
7860 });
7861 return IdentifierReferenceType;
7862}(BaseReferenceType));
7863/**
7864 * @internal
7865 * @hidden
7866 */
7867var CustomReferenceType = /** @class */ (function (_super) {
7868 __extends(CustomReferenceType, _super);
7869 function CustomReferenceType(targetType, options, onInvalidated) {
7870 var _this = _super.call(this, targetType, onInvalidated) || this;
7871 Object.defineProperty(_this, "options", {
7872 enumerable: true,
7873 configurable: true,
7874 writable: true,
7875 value: options
7876 });
7877 return _this;
7878 }
7879 Object.defineProperty(CustomReferenceType.prototype, "getValue", {
7880 enumerable: false,
7881 configurable: true,
7882 writable: true,
7883 value: function (storedRefNode) {
7884 if (!storedRefNode.isAlive)
7885 return undefined;
7886 var referencedNode = this.options.get(storedRefNode.storedValue, storedRefNode.parent ? storedRefNode.parent.storedValue : null);
7887 return referencedNode;
7888 }
7889 });
7890 Object.defineProperty(CustomReferenceType.prototype, "getSnapshot", {
7891 enumerable: false,
7892 configurable: true,
7893 writable: true,
7894 value: function (storedRefNode) {
7895 return storedRefNode.storedValue;
7896 }
7897 });
7898 Object.defineProperty(CustomReferenceType.prototype, "instantiate", {
7899 enumerable: false,
7900 configurable: true,
7901 writable: true,
7902 value: function (parent, subpath, environment, newValue) {
7903 var identifier = isStateTreeNode(newValue)
7904 ? this.options.set(newValue, parent ? parent.storedValue : null)
7905 : newValue;
7906 var storedRefNode = createScalarNode(this, parent, subpath, environment, identifier);
7907 this.watchTargetNodeForInvalidations(storedRefNode, identifier, this.options);
7908 return storedRefNode;
7909 }
7910 });
7911 Object.defineProperty(CustomReferenceType.prototype, "reconcile", {
7912 enumerable: false,
7913 configurable: true,
7914 writable: true,
7915 value: function (current, newValue, parent, subpath) {
7916 var newIdentifier = isStateTreeNode(newValue)
7917 ? this.options.set(newValue, current ? current.storedValue : null)
7918 : newValue;
7919 if (!current.isDetaching &&
7920 current.type === this &&
7921 current.storedValue === newIdentifier) {
7922 current.setParent(parent, subpath);
7923 return current;
7924 }
7925 var newNode = this.instantiate(parent, subpath, undefined, newIdentifier);
7926 current.die(); // noop if detaching
7927 return newNode;
7928 }
7929 });
7930 return CustomReferenceType;
7931}(BaseReferenceType));
7932/**
7933 * `types.reference` - Creates a reference to another type, which should have defined an identifier.
7934 * See also the [reference and identifiers](https://github.com/mobxjs/mobx-state-tree#references-and-identifiers) section.
7935 */
7936function reference(subType, options) {
7937 assertIsType(subType, 1);
7938 if (devMode()) {
7939 if (arguments.length === 2 && typeof arguments[1] === "string") {
7940 // istanbul ignore next
7941 throw fail$1("References with base path are no longer supported. Please remove the base path.");
7942 }
7943 }
7944 var getSetOptions = options ? options : undefined;
7945 var onInvalidated = options
7946 ? options.onInvalidated
7947 : undefined;
7948 if (getSetOptions && (getSetOptions.get || getSetOptions.set)) {
7949 if (devMode()) {
7950 if (!getSetOptions.get || !getSetOptions.set) {
7951 throw fail$1("reference options must either contain both a 'get' and a 'set' method or none of them");
7952 }
7953 }
7954 return new CustomReferenceType(subType, {
7955 get: getSetOptions.get,
7956 set: getSetOptions.set
7957 }, onInvalidated);
7958 }
7959 else {
7960 return new IdentifierReferenceType(subType, onInvalidated);
7961 }
7962}
7963/**
7964 * Returns if a given value represents a reference type.
7965 *
7966 * @param type
7967 * @returns
7968 */
7969function isReferenceType(type) {
7970 return (type.flags & TypeFlags.Reference) > 0;
7971}
7972/**
7973 * `types.safeReference` - A safe reference is like a standard reference, except that it accepts the undefined value by default
7974 * and automatically sets itself to undefined (when the parent is a model) / removes itself from arrays and maps
7975 * when the reference it is pointing to gets detached/destroyed.
7976 *
7977 * The optional options parameter object accepts a parameter named `acceptsUndefined`, which is set to true by default, so it is suitable
7978 * for model properties.
7979 * When used inside collections (arrays/maps), it is recommended to set this option to false so it can't take undefined as value,
7980 * which is usually the desired in those cases.
7981 * Additionally, the optional options parameter object accepts a parameter named `onInvalidated`, which will be called when the reference target node that the reference is pointing to is about to be detached/destroyed
7982 *
7983 * Strictly speaking it is a `types.maybe(types.reference(X))` (when `acceptsUndefined` is set to true, the default) and
7984 * `types.reference(X)` (when `acceptsUndefined` is set to false), both of them with a customized `onInvalidated` option.
7985 *
7986 * @param subType
7987 * @param options
7988 * @returns
7989 */
7990function safeReference(subType, options) {
7991 var refType = reference(subType, __assign(__assign({}, options), { onInvalidated: function (ev) {
7992 if (options && options.onInvalidated) {
7993 options.onInvalidated(ev);
7994 }
7995 ev.removeRef();
7996 } }));
7997 if (options && options.acceptsUndefined === false) {
7998 return refType;
7999 }
8000 else {
8001 return maybe(refType);
8002 }
8003}
8004
8005var BaseIdentifierType = /** @class */ (function (_super) {
8006 __extends(BaseIdentifierType, _super);
8007 function BaseIdentifierType(name, validType) {
8008 var _this = _super.call(this, name) || this;
8009 Object.defineProperty(_this, "validType", {
8010 enumerable: true,
8011 configurable: true,
8012 writable: true,
8013 value: validType
8014 });
8015 Object.defineProperty(_this, "flags", {
8016 enumerable: true,
8017 configurable: true,
8018 writable: true,
8019 value: TypeFlags.Identifier
8020 });
8021 return _this;
8022 }
8023 Object.defineProperty(BaseIdentifierType.prototype, "instantiate", {
8024 enumerable: false,
8025 configurable: true,
8026 writable: true,
8027 value: function (parent, subpath, environment, initialValue) {
8028 if (!parent || !(parent.type instanceof ModelType))
8029 throw fail$1("Identifier types can only be instantiated as direct child of a model type");
8030 return createScalarNode(this, parent, subpath, environment, initialValue);
8031 }
8032 });
8033 Object.defineProperty(BaseIdentifierType.prototype, "reconcile", {
8034 enumerable: false,
8035 configurable: true,
8036 writable: true,
8037 value: function (current, newValue, parent, subpath) {
8038 // we don't consider detaching here since identifier are scalar nodes, and scalar nodes cannot be detached
8039 if (current.storedValue !== newValue)
8040 throw fail$1("Tried to change identifier from '" + current.storedValue + "' to '" + newValue + "'. Changing identifiers is not allowed.");
8041 current.setParent(parent, subpath);
8042 return current;
8043 }
8044 });
8045 Object.defineProperty(BaseIdentifierType.prototype, "isValidSnapshot", {
8046 enumerable: false,
8047 configurable: true,
8048 writable: true,
8049 value: function (value, context) {
8050 if (typeof value !== this.validType) {
8051 return typeCheckFailure(context, value, "Value is not a valid " + this.describe() + ", expected a " + this.validType);
8052 }
8053 return typeCheckSuccess();
8054 }
8055 });
8056 return BaseIdentifierType;
8057}(SimpleType));
8058/**
8059 * @internal
8060 * @hidden
8061 */
8062var IdentifierType = /** @class */ (function (_super) {
8063 __extends(IdentifierType, _super);
8064 function IdentifierType() {
8065 var _this = _super.call(this, "identifier", "string") || this;
8066 Object.defineProperty(_this, "flags", {
8067 enumerable: true,
8068 configurable: true,
8069 writable: true,
8070 value: TypeFlags.Identifier
8071 });
8072 return _this;
8073 }
8074 Object.defineProperty(IdentifierType.prototype, "describe", {
8075 enumerable: false,
8076 configurable: true,
8077 writable: true,
8078 value: function () {
8079 return "identifier";
8080 }
8081 });
8082 return IdentifierType;
8083}(BaseIdentifierType));
8084/**
8085 * @internal
8086 * @hidden
8087 */
8088var IdentifierNumberType = /** @class */ (function (_super) {
8089 __extends(IdentifierNumberType, _super);
8090 function IdentifierNumberType() {
8091 return _super.call(this, "identifierNumber", "number") || this;
8092 }
8093 Object.defineProperty(IdentifierNumberType.prototype, "getSnapshot", {
8094 enumerable: false,
8095 configurable: true,
8096 writable: true,
8097 value: function (node) {
8098 return node.storedValue;
8099 }
8100 });
8101 Object.defineProperty(IdentifierNumberType.prototype, "describe", {
8102 enumerable: false,
8103 configurable: true,
8104 writable: true,
8105 value: function () {
8106 return "identifierNumber";
8107 }
8108 });
8109 return IdentifierNumberType;
8110}(BaseIdentifierType));
8111/**
8112 * `types.identifier` - Identifiers are used to make references, lifecycle events and reconciling works.
8113 * Inside a state tree, for each type can exist only one instance for each given identifier.
8114 * For example there couldn't be 2 instances of user with id 1. If you need more, consider using references.
8115 * Identifier can be used only as type property of a model.
8116 * This type accepts as parameter the value type of the identifier field that can be either string or number.
8117 *
8118 * Example:
8119 * ```ts
8120 * const Todo = types.model("Todo", {
8121 * id: types.identifier,
8122 * title: types.string
8123 * })
8124 * ```
8125 *
8126 * @returns
8127 */
8128var identifier = new IdentifierType();
8129/**
8130 * `types.identifierNumber` - Similar to `types.identifier`. This one will serialize from / to a number when applying snapshots
8131 *
8132 * Example:
8133 * ```ts
8134 * const Todo = types.model("Todo", {
8135 * id: types.identifierNumber,
8136 * title: types.string
8137 * })
8138 * ```
8139 *
8140 * @returns
8141 */
8142var identifierNumber = new IdentifierNumberType();
8143/**
8144 * Returns if a given value represents an identifier type.
8145 *
8146 * @param type
8147 * @returns
8148 */
8149function isIdentifierType(type) {
8150 return isType(type) && (type.flags & TypeFlags.Identifier) > 0;
8151}
8152/**
8153 * @internal
8154 * @hidden
8155 */
8156function normalizeIdentifier(id) {
8157 return "" + id;
8158}
8159/**
8160 * @internal
8161 * @hidden
8162 */
8163function isValidIdentifier(id) {
8164 return typeof id === "string" || typeof id === "number";
8165}
8166/**
8167 * @internal
8168 * @hidden
8169 */
8170function assertIsValidIdentifier(id, argNumber) {
8171 assertArg(id, isValidIdentifier, "string or number (identifier)", argNumber);
8172}
8173
8174/**
8175 * `types.custom` - Creates a custom type. Custom types can be used for arbitrary immutable values, that have a serializable representation. For example, to create your own Date representation, Decimal type etc.
8176 *
8177 * The signature of the options is:
8178 * ```ts
8179 * export interface CustomTypeOptions<S, T> {
8180 * // Friendly name
8181 * name: string
8182 * // given a serialized value and environment, how to turn it into the target type
8183 * fromSnapshot(snapshot: S, env: any): T
8184 * // return the serialization of the current value
8185 * toSnapshot(value: T): S
8186 * // if true, this is a converted value, if false, it's a snapshot
8187 * isTargetType(value: T | S): value is T
8188 * // a non empty string is assumed to be a validation error
8189 * getValidationMessage?(snapshot: S): string
8190 * }
8191 * ```
8192 *
8193 * Example:
8194 * ```ts
8195 * const DecimalPrimitive = types.custom<string, Decimal>({
8196 * name: "Decimal",
8197 * fromSnapshot(value: string) {
8198 * return new Decimal(value)
8199 * },
8200 * toSnapshot(value: Decimal) {
8201 * return value.toString()
8202 * },
8203 * isTargetType(value: string | Decimal): boolean {
8204 * return value instanceof Decimal
8205 * },
8206 * getValidationMessage(value: string): string {
8207 * if (/^-?\d+\.\d+$/.test(value)) return "" // OK
8208 * return `'${value}' doesn't look like a valid decimal number`
8209 * }
8210 * })
8211 *
8212 * const Wallet = types.model({
8213 * balance: DecimalPrimitive
8214 * })
8215 * ```
8216 *
8217 * @param options
8218 * @returns
8219 */
8220function custom(options) {
8221 return new CustomType(options);
8222}
8223/**
8224 * @internal
8225 * @hidden
8226 */
8227var CustomType = /** @class */ (function (_super) {
8228 __extends(CustomType, _super);
8229 function CustomType(options) {
8230 var _this = _super.call(this, options.name) || this;
8231 Object.defineProperty(_this, "options", {
8232 enumerable: true,
8233 configurable: true,
8234 writable: true,
8235 value: options
8236 });
8237 Object.defineProperty(_this, "flags", {
8238 enumerable: true,
8239 configurable: true,
8240 writable: true,
8241 value: TypeFlags.Custom
8242 });
8243 return _this;
8244 }
8245 Object.defineProperty(CustomType.prototype, "describe", {
8246 enumerable: false,
8247 configurable: true,
8248 writable: true,
8249 value: function () {
8250 return this.name;
8251 }
8252 });
8253 Object.defineProperty(CustomType.prototype, "isValidSnapshot", {
8254 enumerable: false,
8255 configurable: true,
8256 writable: true,
8257 value: function (value, context) {
8258 if (this.options.isTargetType(value))
8259 return typeCheckSuccess();
8260 var typeError = this.options.getValidationMessage(value);
8261 if (typeError) {
8262 return typeCheckFailure(context, value, "Invalid value for type '" + this.name + "': " + typeError);
8263 }
8264 return typeCheckSuccess();
8265 }
8266 });
8267 Object.defineProperty(CustomType.prototype, "getSnapshot", {
8268 enumerable: false,
8269 configurable: true,
8270 writable: true,
8271 value: function (node) {
8272 return this.options.toSnapshot(node.storedValue);
8273 }
8274 });
8275 Object.defineProperty(CustomType.prototype, "instantiate", {
8276 enumerable: false,
8277 configurable: true,
8278 writable: true,
8279 value: function (parent, subpath, environment, initialValue) {
8280 var valueToStore = this.options.isTargetType(initialValue)
8281 ? initialValue
8282 : this.options.fromSnapshot(initialValue, parent && parent.root.environment);
8283 return createScalarNode(this, parent, subpath, environment, valueToStore);
8284 }
8285 });
8286 Object.defineProperty(CustomType.prototype, "reconcile", {
8287 enumerable: false,
8288 configurable: true,
8289 writable: true,
8290 value: function (current, value, parent, subpath) {
8291 var isSnapshot = !this.options.isTargetType(value);
8292 // in theory customs use scalar nodes which cannot be detached, but still...
8293 if (!current.isDetaching) {
8294 var unchanged = current.type === this &&
8295 (isSnapshot ? value === current.snapshot : value === current.storedValue);
8296 if (unchanged) {
8297 current.setParent(parent, subpath);
8298 return current;
8299 }
8300 }
8301 var valueToStore = isSnapshot
8302 ? this.options.fromSnapshot(value, parent.root.environment)
8303 : value;
8304 var newNode = this.instantiate(parent, subpath, undefined, valueToStore);
8305 current.die(); // noop if detaching
8306 return newNode;
8307 }
8308 });
8309 return CustomType;
8310}(SimpleType));
8311
8312// we import the types to re-export them inside types.
8313var types = {
8314 enumeration: enumeration,
8315 model: model,
8316 compose: compose,
8317 custom: custom,
8318 reference: reference,
8319 safeReference: safeReference,
8320 union: union,
8321 optional: optional,
8322 literal: literal,
8323 maybe: maybe,
8324 maybeNull: maybeNull,
8325 refinement: refinement,
8326 string: string,
8327 boolean: boolean,
8328 number: number,
8329 integer: integer,
8330 Date: DatePrimitive,
8331 map: map,
8332 array: array,
8333 frozen: frozen,
8334 identifier: identifier,
8335 identifierNumber: identifierNumber,
8336 late: late,
8337 undefined: undefinedType,
8338 null: nullType,
8339 snapshotProcessor: snapshotProcessor
8340};
8341
8342exports.addDisposer = addDisposer;
8343exports.addMiddleware = addMiddleware;
8344exports.applyAction = applyAction;
8345exports.applyPatch = applyPatch;
8346exports.applySnapshot = applySnapshot;
8347exports.cast = cast;
8348exports.castFlowReturn = castFlowReturn;
8349exports.castToReferenceSnapshot = castToReferenceSnapshot;
8350exports.castToSnapshot = castToSnapshot;
8351exports.clone = clone;
8352exports.createActionTrackingMiddleware = createActionTrackingMiddleware;
8353exports.createActionTrackingMiddleware2 = createActionTrackingMiddleware2;
8354exports.decorate = decorate;
8355exports.destroy = destroy;
8356exports.detach = detach;
8357exports.escapeJsonPath = escapeJsonPath;
8358exports.flow = flow;
8359exports.getChildType = getChildType;
8360exports.getEnv = getEnv;
8361exports.getIdentifier = getIdentifier;
8362exports.getLivelinessChecking = getLivelinessChecking;
8363exports.getMembers = getMembers;
8364exports.getNodeId = getNodeId;
8365exports.getParent = getParent;
8366exports.getParentOfType = getParentOfType;
8367exports.getPath = getPath;
8368exports.getPathParts = getPathParts;
8369exports.getPropertyMembers = getPropertyMembers;
8370exports.getRelativePath = getRelativePath;
8371exports.getRoot = getRoot;
8372exports.getRunningActionContext = getRunningActionContext;
8373exports.getSnapshot = getSnapshot;
8374exports.getType = getType;
8375exports.hasParent = hasParent;
8376exports.hasParentOfType = hasParentOfType;
8377exports.isActionContextChildOf = isActionContextChildOf;
8378exports.isActionContextThisOrChildOf = isActionContextThisOrChildOf;
8379exports.isAlive = isAlive;
8380exports.isArrayType = isArrayType;
8381exports.isFrozenType = isFrozenType;
8382exports.isIdentifierType = isIdentifierType;
8383exports.isLateType = isLateType;
8384exports.isLiteralType = isLiteralType;
8385exports.isMapType = isMapType;
8386exports.isModelType = isModelType;
8387exports.isOptionalType = isOptionalType;
8388exports.isPrimitiveType = isPrimitiveType;
8389exports.isProtected = isProtected;
8390exports.isReferenceType = isReferenceType;
8391exports.isRefinementType = isRefinementType;
8392exports.isRoot = isRoot;
8393exports.isStateTreeNode = isStateTreeNode;
8394exports.isType = isType;
8395exports.isUnionType = isUnionType;
8396exports.isValidReference = isValidReference;
8397exports.joinJsonPath = joinJsonPath;
8398exports.onAction = onAction;
8399exports.onPatch = onPatch;
8400exports.onSnapshot = onSnapshot;
8401exports.process = process$1;
8402exports.protect = protect;
8403exports.recordActions = recordActions;
8404exports.recordPatches = recordPatches;
8405exports.resolveIdentifier = resolveIdentifier;
8406exports.resolvePath = resolvePath;
8407exports.setLivelinessChecking = setLivelinessChecking;
8408exports.setLivelynessChecking = setLivelynessChecking;
8409exports.splitJsonPath = splitJsonPath;
8410exports.toGenerator = toGenerator;
8411exports.toGeneratorFunction = toGeneratorFunction;
8412exports.tryReference = tryReference;
8413exports.tryResolve = tryResolve;
8414exports.typecheck = typecheck;
8415exports.types = types;
8416exports.unescapeJsonPath = unescapeJsonPath;
8417exports.unprotect = unprotect;
8418exports.walk = walk;