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