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