@legendapp/state 3.0.0-alpha.9 → 3.0.0-beta.1
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 +498 -281
- package/sync.mjs +503 -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,151 @@ 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((error) => {
|
|
641
|
+
didError = true;
|
|
642
|
+
if (!syncOptions.retry) {
|
|
643
|
+
onError(error);
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
if (!didError) {
|
|
648
|
+
const pathStrs = Array.from(new Set(changesRemote.map((change) => change.pathStr)));
|
|
649
|
+
const { value: changes, lastSync } = updateResult || {};
|
|
650
|
+
if (pathStrs.length > 0) {
|
|
651
|
+
let transformedChanges = void 0;
|
|
652
|
+
const metadata = {};
|
|
653
|
+
if (saveLocal) {
|
|
654
|
+
const pendingMetadata = (_b = pluginPersist.getMetadata(table, configLocal)) == null ? void 0 : _b.pending;
|
|
655
|
+
const pending = localState.pendingChanges;
|
|
656
|
+
for (let i = 0; i < pathStrs.length; i++) {
|
|
657
|
+
const pathStr = pathStrs[i];
|
|
658
|
+
if (pendingMetadata == null ? void 0 : pendingMetadata[pathStr]) {
|
|
659
|
+
delete pendingMetadata[pathStr];
|
|
660
|
+
metadata.pending = pendingMetadata;
|
|
661
|
+
}
|
|
662
|
+
if (pending == null ? void 0 : pending[pathStr]) {
|
|
663
|
+
delete pending[pathStr];
|
|
664
|
+
}
|
|
558
665
|
}
|
|
559
|
-
if (
|
|
560
|
-
|
|
666
|
+
if (lastSync) {
|
|
667
|
+
metadata.lastSync = lastSync;
|
|
561
668
|
}
|
|
562
669
|
}
|
|
563
|
-
if (
|
|
564
|
-
|
|
670
|
+
if (changes && !isEmpty(changes)) {
|
|
671
|
+
transformedChanges = transformLoadData(changes, syncOptions, false, "set");
|
|
565
672
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
if (isPromise(transformedChanges)) {
|
|
572
|
-
transformedChanges = await transformedChanges;
|
|
673
|
+
if (transformedChanges !== void 0) {
|
|
674
|
+
if (isPromise$1(transformedChanges)) {
|
|
675
|
+
transformedChanges = await transformedChanges;
|
|
676
|
+
}
|
|
677
|
+
onChangeRemote(() => mergeIntoObservable(obs$, transformedChanges));
|
|
573
678
|
}
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
updateMetadata(obs, localState, syncState, syncOptions, metadata);
|
|
679
|
+
if (saveLocal) {
|
|
680
|
+
if (shouldSaveMetadata && !isEmpty(metadata)) {
|
|
681
|
+
updateMetadata(obs$, localState, syncState2, syncOptions, metadata);
|
|
682
|
+
}
|
|
579
683
|
}
|
|
580
684
|
}
|
|
685
|
+
state$.numPendingSets.set((v) => v - 1);
|
|
686
|
+
state$.isSetting.set(state$.numPendingSets.peek() > 0);
|
|
581
687
|
onAfterSet == null ? void 0 : onAfterSet();
|
|
582
688
|
}
|
|
583
689
|
}
|
|
584
690
|
}
|
|
585
691
|
}
|
|
586
|
-
function onObsChange(value$,
|
|
587
|
-
if (!
|
|
588
|
-
const inRemoteChange =
|
|
692
|
+
function onObsChange(value$, syncState2, localState, syncOptions, { changes, isFromPersist, isFromSync, getPrevious }) {
|
|
693
|
+
if (!isFromPersist) {
|
|
694
|
+
const inRemoteChange = isFromSync;
|
|
589
695
|
const isApplyingPending = localState.isApplyingPending;
|
|
590
696
|
_queuedChanges.push({
|
|
591
697
|
value$,
|
|
592
|
-
syncState,
|
|
698
|
+
syncState: syncState2,
|
|
593
699
|
localState,
|
|
594
700
|
syncOptions,
|
|
595
701
|
changes,
|
|
@@ -602,24 +708,27 @@ function onObsChange(value$, syncState, localState, syncOptions, { changes, load
|
|
|
602
708
|
}
|
|
603
709
|
}
|
|
604
710
|
}
|
|
605
|
-
async function loadLocal(value$, syncOptions, syncState
|
|
711
|
+
async function loadLocal(value$, syncOptions, syncState$, localState) {
|
|
606
712
|
var _a, _b, _c;
|
|
607
713
|
const { persist } = syncOptions;
|
|
608
714
|
const node = getNode(value$);
|
|
609
715
|
const nodeValue = getNodeValue(getNode(node.state));
|
|
716
|
+
const syncStateValue = syncState$.peek();
|
|
717
|
+
const prevResetPersistence = nodeValue.resetPersistence;
|
|
610
718
|
if (persist == null ? void 0 : persist.name) {
|
|
611
719
|
const PersistPlugin = persist.plugin || ((_a = observableSyncConfiguration.persist) == null ? void 0 : _a.plugin);
|
|
612
720
|
const { table, config } = parseLocalConfig(persist);
|
|
721
|
+
syncStateValue.numPendingLocalLoads = (syncStateValue.numPendingLocalLoads || 0) + 1;
|
|
613
722
|
if (!PersistPlugin) {
|
|
614
723
|
throw new Error("Local persist is not configured");
|
|
615
724
|
}
|
|
616
725
|
if (!mapSyncPlugins.has(PersistPlugin)) {
|
|
617
|
-
const persistPlugin2 = new PersistPlugin();
|
|
726
|
+
const persistPlugin2 = isFunction(PersistPlugin) ? new PersistPlugin() : PersistPlugin;
|
|
618
727
|
const mapValue = { plugin: persistPlugin2, initialized: observable(false) };
|
|
619
728
|
mapSyncPlugins.set(PersistPlugin, mapValue);
|
|
620
729
|
if (persistPlugin2.initialize) {
|
|
621
730
|
const initializePromise = (_c = persistPlugin2.initialize) == null ? void 0 : _c.call(persistPlugin2, ((_b = observableSyncConfiguration) == null ? void 0 : _b.persist) || {});
|
|
622
|
-
if (isPromise(initializePromise)) {
|
|
731
|
+
if (isPromise$1(initializePromise)) {
|
|
623
732
|
await initializePromise;
|
|
624
733
|
}
|
|
625
734
|
}
|
|
@@ -643,14 +752,14 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
|
|
|
643
752
|
if (metadata) {
|
|
644
753
|
metadatas.set(value$, metadata);
|
|
645
754
|
localState.pendingChanges = metadata.pending;
|
|
646
|
-
syncState
|
|
755
|
+
syncState$.assign({
|
|
647
756
|
lastSync: metadata.lastSync
|
|
648
757
|
});
|
|
649
758
|
}
|
|
650
759
|
if (value !== void 0) {
|
|
651
760
|
const { transform } = config;
|
|
652
761
|
value = transformLoadData(value, { transform }, true, "get");
|
|
653
|
-
if (isPromise(value)) {
|
|
762
|
+
if (isPromise$1(value)) {
|
|
654
763
|
value = await value;
|
|
655
764
|
}
|
|
656
765
|
internal.globalState.isLoadingLocal = true;
|
|
@@ -661,15 +770,19 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
|
|
|
661
770
|
}
|
|
662
771
|
internal.globalState.isLoadingLocal = false;
|
|
663
772
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
773
|
+
syncStateValue.numPendingLocalLoads--;
|
|
774
|
+
nodeValue.resetPersistence = () => Promise.all(
|
|
775
|
+
[
|
|
776
|
+
prevResetPersistence,
|
|
777
|
+
persistPlugin.deleteTable(table, config),
|
|
778
|
+
persistPlugin.deleteMetadata(table, config)
|
|
779
|
+
].filter(Boolean)
|
|
780
|
+
);
|
|
668
781
|
} else {
|
|
669
|
-
nodeValue.
|
|
670
|
-
};
|
|
782
|
+
nodeValue.resetPersistence = () => prevResetPersistence == null ? void 0 : prevResetPersistence();
|
|
671
783
|
}
|
|
672
|
-
|
|
784
|
+
nodeValue.clearPersist = nodeValue.resetPersistence;
|
|
785
|
+
syncState$.isPersistLoaded.set(!(syncStateValue.numPendingLocalLoads > 0));
|
|
673
786
|
}
|
|
674
787
|
function syncObservable(obs$, syncOptionsOrSynced) {
|
|
675
788
|
let syncOptions = syncOptionsOrSynced;
|
|
@@ -680,7 +793,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
680
793
|
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && (!obs$ || !node)) {
|
|
681
794
|
throw new Error("[legend-state] syncObservable called with undefined observable");
|
|
682
795
|
}
|
|
683
|
-
syncOptions =
|
|
796
|
+
syncOptions = deepMerge(
|
|
684
797
|
{
|
|
685
798
|
syncMode: "auto"
|
|
686
799
|
},
|
|
@@ -689,24 +802,54 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
689
802
|
);
|
|
690
803
|
const localState = {};
|
|
691
804
|
let sync;
|
|
692
|
-
const syncState =
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
805
|
+
const syncState$ = syncState(obs$);
|
|
806
|
+
const syncStateValue = getNodeValue(getNode(syncState$));
|
|
807
|
+
allSyncStates.set(syncState$, node);
|
|
808
|
+
syncStateValue.getPendingChanges = () => localState.pendingChanges;
|
|
809
|
+
let errorHandled = false;
|
|
810
|
+
const onGetError = (error, params) => {
|
|
811
|
+
var _a;
|
|
812
|
+
syncState$.error.set(error);
|
|
813
|
+
if (!errorHandled) {
|
|
814
|
+
(_a = syncOptions.onError) == null ? void 0 : _a.call(syncOptions, error, { ...params, value$: obs$ });
|
|
815
|
+
}
|
|
816
|
+
errorHandled = true;
|
|
817
|
+
};
|
|
818
|
+
loadLocal(obs$, syncOptions, syncState$, localState);
|
|
819
|
+
let isWaitingForLoad = !!syncOptions.get;
|
|
820
|
+
if (isWaitingForLoad) {
|
|
821
|
+
syncStateValue.numPendingRemoteLoads = (syncStateValue.numPendingRemoteLoads || 0) + 1;
|
|
822
|
+
}
|
|
823
|
+
syncState$.isLoaded.set(!syncState$.numPendingRemoteLoads.peek());
|
|
824
|
+
let isSynced = false;
|
|
825
|
+
let isSubscribed = false;
|
|
826
|
+
let unsubscribe = void 0;
|
|
827
|
+
const applyPending = (pending) => {
|
|
828
|
+
if (pending && !isEmpty(pending)) {
|
|
829
|
+
localState.isApplyingPending = true;
|
|
830
|
+
const keys = Object.keys(pending);
|
|
831
|
+
const changes = [];
|
|
832
|
+
for (let i = 0; i < keys.length; i++) {
|
|
833
|
+
const key = keys[i];
|
|
834
|
+
const path = key.split("/").filter((p2) => p2 !== "");
|
|
835
|
+
const { p, v, t } = pending[key];
|
|
836
|
+
changes.push({ path, valueAtPath: v, prevAtPath: p, pathTypes: t });
|
|
837
|
+
}
|
|
838
|
+
const value = getNodeValue(node);
|
|
839
|
+
onObsChange(obs$, syncState$, localState, syncOptions, {
|
|
840
|
+
value,
|
|
841
|
+
isFromPersist: false,
|
|
842
|
+
isFromSync: false,
|
|
843
|
+
getPrevious: createPreviousHandler(value, changes),
|
|
844
|
+
changes
|
|
845
|
+
});
|
|
846
|
+
localState.isApplyingPending = false;
|
|
847
|
+
}
|
|
848
|
+
};
|
|
703
849
|
if (syncOptions.get) {
|
|
704
|
-
let isSynced = false;
|
|
705
|
-
let isSubscribed = false;
|
|
706
|
-
let unsubscribe = void 0;
|
|
707
850
|
sync = async () => {
|
|
708
|
-
var _a
|
|
709
|
-
if (isSynced && shouldIgnoreUnobserved(node, sync)) {
|
|
851
|
+
var _a;
|
|
852
|
+
if (isSynced && (!getNodeValue(getNode(syncState$)).isSyncEnabled || shouldIgnoreUnobserved(node, sync))) {
|
|
710
853
|
if (unsubscribe) {
|
|
711
854
|
isSubscribed = false;
|
|
712
855
|
unsubscribe();
|
|
@@ -716,14 +859,16 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
716
859
|
}
|
|
717
860
|
const lastSync = (_a = metadatas.get(obs$)) == null ? void 0 : _a.lastSync;
|
|
718
861
|
const pending = localState.pendingChanges;
|
|
719
|
-
const get =
|
|
862
|
+
const get = syncOptions.get;
|
|
720
863
|
if (get) {
|
|
864
|
+
const { waitFor } = syncOptions;
|
|
721
865
|
const runGet = () => {
|
|
866
|
+
var _a2;
|
|
722
867
|
const onChange = async ({ value, mode, lastSync: lastSync2 }) => {
|
|
723
868
|
mode = mode || syncOptions.mode || "set";
|
|
724
869
|
if (value !== void 0) {
|
|
725
870
|
value = transformLoadData(value, syncOptions, true, "get");
|
|
726
|
-
if (isPromise(value)) {
|
|
871
|
+
if (isPromise$1(value)) {
|
|
727
872
|
value = await value;
|
|
728
873
|
}
|
|
729
874
|
const pending2 = localState.pendingChanges;
|
|
@@ -731,9 +876,11 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
731
876
|
if (pending2) {
|
|
732
877
|
let didChangeMetadata = false;
|
|
733
878
|
Object.keys(pending2).forEach((key) => {
|
|
734
|
-
const p = key.split("/").filter((
|
|
879
|
+
const p = key.split("/").filter((k) => k !== "");
|
|
735
880
|
const { v, t } = pending2[key];
|
|
736
881
|
if (t.length === 0 || !value) {
|
|
882
|
+
const oldValue = clone(value);
|
|
883
|
+
pending2[key].p = oldValue;
|
|
737
884
|
if (isObject(value) && isObject(v)) {
|
|
738
885
|
Object.assign(value, v);
|
|
739
886
|
} else {
|
|
@@ -746,6 +893,8 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
746
893
|
delete pending2[key];
|
|
747
894
|
didChangeMetadata = true;
|
|
748
895
|
} else {
|
|
896
|
+
const oldValue = clone(value);
|
|
897
|
+
pending2[key].p = getValueAtPath(oldValue, p);
|
|
749
898
|
value = setAtPath(
|
|
750
899
|
value,
|
|
751
900
|
p,
|
|
@@ -765,18 +914,27 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
765
914
|
}
|
|
766
915
|
}
|
|
767
916
|
});
|
|
768
|
-
if (didChangeMetadata) {
|
|
769
|
-
updateMetadata(obs$, localState, syncState
|
|
917
|
+
if (didChangeMetadata && syncOptions.persist) {
|
|
918
|
+
updateMetadata(obs$, localState, syncState$, syncOptions, {
|
|
770
919
|
pending: pending2
|
|
771
920
|
});
|
|
772
921
|
}
|
|
773
922
|
}
|
|
774
923
|
onChangeRemote(() => {
|
|
775
|
-
if (
|
|
924
|
+
if (isPlainObject(value)) {
|
|
925
|
+
value = ObservableHint.plain(value);
|
|
926
|
+
}
|
|
927
|
+
if (mode === "assign") {
|
|
776
928
|
obs$.assign(value);
|
|
777
|
-
} else if (mode === "append"
|
|
929
|
+
} else if (mode === "append") {
|
|
930
|
+
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
|
|
931
|
+
console.error("[legend-state] mode:append expects the value to be an array");
|
|
932
|
+
}
|
|
778
933
|
obs$.push(...value);
|
|
779
|
-
} else if (mode === "prepend"
|
|
934
|
+
} else if (mode === "prepend") {
|
|
935
|
+
if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !isArray(value)) {
|
|
936
|
+
console.error("[legend-state] mode:prepend expects the value to be an array");
|
|
937
|
+
}
|
|
780
938
|
obs$.splice(0, 0, ...value);
|
|
781
939
|
} else if (mode === "merge") {
|
|
782
940
|
mergeIntoObservable(obs$, value);
|
|
@@ -786,78 +944,180 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
786
944
|
});
|
|
787
945
|
}
|
|
788
946
|
if (lastSync2 && syncOptions.persist) {
|
|
789
|
-
updateMetadata(obs$, localState, syncState
|
|
947
|
+
updateMetadata(obs$, localState, syncState$, syncOptions, {
|
|
790
948
|
lastSync: lastSync2
|
|
791
949
|
});
|
|
792
950
|
}
|
|
793
951
|
};
|
|
794
|
-
|
|
795
|
-
|
|
952
|
+
if (node.activationState) {
|
|
953
|
+
node.activationState.onChange = onChange;
|
|
954
|
+
}
|
|
955
|
+
if (!isSubscribed && syncOptions.subscribe) {
|
|
956
|
+
const subscribe = syncOptions.subscribe;
|
|
957
|
+
isSubscribed = true;
|
|
958
|
+
const doSubscribe = () => {
|
|
959
|
+
const subscribeParams = {
|
|
960
|
+
node,
|
|
961
|
+
value$: obs$,
|
|
962
|
+
lastSync,
|
|
963
|
+
update: (params) => {
|
|
964
|
+
when(syncState$.isLoaded, () => {
|
|
965
|
+
when(waitFor || true, () => {
|
|
966
|
+
params.mode || (params.mode = syncOptions.mode || "merge");
|
|
967
|
+
onChange(params);
|
|
968
|
+
});
|
|
969
|
+
});
|
|
970
|
+
},
|
|
971
|
+
refresh: () => when(syncState$.isLoaded, sync),
|
|
972
|
+
onError: (error) => onGetError(error, { source: "subscribe", subscribeParams })
|
|
973
|
+
};
|
|
974
|
+
unsubscribe = subscribe(subscribeParams);
|
|
975
|
+
};
|
|
976
|
+
if (waitFor) {
|
|
977
|
+
whenReady(waitFor, doSubscribe);
|
|
978
|
+
} else {
|
|
979
|
+
doSubscribe();
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
const existingValue = getNodeValue(node);
|
|
983
|
+
const onError = (error) => onGetError(error, { getParams, source: "get" });
|
|
984
|
+
const getParams = {
|
|
985
|
+
node,
|
|
796
986
|
value$: obs$,
|
|
987
|
+
value: isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked]) ? void 0 : existingValue,
|
|
988
|
+
mode: syncOptions.mode,
|
|
989
|
+
refresh: sync,
|
|
797
990
|
options: syncOptions,
|
|
798
991
|
lastSync,
|
|
799
|
-
|
|
800
|
-
onError
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
992
|
+
updateLastSync: (lastSync2) => getParams.lastSync = lastSync2,
|
|
993
|
+
onError,
|
|
994
|
+
retryNum: 0,
|
|
995
|
+
cancelRetry: false
|
|
996
|
+
};
|
|
997
|
+
let modeBeforeReset = void 0;
|
|
998
|
+
const beforeGetParams = {
|
|
999
|
+
value: getParams.value,
|
|
1000
|
+
lastSync,
|
|
1001
|
+
pendingChanges: pending && !isEmpty(pending) ? pending : void 0,
|
|
1002
|
+
clearPendingChanges: async () => {
|
|
1003
|
+
localState.pendingChanges = {};
|
|
1004
|
+
await updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
|
|
1005
|
+
pending: localState.pendingChanges
|
|
808
1006
|
});
|
|
809
1007
|
},
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
refresh: () => when(node.state.isLoaded, sync)
|
|
1008
|
+
resetCache: () => {
|
|
1009
|
+
var _a3;
|
|
1010
|
+
modeBeforeReset = getParams.mode;
|
|
1011
|
+
getParams.mode = "set";
|
|
1012
|
+
return (_a3 = syncStateValue.resetPersistence) == null ? void 0 : _a3.call(syncStateValue);
|
|
1013
|
+
},
|
|
1014
|
+
cancel: false
|
|
1015
|
+
};
|
|
1016
|
+
(_a2 = syncOptions.onBeforeGet) == null ? void 0 : _a2.call(syncOptions, beforeGetParams);
|
|
1017
|
+
if (!beforeGetParams.cancel) {
|
|
1018
|
+
syncState$.assign({
|
|
1019
|
+
numPendingGets: (syncStateValue.numPendingGets || 0) + 1,
|
|
1020
|
+
isGetting: true
|
|
824
1021
|
});
|
|
1022
|
+
const got = runWithRetry(
|
|
1023
|
+
getParams,
|
|
1024
|
+
syncOptions.retry,
|
|
1025
|
+
(retryEvent) => {
|
|
1026
|
+
const params = getParams;
|
|
1027
|
+
params.cancelRetry = retryEvent.cancelRetry;
|
|
1028
|
+
params.retryNum = retryEvent.retryNum;
|
|
1029
|
+
return get(params);
|
|
1030
|
+
},
|
|
1031
|
+
onError
|
|
1032
|
+
);
|
|
1033
|
+
const numGets = node.numGets = (node.numGets || 0) + 1;
|
|
1034
|
+
const handle = (value) => {
|
|
1035
|
+
syncState$.numPendingGets.set((v) => v - 1);
|
|
1036
|
+
if (isWaitingForLoad) {
|
|
1037
|
+
isWaitingForLoad = false;
|
|
1038
|
+
syncStateValue.numPendingRemoteLoads--;
|
|
1039
|
+
}
|
|
1040
|
+
if (numGets >= (node.getNumResolved || 0)) {
|
|
1041
|
+
node.getNumResolved = node.numGets;
|
|
1042
|
+
onChange({
|
|
1043
|
+
value,
|
|
1044
|
+
lastSync: getParams.lastSync,
|
|
1045
|
+
mode: getParams.mode
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
if (modeBeforeReset) {
|
|
1049
|
+
getParams.mode = modeBeforeReset;
|
|
1050
|
+
modeBeforeReset = void 0;
|
|
1051
|
+
}
|
|
1052
|
+
syncState$.assign({
|
|
1053
|
+
isLoaded: syncStateValue.numPendingRemoteLoads < 1,
|
|
1054
|
+
error: void 0,
|
|
1055
|
+
isGetting: syncStateValue.numPendingGets > 0
|
|
1056
|
+
});
|
|
1057
|
+
};
|
|
1058
|
+
if (isPromise$1(got)) {
|
|
1059
|
+
got.then(handle).catch(onError);
|
|
1060
|
+
} else {
|
|
1061
|
+
handle(got);
|
|
1062
|
+
}
|
|
825
1063
|
}
|
|
826
1064
|
};
|
|
827
|
-
|
|
1065
|
+
if (waitFor) {
|
|
1066
|
+
whenReady(waitFor, () => trackSelector(runGet, sync));
|
|
1067
|
+
} else {
|
|
1068
|
+
trackSelector(runGet, sync);
|
|
1069
|
+
}
|
|
828
1070
|
} else {
|
|
829
|
-
|
|
1071
|
+
syncState$.assign({
|
|
830
1072
|
isLoaded: true,
|
|
831
1073
|
error: void 0
|
|
832
1074
|
});
|
|
833
1075
|
}
|
|
834
1076
|
if (!isSynced) {
|
|
835
1077
|
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
|
-
}
|
|
1078
|
+
await when(syncState$.isLoaded);
|
|
1079
|
+
applyPending(pending);
|
|
857
1080
|
}
|
|
858
1081
|
};
|
|
859
|
-
|
|
1082
|
+
syncStateValue.sync = sync;
|
|
1083
|
+
} else {
|
|
1084
|
+
if (!isSynced) {
|
|
1085
|
+
applyPending(localState.pendingChanges);
|
|
1086
|
+
}
|
|
860
1087
|
}
|
|
1088
|
+
syncStateValue.reset = async () => {
|
|
1089
|
+
const wasPersistEnabled = syncStateValue.isPersistEnabled;
|
|
1090
|
+
const wasSyncEnabled = syncStateValue.isSyncEnabled;
|
|
1091
|
+
const metadata = metadatas.get(obs$);
|
|
1092
|
+
if (metadata) {
|
|
1093
|
+
Object.assign(metadata, { lastSync: void 0, pending: void 0 });
|
|
1094
|
+
}
|
|
1095
|
+
Object.assign(syncStateValue, {
|
|
1096
|
+
isPersistEnabled: false,
|
|
1097
|
+
isSyncEnabled: false,
|
|
1098
|
+
lastSync: void 0,
|
|
1099
|
+
numPendingGets: 0,
|
|
1100
|
+
isLoaded: false,
|
|
1101
|
+
isGetting: false,
|
|
1102
|
+
isSetting: false,
|
|
1103
|
+
numPendingSets: 0,
|
|
1104
|
+
syncCount: 0
|
|
1105
|
+
});
|
|
1106
|
+
isSynced = false;
|
|
1107
|
+
isSubscribed = false;
|
|
1108
|
+
unsubscribe == null ? void 0 : unsubscribe();
|
|
1109
|
+
unsubscribe = void 0;
|
|
1110
|
+
const promise = syncStateValue.resetPersistence();
|
|
1111
|
+
onChangeRemote(() => {
|
|
1112
|
+
var _a;
|
|
1113
|
+
obs$.set((_a = syncOptions.initial) != null ? _a : void 0);
|
|
1114
|
+
});
|
|
1115
|
+
syncState$.isLoaded.set(false);
|
|
1116
|
+
syncStateValue.isPersistEnabled = wasPersistEnabled;
|
|
1117
|
+
syncStateValue.isSyncEnabled = wasSyncEnabled;
|
|
1118
|
+
node.dirtyFn = sync;
|
|
1119
|
+
await promise;
|
|
1120
|
+
};
|
|
861
1121
|
const onAllPersistLoaded = () => {
|
|
862
1122
|
var _a, _b;
|
|
863
1123
|
let parentNode = node;
|
|
@@ -875,77 +1135,27 @@ function syncObservable(obs$, syncOptionsOrSynced) {
|
|
|
875
1135
|
}
|
|
876
1136
|
if ((syncOptions == null ? void 0 : syncOptions.set) || (syncOptions == null ? void 0 : syncOptions.persist)) {
|
|
877
1137
|
obs$.onChange(
|
|
878
|
-
onObsChange.bind(this, obs$, syncState
|
|
1138
|
+
onObsChange.bind(this, obs$, syncState$, localState, syncOptions)
|
|
879
1139
|
);
|
|
880
1140
|
}
|
|
881
1141
|
});
|
|
882
|
-
return syncState
|
|
1142
|
+
return syncState$;
|
|
883
1143
|
}
|
|
884
|
-
var { getProxy, globalState: globalState2,
|
|
1144
|
+
var { getProxy, globalState: globalState2, setNodeValue, getNodeValue: getNodeValue2 } = internal;
|
|
885
1145
|
function enableActivateSyncedNode() {
|
|
886
1146
|
globalState2.activateSyncedNode = function activateSyncedNode(node, newValue) {
|
|
887
1147
|
const obs$ = getProxy(node);
|
|
888
1148
|
if (node.activationState) {
|
|
889
|
-
const {
|
|
890
|
-
|
|
891
|
-
|
|
1149
|
+
const {
|
|
1150
|
+
get: getOrig,
|
|
1151
|
+
initial,
|
|
1152
|
+
set,
|
|
1153
|
+
onChange
|
|
1154
|
+
} = node.activationState;
|
|
892
1155
|
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
|
-
}
|
|
1156
|
+
const get = getOrig ? (params) => {
|
|
1157
|
+
return promiseReturn = getOrig(params);
|
|
1158
|
+
} : void 0;
|
|
949
1159
|
const nodeVal = getNodeValue2(node);
|
|
950
1160
|
if (promiseReturn !== void 0) {
|
|
951
1161
|
newValue = promiseReturn;
|
|
@@ -955,13 +1165,13 @@ function enableActivateSyncedNode() {
|
|
|
955
1165
|
newValue = initial;
|
|
956
1166
|
}
|
|
957
1167
|
setNodeValue(node, promiseReturn ? void 0 : newValue);
|
|
958
|
-
|
|
1168
|
+
syncObservable(obs$, { ...node.activationState, get, set });
|
|
959
1169
|
return { update: onChange, value: newValue };
|
|
960
1170
|
} else {
|
|
961
1171
|
let update = void 0;
|
|
962
1172
|
const get = async (params) => {
|
|
963
1173
|
update = params.refresh;
|
|
964
|
-
if (isPromise(newValue)) {
|
|
1174
|
+
if (isPromise$1(newValue)) {
|
|
965
1175
|
try {
|
|
966
1176
|
newValue = await newValue;
|
|
967
1177
|
} catch (e) {
|
|
@@ -992,13 +1202,20 @@ function installPersistActivateNode() {
|
|
|
992
1202
|
didInstall = true;
|
|
993
1203
|
}
|
|
994
1204
|
}
|
|
1205
|
+
var { deepMerge: deepMerge2 } = internal;
|
|
1206
|
+
function configureSynced(fnOrOrigOptions, origOptions) {
|
|
1207
|
+
const fn = origOptions ? fnOrOrigOptions : synced;
|
|
1208
|
+
origOptions = origOptions != null ? origOptions : fnOrOrigOptions;
|
|
1209
|
+
return (options) => {
|
|
1210
|
+
const merged = deepMerge2(origOptions, options);
|
|
1211
|
+
return fn(merged);
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
995
1214
|
|
|
996
1215
|
// sync.ts
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
var internal3 = {
|
|
1001
|
-
observableSyncConfiguration
|
|
1216
|
+
var internal4 = {
|
|
1217
|
+
observableSyncConfiguration,
|
|
1218
|
+
waitForSet
|
|
1002
1219
|
};
|
|
1003
1220
|
|
|
1004
|
-
export { combineTransforms, configureObservableSync, deepEqual, diffObjects,
|
|
1221
|
+
export { combineTransforms, configureObservableSync, configureSynced, deepEqual, diffObjects, internal4 as internal, mapSyncPlugins, onChangeRemote, removeNullUndefined, syncObservable, synced, transformStringifyDates, transformStringifyKeys };
|