@legendapp/state 3.0.0-alpha.3 → 3.0.0-alpha.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/CHANGELOG.md +831 -1
  2. package/LICENSE +21 -1
  3. package/README.md +141 -1
  4. package/babel.js +0 -2
  5. package/babel.mjs +0 -2
  6. package/config/enable$GetSet.js +2 -1
  7. package/config/enable$GetSet.mjs +2 -1
  8. package/config/enableReactTracking.js +2 -1
  9. package/config/enableReactTracking.mjs +2 -1
  10. package/config/enableReactUse.js +2 -1
  11. package/config/enableReactUse.mjs +2 -1
  12. package/config/enable_PeekAssign.js +2 -1
  13. package/config/enable_PeekAssign.mjs +2 -1
  14. package/config.d.mts +13 -0
  15. package/config.d.ts +13 -0
  16. package/config.js +2066 -0
  17. package/config.mjs +2064 -0
  18. package/helpers/trackHistory.js +2 -2
  19. package/helpers/trackHistory.mjs +2 -2
  20. package/index.d.mts +25 -302
  21. package/index.d.ts +25 -302
  22. package/index.js +293 -322
  23. package/index.mjs +294 -321
  24. package/observableInterfaces-CZR3_8mM.d.mts +283 -0
  25. package/observableInterfaces-CZR3_8mM.d.ts +283 -0
  26. package/package.json +11 -1
  27. package/persist-plugins/async-storage.d.mts +6 -3
  28. package/persist-plugins/async-storage.d.ts +6 -3
  29. package/persist-plugins/async-storage.js +12 -4
  30. package/persist-plugins/async-storage.mjs +12 -5
  31. package/persist-plugins/indexeddb.d.mts +6 -4
  32. package/persist-plugins/indexeddb.d.ts +6 -4
  33. package/persist-plugins/indexeddb.js +16 -6
  34. package/persist-plugins/indexeddb.mjs +16 -7
  35. package/persist-plugins/mmkv.d.mts +5 -1
  36. package/persist-plugins/mmkv.d.ts +5 -1
  37. package/persist-plugins/mmkv.js +14 -5
  38. package/persist-plugins/mmkv.mjs +14 -6
  39. package/react.d.mts +18 -14
  40. package/react.d.ts +18 -14
  41. package/react.js +57 -32
  42. package/react.mjs +58 -33
  43. package/sync-plugins/crud.d.mts +21 -24
  44. package/sync-plugins/crud.d.ts +21 -24
  45. package/sync-plugins/crud.js +240 -139
  46. package/sync-plugins/crud.mjs +242 -141
  47. package/sync-plugins/fetch.js +12 -8
  48. package/sync-plugins/fetch.mjs +13 -9
  49. package/sync-plugins/firebase.d.mts +27 -0
  50. package/sync-plugins/firebase.d.ts +27 -0
  51. package/sync-plugins/firebase.js +373 -0
  52. package/sync-plugins/firebase.mjs +368 -0
  53. package/sync-plugins/keel.d.mts +27 -10
  54. package/sync-plugins/keel.d.ts +27 -10
  55. package/sync-plugins/keel.js +51 -32
  56. package/sync-plugins/keel.mjs +52 -33
  57. package/sync-plugins/supabase.d.mts +12 -7
  58. package/sync-plugins/supabase.d.ts +12 -7
  59. package/sync-plugins/supabase.js +24 -13
  60. package/sync-plugins/supabase.mjs +25 -14
  61. package/sync-plugins/tanstack-query.d.mts +2 -2
  62. package/sync-plugins/tanstack-query.d.ts +2 -2
  63. package/sync-plugins/tanstack-query.js +3 -2
  64. package/sync-plugins/tanstack-query.mjs +3 -2
  65. package/sync-plugins/tanstack-react-query.d.mts +1 -1
  66. package/sync-plugins/tanstack-react-query.d.ts +1 -1
  67. package/sync.d.mts +71 -197
  68. package/sync.d.ts +71 -197
  69. package/sync.js +465 -284
  70. package/sync.mjs +471 -290
  71. package/types/babel.d.ts +12 -1
  72. package/.DS_Store +0 -0
  73. /package/config/{enable_GetSet.d.mts → enable$GetSet.d.mts} +0 -0
  74. /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
- function syncObservableAdapter({ get, set }) {
143
- const ret = {};
144
- if (get) {
145
- ret.get = async (params) => {
146
- try {
147
- let value = get(params);
148
- if (state.isPromise(value)) {
149
- value = await value;
150
- }
151
- params.onChange({
152
- value,
153
- lastSync: params.lastSync,
154
- mode: params.mode
140
+
141
+ // src/is.ts
142
+ function isPromise(obj) {
143
+ return obj instanceof Promise;
144
+ }
145
+
146
+ // src/sync/retry.ts
147
+ function calculateRetryDelay(retryOptions, retryNum) {
148
+ const { backoff, delay = 1e3, infinite, times = 3, maxDelay = 3e4 } = retryOptions;
149
+ if (infinite || retryNum < times) {
150
+ const delayTime = Math.min(delay * (backoff === "constant" ? 1 : 2 ** retryNum), maxDelay);
151
+ return delayTime;
152
+ }
153
+ return null;
154
+ }
155
+ function createRetryTimeout(retryOptions, retryNum, fn) {
156
+ const delayTime = calculateRetryDelay(retryOptions, retryNum);
157
+ if (delayTime) {
158
+ return setTimeout(fn, delayTime);
159
+ } else {
160
+ return false;
161
+ }
162
+ }
163
+ var mapRetryTimeouts = /* @__PURE__ */ new Map();
164
+ function runWithRetry(state, retryOptions, fn, onError) {
165
+ let value = fn(state);
166
+ if (isPromise(value) && retryOptions) {
167
+ let timeoutRetry;
168
+ if (mapRetryTimeouts.has(state.node)) {
169
+ clearTimeout(mapRetryTimeouts.get(state.node));
170
+ }
171
+ return new Promise((resolve, reject) => {
172
+ const run = () => {
173
+ value.then((val) => {
174
+ resolve(val);
175
+ }).catch((error) => {
176
+ state.retryNum++;
177
+ if (timeoutRetry) {
178
+ clearTimeout(timeoutRetry);
179
+ }
180
+ if (onError) {
181
+ onError(error);
182
+ }
183
+ if (!state.cancelRetry) {
184
+ const timeout = createRetryTimeout(retryOptions, state.retryNum, () => {
185
+ value = fn(state);
186
+ run();
187
+ });
188
+ if (timeout === false) {
189
+ state.cancelRetry = true;
190
+ reject(error);
191
+ } else {
192
+ mapRetryTimeouts.set(state.node, timeout);
193
+ timeoutRetry = timeout;
194
+ }
195
+ }
155
196
  });
156
- params.onGet();
157
- } catch (e) {
158
- }
159
- };
197
+ };
198
+ run();
199
+ });
160
200
  }
161
- if (set) {
162
- ret.set = set;
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 { createPreviousHandler, clone, getValueAtPath, globalState, symbolLinked, getNode, getNodeValue } = state.internal;
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 = state.deconstructObjectWithPath(path, pathTypes, saved);
233
+ const saved = await transform.save(constructed);
234
+ value = saved;
235
+ const outPath = [];
236
+ for (let i = 0; i < path.length; i++) {
237
+ outPath[i] = Object.keys(value)[0];
238
+ value = value[outPath[i]];
239
+ }
240
+ path = outPath;
191
241
  }
192
- return value;
242
+ return { value, path };
193
243
  }
194
244
  function transformLoadData(value, { transform }, doUserTransform, method) {
195
245
  if (doUserTransform && (transform == null ? void 0 : transform.load)) {
@@ -197,7 +247,7 @@ function transformLoadData(value, { transform }, doUserTransform, method) {
197
247
  }
198
248
  return value;
199
249
  }
200
- async function updateMetadataImmediate(value$, localState, syncState, syncOptions, newMetadata) {
250
+ async function updateMetadataImmediate(value$, localState, syncState2, syncOptions, newMetadata) {
201
251
  const saves = Array.from(promisesLocalSaves);
202
252
  if (saves.length > 0) {
203
253
  await Promise.all(saves);
@@ -212,17 +262,17 @@ async function updateMetadataImmediate(value$, localState, syncState, syncOption
212
262
  await pluginPersist.setMetadata(table, metadata, config);
213
263
  }
214
264
  if (lastSync) {
215
- syncState.assign({
265
+ syncState2.assign({
216
266
  lastSync
217
267
  });
218
268
  }
219
269
  }
220
- function updateMetadata(value$, localState, syncState, syncOptions, newMetadata) {
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, syncState, syncOptions, newMetadata),
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 changesByObsRemote = /* @__PURE__ */ new Map();
254
- const changesByObsLocal = /* @__PURE__ */ new Map();
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 { value$: obs, changes, inRemoteChange, getPrevious } = value;
309
+ const { changes, inRemoteChange, syncOptions } = value;
261
310
  const targetMap = inRemoteChange ? outRemote : outLocal;
262
- const changesMap = inRemoteChange ? changesByObsRemote : changesByObsLocal;
263
- const existing = changesMap.get(obs);
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(obs, merged);
315
+ changesMap.set(syncOptions, merged);
267
316
  value.changes = merged;
268
- if (!previousByObs.has(obs)) {
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, localState, syncOptions, inRemoteChange, isApplyingPending } = queuedChange;
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 configRemote = syncOptions;
323
- const saveLocal = (persist == null ? void 0 : persist.name) && !configLocal.readonly && !isApplyingPending && syncState.isPersistEnabled.peek();
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 && !syncState.isPersistLoaded.peek()) {
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 configRemote = syncOptions;
393
- const saveLocal = persist && !configLocal.readonly && !isApplyingPending && syncState.isPersistEnabled.peek();
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 && !syncState.isPersistLoaded.peek()) {
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
- configRemote || {}
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 < path.length - 1; i2++) {
436
- const pathParent = path.slice(0, i2 + 1).join("/");
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 = path.slice(i2 + 1);
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 { table, config: configLocal } = parseLocalConfig(persist);
488
- const shouldSaveMetadata = persist == null ? void 0 : persist.retrySync;
489
- if (saveRemote && shouldSaveMetadata) {
490
- await updateMetadataImmediate(obs, localState, syncState, syncOptions, {
491
- pending: localState.pendingChanges
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
- promisesLocalSaves.add(promiseSet);
501
- await promiseSet;
534
+ }
535
+ if (changesLocal.length > 0) {
536
+ let promiseSet = pluginPersist.set(table, changesLocal, configLocal);
537
+ if (promiseSet) {
538
+ promiseSet = promiseSet.then(() => {
539
+ promisesLocalSaves.delete(promiseSet);
540
+ });
541
+ promisesLocalSaves.add(promiseSet);
542
+ await promiseSet;
543
+ }
502
544
  }
503
545
  }
504
546
  }
@@ -507,47 +549,96 @@ async function doChangeRemote(changeInfo) {
507
549
  if (!changeInfo)
508
550
  return;
509
551
  const { queuedChange, changesRemote } = changeInfo;
510
- const { value$: obs, syncState, localState, syncOptions, valuePrevious: previous } = queuedChange;
511
- const { pluginPersist, pluginSync } = localState;
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 { allowSetIfGetError, onBeforeSet, onSetError, waitForSet, onAfterSet } = syncOptions || {};
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
- await state.when(() => syncState.isLoaded.get() || allowSetIfGetError && syncState.error.get());
518
- if (waitForSet) {
519
- const waitFor = state.isFunction(waitForSet) ? waitForSet({ changes: changesRemote, value: obs.peek() }) : waitForSet;
520
- if (waitFor) {
521
- await state.when(waitFor);
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
- let value = obs.peek();
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(clone(value));
582
+ value = transformSave(value);
528
583
  }
584
+ state$.numPendingSets.set((v) => (v || 0) + 1);
585
+ state$.isSetting.set(true);
529
586
  onBeforeSet == null ? void 0 : onBeforeSet();
530
- localState.numSavesOutstanding = (localState.numSavesOutstanding || 0) + 1;
531
- let savedPromise = pluginSync.set({
532
- value$: obs,
533
- syncState,
534
- options: syncOptions,
587
+ let updateResult = void 0;
588
+ const onError = (error) => {
589
+ var _a2;
590
+ state$.error.set(error);
591
+ (_a2 = syncOptions.onSetError) == null ? void 0 : _a2.call(syncOptions, error, {
592
+ setParams,
593
+ source: "set",
594
+ value$: obs$
595
+ });
596
+ };
597
+ const setParams = {
598
+ node,
599
+ value$: obs$,
535
600
  changes: changesRemote,
536
601
  value,
537
- valuePrevious: previous
538
- });
602
+ onError,
603
+ update: (params) => {
604
+ if (updateResult) {
605
+ const { value: value2, lastSync, mode } = params;
606
+ updateResult = {
607
+ lastSync: Math.max(updateResult.lastSync || 0, lastSync || 0),
608
+ value: deepMerge(updateResult.value, value2),
609
+ mode
610
+ };
611
+ } else {
612
+ updateResult = params;
613
+ }
614
+ },
615
+ refresh: syncState2.sync,
616
+ retryNum: 0,
617
+ cancelRetry: false
618
+ };
619
+ let savedPromise = runWithRetry(
620
+ setParams,
621
+ syncOptions.retry,
622
+ async () => {
623
+ return syncOptions.set(setParams);
624
+ },
625
+ onError
626
+ );
627
+ let didError = false;
539
628
  if (state.isPromise(savedPromise)) {
540
- savedPromise = savedPromise.catch((err) => onSetError == null ? void 0 : onSetError(err));
629
+ savedPromise = savedPromise.catch((error) => {
630
+ didError = true;
631
+ onError(error);
632
+ });
633
+ await savedPromise;
541
634
  }
542
- const saved = await savedPromise;
543
- localState.numSavesOutstanding--;
544
- if (saved !== void 0) {
635
+ if (!didError) {
545
636
  const pathStrs = Array.from(new Set(changesRemote.map((change) => change.pathStr)));
546
- const { changes, lastSync } = saved;
637
+ const { value: changes, lastSync } = updateResult || {};
547
638
  if (pathStrs.length > 0) {
548
639
  let transformedChanges = void 0;
549
640
  const metadata = {};
550
- if (persist) {
641
+ if (saveLocal) {
551
642
  const pendingMetadata = (_b = pluginPersist.getMetadata(table, configLocal)) == null ? void 0 : _b.pending;
552
643
  const pending = localState.pendingChanges;
553
644
  for (let i = 0; i < pathStrs.length; i++) {
@@ -567,42 +658,31 @@ async function doChangeRemote(changeInfo) {
567
658
  if (changes && !state.isEmpty(changes)) {
568
659
  transformedChanges = transformLoadData(changes, syncOptions, false, "set");
569
660
  }
570
- if (localState.numSavesOutstanding > 0) {
571
- if (transformedChanges) {
572
- if (!localState.pendingSaveResults) {
573
- localState.pendingSaveResults = [];
574
- }
575
- localState.pendingSaveResults.push(transformedChanges);
661
+ if (transformedChanges !== void 0) {
662
+ if (state.isPromise(transformedChanges)) {
663
+ transformedChanges = await transformedChanges;
576
664
  }
577
- } else {
578
- let allChanges = [...localState.pendingSaveResults || [], transformedChanges].filter(
579
- (v) => v !== void 0
580
- );
581
- if (allChanges.length > 0) {
582
- if (allChanges.some((change) => state.isPromise(change))) {
583
- allChanges = await Promise.all(allChanges);
584
- }
585
- onChangeRemote(() => state.mergeIntoObservable(obs, ...allChanges));
586
- }
587
- if (persist) {
588
- if (shouldSaveMetadata && !state.isEmpty(metadata)) {
589
- updateMetadata(obs, localState, syncState, syncOptions, metadata);
590
- }
665
+ onChangeRemote(() => state.mergeIntoObservable(obs$, transformedChanges));
666
+ }
667
+ if (saveLocal) {
668
+ if (shouldSaveMetadata && !state.isEmpty(metadata)) {
669
+ updateMetadata(obs$, localState, syncState2, syncOptions, metadata);
591
670
  }
592
- localState.pendingSaveResults = [];
593
671
  }
594
- onAfterSet == null ? void 0 : onAfterSet();
595
672
  }
673
+ state$.numPendingSets.set((v) => v - 1);
674
+ state$.isSetting.set(state$.numPendingSets.peek() > 0);
675
+ onAfterSet == null ? void 0 : onAfterSet();
596
676
  }
597
677
  }
598
678
  }
599
- function onObsChange(value$, syncState, localState, syncOptions, { changes, loading, remote, getPrevious }) {
600
- if (!loading) {
601
- const inRemoteChange = remote;
679
+ function onObsChange(value$, syncState2, localState, syncOptions, { changes, isFromPersist, isFromSync, getPrevious }) {
680
+ if (!isFromPersist) {
681
+ const inRemoteChange = isFromSync;
602
682
  const isApplyingPending = localState.isApplyingPending;
603
683
  _queuedChanges.push({
604
684
  value$,
605
- syncState,
685
+ syncState: syncState2,
606
686
  localState,
607
687
  syncOptions,
608
688
  changes,
@@ -615,13 +695,17 @@ function onObsChange(value$, syncState, localState, syncOptions, { changes, load
615
695
  }
616
696
  }
617
697
  }
618
- async function loadLocal(value$, syncOptions, syncState, localState) {
698
+ async function loadLocal(value$, syncOptions, syncState$, localState) {
619
699
  var _a, _b, _c;
620
700
  const { persist } = syncOptions;
621
- if (persist) {
701
+ const node = getNode(value$);
702
+ const nodeValue = getNodeValue(getNode(node.state));
703
+ const syncStateValue = syncState$.peek();
704
+ const prevClearPersist = nodeValue.clearPersist;
705
+ if (persist == null ? void 0 : persist.name) {
622
706
  const PersistPlugin = persist.plugin || ((_a = observableSyncConfiguration.persist) == null ? void 0 : _a.plugin);
623
707
  const { table, config } = parseLocalConfig(persist);
624
- const node = getNode(value$);
708
+ syncStateValue.numPendingLocalLoads = (syncStateValue.numPendingLocalLoads || 0) + 1;
625
709
  if (!PersistPlugin) {
626
710
  throw new Error("Local persist is not configured");
627
711
  }
@@ -655,7 +739,7 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
655
739
  if (metadata) {
656
740
  metadatas.set(value$, metadata);
657
741
  localState.pendingChanges = metadata.pending;
658
- syncState.assign({
742
+ syncState$.assign({
659
743
  lastSync: metadata.lastSync
660
744
  });
661
745
  }
@@ -673,12 +757,18 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
673
757
  }
674
758
  state.internal.globalState.isLoadingLocal = false;
675
759
  }
676
- getNodeValue(getNode(node.state)).clearPersist = () => Promise.all([
677
- persistPlugin.deleteTable(table, config),
678
- persistPlugin.deleteMetadata(table, config)
679
- ]);
760
+ syncStateValue.numPendingLocalLoads--;
761
+ nodeValue.clearPersist = () => Promise.all(
762
+ [
763
+ prevClearPersist,
764
+ persistPlugin.deleteTable(table, config),
765
+ persistPlugin.deleteMetadata(table, config)
766
+ ].filter(Boolean)
767
+ );
768
+ } else {
769
+ nodeValue.clearPersist = () => prevClearPersist == null ? void 0 : prevClearPersist();
680
770
  }
681
- syncState.isPersistLoaded.set(true);
771
+ syncState$.isPersistLoaded.set(!(syncStateValue.numPendingLocalLoads > 0));
682
772
  }
683
773
  function syncObservable(obs$, syncOptionsOrSynced) {
684
774
  let syncOptions = syncOptionsOrSynced;
@@ -689,7 +779,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
689
779
  if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && (!obs$ || !node)) {
690
780
  throw new Error("[legend-state] syncObservable called with undefined observable");
691
781
  }
692
- syncOptions = state.mergeIntoObservable(
782
+ syncOptions = deepMerge(
693
783
  {
694
784
  syncMode: "auto"
695
785
  },
@@ -698,24 +788,50 @@ function syncObservable(obs$, syncOptionsOrSynced) {
698
788
  );
699
789
  const localState = {};
700
790
  let sync;
701
- const syncState = node.state = state.observable({
702
- isPersistLoaded: false,
703
- isLoaded: !syncOptions.get,
704
- isPersistEnabled: true,
705
- isSyncEnabled: true,
706
- clearPersist: void 0,
707
- sync: () => Promise.resolve(),
708
- getPendingChanges: () => localState.pendingChanges
709
- });
710
- loadLocal(obs$, syncOptions, syncState, localState);
711
- localState.pluginSync = syncObservableAdapter(syncOptions);
791
+ const syncState$ = state.syncState(obs$);
792
+ const syncStateValue = getNodeValue(getNode(syncState$));
793
+ allSyncStates.set(syncState$, node);
794
+ syncStateValue.getPendingChanges = () => localState.pendingChanges;
795
+ const onGetError = (error, params) => {
796
+ var _a;
797
+ syncState$.error.set(error);
798
+ (_a = syncOptions.onGetError) == null ? void 0 : _a.call(syncOptions, error, { ...params, value$: obs$ });
799
+ };
800
+ loadLocal(obs$, syncOptions, syncState$, localState);
801
+ let isWaitingForLoad = !!syncOptions.get;
802
+ if (isWaitingForLoad) {
803
+ syncStateValue.numPendingRemoteLoads = (syncStateValue.numPendingRemoteLoads || 0) + 1;
804
+ }
805
+ syncState$.isLoaded.set(!syncState$.numPendingRemoteLoads.peek());
806
+ let isSynced = false;
807
+ let isSubscribed = false;
808
+ let unsubscribe = void 0;
809
+ const applyPending = (pending) => {
810
+ if (pending && !state.isEmpty(pending)) {
811
+ localState.isApplyingPending = true;
812
+ const keys = Object.keys(pending);
813
+ const changes = [];
814
+ for (let i = 0; i < keys.length; i++) {
815
+ const key = keys[i];
816
+ const path = key.split("/").filter((p2) => p2 !== "");
817
+ const { p, v, t } = pending[key];
818
+ changes.push({ path, valueAtPath: v, prevAtPath: p, pathTypes: t });
819
+ }
820
+ const value = getNodeValue(node);
821
+ onObsChange(obs$, syncState$, localState, syncOptions, {
822
+ value,
823
+ isFromPersist: false,
824
+ isFromSync: false,
825
+ getPrevious: createPreviousHandler(value, changes),
826
+ changes
827
+ });
828
+ localState.isApplyingPending = false;
829
+ }
830
+ };
712
831
  if (syncOptions.get) {
713
- let isSynced = false;
714
- let isSubscribed = false;
715
- let unsubscribe = void 0;
716
832
  sync = async () => {
717
- var _a, _b;
718
- if (isSynced && state.shouldIgnoreUnobserved(node, sync)) {
833
+ var _a;
834
+ if (isSynced && (!getNodeValue(getNode(syncState$)).isSyncEnabled || state.shouldIgnoreUnobserved(node, sync))) {
719
835
  if (unsubscribe) {
720
836
  isSubscribed = false;
721
837
  unsubscribe();
@@ -725,9 +841,11 @@ function syncObservable(obs$, syncOptionsOrSynced) {
725
841
  }
726
842
  const lastSync = (_a = metadatas.get(obs$)) == null ? void 0 : _a.lastSync;
727
843
  const pending = localState.pendingChanges;
728
- const get = (_b = localState.pluginSync.get) == null ? void 0 : _b.bind(localState.pluginSync);
844
+ const get = syncOptions.get;
729
845
  if (get) {
846
+ const { waitFor } = syncOptions;
730
847
  const runGet = () => {
848
+ var _a2;
731
849
  const onChange = async ({ value, mode, lastSync: lastSync2 }) => {
732
850
  mode = mode || syncOptions.mode || "set";
733
851
  if (value !== void 0) {
@@ -740,9 +858,11 @@ function syncObservable(obs$, syncOptionsOrSynced) {
740
858
  if (pending2) {
741
859
  let didChangeMetadata = false;
742
860
  Object.keys(pending2).forEach((key) => {
743
- const p = key.split("/").filter((p2) => p2 !== "");
861
+ const p = key.split("/").filter((k) => k !== "");
744
862
  const { v, t } = pending2[key];
745
863
  if (t.length === 0 || !value) {
864
+ const oldValue = clone(value);
865
+ pending2[key].p = oldValue;
746
866
  if (state.isObject(value) && state.isObject(v)) {
747
867
  Object.assign(value, v);
748
868
  } else {
@@ -755,6 +875,8 @@ function syncObservable(obs$, syncOptionsOrSynced) {
755
875
  delete pending2[key];
756
876
  didChangeMetadata = true;
757
877
  } else {
878
+ const oldValue = clone(value);
879
+ pending2[key].p = getValueAtPath(oldValue, p);
758
880
  value = state.setAtPath(
759
881
  value,
760
882
  p,
@@ -774,18 +896,24 @@ function syncObservable(obs$, syncOptionsOrSynced) {
774
896
  }
775
897
  }
776
898
  });
777
- if (didChangeMetadata) {
778
- updateMetadata(obs$, localState, syncState, syncOptions, {
899
+ if (didChangeMetadata && syncOptions.persist) {
900
+ updateMetadata(obs$, localState, syncState$, syncOptions, {
779
901
  pending: pending2
780
902
  });
781
903
  }
782
904
  }
783
905
  onChangeRemote(() => {
784
- if (mode === "assign" && state.isObject(value)) {
906
+ if (mode === "assign") {
785
907
  obs$.assign(value);
786
- } else if (mode === "append" && state.isArray(value)) {
908
+ } else if (mode === "append") {
909
+ if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !state.isArray(value)) {
910
+ console.error("[legend-state] mode:append expects the value to be an array");
911
+ }
787
912
  obs$.push(...value);
788
- } else if (mode === "prepend" && state.isArray(value)) {
913
+ } else if (mode === "prepend") {
914
+ if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !state.isArray(value)) {
915
+ console.error("[legend-state] mode:prepend expects the value to be an array");
916
+ }
789
917
  obs$.splice(0, 0, ...value);
790
918
  } else if (mode === "merge") {
791
919
  state.mergeIntoObservable(obs$, value);
@@ -795,78 +923,174 @@ function syncObservable(obs$, syncOptionsOrSynced) {
795
923
  });
796
924
  }
797
925
  if (lastSync2 && syncOptions.persist) {
798
- updateMetadata(obs$, localState, syncState, syncOptions, {
926
+ updateMetadata(obs$, localState, syncState$, syncOptions, {
799
927
  lastSync: lastSync2
800
928
  });
801
929
  }
802
930
  };
803
- get({
804
- state: syncState,
931
+ if (node.activationState) {
932
+ node.activationState.onChange = onChange;
933
+ }
934
+ if (!isSubscribed && syncOptions.subscribe) {
935
+ const subscribe = syncOptions.subscribe;
936
+ isSubscribed = true;
937
+ const doSubscribe = () => {
938
+ const subscribeParams = {
939
+ node,
940
+ value$: obs$,
941
+ lastSync,
942
+ update: (params) => {
943
+ state.when(syncState$.isLoaded, () => {
944
+ state.when(waitFor || true, () => {
945
+ params.mode || (params.mode = syncOptions.mode || "merge");
946
+ onChange(params);
947
+ });
948
+ });
949
+ },
950
+ refresh: () => state.when(syncState$.isLoaded, sync),
951
+ onError: (error) => onGetError(error, { source: "subscribe", subscribeParams })
952
+ };
953
+ unsubscribe = subscribe(subscribeParams);
954
+ };
955
+ if (waitFor) {
956
+ state.whenReady(waitFor, doSubscribe);
957
+ } else {
958
+ doSubscribe();
959
+ }
960
+ }
961
+ const existingValue = getNodeValue(node);
962
+ const onError = (error) => onGetError(error, { getParams, source: "get" });
963
+ const getParams = {
964
+ node,
805
965
  value$: obs$,
966
+ value: state.isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked]) ? void 0 : existingValue,
967
+ mode: syncOptions.mode,
968
+ refresh: sync,
806
969
  options: syncOptions,
807
970
  lastSync,
808
- dateModified: lastSync,
809
- onError: (error) => {
810
- var _a2;
811
- (_a2 = syncOptions.onGetError) == null ? void 0 : _a2.call(syncOptions, error);
812
- },
813
- onGet: () => {
814
- node.state.assign({
815
- isLoaded: true,
816
- error: void 0
971
+ updateLastSync: (lastSync2) => getParams.lastSync = lastSync2,
972
+ onError,
973
+ retryNum: 0,
974
+ cancelRetry: false
975
+ };
976
+ let modeBeforeReset = void 0;
977
+ (_a2 = syncOptions.onBeforeGet) == null ? void 0 : _a2.call(syncOptions, {
978
+ value: getParams.value,
979
+ lastSync,
980
+ pendingChanges: pending && !state.isEmpty(pending) ? pending : void 0,
981
+ clearPendingChanges: async () => {
982
+ localState.pendingChanges = {};
983
+ await updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
984
+ pending: localState.pendingChanges
817
985
  });
818
986
  },
819
- onChange
987
+ resetCache: () => {
988
+ var _a3;
989
+ modeBeforeReset = getParams.mode;
990
+ getParams.mode = "set";
991
+ return (_a3 = syncStateValue.clearPersist) == null ? void 0 : _a3.call(syncStateValue);
992
+ }
820
993
  });
821
- if (!isSubscribed && syncOptions.subscribe) {
822
- isSubscribed = true;
823
- unsubscribe = syncOptions.subscribe({
824
- node,
825
- value$: obs$,
826
- update: (params) => {
827
- state.when(node.state.isLoaded, () => {
828
- params.mode || (params.mode = syncOptions.mode || "merge");
829
- onChange(params);
830
- });
831
- },
832
- refresh: () => state.when(node.state.isLoaded, sync)
994
+ syncState$.assign({
995
+ numPendingGets: (syncStateValue.numPendingGets || 0) + 1,
996
+ isGetting: true
997
+ });
998
+ const got = runWithRetry(
999
+ getParams,
1000
+ syncOptions.retry,
1001
+ (retryEvent) => {
1002
+ const params = getParams;
1003
+ params.cancelRetry = retryEvent.cancelRetry;
1004
+ params.retryNum = retryEvent.retryNum;
1005
+ return get(params);
1006
+ },
1007
+ onError
1008
+ );
1009
+ const numGets = node.numGets = (node.numGets || 0) + 1;
1010
+ const handle = (value) => {
1011
+ syncState$.numPendingGets.set((v) => v - 1);
1012
+ if (isWaitingForLoad) {
1013
+ isWaitingForLoad = false;
1014
+ syncStateValue.numPendingRemoteLoads--;
1015
+ }
1016
+ if (numGets >= (node.getNumResolved || 0)) {
1017
+ node.getNumResolved = node.numGets;
1018
+ onChange({
1019
+ value,
1020
+ lastSync: getParams.lastSync,
1021
+ mode: getParams.mode
1022
+ });
1023
+ }
1024
+ if (modeBeforeReset) {
1025
+ getParams.mode = modeBeforeReset;
1026
+ modeBeforeReset = void 0;
1027
+ }
1028
+ syncState$.assign({
1029
+ isLoaded: syncStateValue.numPendingRemoteLoads < 1,
1030
+ error: void 0,
1031
+ isGetting: syncStateValue.numPendingGets > 0
833
1032
  });
1033
+ };
1034
+ if (state.isPromise(got)) {
1035
+ got.then(handle);
1036
+ } else {
1037
+ handle(got);
834
1038
  }
835
1039
  };
836
- runGet();
1040
+ if (waitFor) {
1041
+ state.whenReady(waitFor, () => state.trackSelector(runGet, sync));
1042
+ } else {
1043
+ state.trackSelector(runGet, sync);
1044
+ }
837
1045
  } else {
838
- node.state.assign({
1046
+ syncState$.assign({
839
1047
  isLoaded: true,
840
1048
  error: void 0
841
1049
  });
842
1050
  }
843
1051
  if (!isSynced) {
844
1052
  isSynced = true;
845
- await state.when(() => syncState.isLoaded.get() || syncOptions.allowSetIfGetError && syncState.error.get());
846
- if (pending && !state.isEmpty(pending)) {
847
- localState.isApplyingPending = true;
848
- const keys = Object.keys(pending);
849
- const changes = [];
850
- for (let i = 0; i < keys.length; i++) {
851
- const key = keys[i];
852
- const path = key.split("/").filter((p2) => p2 !== "");
853
- const { p, v, t } = pending[key];
854
- changes.push({ path, valueAtPath: v, prevAtPath: p, pathTypes: t });
855
- }
856
- const value = getNodeValue(node);
857
- onObsChange(obs$, syncState, localState, syncOptions, {
858
- value,
859
- loading: false,
860
- remote: false,
861
- getPrevious: createPreviousHandler(value, changes),
862
- changes
863
- });
864
- localState.isApplyingPending = false;
865
- }
1053
+ await state.when(syncState$.isLoaded);
1054
+ applyPending(pending);
866
1055
  }
867
1056
  };
868
- syncState.assign({ sync });
1057
+ syncStateValue.sync = sync;
1058
+ } else {
1059
+ if (!isSynced) {
1060
+ applyPending(localState.pendingChanges);
1061
+ }
869
1062
  }
1063
+ syncStateValue.reset = async () => {
1064
+ var _a;
1065
+ const wasPersistEnabled = syncStateValue.isPersistEnabled;
1066
+ const wasSyncEnabled = syncStateValue.isSyncEnabled;
1067
+ const metadata = metadatas.get(obs$);
1068
+ if (metadata) {
1069
+ Object.assign(metadata, { lastSync: void 0, pending: void 0 });
1070
+ }
1071
+ Object.assign(syncStateValue, {
1072
+ isPersistEnabled: false,
1073
+ isSyncEnabled: false,
1074
+ lastSync: void 0,
1075
+ numPendingGets: 0,
1076
+ isLoaded: false,
1077
+ isGetting: false,
1078
+ isSetting: false,
1079
+ numPendingSets: 0,
1080
+ syncCount: 0
1081
+ });
1082
+ isSynced = false;
1083
+ isSubscribed = false;
1084
+ unsubscribe == null ? void 0 : unsubscribe();
1085
+ unsubscribe = void 0;
1086
+ const promise = syncStateValue.clearPersist();
1087
+ obs$.set((_a = syncOptions.initial) != null ? _a : void 0);
1088
+ syncState$.isLoaded.set(false);
1089
+ syncStateValue.isPersistEnabled = wasPersistEnabled;
1090
+ syncStateValue.isSyncEnabled = wasSyncEnabled;
1091
+ node.dirtyFn = sync;
1092
+ await promise;
1093
+ };
870
1094
  const onAllPersistLoaded = () => {
871
1095
  var _a, _b;
872
1096
  let parentNode = node;
@@ -884,77 +1108,27 @@ function syncObservable(obs$, syncOptionsOrSynced) {
884
1108
  }
885
1109
  if ((syncOptions == null ? void 0 : syncOptions.set) || (syncOptions == null ? void 0 : syncOptions.persist)) {
886
1110
  obs$.onChange(
887
- onObsChange.bind(this, obs$, syncState, localState, syncOptions)
1111
+ onObsChange.bind(this, obs$, syncState$, localState, syncOptions)
888
1112
  );
889
1113
  }
890
1114
  });
891
- return syncState;
1115
+ return syncState$;
892
1116
  }
893
- var { getProxy, globalState: globalState2, runWithRetry, symbolLinked: symbolLinked2, setNodeValue, getNodeValue: getNodeValue2 } = state.internal;
1117
+ var { getProxy, globalState: globalState2, setNodeValue, getNodeValue: getNodeValue2 } = state.internal;
894
1118
  function enableActivateSyncedNode() {
895
1119
  globalState2.activateSyncedNode = function activateSyncedNode(node, newValue) {
896
1120
  const obs$ = getProxy(node);
897
1121
  if (node.activationState) {
898
- const { get, initial, set, retry } = node.activationState;
899
- let onChange = void 0;
900
- const pluginRemote = {};
1122
+ const {
1123
+ get: getOrig,
1124
+ initial,
1125
+ set,
1126
+ onChange
1127
+ } = node.activationState;
901
1128
  let promiseReturn = void 0;
902
- let syncState;
903
- const refresh = () => syncState == null ? void 0 : syncState.sync();
904
- if (get) {
905
- pluginRemote.get = (params) => {
906
- var _a;
907
- onChange = params.onChange;
908
- const updateLastSync = (lastSync) => params.lastSync = lastSync;
909
- const existingValue = getNodeValue2(node);
910
- const value = runWithRetry(node, { attemptNum: 0, retry: retry || ((_a = params.options) == null ? void 0 : _a.retry) }, () => {
911
- const paramsToGet = {
912
- value: state.isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked2]) ? void 0 : existingValue,
913
- lastSync: params.lastSync,
914
- updateLastSync,
915
- mode: params.mode,
916
- refresh
917
- };
918
- const ret = get(paramsToGet);
919
- params.mode = paramsToGet.mode;
920
- return ret;
921
- });
922
- promiseReturn = value;
923
- return value;
924
- };
925
- }
926
- if (set) {
927
- pluginRemote.set = async (params) => {
928
- var _a, _b;
929
- if ((_a = node.state) == null ? void 0 : _a.isLoaded.get()) {
930
- const retryAttempts = { attemptNum: 0, retry: retry || ((_b = params.options) == null ? void 0 : _b.retry) };
931
- return runWithRetry(node, retryAttempts, async (retryEvent) => {
932
- let changes = {};
933
- let maxModified = 0;
934
- if (!node.state.isLoaded.peek()) {
935
- await state.whenReady(node.state.isLoaded);
936
- }
937
- const cancelRetry = () => {
938
- retryEvent.cancel = true;
939
- };
940
- await set({
941
- ...params,
942
- node,
943
- update: (params2) => {
944
- const { value, lastSync } = params2;
945
- maxModified = Math.max(lastSync || 0, maxModified);
946
- changes = state.mergeIntoObservable(changes, value);
947
- },
948
- retryNum: retryAttempts.attemptNum,
949
- cancelRetry,
950
- refresh,
951
- fromSubscribe: false
952
- });
953
- return { changes, lastSync: maxModified || void 0 };
954
- });
955
- }
956
- };
957
- }
1129
+ const get = getOrig ? (params) => {
1130
+ return promiseReturn = getOrig(params);
1131
+ } : void 0;
958
1132
  const nodeVal = getNodeValue2(node);
959
1133
  if (promiseReturn !== void 0) {
960
1134
  newValue = promiseReturn;
@@ -964,7 +1138,7 @@ function enableActivateSyncedNode() {
964
1138
  newValue = initial;
965
1139
  }
966
1140
  setNodeValue(node, promiseReturn ? void 0 : newValue);
967
- syncState = syncObservable(obs$, { ...node.activationState, ...pluginRemote });
1141
+ syncObservable(obs$, { ...node.activationState, get, set });
968
1142
  return { update: onChange, value: newValue };
969
1143
  } else {
970
1144
  let update = void 0;
@@ -1001,21 +1175,28 @@ function installPersistActivateNode() {
1001
1175
  didInstall = true;
1002
1176
  }
1003
1177
  }
1178
+ var { deepMerge: deepMerge2 } = state.internal;
1179
+ function configureSynced(fnOrOrigOptions, origOptions) {
1180
+ const fn = origOptions ? fnOrOrigOptions : void 0;
1181
+ origOptions = origOptions != null ? origOptions : fnOrOrigOptions;
1182
+ return (options) => {
1183
+ const merged = deepMerge2(origOptions, options);
1184
+ return fn ? fn(merged) : merged;
1185
+ };
1186
+ }
1004
1187
 
1005
1188
  // sync.ts
1006
- function isInRemoteChange() {
1007
- return state.internal.globalState.isLoadingRemote;
1008
- }
1009
- var internal3 = {
1010
- observableSyncConfiguration
1189
+ var internal4 = {
1190
+ observableSyncConfiguration,
1191
+ waitForSet
1011
1192
  };
1012
1193
 
1013
1194
  exports.combineTransforms = combineTransforms;
1014
1195
  exports.configureObservableSync = configureObservableSync;
1196
+ exports.configureSynced = configureSynced;
1015
1197
  exports.deepEqual = deepEqual;
1016
1198
  exports.diffObjects = diffObjects;
1017
- exports.internal = internal3;
1018
- exports.isInRemoteChange = isInRemoteChange;
1199
+ exports.internal = internal4;
1019
1200
  exports.mapSyncPlugins = mapSyncPlugins;
1020
1201
  exports.onChangeRemote = onChangeRemote;
1021
1202
  exports.removeNullUndefined = removeNullUndefined;