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