@legendapp/state 3.0.0-alpha.3 → 3.0.0-alpha.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/CHANGELOG.md +831 -1
- package/LICENSE +21 -1
- package/README.md +141 -1
- package/babel.js +0 -2
- package/babel.mjs +0 -2
- package/config/enable$GetSet.js +2 -1
- package/config/enable$GetSet.mjs +2 -1
- package/config/enableReactTracking.js +2 -1
- package/config/enableReactTracking.mjs +2 -1
- package/config/enableReactUse.js +2 -1
- package/config/enableReactUse.mjs +2 -1
- package/config/enable_PeekAssign.js +2 -1
- package/config/enable_PeekAssign.mjs +2 -1
- package/config.d.mts +13 -0
- package/config.d.ts +13 -0
- package/config.js +2052 -0
- package/config.mjs +2050 -0
- package/helpers/trackHistory.js +2 -2
- package/helpers/trackHistory.mjs +2 -2
- package/index.d.mts +21 -302
- package/index.d.ts +21 -302
- package/index.js +274 -318
- package/index.mjs +275 -317
- package/observableInterfaces-Dilj6F92.d.mts +282 -0
- package/observableInterfaces-Dilj6F92.d.ts +282 -0
- package/package.json +11 -1
- package/persist-plugins/async-storage.d.mts +6 -3
- package/persist-plugins/async-storage.d.ts +6 -3
- package/persist-plugins/async-storage.js +12 -4
- package/persist-plugins/async-storage.mjs +12 -5
- package/persist-plugins/indexeddb.d.mts +6 -4
- package/persist-plugins/indexeddb.d.ts +6 -4
- package/persist-plugins/indexeddb.js +16 -6
- package/persist-plugins/indexeddb.mjs +16 -7
- package/persist-plugins/mmkv.d.mts +5 -1
- package/persist-plugins/mmkv.d.ts +5 -1
- package/persist-plugins/mmkv.js +14 -5
- package/persist-plugins/mmkv.mjs +14 -6
- package/react.d.mts +18 -14
- package/react.d.ts +18 -14
- package/react.js +57 -32
- package/react.mjs +58 -33
- package/sync-plugins/_transformObjectFields.d.mts +31 -0
- package/sync-plugins/_transformObjectFields.d.ts +31 -0
- package/sync-plugins/_transformObjectFields.js +114 -0
- package/sync-plugins/_transformObjectFields.mjs +110 -0
- package/sync-plugins/crud.d.mts +15 -23
- package/sync-plugins/crud.d.ts +15 -23
- package/sync-plugins/crud.js +213 -134
- package/sync-plugins/crud.mjs +214 -135
- package/sync-plugins/fetch.js +12 -8
- package/sync-plugins/fetch.mjs +13 -9
- package/sync-plugins/firebase.d.mts +26 -0
- package/sync-plugins/firebase.d.ts +26 -0
- package/sync-plugins/firebase.js +373 -0
- package/sync-plugins/firebase.mjs +368 -0
- package/sync-plugins/keel.d.mts +27 -10
- package/sync-plugins/keel.d.ts +27 -10
- package/sync-plugins/keel.js +40 -21
- package/sync-plugins/keel.mjs +40 -21
- package/sync-plugins/supabase.d.mts +12 -7
- package/sync-plugins/supabase.d.ts +12 -7
- package/sync-plugins/supabase.js +24 -13
- package/sync-plugins/supabase.mjs +25 -14
- package/sync-plugins/tanstack-query.d.mts +2 -2
- package/sync-plugins/tanstack-query.d.ts +2 -2
- package/sync-plugins/tanstack-query.js +3 -2
- package/sync-plugins/tanstack-query.mjs +3 -2
- package/sync-plugins/tanstack-react-query.d.mts +1 -1
- package/sync-plugins/tanstack-react-query.d.ts +1 -1
- package/sync.d.mts +68 -197
- package/sync.d.ts +68 -197
- package/sync.js +448 -283
- package/sync.mjs +454 -289
- package/types/babel.d.ts +12 -1
- package/.DS_Store +0 -0
- /package/config/{enable_GetSet.d.mts → enable$GetSet.d.mts} +0 -0
- /package/config/{enable_GetSet.d.ts → enable$GetSet.d.ts} +0 -0
package/sync.mjs
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import { isObject, isDate, isNullOrUndefined, isString, endBatch, beginBatch, isFunction,
|
|
2
|
-
|
|
3
|
-
// sync.ts
|
|
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, isArray } from '@legendapp/state';
|
|
4
2
|
|
|
5
3
|
// src/sync/configureObservableSync.ts
|
|
6
4
|
var observableSyncConfiguration = {};
|
|
@@ -137,41 +135,81 @@ function transformStringifyDates(...args) {
|
|
|
137
135
|
}
|
|
138
136
|
};
|
|
139
137
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
mode: params.mode
|
|
153
|
-
});
|
|
154
|
-
params.onGet();
|
|
155
|
-
} catch (e) {
|
|
156
|
-
}
|
|
157
|
-
};
|
|
138
|
+
|
|
139
|
+
// src/is.ts
|
|
140
|
+
function isPromise(obj) {
|
|
141
|
+
return obj instanceof Promise;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/sync/retry.ts
|
|
145
|
+
function calculateRetryDelay(retryOptions, retryNum) {
|
|
146
|
+
const { backoff, delay = 1e3, infinite, times = 3, maxDelay = 3e4 } = retryOptions;
|
|
147
|
+
if (infinite || retryNum < times) {
|
|
148
|
+
const delayTime = Math.min(delay * (backoff === "constant" ? 1 : 2 ** retryNum), maxDelay);
|
|
149
|
+
return delayTime;
|
|
158
150
|
}
|
|
159
|
-
|
|
160
|
-
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
function createRetryTimeout(retryOptions, retryNum, fn) {
|
|
154
|
+
const delayTime = calculateRetryDelay(retryOptions, retryNum);
|
|
155
|
+
if (delayTime) {
|
|
156
|
+
return setTimeout(fn, delayTime);
|
|
157
|
+
} else {
|
|
158
|
+
return false;
|
|
161
159
|
}
|
|
162
|
-
|
|
160
|
+
}
|
|
161
|
+
var mapRetryTimeouts = /* @__PURE__ */ new Map();
|
|
162
|
+
function runWithRetry(state, retryOptions, fn, onError) {
|
|
163
|
+
let value = fn(state);
|
|
164
|
+
if (isPromise(value) && retryOptions) {
|
|
165
|
+
let timeoutRetry;
|
|
166
|
+
if (mapRetryTimeouts.has(state.node)) {
|
|
167
|
+
clearTimeout(mapRetryTimeouts.get(state.node));
|
|
168
|
+
}
|
|
169
|
+
return new Promise((resolve, reject) => {
|
|
170
|
+
const run = () => {
|
|
171
|
+
value.then((val) => {
|
|
172
|
+
resolve(val);
|
|
173
|
+
}).catch((error) => {
|
|
174
|
+
state.retryNum++;
|
|
175
|
+
if (timeoutRetry) {
|
|
176
|
+
clearTimeout(timeoutRetry);
|
|
177
|
+
}
|
|
178
|
+
if (onError) {
|
|
179
|
+
onError(error);
|
|
180
|
+
}
|
|
181
|
+
if (!state.cancelRetry) {
|
|
182
|
+
const timeout = createRetryTimeout(retryOptions, state.retryNum, () => {
|
|
183
|
+
value = fn(state);
|
|
184
|
+
run();
|
|
185
|
+
});
|
|
186
|
+
if (timeout === false) {
|
|
187
|
+
state.cancelRetry = true;
|
|
188
|
+
reject(error);
|
|
189
|
+
} else {
|
|
190
|
+
mapRetryTimeouts.set(state.node, timeout);
|
|
191
|
+
timeoutRetry = timeout;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
};
|
|
196
|
+
run();
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return value;
|
|
163
200
|
}
|
|
164
201
|
|
|
165
202
|
// src/sync/syncObservable.ts
|
|
166
|
-
var {
|
|
203
|
+
var { clone, deepMerge, getNode, getNodeValue, getValueAtPath, globalState, symbolLinked, createPreviousHandler } = internal;
|
|
167
204
|
var mapSyncPlugins = /* @__PURE__ */ new WeakMap();
|
|
205
|
+
var allSyncStates = /* @__PURE__ */ new Map();
|
|
168
206
|
var metadatas = /* @__PURE__ */ new WeakMap();
|
|
169
207
|
var promisesLocalSaves = /* @__PURE__ */ new Set();
|
|
170
208
|
function parseLocalConfig(config) {
|
|
171
209
|
return config ? isString(config) ? { table: config, config: { name: config } } : { table: config.name, config } : {};
|
|
172
210
|
}
|
|
173
211
|
function doInOrder(arg1, arg2) {
|
|
174
|
-
return isPromise(arg1) ? arg1.then(arg2) : arg2(arg1);
|
|
212
|
+
return isPromise$1(arg1) ? arg1.then(arg2) : arg2(arg1);
|
|
175
213
|
}
|
|
176
214
|
function onChangeRemote(cb) {
|
|
177
215
|
endBatch(true);
|
|
@@ -181,13 +219,19 @@ function onChangeRemote(cb) {
|
|
|
181
219
|
globalState.isLoadingRemote = false;
|
|
182
220
|
endBatch(true);
|
|
183
221
|
}
|
|
184
|
-
function transformSaveData(value, path, pathTypes, { transform }) {
|
|
222
|
+
async function transformSaveData(value, path, pathTypes, { transform }) {
|
|
185
223
|
if (transform == null ? void 0 : transform.save) {
|
|
186
224
|
const constructed = constructObjectWithPath(path, pathTypes, value);
|
|
187
|
-
const saved = transform.save(constructed);
|
|
188
|
-
value =
|
|
225
|
+
const saved = await transform.save(constructed);
|
|
226
|
+
value = saved;
|
|
227
|
+
const outPath = [];
|
|
228
|
+
for (let i = 0; i < path.length; i++) {
|
|
229
|
+
outPath[i] = Object.keys(value)[0];
|
|
230
|
+
value = value[outPath[i]];
|
|
231
|
+
}
|
|
232
|
+
path = outPath;
|
|
189
233
|
}
|
|
190
|
-
return value;
|
|
234
|
+
return { value, path };
|
|
191
235
|
}
|
|
192
236
|
function transformLoadData(value, { transform }, doUserTransform, method) {
|
|
193
237
|
if (doUserTransform && (transform == null ? void 0 : transform.load)) {
|
|
@@ -195,7 +239,7 @@ function transformLoadData(value, { transform }, doUserTransform, method) {
|
|
|
195
239
|
}
|
|
196
240
|
return value;
|
|
197
241
|
}
|
|
198
|
-
async function updateMetadataImmediate(value$, localState,
|
|
242
|
+
async function updateMetadataImmediate(value$, localState, syncState2, syncOptions, newMetadata) {
|
|
199
243
|
const saves = Array.from(promisesLocalSaves);
|
|
200
244
|
if (saves.length > 0) {
|
|
201
245
|
await Promise.all(saves);
|
|
@@ -210,17 +254,17 @@ async function updateMetadataImmediate(value$, localState, syncState, syncOption
|
|
|
210
254
|
await pluginPersist.setMetadata(table, metadata, config);
|
|
211
255
|
}
|
|
212
256
|
if (lastSync) {
|
|
213
|
-
|
|
257
|
+
syncState2.assign({
|
|
214
258
|
lastSync
|
|
215
259
|
});
|
|
216
260
|
}
|
|
217
261
|
}
|
|
218
|
-
function updateMetadata(value$, localState,
|
|
262
|
+
function updateMetadata(value$, localState, syncState2, syncOptions, newMetadata) {
|
|
219
263
|
if (localState.timeoutSaveMetadata) {
|
|
220
264
|
clearTimeout(localState.timeoutSaveMetadata);
|
|
221
265
|
}
|
|
222
266
|
localState.timeoutSaveMetadata = setTimeout(
|
|
223
|
-
() => updateMetadataImmediate(value$, localState,
|
|
267
|
+
() => updateMetadataImmediate(value$, localState, syncState2, syncOptions, newMetadata),
|
|
224
268
|
0
|
|
225
269
|
);
|
|
226
270
|
}
|
|
@@ -248,26 +292,21 @@ function mergeChanges(changes) {
|
|
|
248
292
|
return changesOut;
|
|
249
293
|
}
|
|
250
294
|
function mergeQueuedChanges(allChanges) {
|
|
251
|
-
const
|
|
252
|
-
const
|
|
253
|
-
const previousByObs = /* @__PURE__ */ new Map();
|
|
295
|
+
const changesByOptionsRemote = /* @__PURE__ */ new Map();
|
|
296
|
+
const changesByOptionsLocal = /* @__PURE__ */ new Map();
|
|
254
297
|
const outRemote = /* @__PURE__ */ new Map();
|
|
255
298
|
const outLocal = /* @__PURE__ */ new Map();
|
|
256
299
|
for (let i = 0; i < allChanges.length; i++) {
|
|
257
300
|
const value = allChanges[i];
|
|
258
|
-
const {
|
|
301
|
+
const { changes, inRemoteChange, syncOptions } = value;
|
|
259
302
|
const targetMap = inRemoteChange ? outRemote : outLocal;
|
|
260
|
-
const changesMap = inRemoteChange ?
|
|
261
|
-
const existing = changesMap.get(
|
|
303
|
+
const changesMap = inRemoteChange ? changesByOptionsRemote : changesByOptionsLocal;
|
|
304
|
+
const existing = changesMap.get(syncOptions);
|
|
262
305
|
const newChanges = existing ? [...existing, ...changes] : changes;
|
|
263
306
|
const merged = mergeChanges(newChanges);
|
|
264
|
-
changesMap.set(
|
|
307
|
+
changesMap.set(syncOptions, merged);
|
|
265
308
|
value.changes = merged;
|
|
266
|
-
|
|
267
|
-
previousByObs.set(obs, getPrevious());
|
|
268
|
-
}
|
|
269
|
-
value.valuePrevious = previousByObs.get(obs);
|
|
270
|
-
targetMap.set(obs, value);
|
|
309
|
+
targetMap.set(syncOptions, value);
|
|
271
310
|
}
|
|
272
311
|
return Array.from(outRemote.values()).concat(Array.from(outLocal.values()));
|
|
273
312
|
}
|
|
@@ -313,15 +352,13 @@ async function processQueuedRemoteChanges(syncOptions) {
|
|
|
313
352
|
}
|
|
314
353
|
}
|
|
315
354
|
async function prepChangeLocal(queuedChange) {
|
|
316
|
-
const { syncState, changes,
|
|
355
|
+
const { syncState: syncState2, changes, syncOptions, inRemoteChange, isApplyingPending } = queuedChange;
|
|
317
356
|
const persist = syncOptions.persist;
|
|
318
|
-
const { pluginSync } = localState;
|
|
319
357
|
const { config: configLocal } = parseLocalConfig(persist);
|
|
320
|
-
const
|
|
321
|
-
const
|
|
322
|
-
const saveRemote = !!(!inRemoteChange && (pluginSync == null ? void 0 : pluginSync.set) && (configRemote == null ? void 0 : configRemote.enableSync) !== false && syncState.isSyncEnabled.peek());
|
|
358
|
+
const saveLocal = (persist == null ? void 0 : persist.name) && !configLocal.readonly && !isApplyingPending && syncState2.isPersistEnabled.peek();
|
|
359
|
+
const saveRemote = !!(!inRemoteChange && (syncOptions == null ? void 0 : syncOptions.set) && syncState2.isSyncEnabled.peek());
|
|
323
360
|
if (saveLocal || saveRemote) {
|
|
324
|
-
if (saveLocal && !
|
|
361
|
+
if (saveLocal && !syncState2.isPersistLoaded.peek()) {
|
|
325
362
|
console.error(
|
|
326
363
|
"[legend-state] WARNING: An observable was changed before being loaded from persist",
|
|
327
364
|
persist
|
|
@@ -354,13 +391,13 @@ async function prepChangeLocal(queuedChange) {
|
|
|
354
391
|
configLocal
|
|
355
392
|
);
|
|
356
393
|
promisesTransform.push(
|
|
357
|
-
doInOrder(promiseTransformLocal, (valueTransformed) => {
|
|
394
|
+
doInOrder(promiseTransformLocal, ({ value: valueTransformed, path: pathTransformed }) => {
|
|
358
395
|
changesLocal.push({
|
|
359
|
-
path,
|
|
396
|
+
path: pathTransformed,
|
|
360
397
|
pathTypes,
|
|
361
398
|
prevAtPath,
|
|
362
399
|
valueAtPath: valueTransformed,
|
|
363
|
-
pathStr
|
|
400
|
+
pathStr: path === pathTransformed ? pathStr : pathTransformed.join("/")
|
|
364
401
|
});
|
|
365
402
|
})
|
|
366
403
|
);
|
|
@@ -376,22 +413,19 @@ async function prepChangeLocal(queuedChange) {
|
|
|
376
413
|
}
|
|
377
414
|
async function prepChangeRemote(queuedChange) {
|
|
378
415
|
const {
|
|
379
|
-
syncState,
|
|
416
|
+
syncState: syncState2,
|
|
380
417
|
changes,
|
|
381
418
|
localState,
|
|
382
419
|
syncOptions,
|
|
383
420
|
inRemoteChange,
|
|
384
|
-
isApplyingPending
|
|
385
|
-
valuePrevious
|
|
421
|
+
isApplyingPending
|
|
386
422
|
} = queuedChange;
|
|
387
423
|
const persist = syncOptions.persist;
|
|
388
|
-
const { pluginSync } = localState;
|
|
389
424
|
const { config: configLocal } = parseLocalConfig(persist);
|
|
390
|
-
const
|
|
391
|
-
const
|
|
392
|
-
const saveRemote = !inRemoteChange && (pluginSync == null ? void 0 : pluginSync.set) && (configRemote == null ? void 0 : configRemote.enableSync) !== false && syncState.isSyncEnabled.peek();
|
|
425
|
+
const saveLocal = persist && !configLocal.readonly && !isApplyingPending && syncState2.isPersistEnabled.peek();
|
|
426
|
+
const saveRemote = !inRemoteChange && (syncOptions == null ? void 0 : syncOptions.set) && syncState2.isSyncEnabled.peek();
|
|
393
427
|
if (saveLocal || saveRemote) {
|
|
394
|
-
if (saveLocal && !
|
|
428
|
+
if (saveLocal && !syncState2.isPersistLoaded.peek()) {
|
|
395
429
|
console.error(
|
|
396
430
|
"[legend-state] WARNING: An observable was changed before being loaded from persist",
|
|
397
431
|
persist
|
|
@@ -421,20 +455,20 @@ async function prepChangeRemote(queuedChange) {
|
|
|
421
455
|
valueAtPath,
|
|
422
456
|
path,
|
|
423
457
|
pathTypes,
|
|
424
|
-
|
|
458
|
+
syncOptions || {}
|
|
425
459
|
);
|
|
426
460
|
promisesTransform.push(
|
|
427
|
-
doInOrder(promiseTransformRemote, (valueTransformed) => {
|
|
461
|
+
doInOrder(promiseTransformRemote, ({ value: valueTransformed, path: pathTransformed }) => {
|
|
428
462
|
var _a;
|
|
429
463
|
if (!localState.pendingChanges) {
|
|
430
464
|
localState.pendingChanges = {};
|
|
431
465
|
}
|
|
432
466
|
let found2 = false;
|
|
433
|
-
for (let i2 = 0; !found2 && i2 <
|
|
434
|
-
const pathParent =
|
|
467
|
+
for (let i2 = 0; !found2 && i2 < pathTransformed.length - 1; i2++) {
|
|
468
|
+
const pathParent = pathTransformed.slice(0, i2 + 1).join("/");
|
|
435
469
|
if ((_a = localState.pendingChanges[pathParent]) == null ? void 0 : _a.v) {
|
|
436
470
|
found2 = true;
|
|
437
|
-
const pathChild =
|
|
471
|
+
const pathChild = pathTransformed.slice(i2 + 1);
|
|
438
472
|
const pathTypesChild = pathTypes.slice(i2 + 1);
|
|
439
473
|
setAtPath(
|
|
440
474
|
localState.pendingChanges[pathParent].v,
|
|
@@ -456,12 +490,11 @@ async function prepChangeRemote(queuedChange) {
|
|
|
456
490
|
localState.pendingChanges[pathStr].v = valueAtPath;
|
|
457
491
|
}
|
|
458
492
|
changesRemote.push({
|
|
459
|
-
path,
|
|
493
|
+
path: pathTransformed,
|
|
460
494
|
pathTypes,
|
|
461
495
|
prevAtPath,
|
|
462
496
|
valueAtPath: valueTransformed,
|
|
463
|
-
pathStr
|
|
464
|
-
valuePrevious
|
|
497
|
+
pathStr
|
|
465
498
|
});
|
|
466
499
|
})
|
|
467
500
|
);
|
|
@@ -479,24 +512,27 @@ async function doChangeLocal(changeInfo) {
|
|
|
479
512
|
if (!changeInfo)
|
|
480
513
|
return;
|
|
481
514
|
const { queuedChange, changesLocal, saveRemote } = changeInfo;
|
|
482
|
-
const { value$: obs, syncState, localState, syncOptions } = queuedChange;
|
|
515
|
+
const { value$: obs, syncState: syncState2, localState, syncOptions } = queuedChange;
|
|
483
516
|
const { pluginPersist } = localState;
|
|
484
517
|
const persist = syncOptions.persist;
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
if (changesLocal.length > 0) {
|
|
493
|
-
let promiseSet = pluginPersist.set(table, changesLocal, configLocal);
|
|
494
|
-
if (promiseSet) {
|
|
495
|
-
promiseSet = promiseSet.then(() => {
|
|
496
|
-
promisesLocalSaves.delete(promiseSet);
|
|
518
|
+
const saveLocal = !!(persist == null ? void 0 : persist.name);
|
|
519
|
+
if (saveLocal) {
|
|
520
|
+
const { table, config: configLocal } = parseLocalConfig(persist);
|
|
521
|
+
const shouldSaveMetadata = persist == null ? void 0 : persist.retrySync;
|
|
522
|
+
if (saveRemote && shouldSaveMetadata) {
|
|
523
|
+
await updateMetadataImmediate(obs, localState, syncState2, syncOptions, {
|
|
524
|
+
pending: localState.pendingChanges
|
|
497
525
|
});
|
|
498
|
-
|
|
499
|
-
|
|
526
|
+
}
|
|
527
|
+
if (changesLocal.length > 0) {
|
|
528
|
+
let promiseSet = pluginPersist.set(table, changesLocal, configLocal);
|
|
529
|
+
if (promiseSet) {
|
|
530
|
+
promiseSet = promiseSet.then(() => {
|
|
531
|
+
promisesLocalSaves.delete(promiseSet);
|
|
532
|
+
});
|
|
533
|
+
promisesLocalSaves.add(promiseSet);
|
|
534
|
+
await promiseSet;
|
|
535
|
+
}
|
|
500
536
|
}
|
|
501
537
|
}
|
|
502
538
|
}
|
|
@@ -505,47 +541,99 @@ async function doChangeRemote(changeInfo) {
|
|
|
505
541
|
if (!changeInfo)
|
|
506
542
|
return;
|
|
507
543
|
const { queuedChange, changesRemote } = changeInfo;
|
|
508
|
-
const { value$: obs
|
|
509
|
-
const { pluginPersist
|
|
544
|
+
const { value$: obs$, syncState: syncState2, localState, syncOptions } = queuedChange;
|
|
545
|
+
const { pluginPersist } = localState;
|
|
546
|
+
const node = getNode(obs$);
|
|
547
|
+
const state$ = node.state;
|
|
510
548
|
const persist = syncOptions.persist;
|
|
511
549
|
const { table, config: configLocal } = parseLocalConfig(persist);
|
|
512
|
-
const {
|
|
550
|
+
const { onBeforeSet, waitForSet, onAfterSet } = syncOptions || {};
|
|
513
551
|
const shouldSaveMetadata = persist == null ? void 0 : persist.retrySync;
|
|
552
|
+
const saveLocal = !!(persist == null ? void 0 : persist.name);
|
|
514
553
|
if (changesRemote.length > 0) {
|
|
515
|
-
|
|
554
|
+
if (!syncState2.isLoaded.peek()) {
|
|
555
|
+
await when(syncState2.isLoaded);
|
|
556
|
+
const pending = localState.pendingChanges;
|
|
557
|
+
if (pending) {
|
|
558
|
+
changesRemote.forEach((change) => {
|
|
559
|
+
const key = change.pathStr;
|
|
560
|
+
const pendingAtPath = pending[key];
|
|
561
|
+
if (!isNullOrUndefined(pendingAtPath)) {
|
|
562
|
+
const { p } = pendingAtPath;
|
|
563
|
+
change.prevAtPath = p;
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
}
|
|
516
568
|
if (waitForSet) {
|
|
517
|
-
const
|
|
518
|
-
if (
|
|
519
|
-
await when(
|
|
569
|
+
const waitFn = isFunction(waitForSet) ? waitForSet({ changes: changesRemote, value: obs$.peek() }) : waitForSet;
|
|
570
|
+
if (waitFn) {
|
|
571
|
+
await when(waitFn);
|
|
520
572
|
}
|
|
521
573
|
}
|
|
522
|
-
let value = obs
|
|
574
|
+
let value = clone(obs$.peek());
|
|
523
575
|
const transformSave = (_a = syncOptions == null ? void 0 : syncOptions.transform) == null ? void 0 : _a.save;
|
|
524
576
|
if (transformSave) {
|
|
525
|
-
value = transformSave(
|
|
577
|
+
value = transformSave(value);
|
|
526
578
|
}
|
|
579
|
+
state$.numPendingSets.set((v) => (v || 0) + 1);
|
|
580
|
+
state$.isSetting.set(true);
|
|
527
581
|
onBeforeSet == null ? void 0 : onBeforeSet();
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
582
|
+
let updateResult = void 0;
|
|
583
|
+
const onError = (error) => {
|
|
584
|
+
var _a2;
|
|
585
|
+
state$.error.set(error);
|
|
586
|
+
(_a2 = syncOptions.onSetError) == null ? void 0 : _a2.call(syncOptions, error, {
|
|
587
|
+
setParams,
|
|
588
|
+
source: "set",
|
|
589
|
+
value$: obs$
|
|
590
|
+
});
|
|
591
|
+
};
|
|
592
|
+
const setParams = {
|
|
593
|
+
node,
|
|
594
|
+
value$: obs$,
|
|
533
595
|
changes: changesRemote,
|
|
534
596
|
value,
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
597
|
+
onError,
|
|
598
|
+
update: (params) => {
|
|
599
|
+
if (updateResult) {
|
|
600
|
+
const { value: value2, lastSync, mode } = params;
|
|
601
|
+
updateResult = {
|
|
602
|
+
lastSync: Math.max(updateResult.lastSync || 0, lastSync || 0),
|
|
603
|
+
value: deepMerge(updateResult.value, value2),
|
|
604
|
+
mode
|
|
605
|
+
};
|
|
606
|
+
} else {
|
|
607
|
+
updateResult = params;
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
refresh: syncState2.sync,
|
|
611
|
+
retryNum: 0,
|
|
612
|
+
cancelRetry: false
|
|
613
|
+
};
|
|
614
|
+
let savedPromise = runWithRetry(
|
|
615
|
+
setParams,
|
|
616
|
+
syncOptions.retry,
|
|
617
|
+
async () => {
|
|
618
|
+
return syncOptions.set(setParams);
|
|
619
|
+
},
|
|
620
|
+
onError
|
|
621
|
+
);
|
|
622
|
+
let didError = false;
|
|
623
|
+
if (isPromise$1(savedPromise)) {
|
|
624
|
+
savedPromise = savedPromise.catch((error) => {
|
|
625
|
+
didError = true;
|
|
626
|
+
onError(error);
|
|
627
|
+
});
|
|
628
|
+
await savedPromise;
|
|
539
629
|
}
|
|
540
|
-
|
|
541
|
-
localState.numSavesOutstanding--;
|
|
542
|
-
if (saved !== void 0) {
|
|
630
|
+
if (!didError) {
|
|
543
631
|
const pathStrs = Array.from(new Set(changesRemote.map((change) => change.pathStr)));
|
|
544
|
-
const { changes, lastSync } =
|
|
632
|
+
const { value: changes, lastSync } = updateResult || {};
|
|
545
633
|
if (pathStrs.length > 0) {
|
|
546
634
|
let transformedChanges = void 0;
|
|
547
635
|
const metadata = {};
|
|
548
|
-
if (
|
|
636
|
+
if (saveLocal) {
|
|
549
637
|
const pendingMetadata = (_b = pluginPersist.getMetadata(table, configLocal)) == null ? void 0 : _b.pending;
|
|
550
638
|
const pending = localState.pendingChanges;
|
|
551
639
|
for (let i = 0; i < pathStrs.length; i++) {
|
|
@@ -565,42 +653,31 @@ async function doChangeRemote(changeInfo) {
|
|
|
565
653
|
if (changes && !isEmpty(changes)) {
|
|
566
654
|
transformedChanges = transformLoadData(changes, syncOptions, false, "set");
|
|
567
655
|
}
|
|
568
|
-
if (
|
|
569
|
-
if (transformedChanges) {
|
|
570
|
-
|
|
571
|
-
localState.pendingSaveResults = [];
|
|
572
|
-
}
|
|
573
|
-
localState.pendingSaveResults.push(transformedChanges);
|
|
656
|
+
if (transformedChanges !== void 0) {
|
|
657
|
+
if (isPromise$1(transformedChanges)) {
|
|
658
|
+
transformedChanges = await transformedChanges;
|
|
574
659
|
}
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
)
|
|
579
|
-
|
|
580
|
-
if (allChanges.some((change) => isPromise(change))) {
|
|
581
|
-
allChanges = await Promise.all(allChanges);
|
|
582
|
-
}
|
|
583
|
-
onChangeRemote(() => mergeIntoObservable(obs, ...allChanges));
|
|
584
|
-
}
|
|
585
|
-
if (persist) {
|
|
586
|
-
if (shouldSaveMetadata && !isEmpty(metadata)) {
|
|
587
|
-
updateMetadata(obs, localState, syncState, syncOptions, metadata);
|
|
588
|
-
}
|
|
660
|
+
onChangeRemote(() => mergeIntoObservable(obs$, transformedChanges));
|
|
661
|
+
}
|
|
662
|
+
if (saveLocal) {
|
|
663
|
+
if (shouldSaveMetadata && !isEmpty(metadata)) {
|
|
664
|
+
updateMetadata(obs$, localState, syncState2, syncOptions, metadata);
|
|
589
665
|
}
|
|
590
|
-
localState.pendingSaveResults = [];
|
|
591
666
|
}
|
|
592
|
-
onAfterSet == null ? void 0 : onAfterSet();
|
|
593
667
|
}
|
|
668
|
+
state$.numPendingSets.set((v) => v - 1);
|
|
669
|
+
state$.isSetting.set(state$.numPendingSets.peek() > 0);
|
|
670
|
+
onAfterSet == null ? void 0 : onAfterSet();
|
|
594
671
|
}
|
|
595
672
|
}
|
|
596
673
|
}
|
|
597
|
-
function onObsChange(value$,
|
|
598
|
-
if (!
|
|
599
|
-
const inRemoteChange =
|
|
674
|
+
function onObsChange(value$, syncState2, localState, syncOptions, { changes, isFromPersist, isFromSync, getPrevious }) {
|
|
675
|
+
if (!isFromPersist) {
|
|
676
|
+
const inRemoteChange = isFromSync;
|
|
600
677
|
const isApplyingPending = localState.isApplyingPending;
|
|
601
678
|
_queuedChanges.push({
|
|
602
679
|
value$,
|
|
603
|
-
syncState,
|
|
680
|
+
syncState: syncState2,
|
|
604
681
|
localState,
|
|
605
682
|
syncOptions,
|
|
606
683
|
changes,
|
|
@@ -613,13 +690,17 @@ function onObsChange(value$, syncState, localState, syncOptions, { changes, load
|
|
|
613
690
|
}
|
|
614
691
|
}
|
|
615
692
|
}
|
|
616
|
-
async function loadLocal(value$, syncOptions, syncState
|
|
693
|
+
async function loadLocal(value$, syncOptions, syncState$, localState) {
|
|
617
694
|
var _a, _b, _c;
|
|
618
695
|
const { persist } = syncOptions;
|
|
619
|
-
|
|
696
|
+
const node = getNode(value$);
|
|
697
|
+
const nodeValue = getNodeValue(getNode(node.state));
|
|
698
|
+
const syncStateValue = syncState$.peek();
|
|
699
|
+
const prevClearPersist = nodeValue.clearPersist;
|
|
700
|
+
if (persist == null ? void 0 : persist.name) {
|
|
620
701
|
const PersistPlugin = persist.plugin || ((_a = observableSyncConfiguration.persist) == null ? void 0 : _a.plugin);
|
|
621
702
|
const { table, config } = parseLocalConfig(persist);
|
|
622
|
-
|
|
703
|
+
syncStateValue.numPendingLocalLoads = (syncStateValue.numPendingLocalLoads || 0) + 1;
|
|
623
704
|
if (!PersistPlugin) {
|
|
624
705
|
throw new Error("Local persist is not configured");
|
|
625
706
|
}
|
|
@@ -629,7 +710,7 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
|
|
|
629
710
|
mapSyncPlugins.set(PersistPlugin, mapValue);
|
|
630
711
|
if (persistPlugin2.initialize) {
|
|
631
712
|
const initializePromise = (_c = persistPlugin2.initialize) == null ? void 0 : _c.call(persistPlugin2, ((_b = observableSyncConfiguration) == null ? void 0 : _b.persist) || {});
|
|
632
|
-
if (isPromise(initializePromise)) {
|
|
713
|
+
if (isPromise$1(initializePromise)) {
|
|
633
714
|
await initializePromise;
|
|
634
715
|
}
|
|
635
716
|
}
|
|
@@ -653,14 +734,14 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
|
|
|
653
734
|
if (metadata) {
|
|
654
735
|
metadatas.set(value$, metadata);
|
|
655
736
|
localState.pendingChanges = metadata.pending;
|
|
656
|
-
syncState
|
|
737
|
+
syncState$.assign({
|
|
657
738
|
lastSync: metadata.lastSync
|
|
658
739
|
});
|
|
659
740
|
}
|
|
660
741
|
if (value !== void 0) {
|
|
661
742
|
const { transform } = config;
|
|
662
743
|
value = transformLoadData(value, { transform }, true, "get");
|
|
663
|
-
if (isPromise(value)) {
|
|
744
|
+
if (isPromise$1(value)) {
|
|
664
745
|
value = await value;
|
|
665
746
|
}
|
|
666
747
|
internal.globalState.isLoadingLocal = true;
|
|
@@ -671,12 +752,18 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
|
|
|
671
752
|
}
|
|
672
753
|
internal.globalState.isLoadingLocal = false;
|
|
673
754
|
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
755
|
+
syncStateValue.numPendingLocalLoads--;
|
|
756
|
+
nodeValue.clearPersist = () => Promise.all(
|
|
757
|
+
[
|
|
758
|
+
prevClearPersist,
|
|
759
|
+
persistPlugin.deleteTable(table, config),
|
|
760
|
+
persistPlugin.deleteMetadata(table, config)
|
|
761
|
+
].filter(Boolean)
|
|
762
|
+
);
|
|
763
|
+
} else {
|
|
764
|
+
nodeValue.clearPersist = () => prevClearPersist == null ? void 0 : prevClearPersist();
|
|
678
765
|
}
|
|
679
|
-
syncState
|
|
766
|
+
syncState$.isPersistLoaded.set(!(syncStateValue.numPendingLocalLoads > 0));
|
|
680
767
|
}
|
|
681
768
|
function syncObservable(obs$, syncOptionsOrSynced) {
|
|
682
769
|
let syncOptions = syncOptionsOrSynced;
|
|
@@ -687,7 +774,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
687
774
|
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && (!obs$ || !node)) {
|
|
688
775
|
throw new Error("[legend-state] syncObservable called with undefined observable");
|
|
689
776
|
}
|
|
690
|
-
syncOptions =
|
|
777
|
+
syncOptions = deepMerge(
|
|
691
778
|
{
|
|
692
779
|
syncMode: "auto"
|
|
693
780
|
},
|
|
@@ -696,24 +783,50 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
696
783
|
);
|
|
697
784
|
const localState = {};
|
|
698
785
|
let sync;
|
|
699
|
-
const syncState =
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
}
|
|
708
|
-
loadLocal(obs$, syncOptions, syncState
|
|
709
|
-
|
|
786
|
+
const syncState$ = syncState(obs$);
|
|
787
|
+
const syncStateValue = getNodeValue(getNode(syncState$));
|
|
788
|
+
allSyncStates.set(syncState$, node);
|
|
789
|
+
syncStateValue.getPendingChanges = () => localState.pendingChanges;
|
|
790
|
+
const onGetError = (error, params) => {
|
|
791
|
+
var _a;
|
|
792
|
+
syncState$.error.set(error);
|
|
793
|
+
(_a = syncOptions.onGetError) == null ? void 0 : _a.call(syncOptions, error, { ...params, value$: obs$ });
|
|
794
|
+
};
|
|
795
|
+
loadLocal(obs$, syncOptions, syncState$, localState);
|
|
796
|
+
let isWaitingForLoad = !!syncOptions.get;
|
|
797
|
+
if (isWaitingForLoad) {
|
|
798
|
+
syncStateValue.numPendingRemoteLoads = (syncStateValue.numPendingRemoteLoads || 0) + 1;
|
|
799
|
+
}
|
|
800
|
+
syncState$.isLoaded.set(!syncState$.numPendingRemoteLoads.peek());
|
|
801
|
+
let isSynced = false;
|
|
802
|
+
let isSubscribed = false;
|
|
803
|
+
let unsubscribe = void 0;
|
|
804
|
+
const applyPending = (pending) => {
|
|
805
|
+
if (pending && !isEmpty(pending)) {
|
|
806
|
+
localState.isApplyingPending = true;
|
|
807
|
+
const keys = Object.keys(pending);
|
|
808
|
+
const changes = [];
|
|
809
|
+
for (let i = 0; i < keys.length; i++) {
|
|
810
|
+
const key = keys[i];
|
|
811
|
+
const path = key.split("/").filter((p2) => p2 !== "");
|
|
812
|
+
const { p, v, t } = pending[key];
|
|
813
|
+
changes.push({ path, valueAtPath: v, prevAtPath: p, pathTypes: t });
|
|
814
|
+
}
|
|
815
|
+
const value = getNodeValue(node);
|
|
816
|
+
onObsChange(obs$, syncState$, localState, syncOptions, {
|
|
817
|
+
value,
|
|
818
|
+
isFromPersist: false,
|
|
819
|
+
isFromSync: false,
|
|
820
|
+
getPrevious: createPreviousHandler(value, changes),
|
|
821
|
+
changes
|
|
822
|
+
});
|
|
823
|
+
localState.isApplyingPending = false;
|
|
824
|
+
}
|
|
825
|
+
};
|
|
710
826
|
if (syncOptions.get) {
|
|
711
|
-
let isSynced = false;
|
|
712
|
-
let isSubscribed = false;
|
|
713
|
-
let unsubscribe = void 0;
|
|
714
827
|
sync = async () => {
|
|
715
|
-
var _a
|
|
716
|
-
if (isSynced && shouldIgnoreUnobserved(node, sync)) {
|
|
828
|
+
var _a;
|
|
829
|
+
if (isSynced && (!getNodeValue(getNode(syncState$)).isSyncEnabled || shouldIgnoreUnobserved(node, sync))) {
|
|
717
830
|
if (unsubscribe) {
|
|
718
831
|
isSubscribed = false;
|
|
719
832
|
unsubscribe();
|
|
@@ -723,14 +836,16 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
723
836
|
}
|
|
724
837
|
const lastSync = (_a = metadatas.get(obs$)) == null ? void 0 : _a.lastSync;
|
|
725
838
|
const pending = localState.pendingChanges;
|
|
726
|
-
const get =
|
|
839
|
+
const get = syncOptions.get;
|
|
727
840
|
if (get) {
|
|
841
|
+
const { waitFor } = syncOptions;
|
|
728
842
|
const runGet = () => {
|
|
843
|
+
var _a2;
|
|
729
844
|
const onChange = async ({ value, mode, lastSync: lastSync2 }) => {
|
|
730
845
|
mode = mode || syncOptions.mode || "set";
|
|
731
846
|
if (value !== void 0) {
|
|
732
847
|
value = transformLoadData(value, syncOptions, true, "get");
|
|
733
|
-
if (isPromise(value)) {
|
|
848
|
+
if (isPromise$1(value)) {
|
|
734
849
|
value = await value;
|
|
735
850
|
}
|
|
736
851
|
const pending2 = localState.pendingChanges;
|
|
@@ -738,9 +853,11 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
738
853
|
if (pending2) {
|
|
739
854
|
let didChangeMetadata = false;
|
|
740
855
|
Object.keys(pending2).forEach((key) => {
|
|
741
|
-
const p = key.split("/").filter((
|
|
856
|
+
const p = key.split("/").filter((k) => k !== "");
|
|
742
857
|
const { v, t } = pending2[key];
|
|
743
858
|
if (t.length === 0 || !value) {
|
|
859
|
+
const oldValue = clone(value);
|
|
860
|
+
pending2[key].p = oldValue;
|
|
744
861
|
if (isObject(value) && isObject(v)) {
|
|
745
862
|
Object.assign(value, v);
|
|
746
863
|
} else {
|
|
@@ -753,6 +870,8 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
753
870
|
delete pending2[key];
|
|
754
871
|
didChangeMetadata = true;
|
|
755
872
|
} else {
|
|
873
|
+
const oldValue = clone(value);
|
|
874
|
+
pending2[key].p = getValueAtPath(oldValue, p);
|
|
756
875
|
value = setAtPath(
|
|
757
876
|
value,
|
|
758
877
|
p,
|
|
@@ -772,18 +891,24 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
772
891
|
}
|
|
773
892
|
}
|
|
774
893
|
});
|
|
775
|
-
if (didChangeMetadata) {
|
|
776
|
-
updateMetadata(obs$, localState, syncState
|
|
894
|
+
if (didChangeMetadata && syncOptions.persist) {
|
|
895
|
+
updateMetadata(obs$, localState, syncState$, syncOptions, {
|
|
777
896
|
pending: pending2
|
|
778
897
|
});
|
|
779
898
|
}
|
|
780
899
|
}
|
|
781
900
|
onChangeRemote(() => {
|
|
782
|
-
if (mode === "assign"
|
|
901
|
+
if (mode === "assign") {
|
|
783
902
|
obs$.assign(value);
|
|
784
|
-
} else if (mode === "append"
|
|
903
|
+
} else if (mode === "append") {
|
|
904
|
+
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
|
|
905
|
+
console.error("[legend-state] mode:append expects the value to be an array");
|
|
906
|
+
}
|
|
785
907
|
obs$.push(...value);
|
|
786
|
-
} else if (mode === "prepend"
|
|
908
|
+
} else if (mode === "prepend") {
|
|
909
|
+
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
|
|
910
|
+
console.error("[legend-state] mode:prepend expects the value to be an array");
|
|
911
|
+
}
|
|
787
912
|
obs$.splice(0, 0, ...value);
|
|
788
913
|
} else if (mode === "merge") {
|
|
789
914
|
mergeIntoObservable(obs$, value);
|
|
@@ -793,78 +918,162 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
793
918
|
});
|
|
794
919
|
}
|
|
795
920
|
if (lastSync2 && syncOptions.persist) {
|
|
796
|
-
updateMetadata(obs$, localState, syncState
|
|
921
|
+
updateMetadata(obs$, localState, syncState$, syncOptions, {
|
|
797
922
|
lastSync: lastSync2
|
|
798
923
|
});
|
|
799
924
|
}
|
|
800
925
|
};
|
|
801
|
-
|
|
802
|
-
|
|
926
|
+
if (node.activationState) {
|
|
927
|
+
node.activationState.onChange = onChange;
|
|
928
|
+
}
|
|
929
|
+
if (!isSubscribed && syncOptions.subscribe) {
|
|
930
|
+
const subscribe = syncOptions.subscribe;
|
|
931
|
+
isSubscribed = true;
|
|
932
|
+
const doSubscribe = () => {
|
|
933
|
+
const subscribeParams = {
|
|
934
|
+
node,
|
|
935
|
+
value$: obs$,
|
|
936
|
+
lastSync,
|
|
937
|
+
update: (params) => {
|
|
938
|
+
when(syncState$.isLoaded, () => {
|
|
939
|
+
when(waitFor || true, () => {
|
|
940
|
+
params.mode || (params.mode = syncOptions.mode || "merge");
|
|
941
|
+
onChange(params);
|
|
942
|
+
});
|
|
943
|
+
});
|
|
944
|
+
},
|
|
945
|
+
refresh: () => when(syncState$.isLoaded, sync),
|
|
946
|
+
onError: (error) => onGetError(error, { source: "subscribe", subscribeParams })
|
|
947
|
+
};
|
|
948
|
+
unsubscribe = subscribe(subscribeParams);
|
|
949
|
+
};
|
|
950
|
+
if (waitFor) {
|
|
951
|
+
whenReady(waitFor, doSubscribe);
|
|
952
|
+
} else {
|
|
953
|
+
doSubscribe();
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
const existingValue = getNodeValue(node);
|
|
957
|
+
const onError = (error) => onGetError(error, { getParams, source: "get" });
|
|
958
|
+
const getParams = {
|
|
959
|
+
node,
|
|
803
960
|
value$: obs$,
|
|
961
|
+
value: isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked]) ? void 0 : existingValue,
|
|
962
|
+
mode: syncOptions.mode,
|
|
963
|
+
refresh: sync,
|
|
804
964
|
options: syncOptions,
|
|
805
965
|
lastSync,
|
|
806
|
-
|
|
807
|
-
onError
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
966
|
+
updateLastSync: (lastSync2) => getParams.lastSync = lastSync2,
|
|
967
|
+
onError,
|
|
968
|
+
retryNum: 0,
|
|
969
|
+
cancelRetry: false
|
|
970
|
+
};
|
|
971
|
+
let modeBeforeReset = void 0;
|
|
972
|
+
(_a2 = syncOptions.onBeforeGet) == null ? void 0 : _a2.call(syncOptions, {
|
|
973
|
+
value: getParams.value,
|
|
974
|
+
lastSync,
|
|
975
|
+
pendingChanges: pending && !isEmpty(pending) ? pending : void 0,
|
|
976
|
+
clearPendingChanges: async () => {
|
|
977
|
+
localState.pendingChanges = {};
|
|
978
|
+
await updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
|
|
979
|
+
pending: localState.pendingChanges
|
|
815
980
|
});
|
|
816
981
|
},
|
|
817
|
-
|
|
982
|
+
resetCache: () => {
|
|
983
|
+
var _a3;
|
|
984
|
+
modeBeforeReset = getParams.mode;
|
|
985
|
+
getParams.mode = "set";
|
|
986
|
+
return (_a3 = syncStateValue.clearPersist) == null ? void 0 : _a3.call(syncStateValue);
|
|
987
|
+
}
|
|
818
988
|
});
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
989
|
+
syncState$.assign({
|
|
990
|
+
numPendingGets: (syncStateValue.numPendingGets || 0) + 1,
|
|
991
|
+
isGetting: true
|
|
992
|
+
});
|
|
993
|
+
const got = runWithRetry(
|
|
994
|
+
getParams,
|
|
995
|
+
syncOptions.retry,
|
|
996
|
+
(retryEvent) => {
|
|
997
|
+
const params = getParams;
|
|
998
|
+
params.cancelRetry = retryEvent.cancelRetry;
|
|
999
|
+
params.retryNum = retryEvent.retryNum;
|
|
1000
|
+
return get(params);
|
|
1001
|
+
},
|
|
1002
|
+
onError
|
|
1003
|
+
);
|
|
1004
|
+
const numGets = node.numGets = (node.numGets || 0) + 1;
|
|
1005
|
+
const handle = (value) => {
|
|
1006
|
+
syncState$.numPendingGets.set((v) => v - 1);
|
|
1007
|
+
if (isWaitingForLoad) {
|
|
1008
|
+
isWaitingForLoad = false;
|
|
1009
|
+
syncStateValue.numPendingRemoteLoads--;
|
|
1010
|
+
}
|
|
1011
|
+
if (numGets >= (node.getNumResolved || 0)) {
|
|
1012
|
+
node.getNumResolved = node.numGets;
|
|
1013
|
+
onChange({
|
|
1014
|
+
value,
|
|
1015
|
+
lastSync: getParams.lastSync,
|
|
1016
|
+
mode: getParams.mode
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
if (modeBeforeReset) {
|
|
1020
|
+
getParams.mode = modeBeforeReset;
|
|
1021
|
+
modeBeforeReset = void 0;
|
|
1022
|
+
}
|
|
1023
|
+
syncState$.assign({
|
|
1024
|
+
isLoaded: syncStateValue.numPendingRemoteLoads < 1,
|
|
1025
|
+
error: void 0,
|
|
1026
|
+
isGetting: syncStateValue.numPendingGets > 0
|
|
831
1027
|
});
|
|
1028
|
+
};
|
|
1029
|
+
if (isPromise$1(got)) {
|
|
1030
|
+
got.then(handle);
|
|
1031
|
+
} else {
|
|
1032
|
+
handle(got);
|
|
832
1033
|
}
|
|
833
1034
|
};
|
|
834
|
-
|
|
1035
|
+
if (waitFor) {
|
|
1036
|
+
whenReady(waitFor, () => trackSelector(runGet, sync));
|
|
1037
|
+
} else {
|
|
1038
|
+
trackSelector(runGet, sync);
|
|
1039
|
+
}
|
|
835
1040
|
} else {
|
|
836
|
-
|
|
1041
|
+
syncState$.assign({
|
|
837
1042
|
isLoaded: true,
|
|
838
1043
|
error: void 0
|
|
839
1044
|
});
|
|
840
1045
|
}
|
|
841
1046
|
if (!isSynced) {
|
|
842
1047
|
isSynced = true;
|
|
843
|
-
await when(
|
|
844
|
-
|
|
845
|
-
localState.isApplyingPending = true;
|
|
846
|
-
const keys = Object.keys(pending);
|
|
847
|
-
const changes = [];
|
|
848
|
-
for (let i = 0; i < keys.length; i++) {
|
|
849
|
-
const key = keys[i];
|
|
850
|
-
const path = key.split("/").filter((p2) => p2 !== "");
|
|
851
|
-
const { p, v, t } = pending[key];
|
|
852
|
-
changes.push({ path, valueAtPath: v, prevAtPath: p, pathTypes: t });
|
|
853
|
-
}
|
|
854
|
-
const value = getNodeValue(node);
|
|
855
|
-
onObsChange(obs$, syncState, localState, syncOptions, {
|
|
856
|
-
value,
|
|
857
|
-
loading: false,
|
|
858
|
-
remote: false,
|
|
859
|
-
getPrevious: createPreviousHandler(value, changes),
|
|
860
|
-
changes
|
|
861
|
-
});
|
|
862
|
-
localState.isApplyingPending = false;
|
|
863
|
-
}
|
|
1048
|
+
await when(syncState$.isLoaded);
|
|
1049
|
+
applyPending(pending);
|
|
864
1050
|
}
|
|
865
1051
|
};
|
|
866
|
-
|
|
1052
|
+
syncStateValue.sync = sync;
|
|
1053
|
+
} else {
|
|
1054
|
+
if (!isSynced) {
|
|
1055
|
+
applyPending(localState.pendingChanges);
|
|
1056
|
+
}
|
|
867
1057
|
}
|
|
1058
|
+
syncStateValue.reset = async () => {
|
|
1059
|
+
var _a;
|
|
1060
|
+
const wasPersistEnabled = syncStateValue.isPersistEnabled;
|
|
1061
|
+
const wasSyncEnabled = syncStateValue.isSyncEnabled;
|
|
1062
|
+
syncStateValue.isPersistEnabled = false;
|
|
1063
|
+
syncStateValue.isSyncEnabled = false;
|
|
1064
|
+
syncStateValue.syncCount = 0;
|
|
1065
|
+
isSynced = false;
|
|
1066
|
+
isSubscribed = false;
|
|
1067
|
+
unsubscribe == null ? void 0 : unsubscribe();
|
|
1068
|
+
unsubscribe = void 0;
|
|
1069
|
+
const promise = syncStateValue.clearPersist();
|
|
1070
|
+
obs$.set((_a = syncOptions.initial) != null ? _a : void 0);
|
|
1071
|
+
syncState$.isLoaded.set(false);
|
|
1072
|
+
syncStateValue.isPersistEnabled = wasPersistEnabled;
|
|
1073
|
+
syncStateValue.isSyncEnabled = wasSyncEnabled;
|
|
1074
|
+
node.dirtyFn = sync;
|
|
1075
|
+
await promise;
|
|
1076
|
+
};
|
|
868
1077
|
const onAllPersistLoaded = () => {
|
|
869
1078
|
var _a, _b;
|
|
870
1079
|
let parentNode = node;
|
|
@@ -882,77 +1091,27 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
882
1091
|
}
|
|
883
1092
|
if ((syncOptions == null ? void 0 : syncOptions.set) || (syncOptions == null ? void 0 : syncOptions.persist)) {
|
|
884
1093
|
obs$.onChange(
|
|
885
|
-
onObsChange.bind(this, obs$, syncState
|
|
1094
|
+
onObsChange.bind(this, obs$, syncState$, localState, syncOptions)
|
|
886
1095
|
);
|
|
887
1096
|
}
|
|
888
1097
|
});
|
|
889
|
-
return syncState
|
|
1098
|
+
return syncState$;
|
|
890
1099
|
}
|
|
891
|
-
var { getProxy, globalState: globalState2,
|
|
1100
|
+
var { getProxy, globalState: globalState2, setNodeValue, getNodeValue: getNodeValue2 } = internal;
|
|
892
1101
|
function enableActivateSyncedNode() {
|
|
893
1102
|
globalState2.activateSyncedNode = function activateSyncedNode(node, newValue) {
|
|
894
1103
|
const obs$ = getProxy(node);
|
|
895
1104
|
if (node.activationState) {
|
|
896
|
-
const {
|
|
897
|
-
|
|
898
|
-
|
|
1105
|
+
const {
|
|
1106
|
+
get: getOrig,
|
|
1107
|
+
initial,
|
|
1108
|
+
set,
|
|
1109
|
+
onChange
|
|
1110
|
+
} = node.activationState;
|
|
899
1111
|
let promiseReturn = void 0;
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
pluginRemote.get = (params) => {
|
|
904
|
-
var _a;
|
|
905
|
-
onChange = params.onChange;
|
|
906
|
-
const updateLastSync = (lastSync) => params.lastSync = lastSync;
|
|
907
|
-
const existingValue = getNodeValue2(node);
|
|
908
|
-
const value = runWithRetry(node, { attemptNum: 0, retry: retry || ((_a = params.options) == null ? void 0 : _a.retry) }, () => {
|
|
909
|
-
const paramsToGet = {
|
|
910
|
-
value: isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked2]) ? void 0 : existingValue,
|
|
911
|
-
lastSync: params.lastSync,
|
|
912
|
-
updateLastSync,
|
|
913
|
-
mode: params.mode,
|
|
914
|
-
refresh
|
|
915
|
-
};
|
|
916
|
-
const ret = get(paramsToGet);
|
|
917
|
-
params.mode = paramsToGet.mode;
|
|
918
|
-
return ret;
|
|
919
|
-
});
|
|
920
|
-
promiseReturn = value;
|
|
921
|
-
return value;
|
|
922
|
-
};
|
|
923
|
-
}
|
|
924
|
-
if (set) {
|
|
925
|
-
pluginRemote.set = async (params) => {
|
|
926
|
-
var _a, _b;
|
|
927
|
-
if ((_a = node.state) == null ? void 0 : _a.isLoaded.get()) {
|
|
928
|
-
const retryAttempts = { attemptNum: 0, retry: retry || ((_b = params.options) == null ? void 0 : _b.retry) };
|
|
929
|
-
return runWithRetry(node, retryAttempts, async (retryEvent) => {
|
|
930
|
-
let changes = {};
|
|
931
|
-
let maxModified = 0;
|
|
932
|
-
if (!node.state.isLoaded.peek()) {
|
|
933
|
-
await whenReady(node.state.isLoaded);
|
|
934
|
-
}
|
|
935
|
-
const cancelRetry = () => {
|
|
936
|
-
retryEvent.cancel = true;
|
|
937
|
-
};
|
|
938
|
-
await set({
|
|
939
|
-
...params,
|
|
940
|
-
node,
|
|
941
|
-
update: (params2) => {
|
|
942
|
-
const { value, lastSync } = params2;
|
|
943
|
-
maxModified = Math.max(lastSync || 0, maxModified);
|
|
944
|
-
changes = mergeIntoObservable(changes, value);
|
|
945
|
-
},
|
|
946
|
-
retryNum: retryAttempts.attemptNum,
|
|
947
|
-
cancelRetry,
|
|
948
|
-
refresh,
|
|
949
|
-
fromSubscribe: false
|
|
950
|
-
});
|
|
951
|
-
return { changes, lastSync: maxModified || void 0 };
|
|
952
|
-
});
|
|
953
|
-
}
|
|
954
|
-
};
|
|
955
|
-
}
|
|
1112
|
+
const get = getOrig ? (params) => {
|
|
1113
|
+
return promiseReturn = getOrig(params);
|
|
1114
|
+
} : void 0;
|
|
956
1115
|
const nodeVal = getNodeValue2(node);
|
|
957
1116
|
if (promiseReturn !== void 0) {
|
|
958
1117
|
newValue = promiseReturn;
|
|
@@ -962,13 +1121,13 @@ function enableActivateSyncedNode() {
|
|
|
962
1121
|
newValue = initial;
|
|
963
1122
|
}
|
|
964
1123
|
setNodeValue(node, promiseReturn ? void 0 : newValue);
|
|
965
|
-
|
|
1124
|
+
syncObservable(obs$, { ...node.activationState, get, set });
|
|
966
1125
|
return { update: onChange, value: newValue };
|
|
967
1126
|
} else {
|
|
968
1127
|
let update = void 0;
|
|
969
1128
|
const get = async (params) => {
|
|
970
1129
|
update = params.refresh;
|
|
971
|
-
if (isPromise(newValue)) {
|
|
1130
|
+
if (isPromise$1(newValue)) {
|
|
972
1131
|
try {
|
|
973
1132
|
newValue = await newValue;
|
|
974
1133
|
} catch (e) {
|
|
@@ -999,13 +1158,19 @@ function installPersistActivateNode() {
|
|
|
999
1158
|
didInstall = true;
|
|
1000
1159
|
}
|
|
1001
1160
|
}
|
|
1161
|
+
var { deepMerge: deepMerge2 } = internal;
|
|
1162
|
+
function configureSynced(fnOrOrigOptions, origOptions) {
|
|
1163
|
+
const fn = origOptions ? fnOrOrigOptions : void 0;
|
|
1164
|
+
origOptions = origOptions != null ? origOptions : fnOrOrigOptions;
|
|
1165
|
+
return (options) => {
|
|
1166
|
+
const merged = deepMerge2(origOptions, options);
|
|
1167
|
+
return fn ? fn(merged) : merged;
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1002
1170
|
|
|
1003
1171
|
// sync.ts
|
|
1004
|
-
|
|
1005
|
-
return internal.globalState.isLoadingRemote;
|
|
1006
|
-
}
|
|
1007
|
-
var internal3 = {
|
|
1172
|
+
var internal4 = {
|
|
1008
1173
|
observableSyncConfiguration
|
|
1009
1174
|
};
|
|
1010
1175
|
|
|
1011
|
-
export { combineTransforms, configureObservableSync, deepEqual, diffObjects,
|
|
1176
|
+
export { combineTransforms, configureObservableSync, configureSynced, deepEqual, diffObjects, internal4 as internal, mapSyncPlugins, onChangeRemote, removeNullUndefined, syncObservable, synced, transformStringifyDates, transformStringifyKeys };
|