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