@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,80 +0,0 @@
1
- import { Selector, computeSelector, getNodeValue } from '@legendapp/state';
2
- import { Synced, SyncedOptions, SyncedSetParams, synced } from '@legendapp/state/sync';
3
-
4
- export interface SyncedFetchOnSavedParams<TRemote, TLocal = TRemote> {
5
- saved: TLocal;
6
- input: TRemote;
7
- currentValue: TLocal;
8
- props: SyncedFetchProps<TRemote, TLocal>;
9
- }
10
-
11
- export interface SyncedFetchProps<TRemote, TLocal = TRemote>
12
- extends Omit<SyncedOptions<TRemote, TLocal>, 'get' | 'set'> {
13
- get: Selector<string>;
14
- set?: Selector<string>;
15
- getInit?: RequestInit;
16
- setInit?: RequestInit;
17
- valueType?: 'arrayBuffer' | 'blob' | 'formData' | 'json' | 'text';
18
- onSavedValueType?: 'arrayBuffer' | 'blob' | 'formData' | 'json' | 'text';
19
- onSaved?: (params: SyncedFetchOnSavedParams<TRemote, TLocal>) => Partial<TLocal> | void;
20
- }
21
-
22
- export function syncedFetch<TRemote, TLocal = TRemote>(props: SyncedFetchProps<TRemote, TLocal>): Synced<TLocal> {
23
- const {
24
- get: getParam,
25
- set: setParam,
26
- getInit,
27
- setInit,
28
- valueType,
29
- onSaved,
30
- onSavedValueType,
31
- transform,
32
- ...rest
33
- } = props;
34
- const get = async () => {
35
- const url = computeSelector(getParam);
36
- const response = await fetch(url, getInit);
37
-
38
- if (!response.ok) {
39
- throw new Error(response.statusText);
40
- }
41
-
42
- let value = await response[valueType || 'json']();
43
-
44
- if (transform?.load) {
45
- value = transform?.load(value, 'get');
46
- }
47
-
48
- return value;
49
- };
50
-
51
- let set: ((params: SyncedSetParams<TRemote>) => void | Promise<any>) | undefined = undefined;
52
- if (setParam) {
53
- set = async ({ value, node, update }: SyncedSetParams<any>) => {
54
- const url = computeSelector(setParam);
55
-
56
- const response = await fetch(
57
- url,
58
- Object.assign({ method: 'POST' }, setInit, { body: JSON.stringify(value) }),
59
- );
60
- if (!response.ok) {
61
- throw new Error(response.statusText);
62
- }
63
- if (onSaved) {
64
- const responseValue = await response[onSavedValueType || valueType || 'json']();
65
- const transformed = transform?.load ? await transform.load(responseValue, 'set') : responseValue;
66
- const currentValue = getNodeValue(node);
67
- const valueSave = onSaved({ input: value, saved: transformed, currentValue, props });
68
- update({
69
- value: valueSave,
70
- });
71
- }
72
- };
73
- }
74
-
75
- return synced({
76
- ...rest,
77
- get,
78
- set,
79
- });
80
- }
@@ -1,495 +0,0 @@
1
- import ksuid from 'ksuid';
2
- import { computeSelector, internal, isEmpty, isFunction, observable, when } from '@legendapp/state';
3
- import {
4
- SyncedOptions,
5
- removeNullUndefined,
6
- type SyncedGetParams,
7
- type SyncedSetParams,
8
- type SyncedSubscribeParams,
9
- } from '@legendapp/state/sync';
10
- import {
11
- CrudAsOption,
12
- CrudResult,
13
- SyncedCrudOnSavedParams,
14
- SyncedCrudPropsBase,
15
- SyncedCrudPropsMany,
16
- SyncedCrudPropsSingle,
17
- SyncedCrudReturnType,
18
- syncedCrud,
19
- } from '@legendapp/state/sync-plugins/crud';
20
- const { clone } = internal;
21
-
22
- // Keel types
23
- export interface KeelObjectBase {
24
- id: string;
25
- createdAt: Date;
26
- updatedAt: Date;
27
- }
28
- export type KeelKey = 'createdAt' | 'updatedAt';
29
- export const KeelKeys: KeelKey[] = ['createdAt', 'updatedAt'];
30
- export type OmitKeelBuiltins<T, T2 extends string = ''> = Omit<T, KeelKey | T2>;
31
- type APIError = { type: string; message: string; requestId?: string };
32
-
33
- type APIResult<T> = Result<T, APIError>;
34
-
35
- type Data<T> = {
36
- data: T;
37
- error?: never;
38
- };
39
-
40
- type Err<U> = {
41
- data?: never;
42
- error: U;
43
- };
44
-
45
- type Result<T, U> = NonNullable<Data<T> | Err<U>>;
46
-
47
- // Keel plugin types
48
-
49
- type SubscribeFn = (params: { refresh: () => void }) => () => void;
50
-
51
- export function generateKeelId() {
52
- return ksuid.randomSync().string;
53
- }
54
-
55
- export interface KeelGetParams {}
56
-
57
- export interface KeelListParams<Where = {}> {
58
- where: { updatedAt?: { after: Date } } & Where;
59
- after?: string;
60
- first?: number;
61
- last?: number;
62
- before?: string;
63
- }
64
-
65
- export interface KeelRealtimePlugin {
66
- subscribe: (realtimeKey: string, refresh: () => void) => void;
67
- setLatestChange: (realtimeKey: string, time: Date) => void;
68
- }
69
-
70
- export interface SyncedKeelConfiguration
71
- extends Omit<
72
- SyncedCrudPropsBase<any>,
73
- | keyof SyncedOptions
74
- | 'create'
75
- | 'update'
76
- | 'delete'
77
- | 'onSaved'
78
- | 'updatePartial'
79
- | 'fieldCreatedAt'
80
- | 'fieldUpdatedAt'
81
- | 'generateId'
82
- > {
83
- client: {
84
- auth: { refresh: () => Promise<boolean>; isAuthenticated: () => Promise<boolean> };
85
- api: { queries: Record<string, (i: any) => Promise<any>> };
86
- };
87
- realtimePlugin?: KeelRealtimePlugin;
88
- as?: Exclude<CrudAsOption, 'value'>;
89
- enabled?: boolean;
90
- onError?: (params: APIResult<any>['error']) => void;
91
- }
92
-
93
- interface PageInfo {
94
- count: number;
95
- endCursor: string;
96
- hasNextPage: boolean;
97
- startCursor: string;
98
- totalCount: number;
99
- }
100
-
101
- interface SyncedKeelPropsManyBase<TRemote, TLocal, AOption extends CrudAsOption>
102
- extends Omit<SyncedCrudPropsMany<TRemote, TLocal, AOption>, 'list'> {
103
- first?: number;
104
- get?: never;
105
- }
106
- interface SyncedKeelPropsManyWhere<TRemote, TLocal, AOption extends CrudAsOption, Where extends Record<string, any>>
107
- extends SyncedKeelPropsManyBase<TRemote, TLocal, AOption> {
108
- list?: (params: KeelListParams<NoInfer<Where>>) => Promise<
109
- CrudResult<
110
- APIResult<{
111
- results: TRemote[];
112
- pageInfo: any;
113
- }>
114
- >
115
- >;
116
- where?: Where | (() => Where);
117
- }
118
- interface SyncedKeelPropsManyNoWhere<TRemote, TLocal, AOption extends CrudAsOption>
119
- extends SyncedKeelPropsManyBase<TRemote, TLocal, AOption> {
120
- list?: (params: KeelListParams<{}>) => Promise<
121
- CrudResult<
122
- APIResult<{
123
- results: TRemote[];
124
- pageInfo: any;
125
- }>
126
- >
127
- >;
128
- where?: never | {};
129
- }
130
- type HasAnyKeys<T> = keyof T extends never ? false : true;
131
-
132
- type SyncedKeelPropsMany<
133
- TRemote,
134
- TLocal,
135
- AOption extends CrudAsOption,
136
- Where extends Record<string, any>,
137
- > = HasAnyKeys<Where> extends true
138
- ? SyncedKeelPropsManyWhere<TRemote, TLocal, AOption, Where>
139
- : SyncedKeelPropsManyNoWhere<TRemote, TLocal, AOption>;
140
-
141
- interface SyncedKeelPropsSingle<TRemote, TLocal> extends Omit<SyncedCrudPropsSingle<TRemote, TLocal>, 'get'> {
142
- get?: (params: KeelGetParams) => Promise<APIResult<TRemote>>;
143
-
144
- first?: never;
145
- where?: never;
146
- list?: never;
147
- as?: never;
148
- }
149
-
150
- interface SyncedKeelPropsBase<TRemote extends { id: string }, TLocal = TRemote>
151
- extends Omit<
152
- SyncedCrudPropsBase<TRemote, TLocal>,
153
- 'create' | 'update' | 'delete' | 'updatePartial' | 'fieldUpdatedAt' | 'fieldCreatedAt'
154
- > {
155
- create?: (i: NoInfer<Partial<TRemote>>) => Promise<APIResult<NoInfer<TRemote>>>;
156
- update?: (params: { where: any; values?: Partial<TRemote> }) => Promise<APIResult<TRemote>>;
157
- delete?: (params: { id: string }) => Promise<APIResult<string>>;
158
- }
159
-
160
- const keelConfig: SyncedKeelConfiguration = {} as SyncedKeelConfiguration;
161
- const modifiedClients = new WeakSet<Record<string, any>>();
162
- const isEnabled$ = observable(true);
163
-
164
- async function ensureAuthToken() {
165
- await when(isEnabled$.get());
166
- let isAuthed = await keelConfig.client.auth.isAuthenticated();
167
- if (!isAuthed) {
168
- isAuthed = await keelConfig.client.auth.refresh();
169
- }
170
-
171
- return isAuthed;
172
- }
173
-
174
- async function handleApiError(error: APIError, retry?: () => any) {
175
- if (error.type === 'unauthorized' || error.type === 'forbidden') {
176
- console.warn('Keel token expired, refreshing...');
177
- await ensureAuthToken();
178
- // Retry
179
- retry?.();
180
- }
181
- }
182
-
183
- function convertObjectToCreate<TRemote>(item: TRemote): TRemote {
184
- const cloned = clone(item);
185
- Object.keys(cloned).forEach((key) => {
186
- if (key.endsWith('Id')) {
187
- if (cloned[key]) {
188
- cloned[key.slice(0, -2)] = { id: cloned[key] };
189
- }
190
- delete cloned[key];
191
- }
192
- });
193
- delete cloned.createdAt;
194
- delete cloned.updatedAt;
195
- return cloned as unknown as TRemote;
196
- }
197
-
198
- export function getSyncedKeelConfiguration() {
199
- return keelConfig;
200
- }
201
- export function configureSyncedKeel(config: SyncedKeelConfiguration) {
202
- const { enabled, realtimePlugin, client, ...rest } = config;
203
- Object.assign(keelConfig, removeNullUndefined(rest));
204
-
205
- if (enabled !== undefined) {
206
- isEnabled$.set(enabled);
207
- }
208
-
209
- if (realtimePlugin) {
210
- keelConfig.realtimePlugin = realtimePlugin;
211
- if (client && !modifiedClients.has(client)) {
212
- modifiedClients.add(client);
213
- const queries = client.api.queries;
214
- Object.keys(queries).forEach((key) => {
215
- if (key.startsWith('list')) {
216
- const oldFn = queries[key];
217
- queries[key] = (i) => {
218
- const realtimeKey = [key, ...Object.values(i.where || {})]
219
- .filter((value) => value && typeof value !== 'object')
220
- .join('/');
221
-
222
- const subscribe = ({ refresh }: SyncedSubscribeParams) => {
223
- if (realtimeKey) {
224
- return realtimePlugin.subscribe(realtimeKey, refresh);
225
- }
226
- };
227
- return oldFn(i).then((ret) => {
228
- if (subscribe) {
229
- ret.subscribe = subscribe;
230
- ret.subscribeKey = realtimeKey;
231
- }
232
- return ret;
233
- });
234
- };
235
- }
236
- });
237
- }
238
- }
239
- }
240
-
241
- const NumPerPage = 200;
242
- async function getAllPages<TRemote>(
243
- listFn: (params: KeelListParams<any>) => Promise<
244
- APIResult<{
245
- results: TRemote[];
246
- pageInfo: any;
247
- }>
248
- >,
249
- params: KeelListParams,
250
- ): Promise<{ results: TRemote[]; subscribe: SubscribeFn; subscribeKey: string }> {
251
- const allData: TRemote[] = [];
252
- let pageInfo: PageInfo | undefined = undefined;
253
- let subscribe_;
254
- let subscribeKey_;
255
-
256
- const { first: firstParam } = params;
257
-
258
- do {
259
- const first = firstParam ? Math.min(firstParam - allData.length, NumPerPage) : NumPerPage;
260
- if (first < 1) {
261
- break;
262
- }
263
- const pageEndCursor = pageInfo?.endCursor;
264
- const paramsWithCursor: KeelListParams = pageEndCursor
265
- ? { first, ...params, after: pageEndCursor }
266
- : { first, ...params };
267
- pageInfo = undefined;
268
- const ret = await listFn(paramsWithCursor);
269
-
270
- if (ret) {
271
- // @ts-expect-error TODOKEEL
272
- const { data, error, subscribe, subscribeKey } = ret;
273
-
274
- if (subscribe) {
275
- subscribe_ = subscribe;
276
- subscribeKey_ = subscribeKey;
277
- }
278
-
279
- if (error) {
280
- await handleApiError(error);
281
- throw new Error(error.message);
282
- } else if (data) {
283
- pageInfo = data.pageInfo as PageInfo;
284
- allData.push(...data.results);
285
- }
286
- }
287
- } while (pageInfo?.hasNextPage);
288
-
289
- return { results: allData, subscribe: subscribe_, subscribeKey: subscribeKey_ };
290
- }
291
-
292
- export function syncedKeel<TRemote extends { id: string }, TLocal = TRemote>(
293
- props: SyncedKeelPropsBase<TRemote, TLocal> & SyncedKeelPropsSingle<TRemote, TLocal>,
294
- ): SyncedCrudReturnType<TLocal, 'value'>;
295
- export function syncedKeel<
296
- TRemote extends { id: string },
297
- TLocal = TRemote,
298
- TOption extends CrudAsOption = 'object',
299
- Where extends Record<string, any> = {},
300
- >(
301
- props: SyncedKeelPropsBase<TRemote, TLocal> & SyncedKeelPropsMany<TRemote, TLocal, TOption, Where>,
302
- ): SyncedCrudReturnType<TLocal, Exclude<TOption, 'value'>>;
303
- export function syncedKeel<
304
- TRemote extends { id: string },
305
- TLocal = TRemote,
306
- TOption extends CrudAsOption = 'object',
307
- Where extends Record<string, any> = {},
308
- >(
309
- props: SyncedKeelPropsBase<TRemote, TLocal> &
310
- (SyncedKeelPropsSingle<TRemote, TLocal> | SyncedKeelPropsMany<TRemote, TLocal, TOption, Where>),
311
- ): SyncedCrudReturnType<TLocal, TOption> {
312
- const { realtimePlugin } = keelConfig;
313
- props = { ...keelConfig, ...props } as any;
314
-
315
- const {
316
- get: getParam,
317
- list: listParam,
318
- create: createParam,
319
- update: updateParam,
320
- delete: deleteParam,
321
- first,
322
- where: whereParam,
323
- waitFor,
324
- fieldDeleted,
325
- ...rest
326
- } = props;
327
-
328
- const { changesSince } = props;
329
-
330
- const asType: TOption = getParam ? ('value' as TOption) : props.as!;
331
-
332
- let subscribeFn: SubscribeFn;
333
- const subscribeFnKey$ = observable('');
334
-
335
- const fieldCreatedAt: KeelKey = 'createdAt';
336
- const fieldUpdatedAt: KeelKey = 'updatedAt';
337
-
338
- const list = listParam
339
- ? async (listParams: SyncedGetParams) => {
340
- const { lastSync, refresh } = listParams;
341
- const queryBySync = !!lastSync && changesSince === 'last-sync';
342
- // If querying with lastSync pass it to the "where" parameters
343
- const where = Object.assign(
344
- queryBySync ? { updatedAt: { after: new Date(lastSync + 1) } } : {},
345
- isFunction(whereParam) ? whereParam() : whereParam,
346
- );
347
- const params: KeelListParams = { where, first };
348
-
349
- // TODO: Error?
350
- const { results, subscribe, subscribeKey } = await getAllPages(listParam, params);
351
- if (subscribe) {
352
- subscribeFn = () => subscribe({ refresh });
353
- subscribeFnKey$.set(subscribeKey);
354
- }
355
-
356
- return results;
357
- }
358
- : undefined;
359
-
360
- const get = getParam
361
- ? async (getParams: SyncedGetParams) => {
362
- const { refresh } = getParams;
363
- // @ts-expect-error TODOKEEL
364
- const { data, error, subscribe, subscribeKey } = await getParam({ refresh });
365
- if (subscribe) {
366
- subscribeFn = () => subscribe({ refresh });
367
- subscribeFnKey$.set(subscribeKey);
368
- }
369
-
370
- if (error) {
371
- throw new Error(error.message);
372
- } else {
373
- return data as TRemote;
374
- }
375
- }
376
- : undefined;
377
-
378
- const onSaved = ({ saved }: SyncedCrudOnSavedParams<TRemote, TLocal>): Partial<TLocal> | void => {
379
- if (saved) {
380
- const updatedAt = saved[fieldUpdatedAt as keyof TLocal] as Date;
381
-
382
- if (updatedAt && realtimePlugin) {
383
- const subscribeFnKey = subscribeFnKey$.get();
384
- if (subscribeFnKey) {
385
- realtimePlugin.setLatestChange(subscribeFnKey, updatedAt);
386
- }
387
- }
388
- }
389
- };
390
-
391
- const handleSetError = async (error: APIError, params: SyncedSetParams<TRemote>, isCreate: boolean) => {
392
- const { retryNum, cancelRetry, update } = params;
393
-
394
- if (
395
- isCreate &&
396
- (error.message as string)?.includes('for the unique') &&
397
- (error.message as string)?.includes('must be unique')
398
- ) {
399
- if (__DEV__) {
400
- console.log('Creating duplicate data already saved, just ignore.');
401
- }
402
- // This has already been saved but didn't update pending changes, so just update with {} to clear the pending state
403
- update({
404
- value: {},
405
- mode: 'assign',
406
- });
407
- } else if (error.type === 'bad_request') {
408
- keelConfig.onError?.(error);
409
-
410
- if (retryNum > 4) {
411
- cancelRetry();
412
- }
413
-
414
- throw new Error(error.message);
415
- } else {
416
- await handleApiError(error);
417
-
418
- throw new Error(error.message);
419
- }
420
- };
421
-
422
- const create = createParam
423
- ? async (input: TRemote, params: SyncedSetParams<TRemote>) => {
424
- const { data, error } = await createParam(convertObjectToCreate(input));
425
-
426
- if (error) {
427
- handleSetError(error, params, true);
428
- }
429
-
430
- return data;
431
- }
432
- : undefined;
433
-
434
- const update = updateParam
435
- ? async (input: TRemote, params: SyncedSetParams<TRemote>) => {
436
- const id = input.id;
437
- const values = convertObjectToCreate(input as unknown as Partial<KeelObjectBase>) as Partial<TRemote> &
438
- Partial<KeelObjectBase>;
439
- delete values.id;
440
- delete values.createdAt;
441
- delete values.updatedAt;
442
- if (!isEmpty(values)) {
443
- const { data, error } = await updateParam({ where: { id }, values });
444
-
445
- if (error) {
446
- handleSetError(error, params, false);
447
- }
448
-
449
- return data;
450
- }
451
- }
452
- : undefined;
453
- const deleteFn = deleteParam
454
- ? async ({ id }: { id: string }, params: SyncedSetParams<TRemote>) => {
455
- const { data, error } = await deleteParam({ id });
456
-
457
- if (error) {
458
- handleSetError(error, params, false);
459
- }
460
-
461
- return data;
462
- }
463
- : undefined;
464
-
465
- const subscribe = (params: SyncedSubscribeParams<TRemote>) => {
466
- let unsubscribe: undefined | (() => void) = undefined;
467
- when(subscribeFnKey$, () => {
468
- unsubscribe = subscribeFn!(params);
469
- });
470
- return () => {
471
- unsubscribe?.();
472
- };
473
- };
474
-
475
- return syncedCrud<TRemote, TLocal, TOption>({
476
- ...rest,
477
- as: asType,
478
- list,
479
- create,
480
- update,
481
- delete: deleteFn,
482
- waitFor: () => isEnabled$.get() && (waitFor ? computeSelector(waitFor) : true),
483
- onSaved,
484
- onSavedUpdate: 'createdUpdatedAt',
485
- fieldCreatedAt,
486
- fieldUpdatedAt,
487
- fieldDeleted: fieldDeleted || 'deleted',
488
- changesSince,
489
- updatePartial: true,
490
- subscribe,
491
- generateId: generateKeelId,
492
- // @ts-expect-error This errors because of the get/list union type
493
- get,
494
- }) as SyncedCrudReturnType<TLocal, TOption>;
495
- }