@legendapp/state 2.2.0-next.19 → 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.
package/index.d.ts CHANGED
@@ -3,21 +3,21 @@ export { batch, beginBatch, endBatch } from './src/batching';
3
3
  export { computed } from './src/computed';
4
4
  export { configureLegendState } from './src/config';
5
5
  export { event } from './src/event';
6
- export { computeSelector, constructObjectWithPath, deconstructObjectWithPath, getObservableIndex, isObservableValueReady, lockObservable, mergeIntoObservable, opaqueObject, setAtPath, setInObservableAtPath, setSilently, } from './src/helpers';
7
6
  export { isObservable } from './src/globals';
7
+ export { computeSelector, constructObjectWithPath, deconstructObjectWithPath, getObservableIndex, isObservableValueReady, lockObservable, mergeIntoObservable, opaqueObject, setAtPath, setInObservableAtPath, setSilently, } from './src/helpers';
8
8
  export { hasOwnProperty, isArray, isBoolean, isEmpty, isFunction, isObject, isPrimitive, isPromise, isString, isSymbol, } from './src/is';
9
9
  export { observable, observablePrimitive, syncState } from './src/observable';
10
10
  export * from './src/observableInterfaces';
11
- export * from './src/persistTypes';
11
+ export * from './src/observableTypes';
12
12
  export { observe } from './src/observe';
13
+ export * from './src/persistTypes';
13
14
  export { proxy } from './src/proxy';
14
15
  export { trackSelector } from './src/trackSelector';
15
16
  export { when, whenReady } from './src/when';
16
- export * from './src/observableTypes';
17
17
  import { get, getProxy, peek, set } from './src/ObservableObject';
18
18
  import { ensureNodeValue, findIDKey, getNode, setNodeValue } from './src/globals';
19
19
  import { setAtPath } from './src/helpers';
20
- import { setupRetry } from './src/retry';
20
+ import { runWithRetry } from './src/retry';
21
21
  export declare const internal: {
22
22
  ensureNodeValue: typeof ensureNodeValue;
23
23
  findIDKey: typeof findIDKey;
@@ -38,10 +38,10 @@ export declare const internal: {
38
38
  observableFns: Map<string, (node: import("./src/observableInterfaces").NodeValue, ...args: any[]) => any>;
39
39
  optimized: symbol;
40
40
  peek: typeof peek;
41
+ runWithRetry: typeof runWithRetry;
41
42
  set: typeof set;
42
43
  setAtPath: typeof setAtPath;
43
44
  setNodeValue: typeof setNodeValue;
44
- setupRetry: typeof setupRetry;
45
45
  symbolActivated: symbol;
46
46
  symbolDelete: symbol;
47
47
  };
package/index.js CHANGED
@@ -483,6 +483,30 @@ function endBatch(force) {
483
483
  }
484
484
  }
485
485
 
486
+ function createObservable(value, makePrimitive, extractPromise, createObject, createPrimitive) {
487
+ const valueIsPromise = isPromise(value);
488
+ const valueIsFunction = isFunction(value);
489
+ const root = {
490
+ _: value,
491
+ };
492
+ let node = {
493
+ root,
494
+ lazy: true,
495
+ };
496
+ if (valueIsFunction) {
497
+ node = Object.assign(cloneFunction(value), node);
498
+ }
499
+ const prim = makePrimitive || isActualPrimitive(value);
500
+ const obs = prim
501
+ ? new createPrimitive(node)
502
+ : createObject(node);
503
+ if (valueIsPromise) {
504
+ setNodeValue(node, undefined);
505
+ extractPromise(node, value);
506
+ }
507
+ return obs;
508
+ }
509
+
486
510
  function isEvent(obs) {
487
511
  var _a;
488
512
  return obs && ((_a = obs[symbolGetNode]) === null || _a === void 0 ? void 0 : _a.isEvent);
@@ -654,30 +678,6 @@ function setSilently(obs, newValue) {
654
678
  return setNodeValue(node, newValue).newValue;
655
679
  }
656
680
 
657
- function createObservable(value, makePrimitive, extractPromise, createObject, createPrimitive) {
658
- const valueIsPromise = isPromise(value);
659
- const valueIsFunction = isFunction(value);
660
- const root = {
661
- _: value,
662
- };
663
- let node = {
664
- root,
665
- lazy: true,
666
- };
667
- if (valueIsFunction) {
668
- node = Object.assign(cloneFunction(value), node);
669
- }
670
- const prim = makePrimitive || isActualPrimitive(value);
671
- const obs = prim
672
- ? new createPrimitive(node)
673
- : createObject(node);
674
- if (valueIsPromise) {
675
- setNodeValue(node, undefined);
676
- extractPromise(node, value);
677
- }
678
- return obs;
679
- }
680
-
681
681
  function onChange(node, callback, options = {}) {
682
682
  const { initial, immediate, noArgs } = options;
683
683
  const { trackingType } = options;
@@ -868,41 +868,6 @@ function observe(selectorOrRun, reactionOrOptions, options) {
868
868
  };
869
869
  }
870
870
 
871
- function setupRetry(retryOptions, refresh, attemptNum) {
872
- const timeout = {};
873
- // let didGiveUp = false;
874
- const { backoff, delay = 1000, infinite, times = 3, maxDelay = 30000 } = retryOptions;
875
- let handleError;
876
- attemptNum.current++;
877
- if (infinite || attemptNum.current < times) {
878
- const delayTime = Math.min(delay * (backoff === 'constant' ? 1 : 2 ** attemptNum.current), maxDelay);
879
- handleError = () => {
880
- timeout.current = setTimeout(refresh, delayTime);
881
- };
882
- }
883
- else {
884
- handleError = () => {
885
- // didGiveUp = true;
886
- };
887
- }
888
- // TODO: Make an easy way to opt into this if
889
- // if (typeof window !== 'undefined') {
890
- // window.addEventListener('online', () => {
891
- // if (didGiveUp || timeout) {
892
- // if (timeout) {
893
- // clearTimeout(timeout.current);
894
- // timeout.current = undefined;
895
- // }
896
- // // Restart the backoff when coming back online
897
- // attemptNum.current = 0;
898
- // didGiveUp = false;
899
- // refresh();
900
- // }
901
- // });
902
- // }
903
- return { handleError, timeout };
904
- }
905
-
906
871
  function _when(predicate, effect, checkReady) {
907
872
  // If predicate is a regular Promise skip all the observable stuff
908
873
  if (isPromise(predicate)) {
@@ -958,6 +923,59 @@ function whenReady(predicate, effect) {
958
923
  return _when(predicate, effect, true);
959
924
  }
960
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
+
961
979
  const noop = () => { };
962
980
  const ArrayModifiers = new Set([
963
981
  'copyWithin',
@@ -1610,7 +1628,7 @@ function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRo
1610
1628
  }
1611
1629
  endBatch();
1612
1630
  }
1613
- function extractPromise(node, value, setter, handleError) {
1631
+ function extractPromise(node, value, setter) {
1614
1632
  if (!node.state) {
1615
1633
  node.state = createObservable({
1616
1634
  isLoaded: false,
@@ -1626,9 +1644,6 @@ function extractPromise(node, value, setter, handleError) {
1626
1644
  })
1627
1645
  .catch((error) => {
1628
1646
  node.state.error.set(error);
1629
- if (handleError) {
1630
- handleError(error);
1631
- }
1632
1647
  });
1633
1648
  }
1634
1649
  function extractFunctionOrComputed(node, obj, k, v) {
@@ -1700,8 +1715,6 @@ function activateNodeFunction(node, lazyFn) {
1700
1715
  // let curTarget$: Observable<any>;
1701
1716
  let update;
1702
1717
  let wasPromise;
1703
- let timeoutRetry;
1704
- const attemptNum = { current: 0 };
1705
1718
  const activateFn = (isFunction(node) ? node : lazyFn);
1706
1719
  const doRetry = () => { var _a; return (_a = node.state) === null || _a === void 0 ? void 0 : _a.refreshNum.set((v) => v + 1); };
1707
1720
  let activatedValue;
@@ -1762,20 +1775,10 @@ function activateNodeFunction(node, lazyFn) {
1762
1775
  if (!wasPromise || !globalState.isLoadingRemote$.peek()) {
1763
1776
  if (wasPromise) {
1764
1777
  if (node.activationState) {
1765
- const { retry, initial } = node.activationState;
1766
- let onError;
1767
- if (retry) {
1768
- if (timeoutRetry === null || timeoutRetry === void 0 ? void 0 : timeoutRetry.current) {
1769
- clearTimeout(timeoutRetry.current);
1770
- }
1771
- const { handleError, timeout } = setupRetry(retry, doRetry, attemptNum);
1772
- onError = handleError;
1773
- timeoutRetry = timeout;
1774
- node.activationState.onError = onError;
1775
- }
1778
+ const { initial } = node.activationState;
1776
1779
  if (value && isPromise(value)) {
1777
1780
  // Extract the promise to make it set the value/error when it comes in
1778
- extractPromise(node, value, update, onError);
1781
+ extractPromise(node, value, update);
1779
1782
  }
1780
1783
  // Set this to undefined only if it's replacing the activation function,
1781
1784
  // so we don't overwrite it if it already has real data from either local
@@ -1785,9 +1788,8 @@ function activateNodeFunction(node, lazyFn) {
1785
1788
  }
1786
1789
  }
1787
1790
  else if (node.activated) {
1788
- let onError;
1789
1791
  // Extract the promise to make it set the value/error when it comes in
1790
- extractPromise(node, value, update, onError);
1792
+ extractPromise(node, value, update);
1791
1793
  // Set this to undefined only if it's replacing the activation function,
1792
1794
  // so we don't overwrite it if it already has real data from either local
1793
1795
  // cache or a previous run
@@ -1824,23 +1826,21 @@ const activateNodeBase = (globalState.activateNode = function activateNodeBase(n
1824
1826
  let isSettingFromSubscribe = false;
1825
1827
  let _mode = 'set';
1826
1828
  if (node.activationState) {
1827
- const { onSet, subscribe, get: getFn, initial, retry, waitFor } = node.activationState;
1828
- // TODO Should this have lastSync and value somehow?
1829
- const run = () => getFn({ updateLastSync: noop, setMode: (mode) => (_mode = mode), lastSync: undefined, value: undefined });
1829
+ const { onSet, subscribe, get: getFn, initial } = node.activationState;
1830
1830
  value = getFn
1831
- ? waitFor
1832
- ? new Promise((resolve) => {
1833
- whenReady(waitFor, () => {
1834
- delete node.activationState.waitFor;
1835
- resolve(run());
1836
- });
1837
- })
1838
- : run()
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
1839
  : undefined;
1840
+ // TODO Should this have lastSync and value somehow?
1840
1841
  if (value == undefined || value === null) {
1841
1842
  value = initial;
1842
1843
  }
1843
- let timeoutRetry;
1844
1844
  if (onSet) {
1845
1845
  let allChanges = [];
1846
1846
  let latestValue = undefined;
@@ -1868,33 +1868,28 @@ const activateNodeBase = (globalState.activateNode = function activateNodeBase(n
1868
1868
  globalState.pendingNodes.delete(node);
1869
1869
  runNumber++;
1870
1870
  const thisRunNumber = runNumber;
1871
- const attemptNum = { current: 0 };
1872
1871
  const run = () => {
1873
1872
  if (thisRunNumber !== runNumber) {
1874
1873
  // set may get called multiple times before it loads so ignore any previous runs
1875
1874
  return;
1876
1875
  }
1877
- let onError;
1878
- if (retry) {
1879
- if (timeoutRetry === null || timeoutRetry === void 0 ? void 0 : timeoutRetry.current) {
1880
- clearTimeout(timeoutRetry.current);
1881
- }
1882
- const { handleError, timeout } = setupRetry(retry, run, attemptNum);
1883
- onError = handleError;
1884
- timeoutRetry = timeout;
1885
- }
1886
- isSetting = true;
1887
- batch(() => onSet({
1888
- value,
1889
- changes,
1890
- getPrevious,
1891
- node,
1892
- update,
1893
- refresh,
1894
- onError,
1895
- fromSubscribe: isSettingFromSubscribe,
1896
- }), () => {
1897
- isSetting = false;
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
+ });
1898
1893
  });
1899
1894
  };
1900
1895
  whenReady(node.state.isLoaded, run);
@@ -2220,10 +2215,10 @@ const internal = {
2220
2215
  observableFns,
2221
2216
  optimized,
2222
2217
  peek,
2218
+ runWithRetry,
2223
2219
  set,
2224
2220
  setAtPath,
2225
2221
  setNodeValue,
2226
- setupRetry,
2227
2222
  symbolActivated,
2228
2223
  symbolDelete,
2229
2224
  };