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

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