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

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 (78) 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 +2052 -0
  17. package/config.mjs +2050 -0
  18. package/helpers/trackHistory.js +2 -2
  19. package/helpers/trackHistory.mjs +2 -2
  20. package/index.d.mts +21 -302
  21. package/index.d.ts +21 -302
  22. package/index.js +274 -318
  23. package/index.mjs +275 -317
  24. package/observableInterfaces-Dilj6F92.d.mts +282 -0
  25. package/observableInterfaces-Dilj6F92.d.ts +282 -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/_transformObjectFields.d.mts +31 -0
  44. package/sync-plugins/_transformObjectFields.d.ts +31 -0
  45. package/sync-plugins/_transformObjectFields.js +114 -0
  46. package/sync-plugins/_transformObjectFields.mjs +110 -0
  47. package/sync-plugins/crud.d.mts +15 -23
  48. package/sync-plugins/crud.d.ts +15 -23
  49. package/sync-plugins/crud.js +213 -134
  50. package/sync-plugins/crud.mjs +214 -135
  51. package/sync-plugins/fetch.js +12 -8
  52. package/sync-plugins/fetch.mjs +13 -9
  53. package/sync-plugins/firebase.d.mts +26 -0
  54. package/sync-plugins/firebase.d.ts +26 -0
  55. package/sync-plugins/firebase.js +373 -0
  56. package/sync-plugins/firebase.mjs +368 -0
  57. package/sync-plugins/keel.d.mts +27 -10
  58. package/sync-plugins/keel.d.ts +27 -10
  59. package/sync-plugins/keel.js +40 -21
  60. package/sync-plugins/keel.mjs +40 -21
  61. package/sync-plugins/supabase.d.mts +12 -7
  62. package/sync-plugins/supabase.d.ts +12 -7
  63. package/sync-plugins/supabase.js +24 -13
  64. package/sync-plugins/supabase.mjs +25 -14
  65. package/sync-plugins/tanstack-query.d.mts +2 -2
  66. package/sync-plugins/tanstack-query.d.ts +2 -2
  67. package/sync-plugins/tanstack-query.js +3 -2
  68. package/sync-plugins/tanstack-query.mjs +3 -2
  69. package/sync-plugins/tanstack-react-query.d.mts +1 -1
  70. package/sync-plugins/tanstack-react-query.d.ts +1 -1
  71. package/sync.d.mts +68 -197
  72. package/sync.d.ts +68 -197
  73. package/sync.js +448 -283
  74. package/sync.mjs +454 -289
  75. package/types/babel.d.ts +12 -1
  76. package/.DS_Store +0 -0
  77. /package/config/{enable_GetSet.d.mts → enable$GetSet.d.mts} +0 -0
  78. /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,74 @@ 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
155
- });
156
- params.onGet();
157
- } catch (e) {
158
- }
159
- };
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;
160
152
  }
161
- if (set) {
162
- ret.set = set;
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;
163
161
  }
164
- return ret;
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
+ }
196
+ });
197
+ };
198
+ run();
199
+ });
200
+ }
201
+ return value;
165
202
  }
166
203
 
167
204
  // src/sync/syncObservable.ts
168
- var { createPreviousHandler, clone, getValueAtPath, globalState, symbolLinked, getNode, getNodeValue } = state.internal;
205
+ var { clone, deepMerge, getNode, getNodeValue, getValueAtPath, globalState, symbolLinked, createPreviousHandler } = state.internal;
169
206
  var mapSyncPlugins = /* @__PURE__ */ new WeakMap();
207
+ var allSyncStates = /* @__PURE__ */ new Map();
170
208
  var metadatas = /* @__PURE__ */ new WeakMap();
171
209
  var promisesLocalSaves = /* @__PURE__ */ new Set();
172
210
  function parseLocalConfig(config) {
@@ -183,13 +221,19 @@ function onChangeRemote(cb) {
183
221
  globalState.isLoadingRemote = false;
184
222
  state.endBatch(true);
185
223
  }
186
- function transformSaveData(value, path, pathTypes, { transform }) {
224
+ async function transformSaveData(value, path, pathTypes, { transform }) {
187
225
  if (transform == null ? void 0 : transform.save) {
188
226
  const constructed = state.constructObjectWithPath(path, pathTypes, value);
189
- const saved = transform.save(constructed);
190
- value = state.deconstructObjectWithPath(path, pathTypes, saved);
227
+ const saved = await transform.save(constructed);
228
+ value = saved;
229
+ const outPath = [];
230
+ for (let i = 0; i < path.length; i++) {
231
+ outPath[i] = Object.keys(value)[0];
232
+ value = value[outPath[i]];
233
+ }
234
+ path = outPath;
191
235
  }
192
- return value;
236
+ return { value, path };
193
237
  }
194
238
  function transformLoadData(value, { transform }, doUserTransform, method) {
195
239
  if (doUserTransform && (transform == null ? void 0 : transform.load)) {
@@ -197,7 +241,7 @@ function transformLoadData(value, { transform }, doUserTransform, method) {
197
241
  }
198
242
  return value;
199
243
  }
200
- async function updateMetadataImmediate(value$, localState, syncState, syncOptions, newMetadata) {
244
+ async function updateMetadataImmediate(value$, localState, syncState2, syncOptions, newMetadata) {
201
245
  const saves = Array.from(promisesLocalSaves);
202
246
  if (saves.length > 0) {
203
247
  await Promise.all(saves);
@@ -212,17 +256,17 @@ async function updateMetadataImmediate(value$, localState, syncState, syncOption
212
256
  await pluginPersist.setMetadata(table, metadata, config);
213
257
  }
214
258
  if (lastSync) {
215
- syncState.assign({
259
+ syncState2.assign({
216
260
  lastSync
217
261
  });
218
262
  }
219
263
  }
220
- function updateMetadata(value$, localState, syncState, syncOptions, newMetadata) {
264
+ function updateMetadata(value$, localState, syncState2, syncOptions, newMetadata) {
221
265
  if (localState.timeoutSaveMetadata) {
222
266
  clearTimeout(localState.timeoutSaveMetadata);
223
267
  }
224
268
  localState.timeoutSaveMetadata = setTimeout(
225
- () => updateMetadataImmediate(value$, localState, syncState, syncOptions, newMetadata),
269
+ () => updateMetadataImmediate(value$, localState, syncState2, syncOptions, newMetadata),
226
270
  0
227
271
  );
228
272
  }
@@ -250,26 +294,21 @@ function mergeChanges(changes) {
250
294
  return changesOut;
251
295
  }
252
296
  function mergeQueuedChanges(allChanges) {
253
- const changesByObsRemote = /* @__PURE__ */ new Map();
254
- const changesByObsLocal = /* @__PURE__ */ new Map();
255
- const previousByObs = /* @__PURE__ */ new Map();
297
+ const changesByOptionsRemote = /* @__PURE__ */ new Map();
298
+ const changesByOptionsLocal = /* @__PURE__ */ new Map();
256
299
  const outRemote = /* @__PURE__ */ new Map();
257
300
  const outLocal = /* @__PURE__ */ new Map();
258
301
  for (let i = 0; i < allChanges.length; i++) {
259
302
  const value = allChanges[i];
260
- const { value$: obs, changes, inRemoteChange, getPrevious } = value;
303
+ const { changes, inRemoteChange, syncOptions } = value;
261
304
  const targetMap = inRemoteChange ? outRemote : outLocal;
262
- const changesMap = inRemoteChange ? changesByObsRemote : changesByObsLocal;
263
- const existing = changesMap.get(obs);
305
+ const changesMap = inRemoteChange ? changesByOptionsRemote : changesByOptionsLocal;
306
+ const existing = changesMap.get(syncOptions);
264
307
  const newChanges = existing ? [...existing, ...changes] : changes;
265
308
  const merged = mergeChanges(newChanges);
266
- changesMap.set(obs, merged);
309
+ changesMap.set(syncOptions, merged);
267
310
  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);
311
+ targetMap.set(syncOptions, value);
273
312
  }
274
313
  return Array.from(outRemote.values()).concat(Array.from(outLocal.values()));
275
314
  }
@@ -315,15 +354,13 @@ async function processQueuedRemoteChanges(syncOptions) {
315
354
  }
316
355
  }
317
356
  async function prepChangeLocal(queuedChange) {
318
- const { syncState, changes, localState, syncOptions, inRemoteChange, isApplyingPending } = queuedChange;
357
+ const { syncState: syncState2, changes, syncOptions, inRemoteChange, isApplyingPending } = queuedChange;
319
358
  const persist = syncOptions.persist;
320
- const { pluginSync } = localState;
321
359
  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());
360
+ const saveLocal = (persist == null ? void 0 : persist.name) && !configLocal.readonly && !isApplyingPending && syncState2.isPersistEnabled.peek();
361
+ const saveRemote = !!(!inRemoteChange && (syncOptions == null ? void 0 : syncOptions.set) && syncState2.isSyncEnabled.peek());
325
362
  if (saveLocal || saveRemote) {
326
- if (saveLocal && !syncState.isPersistLoaded.peek()) {
363
+ if (saveLocal && !syncState2.isPersistLoaded.peek()) {
327
364
  console.error(
328
365
  "[legend-state] WARNING: An observable was changed before being loaded from persist",
329
366
  persist
@@ -356,13 +393,13 @@ async function prepChangeLocal(queuedChange) {
356
393
  configLocal
357
394
  );
358
395
  promisesTransform.push(
359
- doInOrder(promiseTransformLocal, (valueTransformed) => {
396
+ doInOrder(promiseTransformLocal, ({ value: valueTransformed, path: pathTransformed }) => {
360
397
  changesLocal.push({
361
- path,
398
+ path: pathTransformed,
362
399
  pathTypes,
363
400
  prevAtPath,
364
401
  valueAtPath: valueTransformed,
365
- pathStr
402
+ pathStr: path === pathTransformed ? pathStr : pathTransformed.join("/")
366
403
  });
367
404
  })
368
405
  );
@@ -378,22 +415,19 @@ async function prepChangeLocal(queuedChange) {
378
415
  }
379
416
  async function prepChangeRemote(queuedChange) {
380
417
  const {
381
- syncState,
418
+ syncState: syncState2,
382
419
  changes,
383
420
  localState,
384
421
  syncOptions,
385
422
  inRemoteChange,
386
- isApplyingPending,
387
- valuePrevious
423
+ isApplyingPending
388
424
  } = queuedChange;
389
425
  const persist = syncOptions.persist;
390
- const { pluginSync } = localState;
391
426
  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();
427
+ const saveLocal = persist && !configLocal.readonly && !isApplyingPending && syncState2.isPersistEnabled.peek();
428
+ const saveRemote = !inRemoteChange && (syncOptions == null ? void 0 : syncOptions.set) && syncState2.isSyncEnabled.peek();
395
429
  if (saveLocal || saveRemote) {
396
- if (saveLocal && !syncState.isPersistLoaded.peek()) {
430
+ if (saveLocal && !syncState2.isPersistLoaded.peek()) {
397
431
  console.error(
398
432
  "[legend-state] WARNING: An observable was changed before being loaded from persist",
399
433
  persist
@@ -423,20 +457,20 @@ async function prepChangeRemote(queuedChange) {
423
457
  valueAtPath,
424
458
  path,
425
459
  pathTypes,
426
- configRemote || {}
460
+ syncOptions || {}
427
461
  );
428
462
  promisesTransform.push(
429
- doInOrder(promiseTransformRemote, (valueTransformed) => {
463
+ doInOrder(promiseTransformRemote, ({ value: valueTransformed, path: pathTransformed }) => {
430
464
  var _a;
431
465
  if (!localState.pendingChanges) {
432
466
  localState.pendingChanges = {};
433
467
  }
434
468
  let found2 = false;
435
- for (let i2 = 0; !found2 && i2 < path.length - 1; i2++) {
436
- const pathParent = path.slice(0, i2 + 1).join("/");
469
+ for (let i2 = 0; !found2 && i2 < pathTransformed.length - 1; i2++) {
470
+ const pathParent = pathTransformed.slice(0, i2 + 1).join("/");
437
471
  if ((_a = localState.pendingChanges[pathParent]) == null ? void 0 : _a.v) {
438
472
  found2 = true;
439
- const pathChild = path.slice(i2 + 1);
473
+ const pathChild = pathTransformed.slice(i2 + 1);
440
474
  const pathTypesChild = pathTypes.slice(i2 + 1);
441
475
  state.setAtPath(
442
476
  localState.pendingChanges[pathParent].v,
@@ -458,12 +492,11 @@ async function prepChangeRemote(queuedChange) {
458
492
  localState.pendingChanges[pathStr].v = valueAtPath;
459
493
  }
460
494
  changesRemote.push({
461
- path,
495
+ path: pathTransformed,
462
496
  pathTypes,
463
497
  prevAtPath,
464
498
  valueAtPath: valueTransformed,
465
- pathStr,
466
- valuePrevious
499
+ pathStr
467
500
  });
468
501
  })
469
502
  );
@@ -481,24 +514,27 @@ async function doChangeLocal(changeInfo) {
481
514
  if (!changeInfo)
482
515
  return;
483
516
  const { queuedChange, changesLocal, saveRemote } = changeInfo;
484
- const { value$: obs, syncState, localState, syncOptions } = queuedChange;
517
+ const { value$: obs, syncState: syncState2, localState, syncOptions } = queuedChange;
485
518
  const { pluginPersist } = localState;
486
519
  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);
520
+ const saveLocal = !!(persist == null ? void 0 : persist.name);
521
+ if (saveLocal) {
522
+ const { table, config: configLocal } = parseLocalConfig(persist);
523
+ const shouldSaveMetadata = persist == null ? void 0 : persist.retrySync;
524
+ if (saveRemote && shouldSaveMetadata) {
525
+ await updateMetadataImmediate(obs, localState, syncState2, syncOptions, {
526
+ pending: localState.pendingChanges
499
527
  });
500
- promisesLocalSaves.add(promiseSet);
501
- await promiseSet;
528
+ }
529
+ if (changesLocal.length > 0) {
530
+ let promiseSet = pluginPersist.set(table, changesLocal, configLocal);
531
+ if (promiseSet) {
532
+ promiseSet = promiseSet.then(() => {
533
+ promisesLocalSaves.delete(promiseSet);
534
+ });
535
+ promisesLocalSaves.add(promiseSet);
536
+ await promiseSet;
537
+ }
502
538
  }
503
539
  }
504
540
  }
@@ -507,47 +543,99 @@ async function doChangeRemote(changeInfo) {
507
543
  if (!changeInfo)
508
544
  return;
509
545
  const { queuedChange, changesRemote } = changeInfo;
510
- const { value$: obs, syncState, localState, syncOptions, valuePrevious: previous } = queuedChange;
511
- const { pluginPersist, pluginSync } = localState;
546
+ const { value$: obs$, syncState: syncState2, localState, syncOptions } = queuedChange;
547
+ const { pluginPersist } = localState;
548
+ const node = getNode(obs$);
549
+ const state$ = node.state;
512
550
  const persist = syncOptions.persist;
513
551
  const { table, config: configLocal } = parseLocalConfig(persist);
514
- const { allowSetIfGetError, onBeforeSet, onSetError, waitForSet, onAfterSet } = syncOptions || {};
552
+ const { onBeforeSet, waitForSet, onAfterSet } = syncOptions || {};
515
553
  const shouldSaveMetadata = persist == null ? void 0 : persist.retrySync;
554
+ const saveLocal = !!(persist == null ? void 0 : persist.name);
516
555
  if (changesRemote.length > 0) {
517
- await state.when(() => syncState.isLoaded.get() || allowSetIfGetError && syncState.error.get());
556
+ if (!syncState2.isLoaded.peek()) {
557
+ await state.when(syncState2.isLoaded);
558
+ const pending = localState.pendingChanges;
559
+ if (pending) {
560
+ changesRemote.forEach((change) => {
561
+ const key = change.pathStr;
562
+ const pendingAtPath = pending[key];
563
+ if (!state.isNullOrUndefined(pendingAtPath)) {
564
+ const { p } = pendingAtPath;
565
+ change.prevAtPath = p;
566
+ }
567
+ });
568
+ }
569
+ }
518
570
  if (waitForSet) {
519
- const waitFor = state.isFunction(waitForSet) ? waitForSet({ changes: changesRemote, value: obs.peek() }) : waitForSet;
520
- if (waitFor) {
521
- await state.when(waitFor);
571
+ const waitFn = state.isFunction(waitForSet) ? waitForSet({ changes: changesRemote, value: obs$.peek() }) : waitForSet;
572
+ if (waitFn) {
573
+ await state.when(waitFn);
522
574
  }
523
575
  }
524
- let value = obs.peek();
576
+ let value = clone(obs$.peek());
525
577
  const transformSave = (_a = syncOptions == null ? void 0 : syncOptions.transform) == null ? void 0 : _a.save;
526
578
  if (transformSave) {
527
- value = transformSave(clone(value));
579
+ value = transformSave(value);
528
580
  }
581
+ state$.numPendingSets.set((v) => (v || 0) + 1);
582
+ state$.isSetting.set(true);
529
583
  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,
584
+ let updateResult = void 0;
585
+ const onError = (error) => {
586
+ var _a2;
587
+ state$.error.set(error);
588
+ (_a2 = syncOptions.onSetError) == null ? void 0 : _a2.call(syncOptions, error, {
589
+ setParams,
590
+ source: "set",
591
+ value$: obs$
592
+ });
593
+ };
594
+ const setParams = {
595
+ node,
596
+ value$: obs$,
535
597
  changes: changesRemote,
536
598
  value,
537
- valuePrevious: previous
538
- });
599
+ onError,
600
+ update: (params) => {
601
+ if (updateResult) {
602
+ const { value: value2, lastSync, mode } = params;
603
+ updateResult = {
604
+ lastSync: Math.max(updateResult.lastSync || 0, lastSync || 0),
605
+ value: deepMerge(updateResult.value, value2),
606
+ mode
607
+ };
608
+ } else {
609
+ updateResult = params;
610
+ }
611
+ },
612
+ refresh: syncState2.sync,
613
+ retryNum: 0,
614
+ cancelRetry: false
615
+ };
616
+ let savedPromise = runWithRetry(
617
+ setParams,
618
+ syncOptions.retry,
619
+ async () => {
620
+ return syncOptions.set(setParams);
621
+ },
622
+ onError
623
+ );
624
+ let didError = false;
539
625
  if (state.isPromise(savedPromise)) {
540
- savedPromise = savedPromise.catch((err) => onSetError == null ? void 0 : onSetError(err));
626
+ savedPromise = savedPromise.catch((error) => {
627
+ didError = true;
628
+ onError(error);
629
+ });
630
+ await savedPromise;
541
631
  }
542
- const saved = await savedPromise;
543
- localState.numSavesOutstanding--;
544
- if (saved !== void 0) {
632
+ if (!didError) {
545
633
  const pathStrs = Array.from(new Set(changesRemote.map((change) => change.pathStr)));
546
- const { changes, lastSync } = saved;
634
+ const { value: changes, lastSync } = updateResult || {};
547
635
  if (pathStrs.length > 0) {
548
636
  let transformedChanges = void 0;
549
637
  const metadata = {};
550
- if (persist) {
638
+ if (saveLocal) {
551
639
  const pendingMetadata = (_b = pluginPersist.getMetadata(table, configLocal)) == null ? void 0 : _b.pending;
552
640
  const pending = localState.pendingChanges;
553
641
  for (let i = 0; i < pathStrs.length; i++) {
@@ -567,42 +655,31 @@ async function doChangeRemote(changeInfo) {
567
655
  if (changes && !state.isEmpty(changes)) {
568
656
  transformedChanges = transformLoadData(changes, syncOptions, false, "set");
569
657
  }
570
- if (localState.numSavesOutstanding > 0) {
571
- if (transformedChanges) {
572
- if (!localState.pendingSaveResults) {
573
- localState.pendingSaveResults = [];
574
- }
575
- localState.pendingSaveResults.push(transformedChanges);
658
+ if (transformedChanges !== void 0) {
659
+ if (state.isPromise(transformedChanges)) {
660
+ transformedChanges = await transformedChanges;
576
661
  }
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
- }
662
+ onChangeRemote(() => state.mergeIntoObservable(obs$, transformedChanges));
663
+ }
664
+ if (saveLocal) {
665
+ if (shouldSaveMetadata && !state.isEmpty(metadata)) {
666
+ updateMetadata(obs$, localState, syncState2, syncOptions, metadata);
591
667
  }
592
- localState.pendingSaveResults = [];
593
668
  }
594
- onAfterSet == null ? void 0 : onAfterSet();
595
669
  }
670
+ state$.numPendingSets.set((v) => v - 1);
671
+ state$.isSetting.set(state$.numPendingSets.peek() > 0);
672
+ onAfterSet == null ? void 0 : onAfterSet();
596
673
  }
597
674
  }
598
675
  }
599
- function onObsChange(value$, syncState, localState, syncOptions, { changes, loading, remote, getPrevious }) {
600
- if (!loading) {
601
- const inRemoteChange = remote;
676
+ function onObsChange(value$, syncState2, localState, syncOptions, { changes, isFromPersist, isFromSync, getPrevious }) {
677
+ if (!isFromPersist) {
678
+ const inRemoteChange = isFromSync;
602
679
  const isApplyingPending = localState.isApplyingPending;
603
680
  _queuedChanges.push({
604
681
  value$,
605
- syncState,
682
+ syncState: syncState2,
606
683
  localState,
607
684
  syncOptions,
608
685
  changes,
@@ -615,13 +692,17 @@ function onObsChange(value$, syncState, localState, syncOptions, { changes, load
615
692
  }
616
693
  }
617
694
  }
618
- async function loadLocal(value$, syncOptions, syncState, localState) {
695
+ async function loadLocal(value$, syncOptions, syncState$, localState) {
619
696
  var _a, _b, _c;
620
697
  const { persist } = syncOptions;
621
- if (persist) {
698
+ const node = getNode(value$);
699
+ const nodeValue = getNodeValue(getNode(node.state));
700
+ const syncStateValue = syncState$.peek();
701
+ const prevClearPersist = nodeValue.clearPersist;
702
+ if (persist == null ? void 0 : persist.name) {
622
703
  const PersistPlugin = persist.plugin || ((_a = observableSyncConfiguration.persist) == null ? void 0 : _a.plugin);
623
704
  const { table, config } = parseLocalConfig(persist);
624
- const node = getNode(value$);
705
+ syncStateValue.numPendingLocalLoads = (syncStateValue.numPendingLocalLoads || 0) + 1;
625
706
  if (!PersistPlugin) {
626
707
  throw new Error("Local persist is not configured");
627
708
  }
@@ -655,7 +736,7 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
655
736
  if (metadata) {
656
737
  metadatas.set(value$, metadata);
657
738
  localState.pendingChanges = metadata.pending;
658
- syncState.assign({
739
+ syncState$.assign({
659
740
  lastSync: metadata.lastSync
660
741
  });
661
742
  }
@@ -673,12 +754,18 @@ async function loadLocal(value$, syncOptions, syncState, localState) {
673
754
  }
674
755
  state.internal.globalState.isLoadingLocal = false;
675
756
  }
676
- getNodeValue(getNode(node.state)).clearPersist = () => Promise.all([
677
- persistPlugin.deleteTable(table, config),
678
- persistPlugin.deleteMetadata(table, config)
679
- ]);
757
+ syncStateValue.numPendingLocalLoads--;
758
+ nodeValue.clearPersist = () => Promise.all(
759
+ [
760
+ prevClearPersist,
761
+ persistPlugin.deleteTable(table, config),
762
+ persistPlugin.deleteMetadata(table, config)
763
+ ].filter(Boolean)
764
+ );
765
+ } else {
766
+ nodeValue.clearPersist = () => prevClearPersist == null ? void 0 : prevClearPersist();
680
767
  }
681
- syncState.isPersistLoaded.set(true);
768
+ syncState$.isPersistLoaded.set(!(syncStateValue.numPendingLocalLoads > 0));
682
769
  }
683
770
  function syncObservable(obs$, syncOptionsOrSynced) {
684
771
  let syncOptions = syncOptionsOrSynced;
@@ -689,7 +776,7 @@ function syncObservable(obs$, syncOptionsOrSynced) {
689
776
  if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && (!obs$ || !node)) {
690
777
  throw new Error("[legend-state] syncObservable called with undefined observable");
691
778
  }
692
- syncOptions = state.mergeIntoObservable(
779
+ syncOptions = deepMerge(
693
780
  {
694
781
  syncMode: "auto"
695
782
  },
@@ -698,24 +785,50 @@ function syncObservable(obs$, syncOptionsOrSynced) {
698
785
  );
699
786
  const localState = {};
700
787
  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);
788
+ const syncState$ = state.syncState(obs$);
789
+ const syncStateValue = getNodeValue(getNode(syncState$));
790
+ allSyncStates.set(syncState$, node);
791
+ syncStateValue.getPendingChanges = () => localState.pendingChanges;
792
+ const onGetError = (error, params) => {
793
+ var _a;
794
+ syncState$.error.set(error);
795
+ (_a = syncOptions.onGetError) == null ? void 0 : _a.call(syncOptions, error, { ...params, value$: obs$ });
796
+ };
797
+ loadLocal(obs$, syncOptions, syncState$, localState);
798
+ let isWaitingForLoad = !!syncOptions.get;
799
+ if (isWaitingForLoad) {
800
+ syncStateValue.numPendingRemoteLoads = (syncStateValue.numPendingRemoteLoads || 0) + 1;
801
+ }
802
+ syncState$.isLoaded.set(!syncState$.numPendingRemoteLoads.peek());
803
+ let isSynced = false;
804
+ let isSubscribed = false;
805
+ let unsubscribe = void 0;
806
+ const applyPending = (pending) => {
807
+ if (pending && !state.isEmpty(pending)) {
808
+ localState.isApplyingPending = true;
809
+ const keys = Object.keys(pending);
810
+ const changes = [];
811
+ for (let i = 0; i < keys.length; i++) {
812
+ const key = keys[i];
813
+ const path = key.split("/").filter((p2) => p2 !== "");
814
+ const { p, v, t } = pending[key];
815
+ changes.push({ path, valueAtPath: v, prevAtPath: p, pathTypes: t });
816
+ }
817
+ const value = getNodeValue(node);
818
+ onObsChange(obs$, syncState$, localState, syncOptions, {
819
+ value,
820
+ isFromPersist: false,
821
+ isFromSync: false,
822
+ getPrevious: createPreviousHandler(value, changes),
823
+ changes
824
+ });
825
+ localState.isApplyingPending = false;
826
+ }
827
+ };
712
828
  if (syncOptions.get) {
713
- let isSynced = false;
714
- let isSubscribed = false;
715
- let unsubscribe = void 0;
716
829
  sync = async () => {
717
- var _a, _b;
718
- if (isSynced && state.shouldIgnoreUnobserved(node, sync)) {
830
+ var _a;
831
+ if (isSynced && (!getNodeValue(getNode(syncState$)).isSyncEnabled || state.shouldIgnoreUnobserved(node, sync))) {
719
832
  if (unsubscribe) {
720
833
  isSubscribed = false;
721
834
  unsubscribe();
@@ -725,9 +838,11 @@ function syncObservable(obs$, syncOptionsOrSynced) {
725
838
  }
726
839
  const lastSync = (_a = metadatas.get(obs$)) == null ? void 0 : _a.lastSync;
727
840
  const pending = localState.pendingChanges;
728
- const get = (_b = localState.pluginSync.get) == null ? void 0 : _b.bind(localState.pluginSync);
841
+ const get = syncOptions.get;
729
842
  if (get) {
843
+ const { waitFor } = syncOptions;
730
844
  const runGet = () => {
845
+ var _a2;
731
846
  const onChange = async ({ value, mode, lastSync: lastSync2 }) => {
732
847
  mode = mode || syncOptions.mode || "set";
733
848
  if (value !== void 0) {
@@ -740,9 +855,11 @@ function syncObservable(obs$, syncOptionsOrSynced) {
740
855
  if (pending2) {
741
856
  let didChangeMetadata = false;
742
857
  Object.keys(pending2).forEach((key) => {
743
- const p = key.split("/").filter((p2) => p2 !== "");
858
+ const p = key.split("/").filter((k) => k !== "");
744
859
  const { v, t } = pending2[key];
745
860
  if (t.length === 0 || !value) {
861
+ const oldValue = clone(value);
862
+ pending2[key].p = oldValue;
746
863
  if (state.isObject(value) && state.isObject(v)) {
747
864
  Object.assign(value, v);
748
865
  } else {
@@ -755,6 +872,8 @@ function syncObservable(obs$, syncOptionsOrSynced) {
755
872
  delete pending2[key];
756
873
  didChangeMetadata = true;
757
874
  } else {
875
+ const oldValue = clone(value);
876
+ pending2[key].p = getValueAtPath(oldValue, p);
758
877
  value = state.setAtPath(
759
878
  value,
760
879
  p,
@@ -774,18 +893,24 @@ function syncObservable(obs$, syncOptionsOrSynced) {
774
893
  }
775
894
  }
776
895
  });
777
- if (didChangeMetadata) {
778
- updateMetadata(obs$, localState, syncState, syncOptions, {
896
+ if (didChangeMetadata && syncOptions.persist) {
897
+ updateMetadata(obs$, localState, syncState$, syncOptions, {
779
898
  pending: pending2
780
899
  });
781
900
  }
782
901
  }
783
902
  onChangeRemote(() => {
784
- if (mode === "assign" && state.isObject(value)) {
903
+ if (mode === "assign") {
785
904
  obs$.assign(value);
786
- } else if (mode === "append" && state.isArray(value)) {
905
+ } else if (mode === "append") {
906
+ if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !state.isArray(value)) {
907
+ console.error("[legend-state] mode:append expects the value to be an array");
908
+ }
787
909
  obs$.push(...value);
788
- } else if (mode === "prepend" && state.isArray(value)) {
910
+ } else if (mode === "prepend") {
911
+ if ((process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test") && !state.isArray(value)) {
912
+ console.error("[legend-state] mode:prepend expects the value to be an array");
913
+ }
789
914
  obs$.splice(0, 0, ...value);
790
915
  } else if (mode === "merge") {
791
916
  state.mergeIntoObservable(obs$, value);
@@ -795,78 +920,162 @@ function syncObservable(obs$, syncOptionsOrSynced) {
795
920
  });
796
921
  }
797
922
  if (lastSync2 && syncOptions.persist) {
798
- updateMetadata(obs$, localState, syncState, syncOptions, {
923
+ updateMetadata(obs$, localState, syncState$, syncOptions, {
799
924
  lastSync: lastSync2
800
925
  });
801
926
  }
802
927
  };
803
- get({
804
- state: syncState,
928
+ if (node.activationState) {
929
+ node.activationState.onChange = onChange;
930
+ }
931
+ if (!isSubscribed && syncOptions.subscribe) {
932
+ const subscribe = syncOptions.subscribe;
933
+ isSubscribed = true;
934
+ const doSubscribe = () => {
935
+ const subscribeParams = {
936
+ node,
937
+ value$: obs$,
938
+ lastSync,
939
+ update: (params) => {
940
+ state.when(syncState$.isLoaded, () => {
941
+ state.when(waitFor || true, () => {
942
+ params.mode || (params.mode = syncOptions.mode || "merge");
943
+ onChange(params);
944
+ });
945
+ });
946
+ },
947
+ refresh: () => state.when(syncState$.isLoaded, sync),
948
+ onError: (error) => onGetError(error, { source: "subscribe", subscribeParams })
949
+ };
950
+ unsubscribe = subscribe(subscribeParams);
951
+ };
952
+ if (waitFor) {
953
+ state.whenReady(waitFor, doSubscribe);
954
+ } else {
955
+ doSubscribe();
956
+ }
957
+ }
958
+ const existingValue = getNodeValue(node);
959
+ const onError = (error) => onGetError(error, { getParams, source: "get" });
960
+ const getParams = {
961
+ node,
805
962
  value$: obs$,
963
+ value: state.isFunction(existingValue) || (existingValue == null ? void 0 : existingValue[symbolLinked]) ? void 0 : existingValue,
964
+ mode: syncOptions.mode,
965
+ refresh: sync,
806
966
  options: syncOptions,
807
967
  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
968
+ updateLastSync: (lastSync2) => getParams.lastSync = lastSync2,
969
+ onError,
970
+ retryNum: 0,
971
+ cancelRetry: false
972
+ };
973
+ let modeBeforeReset = void 0;
974
+ (_a2 = syncOptions.onBeforeGet) == null ? void 0 : _a2.call(syncOptions, {
975
+ value: getParams.value,
976
+ lastSync,
977
+ pendingChanges: pending && !state.isEmpty(pending) ? pending : void 0,
978
+ clearPendingChanges: async () => {
979
+ localState.pendingChanges = {};
980
+ await updateMetadataImmediate(obs$, localState, syncState$, syncOptions, {
981
+ pending: localState.pendingChanges
817
982
  });
818
983
  },
819
- onChange
984
+ resetCache: () => {
985
+ var _a3;
986
+ modeBeforeReset = getParams.mode;
987
+ getParams.mode = "set";
988
+ return (_a3 = syncStateValue.clearPersist) == null ? void 0 : _a3.call(syncStateValue);
989
+ }
820
990
  });
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)
991
+ syncState$.assign({
992
+ numPendingGets: (syncStateValue.numPendingGets || 0) + 1,
993
+ isGetting: true
994
+ });
995
+ const got = runWithRetry(
996
+ getParams,
997
+ syncOptions.retry,
998
+ (retryEvent) => {
999
+ const params = getParams;
1000
+ params.cancelRetry = retryEvent.cancelRetry;
1001
+ params.retryNum = retryEvent.retryNum;
1002
+ return get(params);
1003
+ },
1004
+ onError
1005
+ );
1006
+ const numGets = node.numGets = (node.numGets || 0) + 1;
1007
+ const handle = (value) => {
1008
+ syncState$.numPendingGets.set((v) => v - 1);
1009
+ if (isWaitingForLoad) {
1010
+ isWaitingForLoad = false;
1011
+ syncStateValue.numPendingRemoteLoads--;
1012
+ }
1013
+ if (numGets >= (node.getNumResolved || 0)) {
1014
+ node.getNumResolved = node.numGets;
1015
+ onChange({
1016
+ value,
1017
+ lastSync: getParams.lastSync,
1018
+ mode: getParams.mode
1019
+ });
1020
+ }
1021
+ if (modeBeforeReset) {
1022
+ getParams.mode = modeBeforeReset;
1023
+ modeBeforeReset = void 0;
1024
+ }
1025
+ syncState$.assign({
1026
+ isLoaded: syncStateValue.numPendingRemoteLoads < 1,
1027
+ error: void 0,
1028
+ isGetting: syncStateValue.numPendingGets > 0
833
1029
  });
1030
+ };
1031
+ if (state.isPromise(got)) {
1032
+ got.then(handle);
1033
+ } else {
1034
+ handle(got);
834
1035
  }
835
1036
  };
836
- runGet();
1037
+ if (waitFor) {
1038
+ state.whenReady(waitFor, () => state.trackSelector(runGet, sync));
1039
+ } else {
1040
+ state.trackSelector(runGet, sync);
1041
+ }
837
1042
  } else {
838
- node.state.assign({
1043
+ syncState$.assign({
839
1044
  isLoaded: true,
840
1045
  error: void 0
841
1046
  });
842
1047
  }
843
1048
  if (!isSynced) {
844
1049
  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
- }
1050
+ await state.when(syncState$.isLoaded);
1051
+ applyPending(pending);
866
1052
  }
867
1053
  };
868
- syncState.assign({ sync });
1054
+ syncStateValue.sync = sync;
1055
+ } else {
1056
+ if (!isSynced) {
1057
+ applyPending(localState.pendingChanges);
1058
+ }
869
1059
  }
1060
+ syncStateValue.reset = async () => {
1061
+ var _a;
1062
+ const wasPersistEnabled = syncStateValue.isPersistEnabled;
1063
+ const wasSyncEnabled = syncStateValue.isSyncEnabled;
1064
+ syncStateValue.isPersistEnabled = false;
1065
+ syncStateValue.isSyncEnabled = false;
1066
+ syncStateValue.syncCount = 0;
1067
+ isSynced = false;
1068
+ isSubscribed = false;
1069
+ unsubscribe == null ? void 0 : unsubscribe();
1070
+ unsubscribe = void 0;
1071
+ const promise = syncStateValue.clearPersist();
1072
+ obs$.set((_a = syncOptions.initial) != null ? _a : void 0);
1073
+ syncState$.isLoaded.set(false);
1074
+ syncStateValue.isPersistEnabled = wasPersistEnabled;
1075
+ syncStateValue.isSyncEnabled = wasSyncEnabled;
1076
+ node.dirtyFn = sync;
1077
+ await promise;
1078
+ };
870
1079
  const onAllPersistLoaded = () => {
871
1080
  var _a, _b;
872
1081
  let parentNode = node;
@@ -884,77 +1093,27 @@ function syncObservable(obs$, syncOptionsOrSynced) {
884
1093
  }
885
1094
  if ((syncOptions == null ? void 0 : syncOptions.set) || (syncOptions == null ? void 0 : syncOptions.persist)) {
886
1095
  obs$.onChange(
887
- onObsChange.bind(this, obs$, syncState, localState, syncOptions)
1096
+ onObsChange.bind(this, obs$, syncState$, localState, syncOptions)
888
1097
  );
889
1098
  }
890
1099
  });
891
- return syncState;
1100
+ return syncState$;
892
1101
  }
893
- var { getProxy, globalState: globalState2, runWithRetry, symbolLinked: symbolLinked2, setNodeValue, getNodeValue: getNodeValue2 } = state.internal;
1102
+ var { getProxy, globalState: globalState2, setNodeValue, getNodeValue: getNodeValue2 } = state.internal;
894
1103
  function enableActivateSyncedNode() {
895
1104
  globalState2.activateSyncedNode = function activateSyncedNode(node, newValue) {
896
1105
  const obs$ = getProxy(node);
897
1106
  if (node.activationState) {
898
- const { get, initial, set, retry } = node.activationState;
899
- let onChange = void 0;
900
- const pluginRemote = {};
1107
+ const {
1108
+ get: getOrig,
1109
+ initial,
1110
+ set,
1111
+ onChange
1112
+ } = node.activationState;
901
1113
  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
- }
1114
+ const get = getOrig ? (params) => {
1115
+ return promiseReturn = getOrig(params);
1116
+ } : void 0;
958
1117
  const nodeVal = getNodeValue2(node);
959
1118
  if (promiseReturn !== void 0) {
960
1119
  newValue = promiseReturn;
@@ -964,7 +1123,7 @@ function enableActivateSyncedNode() {
964
1123
  newValue = initial;
965
1124
  }
966
1125
  setNodeValue(node, promiseReturn ? void 0 : newValue);
967
- syncState = syncObservable(obs$, { ...node.activationState, ...pluginRemote });
1126
+ syncObservable(obs$, { ...node.activationState, get, set });
968
1127
  return { update: onChange, value: newValue };
969
1128
  } else {
970
1129
  let update = void 0;
@@ -1001,21 +1160,27 @@ function installPersistActivateNode() {
1001
1160
  didInstall = true;
1002
1161
  }
1003
1162
  }
1163
+ var { deepMerge: deepMerge2 } = state.internal;
1164
+ function configureSynced(fnOrOrigOptions, origOptions) {
1165
+ const fn = origOptions ? fnOrOrigOptions : void 0;
1166
+ origOptions = origOptions != null ? origOptions : fnOrOrigOptions;
1167
+ return (options) => {
1168
+ const merged = deepMerge2(origOptions, options);
1169
+ return fn ? fn(merged) : merged;
1170
+ };
1171
+ }
1004
1172
 
1005
1173
  // sync.ts
1006
- function isInRemoteChange() {
1007
- return state.internal.globalState.isLoadingRemote;
1008
- }
1009
- var internal3 = {
1174
+ var internal4 = {
1010
1175
  observableSyncConfiguration
1011
1176
  };
1012
1177
 
1013
1178
  exports.combineTransforms = combineTransforms;
1014
1179
  exports.configureObservableSync = configureObservableSync;
1180
+ exports.configureSynced = configureSynced;
1015
1181
  exports.deepEqual = deepEqual;
1016
1182
  exports.diffObjects = diffObjects;
1017
- exports.internal = internal3;
1018
- exports.isInRemoteChange = isInRemoteChange;
1183
+ exports.internal = internal4;
1019
1184
  exports.mapSyncPlugins = mapSyncPlugins;
1020
1185
  exports.onChangeRemote = onChangeRemote;
1021
1186
  exports.removeNullUndefined = removeNullUndefined;