@legendapp/state 2.2.0-next.8 → 2.2.0-next.80

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 (321) 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 +34 -32
  14. package/config/enableReactTracking.js.map +1 -1
  15. package/config/enableReactTracking.mjs +35 -33
  16. package/config/enableReactTracking.mjs.map +1 -1
  17. package/config/enableReactUse.d.ts +1 -1
  18. package/config/enableReactUse.js +9 -1
  19. package/config/enableReactUse.js.map +1 -1
  20. package/config/enableReactUse.mjs +9 -1
  21. package/config/enableReactUse.mjs.map +1 -1
  22. package/config/enable_peek.d.ts +8 -0
  23. package/config/{enableDirectPeek.js → enable_peek.js} +6 -3
  24. package/config/enable_peek.js.map +1 -0
  25. package/config/{enableDirectPeek.mjs → enable_peek.mjs} +5 -3
  26. package/config/enable_peek.mjs.map +1 -0
  27. package/helpers/fetch.d.ts +4 -3
  28. package/helpers/fetch.js.map +1 -1
  29. package/helpers/fetch.mjs.map +1 -1
  30. package/helpers/pageHash.js.map +1 -1
  31. package/helpers/pageHash.mjs.map +1 -1
  32. package/helpers/pageHashParams.js.map +1 -1
  33. package/helpers/pageHashParams.mjs.map +1 -1
  34. package/helpers/time.d.ts +2 -2
  35. package/helpers/time.js.map +1 -1
  36. package/helpers/time.mjs.map +1 -1
  37. package/history.js +2 -2
  38. package/history.js.map +1 -1
  39. package/history.mjs +3 -3
  40. package/history.mjs.map +1 -1
  41. package/index.d.ts +29 -9
  42. package/index.js +964 -671
  43. package/index.js.map +1 -1
  44. package/index.mjs +959 -668
  45. package/index.mjs.map +1 -1
  46. package/package.json +37 -25
  47. package/persist-plugins/async-storage.d.ts +4 -3
  48. package/persist-plugins/async-storage.js +8 -7
  49. package/persist-plugins/async-storage.js.map +1 -1
  50. package/persist-plugins/async-storage.mjs +9 -8
  51. package/persist-plugins/async-storage.mjs.map +1 -1
  52. package/persist-plugins/fetch.d.ts +1 -1
  53. package/persist-plugins/fetch.js.map +1 -1
  54. package/persist-plugins/fetch.mjs.map +1 -1
  55. package/persist-plugins/firebase.d.ts +2 -2
  56. package/persist-plugins/firebase.js +12 -11
  57. package/persist-plugins/firebase.js.map +1 -1
  58. package/persist-plugins/firebase.mjs +13 -12
  59. package/persist-plugins/firebase.mjs.map +1 -1
  60. package/persist-plugins/indexeddb.d.ts +11 -10
  61. package/persist-plugins/indexeddb.js +2 -2
  62. package/persist-plugins/indexeddb.js.map +1 -1
  63. package/persist-plugins/indexeddb.mjs +2 -2
  64. package/persist-plugins/indexeddb.mjs.map +1 -1
  65. package/persist-plugins/local-storage.d.ts +4 -4
  66. package/persist-plugins/local-storage.js +19 -7
  67. package/persist-plugins/local-storage.js.map +1 -1
  68. package/persist-plugins/local-storage.mjs +20 -9
  69. package/persist-plugins/local-storage.mjs.map +1 -1
  70. package/persist-plugins/mmkv.d.ts +9 -8
  71. package/persist-plugins/mmkv.js +5 -4
  72. package/persist-plugins/mmkv.js.map +1 -1
  73. package/persist-plugins/mmkv.mjs +6 -5
  74. package/persist-plugins/mmkv.mjs.map +1 -1
  75. package/persist-plugins/query.d.ts +1 -1
  76. package/persist-plugins/query.js.map +1 -1
  77. package/persist-plugins/query.mjs.map +1 -1
  78. package/persist.d.ts +2 -14
  79. package/persist.js +1270 -269
  80. package/persist.js.map +1 -1
  81. package/persist.mjs +1270 -270
  82. package/persist.mjs.map +1 -1
  83. package/react-hooks/createObservableHook.js +1 -1
  84. package/react-hooks/createObservableHook.js.map +1 -1
  85. package/react-hooks/createObservableHook.mjs +1 -1
  86. package/react-hooks/createObservableHook.mjs.map +1 -1
  87. package/react-hooks/useFetch.d.ts +4 -3
  88. package/react-hooks/useFetch.js.map +1 -1
  89. package/react-hooks/useFetch.mjs.map +1 -1
  90. package/react-hooks/useHover.js.map +1 -1
  91. package/react-hooks/useHover.mjs.map +1 -1
  92. package/react-hooks/useMeasure.js.map +1 -1
  93. package/react-hooks/useMeasure.mjs.map +1 -1
  94. package/react-hooks/useObservableNextRouter.js.map +1 -1
  95. package/react-hooks/useObservableNextRouter.mjs.map +1 -1
  96. package/react-hooks/useObservableQuery.js.map +1 -1
  97. package/react-hooks/useObservableQuery.mjs.map +1 -1
  98. package/react-hooks/usePersistedObservable.d.ts +6 -3
  99. package/react-hooks/usePersistedObservable.js +5 -2
  100. package/react-hooks/usePersistedObservable.js.map +1 -1
  101. package/react-hooks/usePersistedObservable.mjs +5 -2
  102. package/react-hooks/usePersistedObservable.mjs.map +1 -1
  103. package/react.js +73 -93
  104. package/react.js.map +1 -1
  105. package/react.mjs +73 -93
  106. package/react.mjs.map +1 -1
  107. package/src/ObservableObject.ts +1217 -0
  108. package/src/ObservablePrimitive.ts +62 -0
  109. package/src/babel/index.ts +70 -0
  110. package/src/batching.ts +378 -0
  111. package/src/computed.ts +18 -0
  112. package/src/config/enable$get.ts +30 -0
  113. package/src/config/enableReactComponents.ts +26 -0
  114. package/src/config/enableReactNativeComponents.ts +102 -0
  115. package/src/config/enableReactTracking.ts +62 -0
  116. package/src/config/enableReactUse.ts +32 -0
  117. package/src/config/enable_peek.ts +31 -0
  118. package/src/config.ts +47 -0
  119. package/src/createObservable.ts +46 -0
  120. package/src/event.ts +26 -0
  121. package/src/globals.ts +234 -0
  122. package/src/helpers/fetch.ts +26 -0
  123. package/src/helpers/pageHash.ts +41 -0
  124. package/src/helpers/pageHashParams.ts +55 -0
  125. package/src/helpers/time.ts +30 -0
  126. package/src/helpers.ts +224 -0
  127. package/src/history/trackHistory.ts +29 -0
  128. package/src/history/undoRedo.ts +111 -0
  129. package/src/is.ts +63 -0
  130. package/src/linked.ts +6 -0
  131. package/src/observable.ts +32 -0
  132. package/src/observableInterfaces.ts +148 -0
  133. package/src/observableTypes.ts +226 -0
  134. package/src/observe.ts +89 -0
  135. package/src/onChange.ts +136 -0
  136. package/src/persist/configureObservablePersistence.ts +7 -0
  137. package/src/persist/fieldTransformer.ts +149 -0
  138. package/src/persist/observablePersistRemoteFunctionsAdapter.ts +39 -0
  139. package/src/persist/persistObservable.ts +1031 -0
  140. package/src/persist-plugins/async-storage.ts +102 -0
  141. package/src/persist-plugins/fetch.ts +34 -0
  142. package/src/persist-plugins/firebase.ts +1052 -0
  143. package/src/persist-plugins/indexeddb.ts +432 -0
  144. package/src/persist-plugins/local-storage.ts +91 -0
  145. package/src/persist-plugins/mmkv.ts +91 -0
  146. package/src/persist-plugins/query.ts +129 -0
  147. package/src/proxy.ts +28 -0
  148. package/src/react/Computed.tsx +7 -0
  149. package/src/react/For.tsx +116 -0
  150. package/src/react/Memo.tsx +4 -0
  151. package/src/react/Reactive.tsx +53 -0
  152. package/src/react/Show.tsx +33 -0
  153. package/src/react/Switch.tsx +43 -0
  154. package/src/react/react-globals.ts +3 -0
  155. package/src/react/{reactInterfaces.d.ts → reactInterfaces.ts} +15 -7
  156. package/src/react/reactive-observer.tsx +210 -0
  157. package/src/react/useComputed.ts +36 -0
  158. package/src/react/useEffectOnce.ts +41 -0
  159. package/src/react/useIsMounted.ts +16 -0
  160. package/src/react/useMount.ts +15 -0
  161. package/src/react/useObservable.ts +24 -0
  162. package/src/react/useObservableReducer.ts +52 -0
  163. package/src/react/useObservableState.ts +30 -0
  164. package/src/react/useObserve.ts +54 -0
  165. package/src/react/useObserveEffect.ts +40 -0
  166. package/src/react/usePauseProvider.tsx +13 -0
  167. package/src/react/useSelector.ts +167 -0
  168. package/src/react/useUnmount.ts +8 -0
  169. package/src/react/useWhen.ts +9 -0
  170. package/src/react-hooks/createObservableHook.ts +53 -0
  171. package/src/react-hooks/useFetch.ts +16 -0
  172. package/src/react-hooks/useHover.ts +40 -0
  173. package/src/react-hooks/useMeasure.ts +48 -0
  174. package/src/react-hooks/useObservableNextRouter.ts +137 -0
  175. package/src/react-hooks/useObservableQuery.ts +205 -0
  176. package/src/react-hooks/usePersistedObservable.ts +25 -0
  177. package/src/retry.ts +71 -0
  178. package/src/setupTracking.ts +26 -0
  179. package/src/sync/activateSyncedNode.ts +128 -0
  180. package/src/sync/configureObservableSync.ts +7 -0
  181. package/src/sync/persistTypes.ts +226 -0
  182. package/src/sync/syncHelpers.ts +56 -0
  183. package/src/sync/syncObservable.ts +1040 -0
  184. package/src/sync/syncObservableAdapter.ts +31 -0
  185. package/src/sync/syncTypes.ts +188 -0
  186. package/src/sync/synced.ts +20 -0
  187. package/src/sync-plugins/crud.ts +404 -0
  188. package/src/sync-plugins/fetch.ts +72 -0
  189. package/src/sync-plugins/keel.ts +452 -0
  190. package/src/sync-plugins/supabase.ts +261 -0
  191. package/src/trace/traceHelpers.ts +11 -0
  192. package/src/trace/useTraceListeners.ts +34 -0
  193. package/src/trace/useTraceUpdates.ts +24 -0
  194. package/src/trace/useVerifyNotTracking.ts +33 -0
  195. package/src/trace/useVerifyOneRender.ts +10 -0
  196. package/src/trackSelector.ts +52 -0
  197. package/src/tracking.ts +43 -0
  198. package/src/types/babel.d.ts +12 -0
  199. package/src/when.ts +75 -0
  200. package/sync-plugins/crud.d.ts +41 -0
  201. package/sync-plugins/crud.js +290 -0
  202. package/sync-plugins/crud.js.map +1 -0
  203. package/sync-plugins/crud.mjs +286 -0
  204. package/sync-plugins/crud.mjs.map +1 -0
  205. package/sync-plugins/fetch.d.ts +13 -0
  206. package/sync-plugins/fetch.js +46 -0
  207. package/sync-plugins/fetch.js.map +1 -0
  208. package/sync-plugins/fetch.mjs +44 -0
  209. package/sync-plugins/fetch.mjs.map +1 -0
  210. package/sync-plugins/keel.d.ts +91 -0
  211. package/sync-plugins/keel.js +277 -0
  212. package/sync-plugins/keel.js.map +1 -0
  213. package/sync-plugins/keel.mjs +273 -0
  214. package/sync-plugins/keel.mjs.map +1 -0
  215. package/sync-plugins/supabase.d.ts +36 -0
  216. package/sync-plugins/supabase.js +152 -0
  217. package/sync-plugins/supabase.js.map +1 -0
  218. package/sync-plugins/supabase.mjs +149 -0
  219. package/sync-plugins/supabase.mjs.map +1 -0
  220. package/sync.d.ts +11 -0
  221. package/sync.js +976 -0
  222. package/sync.js.map +1 -0
  223. package/sync.mjs +966 -0
  224. package/sync.mjs.map +1 -0
  225. package/trace.js +13 -10
  226. package/trace.js.map +1 -1
  227. package/trace.mjs +11 -8
  228. package/trace.mjs.map +1 -1
  229. package/types/babel.d.ts +3 -3
  230. package/config/enableDirectAccess.d.ts +0 -7
  231. package/config/enableDirectAccess.js +0 -25
  232. package/config/enableDirectAccess.js.map +0 -1
  233. package/config/enableDirectAccess.mjs +0 -23
  234. package/config/enableDirectAccess.mjs.map +0 -1
  235. package/config/enableDirectPeek.d.ts +0 -7
  236. package/config/enableDirectPeek.js.map +0 -1
  237. package/config/enableDirectPeek.mjs.map +0 -1
  238. package/config/enableReactDirectRender.d.ts +0 -2
  239. package/config/enableReactDirectRender.js +0 -78
  240. package/config/enableReactDirectRender.js.map +0 -1
  241. package/config/enableReactDirectRender.mjs +0 -75
  242. package/config/enableReactDirectRender.mjs.map +0 -1
  243. package/src/ObservableObject.d.ts +0 -14
  244. package/src/ObservablePrimitive.d.ts +0 -7
  245. package/src/babel/index.d.ts +0 -17
  246. package/src/batching.d.ts +0 -6
  247. package/src/computed.d.ts +0 -4
  248. package/src/config/enableDirectAccess.d.ts +0 -7
  249. package/src/config/enableDirectPeek.d.ts +0 -7
  250. package/src/config/enableReactComponents.d.ts +0 -7
  251. package/src/config/enableReactDirectRender.d.ts +0 -2
  252. package/src/config/enableReactNativeComponents.d.ts +0 -20
  253. package/src/config/enableReactTracking.d.ts +0 -15
  254. package/src/config/enableReactUse.d.ts +0 -7
  255. package/src/config.d.ts +0 -8
  256. package/src/createObservable.d.ts +0 -2
  257. package/src/event.d.ts +0 -2
  258. package/src/globals.d.ts +0 -32
  259. package/src/helpers/fetch.d.ts +0 -6
  260. package/src/helpers/pageHash.d.ts +0 -7
  261. package/src/helpers/pageHashParams.d.ts +0 -7
  262. package/src/helpers/time.d.ts +0 -3
  263. package/src/helpers.d.ts +0 -13
  264. package/src/history/trackHistory.d.ts +0 -4
  265. package/src/is.d.ts +0 -10
  266. package/src/observable.d.ts +0 -16
  267. package/src/observableInterfaces.d.ts +0 -458
  268. package/src/observe.d.ts +0 -6
  269. package/src/onChange.d.ts +0 -7
  270. package/src/persist/configureObservablePersistence.d.ts +0 -3
  271. package/src/persist/fieldTransformer.d.ts +0 -8
  272. package/src/persist/observablePersistRemoteFunctionsAdapter.d.ts +0 -2
  273. package/src/persist/persistActivateNode.d.ts +0 -1
  274. package/src/persist/persistHelpers.d.ts +0 -1
  275. package/src/persist/persistObservable.d.ts +0 -25
  276. package/src/persist-plugins/async-storage.d.ts +0 -14
  277. package/src/persist-plugins/fetch.d.ts +0 -10
  278. package/src/persist-plugins/firebase.d.ts +0 -51
  279. package/src/persist-plugins/indexeddb.d.ts +0 -25
  280. package/src/persist-plugins/local-storage.d.ts +0 -21
  281. package/src/persist-plugins/mmkv.d.ts +0 -14
  282. package/src/persist-plugins/query.d.ts +0 -18
  283. package/src/proxy.d.ts +0 -5
  284. package/src/react/Computed.d.ts +0 -5
  285. package/src/react/For.d.ts +0 -15
  286. package/src/react/Memo.d.ts +0 -3
  287. package/src/react/Reactive.d.ts +0 -9
  288. package/src/react/Show.d.ts +0 -18
  289. package/src/react/Switch.d.ts +0 -14
  290. package/src/react/react-globals.d.ts +0 -3
  291. package/src/react/reactive-observer.d.ts +0 -14
  292. package/src/react/useComputed.d.ts +0 -5
  293. package/src/react/useEffectOnce.d.ts +0 -1
  294. package/src/react/useIsMounted.d.ts +0 -2
  295. package/src/react/useMount.d.ts +0 -2
  296. package/src/react/useObservable.d.ts +0 -9
  297. package/src/react/useObservableReducer.d.ts +0 -7
  298. package/src/react/useObservableState.d.ts +0 -2
  299. package/src/react/useObserve.d.ts +0 -4
  300. package/src/react/useObserveEffect.d.ts +0 -4
  301. package/src/react/usePauseProvider.d.ts +0 -8
  302. package/src/react/useSelector.d.ts +0 -3
  303. package/src/react/useUnmount.d.ts +0 -2
  304. package/src/react/useWhen.d.ts +0 -3
  305. package/src/react-hooks/createObservableHook.d.ts +0 -2
  306. package/src/react-hooks/useFetch.d.ts +0 -6
  307. package/src/react-hooks/useHover.d.ts +0 -3
  308. package/src/react-hooks/useMeasure.d.ts +0 -6
  309. package/src/react-hooks/useObservableNextRouter.d.ts +0 -33
  310. package/src/react-hooks/useObservableQuery.d.ts +0 -6
  311. package/src/react-hooks/usePersistedObservable.d.ts +0 -11
  312. package/src/retry.d.ts +0 -9
  313. package/src/setupTracking.d.ts +0 -2
  314. package/src/trace/traceHelpers.d.ts +0 -2
  315. package/src/trace/useTraceListeners.d.ts +0 -1
  316. package/src/trace/useTraceUpdates.d.ts +0 -1
  317. package/src/trace/useVerifyNotTracking.d.ts +0 -1
  318. package/src/trace/useVerifyOneRender.d.ts +0 -1
  319. package/src/trackSelector.d.ts +0 -7
  320. package/src/tracking.d.ts +0 -13
  321. package/src/when.d.ts +0 -3
@@ -0,0 +1,226 @@
1
+ import type { GetOptions, ListenerFn, TrackingType } from './observableInterfaces';
2
+
3
+ type Primitive = string | number | boolean | symbol | bigint | undefined | null | Date;
4
+ type ArrayOverrideFnNames =
5
+ | 'find'
6
+ | 'every'
7
+ | 'some'
8
+ | 'filter'
9
+ | 'reduce'
10
+ | 'reduceRight'
11
+ | 'forEach'
12
+ | 'map'
13
+ | 'sort';
14
+
15
+ type RemoveIndex<T> = {
16
+ [K in keyof T as string extends K ? never : number extends K ? never : K]: T[K];
17
+ };
18
+
19
+ type BuiltIns = String | Boolean | Number | Date | Error | RegExp | Array<any> | Function | Promise<any>;
20
+
21
+ type IsUserDefinedObject<T> =
22
+ // Only objects that are not function or arrays or instances of BuiltIns.
23
+ T extends Function | BuiltIns | any[] ? false : T extends object ? true : false;
24
+
25
+ export type RemoveObservables<T> = T extends ImmutableObservableBase<infer t>
26
+ ? t
27
+ : IsUserDefinedObject<T> extends true
28
+ ? {
29
+ [K in keyof T]: RemoveObservables<T[K]>;
30
+ }
31
+ : T;
32
+
33
+ interface ObservableArray<T, U>
34
+ extends ObservablePrimitive<T>,
35
+ Pick<Array<Observable<U>>, ArrayOverrideFnNames>,
36
+ Omit<RemoveIndex<Array<U>>, ArrayOverrideFnNames> {}
37
+
38
+ interface ObservableObjectFns<T> {
39
+ assign(value: Partial<T>): Observable<T>;
40
+ }
41
+
42
+ interface ObservableObjectFunctions<T = Record<string, any>> extends ObservablePrimitive<T>, ObservableObjectFns<T> {}
43
+
44
+ type MapKey<T extends Map<any, any> | WeakMap<any, any>> = Parameters<T['has']>[0];
45
+ type MapValue<T extends Map<any, any> | WeakMap<any, any>> = Parameters<T['get']>[0];
46
+ type ObservableMap<T extends Map<any, any> | WeakMap<any, any>> = Omit<T, 'get' | 'size'> &
47
+ Omit<ObservablePrimitive<T>, 'get' | 'size'> & {
48
+ get(key: Parameters<T['get']>[0]): Observable<Parameters<T['set']>[1]>;
49
+ get(): T;
50
+ size: ImmutableObservableBase<number>;
51
+ assign(
52
+ value: Record<MapKey<T>, MapValue<T>> | Map<MapKey<T>, MapValue<T>> | WeakMap<MapKey<T>, MapValue<T>>,
53
+ ): Observable<T>;
54
+ };
55
+
56
+ type ObservableSet<T extends Set<any> | WeakSet<any>> = Omit<T, 'size'> &
57
+ Omit<ObservablePrimitive<T>, 'size'> & { size: ImmutableObservableBase<number> };
58
+
59
+ interface ObservableBoolean extends ObservablePrimitive<boolean> {
60
+ toggle(): void;
61
+ }
62
+
63
+ interface ObservablePrimitive<T> extends ImmutableObservableBase<T>, MutableObservableBase<T> {}
64
+ type ObservableAny = Partial<ObservableObjectFns<any>> & ObservablePrimitive<any> & Record<string, any>;
65
+
66
+ interface ImmutableObservableSimple<T> {
67
+ peek(): T;
68
+ get(trackingType?: any): any;
69
+ onChange(cb: ListenerFn<any>, options?: any): () => void;
70
+ }
71
+ interface ImmutableObservableBase<T> extends ImmutableObservableSimple<T> {
72
+ peek(): RemoveObservables<T>;
73
+ peek(): T; // This is just to match the Simple base type
74
+ get(trackingType?: TrackingType | GetOptions): RemoveObservables<T>;
75
+ onChange(
76
+ cb: ListenerFn<T>,
77
+ options?: { trackingType?: TrackingType; initial?: boolean; immediate?: boolean; noArgs?: boolean },
78
+ ): () => void;
79
+ }
80
+
81
+ interface MutableObservableSimple {
82
+ set(value: any): void;
83
+ delete(): void;
84
+ }
85
+ interface MutableObservableBase<T> extends MutableObservableSimple {
86
+ set(value: (prev: RemoveObservables<T>) => RemoveObservables<T>): void;
87
+ set(value: RecursiveValueOrFunction<T>): void;
88
+ set(value: Promise<RemoveObservables<T>>): void;
89
+ set(value: RemoveObservables<T>): void;
90
+ set(value: Observable<RemoveObservables<T>>): void;
91
+ delete(): void;
92
+ }
93
+
94
+ type UndefinedIf<T, U> = U extends true ? T | undefined : T;
95
+
96
+ type IsNullable<T> = undefined extends T ? true : null extends T ? true : false;
97
+
98
+ type NonObservable = Function | Observable;
99
+ type NonObservableKeys<T> = {
100
+ [K in keyof T]-?: IsStrictAny<T[K]> extends true
101
+ ? never
102
+ : T[K] extends undefined | null
103
+ ? never
104
+ : NonNullable<T[K]> extends NonObservable
105
+ ? K
106
+ : never;
107
+ }[keyof T];
108
+ type ObservableProps<T> = NonObservableKeys<NonNullable<T>> extends never
109
+ ? T
110
+ : RestoreNullability<T, Omit<NonNullable<T>, NonObservableKeys<NonNullable<T>>>>;
111
+
112
+ type NonObservableProps<T> = RestoreNullability<
113
+ T,
114
+ NullablePropsIf<Pick<NonNullable<T>, NonObservableKeys<NonNullable<T>>>, IsNullable<T>>
115
+ >;
116
+ type NullablePropsIf<T, U> = {
117
+ [K in keyof T]: UndefinedIf<T[K], U>;
118
+ };
119
+
120
+ type RestoreNullability<Source, Target> = IsNullable<Source> extends true
121
+ ? Target | Extract<Source, null | undefined>
122
+ : Target;
123
+
124
+ type ObservableChildren<T, Nullable = IsNullable<T>> = {
125
+ [K in keyof T]-?: Observable<UndefinedIf<T[K], Nullable>>;
126
+ };
127
+ type ObservableFunctionChildren<T> = {
128
+ [K in keyof T]-?: T[K] extends Observable
129
+ ? T[K]
130
+ : T[K] extends (key: infer Key extends string) => Promise<infer t> | infer t
131
+ ? HasOneStringParam<T[K]> extends true
132
+ ? Observable<Record<Key, t>> & T[K]
133
+ : t extends void
134
+ ? T[K]
135
+ : t extends Observable
136
+ ? t
137
+ : Observable<t> & (() => t)
138
+ : T[K];
139
+ };
140
+
141
+ type IsStrictAny<T> = 0 extends 1 & T ? true : false;
142
+
143
+ export interface ObservableState {
144
+ isLoaded: boolean;
145
+ error?: Error;
146
+ }
147
+
148
+ type ObservableObject<T> = ObservableObjectFunctions<ObservableProps<T> & NonObservableProps<T>> &
149
+ ObservableChildren<ObservableProps<T>> &
150
+ ObservableFunctionChildren<NonObservableProps<T>>;
151
+
152
+ type ObservableFunction<T> = T extends () => infer t ? t | (() => t) : T;
153
+
154
+ // Check if the function type T has one lookup parameter
155
+ type HasOneStringParam<T> = T extends (...args: infer P) => any
156
+ ? P extends { length: 1 }
157
+ ? P[0] extends string | ObservablePrimitive<string>
158
+ ? true
159
+ : false
160
+ : false
161
+ : false;
162
+
163
+ // : [T] extends [(key: infer K extends string) => infer t]
164
+ // ? // ? HasParams<T> extends true ? Observable<Record<K, t>>
165
+ type ObservableNode<T, NT = NonNullable<T>> = [NT] extends [never] // means that T is ONLY undefined or null
166
+ ? ObservablePrimitive<T>
167
+ : IsStrictAny<T> extends true
168
+ ? ObservableAny
169
+ : [T] extends [Promise<infer t>]
170
+ ? ObservableNode<t>
171
+ : [T] extends [(key: infer K extends string) => infer t]
172
+ ? [t] extends [ImmutableObservableBase<any>]
173
+ ? HasOneStringParam<T> extends true
174
+ ? Observable<Record<K, t>>
175
+ : t
176
+ : HasOneStringParam<T> extends true
177
+ ? Observable<Record<K, t>> & T
178
+ : Observable<ObservableFunction<t>>
179
+ : [NT] extends [ImmutableObservableBase<any>]
180
+ ? NT
181
+ : [NT] extends [Primitive]
182
+ ? [NT] extends [boolean]
183
+ ? ObservableBoolean
184
+ : ObservablePrimitive<T>
185
+ : NT extends Map<any, any> | WeakMap<any, any>
186
+ ? ObservableMap<NT>
187
+ : NT extends Set<infer U>
188
+ ? ObservableSet<Set<UndefinedIf<U, IsNullable<T>>>>
189
+ : NT extends WeakSet<any>
190
+ ? ObservableSet<NT> // TODO what to do here with nullable? WeakKey is type object | symbol
191
+ : NT extends Array<infer U>
192
+ ? ObservableArray<T, U> & ObservableChildren<T>
193
+ : ObservableObject<T> & {};
194
+
195
+ // Note: The {} makes intellisense display observables as Observable instead of all the subtypes
196
+ type Observable<T = any> = ObservableNode<T> & {};
197
+
198
+ type ObservableParam<T = any> = ImmutableObservableSimple<T> & MutableObservableSimple;
199
+
200
+ // Allow input types to have functions in them
201
+ type ValueOrFunction<T> = T extends Function ? T : T | ImmutableObservableBase<T> | Promise<T> | (() => T | Promise<T>);
202
+ type ValueOrFunctionKeys<T> = {
203
+ [K in keyof T]: RecursiveValueOrFunction<T[K]>;
204
+ };
205
+
206
+ type RecursiveValueOrFunction<T> = T extends Function
207
+ ? T
208
+ : T extends object
209
+ ?
210
+ | ((key: string) => any)
211
+ | Promise<ValueOrFunctionKeys<T>>
212
+ | ValueOrFunctionKeys<T>
213
+ | ImmutableObservableBase<T>
214
+ | (() => T | Promise<T> | ValueOrFunctionKeys<T> | Promise<ValueOrFunctionKeys<T>> | Observable<T>)
215
+ : ValueOrFunction<T>;
216
+
217
+ export type {
218
+ // TODO: how to make these internal somehow?
219
+ ImmutableObservableBase,
220
+ Observable,
221
+ ObservableBoolean,
222
+ ObservableObject,
223
+ ObservablePrimitive,
224
+ ObservableParam,
225
+ RecursiveValueOrFunction,
226
+ };
package/src/observe.ts ADDED
@@ -0,0 +1,89 @@
1
+ import { beginBatch, endBatch } from './batching';
2
+ import { isEvent } from './globals';
3
+ import { isFunction } from './is';
4
+ import { ObserveEvent, ObserveEventCallback, Selector } from './observableInterfaces';
5
+ import { trackSelector } from './trackSelector';
6
+
7
+ export interface ObserveOptions {
8
+ immediate?: boolean; // Ignore batching and run immediately
9
+ /* @internal */
10
+ fromComputed?: boolean;
11
+ }
12
+
13
+ export function observe<T>(run: (e: ObserveEvent<T>) => T | void, options?: ObserveOptions): () => void;
14
+ export function observe<T>(
15
+ selector: Selector<T> | ((e: ObserveEvent<T>) => any),
16
+ reaction?: (e: ObserveEventCallback<T>) => any,
17
+ options?: ObserveOptions,
18
+ ): () => void;
19
+ export function observe<T>(
20
+ selectorOrRun: Selector<T> | ((e: ObserveEvent<T>) => any),
21
+ reactionOrOptions?: ((e: ObserveEventCallback<T>) => any) | ObserveOptions,
22
+ options?: ObserveOptions,
23
+ ) {
24
+ let reaction: (e: ObserveEventCallback<T>) => any;
25
+ if (isFunction(reactionOrOptions)) {
26
+ reaction = reactionOrOptions;
27
+ } else {
28
+ options = reactionOrOptions;
29
+ }
30
+ let dispose: (() => void) | undefined;
31
+ const e: ObserveEventCallback<T> = { num: 0 } as ObserveEventCallback<T>;
32
+ // Wrap it in a function so it doesn't pass all the arguments to run()
33
+ const update = function () {
34
+ if (e.onCleanup) {
35
+ e.onCleanup();
36
+ e.onCleanup = undefined;
37
+ }
38
+
39
+ // Run in a batch so changes don't happen until we're done tracking here
40
+ beginBatch();
41
+
42
+ // Run the function/selector
43
+ delete e.value;
44
+
45
+ // Dispose listeners from previous run
46
+ dispose?.();
47
+
48
+ const { dispose: _dispose, value, nodes } = trackSelector(selectorOrRun as Selector<T>, update, e, options);
49
+ dispose = _dispose;
50
+
51
+ e.value = value;
52
+ e.nodes = nodes;
53
+ e.refresh = update;
54
+
55
+ if (e.onCleanupReaction) {
56
+ e.onCleanupReaction();
57
+ e.onCleanupReaction = undefined;
58
+ }
59
+
60
+ endBatch();
61
+
62
+ // Call the reaction if there is one and the value changed
63
+ if (
64
+ reaction &&
65
+ (options?.fromComputed ||
66
+ ((e.num > 0 || !isEvent(selectorOrRun as any)) &&
67
+ (e.previous !== e.value || typeof e.value === 'object')))
68
+ ) {
69
+ reaction(e);
70
+ }
71
+
72
+ // Update the previous value
73
+ e.previous = e.value;
74
+
75
+ // Increment the counter
76
+ e.num++;
77
+ };
78
+
79
+ update();
80
+
81
+ // Return function calling dispose because dispose may be changed in update()
82
+ return () => {
83
+ e.onCleanup?.();
84
+ e.onCleanup = undefined;
85
+ e.onCleanupReaction?.();
86
+ e.onCleanupReaction = undefined;
87
+ dispose?.();
88
+ };
89
+ }
@@ -0,0 +1,136 @@
1
+ import { isArray } from './is';
2
+ import { getNodeValue } from './globals';
3
+ import type { ListenerFn, ListenerParams, NodeValue, NodeValueListener, TrackingType } from './observableInterfaces';
4
+
5
+ export function onChange(
6
+ node: NodeValue,
7
+ callback: ListenerFn,
8
+ options: { trackingType?: TrackingType; initial?: boolean; immediate?: boolean; noArgs?: boolean } = {},
9
+ fromLinks?: Set<NodeValue>,
10
+ ): () => void {
11
+ const { initial, immediate, noArgs } = options;
12
+ const { trackingType } = options;
13
+
14
+ let listeners = immediate ? node.listenersImmediate : node.listeners;
15
+ if (!listeners) {
16
+ listeners = new Set();
17
+ if (immediate) {
18
+ node.listenersImmediate = listeners;
19
+ } else {
20
+ node.listeners = listeners;
21
+ }
22
+ }
23
+
24
+ const listener: NodeValueListener = {
25
+ listener: callback,
26
+ track: trackingType,
27
+ noArgs,
28
+ };
29
+
30
+ listeners.add(listener);
31
+
32
+ if (initial) {
33
+ const value = getNodeValue(node);
34
+ callback({
35
+ value,
36
+ loading: true,
37
+ remote: false,
38
+ changes: [
39
+ {
40
+ path: [],
41
+ pathTypes: [],
42
+ prevAtPath: value,
43
+ valueAtPath: value,
44
+ },
45
+ ],
46
+ getPrevious: () => undefined,
47
+ });
48
+ }
49
+
50
+ let extraDisposes: (() => void)[];
51
+
52
+ function addLinkedNodeListeners(childNode: NodeValue, cb: ListenerFn = callback, from?: NodeValue) {
53
+ // Don't add listeners for the same node more than once
54
+ if (!fromLinks?.has(childNode)) {
55
+ fromLinks ||= new Set();
56
+ fromLinks.add(from || node);
57
+ cb ||= callback;
58
+ const childOptions: Parameters<typeof onChange>[2] = {
59
+ trackingType: true,
60
+ ...options,
61
+ };
62
+ // onChange for the linked node
63
+ extraDisposes = [...(extraDisposes || []), onChange(childNode, cb as ListenerFn, childOptions, fromLinks)];
64
+ }
65
+ }
66
+
67
+ // Add listeners for linked to nodes
68
+ if (node.linkedToNode) {
69
+ addLinkedNodeListeners(node.linkedToNode);
70
+ }
71
+
72
+ // Add listeners for linked from nodes
73
+ node.linkedFromNodes?.forEach((linkedFromNode) => addLinkedNodeListeners(linkedFromNode));
74
+
75
+ // Go up through the parents and add listeners for linked from nodes
76
+ let parent = node.parent;
77
+ let pathParent: string[] = [node!.key!];
78
+ while (parent) {
79
+ if (parent.linkedFromNodes) {
80
+ for (const linkedFromNode of parent.linkedFromNodes) {
81
+ if (!fromLinks?.has(linkedFromNode)) {
82
+ const cb = createCb(linkedFromNode, pathParent, callback);
83
+ addLinkedNodeListeners(linkedFromNode, cb, parent);
84
+ }
85
+ }
86
+ }
87
+ pathParent = [parent!.key!, ...pathParent];
88
+ parent = parent.parent;
89
+ }
90
+
91
+ return () => {
92
+ listeners!.delete(listener);
93
+ extraDisposes?.forEach((fn) => fn());
94
+ };
95
+ }
96
+
97
+ function createCb(linkedFromNode: NodeValue, path: string[], callback: ListenerFn) {
98
+ // Create a callback for a path that calls it with the current value at the path
99
+ let { valueAtPath: prevAtPath } = getValueAtPath(getNodeValue(linkedFromNode), path);
100
+
101
+ return function ({ value: valueA, loading, remote }: ListenerParams<any>) {
102
+ const { valueAtPath, pathTypes } = getValueAtPath(valueA, path);
103
+ if (valueAtPath !== prevAtPath) {
104
+ callback({
105
+ value: valueAtPath,
106
+ loading,
107
+ remote,
108
+ changes: [
109
+ {
110
+ path,
111
+ pathTypes,
112
+ prevAtPath,
113
+ valueAtPath,
114
+ },
115
+ ],
116
+ getPrevious: () => prevAtPath,
117
+ });
118
+ }
119
+ prevAtPath = valueAtPath;
120
+ };
121
+ }
122
+
123
+ function getValueAtPath(
124
+ obj: Record<string, any>,
125
+ path: string[],
126
+ ): { valueAtPath: any; pathTypes: ('object' | 'array')[] } {
127
+ let o: Record<string, any> = obj;
128
+ const pathTypes: ('object' | 'array')[] = [];
129
+ for (let i = 0; o && i < path.length; i++) {
130
+ pathTypes.push(isArray(o) ? 'array' : 'object');
131
+ const p = path[i];
132
+ o = (o as any)[p];
133
+ }
134
+
135
+ return { valueAtPath: o, pathTypes };
136
+ }
@@ -0,0 +1,7 @@
1
+ import type { ObservablePersistenceConfig } from '@legendapp/state/sync';
2
+
3
+ export const observablePersistConfiguration: ObservablePersistenceConfig = {};
4
+
5
+ export function configureObservablePersistence(options?: ObservablePersistenceConfig) {
6
+ Object.assign(observablePersistConfiguration, options);
7
+ }
@@ -0,0 +1,149 @@
1
+ import {
2
+ constructObjectWithPath,
3
+ deconstructObjectWithPath,
4
+ isArray,
5
+ isObject,
6
+ isString,
7
+ TypeAtPath,
8
+ internal,
9
+ } from '@legendapp/state';
10
+ import type { FieldTransforms } from '@legendapp/state/sync';
11
+
12
+ const { initializePathType, symbolDelete } = internal;
13
+
14
+ let validateMap: (map: Record<string, any>) => void;
15
+
16
+ export function transformPath(path: string[], pathTypes: TypeAtPath[], map: Record<string, any>): string[] {
17
+ const data: Record<string, any> = {};
18
+ let d: Record<string, any> | null = data;
19
+ for (let i = 0; i < path.length; i++) {
20
+ d = d![path[i]] = i === path.length - 1 ? null : initializePathType(pathTypes[i]);
21
+ }
22
+ let value = transformObject(data, map);
23
+ const pathOut = [];
24
+ for (let i = 0; i < path.length; i++) {
25
+ const key = Object.keys(value)[0];
26
+ pathOut.push(key);
27
+ value = value[key];
28
+ }
29
+ return pathOut;
30
+ }
31
+
32
+ export function transformObject(dataIn: Record<string, any>, map: Record<string, any>) {
33
+ if (process.env.NODE_ENV === 'development') {
34
+ validateMap(map);
35
+ }
36
+ let ret = dataIn;
37
+ if (dataIn) {
38
+ if ((dataIn as unknown) === symbolDelete) return dataIn;
39
+ if (isString(dataIn)) {
40
+ return map[dataIn];
41
+ }
42
+
43
+ ret = {};
44
+
45
+ const dict = Object.keys(map).length === 1 && map['_dict'];
46
+
47
+ for (const key in dataIn) {
48
+ let v = dataIn[key];
49
+
50
+ if (dict) {
51
+ ret[key] = transformObject(v, dict);
52
+ } else {
53
+ const mapped = map[key];
54
+ if (mapped === undefined) {
55
+ // Don't transform dateModified if user doesn't want it
56
+ if (key !== '@') {
57
+ ret[key] = v;
58
+ if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
59
+ console.error('A fatal field transformation error has occurred', key, dataIn, map);
60
+ }
61
+ }
62
+ } else if (mapped !== null) {
63
+ if (v !== undefined && v !== null) {
64
+ if (map[key + '_val']) {
65
+ const mapChild = map[key + '_val'];
66
+ if (isArray(v)) {
67
+ v = v.map((vChild) => mapChild[vChild]);
68
+ } else {
69
+ v = mapChild[v];
70
+ }
71
+ } else if (map[key + '_arr'] && isArray(v)) {
72
+ const mapChild = map[key + '_arr'];
73
+ v = v.map((vChild) => transformObject(vChild, mapChild));
74
+ } else if (isObject(v)) {
75
+ if (map[key + '_obj']) {
76
+ v = transformObject(v, map[key + '_obj']);
77
+ } else if (map[key + '_dict']) {
78
+ const mapChild = map[key + '_dict'];
79
+ const out: Record<string, any> = {};
80
+ for (const keyChild in v) {
81
+ out[keyChild] = transformObject(v[keyChild], mapChild);
82
+ }
83
+ v = out;
84
+ }
85
+ }
86
+ }
87
+ ret[mapped] = v;
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ return ret;
94
+ }
95
+
96
+ export function transformObjectWithPath(
97
+ obj: object,
98
+ path: string[],
99
+ pathTypes: TypeAtPath[],
100
+ fieldTransforms: FieldTransforms<any>,
101
+ ) {
102
+ const constructed = constructObjectWithPath(path, pathTypes, obj);
103
+ const transformed = transformObject(constructed, fieldTransforms);
104
+ const transformedPath = transformPath(path as string[], pathTypes, fieldTransforms);
105
+ return { path: transformedPath, obj: deconstructObjectWithPath(transformedPath, pathTypes, transformed) };
106
+ }
107
+
108
+ const invertedMaps = new WeakMap();
109
+
110
+ export function invertFieldMap(obj: Record<string, any>) {
111
+ const existing = invertedMaps.get(obj);
112
+ if (existing) return existing;
113
+
114
+ const target: Record<string, any> = {} as any;
115
+
116
+ for (const key in obj) {
117
+ const val = obj[key];
118
+ if (key === '_dict') {
119
+ target[key] = invertFieldMap(val);
120
+ } else if (key.endsWith('_obj') || key.endsWith('_dict') || key.endsWith('_arr') || key.endsWith('_val')) {
121
+ const keyMapped = obj[key.replace(/_obj|_dict|_arr|_val$/, '')];
122
+ const suffix = key.match(/_obj|_dict|_arr|_val$/)![0];
123
+ target[keyMapped + suffix] = invertFieldMap(val);
124
+ } else if (typeof val === 'string') {
125
+ target[val] = key;
126
+ }
127
+ }
128
+ invertedMaps.set(obj, target);
129
+
130
+ return target;
131
+ }
132
+
133
+ if (process.env.NODE_ENV === 'development') {
134
+ validateMap = function (record: Record<string, any>) {
135
+ const values = Object.values(record).filter((value) => {
136
+ if (isObject(value)) {
137
+ validateMap(value);
138
+ } else {
139
+ return isString(value);
140
+ }
141
+ });
142
+
143
+ const uniques = Array.from(new Set(values));
144
+ if (values.length !== uniques.length) {
145
+ console.error('Field transform map has duplicate values', record, values.length, uniques.length);
146
+ }
147
+ return record;
148
+ };
149
+ }
@@ -0,0 +1,39 @@
1
+ import { isPromise } from '@legendapp/state';
2
+ import {
3
+ type ObservablePersistRemoteClass,
4
+ type ObservablePersistRemoteFunctions,
5
+ type ObservablePersistRemoteGetParams,
6
+ } from '@legendapp/state/sync';
7
+
8
+ export function observablePersistRemoteFunctionsAdapter<T = {}>({
9
+ get,
10
+ set,
11
+ }: ObservablePersistRemoteFunctions<T>): ObservablePersistRemoteClass {
12
+ const ret: ObservablePersistRemoteClass = {};
13
+
14
+ if (get) {
15
+ ret.get = (async (params: ObservablePersistRemoteGetParams<T>) => {
16
+ try {
17
+ let value = get(params);
18
+ if (isPromise(value)) {
19
+ value = await value;
20
+ }
21
+
22
+ params.onChange({
23
+ value,
24
+ dateModified: params.dateModified,
25
+ lastSync: params.lastSync,
26
+ mode: params.mode,
27
+ });
28
+ params.onGet();
29
+ // eslint-disable-next-line no-empty
30
+ } catch {}
31
+ }) as ObservablePersistRemoteClass['get'];
32
+ }
33
+
34
+ if (set) {
35
+ ret.set = set as ObservablePersistRemoteClass['set'];
36
+ }
37
+
38
+ return ret;
39
+ }