@legendapp/state 2.2.0-next.42 → 2.2.0-next.44

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
@@ -1,4 +1,4 @@
1
- export { synced, activated } from './src/synced';
1
+ export { activated } from './src/activated';
2
2
  export { batch, beginBatch, endBatch } from './src/batching';
3
3
  export { computed } from './src/computed';
4
4
  export { configureLegendState } from './src/config';
@@ -28,7 +28,7 @@ export declare const internal: {
28
28
  isLoadingLocal: boolean;
29
29
  isMerging: boolean;
30
30
  isLoadingRemote$: import("./src/observableTypes").ObservablePrimitive<boolean>;
31
- activateNode: (node: import("./src/observableInterfaces").NodeValue, refresh: () => void, wasPromise: boolean, newValue: any) => {
31
+ activateNodePersist: (node: import("./src/observableInterfaces").NodeValue, newValue: any) => {
32
32
  update: import("./src/observableInterfaces").UpdateFn;
33
33
  value: any;
34
34
  };
@@ -42,6 +42,6 @@ export declare const internal: {
42
42
  set: typeof set;
43
43
  setAtPath: typeof setAtPath;
44
44
  setNodeValue: typeof setNodeValue;
45
- symbolSynced: symbol;
45
+ symbolActivated: symbol;
46
46
  symbolDelete: symbol;
47
47
  };
package/index.js CHANGED
@@ -61,12 +61,12 @@ const symbolGetNode = Symbol('getNode');
61
61
  const symbolDelete = /* @__PURE__ */ Symbol('delete');
62
62
  const symbolOpaque = Symbol('opaque');
63
63
  const optimized = Symbol('optimized');
64
- const symbolSynced = Symbol('synced');
64
+ const symbolActivated = Symbol('activated');
65
65
  const globalState = {
66
66
  isLoadingLocal: false,
67
67
  isMerging: false,
68
68
  isLoadingRemote$: undefined,
69
- activateNode: undefined,
69
+ activateNodePersist: undefined,
70
70
  pendingNodes: new Map(),
71
71
  dirtyNodes: new Set(),
72
72
  };
@@ -91,13 +91,6 @@ function setNodeValue(node, newValue) {
91
91
  const isFunc = isFunction(newValue);
92
92
  // Compute newValue if newValue is a function or an observable
93
93
  newValue = !parentNode.isAssigning && isFunc ? newValue(prevValue) : newValue;
94
- // If setting an observable, set a link to the observable instead
95
- if (isObservable(newValue)) {
96
- const val = newValue;
97
- node.lazy = true;
98
- node.lazyFn = () => val;
99
- newValue = undefined;
100
- }
101
94
  if (!globalState.isMerging ||
102
95
  prevValue === undefined ||
103
96
  isFunction(prevValue) ||
@@ -134,7 +127,7 @@ function getNodeValue(node) {
134
127
  return child;
135
128
  }
136
129
  function getChildNode(node, key, asFunction) {
137
- var _a;
130
+ var _a, _b;
138
131
  // Get the child by key
139
132
  let child = (_a = node.children) === null || _a === void 0 ? void 0 : _a.get(key);
140
133
  // Create the child node if it doesn't already exist
@@ -145,11 +138,9 @@ function getChildNode(node, key, asFunction) {
145
138
  key,
146
139
  lazy: true,
147
140
  };
148
- if (node.activationState) {
149
- const { lookup } = node.activationState;
150
- if (lookup) {
151
- asFunction = lookup.bind(node, key);
152
- }
141
+ // Lookup functions are bound with the child key
142
+ if (((_b = node.lazyFn) === null || _b === void 0 ? void 0 : _b.length) === 1) {
143
+ asFunction = node.lazyFn.bind(node, key);
153
144
  }
154
145
  if (asFunction) {
155
146
  child = Object.assign(() => { }, child);
@@ -164,7 +155,7 @@ function getChildNode(node, key, asFunction) {
164
155
  }
165
156
  function ensureNodeValue(node) {
166
157
  let value = getNodeValue(node);
167
- if (!value) {
158
+ if (!value || isFunction(value)) {
168
159
  if (isChildNodeValue(node)) {
169
160
  const parent = ensureNodeValue(node.parent);
170
161
  value = parent[node.key] = {};
@@ -206,13 +197,11 @@ function extractFunction(node, key, fnOrComputed) {
206
197
  node.functions.set(key, fnOrComputed);
207
198
  }
208
199
 
209
- function synced(params) {
200
+ function activated(params) {
210
201
  return (() => ({
211
- [symbolSynced]: params,
202
+ [symbolActivated]: params,
212
203
  }));
213
204
  }
214
- // TODOV3 Remove this for final release
215
- const activated = synced;
216
205
 
217
206
  let timeout;
218
207
  let numInBatch = 0;
@@ -517,14 +506,6 @@ function opaqueObject(value) {
517
506
  }
518
507
  return value;
519
508
  }
520
- function getValueAtPath(obj, path) {
521
- let o = obj;
522
- for (let i = 0; o && i < path.length; i++) {
523
- const p = path[i];
524
- o = o[p];
525
- }
526
- return o;
527
- }
528
509
  function setAtPath(obj, path, pathTypes, value, fullObj, restore) {
529
510
  let o = obj;
530
511
  let oFull = fullObj;
@@ -668,6 +649,7 @@ function setSilently(obs, newValue) {
668
649
  }
669
650
 
670
651
  function onChange(node, callback, options = {}, fromLinks) {
652
+ var _a;
671
653
  const { initial, immediate, noArgs } = options;
672
654
  const { trackingType } = options;
673
655
  let listeners = immediate ? node.listenersImmediate : node.listeners;
@@ -701,59 +683,36 @@ function onChange(node, callback, options = {}, fromLinks) {
701
683
  getPrevious: () => undefined,
702
684
  });
703
685
  }
704
- // TODO: This is really verbose, refactor it to be less code. But for now at least it's correct.
705
686
  let extraDisposes;
706
- if (node.linkedToNode) {
707
- if (!fromLinks || !fromLinks.has(node.linkedToNode)) {
687
+ function addLinkedNodeListeners(childNode, cb = callback, from) {
688
+ // Don't add listeners for the same node more than once
689
+ if (!(fromLinks === null || fromLinks === void 0 ? void 0 : fromLinks.has(childNode))) {
708
690
  fromLinks || (fromLinks = new Set());
709
- fromLinks.add(node);
710
- fromLinks.add(node.linkedToNode);
711
- extraDisposes = [onChange(node.linkedToNode, callback, options, fromLinks)];
691
+ fromLinks.add(from || node);
692
+ cb || (cb = callback);
693
+ const childOptions = {
694
+ trackingType: true,
695
+ ...options,
696
+ };
697
+ // onChange for the linked node
698
+ extraDisposes = [...(extraDisposes || []), onChange(childNode, cb, childOptions, fromLinks)];
712
699
  }
713
700
  }
714
- // TODO: Need to go up through parents find linked nodes and onChange their nodes at the same path
715
- if (node.linkedFromNodes) {
716
- for (const linkedFromNode of node.linkedFromNodes) {
717
- if (!fromLinks || !fromLinks.has(linkedFromNode)) {
718
- fromLinks || (fromLinks = new Set());
719
- fromLinks.add(node);
720
- fromLinks.add(linkedFromNode);
721
- extraDisposes || (extraDisposes = []);
722
- extraDisposes.push(onChange(linkedFromNode, callback, options, fromLinks));
723
- }
724
- }
701
+ // Add listeners for linked to nodes
702
+ if (node.linkedToNode) {
703
+ addLinkedNodeListeners(node.linkedToNode);
725
704
  }
705
+ // Add listeners for linked from nodes
706
+ (_a = node.linkedFromNodes) === null || _a === void 0 ? void 0 : _a.forEach((linkedFromNode) => addLinkedNodeListeners(linkedFromNode));
707
+ // Go up through the parents and add listeners for linked from nodes
726
708
  let parent = node.parent;
727
709
  let pathParent = [node.key];
728
710
  while (parent) {
729
711
  if (parent.linkedFromNodes) {
730
712
  for (const linkedFromNode of parent.linkedFromNodes) {
731
- if (!fromLinks || !fromLinks.has(linkedFromNode)) {
732
- fromLinks || (fromLinks = new Set());
733
- fromLinks.add(parent);
734
- fromLinks.add(linkedFromNode);
735
- extraDisposes || (extraDisposes = []);
736
- const path = pathParent;
737
- const p = getValueAtPath(getNodeValue(linkedFromNode), path);
738
- const prev = p ? JSON.parse(JSON.stringify(p)) : {};
739
- const cb = ({ value: valueA }) => {
740
- const value = getValueAtPath(valueA, path);
741
- if (value !== prev) {
742
- callback({
743
- value,
744
- changes: [
745
- {
746
- path,
747
- pathTypes: path.map(() => 'object'), // TODO CHANGE
748
- prevAtPath: prev,
749
- valueAtPath: value,
750
- },
751
- ],
752
- getPrevious: () => prev,
753
- });
754
- }
755
- };
756
- extraDisposes.push(onChange(linkedFromNode, cb, { trackingType: true, ...options }, fromLinks));
713
+ if (!(fromLinks === null || fromLinks === void 0 ? void 0 : fromLinks.has(linkedFromNode))) {
714
+ const cb = createCb(linkedFromNode, pathParent, callback);
715
+ addLinkedNodeListeners(linkedFromNode, cb, parent);
757
716
  }
758
717
  }
759
718
  }
@@ -765,6 +724,38 @@ function onChange(node, callback, options = {}, fromLinks) {
765
724
  extraDisposes === null || extraDisposes === void 0 ? void 0 : extraDisposes.forEach((fn) => fn());
766
725
  };
767
726
  }
727
+ function createCb(linkedFromNode, path, callback) {
728
+ // Create a callback for a path that calls it with the current value at the path
729
+ let { valueAtPath: prevAtPath } = getValueAtPath(getNodeValue(linkedFromNode), path);
730
+ return function ({ value: valueA }) {
731
+ const { valueAtPath, pathTypes } = getValueAtPath(valueA, path);
732
+ if (valueAtPath !== prevAtPath) {
733
+ callback({
734
+ value: valueAtPath,
735
+ changes: [
736
+ {
737
+ path,
738
+ pathTypes,
739
+ prevAtPath,
740
+ valueAtPath,
741
+ },
742
+ ],
743
+ getPrevious: () => prevAtPath,
744
+ });
745
+ }
746
+ prevAtPath = valueAtPath;
747
+ };
748
+ }
749
+ function getValueAtPath(obj, path) {
750
+ let o = obj;
751
+ const pathTypes = [];
752
+ for (let i = 0; o && i < path.length; i++) {
753
+ pathTypes.push(isArray(o) ? 'array' : 'object');
754
+ const p = path[i];
755
+ o = o[p];
756
+ }
757
+ return { valueAtPath: o, pathTypes };
758
+ }
768
759
 
769
760
  function setupTracking(nodes, update, noArgs, immediate) {
770
761
  let listeners = [];
@@ -973,65 +964,6 @@ function whenReady(predicate, effect) {
973
964
  return _when(predicate, effect, true);
974
965
  }
975
966
 
976
- function calculateRetryDelay(retryOptions, attemptNum) {
977
- const { backoff, delay = 1000, infinite, times = 3, maxDelay = 30000 } = retryOptions;
978
- if (infinite || attemptNum < times) {
979
- const delayTime = Math.min(delay * (backoff === 'constant' ? 1 : 2 ** attemptNum), maxDelay);
980
- return delayTime;
981
- }
982
- return null;
983
- }
984
- function createRetryTimeout(retryOptions, attemptNum, fn) {
985
- const delayTime = calculateRetryDelay(retryOptions, attemptNum);
986
- if (delayTime) {
987
- return setTimeout(fn, delayTime);
988
- }
989
- }
990
- function runWithRetry(node, state, fn) {
991
- const { retry, waitFor } = node.activationState;
992
- const e = { cancel: false };
993
- let value = undefined;
994
- if (waitFor) {
995
- value = whenReady(waitFor, () => {
996
- node.activationState.waitFor = undefined;
997
- return fn(e);
998
- });
999
- }
1000
- else {
1001
- value = fn(e);
1002
- }
1003
- if (isPromise(value) && retry) {
1004
- let timeoutRetry;
1005
- return new Promise((resolve) => {
1006
- const run = () => {
1007
- value
1008
- .then((val) => {
1009
- node.activationState.persistedRetry = false;
1010
- resolve(val);
1011
- })
1012
- .catch(() => {
1013
- state.attemptNum++;
1014
- if (timeoutRetry) {
1015
- clearTimeout(timeoutRetry);
1016
- }
1017
- if (!e.cancel) {
1018
- timeoutRetry = createRetryTimeout(retry, state.attemptNum, () => {
1019
- value = fn(e);
1020
- run();
1021
- });
1022
- }
1023
- })
1024
- .finally(() => {
1025
- node.activationState.persistedRetry = false;
1026
- });
1027
- };
1028
- run();
1029
- });
1030
- }
1031
- return value;
1032
- }
1033
-
1034
- const noop = () => { };
1035
967
  const ArrayModifiers = new Set([
1036
968
  'copyWithin',
1037
969
  'fill',
@@ -1734,8 +1666,14 @@ function peek(node) {
1734
1666
  if (lazy) {
1735
1667
  const lazyFn = node.lazyFn;
1736
1668
  delete node.lazy;
1737
- if (isFunction(node) || isFunction(lazyFn)) {
1738
- value = activateNodeFunction(node, lazyFn);
1669
+ if (isFunction(lazyFn)) {
1670
+ if (lazyFn.length === 1) {
1671
+ // This is a lookup function, so return a record object
1672
+ value = {};
1673
+ }
1674
+ else {
1675
+ value = activateNodeFunction(node, lazyFn);
1676
+ }
1739
1677
  }
1740
1678
  }
1741
1679
  if (lazy || node.needsExtract) {
@@ -1750,10 +1688,8 @@ function peek(node) {
1750
1688
  function reactivateNode(node, lazyFn) {
1751
1689
  var _a, _b;
1752
1690
  (_a = node.activatedObserveDispose) === null || _a === void 0 ? void 0 : _a.call(node);
1753
- node.activatedObserveDispose = undefined;
1754
1691
  (_b = node.linkedToNodeDispose) === null || _b === void 0 ? void 0 : _b.call(node);
1755
- node.linkedToNodeDispose = undefined;
1756
- node.linkedToNode = undefined;
1692
+ node.activatedObserveDispose = node.linkedToNodeDispose = node.linkedToNode = undefined;
1757
1693
  node.lazyFn = lazyFn;
1758
1694
  node.lazy = true;
1759
1695
  }
@@ -1764,7 +1700,6 @@ function activateNodeFunction(node, lazyFn) {
1764
1700
  let wasPromise;
1765
1701
  let ignoreThisUpdate;
1766
1702
  const activateFn = lazyFn;
1767
- const doRetry = () => { var _a; return (_a = node.state) === null || _a === void 0 ? void 0 : _a.refreshNum.set((v) => v + 1); };
1768
1703
  let activatedValue;
1769
1704
  let disposes = [];
1770
1705
  let refreshFn;
@@ -1773,7 +1708,7 @@ function activateNodeFunction(node, lazyFn) {
1773
1708
  globalState.dirtyNodes.add(node);
1774
1709
  }
1775
1710
  node.activatedObserveDispose = observe(() => {
1776
- var _a, _b, _c, _d, _e, _f;
1711
+ var _a, _b, _c, _d;
1777
1712
  // const params = createNodeActivationParams(node);
1778
1713
  // Run the function at this node
1779
1714
  let value = activateFn();
@@ -1784,7 +1719,7 @@ function activateNodeFunction(node, lazyFn) {
1784
1719
  if (isFunction(value)) {
1785
1720
  value = value();
1786
1721
  }
1787
- const activated = value === null || value === void 0 ? void 0 : value[symbolSynced];
1722
+ const activated = value === null || value === void 0 ? void 0 : value[symbolActivated];
1788
1723
  if (activated) {
1789
1724
  node.activationState = activated;
1790
1725
  value = undefined;
@@ -1795,29 +1730,25 @@ function activateNodeFunction(node, lazyFn) {
1795
1730
  // TODO: Is calling recursively bad? If so can it be fixed?
1796
1731
  if (!node.activated) {
1797
1732
  node.activated = true;
1798
- const isCached = !!((_a = node.activationState) === null || _a === void 0 ? void 0 : _a.cache);
1799
- wasPromise = wasPromise || !!isCached;
1800
- const activateNodeFn = wasPromise ? globalState.activateNode : activateNodeBase;
1801
- const { update: newUpdate, value: newValue } = activateNodeFn(node, doRetry, !!wasPromise, value);
1733
+ let activateNodeFn = activateNodeBase;
1734
+ // If this is a Synced then run it through persistence instead of base
1735
+ if (activated === null || activated === void 0 ? void 0 : activated.synced) {
1736
+ activateNodeFn = globalState.activateNodePersist;
1737
+ wasPromise = true;
1738
+ }
1739
+ const { update: newUpdate, value: newValue } = activateNodeFn(node, value);
1802
1740
  update = newUpdate;
1803
1741
  value = newValue !== null && newValue !== void 0 ? newValue : activated === null || activated === void 0 ? void 0 : activated.initial;
1804
1742
  }
1805
1743
  else if (node.activationState) {
1806
1744
  if (!node.activationState.persistedRetry && !node.activationState.waitFor) {
1807
1745
  const activated = node.activationState;
1808
- if ((_c = (_b = node.state) === null || _b === void 0 ? void 0 : _b.peek()) === null || _c === void 0 ? void 0 : _c.sync) {
1746
+ if ((_b = (_a = node.state) === null || _a === void 0 ? void 0 : _a.peek()) === null || _b === void 0 ? void 0 : _b.sync) {
1809
1747
  node.state.sync();
1810
1748
  ignoreThisUpdate = true;
1811
1749
  }
1812
1750
  else {
1813
- value =
1814
- (_e = (_d = activated.get) === null || _d === void 0 ? void 0 : _d.call(activated, {
1815
- updateLastSync: noop,
1816
- setMode: noop,
1817
- lastSync: undefined,
1818
- value: undefined,
1819
- refresh: doRetry,
1820
- })) !== null && _e !== void 0 ? _e : activated.initial;
1751
+ value = (_d = (_c = activated.get) === null || _c === void 0 ? void 0 : _c.call(activated)) !== null && _d !== void 0 ? _d : activated.initial;
1821
1752
  }
1822
1753
  }
1823
1754
  else {
@@ -1826,7 +1757,6 @@ function activateNodeFunction(node, lazyFn) {
1826
1757
  }
1827
1758
  // value is undefined if it's in a persisted retry
1828
1759
  wasPromise = wasPromise || isPromise(value);
1829
- get(getNode((_f = node.state) === null || _f === void 0 ? void 0 : _f.refreshNum));
1830
1760
  return value;
1831
1761
  }, (e) => {
1832
1762
  if (!ignoreThisUpdate) {
@@ -1882,29 +1812,16 @@ function activateNodeFunction(node, lazyFn) {
1882
1812
  }, { fromComputed: true });
1883
1813
  return activatedValue;
1884
1814
  }
1885
- const activateNodeBase = (globalState.activateNode = function activateNodeBase(node, refresh, wasPromise, value) {
1815
+ function activateNodeBase(node, value) {
1886
1816
  if (!node.state) {
1887
1817
  node.state = createObservable({
1888
1818
  isLoaded: false,
1889
1819
  }, false, extractPromise, getProxy);
1890
1820
  }
1891
1821
  let isSetting = false;
1892
- let isSettingFromSubscribe = false;
1893
- let _mode = 'set';
1894
1822
  if (node.activationState) {
1895
- const { onSet, subscribe, get: getFn, initial } = node.activationState;
1896
- value = getFn
1897
- ? runWithRetry(node, { attemptNum: 0 }, () => {
1898
- return getFn({
1899
- updateLastSync: noop,
1900
- setMode: (mode) => (_mode = mode),
1901
- lastSync: undefined,
1902
- value: undefined,
1903
- refresh,
1904
- });
1905
- })
1906
- : undefined;
1907
- // TODO Should this have lastSync and value somehow?
1823
+ const { onSet, get: getFn, initial } = node.activationState;
1824
+ value = getFn === null || getFn === void 0 ? void 0 : getFn();
1908
1825
  if (value == undefined || value === null) {
1909
1826
  value = initial;
1910
1827
  }
@@ -1940,49 +1857,22 @@ const activateNodeBase = (globalState.activateNode = function activateNodeBase(n
1940
1857
  // set may get called multiple times before it loads so ignore any previous runs
1941
1858
  return;
1942
1859
  }
1943
- const retryAttempts = { attemptNum: 0 };
1944
- return runWithRetry(node, retryAttempts, (eventRetry) => {
1945
- const cancelRetry = () => {
1946
- eventRetry.cancel = true;
1947
- };
1948
- return new Promise((resolve, reject) => {
1949
- isSetting = true;
1950
- let isProm = false;
1951
- batch(() => {
1952
- try {
1953
- const val = onSet({
1954
- value,
1955
- changes,
1956
- getPrevious,
1957
- node,
1958
- update,
1959
- refresh,
1960
- retryNum: retryAttempts.attemptNum,
1961
- cancelRetry,
1962
- fromSubscribe: isSettingFromSubscribe,
1963
- });
1964
- isProm = isPromise(val);
1965
- if (isProm) {
1966
- val.then(resolve).catch(reject);
1967
- }
1968
- }
1969
- catch (e) {
1970
- reject(e);
1971
- }
1972
- }, () => {
1973
- if (!isProm) {
1974
- isSetting = false;
1975
- resolve();
1976
- }
1977
- });
1860
+ isSetting = true;
1861
+ batch(() => {
1862
+ onSet({
1863
+ value,
1864
+ changes,
1865
+ getPrevious,
1978
1866
  });
1867
+ }, () => {
1868
+ isSetting = false;
1979
1869
  });
1980
1870
  };
1981
1871
  whenReady(node.state.isLoaded, run);
1982
1872
  }
1983
1873
  };
1984
1874
  const onChangeImmediate = ({ value, changes }) => {
1985
- if (!isSetting || isSettingFromSubscribe) {
1875
+ if (!isSetting) {
1986
1876
  if (changes.length > 1 || !isFunction(changes[0].prevAtPath)) {
1987
1877
  latestValue = value;
1988
1878
  if (allChanges.length > 0) {
@@ -2000,68 +1890,32 @@ const activateNodeBase = (globalState.activateNode = function activateNodeBase(n
2000
1890
  onChange(node, onChangeImmediate, { immediate: true });
2001
1891
  onChange(node, runChanges);
2002
1892
  }
2003
- if (process.env.NODE_ENV === 'development' && node.activationState.cache) {
2004
- // TODO Better message
2005
- console.log('[legend-state] Using cache without setting up persistence first');
2006
- }
2007
- if (process.env.NODE_ENV === 'development' && node.activationState.retry) {
2008
- // TODO Better message
2009
- console.log('[legend-state] Using retry without setting up persistence first');
2010
- }
2011
- if (subscribe) {
2012
- const updateFromSubscribe = (params) => {
2013
- whenReady(node.state.isLoaded, () => {
2014
- isSettingFromSubscribe = true;
2015
- update(params);
2016
- isSettingFromSubscribe = false;
2017
- });
2018
- };
2019
- subscribe({ node, update: updateFromSubscribe, refresh });
2020
- }
2021
1893
  }
2022
- const update = ({ value, mode }) => {
1894
+ const update = ({ value }) => {
2023
1895
  // TODO: This isSetting might not be necessary? Tests still work if removing it.
2024
1896
  // Write tests that would break it if removed? I'd guess a combination of subscribe and
2025
1897
  if (!isSetting) {
2026
1898
  isSetting = true;
2027
- if (_mode === 'assign' || mode === 'assign') {
2028
- assign(node, value);
2029
- }
2030
- else if (_mode === 'merge' || mode === 'merge') {
2031
- mergeIntoObservable(getProxy(node), value);
2032
- }
2033
- else {
2034
- set(node, value);
2035
- }
1899
+ set(node, value);
2036
1900
  isSetting = false;
2037
1901
  }
2038
1902
  };
2039
1903
  return { update, value };
2040
- });
1904
+ }
2041
1905
  function setToObservable(node, value) {
2042
1906
  var _a;
2043
1907
  // If the computed is a proxy to another observable
2044
1908
  // link it to the target observable
2045
1909
  const linkedNode = getNode(value);
2046
1910
  if (linkedNode !== node && (linkedNode === null || linkedNode === void 0 ? void 0 : linkedNode.linkedToNode) !== node) {
2047
- const prevNode = node.linkedToNode;
2048
1911
  node.linkedToNode = linkedNode;
2049
- if (!linkedNode.linkedFromNodes) {
2050
- linkedNode.linkedFromNodes = new Set();
2051
- }
1912
+ linkedNode.linkedFromNodes || (linkedNode.linkedFromNodes = new Set());
2052
1913
  linkedNode.linkedFromNodes.add(node);
2053
- peek(linkedNode);
2054
1914
  (_a = node.linkedToNodeDispose) === null || _a === void 0 ? void 0 : _a.call(node);
2055
1915
  node.linkedToNodeDispose = onChange(linkedNode, () => {
2056
1916
  value = peek(linkedNode);
2057
1917
  set(node, value);
2058
1918
  }, { initial: true }, new Set([node]));
2059
- // If the target observable is different then notify for the change
2060
- if (prevNode) {
2061
- const value = getNodeValue(linkedNode);
2062
- const prevValue = getNodeValue(prevNode);
2063
- notify(node, value, prevValue, 0);
2064
- }
2065
1919
  }
2066
1920
  return value;
2067
1921
  }
@@ -2133,7 +1987,7 @@ globalState.isLoadingRemote$ = observable(false);
2133
1987
 
2134
1988
  function computed(compute, set) {
2135
1989
  return observable(set
2136
- ? synced({
1990
+ ? activated({
2137
1991
  get: compute,
2138
1992
  onSet: ({ value }) => set(value),
2139
1993
  })
@@ -2191,14 +2045,70 @@ function event() {
2191
2045
  }
2192
2046
 
2193
2047
  function proxy(get, set) {
2194
- return observable(synced({
2195
- lookup: (key) => set
2196
- ? synced({
2197
- get: () => get(key),
2198
- onSet: ({ value }) => set(key, value),
2199
- })
2200
- : get(key),
2201
- }));
2048
+ return observable((key) => set
2049
+ ? activated({
2050
+ get: () => get(key),
2051
+ onSet: ({ value }) => set(key, value),
2052
+ })
2053
+ : get(key));
2054
+ }
2055
+
2056
+ function calculateRetryDelay(retryOptions, attemptNum) {
2057
+ const { backoff, delay = 1000, infinite, times = 3, maxDelay = 30000 } = retryOptions;
2058
+ if (infinite || attemptNum < times) {
2059
+ const delayTime = Math.min(delay * (backoff === 'constant' ? 1 : 2 ** attemptNum), maxDelay);
2060
+ return delayTime;
2061
+ }
2062
+ return null;
2063
+ }
2064
+ function createRetryTimeout(retryOptions, attemptNum, fn) {
2065
+ const delayTime = calculateRetryDelay(retryOptions, attemptNum);
2066
+ if (delayTime) {
2067
+ return setTimeout(fn, delayTime);
2068
+ }
2069
+ }
2070
+ function runWithRetry(node, state, fn) {
2071
+ const { retry, waitFor } = node.activationState;
2072
+ const e = { cancel: false };
2073
+ let value = undefined;
2074
+ if (waitFor) {
2075
+ value = whenReady(waitFor, () => {
2076
+ node.activationState.waitFor = undefined;
2077
+ return fn(e);
2078
+ });
2079
+ }
2080
+ else {
2081
+ value = fn(e);
2082
+ }
2083
+ if (isPromise(value) && retry) {
2084
+ let timeoutRetry;
2085
+ return new Promise((resolve) => {
2086
+ const run = () => {
2087
+ value
2088
+ .then((val) => {
2089
+ node.activationState.persistedRetry = false;
2090
+ resolve(val);
2091
+ })
2092
+ .catch(() => {
2093
+ state.attemptNum++;
2094
+ if (timeoutRetry) {
2095
+ clearTimeout(timeoutRetry);
2096
+ }
2097
+ if (!e.cancel) {
2098
+ timeoutRetry = createRetryTimeout(retry, state.attemptNum, () => {
2099
+ value = fn(e);
2100
+ run();
2101
+ });
2102
+ }
2103
+ })
2104
+ .finally(() => {
2105
+ node.activationState.persistedRetry = false;
2106
+ });
2107
+ };
2108
+ run();
2109
+ });
2110
+ }
2111
+ return value;
2202
2112
  }
2203
2113
 
2204
2114
  const internal = {
@@ -2215,7 +2125,7 @@ const internal = {
2215
2125
  set,
2216
2126
  setAtPath,
2217
2127
  setNodeValue,
2218
- symbolSynced,
2128
+ symbolActivated,
2219
2129
  symbolDelete,
2220
2130
  };
2221
2131
 
@@ -2264,7 +2174,6 @@ exports.setSilently = setSilently;
2264
2174
  exports.setupTracking = setupTracking;
2265
2175
  exports.symbolDelete = symbolDelete;
2266
2176
  exports.syncState = syncState;
2267
- exports.synced = synced;
2268
2177
  exports.trackSelector = trackSelector;
2269
2178
  exports.tracking = tracking;
2270
2179
  exports.updateTracking = updateTracking;