@legendapp/state 2.2.0-next.65 → 2.2.0-next.67

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 (65) hide show
  1. package/index.js +29 -15
  2. package/index.js.map +1 -1
  3. package/index.mjs +29 -15
  4. package/index.mjs.map +1 -1
  5. package/package.json +21 -21
  6. package/{cache-plugins → persist-plugins}/async-storage.d.ts +3 -3
  7. package/{cache-plugins → persist-plugins}/async-storage.js +4 -4
  8. package/persist-plugins/async-storage.js.map +1 -0
  9. package/{cache-plugins → persist-plugins}/async-storage.mjs +4 -4
  10. package/persist-plugins/async-storage.mjs.map +1 -0
  11. package/persist-plugins/firebase.js.map +1 -1
  12. package/persist-plugins/firebase.mjs.map +1 -1
  13. package/persist-plugins/indexeddb.d.ts +25 -0
  14. package/{cache-plugins → persist-plugins}/indexeddb.js +2 -2
  15. package/persist-plugins/indexeddb.js.map +1 -0
  16. package/{cache-plugins → persist-plugins}/indexeddb.mjs +2 -2
  17. package/persist-plugins/indexeddb.mjs.map +1 -0
  18. package/persist-plugins/local-storage.d.ts +20 -0
  19. package/{cache-plugins → persist-plugins}/local-storage.js +10 -10
  20. package/persist-plugins/local-storage.js.map +1 -0
  21. package/{cache-plugins → persist-plugins}/local-storage.mjs +8 -8
  22. package/persist-plugins/local-storage.mjs.map +1 -0
  23. package/persist-plugins/mmkv.d.ts +14 -0
  24. package/{cache-plugins → persist-plugins}/mmkv.js +3 -3
  25. package/persist-plugins/mmkv.js.map +1 -0
  26. package/{cache-plugins → persist-plugins}/mmkv.mjs +3 -3
  27. package/persist-plugins/mmkv.mjs.map +1 -0
  28. package/persist.js +56 -53
  29. package/persist.js.map +1 -1
  30. package/persist.mjs +56 -53
  31. package/persist.mjs.map +1 -1
  32. package/react-hooks/usePersistedObservable.d.ts +2 -2
  33. package/src/helpers.ts +28 -14
  34. package/src/observableInterfaces.ts +2 -3
  35. package/src/persist/persistObservable.ts +24 -20
  36. package/src/{cache-plugins → persist-plugins}/async-storage.ts +6 -6
  37. package/src/persist-plugins/firebase.ts +3 -3
  38. package/src/{cache-plugins → persist-plugins}/indexeddb.ts +17 -17
  39. package/src/{cache-plugins → persist-plugins}/local-storage.ts +8 -8
  40. package/src/{cache-plugins → persist-plugins}/mmkv.ts +13 -13
  41. package/src/persistTypes.ts +15 -22
  42. package/src/react-hooks/usePersistedObservable.ts +2 -2
  43. package/src/sync/syncObservable.ts +93 -84
  44. package/src/sync/syncObservableAdapter.ts +2 -2
  45. package/src/sync/synced.ts +2 -2
  46. package/src/sync-plugins/fetch.ts +3 -3
  47. package/src/syncTypes.ts +19 -20
  48. package/sync-plugins/fetch.d.ts +2 -2
  49. package/sync-plugins/fetch.js.map +1 -1
  50. package/sync-plugins/fetch.mjs.map +1 -1
  51. package/sync.js +56 -53
  52. package/sync.js.map +1 -1
  53. package/sync.mjs +56 -53
  54. package/sync.mjs.map +1 -1
  55. package/cache-plugins/async-storage.js.map +0 -1
  56. package/cache-plugins/async-storage.mjs.map +0 -1
  57. package/cache-plugins/indexeddb.d.ts +0 -25
  58. package/cache-plugins/indexeddb.js.map +0 -1
  59. package/cache-plugins/indexeddb.mjs.map +0 -1
  60. package/cache-plugins/local-storage.d.ts +0 -20
  61. package/cache-plugins/local-storage.js.map +0 -1
  62. package/cache-plugins/local-storage.mjs.map +0 -1
  63. package/cache-plugins/mmkv.d.ts +0 -14
  64. package/cache-plugins/mmkv.js.map +0 -1
  65. package/cache-plugins/mmkv.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { Observable, ObservableParam, PersistOptions, observable } from '@legendapp/state';
1
+ import { Observable, ObservableParam, LegacyPersistOptions, observable } from '@legendapp/state';
2
2
  import { persistObservable } from '@legendapp/state/persist';
3
3
  import { useMemo } from 'react';
4
4
 
@@ -13,7 +13,7 @@ import { useMemo } from 'react';
13
13
  * @see https://www.legendapp.com/dev/state/react/#useObservable
14
14
  */
15
15
  export function usePersistedObservable<T>(params: {
16
- options: PersistOptions<T>;
16
+ options: LegacyPersistOptions<T>;
17
17
  initialValue?: T | (() => T) | (() => Promise<T>);
18
18
  }): Observable<T> {
19
19
  // Create the observable from the default value
@@ -1,18 +1,18 @@
1
1
  import type {
2
- CacheMetadata,
3
- CacheOptions,
2
+ PersistMetadata,
3
+ PersistOptions,
4
4
  Change,
5
5
  ClassConstructor,
6
6
  ListenerParams,
7
7
  NodeValue,
8
8
  Observable,
9
- ObservableCachePlugin,
9
+ ObservablePersistPlugin,
10
10
  ObservableObject,
11
11
  ObservableParam,
12
12
  ObservableSyncClass,
13
13
  ObservableSyncState,
14
14
  SyncTransform,
15
- SyncedParams,
15
+ SyncedOptions,
16
16
  TypeAtPath,
17
17
  } from '@legendapp/state';
18
18
  import {
@@ -36,21 +36,21 @@ import { observableSyncConfiguration } from './configureObservableSync';
36
36
  import { removeNullUndefined } from './syncHelpers';
37
37
  import { syncObservableAdapter } from './syncObservableAdapter';
38
38
 
39
- const { globalState, symbolLinked, getNode } = internal;
39
+ const { globalState, symbolLinked, getNode, getNodeValue } = internal;
40
40
 
41
41
  export const mapSyncPlugins: WeakMap<
42
- ClassConstructor<ObservableCachePlugin | ObservableSyncClass>,
42
+ ClassConstructor<ObservablePersistPlugin | ObservableSyncClass>,
43
43
  {
44
- plugin: ObservableCachePlugin | ObservableSyncClass;
44
+ plugin: ObservablePersistPlugin | ObservableSyncClass;
45
45
  initialized: Observable<boolean>;
46
46
  }
47
47
  > = new WeakMap();
48
48
 
49
- const metadatas = new WeakMap<ObservableParam<any>, CacheMetadata>();
49
+ const metadatas = new WeakMap<ObservableParam<any>, PersistMetadata>();
50
50
  const promisesLocalSaves = new Set<Promise<void>>();
51
51
 
52
52
  interface LocalState {
53
- pluginCache?: ObservableCachePlugin;
53
+ pluginPersist?: ObservablePersistPlugin;
54
54
  pluginSync?: ObservableSyncClass;
55
55
  pendingChanges?: Record<string, { p: any; v?: any; t: TypeAtPath[] }>;
56
56
  numSavesOutstanding?: number;
@@ -72,15 +72,15 @@ interface PreppedChangeRemote {
72
72
 
73
73
  type ChangeWithPathStr = Change & { pathStr: string };
74
74
 
75
- function parseLocalConfig(config: string | CacheOptions | undefined): {
75
+ function parseLocalConfig(config: string | PersistOptions | undefined): {
76
76
  table: string;
77
- config: CacheOptions;
77
+ config: PersistOptions;
78
78
  } {
79
79
  return config
80
80
  ? isString(config)
81
81
  ? { table: config, config: { name: config } }
82
82
  : { table: config.name, config }
83
- : ({} as { table: string; config: CacheOptions });
83
+ : ({} as { table: string; config: PersistOptions });
84
84
  }
85
85
 
86
86
  function doInOrder<T>(arg1: T | Promise<T>, arg2: (value: T) => void): any {
@@ -128,19 +128,19 @@ async function updateMetadataImmediate<T>(
128
128
  obs: ObservableParam<any>,
129
129
  localState: LocalState,
130
130
  syncState: Observable<ObservableSyncState>,
131
- syncOptions: SyncedParams<T>,
132
- newMetadata: CacheMetadata,
131
+ syncOptions: SyncedOptions<T>,
132
+ newMetadata: PersistMetadata,
133
133
  ) {
134
134
  const saves = Array.from(promisesLocalSaves);
135
135
  if (saves.length > 0) {
136
136
  await Promise.all(saves);
137
137
  }
138
138
 
139
- const { pluginCache } = localState;
140
- const { table, config } = parseLocalConfig(syncOptions?.cache);
139
+ const { pluginPersist } = localState;
140
+ const { table, config } = parseLocalConfig(syncOptions?.persist);
141
141
 
142
142
  // Save metadata
143
- const oldMetadata: CacheMetadata | undefined = metadatas.get(obs);
143
+ const oldMetadata: PersistMetadata | undefined = metadatas.get(obs);
144
144
 
145
145
  const { lastSync, pending } = newMetadata;
146
146
 
@@ -149,14 +149,13 @@ async function updateMetadataImmediate<T>(
149
149
  if (needsUpdate) {
150
150
  const metadata = Object.assign({}, oldMetadata, newMetadata);
151
151
  metadatas.set(obs, metadata);
152
- if (pluginCache) {
153
- await pluginCache!.setMetadata(table, metadata, config);
152
+ if (pluginPersist) {
153
+ await pluginPersist!.setMetadata(table, metadata, config);
154
154
  }
155
155
 
156
156
  if (lastSync) {
157
157
  syncState.assign({
158
158
  lastSync: lastSync,
159
- dateModified: lastSync,
160
159
  });
161
160
  }
162
161
  }
@@ -166,14 +165,14 @@ function updateMetadata<T>(
166
165
  obs: ObservableParam<any>,
167
166
  localState: LocalState,
168
167
  syncState: ObservableObject<ObservableSyncState>,
169
- syncOptions: SyncedParams<T>,
170
- newMetadata: CacheMetadata,
168
+ syncOptions: SyncedOptions<T>,
169
+ newMetadata: PersistMetadata,
171
170
  ) {
172
171
  if (localState.timeoutSaveMetadata) {
173
172
  clearTimeout(localState.timeoutSaveMetadata);
174
173
  }
175
174
  localState.timeoutSaveMetadata = setTimeout(
176
- () => updateMetadataImmediate(obs, localState, syncState, syncOptions as SyncedParams<T>, newMetadata),
175
+ () => updateMetadataImmediate(obs, localState, syncState, syncOptions as SyncedOptions<T>, newMetadata),
177
176
  0,
178
177
  );
179
178
  }
@@ -184,13 +183,13 @@ interface QueuedChange<T = any> {
184
183
  obs: Observable<T>;
185
184
  syncState: ObservableObject<ObservableSyncState>;
186
185
  localState: LocalState;
187
- syncOptions: SyncedParams<T>;
186
+ syncOptions: SyncedOptions<T>;
188
187
  changes: ListenerParams['changes'];
189
188
  }
190
189
 
191
190
  let _queuedChanges: QueuedChange[] = [];
192
- const _queuedRemoteChanges: Map<SyncedParams, QueuedChange[]> = new Map();
193
- const _queuedRemoteChangesTimeouts: Map<SyncedParams, number> = new Map();
191
+ const _queuedRemoteChanges: Map<SyncedOptions, QueuedChange[]> = new Map();
192
+ const _queuedRemoteChangesTimeouts: Map<SyncedOptions, number> = new Map();
194
193
 
195
194
  function mergeChanges(changes: Change[]) {
196
195
  const changesByPath = new Map<string, Change>();
@@ -235,7 +234,7 @@ async function processQueuedChanges() {
235
234
  const queuedChanges = mergeQueuedChanges(_queuedChanges);
236
235
  _queuedChanges = [];
237
236
 
238
- const pendingSyncOptions = new Set<SyncedParams>();
237
+ const pendingSyncOptions = new Set<SyncedOptions>();
239
238
  for (let i = 0; i < queuedChanges.length; i++) {
240
239
  const change = queuedChanges[i];
241
240
  if (!change.inRemoteChange) {
@@ -284,7 +283,7 @@ async function processQueuedChanges() {
284
283
  }
285
284
  }
286
285
 
287
- async function processQueuedRemoteChanges(syncOptions: SyncedParams) {
286
+ async function processQueuedRemoteChanges(syncOptions: SyncedOptions) {
288
287
  const arr = _queuedRemoteChanges.get(syncOptions);
289
288
  if (arr?.length) {
290
289
  const queuedRemoteChanges = mergeQueuedChanges(arr);
@@ -299,11 +298,11 @@ async function processQueuedRemoteChanges(syncOptions: SyncedParams) {
299
298
  async function prepChangeLocal(queuedChange: QueuedChange): Promise<PreppedChangeLocal | undefined> {
300
299
  const { syncState, changes, localState, syncOptions, inRemoteChange, isApplyingPending } = queuedChange;
301
300
 
302
- const cache = syncOptions.cache;
301
+ const persist = syncOptions.persist;
303
302
  const { pluginSync } = localState;
304
- const { config: configLocal } = parseLocalConfig(cache);
303
+ const { config: configLocal } = parseLocalConfig(persist);
305
304
  const configRemote = syncOptions;
306
- const saveLocal = cache?.name && !configLocal.readonly && !isApplyingPending && syncState.isEnabledLocal.peek();
305
+ const saveLocal = persist?.name && !configLocal.readonly && !isApplyingPending && syncState.isEnabledLocal.peek();
307
306
  const saveRemote = !!(
308
307
  !inRemoteChange &&
309
308
  pluginSync?.set &&
@@ -313,7 +312,10 @@ async function prepChangeLocal(queuedChange: QueuedChange): Promise<PreppedChang
313
312
 
314
313
  if (saveLocal || saveRemote) {
315
314
  if (saveLocal && !syncState.isLoadedLocal.peek()) {
316
- console.error('[legend-state] WARNING: An observable was changed before being loaded from cache', cache);
315
+ console.error(
316
+ '[legend-state] WARNING: An observable was changed before being loaded from persist',
317
+ persist,
318
+ );
317
319
  return undefined;
318
320
  }
319
321
  const changesLocal: ChangeWithPathStr[] = [];
@@ -387,17 +389,20 @@ async function prepChangeRemote(queuedChange: QueuedChange): Promise<PreppedChan
387
389
  isApplyingPending,
388
390
  } = queuedChange;
389
391
 
390
- const cache = syncOptions.cache;
392
+ const persist = syncOptions.persist;
391
393
  const { pluginSync } = localState;
392
- const { config: configLocal } = parseLocalConfig(cache!);
394
+ const { config: configLocal } = parseLocalConfig(persist!);
393
395
  const configRemote = syncOptions;
394
- const saveLocal = cache && !configLocal.readonly && !isApplyingPending && syncState.isEnabledLocal.peek();
396
+ const saveLocal = persist && !configLocal.readonly && !isApplyingPending && syncState.isEnabledLocal.peek();
395
397
  const saveRemote =
396
398
  !inRemoteChange && pluginSync?.set && configRemote?.enableSync !== false && syncState.isEnabledRemote.peek();
397
399
 
398
400
  if (saveLocal || saveRemote) {
399
401
  if (saveLocal && !syncState.isLoadedLocal.peek()) {
400
- console.error('[legend-state] WARNING: An observable was changed before being loaded from cache', cache);
402
+ console.error(
403
+ '[legend-state] WARNING: An observable was changed before being loaded from persist',
404
+ persist,
405
+ );
401
406
  return undefined;
402
407
  }
403
408
  const changesRemote: ChangeWithPathStr[] = [];
@@ -509,12 +514,12 @@ async function doChangeLocal(changeInfo: PreppedChangeLocal | undefined) {
509
514
 
510
515
  const { queuedChange, changesLocal, saveRemote } = changeInfo;
511
516
  const { obs, syncState, localState, syncOptions: syncOptions } = queuedChange;
512
- const { pluginCache } = localState;
517
+ const { pluginPersist } = localState;
513
518
 
514
- const cache = syncOptions.cache;
515
- const { table, config: configLocal } = parseLocalConfig(cache!);
519
+ const persist = syncOptions.persist;
520
+ const { table, config: configLocal } = parseLocalConfig(persist!);
516
521
  const configRemote = syncOptions;
517
- const shouldSaveMetadata = cache && configRemote?.offlineBehavior === 'retry';
522
+ const shouldSaveMetadata = persist && configRemote?.offlineBehavior === 'retry';
518
523
 
519
524
  if (saveRemote && shouldSaveMetadata) {
520
525
  // First save pending changes before saving local or remote
@@ -526,7 +531,7 @@ async function doChangeLocal(changeInfo: PreppedChangeLocal | undefined) {
526
531
  if (changesLocal.length > 0) {
527
532
  // Save the changes to local cache before saving to remote. They are already marked as pending so
528
533
  // if remote sync fails or the app is closed before remote sync, it will attempt to sync them on the next load.
529
- let promiseSet = pluginCache!.set(table, changesLocal, configLocal);
534
+ let promiseSet = pluginPersist!.set(table, changesLocal, configLocal);
530
535
 
531
536
  if (promiseSet) {
532
537
  promiseSet = promiseSet.then(() => {
@@ -545,13 +550,13 @@ async function doChangeRemote(changeInfo: PreppedChangeRemote | undefined) {
545
550
 
546
551
  const { queuedChange, changesRemote } = changeInfo;
547
552
  const { obs, syncState, localState, syncOptions: syncOptions } = queuedChange;
548
- const { pluginCache, pluginSync } = localState;
553
+ const { pluginPersist, pluginSync } = localState;
549
554
 
550
- const cache = syncOptions.cache;
551
- const { table, config: configLocal } = parseLocalConfig(cache!);
555
+ const persist = syncOptions.persist;
556
+ const { table, config: configLocal } = parseLocalConfig(persist!);
552
557
  const { offlineBehavior, allowSetIfGetError, onBeforeSet, onSetError, waitForSet, onAfterSet } =
553
- syncOptions || ({} as SyncedParams);
554
- const shouldSaveMetadata = cache && offlineBehavior === 'retry';
558
+ syncOptions || ({} as SyncedOptions);
559
+ const shouldSaveMetadata = persist && offlineBehavior === 'retry';
555
560
 
556
561
  if (changesRemote.length > 0) {
557
562
  // Wait for remote to be ready before saving
@@ -598,9 +603,9 @@ async function doChangeRemote(changeInfo: PreppedChangeRemote | undefined) {
598
603
  const pathStrs = Array.from(new Set(changesRemote.map((change) => change.pathStr)));
599
604
  const { changes, lastSync } = saved;
600
605
  if (pathStrs.length > 0) {
601
- if (cache) {
602
- const metadata: CacheMetadata = {};
603
- const pending = pluginCache!.getMetadata(table, configLocal)?.pending;
606
+ if (persist) {
607
+ const metadata: PersistMetadata = {};
608
+ const pending = pluginPersist!.getMetadata(table, configLocal)?.pending;
604
609
  let transformedChanges: object | undefined = undefined;
605
610
 
606
611
  for (let i = 0; i < pathStrs.length; i++) {
@@ -656,7 +661,7 @@ function onObsChange<T>(
656
661
  obs: Observable<T>,
657
662
  syncState: ObservableObject<ObservableSyncState>,
658
663
  localState: LocalState,
659
- syncOptions: SyncedParams<T>,
664
+ syncOptions: SyncedOptions<T>,
660
665
  { changes, loading, remote }: ListenerParams,
661
666
  ) {
662
667
  if (!loading) {
@@ -680,27 +685,28 @@ function onObsChange<T>(
680
685
 
681
686
  async function loadLocal<T>(
682
687
  obs: ObservableParam<T>,
683
- syncOptions: SyncedParams<any>,
688
+ syncOptions: SyncedOptions<any>,
684
689
  syncState: ObservableObject<ObservableSyncState>,
685
690
  localState: LocalState,
686
691
  ) {
687
- const { cache } = syncOptions;
692
+ const { persist } = syncOptions;
688
693
 
689
- if (cache) {
690
- const CachePlugin: ClassConstructor<ObservableCachePlugin> =
691
- cache.plugin! || observableSyncConfiguration.cache?.plugin;
692
- const { table, config } = parseLocalConfig(cache);
694
+ if (persist) {
695
+ const PersistPlugin: ClassConstructor<ObservablePersistPlugin> =
696
+ persist.plugin! || observableSyncConfiguration.persist?.plugin;
697
+ const { table, config } = parseLocalConfig(persist);
698
+ const node = getNode(obs);
693
699
 
694
- if (!CachePlugin) {
695
- throw new Error('Local cache is not configured');
700
+ if (!PersistPlugin) {
701
+ throw new Error('Local persist is not configured');
696
702
  }
697
703
  // Ensure there's only one instance of the cache plugin
698
- if (!mapSyncPlugins.has(CachePlugin)) {
699
- const cachePlugin = new CachePlugin();
700
- const mapValue = { plugin: cachePlugin, initialized: observable(false) };
701
- mapSyncPlugins.set(CachePlugin, mapValue);
702
- if (cachePlugin.initialize) {
703
- const initializePromise = cachePlugin.initialize?.(observableSyncConfiguration?.cache || {});
704
+ if (!mapSyncPlugins.has(PersistPlugin)) {
705
+ const persistPlugin = new PersistPlugin();
706
+ const mapValue = { plugin: persistPlugin, initialized: observable(false) };
707
+ mapSyncPlugins.set(PersistPlugin, mapValue);
708
+ if (persistPlugin.initialize) {
709
+ const initializePromise = persistPlugin.initialize?.(observableSyncConfiguration?.persist || {});
704
710
  if (isPromise(initializePromise)) {
705
711
  await initializePromise;
706
712
  }
@@ -708,33 +714,34 @@ async function loadLocal<T>(
708
714
  mapValue.initialized.set(true);
709
715
  }
710
716
 
711
- const { plugin, initialized: initialized$ } = mapSyncPlugins.get(CachePlugin)!;
712
- const cachePlugin = plugin as ObservableCachePlugin;
717
+ const { plugin, initialized: initialized$ } = mapSyncPlugins.get(PersistPlugin)!;
718
+ const persistPlugin = plugin as ObservablePersistPlugin;
713
719
 
714
- localState.pluginCache = cachePlugin as ObservableCachePlugin;
720
+ localState.pluginPersist = persistPlugin as ObservablePersistPlugin;
715
721
 
716
722
  if (!initialized$.peek()) {
717
723
  await when(initialized$);
718
724
  }
719
725
 
720
726
  // If cache has an asynchronous load, wait for it
721
- if (cachePlugin.loadTable) {
722
- const promise = cachePlugin.loadTable(table, config);
727
+ if (persistPlugin.loadTable) {
728
+ const promise = persistPlugin.loadTable(table, config);
723
729
  if (promise) {
724
730
  await promise;
725
731
  }
726
732
  }
727
733
 
734
+ // Get current value for init
735
+ const prevValue = getNodeValue(node) as object;
736
+
728
737
  // Get the value from state
729
- let value = cachePlugin.getTable(table, config);
730
- const metadata = cachePlugin.getMetadata(table, config);
738
+ let value = persistPlugin.getTable(table, prevValue, config);
739
+ const metadata = persistPlugin.getMetadata(table, config);
731
740
 
732
741
  if (metadata) {
733
742
  metadatas.set(obs, metadata);
734
743
  localState.pendingChanges = metadata.pending;
735
- // TODOV3 Remove dateModified
736
744
  syncState.assign({
737
- dateModified: metadata.lastSync,
738
745
  lastSync: metadata.lastSync,
739
746
  });
740
747
  }
@@ -754,7 +761,6 @@ async function loadLocal<T>(
754
761
  internal.globalState.isLoadingLocal = true;
755
762
 
756
763
  // We want to merge the local data on top of any initial state the object is created with
757
- const prevValue = obs.peek();
758
764
  if (value === null && (!prevValue || (prevValue as any)[symbolLinked])) {
759
765
  obs.set(value);
760
766
  } else {
@@ -764,12 +770,10 @@ async function loadLocal<T>(
764
770
  internal.globalState.isLoadingLocal = false;
765
771
  }
766
772
 
767
- const node = getNode(obs);
768
-
769
- (node.state as Observable<ObservableSyncState>).peek().clearLocal = () =>
773
+ node.state!.peek().clearLocal = () =>
770
774
  Promise.all([
771
- cachePlugin.deleteTable(table, config),
772
- cachePlugin.deleteMetadata(table, config),
775
+ persistPlugin.deleteTable(table, config),
776
+ persistPlugin.deleteMetadata(table, config),
773
777
  ]) as unknown as Promise<void>;
774
778
  }
775
779
  syncState.isLoadedLocal.set(true);
@@ -777,7 +781,7 @@ async function loadLocal<T>(
777
781
 
778
782
  export function syncObservable<T>(
779
783
  obs$: ObservableParam<T>,
780
- syncOptions: SyncedParams<T>,
784
+ syncOptions: SyncedOptions<T>,
781
785
  ): Observable<ObservableSyncState> {
782
786
  const node = getNode(obs$);
783
787
 
@@ -786,7 +790,7 @@ export function syncObservable<T>(
786
790
  syncOptions = Object.assign(
787
791
  {
788
792
  syncMode: 'auto',
789
- } as SyncedParams,
793
+ } as SyncedOptions,
790
794
  observableSyncConfiguration,
791
795
  removeNullUndefined(syncOptions),
792
796
  );
@@ -847,13 +851,18 @@ export function syncObservable<T>(
847
851
  const { v, t } = pending[key];
848
852
 
849
853
  if (t.length === 0 || !value) {
850
- value = v;
854
+ if (isObject(value) && isObject(v)) {
855
+ Object.assign(value, v);
856
+ } else {
857
+ value = v;
858
+ }
851
859
  } else if ((value as any)[p[0]] !== undefined) {
852
860
  (value as any) = setAtPath(
853
861
  value as any,
854
862
  p,
855
863
  t,
856
864
  v,
865
+ 'merge',
857
866
  obs$.peek(),
858
867
  (path: string[], value: any) => {
859
868
  delete pending[key];
@@ -882,7 +891,7 @@ export function syncObservable<T>(
882
891
  }
883
892
  });
884
893
  }
885
- if (lastSync && syncOptions.cache) {
894
+ if (lastSync && syncOptions.persist) {
886
895
  updateMetadata(obs$, localState, syncState, syncOptions, {
887
896
  lastSync,
888
897
  });
@@ -951,7 +960,7 @@ export function syncObservable<T>(
951
960
  sync();
952
961
  }
953
962
 
954
- obs$.onChange(onObsChange.bind(this, obs$ as any, syncState, localState, syncOptions as SyncedParams<any>));
963
+ obs$.onChange(onObsChange.bind(this, obs$ as any, syncState, localState, syncOptions as SyncedOptions<any>));
955
964
  });
956
965
 
957
966
  return syncState;
@@ -1,6 +1,6 @@
1
- import { ObservableSyncGetParams, SyncedParams, isPromise, type ObservableSyncClass } from '@legendapp/state';
1
+ import { ObservableSyncGetParams, SyncedOptions, isPromise, type ObservableSyncClass } from '@legendapp/state';
2
2
 
3
- export function syncObservableAdapter<T = {}>({ get, set }: SyncedParams<T>): ObservableSyncClass {
3
+ export function syncObservableAdapter<T = {}>({ get, set }: SyncedOptions<T>): ObservableSyncClass {
4
4
  const ret: ObservableSyncClass = {};
5
5
 
6
6
  if (get) {
@@ -1,10 +1,10 @@
1
- import type { Synced, SyncedParams } from '@legendapp/state';
1
+ import type { Synced, SyncedOptions } from '@legendapp/state';
2
2
  import { internal } from '@legendapp/state';
3
3
  import { enableActivateSyncedNode } from './activateSyncedNode';
4
4
 
5
5
  const { symbolLinked } = internal;
6
6
 
7
- export function synced<T>(params: SyncedParams<T>): Synced<T> {
7
+ export function synced<T>(params: SyncedOptions<T>): Synced<T> {
8
8
  installPersistActivateNode();
9
9
  return (() => ({
10
10
  [symbolLinked]: { ...params, synced: true },
@@ -1,7 +1,7 @@
1
- import { Synced, SyncedParams, SyncedSetParams, isString } from '@legendapp/state';
1
+ import { Synced, SyncedOptions, SyncedSetParams, isString } from '@legendapp/state';
2
2
  import { synced } from '@legendapp/state/persist';
3
3
 
4
- export interface SyncedFetchProps extends Omit<SyncedParams, 'get' | 'set'> {
4
+ export interface SyncedFetchProps extends Omit<SyncedOptions, 'get' | 'set'> {
5
5
  get: string | RequestInfo;
6
6
  set?: string | RequestInfo;
7
7
  getInit?: RequestInit;
@@ -20,7 +20,7 @@ export function syncedFetch<T>({
20
20
  onSet,
21
21
  onSetValueType,
22
22
  }: SyncedFetchProps): Synced<T> {
23
- const ret: SyncedParams = {
23
+ const ret: SyncedOptions = {
24
24
  get: () => fetch(get, getInit).then((response) => response[valueType || 'json']()),
25
25
  };
26
26
 
package/src/syncTypes.ts CHANGED
@@ -16,9 +16,9 @@ import {
16
16
  } from './observableInterfaces';
17
17
  import { Observable, ObservableParam, ObservableState } from './observableTypes';
18
18
 
19
- export interface CacheOptions<T = any> {
19
+ export interface PersistOptions<T = any> {
20
20
  name: string;
21
- plugin?: ClassConstructor<ObservableCachePlugin, T[]>;
21
+ plugin?: ClassConstructor<ObservablePersistPlugin, T[]>;
22
22
  transform?: SyncTransform<T>;
23
23
  readonly?: boolean;
24
24
  mmkv?: MMKVConfiguration;
@@ -48,13 +48,13 @@ export type SyncedSetParams<T> = SetParams<T> & {
48
48
 
49
49
  export type GetMode = 'set' | 'assign' | 'merge' | 'append' | 'prepend';
50
50
 
51
- export interface SyncedParams<T = any> extends Omit<LinkedParams<T>, 'get' | 'set'> {
51
+ export interface SyncedOptions<T = any> extends Omit<LinkedParams<T>, 'get' | 'set'> {
52
52
  get?: (params: SyncedGetParams) => Promise<T> | T;
53
53
  set?: (params: SyncedSetParams<T>) => void | Promise<any>;
54
54
  subscribe?: (params: { node: NodeValue; update: UpdateFn; refresh: () => void }) => void;
55
55
  retry?: RetryOptions;
56
56
  offlineBehavior?: false | 'retry';
57
- cache?: CacheOptions<any>;
57
+ persist?: PersistOptions<any>;
58
58
  debounceSet?: number;
59
59
  syncMode?: 'auto' | 'manual';
60
60
  getMode?: GetMode;
@@ -69,11 +69,11 @@ export interface SyncedParams<T = any> extends Omit<LinkedParams<T>, 'get' | 'se
69
69
  allowSetIfGetError?: boolean;
70
70
  }
71
71
 
72
- export interface SyncedParamsGlobal<T = any> extends Omit<SyncedParams<T>, 'get' | 'set' | 'cache'> {
73
- cache?: ObservableCachePluginOptions & { plugin?: ClassConstructor<ObservableCachePlugin, T[]> };
72
+ export interface SyncedParamsGlobal<T = any> extends Omit<SyncedOptions<T>, 'get' | 'set' | 'persist'> {
73
+ persist?: ObservablePersistPluginOptions & { plugin?: ClassConstructor<ObservablePersistPlugin, T[]> };
74
74
  }
75
75
 
76
- export interface ObservableCachePluginOptions {
76
+ export interface ObservablePersistPluginOptions {
77
77
  onGetError?: (error: Error) => void;
78
78
  onSetError?: (error: Error) => void;
79
79
  indexedDB?: {
@@ -86,17 +86,17 @@ export interface ObservableCachePluginOptions {
86
86
  preload?: boolean | string[];
87
87
  };
88
88
  }
89
- export interface ObservableCachePlugin {
90
- initialize?(config: ObservableCachePluginOptions): void | Promise<void>;
91
- loadTable?(table: string, config: CacheOptions): Promise<any> | void;
92
- getTable<T = any>(table: string, config: CacheOptions): T;
93
- set(table: string, changes: Change[], config: CacheOptions): Promise<any> | void;
94
- deleteTable(table: string, config: CacheOptions): Promise<any> | void;
95
- getMetadata(table: string, config: CacheOptions): CacheMetadata;
96
- setMetadata(table: string, metadata: CacheMetadata, config: CacheOptions): Promise<any> | void;
97
- deleteMetadata(table: string, config: CacheOptions): Promise<any> | void;
89
+ export interface ObservablePersistPlugin {
90
+ initialize?(config: ObservablePersistPluginOptions): void | Promise<void>;
91
+ loadTable?(table: string, config: PersistOptions): Promise<any> | void;
92
+ getTable<T = any>(table: string, init: object, config: PersistOptions): T;
93
+ set(table: string, changes: Change[], config: PersistOptions): Promise<any> | void;
94
+ deleteTable(table: string, config: PersistOptions): Promise<any> | void;
95
+ getMetadata(table: string, config: PersistOptions): PersistMetadata;
96
+ setMetadata(table: string, metadata: PersistMetadata, config: PersistOptions): Promise<any> | void;
97
+ deleteMetadata(table: string, config: PersistOptions): Promise<any> | void;
98
98
  }
99
- export interface CacheMetadata {
99
+ export interface PersistMetadata {
100
100
  id?: '__legend_metadata';
101
101
  // modified ?: number;
102
102
  lastSync?: number;
@@ -110,7 +110,6 @@ export interface ObservableSyncStateBase {
110
110
  isLoadedLocal: boolean;
111
111
  isEnabledLocal: boolean;
112
112
  isEnabledRemote: boolean;
113
- dateModified?: number;
114
113
  lastSync?: number;
115
114
  syncCount?: number;
116
115
  clearLocal: () => Promise<void>;
@@ -130,14 +129,14 @@ export type ObservableSyncState = ObservableState & ObservableSyncStateBase;
130
129
  export interface ObservableSyncSetParams<T> {
131
130
  syncState: Observable<ObservableSyncState>;
132
131
  obs: ObservableParam<T>;
133
- options: SyncedParams<T>;
132
+ options: SyncedOptions<T>;
134
133
  changes: Change[];
135
134
  value: T;
136
135
  }
137
136
  export interface ObservableSyncGetParams<T> {
138
137
  state: Observable<ObservableSyncState>;
139
138
  obs: ObservableParam<T>;
140
- options: SyncedParams<T>;
139
+ options: SyncedOptions<T>;
141
140
  dateModified?: number;
142
141
  lastSync?: number;
143
142
  mode?: GetMode;
@@ -1,5 +1,5 @@
1
- import { Synced, SyncedParams, SyncedSetParams } from '@legendapp/state';
2
- export interface SyncedFetchProps extends Omit<SyncedParams, 'get' | 'set'> {
1
+ import { Synced, SyncedOptions, SyncedSetParams } from '@legendapp/state';
2
+ export interface SyncedFetchProps extends Omit<SyncedOptions, 'get' | 'set'> {
3
3
  get: string | RequestInfo;
4
4
  set?: string | RequestInfo;
5
5
  getInit?: RequestInit;
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.js","sources":["../src/sync-plugins/fetch.ts"],"sourcesContent":[null],"names":["isString","synced"],"mappings":";;;;;SAagB,WAAW,CAAI,EAC3B,GAAG,EACH,GAAG,EACH,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,EACL,cAAc,GACC,EAAA;AACf,IAAA,MAAM,GAAG,GAAiB;QACtB,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;KACrF,CAAC;IAEF,IAAI,GAAG,EAAE;AACL,QAAA,GAAG,CAAC,GAAG,GAAG,OAAO,MAA4B,KAAI;AAC7C,YAAA,MAAM,WAAW,GAAGA,cAAQ,CAAC,GAAG,CAAC,GAAI,EAAE,GAAG,EAAE,GAAG,EAAkB,GAAG,GAAG,CAAC;AACxE,YAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CACxB,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EACtF,OAAO,CACV,CAAC;YACF,IAAI,KAAK,EAAE;AACP,gBAAA,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,cAAc,IAAI,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;gBACjE,KAAK,CAAC,MAAM,CAAC,CAAC;aACjB;AACL,SAAC,CAAC;KACL;AAED,IAAA,OAAOC,cAAM,CAAC,GAAG,CAAC,CAAC;AACvB;;;;"}
1
+ {"version":3,"file":"fetch.js","sources":["../src/sync-plugins/fetch.ts"],"sourcesContent":[null],"names":["isString","synced"],"mappings":";;;;;SAagB,WAAW,CAAI,EAC3B,GAAG,EACH,GAAG,EACH,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,EACL,cAAc,GACC,EAAA;AACf,IAAA,MAAM,GAAG,GAAkB;QACvB,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;KACrF,CAAC;IAEF,IAAI,GAAG,EAAE;AACL,QAAA,GAAG,CAAC,GAAG,GAAG,OAAO,MAA4B,KAAI;AAC7C,YAAA,MAAM,WAAW,GAAGA,cAAQ,CAAC,GAAG,CAAC,GAAI,EAAE,GAAG,EAAE,GAAG,EAAkB,GAAG,GAAG,CAAC;AACxE,YAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CACxB,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EACtF,OAAO,CACV,CAAC;YACF,IAAI,KAAK,EAAE;AACP,gBAAA,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,cAAc,IAAI,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;gBACjE,KAAK,CAAC,MAAM,CAAC,CAAC;aACjB;AACL,SAAC,CAAC;KACL;AAED,IAAA,OAAOC,cAAM,CAAC,GAAG,CAAC,CAAC;AACvB;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.mjs","sources":["../src/sync-plugins/fetch.ts"],"sourcesContent":[null],"names":[],"mappings":";;;SAagB,WAAW,CAAI,EAC3B,GAAG,EACH,GAAG,EACH,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,EACL,cAAc,GACC,EAAA;AACf,IAAA,MAAM,GAAG,GAAiB;QACtB,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;KACrF,CAAC;IAEF,IAAI,GAAG,EAAE;AACL,QAAA,GAAG,CAAC,GAAG,GAAG,OAAO,MAA4B,KAAI;AAC7C,YAAA,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAI,EAAE,GAAG,EAAE,GAAG,EAAkB,GAAG,GAAG,CAAC;AACxE,YAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CACxB,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EACtF,OAAO,CACV,CAAC;YACF,IAAI,KAAK,EAAE;AACP,gBAAA,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,cAAc,IAAI,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;gBACjE,KAAK,CAAC,MAAM,CAAC,CAAC;aACjB;AACL,SAAC,CAAC;KACL;AAED,IAAA,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACvB;;;;"}
1
+ {"version":3,"file":"fetch.mjs","sources":["../src/sync-plugins/fetch.ts"],"sourcesContent":[null],"names":[],"mappings":";;;SAagB,WAAW,CAAI,EAC3B,GAAG,EACH,GAAG,EACH,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,EACL,cAAc,GACC,EAAA;AACf,IAAA,MAAM,GAAG,GAAkB;QACvB,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;KACrF,CAAC;IAEF,IAAI,GAAG,EAAE;AACL,QAAA,GAAG,CAAC,GAAG,GAAG,OAAO,MAA4B,KAAI;AAC7C,YAAA,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAI,EAAE,GAAG,EAAE,GAAG,EAAkB,GAAG,GAAG,CAAC;AACxE,YAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CACxB,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EACtF,OAAO,CACV,CAAC;YACF,IAAI,KAAK,EAAE;AACP,gBAAA,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,cAAc,IAAI,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;gBACjE,KAAK,CAAC,MAAM,CAAC,CAAC;aACjB;AACL,SAAC,CAAC;KACL;AAED,IAAA,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACvB;;;;"}