@legendapp/state 3.0.0-beta.42 → 3.0.0-beta.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/sync.mjs CHANGED
@@ -540,7 +540,7 @@ async function prepChangeRemote(queuedChange) {
540
540
  );
541
541
  promisesTransform.push(
542
542
  doInOrder(promiseTransformRemote, ({ value: valueTransformed, path: pathTransformed }) => {
543
- var _a;
543
+ var _a, _b, _c, _d;
544
544
  if (!localState.pendingChanges) {
545
545
  localState.pendingChanges = {};
546
546
  }
@@ -557,18 +557,27 @@ async function prepChangeRemote(queuedChange) {
557
557
  pathTypesChild,
558
558
  valueAtPath
559
559
  );
560
+ if ((_b = localState.pendingClears) == null ? void 0 : _b[pathParent]) {
561
+ delete localState.pendingClears[pathParent];
562
+ }
560
563
  }
561
564
  }
562
565
  if (!found2) {
563
566
  for (const key in localState.pendingChanges) {
564
567
  if (key !== pathStr && key.startsWith(pathStr)) {
565
568
  delete localState.pendingChanges[key];
569
+ if ((_c = localState.pendingClears) == null ? void 0 : _c[key]) {
570
+ delete localState.pendingClears[key];
571
+ }
566
572
  }
567
573
  }
568
574
  if (!localState.pendingChanges[pathStr]) {
569
575
  localState.pendingChanges[pathStr] = { p: prevAtPath != null ? prevAtPath : null, t: pathTypes };
570
576
  }
571
577
  localState.pendingChanges[pathStr].v = valueAtPath;
578
+ if ((_d = localState.pendingClears) == null ? void 0 : _d[pathStr]) {
579
+ delete localState.pendingClears[pathStr];
580
+ }
572
581
  }
573
582
  changesRemote.push({
574
583
  path: pathTransformed,
@@ -632,7 +641,7 @@ async function doChangeRemote(changeInfo) {
632
641
  const shouldSaveMetadata = persist == null ? void 0 : persist.retrySync;
633
642
  const saveLocal = !!(persist == null ? void 0 : persist.name);
634
643
  if (changesRemote.length > 0) {
635
- if (!syncState2.isLoaded.peek()) {
644
+ if ((syncOptions.get || syncOptions.subscribe) && !syncState2.isLoaded.peek()) {
636
645
  await when(syncState2.isLoaded);
637
646
  const pending = localState.pendingChanges;
638
647
  if (pending) {
@@ -654,6 +663,12 @@ async function doChangeRemote(changeInfo) {
654
663
  if (transformSave) {
655
664
  value = transformSave(value);
656
665
  }
666
+ const setGeneration = localState.pendingSetGeneration;
667
+ const pendingSetsSinceClear = localState.pendingSetsSinceClear || 0;
668
+ const hadPendingSets = setGeneration !== void 0 ? pendingSetsSinceClear > 0 : (state$.numPendingSets.peek() || 0) > 0;
669
+ if (setGeneration !== void 0) {
670
+ localState.pendingSetsSinceClear = pendingSetsSinceClear + 1;
671
+ }
657
672
  state$.numPendingSets.set((v) => (v || 0) + 1);
658
673
  state$.isSetting.set(true);
659
674
  const beforeSetParams = {
@@ -668,6 +683,7 @@ async function doChangeRemote(changeInfo) {
668
683
  if (lastErrorHandled !== error) {
669
684
  if (!params) {
670
685
  params = {
686
+ syncOptions,
671
687
  setParams,
672
688
  source: "set",
673
689
  type: "set",
@@ -675,6 +691,11 @@ async function doChangeRemote(changeInfo) {
675
691
  retry: setParams,
676
692
  revert: createRevertChanges(setParams.value$, setParams.changes)
677
693
  };
694
+ } else if (!params.syncOptions) {
695
+ params = {
696
+ ...params,
697
+ syncOptions
698
+ };
678
699
  }
679
700
  state$.error.set(error);
680
701
  (_a2 = syncOptions.onError) == null ? void 0 : _a2.call(syncOptions, error, params);
@@ -720,24 +741,61 @@ async function doChangeRemote(changeInfo) {
720
741
  }
721
742
  if (!didError || (updateResult == null ? void 0 : updateResult.changes)) {
722
743
  const { value: updateValue, changes: updateChanges = changesRemote } = updateResult || {};
723
- const pathStrs = Array.from(
724
- new Set(updateChanges.map((change) => change.pathStr))
725
- );
744
+ const changesWithPath = updateChanges;
745
+ const pathStrs = Array.from(new Set(changesWithPath.map((change) => change.pathStr)));
726
746
  if (pathStrs.length > 0) {
727
747
  let transformedChanges = void 0;
728
748
  const metadata = {};
729
- if (saveLocal) {
730
- const pendingMetadata = (_b = pluginPersist.getMetadata(table, configLocal)) == null ? void 0 : _b.pending;
731
- const pending = localState.pendingChanges;
732
- for (let i = 0; i < pathStrs.length; i++) {
733
- const pathStr = pathStrs[i];
734
- if (pendingMetadata == null ? void 0 : pendingMetadata[pathStr]) {
735
- delete pendingMetadata[pathStr];
736
- metadata.pending = pendingMetadata;
749
+ const pending = localState.pendingChanges;
750
+ const pendingToKeep = /* @__PURE__ */ new Set();
751
+ if (pending) {
752
+ const changesByPath = /* @__PURE__ */ new Map();
753
+ for (let i = 0; i < changesWithPath.length; i++) {
754
+ const change = changesWithPath[i];
755
+ changesByPath.set(change.pathStr, change);
756
+ }
757
+ for (const key in pending) {
758
+ const pendingEntry = pending[key];
759
+ if (!pendingEntry) {
760
+ continue;
761
+ }
762
+ const change = changesByPath.get(key);
763
+ if (!change || !deepEqual(pendingEntry.v, change.valueAtPath)) {
764
+ pendingToKeep.add(key);
737
765
  }
738
- if (pending == null ? void 0 : pending[pathStr]) {
739
- delete pending[pathStr];
766
+ }
767
+ }
768
+ const pendingToOverlay = new Set(pendingToKeep);
769
+ const pendingClears = localState.pendingClears;
770
+ if (pendingClears) {
771
+ for (const key in pendingClears) {
772
+ pendingToOverlay.add(key);
773
+ }
774
+ }
775
+ if (hadPendingSets) {
776
+ for (let i = 0; i < changesWithPath.length; i++) {
777
+ pendingToOverlay.add(changesWithPath[i].pathStr);
778
+ }
779
+ }
780
+ const pendingMetadata = saveLocal ? (_b = pluginPersist.getMetadata(table, configLocal)) == null ? void 0 : _b.pending : void 0;
781
+ const shouldDeferPendingClear = (state$.numPendingSets.peek() || 0) > 1;
782
+ for (let i = 0; i < pathStrs.length; i++) {
783
+ const pathStr = pathStrs[i];
784
+ if (pendingToKeep.has(pathStr)) {
785
+ continue;
786
+ }
787
+ if (shouldDeferPendingClear && (pending == null ? void 0 : pending[pathStr])) {
788
+ if (!localState.pendingClears) {
789
+ localState.pendingClears = {};
740
790
  }
791
+ localState.pendingClears[pathStr] = pending[pathStr];
792
+ }
793
+ if (pendingMetadata == null ? void 0 : pendingMetadata[pathStr]) {
794
+ delete pendingMetadata[pathStr];
795
+ metadata.pending = pendingMetadata;
796
+ }
797
+ if (pending == null ? void 0 : pending[pathStr]) {
798
+ delete pending[pathStr];
741
799
  }
742
800
  }
743
801
  if (updateValue && !isEmpty(updateValue)) {
@@ -747,7 +805,48 @@ async function doChangeRemote(changeInfo) {
747
805
  if (isPromise$1(transformedChanges)) {
748
806
  transformedChanges = await transformedChanges;
749
807
  }
750
- onChangeRemote2(() => mergeIntoObservable(obs$, transformedChanges));
808
+ if (pendingToOverlay.size === 0) {
809
+ onChangeRemote2(() => mergeIntoObservable(obs$, transformedChanges));
810
+ } else if (!pendingToOverlay.has("")) {
811
+ let updatePatch = transformedChanges;
812
+ if (typeof updatePatch === "object" && updatePatch !== null) {
813
+ updatePatch = clone2(updatePatch);
814
+ const currentValue = obs$.peek();
815
+ for (const pathStr of pendingToOverlay) {
816
+ if (!pathStr) {
817
+ continue;
818
+ }
819
+ const pendingEntry = (pending == null ? void 0 : pending[pathStr]) || (pendingClears == null ? void 0 : pendingClears[pathStr]);
820
+ if (!pendingEntry) {
821
+ continue;
822
+ }
823
+ const path = pathStr.split("/").filter((p) => p);
824
+ const currentAtPath = getValueAtPath(currentValue, path);
825
+ updatePatch = setAtPath(updatePatch, path, pendingEntry.t, currentAtPath);
826
+ }
827
+ if (hadPendingSets) {
828
+ for (let i = 0; i < changesWithPath.length; i++) {
829
+ const change = changesWithPath[i];
830
+ if (!change.pathStr || !pendingToOverlay.has(change.pathStr)) {
831
+ continue;
832
+ }
833
+ const currentAtPath = getValueAtPath(
834
+ currentValue,
835
+ change.path
836
+ );
837
+ updatePatch = setAtPath(
838
+ updatePatch,
839
+ change.path,
840
+ change.pathTypes,
841
+ currentAtPath
842
+ );
843
+ }
844
+ }
845
+ }
846
+ if (updatePatch !== void 0) {
847
+ onChangeRemote2(() => mergeIntoObservable(obs$, updatePatch));
848
+ }
849
+ }
751
850
  }
752
851
  if (saveLocal) {
753
852
  if (shouldSaveMetadata && !isEmpty(metadata)) {
@@ -756,7 +855,18 @@ async function doChangeRemote(changeInfo) {
756
855
  }
757
856
  }
758
857
  state$.numPendingSets.set((v) => v - 1);
759
- state$.isSetting.set(state$.numPendingSets.peek() > 0);
858
+ const remainingSets = state$.numPendingSets.peek() || 0;
859
+ if (setGeneration !== void 0 && localState.pendingSetGeneration === setGeneration) {
860
+ localState.pendingSetsSinceClear = (localState.pendingSetsSinceClear || 1) - 1;
861
+ }
862
+ if (!remainingSets) {
863
+ if (localState.pendingSetGeneration !== void 0 && !localState.pendingSetsSinceClear) {
864
+ localState.pendingSetGeneration = void 0;
865
+ localState.pendingSetsSinceClear = void 0;
866
+ }
867
+ localState.pendingClears = void 0;
868
+ }
869
+ state$.isSetting.set(remainingSets > 0);
760
870
  onAfterSet == null ? void 0 : onAfterSet();
761
871
  }
762
872
  }
@@ -891,10 +1001,18 @@ function syncObservable(obs$, syncOptionsOrSynced) {
891
1001
  observableSyncConfiguration,
892
1002
  removeNullUndefined(syncOptions || {})
893
1003
  );
894
- const localState = {};
895
- let sync;
896
1004
  const syncState$ = syncState(obs$);
897
1005
  const syncStateValue = getNodeValue(getNode(syncState$));
1006
+ const localState = {};
1007
+ let sync;
1008
+ const resetPendingState = () => {
1009
+ var _a;
1010
+ localState.pendingChanges = {};
1011
+ localState.pendingClears = void 0;
1012
+ const hasPendingSets = (syncStateValue.numPendingSets || 0) > 0;
1013
+ localState.pendingSetGeneration = hasPendingSets ? ((_a = localState.pendingSetGeneration) != null ? _a : 0) + 1 : void 0;
1014
+ localState.pendingSetsSinceClear = hasPendingSets ? 0 : void 0;
1015
+ };
898
1016
  allSyncStates.set(syncState$, node);
899
1017
  syncStateValue.getPendingChanges = () => localState.pendingChanges;
900
1018
  let lastErrorHandled;
@@ -903,9 +1021,15 @@ function syncObservable(obs$, syncOptionsOrSynced) {
903
1021
  if (lastErrorHandled !== error) {
904
1022
  if (!params) {
905
1023
  params = {
1024
+ syncOptions,
906
1025
  source: "get",
907
1026
  type: "get",
908
- retry: params
1027
+ retry: { retryNum: 0, cancelRetry: false }
1028
+ };
1029
+ } else if (!params.syncOptions) {
1030
+ params = {
1031
+ ...params,
1032
+ syncOptions
909
1033
  };
910
1034
  }
911
1035
  syncState$.error.set(error);
@@ -1085,7 +1209,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
1085
1209
  onChange(params);
1086
1210
  if (!syncState$.isLoaded.peek()) {
1087
1211
  syncState$.assign({
1088
- isLoaded: syncStateValue.numPendingRemoteLoads < 1,
1212
+ isLoaded: (syncStateValue.numPendingRemoteLoads || 0) < 1,
1089
1213
  error: void 0,
1090
1214
  isGetting: syncStateValue.numPendingGets > 0
1091
1215
  });
@@ -1097,6 +1221,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
1097
1221
  refresh: () => when(syncState$.isLoaded, callSync),
1098
1222
  onError: (error) => onGetError(error, {
1099
1223
  source: "subscribe",
1224
+ syncOptions,
1100
1225
  subscribeParams,
1101
1226
  type: "get",
1102
1227
  retry: {}
@@ -1143,7 +1268,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
1143
1268
  lastSync,
1144
1269
  pendingChanges: pending && !isEmpty(pending) ? pending : void 0,
1145
1270
  clearPendingChanges: async () => {
1146
- localState.pendingChanges = {};
1271
+ resetPendingState();
1147
1272
  await updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
1148
1273
  pending: localState.pendingChanges
1149
1274
  });
@@ -1195,7 +1320,11 @@ function syncObservable(obs$, syncOptionsOrSynced) {
1195
1320
  };
1196
1321
  if (isPromise$1(got)) {
1197
1322
  got.then(handle).catch((error) => {
1198
- onGetError(error, { getParams, source: "get", type: "get", retry: getParams }, true);
1323
+ onGetError(
1324
+ error,
1325
+ { getParams, syncOptions, source: "get", type: "get", retry: getParams },
1326
+ true
1327
+ );
1199
1328
  });
1200
1329
  } else {
1201
1330
  handle(got);
@@ -1230,6 +1359,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
1230
1359
  if (metadata) {
1231
1360
  Object.assign(metadata, { lastSync: void 0, pending: void 0 });
1232
1361
  }
1362
+ resetPendingState();
1233
1363
  const newState = {
1234
1364
  isPersistEnabled: false,
1235
1365
  isSyncEnabled: false,
@@ -1251,7 +1381,6 @@ function syncObservable(obs$, syncOptionsOrSynced) {
1251
1381
  var _a;
1252
1382
  obs$.set((_a = syncOptions.initial) != null ? _a : void 0);
1253
1383
  });
1254
- syncState$.isLoaded.set(false);
1255
1384
  syncStateValue.isPersistEnabled = wasPersistEnabled;
1256
1385
  syncStateValue.isSyncEnabled = wasSyncEnabled;
1257
1386
  node.dirtyFn = sync;
@@ -1,5 +1,6 @@
1
1
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
2
2
  import type { IReactive, FCReactiveObject } from '@legendapp/state/react';
3
+ import type { JSX } from 'react';
3
4
 
4
5
  declare module '@legendapp/state/react' {
5
6
  // eslint-disable-next-line @typescript-eslint/no-empty-interface