UNPKG

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