@bquery/bquery 1.6.0 → 1.8.1

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 (402) hide show
  1. package/README.md +192 -18
  2. package/dist/a11y/announce.d.ts +43 -0
  3. package/dist/a11y/announce.d.ts.map +1 -0
  4. package/dist/a11y/audit.d.ts +42 -0
  5. package/dist/a11y/audit.d.ts.map +1 -0
  6. package/dist/a11y/index.d.ts +53 -0
  7. package/dist/a11y/index.d.ts.map +1 -0
  8. package/dist/a11y/media-preferences.d.ts +77 -0
  9. package/dist/a11y/media-preferences.d.ts.map +1 -0
  10. package/dist/a11y/roving-tab-index.d.ts +38 -0
  11. package/dist/a11y/roving-tab-index.d.ts.map +1 -0
  12. package/dist/a11y/skip-link.d.ts +37 -0
  13. package/dist/a11y/skip-link.d.ts.map +1 -0
  14. package/dist/a11y/trap-focus.d.ts +49 -0
  15. package/dist/a11y/trap-focus.d.ts.map +1 -0
  16. package/dist/a11y/types.d.ts +152 -0
  17. package/dist/a11y/types.d.ts.map +1 -0
  18. package/dist/a11y-DVBCy09c.js +421 -0
  19. package/dist/a11y-DVBCy09c.js.map +1 -0
  20. package/dist/a11y.es.mjs +14 -0
  21. package/dist/component/component.d.ts.map +1 -1
  22. package/dist/component/html.d.ts.map +1 -1
  23. package/dist/component/index.d.ts +2 -1
  24. package/dist/component/index.d.ts.map +1 -1
  25. package/dist/component/library.d.ts.map +1 -1
  26. package/dist/component/scope.d.ts +138 -0
  27. package/dist/component/scope.d.ts.map +1 -0
  28. package/dist/component/types.d.ts +53 -1
  29. package/dist/component/types.d.ts.map +1 -1
  30. package/dist/component-L3-JfOFz.js +684 -0
  31. package/dist/component-L3-JfOFz.js.map +1 -0
  32. package/dist/component.es.mjs +9 -6
  33. package/dist/{config-DRmZZno3.js → config-DhT9auRm.js} +4 -4
  34. package/dist/{config-DRmZZno3.js.map → config-DhT9auRm.js.map} +1 -1
  35. package/dist/constraints-D5RHQLmP.js +100 -0
  36. package/dist/constraints-D5RHQLmP.js.map +1 -0
  37. package/dist/core/collection.d.ts +134 -0
  38. package/dist/core/collection.d.ts.map +1 -1
  39. package/dist/core/element.d.ts +120 -0
  40. package/dist/core/element.d.ts.map +1 -1
  41. package/dist/core/env.d.ts +18 -0
  42. package/dist/core/env.d.ts.map +1 -0
  43. package/dist/core/index.d.ts +1 -0
  44. package/dist/core/index.d.ts.map +1 -1
  45. package/dist/core/shared.d.ts +14 -0
  46. package/dist/core/shared.d.ts.map +1 -1
  47. package/dist/core/utils/index.d.ts +52 -41
  48. package/dist/core/utils/index.d.ts.map +1 -1
  49. package/dist/core-DdtZHzsS.js +168 -0
  50. package/dist/core-DdtZHzsS.js.map +1 -0
  51. package/dist/{core-CCEabVHl.js → core-EMYSLzaT.js} +293 -194
  52. package/dist/core-EMYSLzaT.js.map +1 -0
  53. package/dist/core.es.mjs +48 -46
  54. package/dist/custom-directives-Dr4C5lVV.js +9 -0
  55. package/dist/custom-directives-Dr4C5lVV.js.map +1 -0
  56. package/dist/devtools/devtools.d.ts +212 -0
  57. package/dist/devtools/devtools.d.ts.map +1 -0
  58. package/dist/devtools/index.d.ts +20 -0
  59. package/dist/devtools/index.d.ts.map +1 -0
  60. package/dist/devtools/types.d.ts +69 -0
  61. package/dist/devtools/types.d.ts.map +1 -0
  62. package/dist/devtools-BhB2iDPT.js +122 -0
  63. package/dist/devtools-BhB2iDPT.js.map +1 -0
  64. package/dist/devtools.es.mjs +19 -0
  65. package/dist/dnd/draggable.d.ts +51 -0
  66. package/dist/dnd/draggable.d.ts.map +1 -0
  67. package/dist/dnd/droppable.d.ts +38 -0
  68. package/dist/dnd/droppable.d.ts.map +1 -0
  69. package/dist/dnd/index.d.ts +47 -0
  70. package/dist/dnd/index.d.ts.map +1 -0
  71. package/dist/dnd/sortable.d.ts +43 -0
  72. package/dist/dnd/sortable.d.ts.map +1 -0
  73. package/dist/dnd/types.d.ts +250 -0
  74. package/dist/dnd/types.d.ts.map +1 -0
  75. package/dist/dnd-NwZBYh4l.js +244 -0
  76. package/dist/dnd-NwZBYh4l.js.map +1 -0
  77. package/dist/dnd.es.mjs +6 -0
  78. package/dist/env-CTdvLaH2.js +19 -0
  79. package/dist/env-CTdvLaH2.js.map +1 -0
  80. package/dist/forms/create-form.d.ts +49 -0
  81. package/dist/forms/create-form.d.ts.map +1 -0
  82. package/dist/forms/index.d.ts +40 -0
  83. package/dist/forms/index.d.ts.map +1 -0
  84. package/dist/forms/types.d.ts +185 -0
  85. package/dist/forms/types.d.ts.map +1 -0
  86. package/dist/forms/use-field.d.ts +34 -0
  87. package/dist/forms/use-field.d.ts.map +1 -0
  88. package/dist/forms/validators.d.ts +204 -0
  89. package/dist/forms/validators.d.ts.map +1 -0
  90. package/dist/forms-UcRHsYxC.js +227 -0
  91. package/dist/forms-UcRHsYxC.js.map +1 -0
  92. package/dist/forms.es.mjs +16 -0
  93. package/dist/full.d.ts +30 -11
  94. package/dist/full.d.ts.map +1 -1
  95. package/dist/full.es.mjs +209 -93
  96. package/dist/full.iife.js +47 -31
  97. package/dist/full.iife.js.map +1 -1
  98. package/dist/full.umd.js +47 -31
  99. package/dist/full.umd.js.map +1 -1
  100. package/dist/function-Cybd57JV.js +33 -0
  101. package/dist/function-Cybd57JV.js.map +1 -0
  102. package/dist/i18n/formatting.d.ts +40 -0
  103. package/dist/i18n/formatting.d.ts.map +1 -0
  104. package/dist/i18n/i18n.d.ts +48 -0
  105. package/dist/i18n/i18n.d.ts.map +1 -0
  106. package/dist/i18n/index.d.ts +57 -0
  107. package/dist/i18n/index.d.ts.map +1 -0
  108. package/dist/i18n/translate.d.ts +83 -0
  109. package/dist/i18n/translate.d.ts.map +1 -0
  110. package/dist/i18n/types.d.ts +156 -0
  111. package/dist/i18n/types.d.ts.map +1 -0
  112. package/dist/i18n-kuF6Ekj6.js +89 -0
  113. package/dist/i18n-kuF6Ekj6.js.map +1 -0
  114. package/dist/i18n.es.mjs +6 -0
  115. package/dist/index.d.ts +11 -0
  116. package/dist/index.d.ts.map +1 -1
  117. package/dist/index.es.mjs +257 -143
  118. package/dist/media/battery.d.ts +35 -0
  119. package/dist/media/battery.d.ts.map +1 -0
  120. package/dist/media/breakpoints.d.ts +51 -0
  121. package/dist/media/breakpoints.d.ts.map +1 -0
  122. package/dist/media/clipboard.d.ts +30 -0
  123. package/dist/media/clipboard.d.ts.map +1 -0
  124. package/dist/media/device-sensors.d.ts +54 -0
  125. package/dist/media/device-sensors.d.ts.map +1 -0
  126. package/dist/media/geolocation.d.ts +38 -0
  127. package/dist/media/geolocation.d.ts.map +1 -0
  128. package/dist/media/index.d.ts +42 -0
  129. package/dist/media/index.d.ts.map +1 -0
  130. package/dist/media/media-query.d.ts +36 -0
  131. package/dist/media/media-query.d.ts.map +1 -0
  132. package/dist/media/network.d.ts +35 -0
  133. package/dist/media/network.d.ts.map +1 -0
  134. package/dist/media/types.d.ts +173 -0
  135. package/dist/media/types.d.ts.map +1 -0
  136. package/dist/media/viewport.d.ts +32 -0
  137. package/dist/media/viewport.d.ts.map +1 -0
  138. package/dist/media-i-fB5WxI.js +340 -0
  139. package/dist/media-i-fB5WxI.js.map +1 -0
  140. package/dist/media.es.mjs +12 -0
  141. package/dist/motion/index.d.ts +7 -3
  142. package/dist/motion/index.d.ts.map +1 -1
  143. package/dist/motion/morph.d.ts +27 -0
  144. package/dist/motion/morph.d.ts.map +1 -0
  145. package/dist/motion/parallax.d.ts +30 -0
  146. package/dist/motion/parallax.d.ts.map +1 -0
  147. package/dist/motion/reduced-motion.d.ts +36 -3
  148. package/dist/motion/reduced-motion.d.ts.map +1 -1
  149. package/dist/motion/types.d.ts +58 -0
  150. package/dist/motion/types.d.ts.map +1 -1
  151. package/dist/motion/typewriter.d.ts +31 -0
  152. package/dist/motion/typewriter.d.ts.map +1 -0
  153. package/dist/motion-BJsAuULb.js +530 -0
  154. package/dist/motion-BJsAuULb.js.map +1 -0
  155. package/dist/motion.es.mjs +27 -23
  156. package/dist/{view-C70lA3vf.js → mount-B4Y8bk8Z.js} +166 -160
  157. package/dist/mount-B4Y8bk8Z.js.map +1 -0
  158. package/dist/{object-qGpWr6-J.js → object-BCk-1c8T.js} +5 -4
  159. package/dist/{object-qGpWr6-J.js.map → object-BCk-1c8T.js.map} +1 -1
  160. package/dist/{platform-Dr9b6fsq.js → platform-Dw2gE3zI.js} +21 -22
  161. package/dist/{platform-Dr9b6fsq.js.map → platform-Dw2gE3zI.js.map} +1 -1
  162. package/dist/platform.es.mjs +2 -2
  163. package/dist/plugin/index.d.ts +22 -0
  164. package/dist/plugin/index.d.ts.map +1 -0
  165. package/dist/plugin/registry.d.ts +108 -0
  166. package/dist/plugin/registry.d.ts.map +1 -0
  167. package/dist/plugin/types.d.ts +110 -0
  168. package/dist/plugin/types.d.ts.map +1 -0
  169. package/dist/plugin-C2WuC8SF.js +66 -0
  170. package/dist/plugin-C2WuC8SF.js.map +1 -0
  171. package/dist/plugin.es.mjs +9 -0
  172. package/dist/reactive/async-data.d.ts +28 -3
  173. package/dist/reactive/async-data.d.ts.map +1 -1
  174. package/dist/reactive/computed.d.ts +10 -0
  175. package/dist/reactive/computed.d.ts.map +1 -1
  176. package/dist/reactive/effect.d.ts +3 -0
  177. package/dist/reactive/effect.d.ts.map +1 -1
  178. package/dist/reactive/http.d.ts +194 -0
  179. package/dist/reactive/http.d.ts.map +1 -0
  180. package/dist/reactive/index.d.ts +2 -2
  181. package/dist/reactive/index.d.ts.map +1 -1
  182. package/dist/reactive/pagination.d.ts +126 -0
  183. package/dist/reactive/pagination.d.ts.map +1 -0
  184. package/dist/reactive/polling.d.ts +55 -0
  185. package/dist/reactive/polling.d.ts.map +1 -0
  186. package/dist/reactive/readonly.d.ts +20 -1
  187. package/dist/reactive/readonly.d.ts.map +1 -1
  188. package/dist/reactive/rest.d.ts +293 -0
  189. package/dist/reactive/rest.d.ts.map +1 -0
  190. package/dist/reactive/scope.d.ts +140 -0
  191. package/dist/reactive/scope.d.ts.map +1 -0
  192. package/dist/reactive/signal.d.ts +16 -2
  193. package/dist/reactive/signal.d.ts.map +1 -1
  194. package/dist/reactive/to-value.d.ts +57 -0
  195. package/dist/reactive/to-value.d.ts.map +1 -0
  196. package/dist/reactive/websocket.d.ts +285 -0
  197. package/dist/reactive/websocket.d.ts.map +1 -0
  198. package/dist/reactive-DwkhUJfP.js +1148 -0
  199. package/dist/reactive-DwkhUJfP.js.map +1 -0
  200. package/dist/reactive.es.mjs +38 -20
  201. package/dist/registry-B08iilIh.js +26 -0
  202. package/dist/registry-B08iilIh.js.map +1 -0
  203. package/dist/router/bq-link.d.ts +112 -0
  204. package/dist/router/bq-link.d.ts.map +1 -0
  205. package/dist/router/constraints.d.ts +9 -0
  206. package/dist/router/constraints.d.ts.map +1 -0
  207. package/dist/router/index.d.ts +15 -7
  208. package/dist/router/index.d.ts.map +1 -1
  209. package/dist/router/match.d.ts +0 -1
  210. package/dist/router/match.d.ts.map +1 -1
  211. package/dist/router/path-pattern.d.ts +14 -0
  212. package/dist/router/path-pattern.d.ts.map +1 -0
  213. package/dist/router/query.d.ts.map +1 -1
  214. package/dist/router/router.d.ts +3 -1
  215. package/dist/router/router.d.ts.map +1 -1
  216. package/dist/router/state.d.ts +25 -2
  217. package/dist/router/state.d.ts.map +1 -1
  218. package/dist/router/types.d.ts +48 -4
  219. package/dist/router/types.d.ts.map +1 -1
  220. package/dist/router/use-route.d.ts +50 -0
  221. package/dist/router/use-route.d.ts.map +1 -0
  222. package/dist/router/utils.d.ts +3 -0
  223. package/dist/router/utils.d.ts.map +1 -1
  224. package/dist/router-CQikC9Ed.js +492 -0
  225. package/dist/router-CQikC9Ed.js.map +1 -0
  226. package/dist/router.es.mjs +14 -10
  227. package/dist/{sanitize-Bs2dkMby.js → sanitize-B1V4JswB.js} +2 -1
  228. package/dist/{sanitize-Bs2dkMby.js.map → sanitize-B1V4JswB.js.map} +1 -1
  229. package/dist/security/index.d.ts +2 -2
  230. package/dist/security/index.d.ts.map +1 -1
  231. package/dist/security.es.mjs +1 -1
  232. package/dist/ssr/hydrate.d.ts +65 -0
  233. package/dist/ssr/hydrate.d.ts.map +1 -0
  234. package/dist/ssr/index.d.ts +59 -0
  235. package/dist/ssr/index.d.ts.map +1 -0
  236. package/dist/ssr/render.d.ts +62 -0
  237. package/dist/ssr/render.d.ts.map +1 -0
  238. package/dist/ssr/serialize.d.ts +118 -0
  239. package/dist/ssr/serialize.d.ts.map +1 -0
  240. package/dist/ssr/types.d.ts +70 -0
  241. package/dist/ssr/types.d.ts.map +1 -0
  242. package/dist/ssr-_dAcGdzu.js +248 -0
  243. package/dist/ssr-_dAcGdzu.js.map +1 -0
  244. package/dist/ssr.es.mjs +9 -0
  245. package/dist/store/create-store.d.ts.map +1 -1
  246. package/dist/store/index.d.ts +1 -1
  247. package/dist/store/index.d.ts.map +1 -1
  248. package/dist/store/persisted.d.ts +38 -4
  249. package/dist/store/persisted.d.ts.map +1 -1
  250. package/dist/store/types.d.ts +138 -1
  251. package/dist/store/types.d.ts.map +1 -1
  252. package/dist/store/utils.d.ts +2 -2
  253. package/dist/store/utils.d.ts.map +1 -1
  254. package/dist/store-Cb3gPRve.js +338 -0
  255. package/dist/store-Cb3gPRve.js.map +1 -0
  256. package/dist/store.es.mjs +11 -10
  257. package/dist/storybook/index.d.ts.map +1 -1
  258. package/dist/storybook.es.mjs +1 -1
  259. package/dist/storybook.es.mjs.map +1 -1
  260. package/dist/testing/index.d.ts +23 -0
  261. package/dist/testing/index.d.ts.map +1 -0
  262. package/dist/testing/testing.d.ts +156 -0
  263. package/dist/testing/testing.d.ts.map +1 -0
  264. package/dist/testing/types.d.ts +134 -0
  265. package/dist/testing/types.d.ts.map +1 -0
  266. package/dist/testing-C5Sjfsna.js +224 -0
  267. package/dist/testing-C5Sjfsna.js.map +1 -0
  268. package/dist/testing.es.mjs +9 -0
  269. package/dist/type-guards-BMX2c0LP.js +44 -0
  270. package/dist/type-guards-BMX2c0LP.js.map +1 -0
  271. package/dist/untrack-D0fnO5k2.js +36 -0
  272. package/dist/untrack-D0fnO5k2.js.map +1 -0
  273. package/dist/view/custom-directives.d.ts +20 -0
  274. package/dist/view/custom-directives.d.ts.map +1 -0
  275. package/dist/view/evaluate.d.ts.map +1 -1
  276. package/dist/view/process.d.ts.map +1 -1
  277. package/dist/view.es.mjs +9 -9
  278. package/package.json +47 -11
  279. package/src/a11y/announce.ts +131 -0
  280. package/src/a11y/audit.ts +314 -0
  281. package/src/a11y/index.ts +68 -0
  282. package/src/a11y/media-preferences.ts +255 -0
  283. package/src/a11y/roving-tab-index.ts +164 -0
  284. package/src/a11y/skip-link.ts +255 -0
  285. package/src/a11y/trap-focus.ts +184 -0
  286. package/src/a11y/types.ts +183 -0
  287. package/src/component/component.ts +599 -524
  288. package/src/component/html.ts +153 -153
  289. package/src/component/index.ts +52 -50
  290. package/src/component/library.ts +540 -518
  291. package/src/component/scope.ts +212 -0
  292. package/src/component/types.ts +310 -256
  293. package/src/core/collection.ts +249 -1
  294. package/src/core/element.ts +252 -11
  295. package/src/core/env.ts +60 -0
  296. package/src/core/index.ts +1 -0
  297. package/src/core/shared.ts +64 -0
  298. package/src/core/utils/index.ts +66 -1
  299. package/src/devtools/devtools.ts +410 -0
  300. package/src/devtools/index.ts +48 -0
  301. package/src/devtools/types.ts +104 -0
  302. package/src/dnd/draggable.ts +296 -0
  303. package/src/dnd/droppable.ts +228 -0
  304. package/src/dnd/index.ts +62 -0
  305. package/src/dnd/sortable.ts +307 -0
  306. package/src/dnd/types.ts +293 -0
  307. package/src/forms/create-form.ts +320 -0
  308. package/src/forms/index.ts +70 -0
  309. package/src/forms/types.ts +203 -0
  310. package/src/forms/use-field.ts +231 -0
  311. package/src/forms/validators.ts +294 -0
  312. package/src/full.ts +554 -229
  313. package/src/i18n/formatting.ts +67 -0
  314. package/src/i18n/i18n.ts +200 -0
  315. package/src/i18n/index.ts +67 -0
  316. package/src/i18n/translate.ts +182 -0
  317. package/src/i18n/types.ts +171 -0
  318. package/src/index.ts +72 -0
  319. package/src/media/battery.ts +116 -0
  320. package/src/media/breakpoints.ts +129 -0
  321. package/src/media/clipboard.ts +80 -0
  322. package/src/media/device-sensors.ts +158 -0
  323. package/src/media/geolocation.ts +119 -0
  324. package/src/media/index.ts +76 -0
  325. package/src/media/media-query.ts +92 -0
  326. package/src/media/network.ts +115 -0
  327. package/src/media/types.ts +177 -0
  328. package/src/media/viewport.ts +84 -0
  329. package/src/motion/index.ts +11 -2
  330. package/src/motion/morph.ts +151 -0
  331. package/src/motion/parallax.ts +120 -0
  332. package/src/motion/reduced-motion.ts +52 -3
  333. package/src/motion/types.ts +63 -0
  334. package/src/motion/typewriter.ts +164 -0
  335. package/src/plugin/index.ts +37 -0
  336. package/src/plugin/registry.ts +284 -0
  337. package/src/plugin/types.ts +137 -0
  338. package/src/reactive/async-data.ts +250 -29
  339. package/src/reactive/computed.ts +53 -1
  340. package/src/reactive/effect.ts +29 -6
  341. package/src/reactive/http.ts +790 -0
  342. package/src/reactive/index.ts +60 -0
  343. package/src/reactive/pagination.ts +317 -0
  344. package/src/reactive/polling.ts +179 -0
  345. package/src/reactive/readonly.ts +52 -8
  346. package/src/reactive/rest.ts +859 -0
  347. package/src/reactive/scope.ts +276 -0
  348. package/src/reactive/signal.ts +61 -1
  349. package/src/reactive/to-value.ts +71 -0
  350. package/src/reactive/websocket.ts +849 -0
  351. package/src/router/bq-link.ts +279 -0
  352. package/src/router/constraints.ts +204 -0
  353. package/src/router/index.ts +15 -7
  354. package/src/router/match.ts +255 -49
  355. package/src/router/path-pattern.ts +52 -0
  356. package/src/router/query.ts +3 -0
  357. package/src/router/router.ts +258 -48
  358. package/src/router/state.ts +51 -3
  359. package/src/router/types.ts +50 -4
  360. package/src/router/use-route.ts +68 -0
  361. package/src/router/utils.ts +44 -3
  362. package/src/security/index.ts +12 -17
  363. package/src/security/sanitize.ts +70 -70
  364. package/src/security/trusted-html.ts +71 -71
  365. package/src/ssr/hydrate.ts +84 -0
  366. package/src/ssr/index.ts +70 -0
  367. package/src/ssr/render.ts +508 -0
  368. package/src/ssr/serialize.ts +296 -0
  369. package/src/ssr/types.ts +81 -0
  370. package/src/store/create-store.ts +146 -8
  371. package/src/store/define-store.ts +49 -49
  372. package/src/store/index.ts +5 -0
  373. package/src/store/mapping.ts +74 -74
  374. package/src/store/persisted.ts +245 -62
  375. package/src/store/types.ts +247 -92
  376. package/src/store/utils.ts +4 -10
  377. package/src/store/watch.ts +53 -53
  378. package/src/storybook/index.ts +480 -479
  379. package/src/testing/index.ts +42 -0
  380. package/src/testing/testing.ts +593 -0
  381. package/src/testing/types.ts +170 -0
  382. package/src/view/custom-directives.ts +28 -0
  383. package/src/view/evaluate.ts +2 -0
  384. package/src/view/process.ts +19 -3
  385. package/dist/component-BEQgt5hl.js +0 -600
  386. package/dist/component-BEQgt5hl.js.map +0 -1
  387. package/dist/core-BGQJVw0-.js +0 -35
  388. package/dist/core-BGQJVw0-.js.map +0 -1
  389. package/dist/core-CCEabVHl.js.map +0 -1
  390. package/dist/effect-AFRW_Plg.js +0 -84
  391. package/dist/effect-AFRW_Plg.js.map +0 -1
  392. package/dist/motion-D9TcHxOF.js +0 -415
  393. package/dist/motion-D9TcHxOF.js.map +0 -1
  394. package/dist/reactive-DSkct0dO.js +0 -254
  395. package/dist/reactive-DSkct0dO.js.map +0 -1
  396. package/dist/router-CbDhl8rS.js +0 -188
  397. package/dist/router-CbDhl8rS.js.map +0 -1
  398. package/dist/store-BwDvI45q.js +0 -263
  399. package/dist/store-BwDvI45q.js.map +0 -1
  400. package/dist/untrack-B0rVscTc.js +0 -7
  401. package/dist/untrack-B0rVscTc.js.map +0 -1
  402. package/dist/view-C70lA3vf.js.map +0 -1
@@ -1,74 +1,74 @@
1
- /**
2
- * Mapping helpers for store state and actions.
3
- */
4
-
5
- /**
6
- * Maps store state properties to a reactive object for use in components.
7
- *
8
- * @param store - The store instance
9
- * @param keys - State keys to map
10
- * @returns Object with mapped properties
11
- */
12
- export const mapState = <S extends Record<string, unknown>, K extends keyof S>(
13
- store: S,
14
- keys: K[]
15
- ): Pick<S, K> => {
16
- const mapped = {} as Pick<S, K>;
17
-
18
- for (const key of keys) {
19
- Object.defineProperty(mapped, key, {
20
- get: () => store[key],
21
- enumerable: true,
22
- });
23
- }
24
-
25
- return mapped;
26
- };
27
-
28
- /**
29
- * Maps store getters to a reactive object for use in components.
30
- *
31
- * @param store - The store instance
32
- * @param keys - Getter keys to map
33
- * @returns Object with mapped getters
34
- */
35
- export const mapGetters = <G extends Record<string, unknown>, K extends keyof G>(
36
- store: G,
37
- keys: K[]
38
- ): Pick<G, K> => {
39
- const mapped = {} as Pick<G, K>;
40
-
41
- for (const key of keys) {
42
- Object.defineProperty(mapped, key, {
43
- get: () => store[key],
44
- enumerable: true,
45
- });
46
- }
47
-
48
- return mapped;
49
- };
50
-
51
- /**
52
- * Maps store actions to an object for easier destructuring.
53
- *
54
- * @param store - The store instance
55
- * @param keys - Action keys to map
56
- * @returns Object with mapped actions
57
- */
58
- export const mapActions = <
59
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- actions may declare specific parameter types
60
- A extends Record<string, (...args: any[]) => any>,
61
- K extends keyof A,
62
- >(
63
- store: A,
64
- keys: K[]
65
- ): Pick<A, K> => {
66
- const mapped = {} as Pick<A, K>;
67
-
68
- for (const key of keys) {
69
- (mapped as Record<string, unknown>)[key as string] = (...args: unknown[]) =>
70
- (store[key] as (...args: unknown[]) => unknown)(...args);
71
- }
72
-
73
- return mapped;
74
- };
1
+ /**
2
+ * Mapping helpers for store state and actions.
3
+ */
4
+
5
+ /**
6
+ * Maps store state properties to a reactive object for use in components.
7
+ *
8
+ * @param store - The store instance
9
+ * @param keys - State keys to map
10
+ * @returns Object with mapped properties
11
+ */
12
+ export const mapState = <S extends Record<string, unknown>, K extends keyof S>(
13
+ store: S,
14
+ keys: K[]
15
+ ): Pick<S, K> => {
16
+ const mapped = {} as Pick<S, K>;
17
+
18
+ for (const key of keys) {
19
+ Object.defineProperty(mapped, key, {
20
+ get: () => store[key],
21
+ enumerable: true,
22
+ });
23
+ }
24
+
25
+ return mapped;
26
+ };
27
+
28
+ /**
29
+ * Maps store getters to a reactive object for use in components.
30
+ *
31
+ * @param store - The store instance
32
+ * @param keys - Getter keys to map
33
+ * @returns Object with mapped getters
34
+ */
35
+ export const mapGetters = <G extends Record<string, unknown>, K extends keyof G>(
36
+ store: G,
37
+ keys: K[]
38
+ ): Pick<G, K> => {
39
+ const mapped = {} as Pick<G, K>;
40
+
41
+ for (const key of keys) {
42
+ Object.defineProperty(mapped, key, {
43
+ get: () => store[key],
44
+ enumerable: true,
45
+ });
46
+ }
47
+
48
+ return mapped;
49
+ };
50
+
51
+ /**
52
+ * Maps store actions to an object for easier destructuring.
53
+ *
54
+ * @param store - The store instance
55
+ * @param keys - Action keys to map
56
+ * @returns Object with mapped actions
57
+ */
58
+ export const mapActions = <
59
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- actions may declare specific parameter types
60
+ A extends Record<string, (...args: any[]) => any>,
61
+ K extends keyof A,
62
+ >(
63
+ store: A,
64
+ keys: K[]
65
+ ): Pick<A, K> => {
66
+ const mapped = {} as Pick<A, K>;
67
+
68
+ for (const key of keys) {
69
+ (mapped as Record<string, unknown>)[key as string] = (...args: unknown[]) =>
70
+ (store[key] as (...args: unknown[]) => unknown)(...args);
71
+ }
72
+
73
+ return mapped;
74
+ };
@@ -1,62 +1,245 @@
1
- /**
2
- * Store persistence helpers.
3
- */
4
-
5
- import { createStore } from './create-store';
6
- import type { Store, StoreDefinition } from './types';
7
-
8
- /**
9
- * Creates a store with automatic persistence to localStorage.
10
- *
11
- * @param definition - Store definition
12
- * @param storageKey - Optional custom storage key
13
- * @returns The reactive store instance
14
- */
15
- export const createPersistedStore = <
16
- S extends Record<string, unknown>,
17
- G extends Record<string, unknown> = Record<string, never>,
18
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- actions may declare specific parameter types
19
- A extends Record<string, (...args: any[]) => any> = Record<string, never>,
20
- >(
21
- definition: StoreDefinition<S, G, A>,
22
- storageKey?: string
23
- ): Store<S, G, A> => {
24
- const key = storageKey ?? `bquery-store-${definition.id}`;
25
-
26
- const originalStateFactory = definition.state;
27
-
28
- const wrappedDefinition: StoreDefinition<S, G, A> = {
29
- ...definition,
30
- state: () => {
31
- const defaultState = originalStateFactory();
32
-
33
- if (typeof window !== 'undefined') {
34
- try {
35
- const saved = localStorage.getItem(key);
36
- if (saved) {
37
- return { ...defaultState, ...JSON.parse(saved) } as S;
38
- }
39
- } catch {
40
- // Ignore parse errors
41
- }
42
- }
43
-
44
- return defaultState;
45
- },
46
- };
47
-
48
- const store = createStore(wrappedDefinition);
49
-
50
- // Subscribe to save changes
51
- store.$subscribe((state) => {
52
- if (typeof window !== 'undefined') {
53
- try {
54
- localStorage.setItem(key, JSON.stringify(state));
55
- } catch {
56
- // Ignore quota errors
57
- }
58
- }
59
- });
60
-
61
- return store;
62
- };
1
+ /**
2
+ * Store persistence helpers.
3
+ */
4
+
5
+ import { isPrototypePollutionKey } from '../core/utils/object';
6
+ import { createStore } from './create-store';
7
+ import { isDev } from './utils';
8
+ import type { PersistedStoreOptions, StorageBackend, Store, StoreDefinition } from './types';
9
+
10
+ /** @internal Version key suffix */
11
+ const VERSION_SUFFIX = '__version';
12
+
13
+ /** @internal Default JSON serializer */
14
+ const defaultSerializer = {
15
+ serialize: (state: unknown) => JSON.stringify(state),
16
+ deserialize: (raw: string) => JSON.parse(raw) as unknown,
17
+ };
18
+
19
+ /** @internal Check whether a value can be merged into store state. */
20
+ const isPersistedStateObject = (value: unknown): value is Record<string, unknown> => {
21
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;
22
+
23
+ const prototype = Object.getPrototypeOf(value);
24
+ return prototype === null || Object.getPrototypeOf(prototype) === null;
25
+ };
26
+
27
+ /**
28
+ * Applies persisted state onto the default state while ignoring dangerous
29
+ * prototype-pollution keys such as `__proto__`, `constructor`, and `prototype`.
30
+ *
31
+ * @internal
32
+ */
33
+ const mergePersistedState = <S extends Record<string, unknown>>(
34
+ defaultState: S,
35
+ persisted: Record<string, unknown>
36
+ ): S => {
37
+ const merged = { ...defaultState };
38
+ for (const [key, value] of Object.entries(persisted)) {
39
+ if (isPrototypePollutionKey(key)) continue;
40
+ if (!Object.prototype.hasOwnProperty.call(defaultState, key)) continue;
41
+ merged[key as keyof S] = value as S[keyof S];
42
+ }
43
+ return merged;
44
+ };
45
+
46
+ /** @internal Resolve the default storage backend safely. */
47
+ const getDefaultStorage = (): StorageBackend | undefined => {
48
+ try {
49
+ return globalThis.localStorage;
50
+ } catch {
51
+ return undefined;
52
+ }
53
+ };
54
+
55
+ /**
56
+ * Creates a store with automatic persistence.
57
+ *
58
+ * Supports configurable storage backends, custom serializers, and schema
59
+ * versioning with migration functions. All options are optional and
60
+ * backward-compatible with the simple `(definition, storageKey?)` signature.
61
+ *
62
+ * @param definition - Store definition
63
+ * @param options - Persistence options or a plain string storage key for backward compatibility
64
+ * @returns The reactive store instance
65
+ *
66
+ * @example Basic usage (localStorage + JSON)
67
+ * ```ts
68
+ * const store = createPersistedStore({
69
+ * id: 'settings',
70
+ * state: () => ({ theme: 'dark' }),
71
+ * });
72
+ * ```
73
+ *
74
+ * @example With sessionStorage and custom key
75
+ * ```ts
76
+ * const store = createPersistedStore(
77
+ * { id: 'session', state: () => ({ token: '' }) },
78
+ * { key: 'my-session', storage: sessionStorage },
79
+ * );
80
+ * ```
81
+ *
82
+ * @example With versioning and migration
83
+ * ```ts
84
+ * const store = createPersistedStore(
85
+ * { id: 'app', state: () => ({ name: '', theme: 'auto' }) },
86
+ * {
87
+ * version: 2,
88
+ * migrate: (old, v) => {
89
+ * if (v < 2) return { ...old, theme: 'auto' };
90
+ * return old;
91
+ * },
92
+ * },
93
+ * );
94
+ * ```
95
+ */
96
+ export const createPersistedStore = <
97
+ S extends Record<string, unknown>,
98
+ G extends Record<string, unknown> = Record<string, never>,
99
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- actions may declare specific parameter types
100
+ A extends Record<string, (...args: any[]) => any> = Record<string, never>,
101
+ >(
102
+ definition: StoreDefinition<S, G, A>,
103
+ options?: PersistedStoreOptions | string
104
+ ): Store<S, G, A> => {
105
+ // Normalize options — a plain string is treated as the storage key for backward compatibility
106
+ const opts: PersistedStoreOptions =
107
+ typeof options === 'string' ? { key: options } : (options ?? {});
108
+
109
+ const key = opts.key ?? `bquery-store-${definition.id}`;
110
+ const storage = opts.storage ?? getDefaultStorage();
111
+ const serializer = opts.serializer ?? defaultSerializer;
112
+ const version = opts.version;
113
+ const migrate = opts.migrate;
114
+ const versionKey = key + VERSION_SUFFIX;
115
+ let shouldPersistInitialVersion = storage !== undefined && version !== undefined;
116
+ let pendingVersionWrite = false;
117
+ let canRetryPendingVersionAfterCreate = false;
118
+
119
+ const tryPersistVersion = (warningMessage?: string): boolean => {
120
+ if (!storage || version === undefined) return false;
121
+
122
+ try {
123
+ storage.setItem(versionKey, String(version));
124
+ return true;
125
+ } catch (error) {
126
+ if (
127
+ warningMessage &&
128
+ isDev() &&
129
+ typeof console !== 'undefined' &&
130
+ typeof console.warn === 'function'
131
+ ) {
132
+ console.warn(warningMessage, error);
133
+ }
134
+ return false;
135
+ }
136
+ };
137
+
138
+ const originalStateFactory = definition.state;
139
+
140
+ const wrappedDefinition: StoreDefinition<S, G, A> = {
141
+ ...definition,
142
+ state: () => {
143
+ const defaultState = originalStateFactory();
144
+
145
+ if (!storage) return defaultState;
146
+
147
+ try {
148
+ const saved = storage.getItem(key);
149
+ if (!saved) return defaultState;
150
+
151
+ const deserialized = serializer.deserialize(saved);
152
+ if (!isPersistedStateObject(deserialized)) {
153
+ return defaultState;
154
+ }
155
+
156
+ let persisted = deserialized;
157
+
158
+ // Handle versioning & migration
159
+ if (version !== undefined && migrate) {
160
+ const rawVersion = storage.getItem(versionKey);
161
+ const parsedVersion = rawVersion !== null ? Number(rawVersion) : 0;
162
+ const oldVersion = Number.isFinite(parsedVersion) ? parsedVersion : 0;
163
+
164
+ if (oldVersion !== version) {
165
+ shouldPersistInitialVersion = false;
166
+ pendingVersionWrite = true;
167
+ const migrated = migrate(persisted, oldVersion);
168
+ if (!isPersistedStateObject(migrated)) {
169
+ return defaultState;
170
+ }
171
+ persisted = migrated;
172
+
173
+ let migratedStatePersisted = false;
174
+ // Save the migrated state and version immediately when possible.
175
+ // If the state write fails, never advance the version key.
176
+ try {
177
+ storage.setItem(key, serializer.serialize(persisted));
178
+ migratedStatePersisted = true;
179
+ canRetryPendingVersionAfterCreate = true;
180
+ } catch (e) {
181
+ // Migration will re-run on next load, but state is still usable
182
+ if (isDev() && typeof console !== 'undefined' && typeof console.warn === 'function') {
183
+ console.warn(
184
+ `[bQuery store "${definition.id}"] Failed to persist migrated state:`,
185
+ e
186
+ );
187
+ }
188
+ }
189
+
190
+ if (
191
+ migratedStatePersisted &&
192
+ tryPersistVersion(
193
+ `[bQuery store "${definition.id}"] Failed to persist migrated version:`
194
+ )
195
+ ) {
196
+ pendingVersionWrite = false;
197
+ }
198
+ } else {
199
+ shouldPersistInitialVersion = false;
200
+ }
201
+ }
202
+
203
+ return mergePersistedState(defaultState, persisted);
204
+ } catch {
205
+ // Ignore parse errors
206
+ return defaultState;
207
+ }
208
+ },
209
+ };
210
+
211
+ const store = createStore(wrappedDefinition);
212
+
213
+ // Persist the version number on first creation
214
+ if (shouldPersistInitialVersion && storage) {
215
+ tryPersistVersion();
216
+ } else if (
217
+ pendingVersionWrite &&
218
+ canRetryPendingVersionAfterCreate &&
219
+ tryPersistVersion(
220
+ `[bQuery store "${definition.id}"] Failed to persist migrated version after store creation:`
221
+ )
222
+ ) {
223
+ pendingVersionWrite = false;
224
+ }
225
+
226
+ // Subscribe to save changes
227
+ store.$subscribe((state) => {
228
+ if (!storage) return;
229
+ try {
230
+ storage.setItem(key, serializer.serialize(state));
231
+ if (
232
+ pendingVersionWrite &&
233
+ tryPersistVersion(
234
+ `[bQuery store "${definition.id}"] Failed to persist migrated version after a successful state write:`
235
+ )
236
+ ) {
237
+ pendingVersionWrite = false;
238
+ }
239
+ } catch {
240
+ // Ignore quota errors
241
+ }
242
+ });
243
+
244
+ return store;
245
+ };