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