@legendapp/state 2.2.0-next.2 → 2.2.0-next.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/babel.js.map +1 -1
  2. package/config/enableDirectAccess.d.ts +1 -1
  3. package/config/enableDirectPeek.d.ts +1 -1
  4. package/config/enableReactDirectRender.js.map +1 -1
  5. package/config/enableReactDirectRender.mjs.map +1 -1
  6. package/config/enableReactTracking.d.ts +4 -3
  7. package/config/enableReactTracking.js.map +1 -1
  8. package/config/enableReactTracking.mjs.map +1 -1
  9. package/config/enableReactUse.d.ts +1 -1
  10. package/helpers/fetch.d.ts +4 -3
  11. package/helpers/fetch.js.map +1 -1
  12. package/helpers/fetch.mjs.map +1 -1
  13. package/helpers/pageHash.js.map +1 -1
  14. package/helpers/pageHash.mjs.map +1 -1
  15. package/helpers/pageHashParams.js.map +1 -1
  16. package/helpers/pageHashParams.mjs.map +1 -1
  17. package/helpers/time.d.ts +2 -2
  18. package/helpers/time.js.map +1 -1
  19. package/helpers/time.mjs.map +1 -1
  20. package/history.js.map +1 -1
  21. package/history.mjs.map +1 -1
  22. package/index.d.ts +14 -9
  23. package/index.js +522 -226
  24. package/index.js.map +1 -1
  25. package/index.mjs +521 -227
  26. package/index.mjs.map +1 -1
  27. package/package.json +2 -10
  28. package/persist-plugins/async-storage.js.map +1 -1
  29. package/persist-plugins/async-storage.mjs.map +1 -1
  30. package/persist-plugins/fetch.js.map +1 -1
  31. package/persist-plugins/fetch.mjs.map +1 -1
  32. package/persist-plugins/firebase.js +3 -3
  33. package/persist-plugins/firebase.js.map +1 -1
  34. package/persist-plugins/firebase.mjs +3 -3
  35. package/persist-plugins/firebase.mjs.map +1 -1
  36. package/persist-plugins/indexeddb.js.map +1 -1
  37. package/persist-plugins/indexeddb.mjs.map +1 -1
  38. package/persist-plugins/local-storage.js +1 -1
  39. package/persist-plugins/local-storage.js.map +1 -1
  40. package/persist-plugins/local-storage.mjs +1 -1
  41. package/persist-plugins/local-storage.mjs.map +1 -1
  42. package/persist-plugins/mmkv.js.map +1 -1
  43. package/persist-plugins/mmkv.mjs.map +1 -1
  44. package/persist-plugins/query.js.map +1 -1
  45. package/persist-plugins/query.mjs.map +1 -1
  46. package/persist.d.ts +16 -1
  47. package/persist.js +406 -138
  48. package/persist.js.map +1 -1
  49. package/persist.mjs +407 -139
  50. package/persist.mjs.map +1 -1
  51. package/react-hooks/createObservableHook.js +1 -1
  52. package/react-hooks/createObservableHook.js.map +1 -1
  53. package/react-hooks/createObservableHook.mjs +1 -1
  54. package/react-hooks/createObservableHook.mjs.map +1 -1
  55. package/react-hooks/useFetch.d.ts +4 -3
  56. package/react-hooks/useFetch.js.map +1 -1
  57. package/react-hooks/useFetch.mjs.map +1 -1
  58. package/react-hooks/useHover.js.map +1 -1
  59. package/react-hooks/useHover.mjs.map +1 -1
  60. package/react-hooks/useMeasure.js.map +1 -1
  61. package/react-hooks/useMeasure.mjs.map +1 -1
  62. package/react-hooks/useObservableNextRouter.js.map +1 -1
  63. package/react-hooks/useObservableNextRouter.mjs.map +1 -1
  64. package/react-hooks/useObservableQuery.js.map +1 -1
  65. package/react-hooks/useObservableQuery.mjs.map +1 -1
  66. package/react-hooks/usePersistedObservable.d.ts +2 -2
  67. package/react-hooks/usePersistedObservable.js +3 -3
  68. package/react-hooks/usePersistedObservable.js.map +1 -1
  69. package/react-hooks/usePersistedObservable.mjs +3 -3
  70. package/react-hooks/usePersistedObservable.mjs.map +1 -1
  71. package/react.js +13 -8
  72. package/react.js.map +1 -1
  73. package/react.mjs +14 -9
  74. package/react.mjs.map +1 -1
  75. package/src/ObservableObject.d.ts +8 -4
  76. package/src/ObservablePrimitive.d.ts +2 -1
  77. package/src/activated.d.ts +3 -0
  78. package/src/batching.d.ts +3 -1
  79. package/src/computed.d.ts +1 -1
  80. package/src/config/enableDirectAccess.d.ts +1 -1
  81. package/src/config/enableDirectPeek.d.ts +1 -1
  82. package/src/config/enableReactTracking.d.ts +4 -3
  83. package/src/config/enableReactUse.d.ts +1 -1
  84. package/src/createObservable.d.ts +2 -2
  85. package/src/globals.d.ts +10 -9
  86. package/src/helpers/fetch.d.ts +4 -3
  87. package/src/helpers/time.d.ts +2 -2
  88. package/src/helpers.d.ts +3 -2
  89. package/src/history/trackHistory.d.ts +1 -1
  90. package/src/observable.d.ts +6 -15
  91. package/src/observableInterfaces.d.ts +68 -315
  92. package/src/observableTypes.d.ts +93 -0
  93. package/src/persist/observablePersistRemoteFunctionsAdapter.d.ts +1 -1
  94. package/src/persist/persistActivateNode.d.ts +1 -0
  95. package/src/persist/persistHelpers.d.ts +1 -1
  96. package/src/persist/persistObservable.d.ts +3 -3
  97. package/src/persistTypes.d.ts +229 -0
  98. package/src/proxy.d.ts +2 -1
  99. package/src/react/Computed.d.ts +1 -1
  100. package/src/react/Switch.d.ts +3 -3
  101. package/src/react/reactInterfaces.d.ts +2 -1
  102. package/src/react/usePauseProvider.d.ts +3 -3
  103. package/src/react/useWhen.d.ts +2 -2
  104. package/src/react-hooks/useFetch.d.ts +4 -3
  105. package/src/react-hooks/usePersistedObservable.d.ts +2 -2
  106. package/src/retry.d.ts +4 -0
  107. package/src/trackSelector.d.ts +3 -2
  108. package/src/when.d.ts +6 -2
  109. package/trace.js.map +1 -1
  110. package/trace.mjs.map +1 -1
package/index.mjs CHANGED
@@ -6,7 +6,7 @@ function isString(obj) {
6
6
  return typeof obj === 'string';
7
7
  }
8
8
  function isObject(obj) {
9
- return !!obj && typeof obj === 'object' && !isArray(obj);
9
+ return !!obj && typeof obj === 'object' && !(obj instanceof Date) && !isArray(obj);
10
10
  }
11
11
  function isFunction(obj) {
12
12
  return typeof obj === 'function';
@@ -53,6 +53,7 @@ const symbolGetNode = Symbol('getNode');
53
53
  const symbolDelete = /* @__PURE__ */ Symbol('delete');
54
54
  const symbolOpaque = Symbol('opaque');
55
55
  const optimized = Symbol('optimized');
56
+ const symbolActivated = Symbol('activated');
56
57
  // TODOV3 Remove these
57
58
  const extraPrimitiveActivators = new Map();
58
59
  const extraPrimitiveProps = new Map();
@@ -61,6 +62,8 @@ const globalState = {
61
62
  isMerging: false,
62
63
  isLoadingRemote$: undefined,
63
64
  activateNode: undefined,
65
+ pendingNodes: new Map(),
66
+ dirtyNodes: new Set(),
64
67
  };
65
68
  function isObservable(obs) {
66
69
  return !!obs && !!obs[symbolGetNode];
@@ -156,8 +159,16 @@ function getChildNode(node, key, asFunction) {
156
159
  if (asFunction) {
157
160
  child = Object.assign(cloneFunction(asFunction), child);
158
161
  }
159
- else if (node.proxyFn2) {
160
- child = Object.assign(node.proxyFn2.bind(node, key), child);
162
+ else {
163
+ if (node.activationState) {
164
+ const { lookup } = node.activationState;
165
+ if (lookup) {
166
+ child = Object.assign(lookup.bind(node, key), child);
167
+ if (isFunction(child)) {
168
+ extractFunction(node, key, child);
169
+ }
170
+ }
171
+ }
161
172
  }
162
173
  if (!node.children) {
163
174
  node.children = new Map();
@@ -202,9 +213,11 @@ function findIDKey(obj, node) {
202
213
  return idKey;
203
214
  }
204
215
  function extractFunction(node, key, fnOrComputed, computedChildNode) {
216
+ var _a;
205
217
  if (!node.functions) {
206
218
  node.functions = new Map();
207
219
  }
220
+ (_a = node.children) === null || _a === void 0 ? void 0 : _a.delete(key);
208
221
  node.functions.set(key, fnOrComputed);
209
222
  if (computedChildNode) {
210
223
  computedChildNode.parentOther = getChildNode(node, key);
@@ -215,6 +228,12 @@ function extractFunction(node, key, fnOrComputed, computedChildNode) {
215
228
  }
216
229
  }
217
230
 
231
+ function activated(params) {
232
+ return (() => ({
233
+ [symbolActivated]: params,
234
+ }));
235
+ }
236
+
218
237
  let timeout;
219
238
  let numInBatch = 0;
220
239
  let isRunningBatch = false;
@@ -239,23 +258,28 @@ function isArraySubset(mainArr, subsetArr) {
239
258
  return true;
240
259
  }
241
260
  function createPreviousHandlerInner(value, changes) {
242
- // Clones the current state and inject the previous data at the changed path
243
- let clone = value ? JSON.parse(JSON.stringify(value)) : {};
244
- for (let i = 0; i < changes.length; i++) {
245
- const { path, prevAtPath } = changes[i];
246
- let o = clone;
247
- if (path.length > 0) {
248
- let i;
249
- for (i = 0; i < path.length - 1; i++) {
250
- o = o[path[i]];
261
+ try {
262
+ // Clones the current state and inject the previous data at the changed path
263
+ let clone = value ? JSON.parse(JSON.stringify(value)) : {};
264
+ for (let i = 0; i < changes.length; i++) {
265
+ const { path, prevAtPath } = changes[i];
266
+ let o = clone;
267
+ if (path.length > 0) {
268
+ let i;
269
+ for (i = 0; i < path.length - 1; i++) {
270
+ o = o[path[i]];
271
+ }
272
+ o[path[i]] = prevAtPath;
273
+ }
274
+ else {
275
+ clone = prevAtPath;
251
276
  }
252
- o[path[i]] = prevAtPath;
253
- }
254
- else {
255
- clone = prevAtPath;
256
277
  }
278
+ return clone;
279
+ }
280
+ catch (_a) {
281
+ return undefined;
257
282
  }
258
- return clone;
259
283
  }
260
284
  function createPreviousHandler(value, changes) {
261
285
  // Create a function that generates the previous state
@@ -364,6 +388,13 @@ function batchNotifyChanges(changesInBatch, immediate) {
364
388
  });
365
389
  }
366
390
  function runBatch() {
391
+ const dirtyNodes = Array.from(globalState.dirtyNodes);
392
+ globalState.dirtyNodes.clear();
393
+ dirtyNodes.forEach((node) => {
394
+ var _a;
395
+ (_a = node.dirtyFn) === null || _a === void 0 ? void 0 : _a.call(node);
396
+ node.dirtyFn = undefined;
397
+ });
367
398
  // Save batch locally and reset _batchMap first because a new batch could begin while looping over callbacks.
368
399
  // This can happen with observableComputed for example.
369
400
  const map = _batchMap;
@@ -480,7 +511,7 @@ function isEvent(obs) {
480
511
  }
481
512
  function computeSelector(selector, e, retainObservable) {
482
513
  let c = selector;
483
- if (isFunction(c)) {
514
+ if (!isObservable(c) && isFunction(c)) {
484
515
  c = e ? c(e) : c();
485
516
  }
486
517
  return isObservable(c) && !retainObservable ? c.get() : c;
@@ -579,14 +610,15 @@ function _mergeIntoObservable(target, source) {
579
610
  const targetValue = needsSet ? target.peek() : target;
580
611
  const isTargetArr = isArray(targetValue);
581
612
  const isTargetObj = !isTargetArr && isObject(targetValue);
582
- if ((isTargetObj && isObject(source) && !isEmpty(targetValue)) ||
583
- (isTargetArr && isArray(source) && targetValue.length > 0)) {
613
+ if ((isTargetObj && isObject(source) && !isEmpty(targetValue)) || (isTargetArr && targetValue.length > 0)) {
584
614
  const keys = Object.keys(source);
585
615
  for (let i = 0; i < keys.length; i++) {
586
616
  const key = keys[i];
587
617
  const sourceValue = source[key];
588
618
  if (sourceValue === symbolDelete) {
589
- needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete) ? target[key].delete() : delete target[key];
619
+ needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete)
620
+ ? target[key].delete()
621
+ : delete target[key];
590
622
  }
591
623
  else {
592
624
  const isObj = isObject(sourceValue);
@@ -775,7 +807,7 @@ function trackSelector(selector, update, observeEvent, observeOptions, createRes
775
807
  dispose = setupTracking(nodes, updateFn, false, observeOptions === null || observeOptions === void 0 ? void 0 : observeOptions.immediate);
776
808
  resubscribe = createResubscribe ? () => setupTracking(nodes, updateFn) : undefined;
777
809
  }
778
- return { value, dispose, resubscribe };
810
+ return { value, nodes, dispose, resubscribe };
779
811
  }
780
812
 
781
813
  function observe(selectorOrRun, reactionOrOptions, options) {
@@ -800,9 +832,11 @@ function observe(selectorOrRun, reactionOrOptions, options) {
800
832
  delete e.value;
801
833
  // Dispose listeners from previous run
802
834
  dispose === null || dispose === void 0 ? void 0 : dispose();
803
- const { dispose: _dispose, value } = trackSelector(selectorOrRun, update, e, options);
835
+ const { dispose: _dispose, value, nodes } = trackSelector(selectorOrRun, update, e, options);
804
836
  dispose = _dispose;
805
837
  e.value = value;
838
+ e.nodes = nodes;
839
+ e.refresh = update;
806
840
  if (e.onCleanupReaction) {
807
841
  e.onCleanupReaction();
808
842
  e.onCleanupReaction = undefined;
@@ -810,7 +844,9 @@ function observe(selectorOrRun, reactionOrOptions, options) {
810
844
  endBatch();
811
845
  // Call the reaction if there is one and the value changed
812
846
  if (reaction &&
813
- ((options === null || options === void 0 ? void 0 : options.fromComputed) || ((e.num > 0 || !isEvent(selectorOrRun)) && e.previous !== e.value))) {
847
+ ((options === null || options === void 0 ? void 0 : options.fromComputed) ||
848
+ ((e.num > 0 || !isEvent(selectorOrRun)) &&
849
+ (e.previous !== e.value || typeof e.value === 'object')))) {
814
850
  reaction(e);
815
851
  }
816
852
  // Update the previous value
@@ -830,6 +866,115 @@ function observe(selectorOrRun, reactionOrOptions, options) {
830
866
  };
831
867
  }
832
868
 
869
+ function _when(predicate, effect, checkReady) {
870
+ // If predicate is a regular Promise skip all the observable stuff
871
+ if (isPromise(predicate)) {
872
+ return effect ? predicate.then(effect) : predicate;
873
+ }
874
+ let value;
875
+ let effectValue;
876
+ // Create a wrapping fn that calls the effect if predicate returns true
877
+ function run(e) {
878
+ const ret = computeSelector(predicate);
879
+ if (!isPromise(ret) && (checkReady ? isObservableValueReady(ret) : ret)) {
880
+ value = ret;
881
+ // Set cancel so that observe does not track anymore
882
+ e.cancel = true;
883
+ }
884
+ return value;
885
+ }
886
+ function doEffect() {
887
+ // If value is truthy then run the effect
888
+ effectValue = effect === null || effect === void 0 ? void 0 : effect(value);
889
+ }
890
+ // Run in an observe
891
+ observe(run, doEffect);
892
+ // If first run resulted in a truthy value just return it.
893
+ // It will have set e.cancel so no need to dispose
894
+ if (isPromise(value)) {
895
+ return effect ? value.then(effect) : value;
896
+ }
897
+ else if (value !== undefined) {
898
+ return effect ? effectValue : Promise.resolve(value);
899
+ }
900
+ else {
901
+ // Wrap it in a promise
902
+ const promise = new Promise((resolve) => {
903
+ if (effect) {
904
+ const originalEffect = effect;
905
+ effect = ((value) => {
906
+ const effectValue = originalEffect(value);
907
+ resolve(isPromise(effectValue) ? effectValue.then((value) => value) : effectValue);
908
+ });
909
+ }
910
+ else {
911
+ effect = resolve;
912
+ }
913
+ });
914
+ return promise;
915
+ }
916
+ }
917
+ function when(predicate, effect) {
918
+ return _when(predicate, effect, false);
919
+ }
920
+ function whenReady(predicate, effect) {
921
+ return _when(predicate, effect, true);
922
+ }
923
+
924
+ function calculateRetryDelay(retryOptions, attemptNum) {
925
+ const { backoff, delay = 1000, infinite, times = 3, maxDelay = 30000 } = retryOptions;
926
+ if (infinite || attemptNum < times) {
927
+ const delayTime = Math.min(delay * (backoff === 'constant' ? 1 : 2 ** attemptNum), maxDelay);
928
+ return delayTime;
929
+ }
930
+ return null;
931
+ }
932
+ function createRetryTimout(retryOptions, attemptNum, fn) {
933
+ const delayTime = calculateRetryDelay(retryOptions, attemptNum);
934
+ if (delayTime) {
935
+ return setTimeout(fn, delayTime);
936
+ }
937
+ }
938
+ function runWithRetry(node, state, fn) {
939
+ const { retry, waitFor } = node.activationState;
940
+ let value = undefined;
941
+ if (waitFor) {
942
+ value = whenReady(waitFor, () => {
943
+ node.activationState.waitFor = undefined;
944
+ return fn();
945
+ });
946
+ }
947
+ else {
948
+ value = fn();
949
+ }
950
+ if (isPromise(value) && retry) {
951
+ let timeoutRetry;
952
+ return new Promise((resolve) => {
953
+ const run = () => {
954
+ value
955
+ .then((val) => {
956
+ node.activationState.persistedRetry = false;
957
+ resolve(val);
958
+ })
959
+ .catch(() => {
960
+ node.activationState.persistedRetry = true;
961
+ state.attemptNum++;
962
+ if (timeoutRetry) {
963
+ clearTimeout(timeoutRetry);
964
+ }
965
+ timeoutRetry = createRetryTimout(retry, state.attemptNum, () => {
966
+ value = fn();
967
+ run();
968
+ });
969
+ });
970
+ };
971
+ run();
972
+ });
973
+ }
974
+ return value;
975
+ }
976
+
977
+ const noop = () => { };
833
978
  const ArrayModifiers = new Set([
834
979
  'copyWithin',
835
980
  'fill',
@@ -870,19 +1015,24 @@ if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
870
1015
  }
871
1016
  function collectionSetter(node, target, prop, ...args) {
872
1017
  var _a;
873
- const prevValue = (isArray(target) && target.slice()) || target;
874
- const ret = target[prop].apply(target, args);
875
- if (node) {
876
- const hasParent = isChildNodeValue(node);
877
- const key = hasParent ? node.key : '_';
878
- const parentValue = hasParent ? getNodeValue(node.parent) : node.root;
879
- // Set the object to the previous value first
880
- parentValue[key] = prevValue;
881
- // Then set with the new value so it notifies with the correct prevValue
882
- setKey((_a = node.parent) !== null && _a !== void 0 ? _a : node, key, target);
883
- }
884
- // Return the original value
885
- return ret;
1018
+ if (prop === 'push') {
1019
+ setKey(node, target.length + '', args[0]);
1020
+ }
1021
+ else {
1022
+ const prevValue = target.slice();
1023
+ const ret = target[prop].apply(target, args);
1024
+ if (node) {
1025
+ const hasParent = isChildNodeValue(node);
1026
+ const key = hasParent ? node.key : '_';
1027
+ const parentValue = hasParent ? getNodeValue(node.parent) : node.root;
1028
+ // Set the object to the previous value first
1029
+ parentValue[key] = prevValue;
1030
+ // Then set with the new value so it notifies with the correct prevValue
1031
+ setKey((_a = node.parent) !== null && _a !== void 0 ? _a : node, key, target);
1032
+ }
1033
+ // Return the original value
1034
+ return ret;
1035
+ }
886
1036
  }
887
1037
  function getKeys(obj, isArr, isMap) {
888
1038
  return isArr ? undefined : obj ? (isMap ? Array.from(obj.keys()) : Object.keys(obj)) : [];
@@ -917,8 +1067,9 @@ function updateNodes(parent, obj, prevValue) {
917
1067
  let prevChildrenById;
918
1068
  let moved;
919
1069
  const isMap = obj instanceof Map;
1070
+ const isPrevMap = prevValue instanceof Map;
920
1071
  const keys = getKeys(obj, isArr, isMap);
921
- const keysPrev = getKeys(prevValue, isArr, isMap);
1072
+ const keysPrev = getKeys(prevValue, isArr, isPrevMap);
922
1073
  const length = ((_a = (keys || obj)) === null || _a === void 0 ? void 0 : _a.length) || 0;
923
1074
  const lengthPrev = ((_b = (keysPrev || prevValue)) === null || _b === void 0 ? void 0 : _b.length) || 0;
924
1075
  let idField;
@@ -970,7 +1121,7 @@ function updateNodes(parent, obj, prevValue) {
970
1121
  if (!keys.includes(key)) {
971
1122
  hasADiff = true;
972
1123
  const child = getChildNode(parent, key);
973
- const prev = isMap ? prevValue.get(key) : prevValue[key];
1124
+ const prev = isPrevMap ? prevValue.get(key) : prevValue[key];
974
1125
  if (prev !== undefined) {
975
1126
  if (!isPrimitive(prev)) {
976
1127
  updateNodes(child, undefined, prev);
@@ -989,7 +1140,7 @@ function updateNodes(parent, obj, prevValue) {
989
1140
  for (let i = 0; i < length; i++) {
990
1141
  const key = isArr ? i + '' : keys[i];
991
1142
  const value = isMap ? obj.get(key) : obj[key];
992
- const prev = isMap ? prevValue === null || prevValue === void 0 ? void 0 : prevValue.get(key) : prevValue === null || prevValue === void 0 ? void 0 : prevValue[key];
1143
+ const prev = isPrevMap ? prevValue === null || prevValue === void 0 ? void 0 : prevValue.get(key) : prevValue === null || prevValue === void 0 ? void 0 : prevValue[key];
993
1144
  let isDiff = value !== prev;
994
1145
  if (isDiff) {
995
1146
  const id = idField && value
@@ -1027,7 +1178,10 @@ function updateNodes(parent, obj, prevValue) {
1027
1178
  if (isDiff) {
1028
1179
  // Array has a new / modified element
1029
1180
  // If object iterate through its children
1030
- if (isPrimitive(value)) {
1181
+ if (isFunction(value)) {
1182
+ extractFunctionOrComputed(parent, obj, key, value);
1183
+ }
1184
+ else if (isPrimitive(value)) {
1031
1185
  hasADiff = true;
1032
1186
  }
1033
1187
  else {
@@ -1075,6 +1229,15 @@ function getProxy(node, p, asFunction) {
1075
1229
  // Create a proxy if not already cached and return it
1076
1230
  return (node.proxy || (node.proxy = new Proxy(node, proxyHandler)));
1077
1231
  }
1232
+ function flushPending() {
1233
+ // Need to short circuit the computed batching because the user called get() or peek()
1234
+ // in which case the set needs to run immediately so that the values are up to date.
1235
+ if (globalState.pendingNodes.size > 0) {
1236
+ const nodes = Array.from(globalState.pendingNodes.values());
1237
+ globalState.pendingNodes.clear();
1238
+ nodes.forEach((fn) => fn());
1239
+ }
1240
+ }
1078
1241
  const proxyHandler = {
1079
1242
  get(node, p, receiver) {
1080
1243
  var _a;
@@ -1102,6 +1265,9 @@ const proxyHandler = {
1102
1265
  const fn = observableFns.get(p);
1103
1266
  // If this is an observable function, call it
1104
1267
  if (fn) {
1268
+ if (p === 'get' || p === 'peek') {
1269
+ flushPending();
1270
+ }
1105
1271
  return function (a, b, c) {
1106
1272
  const l = arguments.length;
1107
1273
  // Array call and apply are slow so micro-optimize this hot path.
@@ -1207,10 +1373,6 @@ const proxyHandler = {
1207
1373
  return vProp;
1208
1374
  }
1209
1375
  }
1210
- // TODOV3: Remove "state"
1211
- if (vProp === undefined && (p === 'state' || p === '_state') && node.state) {
1212
- return node.state;
1213
- }
1214
1376
  // Return an observable proxy to the property
1215
1377
  return getProxy(node, p);
1216
1378
  },
@@ -1302,12 +1464,14 @@ function setKey(node, key, newValue, level) {
1302
1464
  console.warn(`[legend-state] Set an HTMLElement into state. You probably don't want to do that.`);
1303
1465
  }
1304
1466
  }
1467
+ const isRoot = !node.parent && key === '_';
1468
+ // TODOv3 root locking will be removed with old computeds
1305
1469
  if (node.root.locked && !node.root.set) {
1306
1470
  // This happens when modifying a locked observable such as a computed.
1307
1471
  // If merging this could be happening deep in a hierarchy so we don't want to throw errors so we'll just do nothing.
1308
1472
  // This could happen during persistence local load for example.
1309
1473
  if (globalState.isMerging) {
1310
- return;
1474
+ return isRoot ? getProxy(node) : getProxy(node, key);
1311
1475
  }
1312
1476
  else {
1313
1477
  throw new Error(process.env.NODE_ENV === 'development'
@@ -1315,18 +1479,28 @@ function setKey(node, key, newValue, level) {
1315
1479
  : '[legend-state] Modified locked observable');
1316
1480
  }
1317
1481
  }
1318
- const isRoot = !node.parent && key === '_';
1482
+ if (node.parent && !getNodeValue(node)) {
1483
+ return set(node, { [key]: newValue });
1484
+ }
1319
1485
  // Get the child node for updating and notifying
1320
1486
  const childNode = isRoot ? node : getChildNode(node, key, isFunction(newValue) ? newValue : undefined);
1321
- // Set the raw value on the parent object
1322
- const { newValue: savedValue, prevValue, parentValue } = setNodeValue(childNode, newValue);
1323
- const isFunc = isFunction(savedValue);
1324
- const isPrim = isPrimitive(savedValue) || savedValue instanceof Date;
1325
- if (savedValue !== prevValue) {
1326
- updateNodesAndNotify(node, savedValue, prevValue, childNode, isPrim, isRoot, level);
1487
+ if (isObservable(newValue)) {
1488
+ setToObservable(childNode, newValue);
1327
1489
  }
1328
- extractFunctionOrComputed(node, parentValue, key, savedValue);
1329
- return isFunc ? savedValue : isRoot ? getProxy(node) : getProxy(node, key);
1490
+ else {
1491
+ // Set the raw value on the parent object
1492
+ const { newValue: savedValue, prevValue, parentValue } = setNodeValue(childNode, newValue);
1493
+ const isFunc = isFunction(savedValue);
1494
+ const isPrim = isPrimitive(savedValue) || savedValue instanceof Date;
1495
+ if (savedValue !== prevValue) {
1496
+ updateNodesAndNotify(node, savedValue, prevValue, childNode, isPrim, isRoot, level);
1497
+ }
1498
+ extractFunctionOrComputed(node, parentValue, key, savedValue);
1499
+ if (isFunc) {
1500
+ return savedValue;
1501
+ }
1502
+ }
1503
+ return isRoot ? getProxy(node) : getProxy(node, key);
1330
1504
  }
1331
1505
  function assign(node, value) {
1332
1506
  const proxy = getProxy(node);
@@ -1431,7 +1605,7 @@ function handlerMapSet(node, p, value) {
1431
1605
  function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRoot, level) {
1432
1606
  if (!childNode)
1433
1607
  childNode = node;
1434
- // Make sure we don't call too many listeners for ever property set
1608
+ // Make sure we don't call too many listeners for every property set
1435
1609
  beginBatch();
1436
1610
  let hasADiff = isPrim;
1437
1611
  let whenOptimizedOnlyIf = false;
@@ -1452,7 +1626,7 @@ function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRo
1452
1626
  }
1453
1627
  endBatch();
1454
1628
  }
1455
- function extractPromise(node, value) {
1629
+ function extractPromise(node, value, setter) {
1456
1630
  if (!node.state) {
1457
1631
  node.state = createObservable({
1458
1632
  isLoaded: false,
@@ -1460,26 +1634,38 @@ function extractPromise(node, value) {
1460
1634
  }
1461
1635
  value
1462
1636
  .then((value) => {
1463
- set(node, value);
1464
- node.state.isLoaded.set(true);
1637
+ setter ? setter({ value }) : set(node, value);
1638
+ node.state.assign({
1639
+ isLoaded: true,
1640
+ error: undefined,
1641
+ });
1465
1642
  })
1466
1643
  .catch((error) => {
1467
1644
  node.state.error.set(error);
1468
1645
  });
1469
1646
  }
1470
1647
  function extractFunctionOrComputed(node, obj, k, v) {
1648
+ var _a;
1471
1649
  if (isPromise(v)) {
1472
- extractPromise(getChildNode(node, k), v);
1650
+ const childNode = getChildNode(node, k);
1651
+ extractPromise(childNode, v);
1652
+ setNodeValue(childNode, undefined);
1473
1653
  }
1474
1654
  else if (typeof v === 'function') {
1655
+ const childNode = (_a = node.children) === null || _a === void 0 ? void 0 : _a.get(k);
1475
1656
  extractFunction(node, k, v);
1476
- delete obj[k];
1657
+ // If child was previously activated, then peek the new linked observable to make sure it's activated
1658
+ if (childNode && !childNode.lazy) {
1659
+ if (isObservable(v)) {
1660
+ const vNode = getNode(v);
1661
+ peek(vNode);
1662
+ }
1663
+ }
1477
1664
  }
1478
1665
  else if (typeof v == 'object' && v !== null && v !== undefined) {
1479
1666
  const childNode = getNode(v);
1480
1667
  if (childNode === null || childNode === void 0 ? void 0 : childNode.isComputed) {
1481
1668
  extractFunction(node, k, v, childNode);
1482
- delete obj[k];
1483
1669
  }
1484
1670
  else {
1485
1671
  return true;
@@ -1493,20 +1679,29 @@ function get(node, options) {
1493
1679
  return peek(node);
1494
1680
  }
1495
1681
  function peek(node) {
1496
- const value = getNodeValue(node);
1682
+ if (node.dirtyFn) {
1683
+ node.dirtyFn();
1684
+ globalState.dirtyNodes.delete(node);
1685
+ node.dirtyFn = undefined;
1686
+ }
1687
+ let value = getNodeValue(node);
1497
1688
  // If node is not yet lazily computed go do that
1498
1689
  const lazy = node.lazy;
1499
1690
  if (lazy) {
1500
1691
  delete node.lazy;
1501
1692
  if (isFunction(node) || isFunction(lazy)) {
1502
- activateNodeFunction(node, lazy);
1503
- }
1504
- else {
1505
- for (const key in value) {
1506
- if (hasOwnProperty.call(value, key)) {
1507
- extractFunctionOrComputed(node, value, key, value[key]);
1693
+ if (node.parent) {
1694
+ const parentValue = getNodeValue(node.parent);
1695
+ if (parentValue) {
1696
+ delete parentValue[node.key];
1508
1697
  }
1509
1698
  }
1699
+ value = activateNodeFunction(node, lazy);
1700
+ }
1701
+ for (const key in value) {
1702
+ if (hasOwnProperty.call(value, key)) {
1703
+ extractFunctionOrComputed(node, value, key, value[key]);
1704
+ }
1510
1705
  }
1511
1706
  }
1512
1707
  // Check if computed needs to activate
@@ -1514,137 +1709,272 @@ function peek(node) {
1514
1709
  return value;
1515
1710
  }
1516
1711
  function activateNodeFunction(node, lazyFn) {
1517
- let setter;
1712
+ // let prevTarget$: Observable<any>;
1713
+ // let curTarget$: Observable<any>;
1518
1714
  let update;
1519
- let subscriber;
1520
- const lastSync = {};
1521
- let cacheOptions;
1522
- // The onSet function handles the observable being set
1523
- // and forwards the set elsewhere
1524
- const onSet = (setterParam) => {
1525
- setter = setterParam;
1526
- };
1527
- // The onSet function handles the observable being set
1528
- // and forwards the set elsewhere
1529
- const updateLastSync = (fn) => {
1530
- lastSync.value = fn;
1531
- };
1532
- // The subscribe function runs a function that listens to
1533
- // a data source and sends updates into the observable
1534
- const subscribe = (fn) => {
1535
- if (!subscriber) {
1536
- subscriber = fn;
1537
- }
1538
- };
1539
- const cache = (fn) => {
1540
- if (!cacheOptions) {
1541
- cacheOptions = isFunction(fn) ? fn() : fn;
1542
- }
1543
- };
1544
- // The proxy function simply marks the node as a proxy with this function
1545
- // so that child nodes will be created with this function, and then simply
1546
- // activated as a function
1547
- const proxy = (fn) => {
1548
- node.proxyFn2 = fn;
1549
- };
1550
- let prevTarget$;
1551
- let curTarget$;
1552
- const activator = (isFunction(node) ? node : lazyFn);
1553
1715
  let wasPromise;
1554
- let isInitial = true;
1716
+ const activateFn = (isFunction(node) ? node : lazyFn);
1717
+ const doRetry = () => { var _a; return (_a = node.state) === null || _a === void 0 ? void 0 : _a.refreshNum.set((v) => v + 1); };
1718
+ let activatedValue;
1719
+ let disposes = [];
1720
+ let refreshFn;
1721
+ function markDirty() {
1722
+ node.dirtyFn = refreshFn;
1723
+ globalState.dirtyNodes.add(node);
1724
+ }
1555
1725
  observe(() => {
1726
+ var _a, _b, _c, _d;
1727
+ // const params = createNodeActivationParams(node);
1556
1728
  // Run the function at this node
1557
- let value = activator({ onSet, subscribe, proxy, cache, updateLastSync });
1558
- // If target is an observable, get() it to make sure we listen to its changes
1559
- // and set up an onSet to write changes back to it
1729
+ let value = activateFn();
1730
+ // If target is an observable, make this node a link to it
1560
1731
  if (isObservable(value)) {
1561
- prevTarget$ = curTarget$;
1562
- curTarget$ = value;
1563
- onSet(({ value: newValue, getPrevious }) => {
1564
- // Don't set the target observable if the target has changed since the last run
1565
- if (!prevTarget$ || curTarget$ === prevTarget$) {
1566
- // Set the node value back to what it was before before setting it.
1567
- // This is a workaround for linked objects because it might not notify
1568
- // if setting a property of an object
1569
- // TODO: Is there a way to not do this? Or at least only do it in a
1570
- // small subset of cases?
1571
- setNodeValue(getNode(curTarget$), getPrevious());
1572
- // Set the value on the curTarget
1573
- curTarget$.set(newValue);
1574
- }
1575
- });
1576
- // Get the value from the observable because we still want the raw value
1577
- // for the effect.
1578
- value = value.get();
1732
+ value = setToObservable(node, value);
1733
+ }
1734
+ if (isFunction(value)) {
1735
+ value = value();
1736
+ }
1737
+ const activated = value === null || value === void 0 ? void 0 : value[symbolActivated];
1738
+ if (activated) {
1739
+ node.activationState = activated;
1740
+ value = undefined;
1579
1741
  }
1580
- wasPromise = isPromise(value) ? value : undefined;
1742
+ wasPromise = isPromise(value);
1743
+ // Activate this node if not activated already (may be called recursively)
1744
+ // TODO: Is calling recursively bad? If so can it be fixed?
1581
1745
  if (!node.activated) {
1582
1746
  node.activated = true;
1747
+ const isCached = !!((_a = node.activationState) === null || _a === void 0 ? void 0 : _a.cache);
1748
+ wasPromise = wasPromise || !!isCached;
1583
1749
  const activateNodeFn = wasPromise ? globalState.activateNode : activateNodeBase;
1584
- update = activateNodeFn(node, value, setter, subscriber, cacheOptions, lastSync).update;
1585
- }
1586
- if (wasPromise) {
1587
- value = undefined;
1750
+ const { update: newUpdate, value: newValue } = activateNodeFn(node, doRetry, !!wasPromise, value);
1751
+ update = newUpdate;
1752
+ value = newValue !== null && newValue !== void 0 ? newValue : activated === null || activated === void 0 ? void 0 : activated.initial;
1753
+ }
1754
+ else if (node.activationState) {
1755
+ if (!node.activationState.persistedRetry && !node.activationState.waitFor) {
1756
+ const activated = node.activationState;
1757
+ // TODO Should this have lastSync and value somehow?
1758
+ value =
1759
+ (_c = (_b = activated.get) === null || _b === void 0 ? void 0 : _b.call(activated, {
1760
+ updateLastSync: noop,
1761
+ setMode: noop,
1762
+ lastSync: undefined,
1763
+ value: undefined,
1764
+ })) !== null && _c !== void 0 ? _c : activated.initial;
1765
+ }
1588
1766
  }
1767
+ wasPromise = wasPromise || isPromise(value);
1768
+ get(getNode((_d = node.state) === null || _d === void 0 ? void 0 : _d.refreshNum));
1589
1769
  return value;
1590
- }, ({ value }) => {
1591
- if (!globalState.isLoadingRemote$.peek()) {
1770
+ }, (e) => {
1771
+ const { value, nodes, refresh } = e;
1772
+ refreshFn = refresh;
1773
+ if (!wasPromise || !globalState.isLoadingRemote$.peek()) {
1592
1774
  if (wasPromise) {
1593
- wasPromise.then((newValue) => {
1594
- update({ value: newValue });
1595
- node.state.isLoaded.set(true);
1596
- });
1597
- if (isInitial && isFunction(getNodeValue(node))) {
1598
- set(node, value);
1775
+ if (node.activationState) {
1776
+ const { initial } = node.activationState;
1777
+ if (value && isPromise(value)) {
1778
+ // Extract the promise to make it set the value/error when it comes in
1779
+ extractPromise(node, value, update);
1780
+ }
1781
+ // Set this to undefined only if it's replacing the activation function,
1782
+ // so we don't overwrite it if it already has real data from either local
1783
+ // cache or a previous run
1784
+ if (isFunction(getNodeValue(node))) {
1785
+ setNodeValue(node, initial !== null && initial !== void 0 ? initial : undefined);
1786
+ }
1787
+ }
1788
+ else if (node.activated) {
1789
+ // Extract the promise to make it set the value/error when it comes in
1790
+ extractPromise(node, value, update);
1791
+ // Set this to undefined only if it's replacing the activation function,
1792
+ // so we don't overwrite it if it already has real data from either local
1793
+ // cache or a previous run
1794
+ if (isFunction(getNodeValue(node))) {
1795
+ setNodeValue(node, undefined);
1796
+ }
1599
1797
  }
1600
1798
  }
1601
1799
  else {
1800
+ activatedValue = value;
1602
1801
  set(node, value);
1603
- node.state.isLoaded.set(true);
1802
+ node.state.assign({
1803
+ isLoaded: true,
1804
+ error: undefined,
1805
+ });
1604
1806
  }
1605
1807
  }
1606
- isInitial = false;
1607
- }, { immediate: true, fromComputed: true });
1808
+ disposes.forEach((fn) => fn());
1809
+ disposes = [];
1810
+ nodes === null || nodes === void 0 ? void 0 : nodes.forEach(({ node }) => {
1811
+ disposes.push(onChange(node, markDirty, { immediate: true }));
1812
+ });
1813
+ e.cancel = true;
1814
+ }, { fromComputed: true });
1815
+ return activatedValue;
1608
1816
  }
1609
- const activateNodeBase = (globalState.activateNode = function activateNodeBase(node, newValue, setter, subscriber, cacheOptions) {
1610
- let isSetting = false;
1817
+ const activateNodeBase = (globalState.activateNode = function activateNodeBase(node, refresh, wasPromise, value) {
1611
1818
  if (!node.state) {
1612
1819
  node.state = createObservable({
1613
1820
  isLoaded: false,
1614
1821
  }, false, extractPromise, getProxy);
1615
1822
  }
1616
- if (setter) {
1617
- const doSet = (params) => {
1618
- // Don't call the set if this is the first value coming in
1619
- if (!isSetting) {
1620
- if (params.changes.length > 1 || !isFunction(params.changes[0].prevAtPath)) {
1621
- isSetting = true;
1622
- batch(() => setter(params), () => {
1623
- isSetting = false;
1624
- });
1823
+ let isSetting = false;
1824
+ let isSettingFromSubscribe = false;
1825
+ let _mode = 'set';
1826
+ if (node.activationState) {
1827
+ const { onSet, subscribe, get: getFn, initial } = node.activationState;
1828
+ value = getFn
1829
+ ? runWithRetry(node, { attemptNum: 0 }, () => {
1830
+ return getFn({
1831
+ updateLastSync: noop,
1832
+ setMode: (mode) => (_mode = mode),
1833
+ lastSync: undefined,
1834
+ value: undefined,
1835
+ });
1836
+ })
1837
+ : undefined;
1838
+ // TODO Should this have lastSync and value somehow?
1839
+ if (value == undefined || value === null) {
1840
+ value = initial;
1841
+ }
1842
+ if (onSet) {
1843
+ let allChanges = [];
1844
+ let latestValue = undefined;
1845
+ let runNumber = 0;
1846
+ const runChanges = (listenerParams) => {
1847
+ // Don't call the set if this is the first value coming in
1848
+ if (allChanges.length > 0) {
1849
+ let changes;
1850
+ let value;
1851
+ let getPrevious;
1852
+ if (listenerParams) {
1853
+ changes = listenerParams.changes;
1854
+ value = listenerParams.value;
1855
+ getPrevious = listenerParams.getPrevious;
1856
+ }
1857
+ else {
1858
+ // If this is called by flushPending then get the change array
1859
+ // that we've been building up.
1860
+ changes = allChanges;
1861
+ value = latestValue;
1862
+ getPrevious = createPreviousHandler(value, changes);
1863
+ }
1864
+ allChanges = [];
1865
+ latestValue = undefined;
1866
+ globalState.pendingNodes.delete(node);
1867
+ runNumber++;
1868
+ const thisRunNumber = runNumber;
1869
+ const run = () => {
1870
+ if (thisRunNumber !== runNumber) {
1871
+ // set may get called multiple times before it loads so ignore any previous runs
1872
+ return;
1873
+ }
1874
+ return runWithRetry(node, { attemptNum: 0 }, () => {
1875
+ return new Promise((resolve, reject) => {
1876
+ isSetting = true;
1877
+ batch(() => onSet({
1878
+ value,
1879
+ changes,
1880
+ getPrevious,
1881
+ node,
1882
+ update,
1883
+ refresh,
1884
+ onError: reject,
1885
+ fromSubscribe: isSettingFromSubscribe,
1886
+ }), () => {
1887
+ isSetting = false;
1888
+ resolve();
1889
+ });
1890
+ });
1891
+ });
1892
+ };
1893
+ whenReady(node.state.isLoaded, run);
1625
1894
  }
1626
- }
1627
- };
1628
- onChange(node, doSet, { immediate: true });
1629
- }
1630
- if (process.env.NODE_ENV === 'development' && cacheOptions) {
1631
- // TODO Better message
1632
- console.log('[legend-state] Using cacheOption without setting up persistence first');
1895
+ };
1896
+ const onChangeImmediate = ({ value, changes }) => {
1897
+ if (!isSetting || isSettingFromSubscribe) {
1898
+ if (changes.length > 1 || !isFunction(changes[0].prevAtPath)) {
1899
+ latestValue = value;
1900
+ if (allChanges.length > 0) {
1901
+ changes = changes.filter((change) => !isArraySubset(allChanges[0].path, change.path));
1902
+ }
1903
+ allChanges.push(...changes);
1904
+ globalState.pendingNodes.set(node, runChanges);
1905
+ }
1906
+ }
1907
+ };
1908
+ // Create an immediate listener to mark this node as pending. Then actually run
1909
+ // the changes at the end of the batch so everything is properly batched.
1910
+ // However, this can be short circuited if the user calls get() or peek()
1911
+ // in which case the set needs to run immediately so that the values are up to date.
1912
+ onChange(node, onChangeImmediate, { immediate: true });
1913
+ onChange(node, runChanges);
1914
+ }
1915
+ if (process.env.NODE_ENV === 'development' && node.activationState.cache) {
1916
+ // TODO Better message
1917
+ console.log('[legend-state] Using cache without setting up persistence first');
1918
+ }
1919
+ if (process.env.NODE_ENV === 'development' && node.activationState.retry) {
1920
+ // TODO Better message
1921
+ console.log('[legend-state] Using retry without setting up persistence first');
1922
+ }
1923
+ if (subscribe) {
1924
+ const updateFromSubscribe = (params) => {
1925
+ whenReady(node.state.isLoaded, () => {
1926
+ isSettingFromSubscribe = true;
1927
+ update(params);
1928
+ isSettingFromSubscribe = false;
1929
+ });
1930
+ };
1931
+ subscribe({ node, update: updateFromSubscribe, refresh });
1932
+ }
1633
1933
  }
1634
- const update = ({ value }) => {
1934
+ const update = ({ value, mode }) => {
1935
+ // TODO: This isSetting might not be necessary? Tests still work if removing it.
1936
+ // Write tests that would break it if removed? I'd guess a combination of subscribe and
1635
1937
  if (!isSetting) {
1636
- set(node, value);
1938
+ isSetting = true;
1939
+ if (_mode === 'assign' || mode === 'assign') {
1940
+ assign(node, value);
1941
+ }
1942
+ else if (_mode === 'merge' || mode === 'merge') {
1943
+ mergeIntoObservable(getProxy(node), value);
1944
+ }
1945
+ else {
1946
+ set(node, value);
1947
+ }
1948
+ isSetting = false;
1637
1949
  }
1638
1950
  };
1639
- const isProm = isPromise(newValue);
1640
- if (isProm) {
1641
- extractPromise(node, newValue);
1642
- }
1643
- if (subscriber) {
1644
- subscriber({ update });
1645
- }
1646
- return { update };
1951
+ return { update, value };
1647
1952
  });
1953
+ function setToObservable(node, value) {
1954
+ // If the computed is a proxy to another observable
1955
+ // link it to the target observable
1956
+ const linkedNode = getNode(value);
1957
+ if (linkedNode !== node) {
1958
+ const prevNode = node.linkedToNode;
1959
+ node.linkedToNode = linkedNode;
1960
+ if (!linkedNode.linkedFromNodes) {
1961
+ linkedNode.linkedFromNodes = new Set();
1962
+ }
1963
+ linkedNode.linkedFromNodes.add(node);
1964
+ peek(linkedNode);
1965
+ onChange(linkedNode, ({ value: newValue }) => {
1966
+ value = newValue;
1967
+ set(node, value);
1968
+ }, { initial: true });
1969
+ // If the target observable is different then notify for the change
1970
+ if (prevNode) {
1971
+ const value = getNodeValue(linkedNode);
1972
+ const prevValue = getNodeValue(prevNode);
1973
+ notify(node, value, prevValue, 0);
1974
+ }
1975
+ }
1976
+ return value;
1977
+ }
1648
1978
 
1649
1979
  const fns = ['get', 'set', 'peek', 'onChange', 'toggle'];
1650
1980
  function ObservablePrimitiveClass(node) {
@@ -1661,8 +1991,14 @@ function proto(key, fn) {
1661
1991
  return fn.call(this, this._node, ...args);
1662
1992
  };
1663
1993
  }
1664
- proto('peek', peek);
1665
- proto('get', get);
1994
+ proto('peek', (node) => {
1995
+ flushPending();
1996
+ return peek(node);
1997
+ });
1998
+ proto('get', (node, options) => {
1999
+ flushPending();
2000
+ return get(node, options);
2001
+ });
1666
2002
  proto('set', set);
1667
2003
  proto('onChange', onChange);
1668
2004
  // Getters
@@ -1693,6 +2029,16 @@ function observable(value) {
1693
2029
  function observablePrimitive(value) {
1694
2030
  return createObservable(value, true, extractPromise, getProxy, ObservablePrimitiveClass);
1695
2031
  }
2032
+ function syncState(obs) {
2033
+ const node = getNode(obs);
2034
+ if (!node.state) {
2035
+ peek(node);
2036
+ }
2037
+ if (!node.state) {
2038
+ node.state = observable({});
2039
+ }
2040
+ return node.state;
2041
+ }
1696
2042
  globalState.isLoadingRemote$ = observable(false);
1697
2043
 
1698
2044
  function computed(compute, set$1) {
@@ -1857,60 +2203,6 @@ function proxy(get, set) {
1857
2203
  return obs;
1858
2204
  }
1859
2205
 
1860
- function _when(predicate, effect, checkReady) {
1861
- // If predicate is a regular Promise skip all the observable stuff
1862
- if (isPromise(predicate)) {
1863
- return effect ? predicate.then(effect) : predicate;
1864
- }
1865
- let value;
1866
- // Create a wrapping fn that calls the effect if predicate returns true
1867
- function run(e) {
1868
- const ret = computeSelector(predicate);
1869
- if (!isPromise(ret) && (checkReady ? isObservableValueReady(ret) : ret)) {
1870
- value = ret;
1871
- // Set cancel so that observe does not track anymore
1872
- e.cancel = true;
1873
- }
1874
- return value;
1875
- }
1876
- function doEffect() {
1877
- // If value is truthy then run the effect
1878
- effect === null || effect === void 0 ? void 0 : effect(value);
1879
- }
1880
- // Run in an observe
1881
- observe(run, doEffect);
1882
- // If first run resulted in a truthy value just return it.
1883
- // It will have set e.cancel so no need to dispose
1884
- if (isPromise(value)) {
1885
- return effect ? value.then(effect) : value;
1886
- }
1887
- else if (value !== undefined) {
1888
- return Promise.resolve(value);
1889
- }
1890
- else {
1891
- // Wrap it in a promise
1892
- const promise = new Promise((resolve) => {
1893
- if (effect) {
1894
- const originalEffect = effect;
1895
- effect = (value) => {
1896
- const effectValue = originalEffect(value);
1897
- resolve(effectValue);
1898
- };
1899
- }
1900
- else {
1901
- effect = resolve;
1902
- }
1903
- });
1904
- return promise;
1905
- }
1906
- }
1907
- function when(predicate, effect) {
1908
- return _when(predicate, effect, false);
1909
- }
1910
- function whenReady(predicate, effect) {
1911
- return _when(predicate, effect, true);
1912
- }
1913
-
1914
2206
  const internal = {
1915
2207
  ensureNodeValue,
1916
2208
  findIDKey,
@@ -1921,11 +2213,13 @@ const internal = {
1921
2213
  observableFns,
1922
2214
  optimized,
1923
2215
  peek,
2216
+ runWithRetry,
1924
2217
  set,
1925
2218
  setAtPath,
1926
2219
  setNodeValue,
2220
+ symbolActivated,
1927
2221
  symbolDelete,
1928
2222
  };
1929
2223
 
1930
- export { ObservablePrimitiveClass, batch, beginBatch, beginTracking, checkActivate, computeSelector, computed, configureLegendState, constructObjectWithPath, deconstructObjectWithPath, endBatch, endTracking, event, extraPrimitiveActivators, extraPrimitiveProps, findIDKey, getNode, getNodeValue, getObservableIndex, hasOwnProperty, internal, isArray, isBoolean, isEmpty, isFunction, isObject, isObservable, isObservableValueReady, isPrimitive, isPromise, isString, isSymbol, lockObservable, mergeIntoObservable, observable, observablePrimitive, observe, opaqueObject, optimized, proxy, setAtPath, setInObservableAtPath, setSilently, setupTracking, symbolDelete, trackSelector, tracking, updateTracking, when, whenReady };
2224
+ export { ObservablePrimitiveClass, activated, batch, beginBatch, beginTracking, checkActivate, computeSelector, computed, configureLegendState, constructObjectWithPath, deconstructObjectWithPath, endBatch, endTracking, event, extraPrimitiveActivators, extraPrimitiveProps, findIDKey, getNode, getNodeValue, getObservableIndex, hasOwnProperty, internal, isArray, isBoolean, isEmpty, isFunction, isObject, isObservable, isObservableValueReady, isPrimitive, isPromise, isString, isSymbol, lockObservable, mergeIntoObservable, observable, observablePrimitive, observe, opaqueObject, optimized, proxy, setAtPath, setInObservableAtPath, setSilently, setupTracking, symbolDelete, syncState, trackSelector, tracking, updateTracking, when, whenReady };
1931
2225
  //# sourceMappingURL=index.mjs.map