@legendapp/state 3.0.0-alpha.2 → 3.0.0-alpha.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 (54) hide show
  1. package/CHANGELOG.md +831 -1
  2. package/LICENSE +21 -1
  3. package/README.md +141 -1
  4. package/babel.js +0 -2
  5. package/babel.mjs +0 -2
  6. package/helpers/trackHistory.js +2 -2
  7. package/helpers/trackHistory.mjs +2 -2
  8. package/index.d.mts +45 -32
  9. package/index.d.ts +45 -32
  10. package/index.js +234 -156
  11. package/index.mjs +234 -156
  12. package/package.json +6 -1
  13. package/persist-plugins/async-storage.d.mts +2 -2
  14. package/persist-plugins/async-storage.d.ts +2 -2
  15. package/persist-plugins/indexeddb.js +1 -1
  16. package/persist-plugins/indexeddb.mjs +1 -1
  17. package/react.d.mts +17 -14
  18. package/react.d.ts +17 -14
  19. package/react.js +55 -30
  20. package/react.mjs +56 -31
  21. package/sync-plugins/_transformObjectFields.d.mts +31 -0
  22. package/sync-plugins/_transformObjectFields.d.ts +31 -0
  23. package/sync-plugins/_transformObjectFields.js +114 -0
  24. package/sync-plugins/_transformObjectFields.mjs +110 -0
  25. package/sync-plugins/crud.d.mts +14 -23
  26. package/sync-plugins/crud.d.ts +14 -23
  27. package/sync-plugins/crud.js +194 -129
  28. package/sync-plugins/crud.mjs +195 -130
  29. package/sync-plugins/firebase.d.mts +26 -0
  30. package/sync-plugins/firebase.d.ts +26 -0
  31. package/sync-plugins/firebase.js +365 -0
  32. package/sync-plugins/firebase.mjs +360 -0
  33. package/sync-plugins/keel.d.mts +24 -8
  34. package/sync-plugins/keel.d.ts +24 -8
  35. package/sync-plugins/keel.js +32 -16
  36. package/sync-plugins/keel.mjs +32 -16
  37. package/sync-plugins/supabase.d.mts +1 -1
  38. package/sync-plugins/supabase.d.ts +1 -1
  39. package/sync-plugins/supabase.js +5 -4
  40. package/sync-plugins/supabase.mjs +6 -5
  41. package/sync-plugins/tanstack-query.d.mts +2 -2
  42. package/sync-plugins/tanstack-query.d.ts +2 -2
  43. package/sync-plugins/tanstack-query.js +3 -2
  44. package/sync-plugins/tanstack-query.mjs +3 -2
  45. package/sync-plugins/tanstack-react-query.d.mts +1 -1
  46. package/sync-plugins/tanstack-react-query.d.ts +1 -1
  47. package/sync.d.mts +38 -185
  48. package/sync.d.ts +38 -185
  49. package/sync.js +354 -296
  50. package/sync.mjs +356 -297
  51. package/types/babel.d.ts +12 -1
  52. package/.DS_Store +0 -0
  53. /package/config/{enable_GetSet.d.mts → enable$GetSet.d.mts} +0 -0
  54. /package/config/{enable_GetSet.d.ts → enable$GetSet.d.ts} +0 -0
package/index.mjs CHANGED
@@ -31,15 +31,20 @@ function isPromise(obj) {
31
31
  function isMap(obj) {
32
32
  return obj instanceof Map;
33
33
  }
34
+ function isSet(obj) {
35
+ return obj instanceof Set;
36
+ }
34
37
  function isNumber(obj) {
35
38
  const n = obj;
36
- return n - n < 1;
39
+ return typeof n === "number" && n - n < 1;
37
40
  }
38
41
  function isEmpty(obj) {
39
42
  if (!obj)
40
43
  return false;
41
44
  if (isArray(obj))
42
45
  return obj.length === 0;
46
+ if (isMap(obj) || isSet(obj))
47
+ return obj.size === 0;
43
48
  for (const key in obj) {
44
49
  if (hasOwnProperty.call(obj, key)) {
45
50
  return false;
@@ -60,6 +65,7 @@ function isChildNodeValue(node) {
60
65
 
61
66
  // src/globals.ts
62
67
  var symbolToPrimitive = Symbol.toPrimitive;
68
+ var symbolIterator = Symbol.iterator;
63
69
  var symbolGetNode = Symbol("getNode");
64
70
  var symbolDelete = /* @__PURE__ */ Symbol("delete");
65
71
  var symbolOpaque = Symbol("opaque");
@@ -67,7 +73,6 @@ var optimized = Symbol("optimized");
67
73
  var symbolLinked = Symbol("linked");
68
74
  var globalState = {
69
75
  isLoadingLocal: false,
70
- isMerging: false,
71
76
  isLoadingRemote: false,
72
77
  activateSyncedNode: void 0,
73
78
  pendingNodes: /* @__PURE__ */ new Map(),
@@ -75,6 +80,9 @@ var globalState = {
75
80
  replacer: void 0,
76
81
  reviver: void 0
77
82
  };
83
+ function isOpaqueObject(value) {
84
+ return value && (value[symbolOpaque] || value["$$typeof"]);
85
+ }
78
86
  function getPathType(value) {
79
87
  return isArray(value) ? "array" : isMap(value) ? "map" : value instanceof Set ? "set" : "object";
80
88
  }
@@ -116,10 +124,10 @@ function reviver(key, value) {
116
124
  return value;
117
125
  }
118
126
  function safeStringify(value) {
119
- return JSON.stringify(value, replacer);
127
+ return value ? JSON.stringify(value, replacer) : value;
120
128
  }
121
129
  function safeParse(value) {
122
- return JSON.parse(value, reviver);
130
+ return value ? JSON.parse(value, reviver) : value;
123
131
  }
124
132
  function clone(value) {
125
133
  return safeParse(safeStringify(value));
@@ -135,7 +143,7 @@ function isEvent(value$) {
135
143
  return value$ && ((_a = value$[symbolGetNode]) == null ? void 0 : _a.isEvent);
136
144
  }
137
145
  function setNodeValue(node, newValue) {
138
- var _a, _b, _c;
146
+ var _a;
139
147
  const parentNode = (_a = node.parent) != null ? _a : node;
140
148
  const key = node.parent ? node.key : "_";
141
149
  const isDelete = newValue === symbolDelete;
@@ -145,7 +153,7 @@ function setNodeValue(node, newValue) {
145
153
  const prevValue = parentValue[key];
146
154
  const isFunc = isFunction(newValue);
147
155
  newValue = !parentNode.isAssigning && isFunc && !isFunction(prevValue) ? newValue(prevValue) : newValue;
148
- if (!globalState.isMerging || isNullOrUndefined(prevValue) || isFunction(prevValue) || !((_c = (_b = node.parent) == null ? void 0 : _b.functions) == null ? void 0 : _c.get(key))) {
156
+ if (newValue !== prevValue) {
149
157
  try {
150
158
  parentNode.isSetting = (parentNode.isSetting || 0) + 1;
151
159
  const useMapFn = isMap(parentValue);
@@ -283,10 +291,15 @@ function setAtPath(obj, path, pathTypes, value, mode, fullObj, restore) {
283
291
  } else if (o[p] === void 0 && value === void 0 && i === path.length - 1) {
284
292
  return obj;
285
293
  } else if (o[p] === void 0 || o[p] === null) {
286
- o[p] = initializePathType(pathTypes[i]);
294
+ const child = initializePathType(pathTypes[i]);
295
+ if (isMap(o)) {
296
+ o.set(p, child);
297
+ } else {
298
+ o[p] = child;
299
+ }
287
300
  }
288
301
  if (i < path.length - 1) {
289
- o = o[p];
302
+ o = isMap(o) ? o.get(p) : o[p];
290
303
  if (oFull) {
291
304
  oFull = oFull[p];
292
305
  }
@@ -295,13 +308,13 @@ function setAtPath(obj, path, pathTypes, value, mode, fullObj, restore) {
295
308
  }
296
309
  if (p === void 0) {
297
310
  if (mode === "merge") {
298
- obj = _mergeIntoObservable(obj, value);
311
+ obj = deepMerge(obj, value, false, 0);
299
312
  } else {
300
313
  obj = value;
301
314
  }
302
315
  } else {
303
316
  if (mode === "merge") {
304
- o[p] = _mergeIntoObservable(o[p], value);
317
+ o[p] = deepMerge(o[p], value, false, 0);
305
318
  } else if (isMap(o)) {
306
319
  o.set(p, value);
307
320
  } else {
@@ -332,48 +345,58 @@ function setInObservableAtPath(value$, path, pathTypes, value, mode) {
332
345
  }
333
346
  }
334
347
  function mergeIntoObservable(target, ...sources) {
348
+ if (process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") {
349
+ if (!isObservable(target)) {
350
+ console.error("[legend-state] should only use mergeIntoObservable with observables");
351
+ }
352
+ }
335
353
  beginBatch();
336
- globalState.isMerging = true;
337
354
  for (let i = 0; i < sources.length; i++) {
338
- target = _mergeIntoObservable(target, sources[i]);
355
+ _mergeIntoObservable(
356
+ target,
357
+ sources[i],
358
+ /*assign*/
359
+ i < sources.length - 1,
360
+ 0
361
+ );
339
362
  }
340
- globalState.isMerging = false;
341
363
  endBatch();
342
364
  return target;
343
365
  }
344
- function _mergeIntoObservable(target, source) {
345
- var _a;
366
+ function _mergeIntoObservable(target, source, assign2, levelsDeep) {
346
367
  if (isObservable(source)) {
347
368
  source = source.peek();
348
369
  }
349
- const needsSet = isObservable(target);
350
- const targetValue = needsSet ? target.peek() : target;
370
+ const targetValue = target.peek();
351
371
  const isTargetArr = isArray(targetValue);
352
372
  const isTargetObj = !isTargetArr && isObject(targetValue);
353
- if (isTargetObj && isObject(source) && !isEmpty(targetValue) || isTargetArr && targetValue.length > 0) {
354
- const keys = Object.keys(source);
373
+ const isSourceMap = isMap(source);
374
+ const isSourceSet = isSet(source);
375
+ if (isSourceSet && isSet(targetValue)) {
376
+ target.set(/* @__PURE__ */ new Set([...source, ...targetValue]));
377
+ } else if (isTargetObj && isObject(source) && !isEmpty(targetValue) || isTargetArr && targetValue.length > 0) {
378
+ const keys = isSourceMap || isSourceSet ? Array.from(source.keys()) : Object.keys(source);
355
379
  for (let i = 0; i < keys.length; i++) {
356
380
  const key = keys[i];
357
- const sourceValue = source[key];
381
+ const sourceValue = isSourceSet ? key : isSourceMap ? source.get(key) : source[key];
358
382
  if (sourceValue === symbolDelete) {
359
- needsSet && ((_a = target[key]) == null ? void 0 : _a.delete) ? target[key].delete() : delete target[key];
383
+ target[key].delete();
360
384
  } else {
361
385
  const isObj = isObject(sourceValue);
362
386
  const isArr = !isObj && isArray(sourceValue);
363
387
  const targetChild = target[key];
364
- if ((isObj || isArr) && targetChild && (needsSet || !isEmpty(targetChild))) {
365
- if (!needsSet && (!targetChild || (isObj ? !isObject(targetChild) : !isArray(targetChild)))) {
366
- target[key] = sourceValue;
367
- } else {
368
- _mergeIntoObservable(targetChild, sourceValue);
388
+ if ((isObj || isArr) && targetChild) {
389
+ if (levelsDeep > 0 && isEmpty(sourceValue)) {
390
+ targetChild.set(sourceValue);
369
391
  }
392
+ _mergeIntoObservable(targetChild, sourceValue, false, levelsDeep + 1);
370
393
  } else {
371
- needsSet ? targetChild.set(sourceValue) : target[key] = sourceValue;
394
+ targetChild.set(sourceValue);
372
395
  }
373
396
  }
374
397
  }
375
398
  } else if (source !== void 0) {
376
- needsSet ? target.set(source) : target = source;
399
+ target.set(source);
377
400
  }
378
401
  return target;
379
402
  }
@@ -428,6 +451,25 @@ function applyChanges(value, changes, applyPrevious) {
428
451
  }
429
452
  return value;
430
453
  }
454
+ function deepMerge(target, ...sources) {
455
+ const result = { ...target };
456
+ for (let i = 0; i < sources.length; i++) {
457
+ const obj2 = sources[i];
458
+ for (const key in obj2) {
459
+ if (hasOwnProperty.call(obj2, key)) {
460
+ if (obj2[key] instanceof Object && !isObservable(obj2[key]) && Object.keys(obj2[key]).length > 0) {
461
+ result[key] = deepMerge(
462
+ result[key] || (isArray(obj2[key]) ? [] : {}),
463
+ obj2[key]
464
+ );
465
+ } else {
466
+ result[key] = obj2[key];
467
+ }
468
+ }
469
+ }
470
+ }
471
+ return result;
472
+ }
431
473
 
432
474
  // src/batching.ts
433
475
  var timeout;
@@ -487,31 +529,35 @@ function notify(node, value, prev, level, whenOptimizedOnlyIf) {
487
529
  level,
488
530
  whenOptimizedOnlyIf
489
531
  );
490
- if (changesInBatch.size) {
491
- batchNotifyChanges(
492
- changesInBatch,
493
- /*immediate*/
494
- true
495
- );
496
- }
497
532
  const existing = _batchMap.get(node);
498
533
  if (existing) {
499
- existing.value = value;
534
+ if (existing.prev === value) {
535
+ _batchMap.delete(node);
536
+ } else {
537
+ existing.value = value;
538
+ }
500
539
  } else {
501
540
  _batchMap.set(node, {
502
541
  value,
503
542
  prev,
504
543
  level,
505
544
  whenOptimizedOnlyIf,
506
- remote: globalState.isLoadingRemote,
507
- loading: globalState.isLoadingLocal
545
+ isFromSync: globalState.isLoadingRemote,
546
+ isFromPersist: globalState.isLoadingLocal
508
547
  });
509
548
  }
549
+ if (changesInBatch.size) {
550
+ batchNotifyChanges(
551
+ changesInBatch,
552
+ /*immediate*/
553
+ true
554
+ );
555
+ }
510
556
  if (numInBatch <= 0) {
511
557
  runBatch();
512
558
  }
513
559
  }
514
- function computeChangesAtNode(changesInBatch, node, loading, remote, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf) {
560
+ function computeChangesAtNode(changesInBatch, node, isFromPersist, isFromSync, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf) {
515
561
  if (immediate ? node.listenersImmediate : node.listeners) {
516
562
  const change = {
517
563
  path,
@@ -524,13 +570,14 @@ function computeChangesAtNode(changesInBatch, node, loading, remote, value, path
524
570
  const { changes } = changeInBatch;
525
571
  if (!isArraySubset(changes[0].path, change.path)) {
526
572
  changes.push(change);
573
+ changeInBatch.level = Math.min(changeInBatch.level, level);
527
574
  }
528
575
  } else {
529
576
  changesInBatch.set(node, {
530
577
  level,
531
578
  value,
532
- remote,
533
- loading,
579
+ isFromSync,
580
+ isFromPersist,
534
581
  whenOptimizedOnlyIf,
535
582
  changes: [change]
536
583
  });
@@ -594,7 +641,7 @@ function computeChangesRecursive(changesInBatch, node, loading, remote, value, p
594
641
  }
595
642
  function batchNotifyChanges(changesInBatch, immediate) {
596
643
  const listenersNotified = /* @__PURE__ */ new Set();
597
- changesInBatch.forEach(({ changes, level, value, loading, remote, whenOptimizedOnlyIf }, node) => {
644
+ changesInBatch.forEach(({ changes, level, value, isFromPersist, isFromSync, whenOptimizedOnlyIf }, node) => {
598
645
  const listeners = immediate ? node.listenersImmediate : node.listeners;
599
646
  if (listeners) {
600
647
  let listenerParams;
@@ -608,8 +655,8 @@ function batchNotifyChanges(changesInBatch, immediate) {
608
655
  if (!noArgs && !listenerParams) {
609
656
  listenerParams = {
610
657
  value,
611
- loading,
612
- remote,
658
+ isFromPersist,
659
+ isFromSync,
613
660
  getPrevious: createPreviousHandler(value, changes),
614
661
  changes
615
662
  };
@@ -637,12 +684,12 @@ function runBatch() {
637
684
  const map = _batchMap;
638
685
  _batchMap = /* @__PURE__ */ new Map();
639
686
  const changesInBatch = /* @__PURE__ */ new Map();
640
- map.forEach(({ value, prev, level, loading, remote, whenOptimizedOnlyIf }, node) => {
687
+ map.forEach(({ value, prev, level, isFromPersist, isFromSync, whenOptimizedOnlyIf }, node) => {
641
688
  computeChangesRecursive(
642
689
  changesInBatch,
643
690
  node,
644
- loading,
645
- remote,
691
+ isFromPersist,
692
+ isFromSync,
646
693
  value,
647
694
  [],
648
695
  [],
@@ -701,21 +748,6 @@ function getNodeAtPath(obj, path) {
701
748
  return o;
702
749
  }
703
750
 
704
- // src/linked.ts
705
- function linked(params, options) {
706
- if (isFunction(params)) {
707
- params = { get: params };
708
- }
709
- if (options) {
710
- params = { ...params, ...options };
711
- }
712
- const ret = function() {
713
- return { [symbolLinked]: params };
714
- };
715
- ret.prototype[symbolLinked] = params;
716
- return ret;
717
- }
718
-
719
751
  // src/createObservable.ts
720
752
  function createObservable(value, makePrimitive, extractPromise2, createObject, createPrimitive) {
721
753
  if (isObservable(value)) {
@@ -745,6 +777,21 @@ function createObservable(value, makePrimitive, extractPromise2, createObject, c
745
777
  return obs;
746
778
  }
747
779
 
780
+ // src/linked.ts
781
+ function linked(params, options) {
782
+ if (isFunction(params)) {
783
+ params = { get: params };
784
+ }
785
+ if (options) {
786
+ params = { ...params, ...options };
787
+ }
788
+ const ret = function() {
789
+ return { [symbolLinked]: params };
790
+ };
791
+ ret.prototype[symbolLinked] = params;
792
+ return ret;
793
+ }
794
+
748
795
  // src/onChange.ts
749
796
  function onChange(node, callback, options = {}, fromLinks) {
750
797
  var _a;
@@ -769,8 +816,8 @@ function onChange(node, callback, options = {}, fromLinks) {
769
816
  const value = getNodeValue(node);
770
817
  callback({
771
818
  value,
772
- loading: true,
773
- remote: false,
819
+ isFromPersist: true,
820
+ isFromSync: false,
774
821
  changes: [
775
822
  {
776
823
  path: [],
@@ -827,13 +874,13 @@ function onChange(node, callback, options = {}, fromLinks) {
827
874
  }
828
875
  function createCb(linkedFromNode, path, callback) {
829
876
  let { valueAtPath: prevAtPath } = getValueAtPath2(getNodeValue(linkedFromNode), path);
830
- return function({ value: valueA, loading, remote }) {
877
+ return function({ value: valueA, isFromPersist, isFromSync }) {
831
878
  const { valueAtPath } = getValueAtPath2(valueA, path);
832
879
  if (valueAtPath !== prevAtPath) {
833
880
  callback({
834
881
  value: valueAtPath,
835
- loading,
836
- remote,
882
+ isFromPersist,
883
+ isFromSync,
837
884
  changes: [
838
885
  {
839
886
  path: [],
@@ -953,12 +1000,17 @@ function observe(selectorOrRun, reactionOrOptions, options) {
953
1000
  options = reactionOrOptions;
954
1001
  }
955
1002
  let dispose;
1003
+ let isRunning = false;
956
1004
  const e = { num: 0 };
957
1005
  const update = function() {
1006
+ if (isRunning) {
1007
+ return;
1008
+ }
958
1009
  if (e.onCleanup) {
959
1010
  e.onCleanup();
960
1011
  e.onCleanup = void 0;
961
1012
  }
1013
+ isRunning = true;
962
1014
  beginBatch();
963
1015
  delete e.value;
964
1016
  dispose == null ? void 0 : dispose();
@@ -972,6 +1024,7 @@ function observe(selectorOrRun, reactionOrOptions, options) {
972
1024
  e.onCleanupReaction = void 0;
973
1025
  }
974
1026
  endBatch();
1027
+ isRunning = false;
975
1028
  if (reaction && ((options == null ? void 0 : options.fromComputed) || (e.num > 0 || !isEvent(selectorOrRun)) && (e.previous !== e.value || typeof e.value === "object"))) {
976
1029
  reaction(e);
977
1030
  }
@@ -1108,7 +1161,7 @@ function updateNodes(parent, obj, prevValue) {
1108
1161
  }
1109
1162
  __devUpdateNodes.add(obj);
1110
1163
  }
1111
- if (isObject(obj) && obj[symbolOpaque] || isObject(prevValue) && prevValue[symbolOpaque]) {
1164
+ if (isObject(obj) && isOpaqueObject(obj) || isObject(prevValue) && isOpaqueObject(prevValue)) {
1112
1165
  const isDiff = obj !== prevValue;
1113
1166
  if (isDiff) {
1114
1167
  if (parent.listeners || parent.listenersImmediate) {
@@ -1296,10 +1349,10 @@ var proxyHandler = {
1296
1349
  if (p === symbolGetNode) {
1297
1350
  return node;
1298
1351
  }
1299
- if (p === "apply") {
1352
+ if (p === "apply" || p === "call") {
1300
1353
  const nodeValue = getNodeValue(node);
1301
1354
  if (isFunction(nodeValue)) {
1302
- return nodeValue.apply;
1355
+ return nodeValue[p];
1303
1356
  }
1304
1357
  }
1305
1358
  let value = peekInternal(
@@ -1307,6 +1360,9 @@ var proxyHandler = {
1307
1360
  /*activateRecursive*/
1308
1361
  p === "get" || p === "peek"
1309
1362
  );
1363
+ if (p === symbolIterator) {
1364
+ return !value || isPrimitive(value) ? void 0 : value[p];
1365
+ }
1310
1366
  const targetNode = node.linkedToNode || (value == null ? void 0 : value[symbolGetNode]);
1311
1367
  if (targetNode && p !== "onChange") {
1312
1368
  return proxyHandler.get(targetNode, p, receiver);
@@ -1341,7 +1397,7 @@ var proxyHandler = {
1341
1397
  return property.get(node);
1342
1398
  }
1343
1399
  let vProp = value == null ? void 0 : value[p];
1344
- if (isObject(value) && value[symbolOpaque]) {
1400
+ if (isObject(value) && isOpaqueObject(value)) {
1345
1401
  return vProp;
1346
1402
  }
1347
1403
  const fnOrComputed = (_a = node.functions) == null ? void 0 : _a.get(p);
@@ -1507,11 +1563,17 @@ function setKey(node, key, newValue, level) {
1507
1563
  } else {
1508
1564
  const { newValue: savedValue, prevValue } = setNodeValue(childNode, newValue);
1509
1565
  const isPrim = isPrimitive(savedValue) || savedValue instanceof Date;
1510
- if (!equals(savedValue, prevValue)) {
1511
- updateNodesAndNotify(node, savedValue, prevValue, childNode, isPrim, isRoot, level);
1512
- }
1513
1566
  if (!isPrim) {
1514
- childNode.needsExtract = true;
1567
+ let parent = childNode;
1568
+ do {
1569
+ parent.needsExtract = true;
1570
+ parent.recursivelyAutoActivated = false;
1571
+ } while (parent = parent.parent);
1572
+ }
1573
+ const notify2 = !equals(savedValue, prevValue);
1574
+ const forceNotify = !notify2 && childNode.isComputing && !isPrim;
1575
+ if (notify2 || forceNotify) {
1576
+ updateNodesAndNotify(node, savedValue, prevValue, childNode, isPrim, isRoot, level, forceNotify);
1515
1577
  }
1516
1578
  extractFunctionOrComputed(node, key, savedValue);
1517
1579
  }
@@ -1526,6 +1588,8 @@ function assign(node, value) {
1526
1588
  const currentValue = getNodeValue(node);
1527
1589
  if (isMap(currentValue)) {
1528
1590
  value.forEach((value2, key) => currentValue.set(key, value2));
1591
+ } else {
1592
+ set(node, value);
1529
1593
  }
1530
1594
  } else {
1531
1595
  node.isAssigning = (node.isAssigning || 0) + 1;
@@ -1622,20 +1686,20 @@ function handlerMapSet(node, p, value) {
1622
1686
  };
1623
1687
  }
1624
1688
  }
1625
- function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRoot, level) {
1689
+ function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRoot, level, forceNotify) {
1626
1690
  if (!childNode)
1627
1691
  childNode = node;
1628
1692
  beginBatch();
1629
1693
  if (isPrim === void 0) {
1630
1694
  isPrim = isPrimitive(newValue);
1631
1695
  }
1632
- let hasADiff = isPrim;
1696
+ let hasADiff = forceNotify || isPrim;
1633
1697
  let whenOptimizedOnlyIf = false;
1634
1698
  if (!isPrim || prevValue && !isPrimitive(prevValue)) {
1635
1699
  if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && typeof __devUpdateNodes !== "undefined") {
1636
1700
  __devUpdateNodes.clear();
1637
1701
  }
1638
- hasADiff = updateNodes(childNode, newValue, prevValue);
1702
+ hasADiff = hasADiff || updateNodes(childNode, newValue, prevValue);
1639
1703
  if (isArray(newValue)) {
1640
1704
  whenOptimizedOnlyIf = (newValue == null ? void 0 : newValue.length) !== (prevValue == null ? void 0 : prevValue.length);
1641
1705
  }
@@ -1652,6 +1716,7 @@ function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRo
1652
1716
  endBatch();
1653
1717
  }
1654
1718
  function extractPromise(node, value, setter) {
1719
+ const numGets = node.numGets = (node.numGets || 0) + 1;
1655
1720
  if (!node.state) {
1656
1721
  node.state = createObservable(
1657
1722
  {
@@ -1663,11 +1728,14 @@ function extractPromise(node, value, setter) {
1663
1728
  );
1664
1729
  }
1665
1730
  value.then((value2) => {
1666
- setter ? setter({ value: value2 }) : set(node, value2);
1667
- node.state.assign({
1668
- isLoaded: true,
1669
- error: void 0
1670
- });
1731
+ if (numGets >= (node.getNumResolved || 0)) {
1732
+ node.getNumResolved = node.numGets;
1733
+ setter ? setter({ value: value2 }) : set(node, value2);
1734
+ node.state.assign({
1735
+ isLoaded: true,
1736
+ error: void 0
1737
+ });
1738
+ }
1671
1739
  }).catch((error) => {
1672
1740
  node.state.error.set(error);
1673
1741
  });
@@ -1684,6 +1752,7 @@ function extractFunctionOrComputed(node, k, v) {
1684
1752
  const childNode = getChildNode(node, k, fn);
1685
1753
  const targetNode = getNode(v);
1686
1754
  const initialValue = peek(targetNode);
1755
+ setToObservable(childNode, v);
1687
1756
  setNodeValue(childNode, initialValue);
1688
1757
  return getNodeValue(childNode);
1689
1758
  } else if (typeof v === "function") {
@@ -1716,7 +1785,9 @@ function peekInternal(node, activateRecursive) {
1716
1785
  }
1717
1786
  isFlushing = false;
1718
1787
  let value = getNodeValue(node);
1719
- value = checkLazy(node, value, !!activateRecursive);
1788
+ if (!globalState.isLoadingLocal) {
1789
+ value = checkLazy(node, value, !!activateRecursive);
1790
+ }
1720
1791
  return value;
1721
1792
  }
1722
1793
  function checkLazy(node, value, activateRecursive) {
@@ -1731,10 +1802,12 @@ function checkLazy(node, value, activateRecursive) {
1731
1802
  } else {
1732
1803
  if (node.parent) {
1733
1804
  const parentValue = getNodeValue(node.parent);
1734
- if (parentValue) {
1735
- delete parentValue[node.key];
1736
- } else {
1737
- node.root._ = void 0;
1805
+ if (isFunction(value)) {
1806
+ if (parentValue) {
1807
+ delete parentValue[node.key];
1808
+ } else {
1809
+ node.root._ = void 0;
1810
+ }
1738
1811
  }
1739
1812
  }
1740
1813
  value = activateNodeFunction(node, lazyFn);
@@ -1823,7 +1896,9 @@ function activateNodeFunction(node, lazyFn) {
1823
1896
  var _a, _b, _c, _d;
1824
1897
  if (isFirst) {
1825
1898
  isFirst = false;
1826
- setNodeValue(node, void 0);
1899
+ if (isFunction(getNodeValue(node))) {
1900
+ setNodeValue(node, void 0);
1901
+ }
1827
1902
  } else if (!isFlushing && refreshFn) {
1828
1903
  if (shouldIgnoreUnobserved(node, refreshFn)) {
1829
1904
  ignoreThisUpdate = true;
@@ -1836,7 +1911,7 @@ function activateNodeFunction(node, lazyFn) {
1836
1911
  didSetToObs = true;
1837
1912
  value = setToObservable(node, value);
1838
1913
  }
1839
- if (isFunction(value)) {
1914
+ if (isFunction(value) && value.length === 0) {
1840
1915
  value = value();
1841
1916
  }
1842
1917
  const activated = !isObservable(value) ? value == null ? void 0 : value[symbolLinked] : void 0;
@@ -1894,16 +1969,14 @@ function activateNodeFunction(node, lazyFn) {
1894
1969
  }
1895
1970
  } else {
1896
1971
  activatedValue = value;
1897
- if (node.state.isLoaded.peek()) {
1972
+ const isLoaded = node.state.isLoaded.peek();
1973
+ if (isLoaded || !isFunction(value)) {
1898
1974
  node.isComputing = true;
1899
1975
  set(node, value);
1900
1976
  node.isComputing = false;
1901
- } else {
1902
- setNodeValue(node, value);
1903
- node.state.assign({
1904
- isLoaded: true,
1905
- error: void 0
1906
- });
1977
+ }
1978
+ if (!isLoaded) {
1979
+ node.state.assign({ isLoaded: true, error: void 0 });
1907
1980
  }
1908
1981
  }
1909
1982
  }
@@ -1944,14 +2017,14 @@ function activateNodeBase(node, value) {
1944
2017
  if (allChanges.length > 0) {
1945
2018
  let changes;
1946
2019
  let value2;
1947
- let loading = false;
1948
- let remote = false;
2020
+ let isFromPersist = false;
2021
+ let isFromSync = false;
1949
2022
  let getPrevious;
1950
2023
  if (listenerParams) {
1951
2024
  changes = listenerParams.changes;
1952
2025
  value2 = listenerParams.value;
1953
- loading = listenerParams.loading;
1954
- remote = listenerParams.remote;
2026
+ isFromPersist = listenerParams.isFromPersist;
2027
+ isFromSync = listenerParams.isFromSync;
1955
2028
  getPrevious = listenerParams.getPrevious;
1956
2029
  } else {
1957
2030
  changes = allChanges;
@@ -1971,8 +2044,8 @@ function activateNodeBase(node, value) {
1971
2044
  setFn({
1972
2045
  value: value2,
1973
2046
  changes,
1974
- loading,
1975
- remote,
2047
+ isFromPersist,
2048
+ isFromSync,
1976
2049
  getPrevious
1977
2050
  });
1978
2051
  node.isComputing = false;
@@ -2017,7 +2090,9 @@ function setToObservable(node, value) {
2017
2090
  linkedNode,
2018
2091
  () => {
2019
2092
  value = peekInternal(linkedNode);
2020
- set(node, value);
2093
+ if (!isFunction(value)) {
2094
+ set(node, value);
2095
+ }
2021
2096
  },
2022
2097
  { initial: true },
2023
2098
  /* @__PURE__ */ new Set([node])
@@ -2026,7 +2101,8 @@ function setToObservable(node, value) {
2026
2101
  return value;
2027
2102
  }
2028
2103
  function recursivelyAutoActivate(obj, node) {
2029
- if (isObject(obj) || isArray(obj)) {
2104
+ if (!node.recursivelyAutoActivated && (isObject(obj) || isArray(obj)) && !isOpaqueObject(obj)) {
2105
+ node.recursivelyAutoActivated = true;
2030
2106
  const pathStack = [];
2031
2107
  const getNodeAtPath2 = () => {
2032
2108
  var _a;
@@ -2044,27 +2120,29 @@ function recursivelyAutoActivate(obj, node) {
2044
2120
  }
2045
2121
  function recursivelyAutoActivateInner(obj, pathStack, getNodeAtPath2) {
2046
2122
  var _a;
2047
- for (const key in obj) {
2048
- if (hasOwnProperty.call(obj, key)) {
2049
- const value = obj[key];
2050
- if (isObservable(value)) {
2051
- const childNode = getNodeAtPath2();
2052
- extractFunctionOrComputed(childNode, key, value);
2053
- delete childNode.lazy;
2054
- } else {
2055
- const linkedOptions = isFunction(value) && ((_a = value.prototype) == null ? void 0 : _a[symbolLinked]);
2056
- if (linkedOptions) {
2057
- const activate = linkedOptions.activate;
2058
- if (!activate || activate === "auto") {
2059
- const childNode = getNodeAtPath2();
2060
- peek(getChildNode(childNode, key, value));
2123
+ if ((isObject(obj) || isArray(obj)) && !isOpaqueObject(obj)) {
2124
+ for (const key in obj) {
2125
+ if (hasOwnProperty.call(obj, key)) {
2126
+ const value = obj[key];
2127
+ if (isObservable(value)) {
2128
+ const childNode = getNodeAtPath2();
2129
+ extractFunctionOrComputed(childNode, key, value);
2130
+ delete childNode.lazy;
2131
+ } else {
2132
+ const linkedOptions = isFunction(value) && ((_a = value.prototype) == null ? void 0 : _a[symbolLinked]);
2133
+ if (linkedOptions) {
2134
+ const activate = linkedOptions.activate;
2135
+ if (!activate || activate === "auto") {
2136
+ const childNode = getNodeAtPath2();
2137
+ peek(getChildNode(childNode, key, value));
2138
+ }
2061
2139
  }
2062
2140
  }
2063
- }
2064
- if (typeof value === "object") {
2065
- pathStack.push({ key, value });
2066
- recursivelyAutoActivateInner(value, pathStack, getNodeAtPath2);
2067
- pathStack.pop();
2141
+ if (typeof value === "object") {
2142
+ pathStack.push({ key, value });
2143
+ recursivelyAutoActivateInner(value, pathStack, getNodeAtPath2);
2144
+ pathStack.pop();
2145
+ }
2068
2146
  }
2069
2147
  }
2070
2148
  }
@@ -2120,16 +2198,6 @@ function observable(value) {
2120
2198
  function observablePrimitive(value) {
2121
2199
  return createObservable(value, true, extractPromise, getProxy, ObservablePrimitiveClass);
2122
2200
  }
2123
- function syncState(obs) {
2124
- const node = getNode(obs);
2125
- if (!node.state) {
2126
- peekInternal(node);
2127
- }
2128
- if (!node.state) {
2129
- node.state = observable({});
2130
- }
2131
- return node.state;
2132
- }
2133
2201
 
2134
2202
  // src/computed.ts
2135
2203
  function computed(get2, set2) {
@@ -2207,54 +2275,63 @@ function proxy(get2, set2) {
2207
2275
  );
2208
2276
  }
2209
2277
 
2278
+ // src/syncState.ts
2279
+ function syncState(obs) {
2280
+ const node = getNode(obs);
2281
+ if (!node.state) {
2282
+ node.state = observable({
2283
+ isPersistLoaded: false,
2284
+ isLoaded: false,
2285
+ isPersistEnabled: true,
2286
+ isSyncEnabled: true,
2287
+ isGetting: false,
2288
+ isSetting: false,
2289
+ numPendingSets: 0,
2290
+ syncCount: 0,
2291
+ clearPersist: void 0,
2292
+ sync: () => Promise.resolve(),
2293
+ getPendingChanges: () => ({})
2294
+ });
2295
+ }
2296
+ return node.state;
2297
+ }
2298
+
2210
2299
  // src/retry.ts
2211
- function calculateRetryDelay(retryOptions, attemptNum) {
2300
+ function calculateRetryDelay(retryOptions, retryNum) {
2212
2301
  const { backoff, delay = 1e3, infinite, times = 3, maxDelay = 3e4 } = retryOptions;
2213
- if (infinite || attemptNum < times) {
2214
- const delayTime = Math.min(delay * (backoff === "constant" ? 1 : 2 ** attemptNum), maxDelay);
2302
+ if (infinite || retryNum < times) {
2303
+ const delayTime = Math.min(delay * (backoff === "constant" ? 1 : 2 ** retryNum), maxDelay);
2215
2304
  return delayTime;
2216
2305
  }
2217
2306
  return null;
2218
2307
  }
2219
- function createRetryTimeout(retryOptions, attemptNum, fn) {
2220
- const delayTime = calculateRetryDelay(retryOptions, attemptNum);
2308
+ function createRetryTimeout(retryOptions, retryNum, fn) {
2309
+ const delayTime = calculateRetryDelay(retryOptions, retryNum);
2221
2310
  if (delayTime) {
2222
2311
  return setTimeout(fn, delayTime);
2223
2312
  }
2224
2313
  }
2225
- function runWithRetry(node, state, fn) {
2226
- const { waitFor } = node.activationState;
2314
+ function runWithRetry(state, fn) {
2227
2315
  const { retry } = state;
2228
- const e = { cancel: false };
2229
- let value = void 0;
2230
- if (waitFor) {
2231
- value = whenReady(waitFor, () => {
2232
- node.activationState.waitFor = void 0;
2233
- return fn(e);
2234
- });
2235
- } else {
2236
- value = fn(e);
2237
- }
2316
+ const e = Object.assign(state, { cancel: false, cancelRetry: () => e.cancel = false });
2317
+ let value = fn(e);
2238
2318
  if (isPromise(value) && retry) {
2239
2319
  let timeoutRetry;
2240
2320
  return new Promise((resolve) => {
2241
2321
  const run = () => {
2242
2322
  value.then((val) => {
2243
- node.activationState.persistedRetry = false;
2244
2323
  resolve(val);
2245
2324
  }).catch(() => {
2246
- state.attemptNum++;
2325
+ state.retryNum++;
2247
2326
  if (timeoutRetry) {
2248
2327
  clearTimeout(timeoutRetry);
2249
2328
  }
2250
2329
  if (!e.cancel) {
2251
- timeoutRetry = createRetryTimeout(retry, state.attemptNum, () => {
2330
+ timeoutRetry = createRetryTimeout(retry, state.retryNum, () => {
2252
2331
  value = fn(e);
2253
2332
  run();
2254
2333
  });
2255
2334
  }
2256
- }).finally(() => {
2257
- node.activationState.persistedRetry = false;
2258
2335
  });
2259
2336
  };
2260
2337
  run();
@@ -2267,6 +2344,7 @@ function runWithRetry(node, state, fn) {
2267
2344
  var internal = {
2268
2345
  createPreviousHandler,
2269
2346
  clone,
2347
+ deepMerge,
2270
2348
  ensureNodeValue,
2271
2349
  findIDKey,
2272
2350
  get,