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