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

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 (327) hide show
  1. package/.DS_Store +0 -0
  2. package/CHANGELOG.md +1 -831
  3. package/LICENSE +1 -21
  4. package/README.md +1 -141
  5. package/as/arrayAsRecord.d.mts +5 -0
  6. package/as/arrayAsRecord.d.ts +5 -0
  7. package/as/arrayAsRecord.js +28 -0
  8. package/as/arrayAsRecord.mjs +26 -0
  9. package/as/arrayAsSet.d.mts +5 -0
  10. package/as/arrayAsSet.d.ts +5 -0
  11. package/as/arrayAsSet.js +13 -0
  12. package/as/arrayAsSet.mjs +11 -0
  13. package/as/arrayAsString.d.mts +5 -0
  14. package/as/arrayAsString.d.ts +5 -0
  15. package/as/arrayAsString.js +13 -0
  16. package/as/arrayAsString.mjs +11 -0
  17. package/as/numberAsString.d.mts +5 -0
  18. package/as/numberAsString.d.ts +5 -0
  19. package/as/numberAsString.js +13 -0
  20. package/as/numberAsString.mjs +11 -0
  21. package/as/recordAsArray.d.mts +5 -0
  22. package/as/recordAsArray.d.ts +5 -0
  23. package/as/recordAsArray.js +25 -0
  24. package/as/recordAsArray.mjs +23 -0
  25. package/as/recordAsString.d.mts +5 -0
  26. package/as/recordAsString.d.ts +5 -0
  27. package/as/recordAsString.js +13 -0
  28. package/as/recordAsString.mjs +11 -0
  29. package/as/setAsArray.d.mts +5 -0
  30. package/as/setAsArray.d.ts +5 -0
  31. package/as/setAsArray.js +13 -0
  32. package/as/setAsArray.mjs +11 -0
  33. package/as/setAsString.d.mts +5 -0
  34. package/as/setAsString.d.ts +5 -0
  35. package/as/setAsString.js +13 -0
  36. package/as/setAsString.mjs +11 -0
  37. package/as/stringAsArray.d.mts +5 -0
  38. package/as/stringAsArray.d.ts +5 -0
  39. package/as/stringAsArray.js +13 -0
  40. package/as/stringAsArray.mjs +11 -0
  41. package/as/stringAsNumber.d.mts +5 -0
  42. package/as/stringAsNumber.d.ts +5 -0
  43. package/as/stringAsNumber.js +16 -0
  44. package/as/stringAsNumber.mjs +14 -0
  45. package/as/stringAsRecord.d.mts +5 -0
  46. package/as/stringAsRecord.d.ts +5 -0
  47. package/as/stringAsRecord.js +15 -0
  48. package/as/stringAsRecord.mjs +13 -0
  49. package/as/stringAsSet.d.mts +5 -0
  50. package/as/stringAsSet.d.ts +5 -0
  51. package/as/stringAsSet.js +13 -0
  52. package/as/stringAsSet.mjs +11 -0
  53. package/babel.d.mts +21 -0
  54. package/babel.d.ts +21 -2
  55. package/babel.js +57 -53
  56. package/babel.mjs +65 -0
  57. package/config/enable$GetSet.js +13 -14
  58. package/config/enable$GetSet.mjs +13 -14
  59. package/config/enableReactComponents.d.mts +9 -0
  60. package/config/enableReactComponents.d.ts +4 -2
  61. package/config/enableReactComponents.js +13 -10
  62. package/config/enableReactComponents.mjs +13 -10
  63. package/config/enableReactNativeComponents.d.mts +22 -0
  64. package/config/enableReactNativeComponents.d.ts +6 -4
  65. package/config/enableReactNativeComponents.js +43 -47
  66. package/config/enableReactNativeComponents.mjs +43 -47
  67. package/config/enableReactTracking.d.mts +7 -0
  68. package/config/enableReactTracking.d.ts +3 -2
  69. package/config/enableReactTracking.js +33 -38
  70. package/config/enableReactTracking.mjs +33 -38
  71. package/config/enableReactUse.d.mts +10 -0
  72. package/config/enableReactUse.d.ts +4 -1
  73. package/config/enableReactUse.js +15 -14
  74. package/config/enableReactUse.mjs +15 -14
  75. package/config/{enable$GetSet.d.ts → enable_GetSet.d.mts} +4 -2
  76. package/config/enable_GetSet.d.ts +10 -0
  77. package/config/enable_PeekAssign.d.mts +10 -0
  78. package/config/enable_PeekAssign.d.ts +4 -2
  79. package/config/enable_PeekAssign.js +13 -14
  80. package/config/enable_PeekAssign.mjs +13 -14
  81. package/helpers/pageHash.d.mts +9 -0
  82. package/helpers/pageHash.d.ts +2 -0
  83. package/helpers/pageHash.js +25 -30
  84. package/helpers/pageHash.mjs +25 -30
  85. package/helpers/pageHashParams.d.mts +9 -0
  86. package/helpers/pageHashParams.d.ts +2 -0
  87. package/helpers/pageHashParams.js +34 -37
  88. package/helpers/pageHashParams.mjs +34 -37
  89. package/helpers/time.d.mts +6 -0
  90. package/helpers/time.d.ts +6 -3
  91. package/helpers/time.js +17 -17
  92. package/helpers/time.mjs +17 -17
  93. package/helpers/trackHistory.d.mts +6 -0
  94. package/helpers/trackHistory.d.ts +4 -2
  95. package/helpers/trackHistory.js +13 -16
  96. package/helpers/trackHistory.mjs +13 -16
  97. package/helpers/undoRedo.d.mts +37 -0
  98. package/helpers/undoRedo.d.ts +5 -3
  99. package/helpers/undoRedo.js +59 -94
  100. package/helpers/undoRedo.mjs +59 -94
  101. package/index.d.mts +404 -0
  102. package/index.d.ts +371 -28
  103. package/index.js +2015 -2166
  104. package/index.mjs +2015 -2166
  105. package/package.json +254 -195
  106. package/persist-plugins/async-storage.d.mts +18 -0
  107. package/persist-plugins/async-storage.d.ts +6 -3
  108. package/persist-plugins/async-storage.js +79 -86
  109. package/persist-plugins/async-storage.mjs +79 -86
  110. package/persist-plugins/indexeddb.d.mts +29 -0
  111. package/persist-plugins/indexeddb.d.ts +6 -3
  112. package/persist-plugins/indexeddb.js +331 -352
  113. package/persist-plugins/indexeddb.mjs +331 -352
  114. package/persist-plugins/local-storage.d.mts +23 -0
  115. package/persist-plugins/local-storage.d.ts +8 -5
  116. package/persist-plugins/local-storage.js +74 -76
  117. package/persist-plugins/local-storage.mjs +74 -76
  118. package/persist-plugins/mmkv.d.mts +18 -0
  119. package/persist-plugins/mmkv.d.ts +6 -3
  120. package/persist-plugins/mmkv.js +82 -86
  121. package/persist-plugins/mmkv.mjs +82 -86
  122. package/react-hooks/createObservableHook.d.mts +5 -0
  123. package/react-hooks/createObservableHook.d.ts +4 -1
  124. package/react-hooks/createObservableHook.js +29 -30
  125. package/react-hooks/createObservableHook.mjs +25 -30
  126. package/react-hooks/useHover.d.mts +5 -0
  127. package/react-hooks/useHover.d.ts +5 -3
  128. package/react-hooks/useHover.js +29 -29
  129. package/react-hooks/useHover.mjs +29 -29
  130. package/react-hooks/useMeasure.d.mts +9 -0
  131. package/react-hooks/useMeasure.d.ts +5 -2
  132. package/react-hooks/useMeasure.js +30 -32
  133. package/react-hooks/useMeasure.mjs +30 -32
  134. package/react-hooks/useObservableNextRouter.d.mts +35 -0
  135. package/react-hooks/useObservableNextRouter.d.ts +9 -7
  136. package/react-hooks/useObservableNextRouter.js +64 -77
  137. package/react-hooks/useObservableNextRouter.mjs +60 -77
  138. package/react.d.mts +157 -0
  139. package/react.d.ts +157 -21
  140. package/react.js +458 -749
  141. package/react.mjs +457 -752
  142. package/sync-plugins/crud.d.mts +54 -0
  143. package/sync-plugins/crud.d.ts +12 -10
  144. package/sync-plugins/crud.js +253 -270
  145. package/sync-plugins/crud.mjs +253 -270
  146. package/sync-plugins/fetch.d.mts +21 -0
  147. package/sync-plugins/fetch.d.ts +7 -4
  148. package/sync-plugins/fetch.js +50 -37
  149. package/sync-plugins/fetch.mjs +50 -37
  150. package/sync-plugins/keel.d.mts +108 -0
  151. package/sync-plugins/keel.d.ts +17 -15
  152. package/sync-plugins/keel.js +229 -462
  153. package/sync-plugins/keel.mjs +227 -464
  154. package/sync-plugins/supabase.d.mts +39 -0
  155. package/sync-plugins/supabase.d.ts +16 -14
  156. package/sync-plugins/supabase.js +128 -128
  157. package/sync-plugins/supabase.mjs +128 -128
  158. package/sync-plugins/tanstack-query.d.mts +14 -0
  159. package/sync-plugins/tanstack-query.d.ts +7 -4
  160. package/sync-plugins/tanstack-query.js +51 -57
  161. package/sync-plugins/tanstack-query.mjs +51 -57
  162. package/sync-plugins/tanstack-react-query.d.mts +8 -0
  163. package/sync-plugins/tanstack-react-query.d.ts +6 -1
  164. package/sync-plugins/tanstack-react-query.js +2 -2
  165. package/sync-plugins/tanstack-react-query.mjs +2 -2
  166. package/sync.d.mts +351 -0
  167. package/sync.d.ts +349 -9
  168. package/sync.js +910 -964
  169. package/sync.mjs +920 -974
  170. package/trace.d.mts +9 -0
  171. package/trace.d.ts +9 -4
  172. package/trace.js +72 -62
  173. package/trace.mjs +72 -62
  174. package/types/babel.d.ts +1 -12
  175. package/babel.js.map +0 -1
  176. package/config/enable$GetSet.js.map +0 -1
  177. package/config/enable$GetSet.mjs.map +0 -1
  178. package/config/enableReactComponents.js.map +0 -1
  179. package/config/enableReactComponents.mjs.map +0 -1
  180. package/config/enableReactNativeComponents.js.map +0 -1
  181. package/config/enableReactNativeComponents.mjs.map +0 -1
  182. package/config/enableReactTracking.js.map +0 -1
  183. package/config/enableReactTracking.mjs.map +0 -1
  184. package/config/enableReactUse.js.map +0 -1
  185. package/config/enableReactUse.mjs.map +0 -1
  186. package/config/enable_PeekAssign.js.map +0 -1
  187. package/config/enable_PeekAssign.mjs.map +0 -1
  188. package/helpers/pageHash.js.map +0 -1
  189. package/helpers/pageHash.mjs.map +0 -1
  190. package/helpers/pageHashParams.js.map +0 -1
  191. package/helpers/pageHashParams.mjs.map +0 -1
  192. package/helpers/time.js.map +0 -1
  193. package/helpers/time.mjs.map +0 -1
  194. package/helpers/trackHistory.js.map +0 -1
  195. package/helpers/trackHistory.mjs.map +0 -1
  196. package/helpers/undoRedo.js.map +0 -1
  197. package/helpers/undoRedo.mjs.map +0 -1
  198. package/history.d.ts +0 -1
  199. package/history.js +0 -24
  200. package/history.js.map +0 -1
  201. package/history.mjs +0 -22
  202. package/history.mjs.map +0 -1
  203. package/index.js.map +0 -1
  204. package/index.mjs.map +0 -1
  205. package/persist-plugins/async-storage.js.map +0 -1
  206. package/persist-plugins/async-storage.mjs.map +0 -1
  207. package/persist-plugins/indexeddb.js.map +0 -1
  208. package/persist-plugins/indexeddb.mjs.map +0 -1
  209. package/persist-plugins/local-storage.js.map +0 -1
  210. package/persist-plugins/local-storage.mjs.map +0 -1
  211. package/persist-plugins/mmkv.js.map +0 -1
  212. package/persist-plugins/mmkv.mjs.map +0 -1
  213. package/react-hooks/createObservableHook.js.map +0 -1
  214. package/react-hooks/createObservableHook.mjs.map +0 -1
  215. package/react-hooks/useHover.js.map +0 -1
  216. package/react-hooks/useHover.mjs.map +0 -1
  217. package/react-hooks/useMeasure.js.map +0 -1
  218. package/react-hooks/useMeasure.mjs.map +0 -1
  219. package/react-hooks/useObservableNextRouter.js.map +0 -1
  220. package/react-hooks/useObservableNextRouter.mjs.map +0 -1
  221. package/react.js.map +0 -1
  222. package/react.mjs.map +0 -1
  223. package/src/ObservableObject.ts +0 -1350
  224. package/src/ObservablePrimitive.ts +0 -62
  225. package/src/babel/index.ts +0 -83
  226. package/src/batching.ts +0 -357
  227. package/src/computed.ts +0 -18
  228. package/src/config/enable$GetSet.ts +0 -30
  229. package/src/config/enableReactComponents.ts +0 -26
  230. package/src/config/enableReactNativeComponents.ts +0 -102
  231. package/src/config/enableReactTracking.ts +0 -62
  232. package/src/config/enableReactUse.ts +0 -32
  233. package/src/config/enable_PeekAssign.ts +0 -31
  234. package/src/config.ts +0 -47
  235. package/src/createObservable.ts +0 -47
  236. package/src/event.ts +0 -26
  237. package/src/globals.ts +0 -235
  238. package/src/helpers/pageHash.ts +0 -41
  239. package/src/helpers/pageHashParams.ts +0 -55
  240. package/src/helpers/time.ts +0 -30
  241. package/src/helpers/trackHistory.ts +0 -29
  242. package/src/helpers/undoRedo.ts +0 -111
  243. package/src/helpers.ts +0 -231
  244. package/src/is.ts +0 -63
  245. package/src/linked.ts +0 -17
  246. package/src/observable.ts +0 -32
  247. package/src/observableInterfaces.ts +0 -151
  248. package/src/observableTypes.ts +0 -232
  249. package/src/observe.ts +0 -89
  250. package/src/old-plugins/firebase.ts +0 -1053
  251. package/src/onChange.ts +0 -146
  252. package/src/persist/configureObservablePersistence.ts +0 -7
  253. package/src/persist/fieldTransformer.ts +0 -149
  254. package/src/persist/observablePersistRemoteFunctionsAdapter.ts +0 -39
  255. package/src/persist/persistObservable.ts +0 -1034
  256. package/src/persist-plugins/async-storage.ts +0 -99
  257. package/src/persist-plugins/indexeddb.ts +0 -439
  258. package/src/persist-plugins/local-storage.ts +0 -86
  259. package/src/persist-plugins/mmkv.ts +0 -91
  260. package/src/proxy.ts +0 -28
  261. package/src/react/Computed.tsx +0 -8
  262. package/src/react/For.tsx +0 -116
  263. package/src/react/Memo.tsx +0 -4
  264. package/src/react/Reactive.tsx +0 -53
  265. package/src/react/Show.tsx +0 -33
  266. package/src/react/Switch.tsx +0 -43
  267. package/src/react/react-globals.ts +0 -3
  268. package/src/react/reactInterfaces.ts +0 -32
  269. package/src/react/reactive-observer.tsx +0 -210
  270. package/src/react/useComputed.ts +0 -36
  271. package/src/react/useEffectOnce.ts +0 -41
  272. package/src/react/useIsMounted.ts +0 -16
  273. package/src/react/useMount.ts +0 -15
  274. package/src/react/useObservable.ts +0 -24
  275. package/src/react/useObservableReducer.ts +0 -52
  276. package/src/react/useObservableState.ts +0 -30
  277. package/src/react/useObserve.ts +0 -54
  278. package/src/react/useObserveEffect.ts +0 -40
  279. package/src/react/usePauseProvider.tsx +0 -16
  280. package/src/react/useSelector.ts +0 -167
  281. package/src/react/useUnmount.ts +0 -8
  282. package/src/react/useWhen.ts +0 -9
  283. package/src/react-hooks/createObservableHook.ts +0 -53
  284. package/src/react-hooks/useHover.ts +0 -40
  285. package/src/react-hooks/useMeasure.ts +0 -48
  286. package/src/react-hooks/useObservableNextRouter.ts +0 -137
  287. package/src/retry.ts +0 -71
  288. package/src/setupTracking.ts +0 -26
  289. package/src/sync/activateSyncedNode.ts +0 -128
  290. package/src/sync/configureObservableSync.ts +0 -7
  291. package/src/sync/persistTypes.ts +0 -216
  292. package/src/sync/syncHelpers.ts +0 -180
  293. package/src/sync/syncObservable.ts +0 -1056
  294. package/src/sync/syncObservableAdapter.ts +0 -31
  295. package/src/sync/syncTypes.ts +0 -189
  296. package/src/sync/synced.ts +0 -21
  297. package/src/sync-plugins/crud.ts +0 -412
  298. package/src/sync-plugins/fetch.ts +0 -80
  299. package/src/sync-plugins/keel.ts +0 -495
  300. package/src/sync-plugins/supabase.ts +0 -249
  301. package/src/sync-plugins/tanstack-query.ts +0 -113
  302. package/src/sync-plugins/tanstack-react-query.ts +0 -12
  303. package/src/trace/traceHelpers.ts +0 -11
  304. package/src/trace/useTraceListeners.ts +0 -34
  305. package/src/trace/useTraceUpdates.ts +0 -24
  306. package/src/trace/useVerifyNotTracking.ts +0 -33
  307. package/src/trace/useVerifyOneRender.ts +0 -10
  308. package/src/trackSelector.ts +0 -52
  309. package/src/tracking.ts +0 -43
  310. package/src/types/babel.d.ts +0 -12
  311. package/src/when.ts +0 -75
  312. package/sync-plugins/crud.js.map +0 -1
  313. package/sync-plugins/crud.mjs.map +0 -1
  314. package/sync-plugins/fetch.js.map +0 -1
  315. package/sync-plugins/fetch.mjs.map +0 -1
  316. package/sync-plugins/keel.js.map +0 -1
  317. package/sync-plugins/keel.mjs.map +0 -1
  318. package/sync-plugins/supabase.js.map +0 -1
  319. package/sync-plugins/supabase.mjs.map +0 -1
  320. package/sync-plugins/tanstack-query.js.map +0 -1
  321. package/sync-plugins/tanstack-query.mjs.map +0 -1
  322. package/sync-plugins/tanstack-react-query.js.map +0 -1
  323. package/sync-plugins/tanstack-react-query.mjs.map +0 -1
  324. package/sync.js.map +0 -1
  325. package/sync.mjs.map +0 -1
  326. package/trace.js.map +0 -1
  327. package/trace.mjs.map +0 -1
@@ -1,31 +0,0 @@
1
- import { isPromise } from '@legendapp/state';
2
- import { ObservableSyncGetParams, SyncedOptions, type ObservableSyncClass } from '@legendapp/state/sync';
3
-
4
- export function syncObservableAdapter<T = {}>({ get, set }: SyncedOptions<T>): ObservableSyncClass {
5
- const ret: ObservableSyncClass = {};
6
-
7
- if (get) {
8
- ret.get = (async (params: ObservableSyncGetParams<T>) => {
9
- try {
10
- let value = get(params as any);
11
- if (isPromise(value)) {
12
- value = await value;
13
- }
14
-
15
- params.onChange({
16
- value,
17
- lastSync: params.lastSync,
18
- mode: params.mode!,
19
- });
20
- params.onGet();
21
- // eslint-disable-next-line no-empty
22
- } catch {}
23
- }) as ObservableSyncClass['get'];
24
- }
25
-
26
- if (set) {
27
- ret.set = set as unknown as ObservableSyncClass['set'];
28
- }
29
-
30
- return ret;
31
- }
@@ -1,189 +0,0 @@
1
- /* eslint-disable @typescript-eslint/ban-ts-comment */
2
- // @ts-ignore
3
- import type { MMKVConfiguration } from 'react-native-mmkv';
4
- // @ts-ignore
5
- import type { AsyncStorageStatic } from '@react-native-async-storage/async-storage';
6
-
7
- import {
8
- Change,
9
- ClassConstructor,
10
- GetMode,
11
- LinkedOptions,
12
- NodeValue,
13
- SetParams,
14
- UpdateFn,
15
- UpdateFnParams,
16
- } from '../observableInterfaces';
17
- import { Observable, ObservableParam, ObservableState } from '../observableTypes';
18
-
19
- export interface PersistOptions<T = any> {
20
- name: string;
21
- plugin?: ClassConstructor<ObservablePersistPlugin, T[]>;
22
- retrySync?: boolean;
23
- transform?: SyncTransform<T>;
24
- readonly?: boolean;
25
- mmkv?: MMKVConfiguration;
26
- indexedDB?: {
27
- prefixID?: string;
28
- itemID?: string;
29
- };
30
- options?: any;
31
- }
32
-
33
- export interface SyncedGetParams {
34
- value: any;
35
- lastSync: number | undefined;
36
- updateLastSync: (lastSync: number) => void;
37
- mode: GetMode;
38
- refresh: () => void;
39
- }
40
-
41
- export interface SyncedSetParams<T> extends SetParams<T> {
42
- node: NodeValue;
43
- valuePrevious: T;
44
- update: UpdateFn;
45
- refresh: () => void;
46
- cancelRetry: () => void;
47
- retryNum: number;
48
- fromSubscribe: boolean | undefined;
49
- }
50
-
51
- export interface SyncedSubscribeParams<T = any> {
52
- node: NodeValue;
53
- value$: ObservableParam<T>;
54
- update: UpdateFn;
55
- refresh: () => void;
56
- }
57
-
58
- export interface SyncedOptions<TRemote = any, TLocal = TRemote> extends Omit<LinkedOptions<TRemote>, 'get' | 'set'> {
59
- get?: (params: SyncedGetParams) => Promise<TRemote> | TRemote;
60
- set?: (params: SyncedSetParams<TRemote>) => void | Promise<any>;
61
- subscribe?: (params: SyncedSubscribeParams<TRemote>) => (() => void) | void;
62
- retry?: RetryOptions;
63
- persist?: PersistOptions<any>;
64
- debounceSet?: number;
65
- syncMode?: 'auto' | 'manual';
66
- mode?: GetMode;
67
- transform?: SyncTransform<TLocal, TRemote>;
68
- // Not implemented yet
69
- enableSync?: boolean;
70
- onGetError?: (error: Error) => void;
71
- onSetError?: (error: Error) => void;
72
- log?: (message?: any, ...optionalParams: any[]) => void;
73
- onBeforeSet?: () => void;
74
- onAfterSet?: () => void;
75
- allowSetIfGetError?: boolean;
76
- }
77
-
78
- export interface SyncedOptionsGlobal<T = any>
79
- extends Omit<
80
- SyncedOptions<T>,
81
- 'get' | 'set' | 'persist' | 'initial' | 'waitForSet' | 'waitFor' | 'transform' | 'subscribe'
82
- > {
83
- persist?: ObservablePersistPluginOptions & Omit<PersistOptions, 'name' | 'transform' | 'options'>;
84
- }
85
-
86
- export interface ObservablePersistPluginOptions {
87
- onGetError?: (error: Error) => void;
88
- onSetError?: (error: Error) => void;
89
- indexedDB?: {
90
- databaseName: string;
91
- version: number;
92
- tableNames: string[];
93
- };
94
- asyncStorage?: {
95
- AsyncStorage: AsyncStorageStatic;
96
- preload?: boolean | string[];
97
- };
98
- }
99
- export interface ObservablePersistPlugin {
100
- initialize?(config: ObservablePersistPluginOptions): void | Promise<void>;
101
- loadTable?(table: string, config: PersistOptions): Promise<any> | void;
102
- getTable<T = any>(table: string, init: object, config: PersistOptions): T;
103
- set(table: string, changes: Change[], config: PersistOptions): Promise<any> | void;
104
- deleteTable(table: string, config: PersistOptions): Promise<any> | void;
105
- getMetadata(table: string, config: PersistOptions): PersistMetadata;
106
- setMetadata(table: string, metadata: PersistMetadata, config: PersistOptions): Promise<any> | void;
107
- deleteMetadata(table: string, config: PersistOptions): Promise<any> | void;
108
- }
109
- export interface PersistMetadata {
110
- id?: '__legend_metadata';
111
- // modified ?: number;
112
- lastSync?: number;
113
- pending?: any;
114
- }
115
- export type SyncTransformMethod = 'get' | 'set';
116
- export interface SyncTransform<TLocal = any, TSaved = TLocal> {
117
- load?: (value: TSaved, method: SyncTransformMethod) => TLocal | Promise<TLocal>;
118
- save?: (value: TLocal) => TSaved | Promise<TSaved>;
119
- }
120
- export interface ObservableSyncStateBase {
121
- isPersistLoaded: boolean;
122
- isPersistEnabled: boolean;
123
- isSyncEnabled: boolean;
124
- lastSync?: number;
125
- syncCount?: number;
126
- clearPersist: () => Promise<void>;
127
- sync: () => Promise<void>;
128
- getPendingChanges: () =>
129
- | Record<
130
- string,
131
- {
132
- p: any;
133
- v?: any;
134
- }
135
- >
136
- | undefined;
137
- }
138
- export type ObservableSyncState = ObservableState & ObservableSyncStateBase;
139
-
140
- export interface ObservableSyncSetParams<T> {
141
- syncState: Observable<ObservableSyncState>;
142
- value$: ObservableParam<T>;
143
- options: SyncedOptions<T>;
144
- changes: Change[];
145
- value: T;
146
- valuePrevious: T;
147
- }
148
- export interface ObservableSyncGetParams<T> {
149
- state: Observable<ObservableSyncState>;
150
- value$: ObservableParam<T>;
151
- options: SyncedOptions<T>;
152
- dateModified?: number;
153
- lastSync?: number;
154
- mode?: GetMode;
155
- onGet: () => void;
156
- onError: (error: Error) => void;
157
- onChange: (params: UpdateFnParams) => void | Promise<void>;
158
- }
159
- export type ObservableSyncRemoteGetFnParams<T> = Omit<ObservableSyncGetParams<T>, 'onGet'>;
160
-
161
- export interface ObservableSyncClass {
162
- get?<T>(params: ObservableSyncGetParams<T>): void;
163
- set?<T>(
164
- params: ObservableSyncSetParams<T>,
165
- ): void | Promise<void | { changes?: object; dateModified?: number; lastSync?: number; pathStrs?: string[] }>;
166
- }
167
-
168
- export interface ObservableSyncFunctions<T = any> {
169
- get?(params: ObservableSyncRemoteGetFnParams<T>): T | Promise<T>;
170
- set?(
171
- params: ObservableSyncSetParams<T>,
172
- ): void | Promise<void | { changes?: object | undefined; dateModified?: number; lastSync?: number }>;
173
- }
174
-
175
- export interface RetryOptions {
176
- infinite?: boolean;
177
- times?: number;
178
- delay?: number;
179
- backoff?: 'constant' | 'exponential';
180
- maxDelay?: number;
181
- }
182
-
183
- export interface SubscribeOptions {
184
- node: NodeValue;
185
- update: UpdateFn;
186
- refresh: () => void;
187
- }
188
-
189
- export type Synced<T> = T;
@@ -1,21 +0,0 @@
1
- import { isFunction, linked } from '@legendapp/state';
2
- import { enableActivateSyncedNode } from './activateSyncedNode';
3
- import type { Synced, SyncedOptions } from './syncTypes';
4
-
5
- export function synced<TRemote, TLocal = TRemote>(
6
- params: SyncedOptions<TRemote, TLocal> | (() => TRemote),
7
- ): Synced<TLocal> {
8
- installPersistActivateNode();
9
- if (isFunction(params)) {
10
- params = { get: params };
11
- }
12
- return linked({ ...params, synced: true } as any);
13
- }
14
-
15
- let didInstall = false;
16
- function installPersistActivateNode() {
17
- if (!didInstall) {
18
- enableActivateSyncedNode();
19
- didInstall = true;
20
- }
21
- }
@@ -1,412 +0,0 @@
1
- import { getNodeValue, internal, isNullOrUndefined } from '@legendapp/state';
2
- import { SyncedGetParams, SyncedOptions, SyncedSetParams, deepEqual, diffObjects, synced } from '@legendapp/state/sync';
3
-
4
- const { clone } = internal;
5
-
6
- export type CrudAsOption = 'Map' | 'object' | 'value' | 'array';
7
-
8
- export type CrudResult<T> = T;
9
-
10
- export interface SyncedCrudPropsSingle<TRemote, TLocal> {
11
- get?: (params: SyncedGetParams) => Promise<CrudResult<TRemote | null>> | CrudResult<TRemote | null>;
12
- initial?: InitialValue<TLocal, 'value'>;
13
- as?: never | 'value';
14
- }
15
- export interface SyncedCrudPropsMany<TRemote, TLocal, TAsOption extends CrudAsOption> {
16
- list?: (params: SyncedGetParams) => Promise<CrudResult<TRemote[] | null>> | CrudResult<TRemote[] | null>;
17
- as?: TAsOption;
18
- initial?: InitialValue<TLocal, TAsOption>;
19
- }
20
- export interface SyncedCrudOnSavedParams<TRemote extends { id: string | number }, TLocal> {
21
- saved: TLocal;
22
- input: TRemote;
23
- currentValue: TLocal;
24
- isCreate: boolean;
25
- props: SyncedCrudPropsBase<TRemote, TLocal>;
26
- }
27
- export interface SyncedCrudPropsBase<TRemote extends { id: string | number }, TLocal = TRemote>
28
- extends Omit<SyncedOptions<TRemote, TLocal>, 'get' | 'set' | 'initial'> {
29
- create?(input: TRemote, params: SyncedSetParams<TRemote>): Promise<CrudResult<TRemote> | null | undefined>;
30
- update?(
31
- input: Partial<TRemote>,
32
- params: SyncedSetParams<TRemote>,
33
- ): Promise<CrudResult<Partial<TRemote> | null | undefined>>;
34
- delete?(input: { id: TRemote['id'] }, params: SyncedSetParams<TRemote>): Promise<CrudResult<any>>;
35
- onSaved?(params: SyncedCrudOnSavedParams<TRemote, TLocal>): Partial<TLocal> | void;
36
- onSavedUpdate?: 'createdUpdatedAt';
37
- fieldUpdatedAt?: string;
38
- fieldCreatedAt?: string;
39
- fieldDeleted?: string;
40
- updatePartial?: boolean;
41
- changesSince?: 'all' | 'last-sync';
42
- generateId?: () => string | number;
43
- }
44
-
45
- type InitialValue<TLocal, TAsOption extends CrudAsOption> = TAsOption extends 'Map'
46
- ? Map<string | number, TLocal>
47
- : TAsOption extends 'object'
48
- ? Record<string | number, TLocal>
49
- : TAsOption extends 'value'
50
- ? TLocal
51
- : TLocal[];
52
-
53
- export type SyncedCrudReturnType<TLocal, TAsOption extends CrudAsOption> = TAsOption extends 'Map'
54
- ? Map<TLocal extends { id: number } ? number : string, TLocal>
55
- : TAsOption extends 'object'
56
- ? Record<TLocal extends { id: number } ? number : string, TLocal>
57
- : TAsOption extends 'value'
58
- ? TLocal
59
- : TLocal[];
60
-
61
- let _asOption: CrudAsOption;
62
-
63
- function transformOut<T1, T2>(data: T1, transform: undefined | ((value: T1) => T2)) {
64
- return transform ? transform(clone(data)) : data;
65
- }
66
-
67
- function ensureId(obj: { id: string | number }, generateId: () => string | number) {
68
- if (!obj.id) {
69
- obj.id = generateId();
70
- }
71
- return obj.id;
72
- }
73
-
74
- function onSavedCreatedUpdatedAt<TRemote extends { id: string | number }, TLocal>(
75
- mode: SyncedCrudPropsBase<TRemote>['onSavedUpdate'],
76
- { saved, currentValue, isCreate, props }: SyncedCrudOnSavedParams<TRemote, TLocal>,
77
- ): Partial<TLocal> {
78
- const savedOut: Partial<TLocal> = {};
79
-
80
- if (isCreate) {
81
- // Update with any fields that are currently undefined
82
- Object.keys(saved!).forEach((key) => {
83
- if (isNullOrUndefined(currentValue[key as keyof TLocal])) {
84
- savedOut[key as keyof TLocal] = saved[key as keyof TLocal];
85
- }
86
- });
87
- } else if (mode === 'createdUpdatedAt') {
88
- // Update with any fields ending in createdAt or updatedAt
89
- Object.keys(saved!).forEach((key) => {
90
- const k = key as keyof TLocal;
91
- const keyLower = key.toLowerCase();
92
- if (
93
- (key === props.fieldCreatedAt ||
94
- key === props.fieldUpdatedAt ||
95
- keyLower.endsWith('createdat') ||
96
- keyLower.endsWith('updatedat') ||
97
- keyLower.endsWith('created_at') ||
98
- keyLower.endsWith('updated_at')) &&
99
- saved[k] instanceof Date
100
- ) {
101
- savedOut[k] = saved[k];
102
- }
103
- });
104
- }
105
-
106
- return savedOut;
107
- }
108
-
109
- export function syncedCrud<TRemote extends { id: string | number }, TLocal = TRemote>(
110
- props: SyncedCrudPropsBase<TRemote, TLocal> & SyncedCrudPropsSingle<TRemote, TLocal>,
111
- ): SyncedCrudReturnType<TLocal, 'value'>;
112
- export function syncedCrud<
113
- TRemote extends { id: string | number },
114
- TLocal = TRemote,
115
- TAsOption extends CrudAsOption = 'object',
116
- >(
117
- props: SyncedCrudPropsBase<TRemote, TLocal> & SyncedCrudPropsMany<TRemote, TLocal, TAsOption>,
118
- ): SyncedCrudReturnType<TLocal, Exclude<TAsOption, 'value'>>;
119
- export function syncedCrud<
120
- TRemote extends { id: string | number },
121
- TLocal = TRemote,
122
- TAsOption extends CrudAsOption = 'object',
123
- >(
124
- props: SyncedCrudPropsBase<TRemote, TLocal> &
125
- (SyncedCrudPropsSingle<TRemote, TLocal> & SyncedCrudPropsMany<TRemote, TLocal, TAsOption>),
126
- ): SyncedCrudReturnType<TLocal, TAsOption> {
127
- const {
128
- get: getFn,
129
- list: listFn,
130
- create: createFn,
131
- update: updateFn,
132
- delete: deleteFn,
133
- transform,
134
- fieldCreatedAt,
135
- fieldUpdatedAt,
136
- fieldDeleted,
137
- updatePartial,
138
- onSaved,
139
- onSavedUpdate,
140
- mode: modeParam,
141
- changesSince,
142
- generateId,
143
- ...rest
144
- } = props;
145
-
146
- let asType = props.as as TAsOption;
147
-
148
- if (!asType) {
149
- asType = (getFn ? 'value' : _asOption || 'object') as CrudAsOption as TAsOption;
150
- }
151
-
152
- const asMap = asType === 'Map';
153
- const asArray = asType === 'array';
154
-
155
- const get: undefined | ((params: SyncedGetParams) => Promise<TLocal>) =
156
- getFn || listFn
157
- ? async (getParams: SyncedGetParams) => {
158
- const { updateLastSync, lastSync, value } = getParams;
159
- if (listFn) {
160
- const isLastSyncMode = changesSince === 'last-sync';
161
- if (isLastSyncMode && lastSync) {
162
- getParams.mode =
163
- modeParam || (asType === 'array' ? 'append' : asType === 'value' ? 'set' : 'assign');
164
- }
165
-
166
- const data = (await listFn(getParams)) || [];
167
- let newLastSync = 0;
168
- for (let i = 0; i < data.length; i++) {
169
- const updated =
170
- (data[i] as any)[fieldUpdatedAt as any] || (data[i] as any)[fieldCreatedAt as any];
171
- if (updated) {
172
- newLastSync = Math.max(newLastSync, +new Date(updated));
173
- }
174
- }
175
- if (newLastSync && newLastSync !== lastSync) {
176
- updateLastSync(newLastSync);
177
- }
178
- let transformed = data as unknown as TLocal[];
179
- if (transform?.load) {
180
- transformed = await Promise.all(data.map((value) => transform.load!(value, 'get')));
181
- }
182
- if (asType === 'value') {
183
- return transformed.length > 0
184
- ? transformed[0]
185
- : (isLastSyncMode && lastSync && value) || null;
186
- } else {
187
- const results = transformed.map((result: any) =>
188
- result[fieldDeleted as any] || result.__deleted ? internal.symbolDelete : result,
189
- );
190
- const out = asType === 'array' ? [] : asMap ? new Map() : {};
191
- for (let i = 0; i < results.length; i++) {
192
- let result = results[i];
193
- result = result[fieldDeleted as any] || result.__deleted ? internal.symbolDelete : result;
194
- if (asArray) {
195
- (out as any[]).push(result);
196
- } else if (asMap) {
197
- (out as Map<string, any>).set(result.id, result);
198
- } else {
199
- (out as Record<string, any>)[result.id] = result;
200
- }
201
- }
202
- return out;
203
- }
204
- } else if (getFn) {
205
- const data = await getFn(getParams);
206
-
207
- let transformed = data as unknown as TLocal;
208
- if (data) {
209
- const newLastSync =
210
- (data as any)[fieldUpdatedAt as any] || (data as any)[fieldCreatedAt as any];
211
- if (newLastSync && newLastSync !== lastSync) {
212
- updateLastSync(newLastSync);
213
- }
214
- if (transform?.load) {
215
- transformed = await transform.load(data, 'get');
216
- }
217
- }
218
-
219
- return transformed as any;
220
- }
221
- }
222
- : undefined;
223
-
224
- const set =
225
- createFn || updateFn || deleteFn
226
- ? async (params: SyncedSetParams<any> & { retryAsCreate?: boolean }) => {
227
- const { value, changes, update, retryAsCreate, valuePrevious, node } = params;
228
- const creates = new Map<string, TLocal>();
229
- const updates = new Map<string, object>();
230
- const deletes = new Set<string>();
231
-
232
- changes.forEach(({ path, prevAtPath, valueAtPath }) => {
233
- if (asType === 'value') {
234
- if (value) {
235
- let id = value?.id;
236
- const isCreate = fieldCreatedAt ? !value[fieldCreatedAt!] : !prevAtPath;
237
- if (!id && generateId) {
238
- id = ensureId(value, generateId);
239
- }
240
- if (id) {
241
- if (isCreate || retryAsCreate) {
242
- creates.set(id, value);
243
- } else if (path.length === 0) {
244
- if (valueAtPath) {
245
- updates.set(id, valueAtPath);
246
- } else if (prevAtPath) {
247
- deletes.add(prevAtPath?.id);
248
- }
249
- } else {
250
- updates.set(id, Object.assign(updates.get(id) || { id }, value));
251
- }
252
- } else {
253
- console.error('[legend-state]: added synced item without an id');
254
- }
255
- } else if (path.length === 0) {
256
- const id = prevAtPath?.id;
257
- if (id) {
258
- deletes.add(id);
259
- }
260
- }
261
- } else {
262
- let itemsChanged: [string, any][] | undefined = undefined;
263
- if (path.length === 0) {
264
- // Do a deep equal of each element vs its previous element to see which have changed
265
- itemsChanged = (
266
- asMap
267
- ? Array.from((valueAtPath as Map<any, any>).entries())
268
- : Object.entries(valueAtPath)
269
- ).filter(([key, value]) => {
270
- const prev = asMap ? prevAtPath.get(key) : prevAtPath[key];
271
- const isDiff = !prevAtPath || !deepEqual(value, prev);
272
-
273
- return isDiff;
274
- });
275
- } else {
276
- const itemKey = path[0];
277
- const itemValue = asMap ? value.get(itemKey) : value[itemKey];
278
- if (!itemValue) {
279
- if (path.length === 1 && prevAtPath) {
280
- deletes.add(itemKey);
281
- }
282
- } else {
283
- itemsChanged = [[itemKey, itemValue]];
284
- }
285
- }
286
- itemsChanged?.forEach(([itemKey, item]) => {
287
- if (isNullOrUndefined(item)) {
288
- deletes.add(itemKey);
289
- } else {
290
- const prev = asMap ? valuePrevious.get(itemKey) : valuePrevious[itemKey];
291
-
292
- const isCreate = fieldCreatedAt
293
- ? !item[fieldCreatedAt!]
294
- : fieldUpdatedAt
295
- ? !item[fieldUpdatedAt]
296
- : isNullOrUndefined(prev);
297
- if (isCreate) {
298
- if (generateId) {
299
- ensureId(item, generateId);
300
- }
301
- if (!item.id) {
302
- console.error('[legend-state]: added item without an id');
303
- }
304
- if (createFn) {
305
- creates.set(item.id, item);
306
- } else {
307
- console.log('[legend-state] missing create function');
308
- }
309
- } else {
310
- if (updateFn) {
311
- updates.set(item.id, item);
312
- } else {
313
- console.log('[legend-state] missing update function');
314
- }
315
- }
316
- }
317
- });
318
- }
319
- });
320
-
321
- const saveResult = async (
322
- itemKey: string,
323
- input: TRemote,
324
- data: CrudResult<TRemote>,
325
- isCreate: boolean,
326
- ) => {
327
- if (data && (onSaved || onSavedUpdate)) {
328
- const saved: TLocal = (transform?.load ? transform.load(data as any, 'set') : data) as any;
329
-
330
- const isChild = itemKey !== 'undefined' && asType !== 'value';
331
- const currentPeeked = getNodeValue(node);
332
-
333
- const currentValue = isChild ? currentPeeked?.[itemKey] : currentPeeked;
334
-
335
- const dataOnSaved: SyncedCrudOnSavedParams<TRemote, TLocal> = {
336
- saved,
337
- input,
338
- currentValue,
339
- isCreate,
340
- props,
341
- };
342
- let savedOut: Partial<TLocal> | undefined = undefined;
343
-
344
- if (onSavedUpdate) {
345
- savedOut = onSavedCreatedUpdatedAt(onSavedUpdate, dataOnSaved);
346
- }
347
-
348
- if (onSaved) {
349
- const ret = onSaved(dataOnSaved);
350
- if (ret) {
351
- savedOut = ret;
352
- }
353
- }
354
-
355
- if (savedOut) {
356
- const createdAt = fieldCreatedAt ? savedOut[fieldCreatedAt as keyof TLocal] : undefined;
357
- const updatedAt = fieldUpdatedAt ? savedOut[fieldUpdatedAt as keyof TLocal] : undefined;
358
-
359
- const value =
360
- itemKey !== 'undefined' && asType !== 'value' ? { [itemKey]: savedOut } : savedOut;
361
- update({
362
- value,
363
- lastSync:
364
- updatedAt || createdAt ? +new Date(updatedAt || (createdAt as any)) : undefined,
365
- mode: 'merge',
366
- });
367
- }
368
- }
369
- };
370
-
371
- return Promise.all([
372
- ...Array.from(creates).map(([itemKey, itemValue]) => {
373
- const createObj = transformOut(itemValue, transform?.save) as TRemote;
374
- return createFn!(createObj, params).then((result) =>
375
- saveResult(itemKey, createObj, result as any, true),
376
- );
377
- }),
378
- ...Array.from(updates).map(([itemKey, itemValue]) => {
379
- const toSave = updatePartial
380
- ? Object.assign(
381
- diffObjects(asType === 'value' ? valuePrevious : valuePrevious[itemKey], itemValue),
382
- { id: (itemValue as any).id },
383
- )
384
- : itemValue;
385
- const changed = transformOut(toSave as TLocal, transform?.save) as TRemote;
386
-
387
- if (Object.keys(changed).length > 0) {
388
- return updateFn!(changed, params).then(
389
- (result) => result && saveResult(itemKey, changed, result as any, false),
390
- );
391
- }
392
- }),
393
- ...Array.from(deletes).map((id) => {
394
- if (deleteFn) {
395
- deleteFn({ id }, params);
396
- } else if (fieldDeleted && updateFn) {
397
- updateFn({ id, [fieldDeleted]: true } as any, params);
398
- } else {
399
- console.log('[legend-state] missing delete function');
400
- }
401
- }),
402
- ]);
403
- }
404
- : undefined;
405
-
406
- return synced<any>({
407
- set,
408
- get,
409
- mode: modeParam,
410
- ...rest,
411
- });
412
- }