@bquery/bquery 1.7.0 → 1.8.2

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 (262) hide show
  1. package/README.md +760 -716
  2. package/dist/{a11y-C5QOVvRn.js → a11y-DVBCy09c.js} +3 -3
  3. package/dist/a11y-DVBCy09c.js.map +1 -0
  4. package/dist/a11y.es.mjs +1 -1
  5. package/dist/component/library.d.ts.map +1 -1
  6. package/dist/{component-CuuTijA6.js → component-L3-JfOFz.js} +5 -5
  7. package/dist/component-L3-JfOFz.js.map +1 -0
  8. package/dist/component.es.mjs +1 -1
  9. package/dist/{config-BW35FKuA.js → config-DhT9auRm.js} +1 -1
  10. package/dist/{config-BW35FKuA.js.map → config-DhT9auRm.js.map} +1 -1
  11. package/dist/{constraints-3lV9yyBw.js → constraints-D5RHQLmP.js} +1 -1
  12. package/dist/constraints-D5RHQLmP.js.map +1 -0
  13. package/dist/core/collection.d.ts +86 -0
  14. package/dist/core/collection.d.ts.map +1 -1
  15. package/dist/core/element.d.ts +28 -0
  16. package/dist/core/element.d.ts.map +1 -1
  17. package/dist/core/shared.d.ts +6 -0
  18. package/dist/core/shared.d.ts.map +1 -1
  19. package/dist/core-DdtZHzsS.js +168 -0
  20. package/dist/core-DdtZHzsS.js.map +1 -0
  21. package/dist/{core-Cjl7GUu8.js → core-EMYSLzaT.js} +289 -259
  22. package/dist/core-EMYSLzaT.js.map +1 -0
  23. package/dist/core.es.mjs +48 -47
  24. package/dist/{custom-directives-7wAShnnd.js → custom-directives-Dr4C5lVV.js} +1 -1
  25. package/dist/custom-directives-Dr4C5lVV.js.map +1 -0
  26. package/dist/{devtools-D2fQLhDN.js → devtools-BhB2iDPT.js} +2 -2
  27. package/dist/devtools-BhB2iDPT.js.map +1 -0
  28. package/dist/devtools.es.mjs +1 -1
  29. package/dist/{dnd-B8EgyzaI.js → dnd-NwZBYh4l.js} +1 -1
  30. package/dist/dnd-NwZBYh4l.js.map +1 -0
  31. package/dist/dnd.es.mjs +1 -1
  32. package/dist/{env-NeVmr4Gf.js → env-CTdvLaH2.js} +1 -1
  33. package/dist/env-CTdvLaH2.js.map +1 -0
  34. package/dist/forms/create-form.d.ts.map +1 -1
  35. package/dist/forms/index.d.ts +3 -2
  36. package/dist/forms/index.d.ts.map +1 -1
  37. package/dist/forms/types.d.ts +46 -0
  38. package/dist/forms/types.d.ts.map +1 -1
  39. package/dist/forms/use-field.d.ts +34 -0
  40. package/dist/forms/use-field.d.ts.map +1 -0
  41. package/dist/forms/validators.d.ts +25 -0
  42. package/dist/forms/validators.d.ts.map +1 -1
  43. package/dist/forms-UcRHsYxC.js +227 -0
  44. package/dist/forms-UcRHsYxC.js.map +1 -0
  45. package/dist/forms.es.mjs +14 -12
  46. package/dist/full.d.ts +17 -26
  47. package/dist/full.d.ts.map +1 -1
  48. package/dist/full.es.mjs +206 -181
  49. package/dist/full.iife.js +33 -33
  50. package/dist/full.iife.js.map +1 -1
  51. package/dist/full.umd.js +33 -33
  52. package/dist/full.umd.js.map +1 -1
  53. package/dist/function-Cybd57JV.js +33 -0
  54. package/dist/function-Cybd57JV.js.map +1 -0
  55. package/dist/{i18n-BnnhTFOS.js → i18n-kuF6Ekj6.js} +3 -3
  56. package/dist/i18n-kuF6Ekj6.js.map +1 -0
  57. package/dist/i18n.es.mjs +1 -1
  58. package/dist/index.es.mjs +251 -228
  59. package/dist/media/breakpoints.d.ts.map +1 -1
  60. package/dist/media/types.d.ts +2 -2
  61. package/dist/media/types.d.ts.map +1 -1
  62. package/dist/{media-Di2Ta22s.js → media-i-fB5WxI.js} +3 -3
  63. package/dist/media-i-fB5WxI.js.map +1 -0
  64. package/dist/media.es.mjs +1 -1
  65. package/dist/{motion-qPj_TYGv.js → motion-BJsAuULb.js} +2 -2
  66. package/dist/motion-BJsAuULb.js.map +1 -0
  67. package/dist/motion.es.mjs +1 -1
  68. package/dist/{mount-SM07RUa6.js → mount-B4Y8bk8Z.js} +5 -5
  69. package/dist/mount-B4Y8bk8Z.js.map +1 -0
  70. package/dist/{platform-CPbCprb6.js → platform-Dw2gE3zI.js} +3 -3
  71. package/dist/{platform-CPbCprb6.js.map → platform-Dw2gE3zI.js.map} +1 -1
  72. package/dist/platform.es.mjs +2 -2
  73. package/dist/plugin/registry.d.ts.map +1 -1
  74. package/dist/{plugin-cPoOHFLY.js → plugin-C2WuC8SF.js} +20 -18
  75. package/dist/plugin-C2WuC8SF.js.map +1 -0
  76. package/dist/plugin.es.mjs +1 -1
  77. package/dist/reactive/async-data.d.ts +28 -3
  78. package/dist/reactive/async-data.d.ts.map +1 -1
  79. package/dist/reactive/computed.d.ts +3 -0
  80. package/dist/reactive/computed.d.ts.map +1 -1
  81. package/dist/reactive/effect.d.ts +3 -0
  82. package/dist/reactive/effect.d.ts.map +1 -1
  83. package/dist/reactive/http.d.ts +194 -0
  84. package/dist/reactive/http.d.ts.map +1 -0
  85. package/dist/reactive/index.d.ts +2 -2
  86. package/dist/reactive/index.d.ts.map +1 -1
  87. package/dist/reactive/pagination.d.ts +126 -0
  88. package/dist/reactive/pagination.d.ts.map +1 -0
  89. package/dist/reactive/polling.d.ts +55 -0
  90. package/dist/reactive/polling.d.ts.map +1 -0
  91. package/dist/reactive/readonly.d.ts +20 -1
  92. package/dist/reactive/readonly.d.ts.map +1 -1
  93. package/dist/reactive/rest.d.ts +293 -0
  94. package/dist/reactive/rest.d.ts.map +1 -0
  95. package/dist/reactive/scope.d.ts +140 -0
  96. package/dist/reactive/scope.d.ts.map +1 -0
  97. package/dist/reactive/signal.d.ts +16 -2
  98. package/dist/reactive/signal.d.ts.map +1 -1
  99. package/dist/reactive/to-value.d.ts +57 -0
  100. package/dist/reactive/to-value.d.ts.map +1 -0
  101. package/dist/reactive/websocket.d.ts +285 -0
  102. package/dist/reactive/websocket.d.ts.map +1 -0
  103. package/dist/reactive-DwkhUJfP.js +1148 -0
  104. package/dist/reactive-DwkhUJfP.js.map +1 -0
  105. package/dist/reactive.es.mjs +38 -19
  106. package/dist/{registry-CWf368tT.js → registry-B08iilIh.js} +1 -1
  107. package/dist/{registry-CWf368tT.js.map → registry-B08iilIh.js.map} +1 -1
  108. package/dist/router/constraints.d.ts.map +1 -1
  109. package/dist/router/index.d.ts +1 -1
  110. package/dist/router/index.d.ts.map +1 -1
  111. package/dist/router/router.d.ts.map +1 -1
  112. package/dist/router/state.d.ts +25 -2
  113. package/dist/router/state.d.ts.map +1 -1
  114. package/dist/router-CQikC9Ed.js +492 -0
  115. package/dist/router-CQikC9Ed.js.map +1 -0
  116. package/dist/router.es.mjs +9 -8
  117. package/dist/ssr/hydrate.d.ts.map +1 -1
  118. package/dist/{ssr-B2qd_WBB.js → ssr-_dAcGdzu.js} +4 -4
  119. package/dist/ssr-_dAcGdzu.js.map +1 -0
  120. package/dist/ssr.es.mjs +1 -1
  121. package/dist/store/persisted.d.ts.map +1 -1
  122. package/dist/{store-DWpyH6p5.js → store-Cb3gPRve.js} +7 -7
  123. package/dist/store-Cb3gPRve.js.map +1 -0
  124. package/dist/store.es.mjs +2 -2
  125. package/dist/storybook.es.mjs.map +1 -1
  126. package/dist/{testing-CsqjNUyy.js → testing-C5Sjfsna.js} +8 -8
  127. package/dist/testing-C5Sjfsna.js.map +1 -0
  128. package/dist/testing.es.mjs +1 -1
  129. package/dist/{type-guards-Do9DWgNp.js → type-guards-BMX2c0LP.js} +1 -1
  130. package/dist/{type-guards-Do9DWgNp.js.map → type-guards-BMX2c0LP.js.map} +1 -1
  131. package/dist/untrack-D0fnO5k2.js +36 -0
  132. package/dist/untrack-D0fnO5k2.js.map +1 -0
  133. package/dist/view/custom-directives.d.ts.map +1 -1
  134. package/dist/view.es.mjs +4 -4
  135. package/package.json +178 -177
  136. package/src/a11y/announce.ts +131 -131
  137. package/src/a11y/audit.ts +314 -314
  138. package/src/a11y/index.ts +68 -68
  139. package/src/a11y/media-preferences.ts +255 -255
  140. package/src/a11y/roving-tab-index.ts +164 -164
  141. package/src/a11y/skip-link.ts +255 -255
  142. package/src/a11y/trap-focus.ts +184 -184
  143. package/src/a11y/types.ts +183 -183
  144. package/src/component/component.ts +599 -599
  145. package/src/component/html.ts +153 -153
  146. package/src/component/index.ts +52 -52
  147. package/src/component/library.ts +540 -542
  148. package/src/component/scope.ts +212 -212
  149. package/src/component/types.ts +310 -310
  150. package/src/core/collection.ts +876 -707
  151. package/src/core/element.ts +1015 -981
  152. package/src/core/env.ts +60 -60
  153. package/src/core/index.ts +49 -49
  154. package/src/core/shared.ts +77 -62
  155. package/src/core/utils/index.ts +148 -148
  156. package/src/devtools/devtools.ts +410 -410
  157. package/src/devtools/index.ts +48 -48
  158. package/src/devtools/types.ts +104 -104
  159. package/src/dnd/draggable.ts +296 -296
  160. package/src/dnd/droppable.ts +228 -228
  161. package/src/dnd/index.ts +62 -62
  162. package/src/dnd/sortable.ts +307 -307
  163. package/src/dnd/types.ts +293 -293
  164. package/src/forms/create-form.ts +320 -278
  165. package/src/forms/index.ts +70 -65
  166. package/src/forms/types.ts +203 -154
  167. package/src/forms/use-field.ts +231 -0
  168. package/src/forms/validators.ts +294 -265
  169. package/src/full.ts +554 -480
  170. package/src/i18n/formatting.ts +67 -67
  171. package/src/i18n/i18n.ts +200 -200
  172. package/src/i18n/index.ts +67 -67
  173. package/src/i18n/translate.ts +182 -182
  174. package/src/i18n/types.ts +171 -171
  175. package/src/index.ts +108 -108
  176. package/src/media/battery.ts +116 -116
  177. package/src/media/breakpoints.ts +129 -131
  178. package/src/media/clipboard.ts +80 -80
  179. package/src/media/device-sensors.ts +158 -158
  180. package/src/media/geolocation.ts +119 -119
  181. package/src/media/index.ts +76 -76
  182. package/src/media/media-query.ts +92 -92
  183. package/src/media/network.ts +115 -115
  184. package/src/media/types.ts +177 -177
  185. package/src/media/viewport.ts +84 -84
  186. package/src/motion/index.ts +57 -57
  187. package/src/motion/morph.ts +151 -151
  188. package/src/motion/parallax.ts +120 -120
  189. package/src/motion/reduced-motion.ts +66 -66
  190. package/src/motion/types.ts +271 -271
  191. package/src/motion/typewriter.ts +164 -164
  192. package/src/plugin/index.ts +37 -37
  193. package/src/plugin/registry.ts +284 -269
  194. package/src/plugin/types.ts +137 -137
  195. package/src/reactive/async-data.ts +250 -29
  196. package/src/reactive/computed.ts +144 -130
  197. package/src/reactive/effect.ts +29 -6
  198. package/src/reactive/http.ts +790 -0
  199. package/src/reactive/index.ts +60 -0
  200. package/src/reactive/pagination.ts +317 -0
  201. package/src/reactive/polling.ts +179 -0
  202. package/src/reactive/readonly.ts +52 -8
  203. package/src/reactive/rest.ts +859 -0
  204. package/src/reactive/scope.ts +276 -0
  205. package/src/reactive/signal.ts +61 -1
  206. package/src/reactive/to-value.ts +71 -0
  207. package/src/reactive/websocket.ts +849 -0
  208. package/src/router/bq-link.ts +279 -279
  209. package/src/router/constraints.ts +204 -201
  210. package/src/router/index.ts +49 -49
  211. package/src/router/match.ts +312 -312
  212. package/src/router/path-pattern.ts +52 -52
  213. package/src/router/query.ts +38 -38
  214. package/src/router/router.ts +421 -402
  215. package/src/router/state.ts +51 -3
  216. package/src/router/types.ts +139 -139
  217. package/src/router/use-route.ts +68 -68
  218. package/src/router/utils.ts +157 -157
  219. package/src/security/index.ts +12 -12
  220. package/src/ssr/hydrate.ts +84 -82
  221. package/src/ssr/index.ts +70 -70
  222. package/src/ssr/render.ts +508 -508
  223. package/src/ssr/serialize.ts +296 -296
  224. package/src/ssr/types.ts +81 -81
  225. package/src/store/create-store.ts +467 -467
  226. package/src/store/index.ts +27 -27
  227. package/src/store/persisted.ts +245 -249
  228. package/src/store/types.ts +247 -247
  229. package/src/store/utils.ts +135 -135
  230. package/src/storybook/index.ts +480 -480
  231. package/src/testing/index.ts +42 -42
  232. package/src/testing/testing.ts +593 -593
  233. package/src/testing/types.ts +170 -170
  234. package/src/view/custom-directives.ts +28 -30
  235. package/src/view/evaluate.ts +292 -292
  236. package/src/view/process.ts +108 -108
  237. package/dist/a11y-C5QOVvRn.js.map +0 -1
  238. package/dist/component-CuuTijA6.js.map +0 -1
  239. package/dist/constraints-3lV9yyBw.js.map +0 -1
  240. package/dist/core-Cjl7GUu8.js.map +0 -1
  241. package/dist/core-DnlyjbF2.js +0 -112
  242. package/dist/core-DnlyjbF2.js.map +0 -1
  243. package/dist/custom-directives-7wAShnnd.js.map +0 -1
  244. package/dist/devtools-D2fQLhDN.js.map +0 -1
  245. package/dist/dnd-B8EgyzaI.js.map +0 -1
  246. package/dist/env-NeVmr4Gf.js.map +0 -1
  247. package/dist/forms-C3yovgH9.js +0 -141
  248. package/dist/forms-C3yovgH9.js.map +0 -1
  249. package/dist/i18n-BnnhTFOS.js.map +0 -1
  250. package/dist/media-Di2Ta22s.js.map +0 -1
  251. package/dist/motion-qPj_TYGv.js.map +0 -1
  252. package/dist/mount-SM07RUa6.js.map +0 -1
  253. package/dist/plugin-cPoOHFLY.js.map +0 -1
  254. package/dist/reactive-Cfv0RK6x.js +0 -233
  255. package/dist/reactive-Cfv0RK6x.js.map +0 -1
  256. package/dist/router-BrthaP_z.js +0 -473
  257. package/dist/router-BrthaP_z.js.map +0 -1
  258. package/dist/ssr-B2qd_WBB.js.map +0 -1
  259. package/dist/store-DWpyH6p5.js.map +0 -1
  260. package/dist/testing-CsqjNUyy.js.map +0 -1
  261. package/dist/untrack-DJVQQ2WM.js +0 -33
  262. package/dist/untrack-DJVQQ2WM.js.map +0 -1
@@ -0,0 +1,293 @@
1
+ /**
2
+ * REST resource composable for CRUD operations with optimistic updates,
3
+ * form submission, and reactive caching built on the bQuery fetch layer.
4
+ *
5
+ * @module bquery/reactive
6
+ */
7
+ import { Signal } from './core';
8
+ import { type AsyncDataStatus, type UseFetchOptions } from './async-data';
9
+ import { type HttpClient, type HttpRequestConfig, type HttpResponse } from './http';
10
+ /** HTTP method shortcuts available on a resource. */
11
+ export interface ResourceActions<T> {
12
+ /** Fetch the resource (GET). */
13
+ fetch: () => Promise<T | undefined>;
14
+ /** Create a new item (POST). */
15
+ create: (body: Partial<T> | Record<string, unknown>) => Promise<T | undefined>;
16
+ /** Replace the resource (PUT). */
17
+ update: (body: Partial<T> | Record<string, unknown>) => Promise<T | undefined>;
18
+ /** Partially update the resource (PATCH). */
19
+ patch: (body: Partial<T> | Record<string, unknown>) => Promise<T | undefined>;
20
+ /** Delete the resource (DELETE). */
21
+ remove: () => Promise<void>;
22
+ }
23
+ /** Options for `useResource()`. */
24
+ export interface UseResourceOptions<T = unknown> extends Omit<UseFetchOptions<T>, 'method' | 'body'> {
25
+ /** Enable optimistic updates for mutating operations (default: false). */
26
+ optimistic?: boolean;
27
+ /** Called after any successful mutation (create / update / patch / remove). */
28
+ onMutationSuccess?: (data: T | undefined, action: string) => void;
29
+ /** Called after a failed mutation, receives the error and action name. */
30
+ onMutationError?: (error: Error, action: string) => void;
31
+ }
32
+ /** Return value of `useResource()`. */
33
+ export interface UseResourceReturn<T> {
34
+ /** Reactive resource data. */
35
+ data: Signal<T | undefined>;
36
+ /** Last error. */
37
+ error: Signal<Error | null>;
38
+ /** Lifecycle status for the initial fetch. */
39
+ status: Signal<AsyncDataStatus>;
40
+ /** Whether the initial fetch is pending. */
41
+ pending: {
42
+ readonly value: boolean;
43
+ peek(): boolean;
44
+ };
45
+ /** Whether any mutation is in progress. */
46
+ isMutating: {
47
+ readonly value: boolean;
48
+ peek(): boolean;
49
+ };
50
+ /** CRUD actions. */
51
+ actions: ResourceActions<T>;
52
+ /** Refresh the resource (re-GET). */
53
+ refresh: () => Promise<T | undefined>;
54
+ /** Clear data, error, and status. */
55
+ clear: () => void;
56
+ /** Dispose all reactive state and prevent future operations. */
57
+ dispose: () => void;
58
+ }
59
+ /**
60
+ * Reactive REST resource composable providing CRUD operations.
61
+ *
62
+ * Binds a base URL to a resource and exposes `fetch`, `create`, `update`,
63
+ * `patch`, and `remove` helpers with optional optimistic updates.
64
+ *
65
+ * @template T - Resource data type
66
+ * @param url - Resource endpoint URL or getter
67
+ * @param options - Fetch and resource options
68
+ * @returns Reactive resource state with CRUD actions
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * import { useResource } from '@bquery/bquery/reactive';
73
+ *
74
+ * const user = useResource<User>('/api/users/1', {
75
+ * baseUrl: 'https://api.example.com',
76
+ * optimistic: true,
77
+ * });
78
+ *
79
+ * // Read
80
+ * await user.actions.fetch();
81
+ *
82
+ * // Update
83
+ * await user.actions.patch({ name: 'Ada' });
84
+ *
85
+ * // Delete
86
+ * await user.actions.remove();
87
+ * ```
88
+ */
89
+ export declare const useResource: <T = unknown>(url: string | URL | (() => string | URL), options?: UseResourceOptions<T>) => UseResourceReturn<T>;
90
+ /** Options for `useSubmit()`. */
91
+ export interface UseSubmitOptions<TResponse = unknown> extends Omit<UseFetchOptions<TResponse>, 'body' | 'immediate'> {
92
+ /** HTTP method (default: `'POST'`). */
93
+ method?: string;
94
+ }
95
+ /** Return value of `useSubmit()`. */
96
+ export interface UseSubmitReturn<TResponse = unknown> {
97
+ /** Last response data. */
98
+ data: Signal<TResponse | undefined>;
99
+ /** Last error. */
100
+ error: Signal<Error | null>;
101
+ /** Current status. */
102
+ status: Signal<AsyncDataStatus>;
103
+ /** Whether the submission is pending. */
104
+ pending: {
105
+ readonly value: boolean;
106
+ peek(): boolean;
107
+ };
108
+ /** Submit data to the endpoint. */
109
+ submit: (body: Record<string, unknown> | FormData | BodyInit) => Promise<TResponse | undefined>;
110
+ /** Reset state. */
111
+ clear: () => void;
112
+ }
113
+ /**
114
+ * Reactive form submission composable.
115
+ *
116
+ * Provides a `submit()` function that sends data to an endpoint with
117
+ * reactive status, data, and error signals.
118
+ *
119
+ * @template TResponse - Response data type
120
+ * @param url - Submission endpoint URL
121
+ * @param options - Fetch options (method defaults to POST)
122
+ * @returns Reactive submission state with `submit()` and `clear()`
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * import { useSubmit } from '@bquery/bquery/reactive';
127
+ *
128
+ * const form = useSubmit<{ id: number }>('/api/users', {
129
+ * baseUrl: 'https://api.example.com',
130
+ * headers: { 'x-csrf': token },
131
+ * });
132
+ *
133
+ * const result = await form.submit({ name: 'Ada', email: 'ada@example.com' });
134
+ * console.log(form.status.value); // 'success'
135
+ * ```
136
+ */
137
+ export declare const useSubmit: <TResponse = unknown>(url: string | URL, options?: UseSubmitOptions<TResponse>) => UseSubmitReturn<TResponse>;
138
+ /** Typed CRUD methods for a REST endpoint. */
139
+ export interface RestClient<T = unknown> {
140
+ /** GET all items. */
141
+ list: (config?: HttpRequestConfig) => Promise<HttpResponse<T[]>>;
142
+ /** GET a single item by ID. */
143
+ get: (id: string | number, config?: HttpRequestConfig) => Promise<HttpResponse<T>>;
144
+ /** POST a new item. */
145
+ create: (body: Partial<T> | Record<string, unknown>, config?: HttpRequestConfig) => Promise<HttpResponse<T>>;
146
+ /** PUT (full replace) an item by ID. */
147
+ update: (id: string | number, body: Partial<T> | Record<string, unknown>, config?: HttpRequestConfig) => Promise<HttpResponse<T>>;
148
+ /** PATCH (partial update) an item by ID. */
149
+ patch: (id: string | number, body: Partial<T> | Record<string, unknown>, config?: HttpRequestConfig) => Promise<HttpResponse<T>>;
150
+ /** DELETE an item by ID. */
151
+ remove: (id: string | number, config?: HttpRequestConfig) => Promise<HttpResponse<void>>;
152
+ /** The underlying HttpClient instance. */
153
+ http: HttpClient;
154
+ }
155
+ /**
156
+ * Create a typed REST client for a specific API resource.
157
+ *
158
+ * Wraps `createHttp()` and maps standard CRUD operations to their
159
+ * conventional REST endpoints (`GET /`, `GET /:id`, `POST /`, `PUT /:id`,
160
+ * `PATCH /:id`, `DELETE /:id`).
161
+ *
162
+ * @template T - Resource item type
163
+ * @param baseUrl - Base URL of the resource (e.g. `https://api.example.com/users`)
164
+ * @param defaults - Default request configuration merged into every call
165
+ * @returns Typed REST client with `list`, `get`, `create`, `update`, `patch`, `remove`
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * import { createRestClient } from '@bquery/bquery/reactive';
170
+ *
171
+ * interface User { id: number; name: string; email: string }
172
+ *
173
+ * const users = createRestClient<User>('https://api.example.com/users', {
174
+ * headers: { authorization: '******' },
175
+ * timeout: 10_000,
176
+ * });
177
+ *
178
+ * const { data: allUsers } = await users.list();
179
+ * const { data: user } = await users.get(1);
180
+ * const { data: created } = await users.create({ name: 'Ada' });
181
+ * await users.update(1, { name: 'Ada', email: 'ada@example.com' });
182
+ * await users.patch(1, { email: 'new@example.com' });
183
+ * await users.remove(1);
184
+ * ```
185
+ */
186
+ export declare const createRestClient: <T = unknown>(baseUrl: string, defaults?: HttpRequestConfig) => RestClient<T>;
187
+ /** Extract a unique identifier from an item. */
188
+ export type IdExtractor<T> = (item: T) => string | number;
189
+ /** Options for `useResourceList()`. */
190
+ export interface UseResourceListOptions<T = unknown> extends Omit<UseFetchOptions<T[]>, 'method' | 'body'> {
191
+ /** Extract the unique ID from each item (default: `item.id`). */
192
+ getId?: IdExtractor<T>;
193
+ /** Enable optimistic list mutations (default: false). */
194
+ optimistic?: boolean;
195
+ /** Called after a successful list mutation. */
196
+ onMutationSuccess?: (action: string) => void;
197
+ /** Called after a failed list mutation. */
198
+ onMutationError?: (error: Error, action: string) => void;
199
+ }
200
+ /** CRUD actions for a list resource. */
201
+ export interface ResourceListActions<T> {
202
+ /** Refresh the list (GET). */
203
+ fetch: () => Promise<T[] | undefined>;
204
+ /** Add a new item to the list (POST). */
205
+ add: (body: Partial<T> | Record<string, unknown>) => Promise<T | undefined>;
206
+ /** Update an existing item (PUT) by ID. */
207
+ update: (id: string | number, body: Partial<T> | Record<string, unknown>) => Promise<T | undefined>;
208
+ /** Partially update an existing item (PATCH) by ID. */
209
+ patch: (id: string | number, body: Partial<T> | Record<string, unknown>) => Promise<T | undefined>;
210
+ /** Remove an item from the list (DELETE) by ID. */
211
+ remove: (id: string | number) => Promise<void>;
212
+ }
213
+ /** Return value of `useResourceList()`. */
214
+ export interface UseResourceListReturn<T> {
215
+ /** Reactive list data. */
216
+ data: Signal<T[] | undefined>;
217
+ /** Last error. */
218
+ error: Signal<Error | null>;
219
+ /** Lifecycle status. */
220
+ status: Signal<AsyncDataStatus>;
221
+ /** Whether the list fetch is pending. */
222
+ pending: {
223
+ readonly value: boolean;
224
+ peek(): boolean;
225
+ };
226
+ /** Whether any mutation is in progress. */
227
+ isMutating: {
228
+ readonly value: boolean;
229
+ peek(): boolean;
230
+ };
231
+ /** CRUD actions. */
232
+ actions: ResourceListActions<T>;
233
+ /** Refresh the list. */
234
+ refresh: () => Promise<T[] | undefined>;
235
+ /** Clear data, error, and status. */
236
+ clear: () => void;
237
+ /** Dispose all reactive state. */
238
+ dispose: () => void;
239
+ }
240
+ /**
241
+ * Reactive list/collection CRUD composable with optimistic add, remove, and update.
242
+ *
243
+ * Fetches a list of items and provides typed CRUD helpers that update the
244
+ * reactive array optimistically or after server confirmation.
245
+ *
246
+ * @template T - Item type
247
+ * @param url - List endpoint URL or getter
248
+ * @param options - Fetch and list options
249
+ * @returns Reactive list state with CRUD actions
250
+ *
251
+ * @example
252
+ * ```ts
253
+ * import { useResourceList } from '@bquery/bquery/reactive';
254
+ *
255
+ * interface Todo { id: number; title: string; done: boolean }
256
+ *
257
+ * const todos = useResourceList<Todo>('/api/todos', {
258
+ * baseUrl: 'https://api.example.com',
259
+ * optimistic: true,
260
+ * getId: (t) => t.id,
261
+ * });
262
+ *
263
+ * await todos.actions.add({ title: 'Buy milk', done: false });
264
+ * await todos.actions.patch(1, { done: true });
265
+ * await todos.actions.remove(1);
266
+ * ```
267
+ */
268
+ export declare const useResourceList: <T = unknown>(url: string | URL | (() => string | URL), options?: UseResourceListOptions<T>) => UseResourceListReturn<T>;
269
+ /**
270
+ * Deduplicate identical in-flight requests or operations keyed by `key`.
271
+ *
272
+ * If an operation with the same key is already in flight, reuse its promise
273
+ * instead of starting a new one. Once the operation completes, the entry is removed.
274
+ *
275
+ * @param key - Cache key for the in-flight operation (for HTTP, typically URL + serialized query)
276
+ * @param execute - The operation function to run if no duplicate is in flight
277
+ * @returns The shared result promise for callers using the same key concurrently
278
+ *
279
+ * @example
280
+ * ```ts
281
+ * import { deduplicateRequest, createHttp } from '@bquery/bquery/reactive';
282
+ *
283
+ * const api = createHttp({ baseUrl: 'https://api.example.com' });
284
+ *
285
+ * // Both calls share the same in-flight operation
286
+ * const [a, b] = await Promise.all([
287
+ * deduplicateRequest('/users', () => api.get('/users')),
288
+ * deduplicateRequest('/users', () => api.get('/users')),
289
+ * ]);
290
+ * ```
291
+ */
292
+ export declare function deduplicateRequest<T>(key: string, execute: () => Promise<T>): Promise<T>;
293
+ //# sourceMappingURL=rest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rest.d.ts","sourceRoot":"","sources":["../../src/reactive/rest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Reactive effect scopes for grouped disposal.
3
+ *
4
+ * An `EffectScope` collects all effects, computed values, and watches created
5
+ * inside its `run()` callback so they can be disposed together with a single
6
+ * `stop()` call. Scopes nest — an inner scope is collected by its parent.
7
+ *
8
+ * @module bquery/reactive
9
+ */
10
+ import type { CleanupFn } from './internals';
11
+ /**
12
+ * A scope that collects reactive resources for grouped disposal.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { effectScope, signal, effect, computed } from '@bquery/bquery/reactive';
17
+ *
18
+ * const scope = effectScope();
19
+ *
20
+ * scope.run(() => {
21
+ * const count = signal(0);
22
+ * effect(() => console.log(count.value));
23
+ * const doubled = computed(() => count.value * 2);
24
+ * });
25
+ *
26
+ * scope.stop(); // All effects and computed values disposed
27
+ * ```
28
+ */
29
+ export interface EffectScope {
30
+ /** Whether the scope has not yet been stopped. */
31
+ readonly active: boolean;
32
+ /**
33
+ * Executes `fn` inside this scope, collecting any reactive resources
34
+ * (effects, computed values, watches, nested scopes) created during the call.
35
+ *
36
+ * `run()` is synchronous-only. Do not pass an async function or a function
37
+ * that returns a Promise — resources created after an `await` cannot be
38
+ * collected reliably.
39
+ *
40
+ * @template T - Return type of the provided function
41
+ * @param fn - Function to run inside the scope
42
+ * @returns The return value of `fn`
43
+ * @throws {Error} If the scope has already been stopped
44
+ */
45
+ run<T>(fn: () => T): T;
46
+ /**
47
+ * Disposes all collected resources and marks the scope as inactive.
48
+ * Calling `stop()` on an already-stopped scope is a safe no-op.
49
+ */
50
+ stop(): void;
51
+ }
52
+ /** @internal */
53
+ export declare const hasScopeDisposer: (scope: EffectScope | undefined) => scope is EffectScope & {
54
+ _addDisposer(fn: CleanupFn): void;
55
+ };
56
+ /**
57
+ * Returns the currently active scope, or `undefined` if none.
58
+ * @internal
59
+ */
60
+ export declare const getActiveScope: () => EffectScope | undefined;
61
+ /**
62
+ * Creates a new effect scope for grouped disposal of reactive resources.
63
+ *
64
+ * All `effect()`, `computed()`, `watch()`, and nested `effectScope()` calls
65
+ * made inside `scope.run(fn)` are automatically collected. Calling
66
+ * `scope.stop()` disposes them all at once.
67
+ *
68
+ * `run()` is synchronous-only. Create the scope outside async flows when
69
+ * needed, but keep the callback itself synchronous so cleanup registration
70
+ * stays deterministic.
71
+ *
72
+ * @returns A new {@link EffectScope}
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * import { effectScope, signal, effect, onScopeDispose } from '@bquery/bquery/reactive';
77
+ *
78
+ * const scope = effectScope();
79
+ *
80
+ * scope.run(() => {
81
+ * const count = signal(0);
82
+ *
83
+ * effect(() => console.log(count.value));
84
+ *
85
+ * onScopeDispose(() => {
86
+ * console.log('Custom cleanup');
87
+ * });
88
+ * });
89
+ *
90
+ * scope.stop(); // logs "Custom cleanup", all effects stopped
91
+ * ```
92
+ */
93
+ export declare const effectScope: () => EffectScope;
94
+ /**
95
+ * Returns the currently active {@link EffectScope}, or `undefined` if
96
+ * code is not running inside any scope's `run()` callback.
97
+ *
98
+ * @returns The active scope, or `undefined`
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * import { effectScope, getCurrentScope } from '@bquery/bquery/reactive';
103
+ *
104
+ * const scope = effectScope();
105
+ * scope.run(() => {
106
+ * console.log(getCurrentScope() !== undefined); // true
107
+ * });
108
+ *
109
+ * console.log(getCurrentScope()); // undefined
110
+ * ```
111
+ */
112
+ export declare const getCurrentScope: () => EffectScope | undefined;
113
+ /**
114
+ * Registers a cleanup callback on the currently active scope.
115
+ *
116
+ * The callback runs when the scope is stopped. This is useful for
117
+ * registering arbitrary cleanup (e.g. event listeners, timers)
118
+ * alongside effects and computed values.
119
+ *
120
+ * @param fn - Cleanup function to run when the scope stops
121
+ * @throws {Error} If called outside an active scope
122
+ *
123
+ * @example
124
+ * ```ts
125
+ * import { effectScope, onScopeDispose } from '@bquery/bquery/reactive';
126
+ *
127
+ * const scope = effectScope();
128
+ *
129
+ * scope.run(() => {
130
+ * const controller = new AbortController();
131
+ * fetch('/api/data', { signal: controller.signal });
132
+ *
133
+ * onScopeDispose(() => controller.abort());
134
+ * });
135
+ *
136
+ * scope.stop(); // abort() is called
137
+ * ```
138
+ */
139
+ export declare const onScopeDispose: (fn: CleanupFn) => void;
140
+ //# sourceMappingURL=scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/reactive/scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAM7C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,WAAW;IAC1B,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEzB;;;;;;;;;;;;OAYG;IACH,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAEvB;;;OAGG;IACH,IAAI,IAAI,IAAI,CAAC;CACd;AAcD,gBAAgB;AAChB,eAAO,MAAM,gBAAgB,GAC3B,OAAO,WAAW,GAAG,SAAS,KAC7B,KAAK,IAAI,WAAW,GAAG;IAAE,YAAY,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI,CAAA;CACW,CAAC;AA2BzE;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAO,WAAW,GAAG,SAQ/C,CAAC;AA8DF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,WAAW,QAAO,WAU9B,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,eAAe,QAAO,WAAW,GAAG,SAA6B,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,cAAc,GAAI,IAAI,SAAS,KAAG,IAQ9C,CAAC"}
@@ -8,14 +8,28 @@ export { createUseFetch, useAsyncData, useFetch } from './async-data';
8
8
  export { Computed, computed } from './computed';
9
9
  export { Signal, signal } from './core';
10
10
  export { effect } from './effect';
11
+ export { createHttp, createRequestQueue, http, HttpError } from './http';
11
12
  export { linkedSignal } from './linked';
13
+ export { useInfiniteFetch, usePaginatedFetch } from './pagination';
12
14
  export { persistedSignal } from './persisted';
15
+ export { usePolling } from './polling';
13
16
  export { readonly } from './readonly';
17
+ export { createRestClient, deduplicateRequest, useResource, useResourceList, useSubmit, } from './rest';
18
+ export { effectScope, getCurrentScope, onScopeDispose } from './scope';
14
19
  export { isComputed, isSignal } from './type-guards';
20
+ export { toValue } from './to-value';
15
21
  export { untrack } from './untrack';
16
22
  export { watch } from './watch';
23
+ export { useEventSource, useWebSocket, useWebSocketChannel } from './websocket';
17
24
  export type { CleanupFn, Observer } from './internals';
18
- export type { AsyncDataState, AsyncDataStatus, AsyncWatchSource, FetchInput, UseAsyncDataOptions, UseFetchOptions, } from './async-data';
25
+ export type { AsyncDataState, AsyncDataStatus, AsyncWatchSource, FetchInput, UseAsyncDataOptions, UseFetchOptions, UseFetchRetryConfig, } from './async-data';
26
+ export type { HttpClient, HttpProgressEvent, HttpRequestConfig, HttpResponse, Interceptor, InterceptorManager, RequestQueue, RequestQueueOptions, RetryConfig, } from './http';
27
+ export type { InfiniteState, PaginatedState, UseInfiniteFetchOptions, UsePaginatedFetchOptions, } from './pagination';
28
+ export type { PollingState, UsePollingOptions } from './polling';
29
+ export type { IdExtractor, ResourceListActions, RestClient, UseResourceListOptions, UseResourceListReturn, UseResourceOptions, UseResourceReturn, UseSubmitOptions, UseSubmitReturn, } from './rest';
30
+ export type { EffectScope } from './scope';
19
31
  export type { LinkedSignal } from './linked';
20
- export type { ReadonlySignal } from './readonly';
32
+ export type { MaybeSignal } from './to-value';
33
+ export type { ReadonlySignal, ReadonlySignalHandle } from './readonly';
34
+ export type { ChannelMessage, ChannelSubscription, EventSourceStatus, UseEventSourceOptions, UseEventSourceReturn, UseWebSocketChannelOptions, UseWebSocketChannelReturn, UseWebSocketOptions, UseWebSocketReturn, WebSocketHeartbeatConfig, WebSocketReconnectConfig, WebSocketSerializer, WebSocketStatus, } from './websocket';
21
35
  //# sourceMappingURL=signal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"signal.d.ts","sourceRoot":"","sources":["../../src/reactive/signal.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,mBAAmB,EACnB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"signal.d.ts","sourceRoot":"","sources":["../../src/reactive/signal.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,eAAe,EACf,SAAS,GACV,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEhF,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EACV,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,WAAW,GACZ,MAAM,QAAQ,CAAC;AAChB,YAAY,EACV,aAAa,EACb,cAAc,EACd,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACjE,YAAY,EACV,WAAW,EACX,mBAAmB,EACnB,UAAU,EACV,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,GAChB,MAAM,QAAQ,CAAC;AAChB,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvE,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,eAAe,GAChB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Utility to unwrap reactive or plain values.
3
+ */
4
+ import { Computed } from './computed';
5
+ import { Signal } from './core';
6
+ import { readonly } from './readonly';
7
+ /**
8
+ * A value that may be a raw value, a Signal, a `readonly()` wrapper, or a Computed.
9
+ *
10
+ * Useful for APIs that accept both reactive and plain inputs.
11
+ *
12
+ * Readonly wrappers are limited to the values returned by {@link readonly}. This keeps
13
+ * the type aligned with runtime behavior, where arbitrary structural `{ value, peek }`
14
+ * objects are intentionally returned unchanged.
15
+ *
16
+ * @template T - The underlying value type
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * function useTitle(title: MaybeSignal<string>) {
21
+ * document.title = toValue(title);
22
+ * }
23
+ *
24
+ * useTitle('Hello'); // plain string
25
+ * useTitle(signal('Hello')); // reactive signal
26
+ * useTitle(computed(() => 'Hi')); // computed value
27
+ * ```
28
+ */
29
+ export type MaybeSignal<T> = T | Signal<T> | ReturnType<typeof readonly<T>> | Computed<T>;
30
+ /**
31
+ * Extracts the current value from a Signal, a bQuery `readonly()` wrapper, a
32
+ * Computed, or returns the raw value as-is. This eliminates repetitive
33
+ * `isSignal(x) ? x.value : x` patterns throughout user code.
34
+ *
35
+ * Reading a Signal or Computed via `toValue()` uses `.value`, so the
36
+ * read **does** participate in reactive tracking when called inside
37
+ * an effect or computed.
38
+ *
39
+ * @template T - The underlying value type
40
+ * @param source - A plain value, Signal, bQuery readonly wrapper, or Computed
41
+ * @returns The unwrapped value
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * import { signal, computed, toValue } from '@bquery/bquery/reactive';
46
+ *
47
+ * const count = signal(5);
48
+ * const doubled = computed(() => count.value * 2);
49
+ *
50
+ * toValue(42); // 42
51
+ * toValue(count); // 5
52
+ * toValue(doubled); // 10
53
+ * toValue(null); // null
54
+ * ```
55
+ */
56
+ export declare const toValue: <T>(source: MaybeSignal<T>) => T;
57
+ //# sourceMappingURL=to-value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to-value.d.ts","sourceRoot":"","sources":["../../src/reactive/to-value.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAoB,MAAM,YAAY,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AAE1F;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,OAAO,GAAI,CAAC,EAAE,QAAQ,WAAW,CAAC,CAAC,CAAC,KAAG,CAYnD,CAAC"}