@legendapp/state 3.0.0-alpha.8 → 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 +104 -80
- package/index.d.ts +104 -80
- package/index.js +328 -318
- package/index.mjs +325 -316
- 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 -24
- package/sync-plugins/crud.d.ts +21 -24
- package/sync-plugins/crud.js +241 -140
- package/sync-plugins/crud.mjs +243 -142
- 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 -100
- package/sync-plugins/keel.mjs +147 -100
- package/sync-plugins/supabase.d.mts +19 -9
- package/sync-plugins/supabase.d.ts +19 -9
- package/sync-plugins/supabase.js +52 -22
- package/sync-plugins/supabase.mjs +53 -23
- 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 +492 -293
- package/sync.mjs +498 -299
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,103 +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
|
-
value = transformSave(
|
|
530
|
-
}
|
|
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
|
-
|
|
558
|
-
|
|
559
|
-
|
|
584
|
+
value = transformSave(value);
|
|
585
|
+
}
|
|
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
|
+
}
|
|
560
662
|
}
|
|
561
|
-
if (
|
|
562
|
-
|
|
663
|
+
if (lastSync) {
|
|
664
|
+
metadata.lastSync = lastSync;
|
|
563
665
|
}
|
|
564
666
|
}
|
|
565
|
-
if (
|
|
566
|
-
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
if (changes && !isEmpty(changes)) {
|
|
570
|
-
transformedChanges = transformLoadData(changes, syncOptions, false, "set");
|
|
571
|
-
}
|
|
572
|
-
if (localState.numSavesOutstanding > 0) {
|
|
573
|
-
if (transformedChanges) {
|
|
574
|
-
if (!localState.pendingSaveResults) {
|
|
575
|
-
localState.pendingSaveResults = [];
|
|
576
|
-
}
|
|
577
|
-
localState.pendingSaveResults.push(transformedChanges);
|
|
667
|
+
if (changes && !isEmpty(changes)) {
|
|
668
|
+
transformedChanges = transformLoadData(changes, syncOptions, false, "set");
|
|
578
669
|
}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
);
|
|
583
|
-
if (allChanges.length > 0) {
|
|
584
|
-
if (allChanges.some((change) => isPromise(change))) {
|
|
585
|
-
allChanges = await Promise.all(allChanges);
|
|
670
|
+
if (transformedChanges !== void 0) {
|
|
671
|
+
if (isPromise$1(transformedChanges)) {
|
|
672
|
+
transformedChanges = await transformedChanges;
|
|
586
673
|
}
|
|
587
|
-
onChangeRemote(() => mergeIntoObservable(obs
|
|
674
|
+
onChangeRemote(() => mergeIntoObservable(obs$, transformedChanges));
|
|
588
675
|
}
|
|
589
676
|
if (saveLocal) {
|
|
590
677
|
if (shouldSaveMetadata && !isEmpty(metadata)) {
|
|
591
|
-
updateMetadata(obs
|
|
678
|
+
updateMetadata(obs$, localState, syncState2, syncOptions, metadata);
|
|
592
679
|
}
|
|
593
680
|
}
|
|
594
|
-
localState.pendingSaveResults = [];
|
|
595
681
|
}
|
|
682
|
+
state$.numPendingSets.set((v) => v - 1);
|
|
683
|
+
state$.isSetting.set(state$.numPendingSets.peek() > 0);
|
|
596
684
|
onAfterSet == null ? void 0 : onAfterSet();
|
|
597
685
|
}
|
|
598
686
|
}
|
|
599
687
|
}
|
|
600
688
|
}
|
|
601
|
-
function onObsChange(value$,
|
|
602
|
-
if (!
|
|
603
|
-
const inRemoteChange =
|
|
689
|
+
function onObsChange(value$, syncState2, localState, syncOptions, { changes, isFromPersist, isFromSync, getPrevious }) {
|
|
690
|
+
if (!isFromPersist) {
|
|
691
|
+
const inRemoteChange = isFromSync;
|
|
604
692
|
const isApplyingPending = localState.isApplyingPending;
|
|
605
693
|
_queuedChanges.push({
|
|
606
694
|
value$,
|
|
607
|
-
syncState,
|
|
695
|
+
syncState: syncState2,
|
|
608
696
|
localState,
|
|
609
697
|
syncOptions,
|
|
610
698
|
changes,
|
|
@@ -617,24 +705,27 @@ function onObsChange(value$, syncState, localState, syncOptions, { changes, load
|
|
|
617
705
|
}
|
|
618
706
|
}
|
|
619
707
|
}
|
|
620
|
-
async function loadLocal(value$, syncOptions, syncState
|
|
708
|
+
async function loadLocal(value$, syncOptions, syncState$, localState) {
|
|
621
709
|
var _a, _b, _c;
|
|
622
710
|
const { persist } = syncOptions;
|
|
623
711
|
const node = getNode(value$);
|
|
624
712
|
const nodeValue = getNodeValue(getNode(node.state));
|
|
713
|
+
const syncStateValue = syncState$.peek();
|
|
714
|
+
const prevResetPersistence = nodeValue.resetPersistence;
|
|
625
715
|
if (persist == null ? void 0 : persist.name) {
|
|
626
716
|
const PersistPlugin = persist.plugin || ((_a = observableSyncConfiguration.persist) == null ? void 0 : _a.plugin);
|
|
627
717
|
const { table, config } = parseLocalConfig(persist);
|
|
718
|
+
syncStateValue.numPendingLocalLoads = (syncStateValue.numPendingLocalLoads || 0) + 1;
|
|
628
719
|
if (!PersistPlugin) {
|
|
629
720
|
throw new Error("Local persist is not configured");
|
|
630
721
|
}
|
|
631
722
|
if (!mapSyncPlugins.has(PersistPlugin)) {
|
|
632
|
-
const persistPlugin2 = new PersistPlugin();
|
|
723
|
+
const persistPlugin2 = isFunction(PersistPlugin) ? new PersistPlugin() : PersistPlugin;
|
|
633
724
|
const mapValue = { plugin: persistPlugin2, initialized: observable(false) };
|
|
634
725
|
mapSyncPlugins.set(PersistPlugin, mapValue);
|
|
635
726
|
if (persistPlugin2.initialize) {
|
|
636
727
|
const initializePromise = (_c = persistPlugin2.initialize) == null ? void 0 : _c.call(persistPlugin2, ((_b = observableSyncConfiguration) == null ? void 0 : _b.persist) || {});
|
|
637
|
-
if (isPromise(initializePromise)) {
|
|
728
|
+
if (isPromise$1(initializePromise)) {
|
|
638
729
|
await initializePromise;
|
|
639
730
|
}
|
|
640
731
|
}
|
|
@@ -658,14 +749,14 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
|
|
|
658
749
|
if (metadata) {
|
|
659
750
|
metadatas.set(value$, metadata);
|
|
660
751
|
localState.pendingChanges = metadata.pending;
|
|
661
|
-
syncState
|
|
752
|
+
syncState$.assign({
|
|
662
753
|
lastSync: metadata.lastSync
|
|
663
754
|
});
|
|
664
755
|
}
|
|
665
756
|
if (value !== void 0) {
|
|
666
757
|
const { transform } = config;
|
|
667
758
|
value = transformLoadData(value, { transform }, true, "get");
|
|
668
|
-
if (isPromise(value)) {
|
|
759
|
+
if (isPromise$1(value)) {
|
|
669
760
|
value = await value;
|
|
670
761
|
}
|
|
671
762
|
internal.globalState.isLoadingLocal = true;
|
|
@@ -676,15 +767,19 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
|
|
|
676
767
|
}
|
|
677
768
|
internal.globalState.isLoadingLocal = false;
|
|
678
769
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
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
|
+
);
|
|
683
778
|
} else {
|
|
684
|
-
nodeValue.
|
|
685
|
-
};
|
|
779
|
+
nodeValue.resetPersistence = () => prevResetPersistence == null ? void 0 : prevResetPersistence();
|
|
686
780
|
}
|
|
687
|
-
|
|
781
|
+
nodeValue.clearPersist = nodeValue.resetPersistence;
|
|
782
|
+
syncState$.isPersistLoaded.set(!(syncStateValue.numPendingLocalLoads > 0));
|
|
688
783
|
}
|
|
689
784
|
function syncObservable(obs$, syncOptionsOrSynced) {
|
|
690
785
|
let syncOptions = syncOptionsOrSynced;
|
|
@@ -695,7 +790,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
695
790
|
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && (!obs$ || !node)) {
|
|
696
791
|
throw new Error("[legend-state] syncObservable called with undefined observable");
|
|
697
792
|
}
|
|
698
|
-
syncOptions =
|
|
793
|
+
syncOptions = deepMerge(
|
|
699
794
|
{
|
|
700
795
|
syncMode: "auto"
|
|
701
796
|
},
|
|
@@ -704,24 +799,54 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
704
799
|
);
|
|
705
800
|
const localState = {};
|
|
706
801
|
let sync;
|
|
707
|
-
const syncState =
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
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
|
+
};
|
|
718
846
|
if (syncOptions.get) {
|
|
719
|
-
let isSynced = false;
|
|
720
|
-
let isSubscribed = false;
|
|
721
|
-
let unsubscribe = void 0;
|
|
722
847
|
sync = async () => {
|
|
723
|
-
var _a
|
|
724
|
-
if (isSynced && shouldIgnoreUnobserved(node, sync)) {
|
|
848
|
+
var _a;
|
|
849
|
+
if (isSynced && (!getNodeValue(getNode(syncState$)).isSyncEnabled || shouldIgnoreUnobserved(node, sync))) {
|
|
725
850
|
if (unsubscribe) {
|
|
726
851
|
isSubscribed = false;
|
|
727
852
|
unsubscribe();
|
|
@@ -731,14 +856,16 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
731
856
|
}
|
|
732
857
|
const lastSync = (_a = metadatas.get(obs$)) == null ? void 0 : _a.lastSync;
|
|
733
858
|
const pending = localState.pendingChanges;
|
|
734
|
-
const get =
|
|
859
|
+
const get = syncOptions.get;
|
|
735
860
|
if (get) {
|
|
861
|
+
const { waitFor } = syncOptions;
|
|
736
862
|
const runGet = () => {
|
|
863
|
+
var _a2;
|
|
737
864
|
const onChange = async ({ value, mode, lastSync: lastSync2 }) => {
|
|
738
865
|
mode = mode || syncOptions.mode || "set";
|
|
739
866
|
if (value !== void 0) {
|
|
740
867
|
value = transformLoadData(value, syncOptions, true, "get");
|
|
741
|
-
if (isPromise(value)) {
|
|
868
|
+
if (isPromise$1(value)) {
|
|
742
869
|
value = await value;
|
|
743
870
|
}
|
|
744
871
|
const pending2 = localState.pendingChanges;
|
|
@@ -746,9 +873,11 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
746
873
|
if (pending2) {
|
|
747
874
|
let didChangeMetadata = false;
|
|
748
875
|
Object.keys(pending2).forEach((key) => {
|
|
749
|
-
const p = key.split("/").filter((
|
|
876
|
+
const p = key.split("/").filter((k) => k !== "");
|
|
750
877
|
const { v, t } = pending2[key];
|
|
751
878
|
if (t.length === 0 || !value) {
|
|
879
|
+
const oldValue = clone(value);
|
|
880
|
+
pending2[key].p = oldValue;
|
|
752
881
|
if (isObject(value) && isObject(v)) {
|
|
753
882
|
Object.assign(value, v);
|
|
754
883
|
} else {
|
|
@@ -761,6 +890,8 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
761
890
|
delete pending2[key];
|
|
762
891
|
didChangeMetadata = true;
|
|
763
892
|
} else {
|
|
893
|
+
const oldValue = clone(value);
|
|
894
|
+
pending2[key].p = getValueAtPath(oldValue, p);
|
|
764
895
|
value = setAtPath(
|
|
765
896
|
value,
|
|
766
897
|
p,
|
|
@@ -780,18 +911,27 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
780
911
|
}
|
|
781
912
|
}
|
|
782
913
|
});
|
|
783
|
-
if (didChangeMetadata) {
|
|
784
|
-
updateMetadata(obs$, localState, syncState
|
|
914
|
+
if (didChangeMetadata && syncOptions.persist) {
|
|
915
|
+
updateMetadata(obs$, localState, syncState$, syncOptions, {
|
|
785
916
|
pending: pending2
|
|
786
917
|
});
|
|
787
918
|
}
|
|
788
919
|
}
|
|
789
920
|
onChangeRemote(() => {
|
|
790
|
-
if (
|
|
921
|
+
if (isPlainObject(value)) {
|
|
922
|
+
value = ObservableHint.plain(value);
|
|
923
|
+
}
|
|
924
|
+
if (mode === "assign") {
|
|
791
925
|
obs$.assign(value);
|
|
792
|
-
} 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
|
+
}
|
|
793
930
|
obs$.push(...value);
|
|
794
|
-
} 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
|
+
}
|
|
795
935
|
obs$.splice(0, 0, ...value);
|
|
796
936
|
} else if (mode === "merge") {
|
|
797
937
|
mergeIntoObservable(obs$, value);
|
|
@@ -801,78 +941,180 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
801
941
|
});
|
|
802
942
|
}
|
|
803
943
|
if (lastSync2 && syncOptions.persist) {
|
|
804
|
-
updateMetadata(obs$, localState, syncState
|
|
944
|
+
updateMetadata(obs$, localState, syncState$, syncOptions, {
|
|
805
945
|
lastSync: lastSync2
|
|
806
946
|
});
|
|
807
947
|
}
|
|
808
948
|
};
|
|
809
|
-
|
|
810
|
-
|
|
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,
|
|
811
983
|
value$: obs$,
|
|
984
|
+
value: isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked]) ? void 0 : existingValue,
|
|
985
|
+
mode: syncOptions.mode,
|
|
986
|
+
refresh: sync,
|
|
812
987
|
options: syncOptions,
|
|
813
988
|
lastSync,
|
|
814
|
-
|
|
815
|
-
onError
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
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
|
|
823
1003
|
});
|
|
824
1004
|
},
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
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
|
|
839
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
|
+
}
|
|
840
1060
|
}
|
|
841
1061
|
};
|
|
842
|
-
|
|
1062
|
+
if (waitFor) {
|
|
1063
|
+
whenReady(waitFor, () => trackSelector(runGet, sync));
|
|
1064
|
+
} else {
|
|
1065
|
+
trackSelector(runGet, sync);
|
|
1066
|
+
}
|
|
843
1067
|
} else {
|
|
844
|
-
|
|
1068
|
+
syncState$.assign({
|
|
845
1069
|
isLoaded: true,
|
|
846
1070
|
error: void 0
|
|
847
1071
|
});
|
|
848
1072
|
}
|
|
849
1073
|
if (!isSynced) {
|
|
850
1074
|
isSynced = true;
|
|
851
|
-
await when(
|
|
852
|
-
|
|
853
|
-
localState.isApplyingPending = true;
|
|
854
|
-
const keys = Object.keys(pending);
|
|
855
|
-
const changes = [];
|
|
856
|
-
for (let i = 0; i < keys.length; i++) {
|
|
857
|
-
const key = keys[i];
|
|
858
|
-
const path = key.split("/").filter((p2) => p2 !== "");
|
|
859
|
-
const { p, v, t } = pending[key];
|
|
860
|
-
changes.push({ path, valueAtPath: v, prevAtPath: p, pathTypes: t });
|
|
861
|
-
}
|
|
862
|
-
const value = getNodeValue(node);
|
|
863
|
-
onObsChange(obs$, syncState, localState, syncOptions, {
|
|
864
|
-
value,
|
|
865
|
-
loading: false,
|
|
866
|
-
remote: false,
|
|
867
|
-
getPrevious: createPreviousHandler(value, changes),
|
|
868
|
-
changes
|
|
869
|
-
});
|
|
870
|
-
localState.isApplyingPending = false;
|
|
871
|
-
}
|
|
1075
|
+
await when(syncState$.isLoaded);
|
|
1076
|
+
applyPending(pending);
|
|
872
1077
|
}
|
|
873
1078
|
};
|
|
874
|
-
|
|
1079
|
+
syncStateValue.sync = sync;
|
|
1080
|
+
} else {
|
|
1081
|
+
if (!isSynced) {
|
|
1082
|
+
applyPending(localState.pendingChanges);
|
|
1083
|
+
}
|
|
875
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
|
+
};
|
|
876
1118
|
const onAllPersistLoaded = () => {
|
|
877
1119
|
var _a, _b;
|
|
878
1120
|
let parentNode = node;
|
|
@@ -890,77 +1132,27 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
890
1132
|
}
|
|
891
1133
|
if ((syncOptions == null ? void 0 : syncOptions.set) || (syncOptions == null ? void 0 : syncOptions.persist)) {
|
|
892
1134
|
obs$.onChange(
|
|
893
|
-
onObsChange.bind(this, obs$, syncState
|
|
1135
|
+
onObsChange.bind(this, obs$, syncState$, localState, syncOptions)
|
|
894
1136
|
);
|
|
895
1137
|
}
|
|
896
1138
|
});
|
|
897
|
-
return syncState
|
|
1139
|
+
return syncState$;
|
|
898
1140
|
}
|
|
899
|
-
var { getProxy, globalState: globalState2,
|
|
1141
|
+
var { getProxy, globalState: globalState2, setNodeValue, getNodeValue: getNodeValue2 } = internal;
|
|
900
1142
|
function enableActivateSyncedNode() {
|
|
901
1143
|
globalState2.activateSyncedNode = function activateSyncedNode(node, newValue) {
|
|
902
1144
|
const obs$ = getProxy(node);
|
|
903
1145
|
if (node.activationState) {
|
|
904
|
-
const {
|
|
905
|
-
|
|
906
|
-
|
|
1146
|
+
const {
|
|
1147
|
+
get: getOrig,
|
|
1148
|
+
initial,
|
|
1149
|
+
set,
|
|
1150
|
+
onChange
|
|
1151
|
+
} = node.activationState;
|
|
907
1152
|
let promiseReturn = void 0;
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
pluginRemote.get = (params) => {
|
|
912
|
-
var _a;
|
|
913
|
-
onChange = params.onChange;
|
|
914
|
-
const updateLastSync = (lastSync) => params.lastSync = lastSync;
|
|
915
|
-
const existingValue = getNodeValue2(node);
|
|
916
|
-
const value = runWithRetry(node, { attemptNum: 0, retry: retry || ((_a = params.options) == null ? void 0 : _a.retry) }, () => {
|
|
917
|
-
const paramsToGet = {
|
|
918
|
-
value: isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked2]) ? void 0 : existingValue,
|
|
919
|
-
lastSync: params.lastSync,
|
|
920
|
-
updateLastSync,
|
|
921
|
-
mode: params.mode,
|
|
922
|
-
refresh
|
|
923
|
-
};
|
|
924
|
-
const ret = get(paramsToGet);
|
|
925
|
-
params.mode = paramsToGet.mode;
|
|
926
|
-
return ret;
|
|
927
|
-
});
|
|
928
|
-
promiseReturn = value;
|
|
929
|
-
return value;
|
|
930
|
-
};
|
|
931
|
-
}
|
|
932
|
-
if (set) {
|
|
933
|
-
pluginRemote.set = async (params) => {
|
|
934
|
-
var _a, _b;
|
|
935
|
-
if ((_a = node.state) == null ? void 0 : _a.isLoaded.get()) {
|
|
936
|
-
const retryAttempts = { attemptNum: 0, retry: retry || ((_b = params.options) == null ? void 0 : _b.retry) };
|
|
937
|
-
return runWithRetry(node, retryAttempts, async (retryEvent) => {
|
|
938
|
-
let changes = {};
|
|
939
|
-
let maxModified = 0;
|
|
940
|
-
if (!node.state.isLoaded.peek()) {
|
|
941
|
-
await whenReady(node.state.isLoaded);
|
|
942
|
-
}
|
|
943
|
-
const cancelRetry = () => {
|
|
944
|
-
retryEvent.cancel = true;
|
|
945
|
-
};
|
|
946
|
-
await set({
|
|
947
|
-
...params,
|
|
948
|
-
node,
|
|
949
|
-
update: (params2) => {
|
|
950
|
-
const { value, lastSync } = params2;
|
|
951
|
-
maxModified = Math.max(lastSync || 0, maxModified);
|
|
952
|
-
changes = mergeIntoObservable(changes, value);
|
|
953
|
-
},
|
|
954
|
-
retryNum: retryAttempts.attemptNum,
|
|
955
|
-
cancelRetry,
|
|
956
|
-
refresh,
|
|
957
|
-
fromSubscribe: false
|
|
958
|
-
});
|
|
959
|
-
return { changes, lastSync: maxModified || void 0 };
|
|
960
|
-
});
|
|
961
|
-
}
|
|
962
|
-
};
|
|
963
|
-
}
|
|
1153
|
+
const get = getOrig ? (params) => {
|
|
1154
|
+
return promiseReturn = getOrig(params);
|
|
1155
|
+
} : void 0;
|
|
964
1156
|
const nodeVal = getNodeValue2(node);
|
|
965
1157
|
if (promiseReturn !== void 0) {
|
|
966
1158
|
newValue = promiseReturn;
|
|
@@ -970,13 +1162,13 @@ function enableActivateSyncedNode() {
|
|
|
970
1162
|
newValue = initial;
|
|
971
1163
|
}
|
|
972
1164
|
setNodeValue(node, promiseReturn ? void 0 : newValue);
|
|
973
|
-
|
|
1165
|
+
syncObservable(obs$, { ...node.activationState, get, set });
|
|
974
1166
|
return { update: onChange, value: newValue };
|
|
975
1167
|
} else {
|
|
976
1168
|
let update = void 0;
|
|
977
1169
|
const get = async (params) => {
|
|
978
1170
|
update = params.refresh;
|
|
979
|
-
if (isPromise(newValue)) {
|
|
1171
|
+
if (isPromise$1(newValue)) {
|
|
980
1172
|
try {
|
|
981
1173
|
newValue = await newValue;
|
|
982
1174
|
} catch (e) {
|
|
@@ -1007,13 +1199,20 @@ function installPersistActivateNode() {
|
|
|
1007
1199
|
didInstall = true;
|
|
1008
1200
|
}
|
|
1009
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
|
+
}
|
|
1010
1211
|
|
|
1011
1212
|
// sync.ts
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
var internal3 = {
|
|
1016
|
-
observableSyncConfiguration
|
|
1213
|
+
var internal4 = {
|
|
1214
|
+
observableSyncConfiguration,
|
|
1215
|
+
waitForSet
|
|
1017
1216
|
};
|
|
1018
1217
|
|
|
1019
|
-
export { combineTransforms, configureObservableSync, deepEqual, diffObjects,
|
|
1218
|
+
export { combineTransforms, configureObservableSync, configureSynced, deepEqual, diffObjects, internal4 as internal, mapSyncPlugins, onChangeRemote, removeNullUndefined, syncObservable, synced, transformStringifyDates, transformStringifyKeys };
|