@legendapp/state 2.2.0-next.7 → 2.2.0-next.71

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 (298) hide show
  1. package/README.md +4 -2
  2. package/babel.js.map +1 -1
  3. package/config/enable$get.d.ts +8 -0
  4. package/config/enable$get.js +24 -0
  5. package/config/enable$get.js.map +1 -0
  6. package/config/enable$get.mjs +21 -0
  7. package/config/enable$get.mjs.map +1 -0
  8. package/config/enableReactComponents.js.map +1 -1
  9. package/config/enableReactComponents.mjs.map +1 -1
  10. package/config/enableReactNativeComponents.js.map +1 -1
  11. package/config/enableReactNativeComponents.mjs.map +1 -1
  12. package/config/enableReactTracking.d.ts +0 -9
  13. package/config/enableReactTracking.js.map +1 -1
  14. package/config/enableReactTracking.mjs.map +1 -1
  15. package/config/enableReactUse.d.ts +1 -1
  16. package/config/enableReactUse.js +1 -0
  17. package/config/enableReactUse.js.map +1 -1
  18. package/config/enableReactUse.mjs +1 -0
  19. package/config/enableReactUse.mjs.map +1 -1
  20. package/config/enable_peek.d.ts +8 -0
  21. package/config/{enableDirectPeek.js → enable_peek.js} +6 -3
  22. package/config/enable_peek.js.map +1 -0
  23. package/config/{enableDirectPeek.mjs → enable_peek.mjs} +5 -3
  24. package/config/enable_peek.mjs.map +1 -0
  25. package/helpers/fetch.d.ts +4 -3
  26. package/helpers/fetch.js.map +1 -1
  27. package/helpers/fetch.mjs.map +1 -1
  28. package/helpers/pageHash.js.map +1 -1
  29. package/helpers/pageHash.mjs.map +1 -1
  30. package/helpers/pageHashParams.js.map +1 -1
  31. package/helpers/pageHashParams.mjs.map +1 -1
  32. package/helpers/time.d.ts +2 -2
  33. package/helpers/time.js.map +1 -1
  34. package/helpers/time.mjs.map +1 -1
  35. package/history.js +2 -2
  36. package/history.js.map +1 -1
  37. package/history.mjs +3 -3
  38. package/history.mjs.map +1 -1
  39. package/index.d.ts +30 -9
  40. package/index.js +877 -661
  41. package/index.js.map +1 -1
  42. package/index.mjs +874 -658
  43. package/index.mjs.map +1 -1
  44. package/package.json +22 -25
  45. package/persist-plugins/async-storage.d.ts +3 -3
  46. package/persist-plugins/async-storage.js +8 -7
  47. package/persist-plugins/async-storage.js.map +1 -1
  48. package/persist-plugins/async-storage.mjs +9 -8
  49. package/persist-plugins/async-storage.mjs.map +1 -1
  50. package/persist-plugins/fetch.js.map +1 -1
  51. package/persist-plugins/fetch.mjs.map +1 -1
  52. package/persist-plugins/firebase.d.ts +1 -1
  53. package/persist-plugins/firebase.js +12 -11
  54. package/persist-plugins/firebase.js.map +1 -1
  55. package/persist-plugins/firebase.mjs +13 -12
  56. package/persist-plugins/firebase.mjs.map +1 -1
  57. package/persist-plugins/indexeddb.d.ts +10 -10
  58. package/persist-plugins/indexeddb.js +2 -2
  59. package/persist-plugins/indexeddb.js.map +1 -1
  60. package/persist-plugins/indexeddb.mjs +2 -2
  61. package/persist-plugins/indexeddb.mjs.map +1 -1
  62. package/persist-plugins/local-storage.d.ts +3 -4
  63. package/persist-plugins/local-storage.js +19 -7
  64. package/persist-plugins/local-storage.js.map +1 -1
  65. package/persist-plugins/local-storage.mjs +20 -9
  66. package/persist-plugins/local-storage.mjs.map +1 -1
  67. package/persist-plugins/mmkv.d.ts +8 -8
  68. package/persist-plugins/mmkv.js +5 -4
  69. package/persist-plugins/mmkv.js.map +1 -1
  70. package/persist-plugins/mmkv.mjs +6 -5
  71. package/persist-plugins/mmkv.mjs.map +1 -1
  72. package/persist-plugins/query.js.map +1 -1
  73. package/persist-plugins/query.mjs.map +1 -1
  74. package/persist.d.ts +2 -14
  75. package/persist.js +1250 -268
  76. package/persist.js.map +1 -1
  77. package/persist.mjs +1250 -269
  78. package/persist.mjs.map +1 -1
  79. package/react-hooks/createObservableHook.js +1 -1
  80. package/react-hooks/createObservableHook.js.map +1 -1
  81. package/react-hooks/createObservableHook.mjs +1 -1
  82. package/react-hooks/createObservableHook.mjs.map +1 -1
  83. package/react-hooks/useFetch.d.ts +4 -3
  84. package/react-hooks/useFetch.js.map +1 -1
  85. package/react-hooks/useFetch.mjs.map +1 -1
  86. package/react-hooks/useHover.js.map +1 -1
  87. package/react-hooks/useHover.mjs.map +1 -1
  88. package/react-hooks/useMeasure.js.map +1 -1
  89. package/react-hooks/useMeasure.mjs.map +1 -1
  90. package/react-hooks/useObservableNextRouter.js.map +1 -1
  91. package/react-hooks/useObservableNextRouter.mjs.map +1 -1
  92. package/react-hooks/useObservableQuery.js.map +1 -1
  93. package/react-hooks/useObservableQuery.mjs.map +1 -1
  94. package/react-hooks/usePersistedObservable.d.ts +5 -3
  95. package/react-hooks/usePersistedObservable.js +5 -2
  96. package/react-hooks/usePersistedObservable.js.map +1 -1
  97. package/react-hooks/usePersistedObservable.mjs +5 -2
  98. package/react-hooks/usePersistedObservable.mjs.map +1 -1
  99. package/react.js +61 -75
  100. package/react.js.map +1 -1
  101. package/react.mjs +61 -75
  102. package/react.mjs.map +1 -1
  103. package/src/ObservableObject.ts +1184 -0
  104. package/src/ObservablePrimitive.ts +62 -0
  105. package/src/babel/index.ts +70 -0
  106. package/src/batching.ts +372 -0
  107. package/src/computed.ts +16 -0
  108. package/src/config/enable$get.ts +30 -0
  109. package/src/config/enableReactComponents.ts +26 -0
  110. package/src/config/enableReactNativeComponents.ts +102 -0
  111. package/src/config/enableReactTracking.ts +60 -0
  112. package/src/config/enableReactUse.ts +23 -0
  113. package/src/config/enable_peek.ts +31 -0
  114. package/src/config.ts +47 -0
  115. package/src/createObservable.ts +46 -0
  116. package/src/event.ts +26 -0
  117. package/src/globals.ts +224 -0
  118. package/src/helpers/fetch.ts +26 -0
  119. package/src/helpers/pageHash.ts +41 -0
  120. package/src/helpers/pageHashParams.ts +55 -0
  121. package/src/helpers/time.ts +30 -0
  122. package/src/helpers.ts +221 -0
  123. package/src/history/trackHistory.ts +29 -0
  124. package/src/is.ts +56 -0
  125. package/src/linked.ts +6 -0
  126. package/src/observable.ts +32 -0
  127. package/src/observableInterfaces.ts +165 -0
  128. package/src/observableTypes.ts +221 -0
  129. package/src/observe.ts +89 -0
  130. package/src/onChange.ts +136 -0
  131. package/src/persist/configureObservablePersistence.ts +7 -0
  132. package/src/persist/fieldTransformer.ts +149 -0
  133. package/src/persist/observablePersistRemoteFunctionsAdapter.ts +39 -0
  134. package/src/persist/persistObservable.ts +1029 -0
  135. package/src/persist-plugins/async-storage.ts +102 -0
  136. package/src/persist-plugins/fetch.ts +33 -0
  137. package/src/persist-plugins/firebase.ts +1050 -0
  138. package/src/persist-plugins/indexeddb.ts +433 -0
  139. package/src/persist-plugins/local-storage.ts +90 -0
  140. package/src/persist-plugins/mmkv.ts +90 -0
  141. package/src/persist-plugins/query.ts +133 -0
  142. package/src/persistTypes.ts +226 -0
  143. package/src/proxy.ts +28 -0
  144. package/src/react/Computed.tsx +7 -0
  145. package/src/react/For.tsx +116 -0
  146. package/src/react/Memo.tsx +4 -0
  147. package/src/react/Reactive.tsx +53 -0
  148. package/src/react/Show.tsx +33 -0
  149. package/src/react/Switch.tsx +43 -0
  150. package/src/react/react-globals.ts +3 -0
  151. package/src/react/{reactInterfaces.d.ts → reactInterfaces.ts} +15 -7
  152. package/src/react/reactive-observer.tsx +210 -0
  153. package/src/react/useComputed.ts +36 -0
  154. package/src/react/useEffectOnce.ts +41 -0
  155. package/src/react/useIsMounted.ts +16 -0
  156. package/src/react/useMount.ts +15 -0
  157. package/src/react/useObservable.ts +24 -0
  158. package/src/react/useObservableReducer.ts +52 -0
  159. package/src/react/useObservableState.ts +30 -0
  160. package/src/react/useObserve.ts +54 -0
  161. package/src/react/useObserveEffect.ts +40 -0
  162. package/src/react/usePauseProvider.tsx +13 -0
  163. package/src/react/useSelector.ts +167 -0
  164. package/src/react/useUnmount.ts +8 -0
  165. package/src/react/useWhen.ts +9 -0
  166. package/src/react-hooks/createObservableHook.ts +53 -0
  167. package/src/react-hooks/useFetch.ts +16 -0
  168. package/src/react-hooks/useHover.ts +40 -0
  169. package/src/react-hooks/useMeasure.ts +48 -0
  170. package/src/react-hooks/useObservableNextRouter.ts +137 -0
  171. package/src/react-hooks/useObservableQuery.ts +205 -0
  172. package/src/react-hooks/usePersistedObservable.ts +24 -0
  173. package/src/retry.ts +69 -0
  174. package/src/setupTracking.ts +26 -0
  175. package/src/sync/activateSyncedNode.ts +146 -0
  176. package/src/sync/configureObservableSync.ts +7 -0
  177. package/src/sync/syncHelpers.ts +15 -0
  178. package/src/sync/syncObservable.ts +989 -0
  179. package/src/sync/syncObservableAdapter.ts +30 -0
  180. package/src/sync/synced.ts +20 -0
  181. package/src/sync-plugins/fetch.ts +42 -0
  182. package/src/syncTypes.ts +163 -0
  183. package/src/trace/traceHelpers.ts +11 -0
  184. package/src/trace/useTraceListeners.ts +34 -0
  185. package/src/trace/useTraceUpdates.ts +24 -0
  186. package/src/trace/useVerifyNotTracking.ts +33 -0
  187. package/src/trace/useVerifyOneRender.ts +10 -0
  188. package/src/trackSelector.ts +52 -0
  189. package/src/tracking.ts +43 -0
  190. package/src/types/babel.d.ts +12 -0
  191. package/src/when.ts +70 -0
  192. package/sync-plugins/fetch.d.ts +11 -0
  193. package/sync-plugins/fetch.js +24 -0
  194. package/sync-plugins/fetch.js.map +1 -0
  195. package/sync-plugins/fetch.mjs +22 -0
  196. package/sync-plugins/fetch.mjs.map +1 -0
  197. package/sync.d.ts +8 -0
  198. package/sync.js +919 -0
  199. package/sync.js.map +1 -0
  200. package/sync.mjs +912 -0
  201. package/sync.mjs.map +1 -0
  202. package/trace.js +13 -10
  203. package/trace.js.map +1 -1
  204. package/trace.mjs +11 -8
  205. package/trace.mjs.map +1 -1
  206. package/types/babel.d.ts +3 -3
  207. package/config/enableDirectAccess.d.ts +0 -7
  208. package/config/enableDirectAccess.js +0 -25
  209. package/config/enableDirectAccess.js.map +0 -1
  210. package/config/enableDirectAccess.mjs +0 -23
  211. package/config/enableDirectAccess.mjs.map +0 -1
  212. package/config/enableDirectPeek.d.ts +0 -7
  213. package/config/enableDirectPeek.js.map +0 -1
  214. package/config/enableDirectPeek.mjs.map +0 -1
  215. package/config/enableReactDirectRender.d.ts +0 -2
  216. package/config/enableReactDirectRender.js +0 -78
  217. package/config/enableReactDirectRender.js.map +0 -1
  218. package/config/enableReactDirectRender.mjs +0 -75
  219. package/config/enableReactDirectRender.mjs.map +0 -1
  220. package/src/ObservableObject.d.ts +0 -14
  221. package/src/ObservablePrimitive.d.ts +0 -7
  222. package/src/babel/index.d.ts +0 -17
  223. package/src/batching.d.ts +0 -6
  224. package/src/computed.d.ts +0 -4
  225. package/src/config/enableDirectAccess.d.ts +0 -7
  226. package/src/config/enableDirectPeek.d.ts +0 -7
  227. package/src/config/enableReactComponents.d.ts +0 -7
  228. package/src/config/enableReactDirectRender.d.ts +0 -2
  229. package/src/config/enableReactNativeComponents.d.ts +0 -20
  230. package/src/config/enableReactTracking.d.ts +0 -15
  231. package/src/config/enableReactUse.d.ts +0 -7
  232. package/src/config.d.ts +0 -8
  233. package/src/createObservable.d.ts +0 -2
  234. package/src/event.d.ts +0 -2
  235. package/src/globals.d.ts +0 -32
  236. package/src/helpers/fetch.d.ts +0 -6
  237. package/src/helpers/pageHash.d.ts +0 -7
  238. package/src/helpers/pageHashParams.d.ts +0 -7
  239. package/src/helpers/time.d.ts +0 -3
  240. package/src/helpers.d.ts +0 -13
  241. package/src/history/trackHistory.d.ts +0 -4
  242. package/src/is.d.ts +0 -10
  243. package/src/observable.d.ts +0 -16
  244. package/src/observableInterfaces.d.ts +0 -456
  245. package/src/observe.d.ts +0 -6
  246. package/src/onChange.d.ts +0 -7
  247. package/src/persist/configureObservablePersistence.d.ts +0 -3
  248. package/src/persist/fieldTransformer.d.ts +0 -8
  249. package/src/persist/observablePersistRemoteFunctionsAdapter.d.ts +0 -2
  250. package/src/persist/persistActivateNode.d.ts +0 -1
  251. package/src/persist/persistHelpers.d.ts +0 -1
  252. package/src/persist/persistObservable.d.ts +0 -25
  253. package/src/persist-plugins/async-storage.d.ts +0 -14
  254. package/src/persist-plugins/fetch.d.ts +0 -10
  255. package/src/persist-plugins/firebase.d.ts +0 -51
  256. package/src/persist-plugins/indexeddb.d.ts +0 -25
  257. package/src/persist-plugins/local-storage.d.ts +0 -21
  258. package/src/persist-plugins/mmkv.d.ts +0 -14
  259. package/src/persist-plugins/query.d.ts +0 -18
  260. package/src/proxy.d.ts +0 -5
  261. package/src/react/Computed.d.ts +0 -5
  262. package/src/react/For.d.ts +0 -15
  263. package/src/react/Memo.d.ts +0 -3
  264. package/src/react/Reactive.d.ts +0 -9
  265. package/src/react/Show.d.ts +0 -18
  266. package/src/react/Switch.d.ts +0 -14
  267. package/src/react/react-globals.d.ts +0 -3
  268. package/src/react/reactive-observer.d.ts +0 -14
  269. package/src/react/useComputed.d.ts +0 -5
  270. package/src/react/useEffectOnce.d.ts +0 -1
  271. package/src/react/useIsMounted.d.ts +0 -2
  272. package/src/react/useMount.d.ts +0 -2
  273. package/src/react/useObservable.d.ts +0 -9
  274. package/src/react/useObservableReducer.d.ts +0 -7
  275. package/src/react/useObservableState.d.ts +0 -2
  276. package/src/react/useObserve.d.ts +0 -4
  277. package/src/react/useObserveEffect.d.ts +0 -4
  278. package/src/react/usePauseProvider.d.ts +0 -8
  279. package/src/react/useSelector.d.ts +0 -3
  280. package/src/react/useUnmount.d.ts +0 -2
  281. package/src/react/useWhen.d.ts +0 -3
  282. package/src/react-hooks/createObservableHook.d.ts +0 -2
  283. package/src/react-hooks/useFetch.d.ts +0 -6
  284. package/src/react-hooks/useHover.d.ts +0 -3
  285. package/src/react-hooks/useMeasure.d.ts +0 -6
  286. package/src/react-hooks/useObservableNextRouter.d.ts +0 -33
  287. package/src/react-hooks/useObservableQuery.d.ts +0 -6
  288. package/src/react-hooks/usePersistedObservable.d.ts +0 -11
  289. package/src/retry.d.ts +0 -9
  290. package/src/setupTracking.d.ts +0 -2
  291. package/src/trace/traceHelpers.d.ts +0 -2
  292. package/src/trace/useTraceListeners.d.ts +0 -1
  293. package/src/trace/useTraceUpdates.d.ts +0 -1
  294. package/src/trace/useVerifyNotTracking.d.ts +0 -1
  295. package/src/trace/useVerifyOneRender.d.ts +0 -1
  296. package/src/trackSelector.d.ts +0 -7
  297. package/src/tracking.d.ts +0 -13
  298. package/src/when.d.ts +0 -3
@@ -0,0 +1,133 @@
1
+ import {
2
+ ObservablePersistRemoteFunctions,
3
+ isFunction,
4
+ observe,
5
+ type ObservablePersistRemoteSetParams,
6
+ } from '@legendapp/state';
7
+ import {
8
+ InfiniteQueryObserver,
9
+ MutationObserver,
10
+ QueryClient,
11
+ QueryKey,
12
+ QueryObserver,
13
+ UseBaseQueryOptions,
14
+ UseMutationOptions,
15
+ notifyManager,
16
+ useQueryClient,
17
+ } from '@tanstack/react-query';
18
+
19
+ type ObservableQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey extends QueryKey> = Omit<
20
+ UseBaseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>,
21
+ 'queryKey'
22
+ > & { queryKey?: TQueryKey | (() => TQueryKey) };
23
+
24
+ type Params<TQueryFnData, TError, TData, TQueryData, TQueryKey extends QueryKey> = {
25
+ query: ObservableQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>;
26
+ mutation?: UseMutationOptions<TData, TError, void>;
27
+ type?: 'Query' | 'Infinite';
28
+ } & (
29
+ | {
30
+ queryClient: QueryClient;
31
+ useContext?: false | undefined | never;
32
+ }
33
+ | {
34
+ queryClient?: QueryClient;
35
+ useContext?: true;
36
+ }
37
+ );
38
+
39
+ export function persistPluginQuery<TObs, TQueryFnData, TError, TData, TQueryData, TQueryKey extends QueryKey>({
40
+ query: options,
41
+ mutation: mutationOptions,
42
+ type = 'Query',
43
+ queryClient,
44
+ useContext,
45
+ }: Params<TQueryFnData, TError, TData, TQueryData, TQueryKey>): ObservablePersistRemoteFunctions<TObs> {
46
+ if (useContext) {
47
+ queryClient = queryClient || useQueryClient();
48
+ }
49
+ // Set up the defaults like useBaseQuery does
50
+ const defaultedOptions = queryClient!.defaultQueryOptions(
51
+ options as UseBaseQueryOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey>,
52
+ );
53
+
54
+ // Include callbacks in batch renders
55
+ if (defaultedOptions.onError) {
56
+ defaultedOptions.onError = notifyManager.batchCalls(defaultedOptions.onError);
57
+ }
58
+
59
+ if (defaultedOptions.onSuccess) {
60
+ defaultedOptions.onSuccess = notifyManager.batchCalls(defaultedOptions.onSuccess);
61
+ }
62
+
63
+ if (defaultedOptions.onSettled) {
64
+ defaultedOptions.onSettled = notifyManager.batchCalls(defaultedOptions.onSettled);
65
+ }
66
+
67
+ const Observer = type === 'Query' ? QueryObserver : (InfiniteQueryObserver as typeof QueryObserver);
68
+
69
+ const ret: ObservablePersistRemoteFunctions<unknown> = {
70
+ get({ onChange }) {
71
+ let observer: QueryObserver<TQueryFnData, TError, TData, TQueryData, TQueryKey> | undefined = undefined;
72
+ let latestOptions = defaultedOptions;
73
+ let queryKeyFromFn: TQueryKey;
74
+
75
+ const origQueryKey = options.queryKey!;
76
+
77
+ // If the queryKey is a function, observe it and extract the raw value
78
+ const isKeyFunction = isFunction(origQueryKey);
79
+ if (isKeyFunction) {
80
+ observe(({ num }) => {
81
+ queryKeyFromFn = origQueryKey();
82
+ if (num > 0) {
83
+ updateQueryOptions(latestOptions);
84
+ }
85
+ });
86
+ }
87
+
88
+ const updateQueryOptions = (obj: any) => {
89
+ // Since legend-state mutates the query options, we need to clone it to make Query
90
+ // see it as changed
91
+ const options = Object.assign({}, obj);
92
+
93
+ // Use the latest value from the observed queryKey function
94
+ if (isKeyFunction) {
95
+ options.queryKey = queryKeyFromFn;
96
+ }
97
+
98
+ latestOptions = options;
99
+
100
+ // Update the Query options
101
+ if (observer) {
102
+ observer.setOptions(options, { listeners: false });
103
+ }
104
+ };
105
+ updateQueryOptions(defaultedOptions);
106
+
107
+ // Create the observer
108
+ observer = new Observer!<TQueryFnData, TError, TData, TQueryData, TQueryKey>(queryClient!, latestOptions);
109
+
110
+ // Get the initial optimistic results if it's already cached
111
+ const result = observer!.getOptimisticResult(latestOptions);
112
+ // Subscribe to Query's observer and update the observable
113
+ observer!.subscribe((result) => {
114
+ onChange({ value: result.data });
115
+ });
116
+
117
+ // Return the initial data
118
+ if (result) {
119
+ return result.data;
120
+ }
121
+ },
122
+ };
123
+
124
+ if (mutationOptions) {
125
+ const mutator = new MutationObserver(queryClient!, mutationOptions);
126
+ // When the observable changes call the mutator function
127
+ ret.set = async ({ value }: ObservablePersistRemoteSetParams<any>) => {
128
+ mutator.mutate(value);
129
+ };
130
+ }
131
+
132
+ return ret as any;
133
+ }
@@ -0,0 +1,226 @@
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
+ // @ts-ignore
7
+ import type { DatabaseReference, Query } from 'firebase/database';
8
+
9
+ import type { GetMode, PersistMetadata } from './syncTypes';
10
+ import type {
11
+ ArrayValue,
12
+ Change,
13
+ ClassConstructor,
14
+ LinkedOptions,
15
+ RecordValue,
16
+ RetryOptions,
17
+ Selector,
18
+ TypeAtPath,
19
+ } from './observableInterfaces';
20
+ import type { Observable, ObservableParam, ObservableState } from './observableTypes';
21
+
22
+ export interface PersistTransform<TOrig = any, TSaved = TOrig> {
23
+ load?: (value: TSaved) => TOrig | Promise<TOrig>;
24
+ save?: (value: TOrig) => TSaved | Promise<TSaved>;
25
+ }
26
+
27
+ export interface LegacyPersistOptionsLocal<T = any> {
28
+ name: string;
29
+ transform?: PersistTransform<T>;
30
+ fieldTransforms?: FieldTransforms<T>;
31
+ readonly?: boolean;
32
+ mmkv?: MMKVConfiguration;
33
+ indexedDB?: {
34
+ prefixID?: string;
35
+ itemID?: string;
36
+ };
37
+ options?: any;
38
+ }
39
+ export type LegacyPersistOptionsRemote<T = any> = ObservablePersistenceConfigRemoteGlobalOptions & {
40
+ readonly?: boolean;
41
+ waitForGet?: Selector<any>;
42
+ waitForSet?: LinkedOptions['waitForSet'];
43
+ manual?: boolean;
44
+ fieldTransforms?: FieldTransforms<T>;
45
+ allowSetIfError?: boolean;
46
+ transform?: PersistTransform<T>;
47
+ firebase?: {
48
+ refPath: (uid: string | undefined) => string;
49
+ query?: (ref: DatabaseReference) => DatabaseReference | Query;
50
+ queryByModified?: QueryByModified<T>;
51
+ ignoreKeys?: string[];
52
+ requireAuth?: boolean;
53
+ mode?: 'once' | 'realtime';
54
+ };
55
+ offlineBehavior?: false | 'retry';
56
+ changeTimeout?: number;
57
+ metadataTimeout?: number;
58
+ retry?: RetryOptions;
59
+ onGetError?: (error: Error) => void;
60
+ onSetError?: (error: Error) => void;
61
+ log?: (message?: any, ...optionalParams: any[]) => void;
62
+ onBeforeSet?: () => void;
63
+ onSet?: () => void;
64
+ };
65
+ export interface ObservablePersistenceConfigLocalGlobalOptions {
66
+ onGetError?: (error: Error) => void;
67
+ onSetError?: (error: Error) => void;
68
+ indexedDB?: {
69
+ databaseName: string;
70
+ version: number;
71
+ tableNames: string[];
72
+ };
73
+ asyncStorage?: {
74
+ AsyncStorage: AsyncStorageStatic;
75
+ preload?: boolean | string[];
76
+ };
77
+ }
78
+ export interface ObservablePersistenceConfigRemoteGlobalOptions {
79
+ debounceSet?: number;
80
+ dateModifiedKey?: string;
81
+ offlineBehavior?: false | 'retry';
82
+ retry?: RetryOptions;
83
+ onGetError?: (error: Error) => void;
84
+ onSetError?: (error: Error) => void;
85
+ log?: (logLevel: 'verbose' | 'warning' | 'error', message: any, ...optionalParams: any[]) => void;
86
+ onBeforeSet?: () => void;
87
+ onAfterSet?: () => void;
88
+ }
89
+ export interface ObservablePersistenceConfig {
90
+ pluginLocal?: ClassConstructor<ObservablePersistLocal>;
91
+ pluginRemote?: ClassConstructor<ObservablePersistRemoteClass> | ObservablePersistRemoteFunctions;
92
+ localOptions?: ObservablePersistenceConfigLocalGlobalOptions;
93
+ remoteOptions?: ObservablePersistenceConfigRemoteGlobalOptions;
94
+ }
95
+ export interface LegacyPersistOptions<T = any> {
96
+ local?: string | LegacyPersistOptionsLocal<T>;
97
+ remote?: LegacyPersistOptionsRemote<T>;
98
+ pluginLocal?: ClassConstructor<ObservablePersistLocal>;
99
+ pluginRemote?: ClassConstructor<ObservablePersistRemoteClass> | ObservablePersistRemoteFunctions<T>;
100
+ }
101
+
102
+ export interface ObservablePersistLocal {
103
+ initialize?(config: ObservablePersistenceConfigLocalGlobalOptions): void | Promise<void>;
104
+ loadTable?(table: string, config: LegacyPersistOptionsLocal): Promise<any> | void;
105
+ getTable<T = any>(table: string, config: LegacyPersistOptionsLocal): T;
106
+ set(table: string, changes: Change[], config: LegacyPersistOptionsLocal): Promise<any> | void;
107
+ deleteTable(table: string, config: LegacyPersistOptionsLocal): Promise<any> | void;
108
+ getMetadata(table: string, config: LegacyPersistOptionsLocal): PersistMetadata;
109
+ setMetadata(table: string, metadata: PersistMetadata, config: LegacyPersistOptionsLocal): Promise<any> | void;
110
+ deleteMetadata(table: string, config: LegacyPersistOptionsLocal): Promise<any> | void;
111
+ }
112
+ export interface ObservableOnChangeParams {
113
+ value: unknown;
114
+ path?: string[]; // TODOv4 remove
115
+ pathTypes?: TypeAtPath[]; // TODOv4 remove
116
+ mode?: GetMode;
117
+ dateModified?: number | undefined; // TODOv4 remove
118
+ lastSync?: number | undefined;
119
+ }
120
+ export interface ObservablePersistRemoteSetParams<T> {
121
+ syncState: Observable<ObservablePersistState>;
122
+ obs: ObservableParam<T>;
123
+ options: LegacyPersistOptions<T>;
124
+ changes: Change[];
125
+ value: T;
126
+ }
127
+ export interface ObservablePersistRemoteGetParams<T> {
128
+ state: Observable<ObservablePersistState>;
129
+ obs: ObservableParam<T>;
130
+ options: LegacyPersistOptions<T>;
131
+ dateModified?: number;
132
+ lastSync?: number;
133
+ mode?: GetMode;
134
+ onGet: () => void;
135
+ onError: (error: Error) => void;
136
+ onChange: (params: ObservableOnChangeParams) => void | Promise<void>;
137
+ }
138
+ export type ObservablePersistRemoteGetFnParams<T> = Omit<ObservablePersistRemoteGetParams<T>, 'onGet'>;
139
+
140
+ export interface ObservablePersistRemoteClass {
141
+ get?<T>(params: ObservablePersistRemoteGetParams<T>): void;
142
+ set?<T>(
143
+ params: ObservablePersistRemoteSetParams<T>,
144
+ ): void | Promise<void | { changes?: object; dateModified?: number; lastSync?: number; pathStrs?: string[] }>;
145
+ }
146
+
147
+ export interface ObservablePersistRemoteFunctions<T = any> {
148
+ get?(params: ObservablePersistRemoteGetFnParams<T>): T | Promise<T>;
149
+ set?(
150
+ params: ObservablePersistRemoteSetParams<T>,
151
+ ): void | Promise<void | { changes?: object | undefined; dateModified?: number; lastSync?: number }>;
152
+ }
153
+
154
+ export interface ObservablePersistStateBase {
155
+ isLoadedLocal: boolean;
156
+ isEnabledLocal: boolean;
157
+ isEnabledRemote: boolean;
158
+ dateModified?: number;
159
+ lastSync?: number;
160
+ syncCount?: number;
161
+ clearLocal: () => Promise<void>;
162
+ sync: () => Promise<void>;
163
+ getPendingChanges: () =>
164
+ | Record<
165
+ string,
166
+ {
167
+ p: any;
168
+ v?: any;
169
+ }
170
+ >
171
+ | undefined;
172
+ }
173
+ export type ObservablePersistState = ObservableState & ObservablePersistStateBase;
174
+
175
+ // This converts the state object's shape to the field transformer's shape
176
+ // TODO: FieldTransformer and this shape can likely be refactored to be simpler
177
+ declare type ObjectKeys<T> = Pick<
178
+ T,
179
+ {
180
+ [K in keyof T]-?: K extends string
181
+ ? T[K] extends Record<string, any>
182
+ ? T[K] extends any[]
183
+ ? never
184
+ : K
185
+ : never
186
+ : never;
187
+ }[keyof T]
188
+ >;
189
+ declare type DictKeys<T> = Pick<
190
+ T,
191
+ {
192
+ [K in keyof T]-?: K extends string ? (T[K] extends Record<string, Record<string, any>> ? K : never) : never;
193
+ }[keyof T]
194
+ >;
195
+ declare type ArrayKeys<T> = Pick<
196
+ T,
197
+ {
198
+ [K in keyof T]-?: K extends string | number ? (T[K] extends any[] ? K : never) : never;
199
+ }[keyof T]
200
+ >;
201
+ export declare type FieldTransforms<T> =
202
+ | (T extends Record<string, Record<string, any>> ? { _dict: FieldTransformsInner<RecordValue<T>> } : never)
203
+ | FieldTransformsInner<T>;
204
+ export declare type FieldTransformsInner<T> = {
205
+ [K in keyof T]: string;
206
+ } & (
207
+ | {
208
+ [K in keyof ObjectKeys<T> as `${K}_obj`]?: FieldTransforms<T[K]>;
209
+ }
210
+ | {
211
+ [K in keyof DictKeys<T> as `${K}_dict`]?: FieldTransforms<RecordValue<T[K]>>;
212
+ }
213
+ ) & {
214
+ [K in keyof ArrayKeys<T> as `${K}_arr`]?: FieldTransforms<ArrayValue<T[K]>>;
215
+ } & {
216
+ [K in keyof ArrayKeys<T> as `${K}_val`]?: FieldTransforms<ArrayValue<T[K]>>;
217
+ };
218
+
219
+ export type QueryByModified<T> =
220
+ | boolean
221
+ | {
222
+ [K in keyof T]?: QueryByModified<T[K]>;
223
+ }
224
+ | {
225
+ '*'?: boolean;
226
+ };
package/src/proxy.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { linked } from './linked';
2
+ import { observable } from './observable';
3
+ import { Observable, ObservableParam } from './observableTypes';
4
+
5
+ // Deprecated. Remove in v4
6
+
7
+ export function proxy<T, T2 = T>(
8
+ get: (key: string) => T,
9
+ set: (key: string, value: T2) => void,
10
+ ): Observable<Record<string, T>>;
11
+ export function proxy<T extends Record<string, any>>(
12
+ get: <K extends keyof T>(key: K) => ObservableParam<T[K]>,
13
+ ): Observable<T>;
14
+ export function proxy<T>(get: (key: string) => ObservableParam<T>): Observable<Record<string, T>>;
15
+ export function proxy<T>(get: (key: string) => T): Observable<Record<string, T>>;
16
+ export function proxy<T extends Record<string, any>, T2 = T>(
17
+ get: (key: any) => ObservableParam<any>,
18
+ set?: (key: any, value: T2) => void,
19
+ ): any {
20
+ return observable((key: string) =>
21
+ set
22
+ ? linked({
23
+ get: () => get(key),
24
+ set: ({ value }) => set(key, value as any),
25
+ })
26
+ : get(key),
27
+ );
28
+ }
@@ -0,0 +1,7 @@
1
+ import { ReactElement, ReactNode } from 'react';
2
+ import type { ObservableParam } from '../observableTypes';
3
+ import { useSelector } from './useSelector';
4
+
5
+ export function Computed({ children }: { children: ObservableParam | (() => ReactNode) }): ReactElement {
6
+ return useSelector(children, { skipCheck: true }) as ReactElement;
7
+ }
@@ -0,0 +1,116 @@
1
+ import type { Observable, ObservableObject, ObservableParam } from '@legendapp/state';
2
+ import { internal, isArray, isFunction } from '@legendapp/state';
3
+ import { FC, ReactElement, createElement, memo, useMemo, useRef } from 'react';
4
+ import { observer } from './reactive-observer';
5
+ import { useSelector } from './useSelector';
6
+ const { findIDKey, getNode, optimized } = internal;
7
+
8
+ const autoMemoCache = new Map<FC<any>, FC<any>>();
9
+
10
+ type ForItemProps<T, TProps = {}> = {
11
+ item$: Observable<T>;
12
+ id?: string;
13
+ } & TProps;
14
+
15
+ export function For<T, TProps>({
16
+ each,
17
+ optimized: isOptimized,
18
+ item,
19
+ itemProps,
20
+ sortValues,
21
+ children,
22
+ }: {
23
+ each?: ObservableParam<T[] | Record<any, T> | Map<any, T>>;
24
+ optimized?: boolean;
25
+ item?: FC<ForItemProps<T, TProps>>;
26
+ itemProps?: TProps;
27
+ sortValues?: (A: T, B: T, AKey: string, BKey: string) => number;
28
+ children?: (value: Observable<T>, id: string | undefined) => ReactElement;
29
+ }): ReactElement | null {
30
+ if (!each) return null;
31
+
32
+ // Get the raw value with a shallow listener so this list only re-renders
33
+ // when the array length changes
34
+ const value = useSelector(() => each!.get(isOptimized ? optimized : true));
35
+
36
+ // The child function gets wrapped in a memoized observer component
37
+ if (!item && children) {
38
+ // Update the ref so the generated component uses the latest function
39
+ const refChildren = useRef<(value: Observable<T>, id: string | undefined) => ReactElement>();
40
+ refChildren.current = children;
41
+
42
+ item = useMemo(() => observer(({ item$, id }) => refChildren.current!(item$, id)), []);
43
+ } else {
44
+ // @ts-expect-error $$typeof is private
45
+ if (item.$$typeof !== Symbol.for('react.memo')) {
46
+ let memod = autoMemoCache.get(item!);
47
+ if (!memod) {
48
+ memod = memo(item!);
49
+ autoMemoCache.set(item!, memod);
50
+ }
51
+ item = memod;
52
+ }
53
+ }
54
+
55
+ // This early out needs to be after any hooks
56
+ if (!value) return null;
57
+
58
+ // Create the child elements
59
+ const out: ReactElement[] = [];
60
+
61
+ const isArr = isArray(value);
62
+
63
+ if (isArr) {
64
+ // Get the appropriate id field
65
+ const v0 = value[0] as any;
66
+ const node = getNode(each!);
67
+ const length = (value as any[]).length;
68
+
69
+ const idField =
70
+ length > 0
71
+ ? (node && findIDKey(v0, node)) ||
72
+ (v0.id !== undefined ? 'id' : v0.key !== undefined ? 'key' : undefined)
73
+ : undefined;
74
+
75
+ const isIdFieldFunction = isFunction(idField);
76
+
77
+ for (let i = 0; i < length; i++) {
78
+ if (value[i]) {
79
+ const val = value[i];
80
+ const key = (isIdFieldFunction ? idField(val) : (val as Record<string, any>)[idField as string]) ?? i;
81
+ const item$ = (each as Observable<any[]>)[i];
82
+ // TODOV3 Remove item
83
+ const props: ForItemProps<any> & { key: string; item: Observable<any> } = {
84
+ key,
85
+ id: key,
86
+ item$,
87
+ item: item$,
88
+ };
89
+
90
+ out.push(createElement(item as FC, itemProps ? Object.assign(props, itemProps) : props));
91
+ }
92
+ }
93
+ } else {
94
+ // Render the values of the object / Map
95
+ const isMap = value instanceof Map;
96
+ const keys = isMap ? Array.from(value.keys()) : Object.keys(value);
97
+ if (sortValues) {
98
+ keys.sort((A, B) => sortValues(isMap ? value.get(A)! : value[A], isMap ? value.get(B)! : value[B], A, B));
99
+ }
100
+ for (let i = 0; i < keys.length; i++) {
101
+ const key = keys[i];
102
+ if (isMap ? value.get(key) : value[key]) {
103
+ const item$ = isMap ? each!.get(key) : (each as ObservableObject<Record<string, any>>)[key];
104
+ const props: ForItemProps<any> & { key: string; item: Observable<any> } = {
105
+ key,
106
+ id: key,
107
+ item$,
108
+ item: item$,
109
+ };
110
+ out.push(createElement(item as FC, itemProps ? Object.assign(props, itemProps) : props));
111
+ }
112
+ }
113
+ }
114
+
115
+ return out as unknown as ReactElement;
116
+ }
@@ -0,0 +1,4 @@
1
+ import { memo } from 'react';
2
+ import { Computed } from './Computed';
3
+
4
+ export const Memo = memo(Computed, () => true);
@@ -0,0 +1,53 @@
1
+ import { isEmpty, isFunction } from '@legendapp/state';
2
+ import { ComponentClass, FC, createElement, forwardRef } from 'react';
3
+ import { BindKeys } from './reactInterfaces';
4
+ import { reactive } from './reactive-observer';
5
+
6
+ const ReactiveFns = new Map<string, FC | ComponentClass>();
7
+ const ReactiveFnBinders = new Map<string, BindKeys>();
8
+
9
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
10
+ export interface IReactive {}
11
+
12
+ export const Reactive: IReactive = new Proxy(
13
+ {},
14
+ {
15
+ get(target: Record<string, FC>, p: string) {
16
+ if (!target[p]) {
17
+ const Component = ReactiveFns.get(p) || p;
18
+
19
+ // Create a wrapper around createElement with the string so we can proxy it
20
+ // eslint-disable-next-line react/display-name
21
+ const render = forwardRef((props, ref) => {
22
+ const propsOut = { ...props } as any;
23
+ if (ref && (isFunction(ref) || !isEmpty(ref))) {
24
+ propsOut.ref = ref;
25
+ }
26
+ return createElement(Component, propsOut);
27
+ });
28
+
29
+ target[p] = reactive(render, ReactiveFnBinders.get(p));
30
+ }
31
+ return target[p];
32
+ },
33
+ },
34
+ ) as unknown as IReactive;
35
+
36
+ export function configureReactive({
37
+ components,
38
+ binders,
39
+ }: {
40
+ components?: Record<string, FC | ComponentClass<any>>;
41
+ binders?: Record<string, BindKeys>;
42
+ }) {
43
+ if (components) {
44
+ for (const key in components) {
45
+ ReactiveFns.set(key, components[key]);
46
+ }
47
+ }
48
+ if (binders) {
49
+ for (const key in binders) {
50
+ ReactiveFnBinders.set(key, binders[key]);
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,33 @@
1
+ import type { Selector } from '@legendapp/state';
2
+ import { isFunction, isObservableValueReady } from '@legendapp/state';
3
+ import { FC, ReactElement, ReactNode, createElement } from 'react';
4
+ import { useSelector } from './useSelector';
5
+
6
+ interface PropsIf<T> {
7
+ if: Selector<T>;
8
+ ifReady?: never;
9
+ }
10
+ interface PropsIfReady<T> {
11
+ if?: never;
12
+ ifReady: Selector<T>;
13
+ }
14
+
15
+ interface PropsBase<T> {
16
+ else?: ReactNode | (() => ReactNode);
17
+ wrap?: FC;
18
+ children: ReactNode | ((value?: T) => ReactNode);
19
+ }
20
+
21
+ type Props<T> = PropsBase<T> & (PropsIf<T> | PropsIfReady<T>);
22
+
23
+ export function Show<T>(props: Props<T>): ReactElement;
24
+ export function Show<T>({ if: if_, ifReady, else: else_, wrap, children }: Props<T>): ReactElement {
25
+ const value = useSelector(if_ ?? ifReady);
26
+ const show = ifReady !== undefined ? isObservableValueReady(value) : value;
27
+ const child = useSelector(
28
+ show ? (isFunction(children) ? () => children(value) : (children as any)) : else_ ?? null,
29
+ { skipCheck: true },
30
+ );
31
+
32
+ return wrap ? createElement(wrap, undefined, child) : child;
33
+ }
@@ -0,0 +1,43 @@
1
+ import type { Selector } from '@legendapp/state';
2
+ import { ReactElement, ReactNode } from 'react';
3
+ import { useSelector } from './useSelector';
4
+
5
+ export function Switch<T extends object>({
6
+ value,
7
+ children,
8
+ }: {
9
+ value?: Selector<T>;
10
+ children: Partial<Record<keyof T | 'null' | 'undefined' | 'default', () => ReactNode>>;
11
+ }): ReactElement | null;
12
+ export function Switch<T extends string | number | symbol>({
13
+ value,
14
+ children,
15
+ }: {
16
+ value?: Selector<T>;
17
+ children: Partial<Record<T | 'null' | 'undefined' | 'default', () => ReactNode>>;
18
+ }): ReactElement | null;
19
+ export function Switch<T extends boolean>({
20
+ value,
21
+ children,
22
+ }: {
23
+ value?: Selector<T>;
24
+ children: Partial<Record<'false' | 'true' | 'null' | 'undefined' | 'default', () => ReactNode>>;
25
+ }): ReactElement | null;
26
+ export function Switch<T>({
27
+ value,
28
+ children,
29
+ }: {
30
+ value?: Selector<T>;
31
+ children: Partial<Record<'undefined' | 'default', () => ReactNode>>;
32
+ }): ReactElement | null;
33
+ export function Switch<T>({
34
+ value,
35
+ children,
36
+ }: {
37
+ value?: Selector<T>;
38
+ children: Partial<Record<any, () => ReactNode>>;
39
+ }): ReactNode {
40
+ // Select from an object of cases
41
+ const child = children[useSelector(value)!];
42
+ return (child ? child() : children['default']?.()) ?? null;
43
+ }
@@ -0,0 +1,3 @@
1
+ export const reactGlobals = {
2
+ inObserver: false,
3
+ };