@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,30 @@
1
+ import { ObservableSyncGetParams, SyncedOptions, isPromise, type ObservableSyncClass } from '@legendapp/state';
2
+
3
+ export function syncObservableAdapter<T = {}>({ get, set }: SyncedOptions<T>): ObservableSyncClass {
4
+ const ret: ObservableSyncClass = {};
5
+
6
+ if (get) {
7
+ ret.get = (async (params: ObservableSyncGetParams<T>) => {
8
+ try {
9
+ let value = get(params as any);
10
+ if (isPromise(value)) {
11
+ value = await value;
12
+ }
13
+
14
+ params.onChange({
15
+ value,
16
+ lastSync: params.lastSync,
17
+ mode: params.mode!,
18
+ });
19
+ params.onGet();
20
+ // eslint-disable-next-line no-empty
21
+ } catch {}
22
+ }) as ObservableSyncClass['get'];
23
+ }
24
+
25
+ if (set) {
26
+ ret.set = set as unknown as ObservableSyncClass['set'];
27
+ }
28
+
29
+ return ret;
30
+ }
@@ -0,0 +1,20 @@
1
+ import type { Synced, SyncedOptions } from '@legendapp/state';
2
+ import { internal } from '@legendapp/state';
3
+ import { enableActivateSyncedNode } from './activateSyncedNode';
4
+
5
+ const { symbolLinked } = internal;
6
+
7
+ export function synced<T>(params: SyncedOptions<T>): Synced<T> {
8
+ installPersistActivateNode();
9
+ return (() => ({
10
+ [symbolLinked]: { ...params, synced: true },
11
+ })) as any;
12
+ }
13
+
14
+ let didInstall = false;
15
+ function installPersistActivateNode() {
16
+ if (!didInstall) {
17
+ enableActivateSyncedNode();
18
+ didInstall = true;
19
+ }
20
+ }
@@ -0,0 +1,42 @@
1
+ import { Synced, SyncedOptions, SyncedSetParams, isString } from '@legendapp/state';
2
+ import { synced } from '@legendapp/state/persist';
3
+
4
+ export interface SyncedFetchProps extends Omit<SyncedOptions, 'get' | 'set'> {
5
+ get: string | RequestInfo;
6
+ set?: string | RequestInfo;
7
+ getInit?: RequestInit;
8
+ setInit?: RequestInit;
9
+ valueType?: 'arrayBuffer' | 'blob' | 'formData' | 'json' | 'text';
10
+ onSetValueType?: 'arrayBuffer' | 'blob' | 'formData' | 'json' | 'text';
11
+ onSet?: (params: SyncedSetParams<any>) => void;
12
+ }
13
+
14
+ export function syncedFetch<T>({
15
+ get,
16
+ set,
17
+ getInit,
18
+ setInit,
19
+ valueType,
20
+ onSet,
21
+ onSetValueType,
22
+ }: SyncedFetchProps): Synced<T> {
23
+ const ret: SyncedOptions = {
24
+ get: () => fetch(get, getInit).then((response) => response[valueType || 'json']()),
25
+ };
26
+
27
+ if (set) {
28
+ ret.set = async (params: SyncedSetParams<any>) => {
29
+ const requestInfo = isString(set) ? ({ url: set } as RequestInfo) : set;
30
+ const response = await fetch(
31
+ Object.assign({ method: 'POST' }, requestInfo, { body: JSON.stringify(params.value) }),
32
+ setInit,
33
+ );
34
+ if (onSet) {
35
+ params.value = response[onSetValueType || valueType || 'json']();
36
+ onSet(params);
37
+ }
38
+ };
39
+ }
40
+
41
+ return synced(ret);
42
+ }
@@ -0,0 +1,163 @@
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
+ LinkedOptions,
11
+ NodeValue,
12
+ RetryOptions,
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
+ transform?: SyncTransform<T>;
23
+ readonly?: boolean;
24
+ mmkv?: MMKVConfiguration;
25
+ indexedDB?: {
26
+ prefixID?: string;
27
+ itemID?: string;
28
+ };
29
+ options?: any;
30
+ }
31
+
32
+ export interface SyncedGetParams {
33
+ value: any;
34
+ lastSync: number | undefined;
35
+ updateLastSync: (lastSync: number) => void;
36
+ setMode: (mode: GetMode) => void;
37
+ refresh: () => void;
38
+ }
39
+
40
+ export type SyncedSetParams<T> = SetParams<T> & {
41
+ node: NodeValue;
42
+ valuePrevious: T;
43
+ update: UpdateFn;
44
+ refresh: () => void;
45
+ cancelRetry: () => void;
46
+ retryNum: number;
47
+ fromSubscribe: boolean | undefined;
48
+ };
49
+
50
+ export type GetMode = 'set' | 'assign' | 'merge' | 'append' | 'prepend';
51
+
52
+ export interface SyncedOptions<T = any> extends Omit<LinkedOptions<T>, 'get' | 'set'> {
53
+ get?: (params: SyncedGetParams) => Promise<T> | T;
54
+ set?: (params: SyncedSetParams<T>) => void | Promise<any>;
55
+ subscribe?: (params: { node: NodeValue; update: UpdateFn; refresh: () => void }) => void;
56
+ retry?: RetryOptions;
57
+ offlineBehavior?: false | 'retry';
58
+ persist?: PersistOptions<any>;
59
+ debounceSet?: number;
60
+ syncMode?: 'auto' | 'manual';
61
+ mode?: GetMode;
62
+ transform?: SyncTransform<T>;
63
+ // Not implemented yet
64
+ enableSync?: boolean;
65
+ onGetError?: (error: Error) => void;
66
+ onSetError?: (error: Error) => void;
67
+ log?: (message?: any, ...optionalParams: any[]) => void;
68
+ onBeforeSet?: () => void;
69
+ onAfterSet?: () => void;
70
+ allowSetIfGetError?: boolean;
71
+ }
72
+
73
+ export interface SyncedOptionsGlobal<T = any> extends Omit<SyncedOptions<T>, 'get' | 'set' | 'persist'> {
74
+ persist?: ObservablePersistPluginOptions & { plugin?: ClassConstructor<ObservablePersistPlugin, T[]> };
75
+ }
76
+
77
+ export interface ObservablePersistPluginOptions {
78
+ onGetError?: (error: Error) => void;
79
+ onSetError?: (error: Error) => void;
80
+ indexedDB?: {
81
+ databaseName: string;
82
+ version: number;
83
+ tableNames: string[];
84
+ };
85
+ asyncStorage?: {
86
+ AsyncStorage: AsyncStorageStatic;
87
+ preload?: boolean | string[];
88
+ };
89
+ }
90
+ export interface ObservablePersistPlugin {
91
+ initialize?(config: ObservablePersistPluginOptions): void | Promise<void>;
92
+ loadTable?(table: string, config: PersistOptions): Promise<any> | void;
93
+ getTable<T = any>(table: string, init: object, config: PersistOptions): T;
94
+ set(table: string, changes: Change[], config: PersistOptions): Promise<any> | void;
95
+ deleteTable(table: string, config: PersistOptions): Promise<any> | void;
96
+ getMetadata(table: string, config: PersistOptions): PersistMetadata;
97
+ setMetadata(table: string, metadata: PersistMetadata, config: PersistOptions): Promise<any> | void;
98
+ deleteMetadata(table: string, config: PersistOptions): Promise<any> | void;
99
+ }
100
+ export interface PersistMetadata {
101
+ id?: '__legend_metadata';
102
+ // modified ?: number;
103
+ lastSync?: number;
104
+ pending?: any;
105
+ }
106
+ export interface SyncTransform<TOrig = any, TSaved = TOrig> {
107
+ load?: (value: TSaved) => TOrig | Promise<TOrig>;
108
+ save?: (value: TOrig) => TSaved | Promise<TSaved>;
109
+ }
110
+ export interface ObservableSyncStateBase {
111
+ isPersistLoaded: boolean;
112
+ isPersistEnabled: boolean;
113
+ isEnabledRemote: boolean;
114
+ lastSync?: number;
115
+ syncCount?: number;
116
+ clearPersist: () => Promise<void>;
117
+ sync: () => Promise<void>;
118
+ getPendingChanges: () =>
119
+ | Record<
120
+ string,
121
+ {
122
+ p: any;
123
+ v?: any;
124
+ }
125
+ >
126
+ | undefined;
127
+ }
128
+ export type ObservableSyncState = ObservableState & ObservableSyncStateBase;
129
+
130
+ export interface ObservableSyncSetParams<T> {
131
+ syncState: Observable<ObservableSyncState>;
132
+ obs: ObservableParam<T>;
133
+ options: SyncedOptions<T>;
134
+ changes: Change[];
135
+ value: T;
136
+ valuePrevious: T;
137
+ }
138
+ export interface ObservableSyncGetParams<T> {
139
+ state: Observable<ObservableSyncState>;
140
+ obs: ObservableParam<T>;
141
+ options: SyncedOptions<T>;
142
+ dateModified?: number;
143
+ lastSync?: number;
144
+ mode?: GetMode;
145
+ onGet: () => void;
146
+ onError: (error: Error) => void;
147
+ onChange: (params: UpdateFnParams) => void | Promise<void>;
148
+ }
149
+ export type ObservableSyncRemoteGetFnParams<T> = Omit<ObservableSyncGetParams<T>, 'onGet'>;
150
+
151
+ export interface ObservableSyncClass {
152
+ get?<T>(params: ObservableSyncGetParams<T>): void;
153
+ set?<T>(
154
+ params: ObservableSyncSetParams<T>,
155
+ ): void | Promise<void | { changes?: object; dateModified?: number; lastSync?: number; pathStrs?: string[] }>;
156
+ }
157
+
158
+ export interface ObservableSyncFunctions<T = any> {
159
+ get?(params: ObservableSyncRemoteGetFnParams<T>): T | Promise<T>;
160
+ set?(
161
+ params: ObservableSyncSetParams<T>,
162
+ ): void | Promise<void | { changes?: object | undefined; dateModified?: number; lastSync?: number }>;
163
+ }
@@ -0,0 +1,11 @@
1
+ import type { NodeValue } from '@legendapp/state';
2
+
3
+ export function getNodePath(node: NodeValue) {
4
+ const arr: (string | number)[] = [];
5
+ let n = node;
6
+ while (n?.key !== undefined) {
7
+ arr.splice(0, 0, n.key);
8
+ n = n.parent;
9
+ }
10
+ return arr.join('.');
11
+ }
@@ -0,0 +1,34 @@
1
+ import { NodeValue, internal, TrackingNode } from '@legendapp/state';
2
+ import { getNodePath } from './traceHelpers';
3
+ const { optimized, tracking } = internal;
4
+
5
+ export function useTraceListeners(this: any, name?: string) {
6
+ if (process.env.NODE_ENV === 'development' && tracking.current) {
7
+ tracking.current.traceListeners = traceNodes.bind(this, name);
8
+ }
9
+ }
10
+
11
+ function traceNodes(name: string | undefined, nodes: Map<NodeValue, TrackingNode>) {
12
+ if (process.env.NODE_ENV === 'development' && tracking.current) {
13
+ tracking.current.traceListeners = undefined;
14
+ const arr: string[] = [];
15
+ if (nodes) {
16
+ for (const tracked of nodes.values()) {
17
+ const { node, track } = tracked;
18
+ const shallow = track === true;
19
+ const isOptimized = track === optimized;
20
+ arr.push(
21
+ `${arr.length + 1}: ${getNodePath(node)}${shallow ? ' (shallow)' : ''}${
22
+ isOptimized ? ' (optimized)' : ''
23
+ }`,
24
+ );
25
+ }
26
+ }
27
+
28
+ console.log(
29
+ `[legend-state] ${name ? name + ' ' : ''}tracking ${arr.length} observable${
30
+ arr.length !== 1 ? 's' : ''
31
+ }:\n${arr.join('\n')}`,
32
+ );
33
+ }
34
+ }
@@ -0,0 +1,24 @@
1
+ import { ListenerParams, internal } from '@legendapp/state';
2
+ const { tracking } = internal;
3
+
4
+ export function useTraceUpdates(name?: string) {
5
+ if (process.env.NODE_ENV === 'development' && tracking.current) {
6
+ tracking.current.traceUpdates = replaceUpdateFn.bind(undefined, name);
7
+ }
8
+ }
9
+
10
+ function replaceUpdateFn(name: string | undefined, updateFn: Function) {
11
+ return onChange.bind(undefined, name, updateFn);
12
+ }
13
+
14
+ function onChange(name: string | undefined, updateFn: Function, params: ListenerParams<any>) {
15
+ const { changes } = params;
16
+ if (process.env.NODE_ENV === 'development') {
17
+ changes.forEach(({ path, valueAtPath, prevAtPath }) => {
18
+ console.log(`[legend-state] Rendering ${name ? name + ' ' : ''}because "${path}" changed:
19
+ from: ${JSON.stringify(prevAtPath)}
20
+ to: ${JSON.stringify(valueAtPath)}`);
21
+ });
22
+ return updateFn();
23
+ }
24
+ }
@@ -0,0 +1,33 @@
1
+ import { internal, NodeValue, TrackingNode } from '@legendapp/state';
2
+ import { getNodePath } from './traceHelpers';
3
+ const { optimized, tracking } = internal;
4
+
5
+ export function useVerifyNotTracking(this: any, name?: string) {
6
+ if (process.env.NODE_ENV === 'development') {
7
+ tracking.current!.traceListeners = traceNodes.bind(this, name);
8
+ }
9
+ }
10
+
11
+ function traceNodes(name: string | undefined, nodes: Map<NodeValue, TrackingNode>) {
12
+ if (process.env.NODE_ENV === 'development') {
13
+ tracking.current!.traceListeners = undefined;
14
+ const arr: string[] = [];
15
+ if (nodes) {
16
+ for (const tracked of nodes.values()) {
17
+ const { node, track } = tracked;
18
+ const shallow = track === true;
19
+ const isOptimized = track === optimized;
20
+ arr.push(
21
+ `${arr.length + 1}: ${getNodePath(node)}${shallow ? ' (shallow)' : ''}${
22
+ isOptimized ? ' (optimized)' : ''
23
+ }`,
24
+ );
25
+ }
26
+ console.error(
27
+ `[legend-state] ${name ? name + ' ' : ''}tracking ${arr.length} observable${
28
+ arr.length !== 1 ? 's' : ''
29
+ } when it should not be:\n${arr.join('\n')}`,
30
+ );
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,10 @@
1
+ import { useRef } from 'react';
2
+
3
+ export function useVerifyOneRender(name?: string) {
4
+ if (process.env.NODE_ENV === 'development') {
5
+ const numRenders = ++useRef(0).current;
6
+ if (numRenders > 1) {
7
+ console.error(`[legend-state] ${name ? name + ' ' : ''}Component rendered more than once`);
8
+ }
9
+ }
10
+ }
@@ -0,0 +1,52 @@
1
+ import { computeSelector } from './helpers';
2
+ import type { ListenerParams, ObserveEvent, Selector } from './observableInterfaces';
3
+ import type { ObserveOptions } from './observe';
4
+ import { setupTracking } from './setupTracking';
5
+ import { beginTracking, endTracking, tracking } from './tracking';
6
+
7
+ export function trackSelector<T>(
8
+ selector: Selector<T>,
9
+ update: (params: ListenerParams) => void,
10
+ observeEvent?: ObserveEvent<T>,
11
+ observeOptions?: ObserveOptions,
12
+ createResubscribe?: boolean,
13
+ ) {
14
+ let dispose: undefined | (() => void);
15
+ let resubscribe: (() => () => void) | undefined;
16
+ let updateFn = update;
17
+
18
+ beginTracking();
19
+ const value = selector ? computeSelector(selector, observeEvent, observeOptions?.fromComputed) : selector;
20
+ const tracker = tracking.current;
21
+ const nodes = tracker!.nodes;
22
+ endTracking();
23
+
24
+ if ((process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') && tracker && nodes) {
25
+ tracker.traceListeners?.(nodes);
26
+ if (tracker.traceUpdates) {
27
+ updateFn = tracker.traceUpdates(update) as () => void;
28
+ }
29
+ // Clear tracing so it doesn't leak to other components
30
+ tracker.traceListeners = undefined;
31
+ tracker.traceUpdates = undefined;
32
+ }
33
+
34
+ if (!observeEvent?.cancel) {
35
+ // Do tracing if it was requested
36
+
37
+ // useSyncExternalStore doesn't subscribe until after the component mount.
38
+ // We want to subscribe immediately so we don't miss any updates
39
+ dispose = setupTracking(nodes, updateFn, false, observeOptions?.immediate);
40
+ if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
41
+ resubscribe = createResubscribe
42
+ ? () => {
43
+ dispose?.();
44
+ dispose = setupTracking(nodes, updateFn);
45
+ return dispose;
46
+ }
47
+ : undefined;
48
+ }
49
+ }
50
+
51
+ return { nodes, value, dispose, resubscribe };
52
+ }
@@ -0,0 +1,43 @@
1
+ import type { NodeValue, TrackingState, TrackingType } from './observableInterfaces';
2
+
3
+ let trackCount = 0;
4
+ const trackingQueue: (TrackingState | undefined)[] = [];
5
+
6
+ export const tracking = {
7
+ current: undefined as TrackingState | undefined,
8
+ };
9
+
10
+ export function beginTracking() {
11
+ // Keep a copy of the previous tracking context so it can be restored
12
+ // when this context is complete
13
+ trackingQueue.push(tracking.current);
14
+ trackCount++;
15
+ tracking.current = {};
16
+ }
17
+ export function endTracking() {
18
+ // Restore the previous tracking context
19
+ trackCount--;
20
+ if (trackCount < 0) {
21
+ trackCount = 0;
22
+ }
23
+ tracking.current = trackingQueue.pop();
24
+ }
25
+
26
+ export function updateTracking(node: NodeValue, track?: TrackingType) {
27
+ if (trackCount) {
28
+ const tracker = tracking.current;
29
+ if (tracker) {
30
+ if (!tracker.nodes) {
31
+ tracker.nodes = new Map();
32
+ }
33
+
34
+ const existing = tracker.nodes.get(node);
35
+ if (existing) {
36
+ existing.track = existing.track || track;
37
+ existing.num++;
38
+ } else {
39
+ tracker.nodes.set(node, { node, track, num: 1 });
40
+ }
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,12 @@
1
+ import type { ObservableParam } from '@legendapp/state';
2
+ import { ReactNode } from 'react';
3
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
4
+ import type { Computed, Memo } from '@legendapp/state/react';
5
+ declare module '@legendapp/state/react' {
6
+ export declare const Computed: (props: {
7
+ children: ObservableParam | (() => ReactNode) | ReactNode;
8
+ }) => React.ReactElement;
9
+ export declare const Memo: (props: {
10
+ children: ObservableParam | (() => ReactNode) | ReactNode;
11
+ }) => React.ReactElement;
12
+ }
package/src/when.ts ADDED
@@ -0,0 +1,70 @@
1
+ import { computeSelector, isObservableValueReady } from './helpers';
2
+ import { isPromise } from './is';
3
+ import type { ObserveEvent, Selector } from './observableInterfaces';
4
+ import { observe } from './observe';
5
+
6
+ function _when<T, T2>(predicate: Selector<T>, effect?: (value: T) => T2, checkReady?: boolean): any {
7
+ // If predicate is a regular Promise skip all the observable stuff
8
+ if (isPromise<T>(predicate)) {
9
+ return effect ? predicate.then(effect) : (predicate as any);
10
+ }
11
+
12
+ let value: T | undefined;
13
+ let effectValue: T2 | undefined;
14
+
15
+ // Create a wrapping fn that calls the effect if predicate returns true
16
+ function run(e: ObserveEvent<T>) {
17
+ const ret = computeSelector(predicate);
18
+
19
+ if (!isPromise(ret) && (checkReady ? isObservableValueReady(ret) : ret)) {
20
+ value = ret;
21
+
22
+ // Set cancel so that observe does not track anymore
23
+ e.cancel = true;
24
+ }
25
+
26
+ return value;
27
+ }
28
+ function doEffect() {
29
+ // If value is truthy then run the effect
30
+ effectValue = effect?.(value!);
31
+ }
32
+ // Run in an observe
33
+ observe(run, doEffect);
34
+
35
+ // If first run resulted in a truthy value just return it.
36
+ // It will have set e.cancel so no need to dispose
37
+ if (isPromise<T>(value)) {
38
+ return effect ? value.then(effect) : (value as any);
39
+ } else if (value !== undefined) {
40
+ return effect ? effectValue : Promise.resolve(value);
41
+ } else {
42
+ // Wrap it in a promise
43
+ const promise = new Promise<T2>((resolve) => {
44
+ if (effect) {
45
+ const originalEffect = effect;
46
+ effect = ((value: T) => {
47
+ const effectValue = originalEffect(value);
48
+ resolve(isPromise(effectValue) ? effectValue.then((value) => value as T2) : effectValue);
49
+ }) as any;
50
+ } else {
51
+ effect = resolve as any;
52
+ }
53
+ });
54
+
55
+ return promise;
56
+ }
57
+ }
58
+
59
+ export function when<T, T2>(predicate: Promise<T>, effect: (value: T) => T2): Promise<T2>;
60
+ export function when<T, T2>(predicate: Selector<T>, effect: (value: T) => T2): Promise<T2>;
61
+ export function when<T>(predicate: Selector<T>): Promise<T>;
62
+ export function when<T, T2>(predicate: Selector<T>, effect?: (value: T) => T2): Promise<T | T2> {
63
+ return _when<T, T2>(predicate, effect, false);
64
+ }
65
+ export function whenReady<T, T2>(predicate: Promise<T>, effect: (value: T) => T2): Promise<T2>;
66
+ export function whenReady<T, T2>(predicate: Selector<T>, effect: (value: T) => T2): Promise<T2>;
67
+ export function whenReady<T>(predicate: Selector<T>): Promise<T>;
68
+ export function whenReady<T, T2>(predicate: Selector<T>, effect?: (value: T) => T2): Promise<T | T2> {
69
+ return _when<T, T2>(predicate, effect, true);
70
+ }
@@ -0,0 +1,11 @@
1
+ import { Synced, SyncedOptions, SyncedSetParams } from '@legendapp/state';
2
+ export interface SyncedFetchProps extends Omit<SyncedOptions, 'get' | 'set'> {
3
+ get: string | RequestInfo;
4
+ set?: string | RequestInfo;
5
+ getInit?: RequestInit;
6
+ setInit?: RequestInit;
7
+ valueType?: 'arrayBuffer' | 'blob' | 'formData' | 'json' | 'text';
8
+ onSetValueType?: 'arrayBuffer' | 'blob' | 'formData' | 'json' | 'text';
9
+ onSet?: (params: SyncedSetParams<any>) => void;
10
+ }
11
+ export declare function syncedFetch<T>({ get, set, getInit, setInit, valueType, onSet, onSetValueType, }: SyncedFetchProps): Synced<T>;
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ var state = require('@legendapp/state');
4
+ var persist = require('@legendapp/state/persist');
5
+
6
+ function syncedFetch({ get, set, getInit, setInit, valueType, onSet, onSetValueType, }) {
7
+ const ret = {
8
+ get: () => fetch(get, getInit).then((response) => response[valueType || 'json']()),
9
+ };
10
+ if (set) {
11
+ ret.set = async (params) => {
12
+ const requestInfo = state.isString(set) ? { url: set } : set;
13
+ const response = await fetch(Object.assign({ method: 'POST' }, requestInfo, { body: JSON.stringify(params.value) }), setInit);
14
+ if (onSet) {
15
+ params.value = response[onSetValueType || valueType || 'json']();
16
+ onSet(params);
17
+ }
18
+ };
19
+ }
20
+ return persist.synced(ret);
21
+ }
22
+
23
+ exports.syncedFetch = syncedFetch;
24
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sources":["../src/sync-plugins/fetch.ts"],"sourcesContent":[null],"names":["isString","synced"],"mappings":";;;;;SAagB,WAAW,CAAI,EAC3B,GAAG,EACH,GAAG,EACH,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,EACL,cAAc,GACC,EAAA;AACf,IAAA,MAAM,GAAG,GAAkB;QACvB,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;KACrF,CAAC;IAEF,IAAI,GAAG,EAAE;AACL,QAAA,GAAG,CAAC,GAAG,GAAG,OAAO,MAA4B,KAAI;AAC7C,YAAA,MAAM,WAAW,GAAGA,cAAQ,CAAC,GAAG,CAAC,GAAI,EAAE,GAAG,EAAE,GAAG,EAAkB,GAAG,GAAG,CAAC;AACxE,YAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CACxB,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EACtF,OAAO,CACV,CAAC;YACF,IAAI,KAAK,EAAE;AACP,gBAAA,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,cAAc,IAAI,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;gBACjE,KAAK,CAAC,MAAM,CAAC,CAAC;aACjB;AACL,SAAC,CAAC;KACL;AAED,IAAA,OAAOC,cAAM,CAAC,GAAG,CAAC,CAAC;AACvB;;;;"}
@@ -0,0 +1,22 @@
1
+ import { isString } from '@legendapp/state';
2
+ import { synced } from '@legendapp/state/persist';
3
+
4
+ function syncedFetch({ get, set, getInit, setInit, valueType, onSet, onSetValueType, }) {
5
+ const ret = {
6
+ get: () => fetch(get, getInit).then((response) => response[valueType || 'json']()),
7
+ };
8
+ if (set) {
9
+ ret.set = async (params) => {
10
+ const requestInfo = isString(set) ? { url: set } : set;
11
+ const response = await fetch(Object.assign({ method: 'POST' }, requestInfo, { body: JSON.stringify(params.value) }), setInit);
12
+ if (onSet) {
13
+ params.value = response[onSetValueType || valueType || 'json']();
14
+ onSet(params);
15
+ }
16
+ };
17
+ }
18
+ return synced(ret);
19
+ }
20
+
21
+ export { syncedFetch };
22
+ //# sourceMappingURL=fetch.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.mjs","sources":["../src/sync-plugins/fetch.ts"],"sourcesContent":[null],"names":[],"mappings":";;;SAagB,WAAW,CAAI,EAC3B,GAAG,EACH,GAAG,EACH,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,EACL,cAAc,GACC,EAAA;AACf,IAAA,MAAM,GAAG,GAAkB;QACvB,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;KACrF,CAAC;IAEF,IAAI,GAAG,EAAE;AACL,QAAA,GAAG,CAAC,GAAG,GAAG,OAAO,MAA4B,KAAI;AAC7C,YAAA,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAI,EAAE,GAAG,EAAE,GAAG,EAAkB,GAAG,GAAG,CAAC;AACxE,YAAA,MAAM,QAAQ,GAAG,MAAM,KAAK,CACxB,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,EACtF,OAAO,CACV,CAAC;YACF,IAAI,KAAK,EAAE;AACP,gBAAA,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC,cAAc,IAAI,SAAS,IAAI,MAAM,CAAC,EAAE,CAAC;gBACjE,KAAK,CAAC,MAAM,CAAC,CAAC;aACjB;AACL,SAAC,CAAC;KACL;AAED,IAAA,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACvB;;;;"}
package/sync.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import type { SyncedOptionsGlobal } from '@legendapp/state';
2
+ export { configureObservableSync } from './src/sync/configureObservableSync';
3
+ export { mapSyncPlugins, syncObservable } from './src/sync/syncObservable';
4
+ export { synced } from './src/sync/synced';
5
+ export declare function isInRemoteChange(): boolean;
6
+ export declare const internal: {
7
+ observableSyncConfiguration: SyncedOptionsGlobal;
8
+ };