@legendapp/state 3.0.0-beta.3 → 3.0.0-beta.31
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/.DS_Store +0 -0
- package/config/enableReactComponents.js +3 -1
- package/config/enableReactComponents.mjs +3 -1
- package/config/enableReactTracking.d.mts +2 -1
- package/config/enableReactTracking.d.ts +2 -1
- package/config/enableReactTracking.js +32 -13
- package/config/enableReactTracking.mjs +32 -13
- package/index.d.mts +38 -5
- package/index.d.ts +38 -5
- package/index.js +202 -31
- package/index.mjs +202 -31
- package/package.json +35 -1
- package/persist-plugins/async-storage.js +17 -9
- package/persist-plugins/async-storage.mjs +17 -9
- package/persist-plugins/expo-sqlite.d.mts +19 -0
- package/persist-plugins/expo-sqlite.d.ts +19 -0
- package/persist-plugins/expo-sqlite.js +72 -0
- package/persist-plugins/expo-sqlite.mjs +69 -0
- package/react-native.d.mts +4 -0
- package/react-native.d.ts +4 -0
- package/react-native.js +53 -0
- package/react-native.mjs +40 -0
- package/react-reactive/Components.d.mts +19 -0
- package/react-reactive/Components.d.ts +19 -0
- package/react-reactive/Components.js +53 -0
- package/react-reactive/Components.mjs +40 -0
- package/react-reactive/enableReactComponents.d.mts +3 -2
- package/react-reactive/enableReactComponents.d.ts +3 -2
- package/react-reactive/enableReactComponents.js +10 -3
- package/react-reactive/enableReactComponents.mjs +10 -3
- package/react-reactive/enableReactNativeComponents.d.mts +3 -20
- package/react-reactive/enableReactNativeComponents.d.ts +3 -20
- package/react-reactive/enableReactNativeComponents.js +8 -3
- package/react-reactive/enableReactNativeComponents.mjs +8 -3
- package/react-reactive/enableReactive.js +10 -3
- package/react-reactive/enableReactive.mjs +10 -3
- package/react-reactive/enableReactive.native.js +8 -3
- package/react-reactive/enableReactive.native.mjs +8 -3
- package/react-reactive/enableReactive.web.js +8 -3
- package/react-reactive/enableReactive.web.mjs +8 -3
- package/react-web.d.mts +6 -0
- package/react-web.d.ts +6 -0
- package/react-web.js +39 -0
- package/react-web.mjs +37 -0
- package/react.d.mts +41 -21
- package/react.d.ts +41 -21
- package/react.js +86 -63
- package/react.mjs +87 -65
- package/sync-plugins/crud.d.mts +24 -9
- package/sync-plugins/crud.d.ts +24 -9
- package/sync-plugins/crud.js +250 -116
- package/sync-plugins/crud.mjs +251 -117
- package/sync-plugins/firebase.d.mts +7 -3
- package/sync-plugins/firebase.d.ts +7 -3
- package/sync-plugins/firebase.js +4 -2
- package/sync-plugins/firebase.mjs +4 -2
- package/sync-plugins/keel.d.mts +12 -13
- package/sync-plugins/keel.d.ts +12 -13
- package/sync-plugins/keel.js +60 -52
- package/sync-plugins/keel.mjs +61 -48
- package/sync-plugins/supabase.d.mts +7 -3
- package/sync-plugins/supabase.d.ts +7 -3
- package/sync-plugins/supabase.js +90 -33
- package/sync-plugins/supabase.mjs +91 -34
- package/sync-plugins/tanstack-query.d.mts +3 -3
- package/sync-plugins/tanstack-query.d.ts +3 -3
- package/sync.d.mts +16 -8
- package/sync.d.ts +16 -8
- package/sync.js +324 -215
- package/sync.mjs +323 -215
- package/trace.js +5 -6
- package/trace.mjs +5 -6
- package/types/reactive-native.d.ts +19 -0
- package/types/reactive-web.d.ts +7 -0
package/sync.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { isObject, isDate, isNullOrUndefined, isString, endBatch, beginBatch, isFunction, syncState, when, linked, internal, observable, isPromise as isPromise$1, mergeIntoObservable, isEmpty, shouldIgnoreUnobserved, whenReady, trackSelector, constructObjectWithPath, setAtPath, isPlainObject, ObservableHint, isArray } from '@legendapp/state';
|
|
1
|
+
import { isObject, isDate, isNullOrUndefined, isString, applyChanges, endBatch, beginBatch, isFunction, syncState, when, linked, internal, observable, isPromise as isPromise$1, mergeIntoObservable, isEmpty, shouldIgnoreUnobserved, whenReady, trackSelector, constructObjectWithPath, setAtPath, isPlainObject, ObservableHint, isArray } from '@legendapp/state';
|
|
2
|
+
import { onChangeRemote } from '@legendapp/state/sync';
|
|
2
3
|
|
|
3
4
|
// src/sync/configureObservableSync.ts
|
|
4
5
|
var observableSyncConfiguration = {};
|
|
@@ -33,12 +34,12 @@ function diffObjects(obj1, obj2, deep = false) {
|
|
|
33
34
|
return diff;
|
|
34
35
|
}
|
|
35
36
|
function deepEqual(a, b, ignoreFields, nullVsUndefined) {
|
|
36
|
-
if (a === b)
|
|
37
|
+
if (a === b)
|
|
37
38
|
return true;
|
|
38
|
-
|
|
39
|
-
if (isNullOrUndefined(a) !== isNullOrUndefined(b)) {
|
|
39
|
+
if (isNullOrUndefined(a) !== isNullOrUndefined(b))
|
|
40
40
|
return false;
|
|
41
|
-
|
|
41
|
+
if (!isObject(a) || !isObject(b))
|
|
42
|
+
return a === b;
|
|
42
43
|
if (nullVsUndefined) {
|
|
43
44
|
a = removeNullUndefined(
|
|
44
45
|
a,
|
|
@@ -51,8 +52,18 @@ function deepEqual(a, b, ignoreFields, nullVsUndefined) {
|
|
|
51
52
|
true
|
|
52
53
|
);
|
|
53
54
|
}
|
|
54
|
-
const
|
|
55
|
-
|
|
55
|
+
const keysA = Object.keys(a).filter((key) => !(ignoreFields == null ? void 0 : ignoreFields.includes(key)));
|
|
56
|
+
const keysB = Object.keys(b).filter((key) => !(ignoreFields == null ? void 0 : ignoreFields.includes(key)));
|
|
57
|
+
if (keysA.length !== keysB.length)
|
|
58
|
+
return false;
|
|
59
|
+
return keysA.every((key) => {
|
|
60
|
+
if (!Object.prototype.hasOwnProperty.call(b, key))
|
|
61
|
+
return false;
|
|
62
|
+
if (isDate(a[key]) && isDate(b[key])) {
|
|
63
|
+
return a[key].getTime() === b[key].getTime();
|
|
64
|
+
}
|
|
65
|
+
return deepEqual(a[key], b[key], ignoreFields, nullVsUndefined);
|
|
66
|
+
});
|
|
56
67
|
}
|
|
57
68
|
function combineTransforms(...transforms) {
|
|
58
69
|
return {
|
|
@@ -159,13 +170,13 @@ function createRetryTimeout(retryOptions, retryNum, fn) {
|
|
|
159
170
|
}
|
|
160
171
|
}
|
|
161
172
|
var mapRetryTimeouts = /* @__PURE__ */ new Map();
|
|
162
|
-
function runWithRetry(state, retryOptions,
|
|
173
|
+
function runWithRetry(state, retryOptions, retryId, fn) {
|
|
163
174
|
try {
|
|
164
175
|
let value = fn(state);
|
|
165
176
|
if (isPromise(value) && retryOptions) {
|
|
166
177
|
let timeoutRetry;
|
|
167
|
-
if (mapRetryTimeouts.has(
|
|
168
|
-
clearTimeout(mapRetryTimeouts.get(
|
|
178
|
+
if (mapRetryTimeouts.has(retryId)) {
|
|
179
|
+
clearTimeout(mapRetryTimeouts.get(retryId));
|
|
169
180
|
}
|
|
170
181
|
return new Promise((resolve, reject) => {
|
|
171
182
|
const run = () => {
|
|
@@ -176,9 +187,6 @@ function runWithRetry(state, retryOptions, fn, onError) {
|
|
|
176
187
|
if (timeoutRetry) {
|
|
177
188
|
clearTimeout(timeoutRetry);
|
|
178
189
|
}
|
|
179
|
-
if (onError) {
|
|
180
|
-
onError(error, state);
|
|
181
|
-
}
|
|
182
190
|
if (!state.cancelRetry) {
|
|
183
191
|
const timeout = createRetryTimeout(retryOptions, state.retryNum, () => {
|
|
184
192
|
value = fn(state);
|
|
@@ -188,7 +196,7 @@ function runWithRetry(state, retryOptions, fn, onError) {
|
|
|
188
196
|
state.cancelRetry = true;
|
|
189
197
|
reject(error);
|
|
190
198
|
} else {
|
|
191
|
-
mapRetryTimeouts.set(
|
|
199
|
+
mapRetryTimeouts.set(retryId, timeout);
|
|
192
200
|
timeoutRetry = timeout;
|
|
193
201
|
}
|
|
194
202
|
}
|
|
@@ -208,9 +216,33 @@ async function waitForSet(waitForSet2, changes, value, params = {}) {
|
|
|
208
216
|
await when(waitFn);
|
|
209
217
|
}
|
|
210
218
|
}
|
|
219
|
+
var { clone } = internal;
|
|
220
|
+
function createRevertChanges(obs$, changes) {
|
|
221
|
+
return () => {
|
|
222
|
+
const previous = applyChanges(
|
|
223
|
+
clone(obs$.peek()),
|
|
224
|
+
changes,
|
|
225
|
+
/*applyPrevious*/
|
|
226
|
+
true
|
|
227
|
+
);
|
|
228
|
+
onChangeRemote(() => {
|
|
229
|
+
obs$.set(previous);
|
|
230
|
+
});
|
|
231
|
+
};
|
|
232
|
+
}
|
|
211
233
|
|
|
212
234
|
// src/sync/syncObservable.ts
|
|
213
|
-
var {
|
|
235
|
+
var {
|
|
236
|
+
clone: clone2,
|
|
237
|
+
createPreviousHandler,
|
|
238
|
+
deepMerge,
|
|
239
|
+
getNode,
|
|
240
|
+
getNodeValue,
|
|
241
|
+
getValueAtPath,
|
|
242
|
+
globalState,
|
|
243
|
+
registerMiddleware,
|
|
244
|
+
symbolLinked
|
|
245
|
+
} = internal;
|
|
214
246
|
var mapSyncPlugins = /* @__PURE__ */ new WeakMap();
|
|
215
247
|
var allSyncStates = /* @__PURE__ */ new Map();
|
|
216
248
|
var metadatas = /* @__PURE__ */ new WeakMap();
|
|
@@ -221,7 +253,7 @@ function parseLocalConfig(config) {
|
|
|
221
253
|
function doInOrder(arg1, arg2) {
|
|
222
254
|
return isPromise$1(arg1) ? arg1.then(arg2) : arg2(arg1);
|
|
223
255
|
}
|
|
224
|
-
function
|
|
256
|
+
function onChangeRemote2(cb) {
|
|
225
257
|
endBatch(true);
|
|
226
258
|
globalState.isLoadingRemote = true;
|
|
227
259
|
beginBatch();
|
|
@@ -273,10 +305,10 @@ function updateMetadata(value$, localState, syncState2, syncOptions, newMetadata
|
|
|
273
305
|
if (localState.timeoutSaveMetadata) {
|
|
274
306
|
clearTimeout(localState.timeoutSaveMetadata);
|
|
275
307
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
);
|
|
308
|
+
metadatas.set(value$, { ...metadatas.get(value$) || {}, ...newMetadata });
|
|
309
|
+
localState.timeoutSaveMetadata = setTimeout(() => {
|
|
310
|
+
updateMetadataImmediate(value$, localState, syncState2, syncOptions, metadatas.get(value$));
|
|
311
|
+
}, 0);
|
|
280
312
|
}
|
|
281
313
|
var _queuedChanges = [];
|
|
282
314
|
var _queuedRemoteChanges = /* @__PURE__ */ new Map();
|
|
@@ -295,8 +327,25 @@ function mergeChanges(changes) {
|
|
|
295
327
|
existing.valueAtPath = change.valueAtPath;
|
|
296
328
|
}
|
|
297
329
|
} else {
|
|
298
|
-
|
|
299
|
-
|
|
330
|
+
let found = false;
|
|
331
|
+
for (let u = 0; u < change.path.length; u++) {
|
|
332
|
+
const path = change.path.slice(0, u).join("/");
|
|
333
|
+
if (changesByPath.has(path)) {
|
|
334
|
+
const remaining = change.path.slice(u);
|
|
335
|
+
setAtPath(
|
|
336
|
+
changesByPath.get(path).valueAtPath,
|
|
337
|
+
remaining,
|
|
338
|
+
change.pathTypes.slice(u),
|
|
339
|
+
change.valueAtPath
|
|
340
|
+
);
|
|
341
|
+
found = true;
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (!found) {
|
|
346
|
+
changesByPath.set(pathStr, change);
|
|
347
|
+
changesOut.push(change);
|
|
348
|
+
}
|
|
300
349
|
}
|
|
301
350
|
}
|
|
302
351
|
return changesOut;
|
|
@@ -578,7 +627,7 @@ async function doChangeRemote(changeInfo) {
|
|
|
578
627
|
if (waitForSetParam) {
|
|
579
628
|
await waitForSet(waitForSetParam, changesRemote, obs$.peek());
|
|
580
629
|
}
|
|
581
|
-
let value =
|
|
630
|
+
let value = clone2(obs$.peek());
|
|
582
631
|
const transformSave = (_a = syncOptions == null ? void 0 : syncOptions.transform) == null ? void 0 : _a.save;
|
|
583
632
|
if (transformSave) {
|
|
584
633
|
value = transformSave(value);
|
|
@@ -591,33 +640,41 @@ async function doChangeRemote(changeInfo) {
|
|
|
591
640
|
onBeforeSet == null ? void 0 : onBeforeSet(beforeSetParams);
|
|
592
641
|
if (!beforeSetParams.cancel) {
|
|
593
642
|
let updateResult = void 0;
|
|
594
|
-
let
|
|
595
|
-
const
|
|
643
|
+
let lastErrorHandled;
|
|
644
|
+
const onSetError = (error, params, noThrow) => {
|
|
596
645
|
var _a2;
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
646
|
+
if (lastErrorHandled !== error) {
|
|
647
|
+
if (!params) {
|
|
648
|
+
params = {
|
|
649
|
+
setParams,
|
|
650
|
+
source: "set",
|
|
651
|
+
type: "set",
|
|
652
|
+
input: value,
|
|
653
|
+
retry: setParams,
|
|
654
|
+
revert: createRevertChanges(setParams.value$, setParams.changes)
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
state$.error.set(error);
|
|
658
|
+
(_a2 = syncOptions.onError) == null ? void 0 : _a2.call(syncOptions, error, params);
|
|
659
|
+
lastErrorHandled = error;
|
|
660
|
+
if (!noThrow) {
|
|
661
|
+
throw error;
|
|
662
|
+
}
|
|
605
663
|
}
|
|
606
|
-
errorHandled = true;
|
|
607
664
|
};
|
|
608
665
|
const setParams = {
|
|
609
666
|
node,
|
|
610
667
|
value$: obs$,
|
|
611
668
|
changes: changesRemote,
|
|
612
669
|
value,
|
|
613
|
-
onError,
|
|
670
|
+
onError: onSetError,
|
|
614
671
|
update: (params) => {
|
|
615
672
|
if (updateResult) {
|
|
616
|
-
const { value: value2,
|
|
673
|
+
const { value: value2, mode, changes } = params;
|
|
617
674
|
updateResult = {
|
|
618
|
-
lastSync: Math.max(updateResult.lastSync || 0, lastSync || 0),
|
|
619
675
|
value: deepMerge(updateResult.value, value2),
|
|
620
|
-
mode
|
|
676
|
+
mode,
|
|
677
|
+
changes: changes ? [...updateResult.changes || [], ...changes] : updateResult.changes
|
|
621
678
|
};
|
|
622
679
|
} else {
|
|
623
680
|
updateResult = params;
|
|
@@ -627,26 +684,23 @@ async function doChangeRemote(changeInfo) {
|
|
|
627
684
|
retryNum: 0,
|
|
628
685
|
cancelRetry: false
|
|
629
686
|
};
|
|
630
|
-
const savedPromise = runWithRetry(
|
|
631
|
-
setParams
|
|
632
|
-
|
|
633
|
-
async () => {
|
|
634
|
-
return syncOptions.set(setParams);
|
|
635
|
-
},
|
|
636
|
-
onError
|
|
637
|
-
);
|
|
687
|
+
const savedPromise = runWithRetry(setParams, syncOptions.retry, node, async () => {
|
|
688
|
+
return syncOptions.set(setParams);
|
|
689
|
+
});
|
|
638
690
|
let didError = false;
|
|
639
691
|
if (isPromise$1(savedPromise)) {
|
|
640
692
|
await savedPromise.catch((error) => {
|
|
641
693
|
didError = true;
|
|
642
694
|
if (!syncOptions.retry) {
|
|
643
|
-
|
|
695
|
+
onSetError(error, void 0, true);
|
|
644
696
|
}
|
|
645
697
|
});
|
|
646
698
|
}
|
|
647
|
-
if (!didError) {
|
|
648
|
-
const
|
|
649
|
-
const
|
|
699
|
+
if (!didError || (updateResult == null ? void 0 : updateResult.changes)) {
|
|
700
|
+
const { value: updateValue, changes: updateChanges = changesRemote } = updateResult || {};
|
|
701
|
+
const pathStrs = Array.from(
|
|
702
|
+
new Set(updateChanges.map((change) => change.pathStr))
|
|
703
|
+
);
|
|
650
704
|
if (pathStrs.length > 0) {
|
|
651
705
|
let transformedChanges = void 0;
|
|
652
706
|
const metadata = {};
|
|
@@ -663,18 +717,15 @@ async function doChangeRemote(changeInfo) {
|
|
|
663
717
|
delete pending[pathStr];
|
|
664
718
|
}
|
|
665
719
|
}
|
|
666
|
-
if (lastSync) {
|
|
667
|
-
metadata.lastSync = lastSync;
|
|
668
|
-
}
|
|
669
720
|
}
|
|
670
|
-
if (
|
|
671
|
-
transformedChanges = transformLoadData(
|
|
721
|
+
if (updateValue && !isEmpty(updateValue)) {
|
|
722
|
+
transformedChanges = transformLoadData(updateValue, syncOptions, false, "set");
|
|
672
723
|
}
|
|
673
724
|
if (transformedChanges !== void 0) {
|
|
674
725
|
if (isPromise$1(transformedChanges)) {
|
|
675
726
|
transformedChanges = await transformedChanges;
|
|
676
727
|
}
|
|
677
|
-
|
|
728
|
+
onChangeRemote2(() => mergeIntoObservable(obs$, transformedChanges));
|
|
678
729
|
}
|
|
679
730
|
if (saveLocal) {
|
|
680
731
|
if (shouldSaveMetadata && !isEmpty(metadata)) {
|
|
@@ -741,9 +792,20 @@ async function loadLocal(value$, syncOptions, syncState$, localState) {
|
|
|
741
792
|
await when(initialized$);
|
|
742
793
|
}
|
|
743
794
|
if (persistPlugin.loadTable) {
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
795
|
+
try {
|
|
796
|
+
const promise = persistPlugin.loadTable(table, config);
|
|
797
|
+
if (promise) {
|
|
798
|
+
await promise;
|
|
799
|
+
}
|
|
800
|
+
} catch (err) {
|
|
801
|
+
if (process.env.NODE_ENV === "development") {
|
|
802
|
+
console.error(
|
|
803
|
+
"[legend-state] Error loading local cache. This would be a crashing error in production.",
|
|
804
|
+
err
|
|
805
|
+
);
|
|
806
|
+
} else {
|
|
807
|
+
throw err;
|
|
808
|
+
}
|
|
747
809
|
}
|
|
748
810
|
}
|
|
749
811
|
const prevValue = getNodeValue(node);
|
|
@@ -762,12 +824,14 @@ async function loadLocal(value$, syncOptions, syncState$, localState) {
|
|
|
762
824
|
if (isPromise$1(value)) {
|
|
763
825
|
value = await value;
|
|
764
826
|
}
|
|
827
|
+
node.root.isLoadingLocal = true;
|
|
765
828
|
internal.globalState.isLoadingLocal = true;
|
|
766
829
|
if (value === null && (!prevValue || prevValue[symbolLinked])) {
|
|
767
830
|
value$.set(value);
|
|
768
831
|
} else {
|
|
769
832
|
mergeIntoObservable(value$, value);
|
|
770
833
|
}
|
|
834
|
+
node.root.isLoadingLocal = false;
|
|
771
835
|
internal.globalState.isLoadingLocal = false;
|
|
772
836
|
}
|
|
773
837
|
syncStateValue.numPendingLocalLoads--;
|
|
@@ -779,6 +843,11 @@ async function loadLocal(value$, syncOptions, syncState$, localState) {
|
|
|
779
843
|
].filter(Boolean)
|
|
780
844
|
);
|
|
781
845
|
} else {
|
|
846
|
+
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && persist && persist.plugin && !Object.hasOwn(persist, "name")) {
|
|
847
|
+
console.warn(
|
|
848
|
+
"[legend-state] Trying to syncObservable without `name` defined. Please include a `name` property in the `persist` configuration."
|
|
849
|
+
);
|
|
850
|
+
}
|
|
782
851
|
nodeValue.resetPersistence = () => prevResetPersistence == null ? void 0 : prevResetPersistence();
|
|
783
852
|
}
|
|
784
853
|
nodeValue.clearPersist = nodeValue.resetPersistence;
|
|
@@ -806,14 +875,24 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
806
875
|
const syncStateValue = getNodeValue(getNode(syncState$));
|
|
807
876
|
allSyncStates.set(syncState$, node);
|
|
808
877
|
syncStateValue.getPendingChanges = () => localState.pendingChanges;
|
|
809
|
-
let
|
|
810
|
-
const onGetError = (error, params) => {
|
|
878
|
+
let lastErrorHandled;
|
|
879
|
+
const onGetError = (error, params, noThrow) => {
|
|
811
880
|
var _a;
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
881
|
+
if (lastErrorHandled !== error) {
|
|
882
|
+
if (!params) {
|
|
883
|
+
params = {
|
|
884
|
+
source: "get",
|
|
885
|
+
type: "get",
|
|
886
|
+
retry: params
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
syncState$.error.set(error);
|
|
890
|
+
(_a = syncOptions.onError) == null ? void 0 : _a.call(syncOptions, error, params);
|
|
891
|
+
lastErrorHandled = error;
|
|
892
|
+
if (!noThrow) {
|
|
893
|
+
throw error;
|
|
894
|
+
}
|
|
815
895
|
}
|
|
816
|
-
errorHandled = true;
|
|
817
896
|
};
|
|
818
897
|
loadLocal(obs$, syncOptions, syncState$, localState);
|
|
819
898
|
let isWaitingForLoad = !!syncOptions.get;
|
|
@@ -823,30 +902,37 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
823
902
|
syncState$.isLoaded.set(!syncState$.numPendingRemoteLoads.peek());
|
|
824
903
|
let isSynced = false;
|
|
825
904
|
let isSubscribed = false;
|
|
905
|
+
let isApplyingPendingAfterSync = false;
|
|
826
906
|
let unsubscribe = void 0;
|
|
827
907
|
const applyPending = (pending) => {
|
|
828
908
|
if (pending && !isEmpty(pending)) {
|
|
829
|
-
localState.isApplyingPending = true;
|
|
830
909
|
const keys = Object.keys(pending);
|
|
910
|
+
const value = getNodeValue(node);
|
|
831
911
|
const changes = [];
|
|
832
912
|
for (let i = 0; i < keys.length; i++) {
|
|
833
913
|
const key = keys[i];
|
|
834
914
|
const path = key.split("/").filter((p2) => p2 !== "");
|
|
835
|
-
const { p,
|
|
836
|
-
|
|
915
|
+
const { p, t, v } = pending[key];
|
|
916
|
+
const valueAtPath = getValueAtPath(value, path);
|
|
917
|
+
if (isApplyingPendingAfterSync || !deepEqual(valueAtPath, v)) {
|
|
918
|
+
changes.push({ path, valueAtPath: v, prevAtPath: p, pathTypes: t });
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
if (changes.length > 0) {
|
|
922
|
+
localState.isApplyingPending = true;
|
|
923
|
+
onObsChange(obs$, syncState$, localState, syncOptions, {
|
|
924
|
+
value,
|
|
925
|
+
isFromPersist: false,
|
|
926
|
+
isFromSync: false,
|
|
927
|
+
getPrevious: createPreviousHandler(value, changes),
|
|
928
|
+
changes
|
|
929
|
+
});
|
|
930
|
+
localState.isApplyingPending = false;
|
|
837
931
|
}
|
|
838
|
-
const value = getNodeValue(node);
|
|
839
|
-
onObsChange(obs$, syncState$, localState, syncOptions, {
|
|
840
|
-
value,
|
|
841
|
-
isFromPersist: false,
|
|
842
|
-
isFromSync: false,
|
|
843
|
-
getPrevious: createPreviousHandler(value, changes),
|
|
844
|
-
changes
|
|
845
|
-
});
|
|
846
|
-
localState.isApplyingPending = false;
|
|
847
932
|
}
|
|
848
933
|
};
|
|
849
|
-
|
|
934
|
+
const { get, subscribe } = syncOptions;
|
|
935
|
+
if (get || subscribe) {
|
|
850
936
|
sync = async () => {
|
|
851
937
|
var _a;
|
|
852
938
|
if (isSynced && (!getNodeValue(getNode(syncState$)).isSyncEnabled || shouldIgnoreUnobserved(node, sync))) {
|
|
@@ -859,128 +945,154 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
859
945
|
}
|
|
860
946
|
const lastSync = (_a = metadatas.get(obs$)) == null ? void 0 : _a.lastSync;
|
|
861
947
|
const pending = localState.pendingChanges;
|
|
862
|
-
const
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
const
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
if (value
|
|
870
|
-
value =
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
const
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
} else {
|
|
887
|
-
value = v;
|
|
888
|
-
}
|
|
889
|
-
} else if (value[p[0]] !== void 0) {
|
|
890
|
-
const curValue = getValueAtPath(currentValue, p);
|
|
891
|
-
const newValue = getValueAtPath(value, p);
|
|
892
|
-
if (JSON.stringify(curValue) === JSON.stringify(newValue)) {
|
|
893
|
-
delete pending2[key];
|
|
894
|
-
didChangeMetadata = true;
|
|
895
|
-
} else {
|
|
896
|
-
const oldValue = clone(value);
|
|
897
|
-
pending2[key].p = getValueAtPath(oldValue, p);
|
|
898
|
-
value = setAtPath(
|
|
899
|
-
value,
|
|
900
|
-
p,
|
|
901
|
-
t,
|
|
902
|
-
v,
|
|
903
|
-
"merge",
|
|
904
|
-
obs$.peek(),
|
|
905
|
-
(path, value2) => {
|
|
906
|
-
delete pending2[key];
|
|
907
|
-
pending2[path.join("/")] = {
|
|
908
|
-
p: null,
|
|
909
|
-
v: value2,
|
|
910
|
-
t: t.slice(0, path.length)
|
|
911
|
-
};
|
|
912
|
-
}
|
|
913
|
-
);
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
});
|
|
917
|
-
if (didChangeMetadata && syncOptions.persist) {
|
|
918
|
-
updateMetadata(obs$, localState, syncState$, syncOptions, {
|
|
919
|
-
pending: pending2
|
|
920
|
-
});
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
onChangeRemote(() => {
|
|
924
|
-
if (isPlainObject(value)) {
|
|
925
|
-
value = ObservableHint.plain(value);
|
|
926
|
-
}
|
|
927
|
-
if (mode === "assign") {
|
|
928
|
-
obs$.assign(value);
|
|
929
|
-
} else if (mode === "append") {
|
|
930
|
-
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
|
|
931
|
-
console.error("[legend-state] mode:append expects the value to be an array");
|
|
948
|
+
const { waitFor } = syncOptions;
|
|
949
|
+
const runGet = () => {
|
|
950
|
+
var _a2;
|
|
951
|
+
const onChange = async ({ value, mode, lastSync: lastSync2 }) => {
|
|
952
|
+
mode = mode || syncOptions.mode || "set";
|
|
953
|
+
if (value !== void 0) {
|
|
954
|
+
value = transformLoadData(value, syncOptions, true, "get");
|
|
955
|
+
if (isPromise$1(value)) {
|
|
956
|
+
value = await value;
|
|
957
|
+
}
|
|
958
|
+
const pending2 = localState.pendingChanges;
|
|
959
|
+
const currentValue = obs$.peek();
|
|
960
|
+
if (pending2) {
|
|
961
|
+
let didChangeMetadata = false;
|
|
962
|
+
Object.keys(pending2).forEach((key) => {
|
|
963
|
+
const p = key.split("/").filter((k) => k !== "");
|
|
964
|
+
const { v, t } = pending2[key];
|
|
965
|
+
if (t.length === 0 || !value) {
|
|
966
|
+
const oldValue = clone2(value);
|
|
967
|
+
pending2[key].p = key ? oldValue[key] : oldValue;
|
|
968
|
+
if (isObject(value) && isObject(v)) {
|
|
969
|
+
Object.assign(value, key ? { [key]: v } : v);
|
|
970
|
+
} else if (!key) {
|
|
971
|
+
value = v;
|
|
932
972
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
973
|
+
} else if (value[p[0]] !== void 0) {
|
|
974
|
+
const curValue = getValueAtPath(currentValue, p);
|
|
975
|
+
const newValue = getValueAtPath(value, p);
|
|
976
|
+
if (JSON.stringify(curValue) === JSON.stringify(newValue)) {
|
|
977
|
+
delete pending2[key];
|
|
978
|
+
didChangeMetadata = true;
|
|
979
|
+
} else {
|
|
980
|
+
const oldValue = clone2(value);
|
|
981
|
+
pending2[key].p = getValueAtPath(oldValue, p);
|
|
982
|
+
didChangeMetadata = true;
|
|
983
|
+
value = setAtPath(
|
|
984
|
+
value,
|
|
985
|
+
p,
|
|
986
|
+
t,
|
|
987
|
+
v,
|
|
988
|
+
"merge",
|
|
989
|
+
obs$.peek(),
|
|
990
|
+
(path, value2) => {
|
|
991
|
+
delete pending2[key];
|
|
992
|
+
pending2[path.join("/")] = {
|
|
993
|
+
p: null,
|
|
994
|
+
v: value2,
|
|
995
|
+
t: t.slice(0, path.length)
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
);
|
|
937
999
|
}
|
|
938
|
-
obs$.splice(0, 0, ...value);
|
|
939
|
-
} else if (mode === "merge") {
|
|
940
|
-
mergeIntoObservable(obs$, value);
|
|
941
|
-
} else {
|
|
942
|
-
obs$.set(value);
|
|
943
1000
|
}
|
|
944
1001
|
});
|
|
1002
|
+
if (didChangeMetadata && syncOptions.persist) {
|
|
1003
|
+
updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
|
|
1004
|
+
pending: pending2
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
945
1007
|
}
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
1008
|
+
onChangeRemote2(() => {
|
|
1009
|
+
if (isPlainObject(value)) {
|
|
1010
|
+
value = ObservableHint.plain(value);
|
|
1011
|
+
}
|
|
1012
|
+
if (mode === "assign") {
|
|
1013
|
+
obs$.assign(value);
|
|
1014
|
+
} else if (mode === "append") {
|
|
1015
|
+
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
|
|
1016
|
+
console.error("[legend-state] mode:append expects the value to be an array");
|
|
1017
|
+
}
|
|
1018
|
+
obs$.push(...value);
|
|
1019
|
+
} else if (mode === "prepend") {
|
|
1020
|
+
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
|
|
1021
|
+
console.error("[legend-state] mode:prepend expects the value to be an array");
|
|
1022
|
+
}
|
|
1023
|
+
obs$.splice(0, 0, ...value);
|
|
1024
|
+
} else if (mode === "merge") {
|
|
1025
|
+
mergeIntoObservable(obs$, value);
|
|
1026
|
+
} else {
|
|
1027
|
+
obs$.set(value);
|
|
1028
|
+
}
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
if (lastSync2 && syncOptions.persist) {
|
|
1032
|
+
updateMetadata(obs$, localState, syncState$, syncOptions, {
|
|
1033
|
+
lastSync: lastSync2
|
|
1034
|
+
});
|
|
954
1035
|
}
|
|
955
|
-
|
|
956
|
-
|
|
1036
|
+
};
|
|
1037
|
+
if (node.activationState) {
|
|
1038
|
+
node.activationState.onChange = onChange;
|
|
1039
|
+
}
|
|
1040
|
+
if (!isSubscribed && syncOptions.subscribe) {
|
|
1041
|
+
const subscribe2 = syncOptions.subscribe;
|
|
1042
|
+
const doSubscribe = () => {
|
|
957
1043
|
isSubscribed = true;
|
|
958
|
-
const
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1044
|
+
const subscribeParams = {
|
|
1045
|
+
node,
|
|
1046
|
+
value$: obs$,
|
|
1047
|
+
lastSync,
|
|
1048
|
+
update: (params) => {
|
|
1049
|
+
when(
|
|
1050
|
+
() => !get || syncState$.isLoaded.get(),
|
|
1051
|
+
() => {
|
|
965
1052
|
when(waitFor || true, () => {
|
|
966
1053
|
params.mode || (params.mode = syncOptions.mode || "merge");
|
|
967
1054
|
onChange(params);
|
|
1055
|
+
if (!syncState$.isLoaded.peek()) {
|
|
1056
|
+
syncState$.assign({
|
|
1057
|
+
isLoaded: syncStateValue.numPendingRemoteLoads < 1,
|
|
1058
|
+
error: void 0,
|
|
1059
|
+
isGetting: syncStateValue.numPendingGets > 0
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
968
1062
|
});
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1063
|
+
}
|
|
1064
|
+
);
|
|
1065
|
+
},
|
|
1066
|
+
refresh: () => when(syncState$.isLoaded, sync),
|
|
1067
|
+
onError: (error) => onGetError(error, {
|
|
1068
|
+
source: "subscribe",
|
|
1069
|
+
subscribeParams,
|
|
1070
|
+
type: "get",
|
|
1071
|
+
retry: {}
|
|
1072
|
+
})
|
|
975
1073
|
};
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1074
|
+
unsubscribe = subscribe2(subscribeParams);
|
|
1075
|
+
registerMiddleware(node, "listeners-cleared", () => {
|
|
1076
|
+
if (unsubscribe) {
|
|
1077
|
+
isSubscribed = false;
|
|
1078
|
+
unsubscribe();
|
|
1079
|
+
unsubscribe = void 0;
|
|
1080
|
+
}
|
|
1081
|
+
});
|
|
1082
|
+
registerMiddleware(node, "listener-added", () => {
|
|
1083
|
+
if (!isSubscribed) {
|
|
1084
|
+
doSubscribe();
|
|
1085
|
+
}
|
|
1086
|
+
});
|
|
1087
|
+
};
|
|
1088
|
+
if (waitFor) {
|
|
1089
|
+
whenReady(waitFor, doSubscribe);
|
|
1090
|
+
} else {
|
|
1091
|
+
doSubscribe();
|
|
981
1092
|
}
|
|
982
|
-
|
|
983
|
-
|
|
1093
|
+
}
|
|
1094
|
+
const existingValue = getNodeValue(node);
|
|
1095
|
+
if (get) {
|
|
984
1096
|
const getParams = {
|
|
985
1097
|
node,
|
|
986
1098
|
value$: obs$,
|
|
@@ -990,7 +1102,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
990
1102
|
options: syncOptions,
|
|
991
1103
|
lastSync,
|
|
992
1104
|
updateLastSync: (lastSync2) => getParams.lastSync = lastSync2,
|
|
993
|
-
onError,
|
|
1105
|
+
onError: onGetError,
|
|
994
1106
|
retryNum: 0,
|
|
995
1107
|
cancelRetry: false
|
|
996
1108
|
};
|
|
@@ -1019,17 +1131,12 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
1019
1131
|
numPendingGets: (syncStateValue.numPendingGets || 0) + 1,
|
|
1020
1132
|
isGetting: true
|
|
1021
1133
|
});
|
|
1022
|
-
const got = runWithRetry(
|
|
1023
|
-
getParams
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
params.retryNum = retryEvent.retryNum;
|
|
1029
|
-
return get(params);
|
|
1030
|
-
},
|
|
1031
|
-
onError
|
|
1032
|
-
);
|
|
1134
|
+
const got = runWithRetry(getParams, syncOptions.retry, node, (retryEvent) => {
|
|
1135
|
+
const params = getParams;
|
|
1136
|
+
params.cancelRetry = retryEvent.cancelRetry;
|
|
1137
|
+
params.retryNum = retryEvent.retryNum;
|
|
1138
|
+
return get(params);
|
|
1139
|
+
});
|
|
1033
1140
|
const numGets = node.numGets = (node.numGets || 0) + 1;
|
|
1034
1141
|
const handle = (value) => {
|
|
1035
1142
|
syncState$.numPendingGets.set((v) => v - 1);
|
|
@@ -1056,33 +1163,33 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
1056
1163
|
});
|
|
1057
1164
|
};
|
|
1058
1165
|
if (isPromise$1(got)) {
|
|
1059
|
-
got.then(handle).catch(
|
|
1166
|
+
got.then(handle).catch((error) => {
|
|
1167
|
+
onGetError(error, { getParams, source: "get", type: "get", retry: getParams }, true);
|
|
1168
|
+
});
|
|
1060
1169
|
} else {
|
|
1061
1170
|
handle(got);
|
|
1062
1171
|
}
|
|
1063
1172
|
}
|
|
1064
|
-
};
|
|
1065
|
-
if (waitFor) {
|
|
1066
|
-
whenReady(waitFor, () => trackSelector(runGet, sync));
|
|
1067
|
-
} else {
|
|
1068
|
-
trackSelector(runGet, sync);
|
|
1069
1173
|
}
|
|
1174
|
+
};
|
|
1175
|
+
if (waitFor) {
|
|
1176
|
+
whenReady(waitFor, () => trackSelector(runGet, sync));
|
|
1070
1177
|
} else {
|
|
1071
|
-
|
|
1072
|
-
isLoaded: true,
|
|
1073
|
-
error: void 0
|
|
1074
|
-
});
|
|
1178
|
+
trackSelector(runGet, sync);
|
|
1075
1179
|
}
|
|
1076
1180
|
if (!isSynced) {
|
|
1077
1181
|
isSynced = true;
|
|
1078
|
-
|
|
1182
|
+
isApplyingPendingAfterSync = true;
|
|
1079
1183
|
applyPending(pending);
|
|
1184
|
+
isApplyingPendingAfterSync = false;
|
|
1080
1185
|
}
|
|
1081
1186
|
};
|
|
1082
1187
|
syncStateValue.sync = sync;
|
|
1083
1188
|
} else {
|
|
1084
1189
|
if (!isSynced) {
|
|
1190
|
+
isApplyingPendingAfterSync = true;
|
|
1085
1191
|
applyPending(localState.pendingChanges);
|
|
1192
|
+
isApplyingPendingAfterSync = false;
|
|
1086
1193
|
}
|
|
1087
1194
|
}
|
|
1088
1195
|
syncStateValue.reset = async () => {
|
|
@@ -1108,7 +1215,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
1108
1215
|
unsubscribe == null ? void 0 : unsubscribe();
|
|
1109
1216
|
unsubscribe = void 0;
|
|
1110
1217
|
const promise = syncStateValue.resetPersistence();
|
|
1111
|
-
|
|
1218
|
+
onChangeRemote2(() => {
|
|
1112
1219
|
var _a;
|
|
1113
1220
|
obs$.set((_a = syncOptions.initial) != null ? _a : void 0);
|
|
1114
1221
|
});
|
|
@@ -1130,7 +1237,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
1130
1237
|
return true;
|
|
1131
1238
|
};
|
|
1132
1239
|
when(onAllPersistLoaded, function() {
|
|
1133
|
-
if (syncOptions.get && syncOptions.syncMode === "auto") {
|
|
1240
|
+
if ((syncOptions.get || syncOptions.subscribe) && syncOptions.syncMode === "auto") {
|
|
1134
1241
|
sync();
|
|
1135
1242
|
}
|
|
1136
1243
|
if ((syncOptions == null ? void 0 : syncOptions.set) || (syncOptions == null ? void 0 : syncOptions.persist)) {
|
|
@@ -1213,9 +1320,10 @@ function configureSynced(fnOrOrigOptions, origOptions) {
|
|
|
1213
1320
|
}
|
|
1214
1321
|
|
|
1215
1322
|
// sync.ts
|
|
1216
|
-
var
|
|
1323
|
+
var internal5 = {
|
|
1217
1324
|
observableSyncConfiguration,
|
|
1218
|
-
waitForSet
|
|
1325
|
+
waitForSet,
|
|
1326
|
+
runWithRetry
|
|
1219
1327
|
};
|
|
1220
1328
|
|
|
1221
|
-
export { combineTransforms, configureObservableSync, configureSynced, deepEqual, diffObjects,
|
|
1329
|
+
export { combineTransforms, configureObservableSync, configureSynced, createRevertChanges, deepEqual, diffObjects, internal5 as internal, mapSyncPlugins, onChangeRemote2 as onChangeRemote, removeNullUndefined, syncObservable, synced, transformStringifyDates, transformStringifyKeys };
|