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