alepha 0.22.0 → 0.24.0

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 (869) hide show
  1. package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
  2. package/assets/swagger-ui/swagger-ui-standalone-preset.js +1 -1
  3. package/dist/api/audits/index.browser.js +49 -52
  4. package/dist/api/audits/index.browser.js.map +1 -1
  5. package/dist/api/audits/index.d.ts +629 -565
  6. package/dist/api/audits/index.d.ts.map +1 -1
  7. package/dist/api/audits/index.js +206 -98
  8. package/dist/api/audits/index.js.map +1 -1
  9. package/dist/api/files/index.browser.js +44 -44
  10. package/dist/api/files/index.browser.js.map +1 -1
  11. package/dist/api/files/index.d.ts +292 -293
  12. package/dist/api/files/index.d.ts.map +1 -1
  13. package/dist/api/files/index.js +61 -64
  14. package/dist/api/files/index.js.map +1 -1
  15. package/dist/api/jobs/index.browser.js +61 -59
  16. package/dist/api/jobs/index.browser.js.map +1 -1
  17. package/dist/api/jobs/index.d.ts +546 -347
  18. package/dist/api/jobs/index.d.ts.map +1 -1
  19. package/dist/api/jobs/index.js +165 -86
  20. package/dist/api/jobs/index.js.map +1 -1
  21. package/dist/api/keys/index.d.ts +242 -230
  22. package/dist/api/keys/index.d.ts.map +1 -1
  23. package/dist/api/keys/index.js +63 -66
  24. package/dist/api/keys/index.js.map +1 -1
  25. package/dist/api/notifications/index.browser.js +40 -38
  26. package/dist/api/notifications/index.browser.js.map +1 -1
  27. package/dist/api/notifications/index.d.ts +339 -209
  28. package/dist/api/notifications/index.d.ts.map +1 -1
  29. package/dist/api/notifications/index.js +108 -60
  30. package/dist/api/notifications/index.js.map +1 -1
  31. package/dist/api/oauth/index.d.ts +190 -78
  32. package/dist/api/oauth/index.d.ts.map +1 -1
  33. package/dist/api/oauth/index.js +290 -68
  34. package/dist/api/oauth/index.js.map +1 -1
  35. package/dist/api/organizations/index.browser.js +14 -14
  36. package/dist/api/organizations/index.browser.js.map +1 -1
  37. package/dist/api/organizations/index.d.ts +158 -134
  38. package/dist/api/organizations/index.d.ts.map +1 -1
  39. package/dist/api/organizations/index.js +18 -18
  40. package/dist/api/organizations/index.js.map +1 -1
  41. package/dist/api/parameters/index.browser.js +74 -53
  42. package/dist/api/parameters/index.browser.js.map +1 -1
  43. package/dist/api/parameters/index.d.ts +607 -513
  44. package/dist/api/parameters/index.d.ts.map +1 -1
  45. package/dist/api/parameters/index.js +205 -127
  46. package/dist/api/parameters/index.js.map +1 -1
  47. package/dist/api/payments/index.d.ts +652 -449
  48. package/dist/api/payments/index.d.ts.map +1 -1
  49. package/dist/api/payments/index.js +159 -93
  50. package/dist/api/payments/index.js.map +1 -1
  51. package/dist/api/subscriptions/index.d.ts +1032 -762
  52. package/dist/api/subscriptions/index.d.ts.map +1 -1
  53. package/dist/api/subscriptions/index.js +166 -185
  54. package/dist/api/subscriptions/index.js.map +1 -1
  55. package/dist/api/users/index.browser.js +48 -71
  56. package/dist/api/users/index.browser.js.map +1 -1
  57. package/dist/api/users/index.d.ts +1297 -1109
  58. package/dist/api/users/index.d.ts.map +1 -1
  59. package/dist/api/users/index.js +454 -369
  60. package/dist/api/users/index.js.map +1 -1
  61. package/dist/api/verifications/index.browser.js +17 -17
  62. package/dist/api/verifications/index.browser.js.map +1 -1
  63. package/dist/api/verifications/index.d.ts +169 -157
  64. package/dist/api/verifications/index.d.ts.map +1 -1
  65. package/dist/api/verifications/index.js +47 -95
  66. package/dist/api/verifications/index.js.map +1 -1
  67. package/dist/background/index.d.ts +0 -1
  68. package/dist/background/index.d.ts.map +1 -1
  69. package/dist/background/index.js.map +1 -1
  70. package/dist/background/index.workerd.js.map +1 -1
  71. package/dist/batch/index.d.ts +0 -1
  72. package/dist/batch/index.d.ts.map +1 -1
  73. package/dist/batch/index.js.map +1 -1
  74. package/dist/bin/index.js +1 -1
  75. package/dist/bin/index.js.map +1 -1
  76. package/dist/bucket/index.d.ts +27 -32
  77. package/dist/bucket/index.d.ts.map +1 -1
  78. package/dist/bucket/index.js +56 -26
  79. package/dist/bucket/index.js.map +1 -1
  80. package/dist/bucket/index.workerd.js +52 -24
  81. package/dist/bucket/index.workerd.js.map +1 -1
  82. package/dist/cache/core/index.d.ts +4 -6
  83. package/dist/cache/core/index.d.ts.map +1 -1
  84. package/dist/cache/core/index.js +4 -10
  85. package/dist/cache/core/index.js.map +1 -1
  86. package/dist/cache/core/index.workerd.js +4 -10
  87. package/dist/cache/core/index.workerd.js.map +1 -1
  88. package/dist/cache/database/index.d.ts +22 -23
  89. package/dist/cache/database/index.d.ts.map +1 -1
  90. package/dist/cache/database/index.js +11 -20
  91. package/dist/cache/database/index.js.map +1 -1
  92. package/dist/cache/redis/index.d.ts +3 -4
  93. package/dist/cache/redis/index.d.ts.map +1 -1
  94. package/dist/cache/redis/index.js +2 -2
  95. package/dist/cache/redis/index.js.map +1 -1
  96. package/dist/captcha/index.d.ts.map +1 -1
  97. package/dist/captcha/index.js +4 -4
  98. package/dist/captcha/index.js.map +1 -1
  99. package/dist/cli/config/index.d.ts +0 -1
  100. package/dist/cli/config/index.d.ts.map +1 -1
  101. package/dist/cli/core/index.d.ts +244 -475
  102. package/dist/cli/core/index.d.ts.map +1 -1
  103. package/dist/cli/core/index.js +308 -383
  104. package/dist/cli/core/index.js.map +1 -1
  105. package/dist/cli/devtools/index.d.ts +3 -9
  106. package/dist/cli/devtools/index.d.ts.map +1 -1
  107. package/dist/cli/devtools/index.js +3 -3
  108. package/dist/cli/devtools/index.js.map +1 -1
  109. package/dist/cli/i18n/index.d.ts +20 -39
  110. package/dist/cli/i18n/index.d.ts.map +1 -1
  111. package/dist/cli/i18n/index.js +51 -17
  112. package/dist/cli/i18n/index.js.map +1 -1
  113. package/dist/cli/platform/index.d.ts +89 -82
  114. package/dist/cli/platform/index.d.ts.map +1 -1
  115. package/dist/cli/platform/index.js +27 -33
  116. package/dist/cli/platform/index.js.map +1 -1
  117. package/dist/cli/platform-lib/index.d.ts +383 -410
  118. package/dist/cli/platform-lib/index.d.ts.map +1 -1
  119. package/dist/cli/platform-lib/index.js +300 -258
  120. package/dist/cli/platform-lib/index.js.map +1 -1
  121. package/dist/cli/vendor/index.d.ts +17 -41
  122. package/dist/cli/vendor/index.d.ts.map +1 -1
  123. package/dist/cli/vendor/index.js +10 -13
  124. package/dist/cli/vendor/index.js.map +1 -1
  125. package/dist/command/index.d.ts +82 -194
  126. package/dist/command/index.d.ts.map +1 -1
  127. package/dist/command/index.js +160 -563
  128. package/dist/command/index.js.map +1 -1
  129. package/dist/core/index.browser.js +845 -859
  130. package/dist/core/index.browser.js.map +1 -1
  131. package/dist/core/index.d.ts +787 -527
  132. package/dist/core/index.d.ts.map +1 -1
  133. package/dist/core/index.js +845 -859
  134. package/dist/core/index.js.map +1 -1
  135. package/dist/core/index.native.js +845 -859
  136. package/dist/core/index.native.js.map +1 -1
  137. package/dist/core/index.workerd.js +845 -859
  138. package/dist/core/index.workerd.js.map +1 -1
  139. package/dist/crypto/index.browser.js +1 -1
  140. package/dist/crypto/index.browser.js.map +1 -1
  141. package/dist/crypto/index.d.ts +3 -4
  142. package/dist/crypto/index.d.ts.map +1 -1
  143. package/dist/crypto/index.js +6 -3
  144. package/dist/crypto/index.js.map +1 -1
  145. package/dist/datetime/index.d.ts +12 -2
  146. package/dist/datetime/index.d.ts.map +1 -1
  147. package/dist/datetime/index.js +6 -1
  148. package/dist/datetime/index.js.map +1 -1
  149. package/dist/email/brevo/index.d.ts +0 -1
  150. package/dist/email/brevo/index.d.ts.map +1 -1
  151. package/dist/email/brevo/index.js +4 -4
  152. package/dist/email/brevo/index.js.map +1 -1
  153. package/dist/email/cloudflare/index.d.ts +0 -1
  154. package/dist/email/cloudflare/index.d.ts.map +1 -1
  155. package/dist/email/cloudflare/index.js +2 -2
  156. package/dist/email/cloudflare/index.js.map +1 -1
  157. package/dist/email/core/index.d.ts +15 -7
  158. package/dist/email/core/index.d.ts.map +1 -1
  159. package/dist/email/core/index.js +14 -5
  160. package/dist/email/core/index.js.map +1 -1
  161. package/dist/email/core/index.workerd.js +5 -1
  162. package/dist/email/core/index.workerd.js.map +1 -1
  163. package/dist/email/smtp/index.d.ts +8 -9
  164. package/dist/email/smtp/index.d.ts.map +1 -1
  165. package/dist/email/smtp/index.js +702 -479
  166. package/dist/email/smtp/index.js.map +1 -1
  167. package/dist/fake/index.d.ts +1580 -1238
  168. package/dist/fake/index.d.ts.map +1 -1
  169. package/dist/fake/index.js +11728 -32131
  170. package/dist/fake/index.js.map +1 -1
  171. package/dist/lock/core/index.d.ts +13 -9
  172. package/dist/lock/core/index.d.ts.map +1 -1
  173. package/dist/lock/core/index.js +5 -5
  174. package/dist/lock/core/index.js.map +1 -1
  175. package/dist/lock/redis/index.d.ts +0 -1
  176. package/dist/lock/redis/index.d.ts.map +1 -1
  177. package/dist/lock/redis/index.js.map +1 -1
  178. package/dist/logger/index.d.ts +81 -69
  179. package/dist/logger/index.d.ts.map +1 -1
  180. package/dist/logger/index.js +123 -56
  181. package/dist/logger/index.js.map +1 -1
  182. package/dist/mcp/index.d.ts +36 -90
  183. package/dist/mcp/index.d.ts.map +1 -1
  184. package/dist/mcp/index.js +65 -70
  185. package/dist/mcp/index.js.map +1 -1
  186. package/dist/orm/core/index.browser.js +54 -40
  187. package/dist/orm/core/index.browser.js.map +1 -1
  188. package/dist/orm/core/index.bun.js +140 -106
  189. package/dist/orm/core/index.bun.js.map +1 -1
  190. package/dist/orm/core/index.d.ts +145 -150
  191. package/dist/orm/core/index.d.ts.map +1 -1
  192. package/dist/orm/core/index.js +144 -109
  193. package/dist/orm/core/index.js.map +1 -1
  194. package/dist/orm/postgres/index.bun.js +64 -54
  195. package/dist/orm/postgres/index.bun.js.map +1 -1
  196. package/dist/orm/postgres/index.d.ts +36 -76
  197. package/dist/orm/postgres/index.d.ts.map +1 -1
  198. package/dist/orm/postgres/index.js +67 -57
  199. package/dist/orm/postgres/index.js.map +1 -1
  200. package/dist/queue/core/index.d.ts +62 -75
  201. package/dist/queue/core/index.d.ts.map +1 -1
  202. package/dist/queue/core/index.js +48 -71
  203. package/dist/queue/core/index.js.map +1 -1
  204. package/dist/queue/core/index.workerd.js +48 -71
  205. package/dist/queue/core/index.workerd.js.map +1 -1
  206. package/dist/queue/redis/index.d.ts +3 -4
  207. package/dist/queue/redis/index.d.ts.map +1 -1
  208. package/dist/queue/redis/index.js +2 -2
  209. package/dist/queue/redis/index.js.map +1 -1
  210. package/dist/react/auth/index.browser.js.map +1 -1
  211. package/dist/react/auth/index.d.ts +7 -4
  212. package/dist/react/auth/index.d.ts.map +1 -1
  213. package/dist/react/auth/index.js.map +1 -1
  214. package/dist/react/core/index.d.ts +87 -5
  215. package/dist/react/core/index.d.ts.map +1 -1
  216. package/dist/react/core/index.js +170 -23
  217. package/dist/react/core/index.js.map +1 -1
  218. package/dist/react/form/index.d.ts +4 -6
  219. package/dist/react/form/index.d.ts.map +1 -1
  220. package/dist/react/form/index.js +107 -71
  221. package/dist/react/form/index.js.map +1 -1
  222. package/dist/react/head/index.browser.js.map +1 -1
  223. package/dist/react/head/index.d.ts +0 -1
  224. package/dist/react/head/index.d.ts.map +1 -1
  225. package/dist/react/head/index.js.map +1 -1
  226. package/dist/react/i18n/index.d.ts +47 -5
  227. package/dist/react/i18n/index.d.ts.map +1 -1
  228. package/dist/react/i18n/index.js +116 -12
  229. package/dist/react/i18n/index.js.map +1 -1
  230. package/dist/react/intro/index.d.ts +1 -4
  231. package/dist/react/intro/index.d.ts.map +1 -1
  232. package/dist/react/intro/index.js.map +1 -1
  233. package/dist/react/router/index.browser.js +188 -29
  234. package/dist/react/router/index.browser.js.map +1 -1
  235. package/dist/react/router/index.d.ts +480 -372
  236. package/dist/react/router/index.d.ts.map +1 -1
  237. package/dist/react/router/index.js +261 -47
  238. package/dist/react/router/index.js.map +1 -1
  239. package/dist/react/sitemap/index.browser.js +35 -0
  240. package/dist/react/sitemap/index.browser.js.map +1 -0
  241. package/dist/react/sitemap/index.d.ts +91 -0
  242. package/dist/react/sitemap/index.d.ts.map +1 -0
  243. package/dist/react/sitemap/index.js +131 -0
  244. package/dist/react/sitemap/index.js.map +1 -0
  245. package/dist/react/testing/index.d.ts +4 -5
  246. package/dist/react/testing/index.d.ts.map +1 -1
  247. package/dist/react/testing/index.js +41 -15
  248. package/dist/react/testing/index.js.map +1 -1
  249. package/dist/react/testing/{chunk-BpyX8vjI.js → rolldown-runtime-Bl3dcgcQ.js} +1 -1
  250. package/dist/react/ui/index.d.ts +35 -34
  251. package/dist/react/ui/index.d.ts.map +1 -1
  252. package/dist/react/ui/index.js +12 -17
  253. package/dist/react/ui/index.js.map +1 -1
  254. package/dist/redis/index.bun.js +5 -5
  255. package/dist/redis/index.bun.js.map +1 -1
  256. package/dist/redis/index.d.ts +6 -7
  257. package/dist/redis/index.d.ts.map +1 -1
  258. package/dist/redis/index.js +6 -6
  259. package/dist/redis/index.js.map +1 -1
  260. package/dist/retry/index.d.ts +0 -1
  261. package/dist/retry/index.d.ts.map +1 -1
  262. package/dist/retry/index.js.map +1 -1
  263. package/dist/router/index.d.ts.map +1 -1
  264. package/dist/router/index.js.map +1 -1
  265. package/dist/scheduler/index.d.ts +4 -12
  266. package/dist/scheduler/index.d.ts.map +1 -1
  267. package/dist/scheduler/index.js +9 -4
  268. package/dist/scheduler/index.js.map +1 -1
  269. package/dist/scheduler/index.workerd.js +9 -4
  270. package/dist/scheduler/index.workerd.js.map +1 -1
  271. package/dist/security/index.browser.js +30 -28
  272. package/dist/security/index.browser.js.map +1 -1
  273. package/dist/security/index.d.ts +113 -44
  274. package/dist/security/index.d.ts.map +1 -1
  275. package/dist/security/index.js +452 -37
  276. package/dist/security/index.js.map +1 -1
  277. package/dist/server/auth/index.browser.js +19 -19
  278. package/dist/server/auth/index.browser.js.map +1 -1
  279. package/dist/server/auth/index.d.ts +215 -187
  280. package/dist/server/auth/index.d.ts.map +1 -1
  281. package/dist/server/auth/index.js +1145 -86
  282. package/dist/server/auth/index.js.map +1 -1
  283. package/dist/server/cookies/index.browser.js +103 -5
  284. package/dist/server/cookies/index.browser.js.map +1 -1
  285. package/dist/server/cookies/index.d.ts +86 -4
  286. package/dist/server/cookies/index.d.ts.map +1 -1
  287. package/dist/server/cookies/index.js +121 -8
  288. package/dist/server/cookies/index.js.map +1 -1
  289. package/dist/server/core/index.browser.js +22 -27
  290. package/dist/server/core/index.browser.js.map +1 -1
  291. package/dist/server/core/index.d.ts +134 -85
  292. package/dist/server/core/index.d.ts.map +1 -1
  293. package/dist/server/core/index.js +130 -118
  294. package/dist/server/core/index.js.map +1 -1
  295. package/dist/server/cors/index.d.ts +9 -10
  296. package/dist/server/cors/index.d.ts.map +1 -1
  297. package/dist/server/cors/index.js +14 -26
  298. package/dist/server/cors/index.js.map +1 -1
  299. package/dist/server/etag/index.d.ts +2 -3
  300. package/dist/server/etag/index.d.ts.map +1 -1
  301. package/dist/server/etag/index.js.map +1 -1
  302. package/dist/server/health/index.d.ts +18 -19
  303. package/dist/server/health/index.d.ts.map +1 -1
  304. package/dist/server/health/index.js +6 -6
  305. package/dist/server/health/index.js.map +1 -1
  306. package/dist/server/links/index.browser.js +15 -18
  307. package/dist/server/links/index.browser.js.map +1 -1
  308. package/dist/server/links/index.d.ts +66 -67
  309. package/dist/server/links/index.d.ts.map +1 -1
  310. package/dist/server/links/index.js +29 -32
  311. package/dist/server/links/index.js.map +1 -1
  312. package/dist/server/metrics/index.d.ts +0 -1
  313. package/dist/server/metrics/index.d.ts.map +1 -1
  314. package/dist/server/metrics/index.js +10 -3
  315. package/dist/server/metrics/index.js.map +1 -1
  316. package/dist/server/proxy/index.d.ts +0 -1
  317. package/dist/server/proxy/index.d.ts.map +1 -1
  318. package/dist/server/proxy/index.js.map +1 -1
  319. package/dist/server/rate-limit/index.d.ts +8 -9
  320. package/dist/server/rate-limit/index.d.ts.map +1 -1
  321. package/dist/server/rate-limit/index.js +6 -12
  322. package/dist/server/rate-limit/index.js.map +1 -1
  323. package/dist/server/static/index.d.ts +0 -1
  324. package/dist/server/static/index.d.ts.map +1 -1
  325. package/dist/server/static/index.js.map +1 -1
  326. package/dist/server/swagger/index.d.ts +4 -4
  327. package/dist/server/swagger/index.d.ts.map +1 -1
  328. package/dist/server/swagger/index.js +37 -25
  329. package/dist/server/swagger/index.js.map +1 -1
  330. package/dist/sms/index.d.ts +0 -1
  331. package/dist/sms/index.d.ts.map +1 -1
  332. package/dist/sms/index.js.map +1 -1
  333. package/dist/system/index.browser.js.map +1 -1
  334. package/dist/system/index.d.ts +0 -1
  335. package/dist/system/index.d.ts.map +1 -1
  336. package/dist/system/index.js +2 -1
  337. package/dist/system/index.js.map +1 -1
  338. package/dist/system/index.workerd.js.map +1 -1
  339. package/dist/topic/core/index.d.ts +19 -20
  340. package/dist/topic/core/index.d.ts.map +1 -1
  341. package/dist/topic/core/index.js +8 -8
  342. package/dist/topic/core/index.js.map +1 -1
  343. package/dist/topic/redis/index.d.ts +3 -4
  344. package/dist/topic/redis/index.d.ts.map +1 -1
  345. package/dist/topic/redis/index.js +2 -2
  346. package/dist/topic/redis/index.js.map +1 -1
  347. package/package.json +36 -36
  348. package/src/api/audits/__tests__/AuditJobs.spec.ts +83 -0
  349. package/src/api/audits/__tests__/AuditService.spec.ts +139 -1
  350. package/src/api/audits/controllers/AdminAuditController.ts +41 -41
  351. package/src/api/audits/entities/audits.ts +22 -22
  352. package/src/api/audits/index.ts +6 -1
  353. package/src/api/audits/jobs/AuditJobs.ts +29 -0
  354. package/src/api/audits/parameters/AuditParameters.ts +51 -0
  355. package/src/api/audits/primitives/$audit.ts +24 -0
  356. package/src/api/audits/schemas/auditQuerySchema.ts +13 -13
  357. package/src/api/audits/schemas/createAuditSchema.ts +18 -18
  358. package/src/api/audits/services/AuditService.ts +79 -7
  359. package/src/api/files/__tests__/FileController.spec.ts +5 -5
  360. package/src/api/files/__tests__/FileJobs.spec.ts +6 -0
  361. package/src/api/files/controllers/FileController.ts +25 -25
  362. package/src/api/files/entities/files.ts +15 -15
  363. package/src/api/files/schemas/fileCreatorSummarySchema.ts +7 -7
  364. package/src/api/files/schemas/fileQuerySchema.ts +9 -9
  365. package/src/api/files/schemas/fileResourceSchema.ts +7 -9
  366. package/src/api/files/schemas/storageStatsSchema.ts +13 -13
  367. package/src/api/jobs/__tests__/$job-hardening.spec.ts +289 -0
  368. package/src/api/jobs/__tests__/$job.spec.ts +18 -18
  369. package/src/api/jobs/controllers/AdminJobController.ts +8 -8
  370. package/src/api/jobs/entities/jobExecutionEntity.ts +29 -19
  371. package/src/api/jobs/providers/JobProvider.ts +128 -12
  372. package/src/api/jobs/providers/JobQueueProvider.ts +2 -2
  373. package/src/api/jobs/schemas/jobConfigAtom.ts +22 -22
  374. package/src/api/jobs/schemas/jobExecutionQuerySchema.ts +6 -6
  375. package/src/api/jobs/schemas/jobExecutionResourceSchema.ts +11 -15
  376. package/src/api/jobs/schemas/jobRegistrationSchema.ts +20 -19
  377. package/src/api/jobs/schemas/triggerJobSchema.ts +3 -3
  378. package/src/api/jobs/services/JobService.ts +6 -6
  379. package/src/api/keys/__tests__/ApiKeyService.spec.ts +2 -2
  380. package/src/api/keys/controllers/AdminApiKeyController.ts +10 -10
  381. package/src/api/keys/entities/apiKeyEntity.ts +15 -15
  382. package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +4 -4
  383. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +15 -15
  384. package/src/api/keys/schemas/createApiKeyBodySchema.ts +5 -5
  385. package/src/api/keys/schemas/createApiKeyResponseSchema.ts +9 -9
  386. package/src/api/keys/schemas/listApiKeyResponseSchema.ts +13 -13
  387. package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +3 -3
  388. package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +3 -3
  389. package/src/api/notifications/__tests__/AlephaApiNotifications.spec.ts +2 -2
  390. package/src/api/notifications/controllers/AdminNotificationController.ts +38 -14
  391. package/src/api/notifications/jobs/NotificationJobs.ts +7 -6
  392. package/src/api/notifications/primitives/$notification.ts +43 -4
  393. package/src/api/notifications/schemas/notificationContactPreferencesSchema.ts +4 -4
  394. package/src/api/notifications/schemas/notificationContactSchema.ts +7 -7
  395. package/src/api/notifications/schemas/notificationDetailResourceSchema.ts +9 -11
  396. package/src/api/notifications/schemas/notificationPayloadSchema.ts +11 -9
  397. package/src/api/notifications/schemas/notificationQuerySchema.ts +6 -6
  398. package/src/api/notifications/schemas/notificationResourceSchema.ts +14 -14
  399. package/src/api/notifications/services/NotificationSenderService.ts +38 -2
  400. package/src/api/oauth/__tests__/OAuthClientService.spec.ts +42 -0
  401. package/src/api/oauth/__tests__/OAuthController.spec.ts +128 -0
  402. package/src/api/oauth/controllers/OAuthController.ts +132 -12
  403. package/src/api/oauth/entities/oauthClientEntity.ts +29 -12
  404. package/src/api/oauth/helpers/oauthMetadata.ts +1 -0
  405. package/src/api/oauth/helpers/oidcMetadata.ts +19 -0
  406. package/src/api/oauth/index.ts +1 -0
  407. package/src/api/oauth/schemas/authorizeDecisionBodySchema.ts +12 -11
  408. package/src/api/oauth/schemas/authorizeQuerySchema.ts +12 -10
  409. package/src/api/oauth/schemas/registerClientBodySchema.ts +10 -11
  410. package/src/api/oauth/schemas/tokenRequestBodySchema.ts +9 -8
  411. package/src/api/oauth/services/OAuthClientService.ts +228 -15
  412. package/src/api/organizations/controllers/AdminOrganizationController.ts +8 -8
  413. package/src/api/organizations/entities/organizations.ts +6 -6
  414. package/src/api/organizations/schemas/createOrganizationSchema.ts +5 -5
  415. package/src/api/organizations/schemas/organizationQuerySchema.ts +4 -4
  416. package/src/api/organizations/schemas/updateOrganizationSchema.ts +1 -2
  417. package/src/api/parameters/__tests__/$parameter.spec.ts +229 -50
  418. package/src/api/parameters/controllers/AdminParameterController.ts +9 -12
  419. package/src/api/parameters/entities/parameters.ts +29 -16
  420. package/src/api/parameters/primitives/$parameter.ts +3 -3
  421. package/src/api/parameters/schemas/activateParameterBodySchema.ts +4 -4
  422. package/src/api/parameters/schemas/createParameterVersionBodySchema.ts +15 -15
  423. package/src/api/parameters/schemas/parameterCreatorSummarySchema.ts +7 -7
  424. package/src/api/parameters/schemas/parameterCurrentResponseSchema.ts +7 -7
  425. package/src/api/parameters/schemas/parameterHistoryResponseSchema.ts +3 -3
  426. package/src/api/parameters/schemas/parameterNameParamSchema.ts +2 -3
  427. package/src/api/parameters/schemas/parameterNamesResponseSchema.ts +3 -3
  428. package/src/api/parameters/schemas/parameterResponseSchema.ts +3 -3
  429. package/src/api/parameters/schemas/parameterStatusSchema.ts +2 -2
  430. package/src/api/parameters/schemas/parameterTreeNodeSchema.ts +6 -6
  431. package/src/api/parameters/schemas/parameterVersionParamSchema.ts +5 -6
  432. package/src/api/parameters/schemas/parameterVersionResponseSchema.ts +3 -3
  433. package/src/api/parameters/schemas/rollbackParameterBodySchema.ts +6 -9
  434. package/src/api/parameters/services/ParameterProvider.ts +152 -65
  435. package/src/api/payments/controllers/AdminPaymentController.ts +7 -7
  436. package/src/api/payments/controllers/MockCheckoutController.ts +79 -28
  437. package/src/api/payments/controllers/PaymentController.ts +4 -4
  438. package/src/api/payments/entities/paymentIntents.ts +11 -11
  439. package/src/api/payments/entities/paymentMethods.ts +11 -11
  440. package/src/api/payments/entities/refunds.ts +9 -9
  441. package/src/api/payments/providers/PaymentProvider.ts +18 -0
  442. package/src/api/payments/schemas/intentSchemas.ts +25 -25
  443. package/src/api/payments/schemas/paymentMethodSchemas.ts +3 -3
  444. package/src/api/payments/services/PaymentService.ts +60 -3
  445. package/src/api/subscriptions/__tests__/SubscriptionService.spec.ts +14 -0
  446. package/src/api/subscriptions/controllers/AdminSubscriptionController.ts +11 -11
  447. package/src/api/subscriptions/controllers/SubscriptionController.ts +5 -4
  448. package/src/api/subscriptions/entities/subscriptionEvents.ts +15 -15
  449. package/src/api/subscriptions/entities/subscriptions.ts +22 -22
  450. package/src/api/subscriptions/notifications/SubscriptionNotifications.ts +22 -22
  451. package/src/api/subscriptions/schemas/cancelSubscriptionSchema.ts +4 -4
  452. package/src/api/subscriptions/schemas/changePlanSchema.ts +5 -5
  453. package/src/api/subscriptions/schemas/createSubscriptionSchema.ts +14 -7
  454. package/src/api/subscriptions/schemas/entitlementsSchema.ts +10 -10
  455. package/src/api/subscriptions/schemas/mrrSchema.ts +9 -9
  456. package/src/api/subscriptions/schemas/planDefinitionSchema.ts +21 -21
  457. package/src/api/subscriptions/schemas/planResourceSchema.ts +19 -19
  458. package/src/api/subscriptions/schemas/subscriptionQuerySchema.ts +8 -8
  459. package/src/api/subscriptions/schemas/subscriptionSettingsSchema.ts +7 -7
  460. package/src/api/subscriptions/schemas/subscriptionStatsSchema.ts +17 -17
  461. package/src/api/subscriptions/services/SubscriptionConfig.ts +2 -2
  462. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +11 -11
  463. package/src/api/users/atoms/realmAuthSettingsAtom.ts +111 -119
  464. package/src/api/users/controllers/AdminIdentityController.ts +29 -19
  465. package/src/api/users/controllers/AdminSessionController.ts +37 -27
  466. package/src/api/users/controllers/AdminUserController.ts +75 -53
  467. package/src/api/users/controllers/MySessionController.ts +125 -0
  468. package/src/api/users/controllers/RealmController.ts +9 -9
  469. package/src/api/users/controllers/UserController.ts +55 -55
  470. package/src/api/users/entities/identities.ts +8 -8
  471. package/src/api/users/entities/sessions.ts +17 -17
  472. package/src/api/users/entities/users.ts +17 -17
  473. package/src/api/users/index.ts +3 -0
  474. package/src/api/users/notifications/UserNotifications.ts +76 -24
  475. package/src/api/users/primitives/$realm.ts +12 -0
  476. package/src/api/users/schemas/completePasswordResetRequestSchema.ts +8 -12
  477. package/src/api/users/schemas/completeRegistrationRequestSchema.ts +17 -20
  478. package/src/api/users/schemas/createUserSchema.ts +2 -2
  479. package/src/api/users/schemas/identityQuerySchema.ts +4 -4
  480. package/src/api/users/schemas/identityResourceSchema.ts +3 -2
  481. package/src/api/users/schemas/loginSchema.ts +4 -4
  482. package/src/api/users/schemas/passwordResetIntentResponseSchema.ts +6 -8
  483. package/src/api/users/schemas/realmConfigSchema.ts +10 -10
  484. package/src/api/users/schemas/registerQuerySchema.ts +6 -6
  485. package/src/api/users/schemas/registerRequestSchema.ts +21 -43
  486. package/src/api/users/schemas/registerResponseSchema.ts +2 -2
  487. package/src/api/users/schemas/registerSchema.ts +13 -31
  488. package/src/api/users/schemas/registrationIntentResponseSchema.ts +19 -23
  489. package/src/api/users/schemas/resetPasswordSchema.ts +10 -17
  490. package/src/api/users/schemas/sessionQuerySchema.ts +3 -3
  491. package/src/api/users/schemas/sessionResourceSchema.ts +25 -25
  492. package/src/api/users/schemas/updateUserSchema.ts +3 -4
  493. package/src/api/users/schemas/userQuerySchema.ts +7 -7
  494. package/src/api/users/services/RegistrationService.ts +25 -11
  495. package/src/api/users/services/UserService.ts +12 -6
  496. package/src/api/verifications/__tests__/CodeVerification.spec.ts +63 -101
  497. package/src/api/verifications/__tests__/LinkVerification.spec.ts +23 -92
  498. package/src/api/verifications/controllers/VerificationController.ts +13 -27
  499. package/src/api/verifications/entities/verifications.ts +13 -14
  500. package/src/api/verifications/schemas/requestVerificationCodeResponseSchema.ts +17 -14
  501. package/src/api/verifications/schemas/validateVerificationCodeResponseSchema.ts +9 -10
  502. package/src/api/verifications/schemas/verificationSettingsSchema.ts +65 -66
  503. package/src/api/verifications/schemas/verificationTypeEnumSchema.ts +2 -2
  504. package/src/api/verifications/services/VerificationService.ts +12 -0
  505. package/src/background/__tests__/BackgroundTaskProvider.spec.ts +36 -0
  506. package/src/batch/__tests__/$batch.spec.ts +22 -22
  507. package/src/batch/__tests__/startup-buffering.spec.ts +9 -9
  508. package/src/bin/index.ts +1 -1
  509. package/src/bucket/__tests__/TenantScopedBucket.spec.ts +60 -0
  510. package/src/bucket/providers/LocalFileStorageProvider.ts +14 -6
  511. package/src/bucket/providers/MemoryFileStorageProvider.ts +18 -7
  512. package/src/bucket/providers/R2FileStorageProvider.ts +14 -6
  513. package/src/bucket/providers/S3FileStorageProvider.ts +31 -15
  514. package/src/cache/core/primitives/$cache.ts +7 -10
  515. package/src/cache/database/entities/cacheEntries.ts +16 -27
  516. package/src/cache/database/providers/DatabaseCacheProvider.ts +15 -13
  517. package/src/cache/redis/providers/RedisCacheProvider.ts +6 -6
  518. package/src/captcha/providers/TurnstileCaptchaProvider.ts +4 -4
  519. package/src/cli/core/__tests__/BuildCloudflareTask.spec.ts +178 -0
  520. package/src/cli/core/__tests__/BuildDockerTask.spec.ts +0 -2
  521. package/src/cli/core/__tests__/DbCommand.spec.ts +108 -0
  522. package/src/cli/core/atoms/appEntryOptions.ts +5 -5
  523. package/src/cli/core/atoms/buildOptions.ts +76 -88
  524. package/src/cli/core/atoms/changelogOptions.ts +3 -3
  525. package/src/cli/core/atoms/devOptions.ts +3 -3
  526. package/src/cli/core/commands/build.ts +36 -49
  527. package/src/cli/core/commands/db.ts +171 -83
  528. package/src/cli/core/commands/dev.ts +8 -8
  529. package/src/cli/core/commands/gen/changelog.ts +12 -14
  530. package/src/cli/core/commands/gen/env.ts +6 -6
  531. package/src/cli/core/commands/gen/openapi.ts +6 -6
  532. package/src/cli/core/commands/init.ts +28 -33
  533. package/src/cli/core/commands/pack.ts +10 -10
  534. package/src/cli/core/commands/root.ts +7 -8
  535. package/src/cli/core/commands/test.ts +17 -20
  536. package/src/cli/core/index.ts +0 -3
  537. package/src/cli/core/tasks/BuildCloudflareTask.ts +138 -245
  538. package/src/cli/core/tasks/BuildPrerenderTask.ts +44 -7
  539. package/src/cli/core/templates/apiHelloResponseSchemaTs.ts +4 -4
  540. package/src/cli/devtools/atoms/devtoolsOptions.ts +6 -6
  541. package/src/cli/i18n/__tests__/I18nCheckService.spec.ts +48 -0
  542. package/src/cli/i18n/atoms/i18nOptions.ts +8 -8
  543. package/src/cli/i18n/services/I18nCheckService.ts +65 -11
  544. package/src/cli/platform/commands/SecretsCommand.ts +24 -25
  545. package/src/cli/platform/commands/platform.ts +40 -46
  546. package/src/cli/platform/index.ts +1 -1
  547. package/src/cli/platform-lib/__tests__/CloudflareAdapter.spec.ts +0 -4
  548. package/src/cli/platform-lib/__tests__/PlatformInspector.spec.ts +10 -3
  549. package/src/cli/platform-lib/__tests__/VercelAdapter.spec.ts +0 -2
  550. package/src/cli/platform-lib/adapters/CloudflareAdapter.ts +141 -50
  551. package/src/cli/platform-lib/adapters/VercelAdapter.ts +6 -11
  552. package/src/cli/platform-lib/atoms/platformOptions.ts +46 -25
  553. package/src/cli/platform-lib/schemas/cloudflare.ts +87 -87
  554. package/src/cli/platform-lib/schemas/platform.ts +51 -51
  555. package/src/cli/platform-lib/schemas/vercel.ts +28 -28
  556. package/src/cli/platform-lib/services/CloudflareApi.ts +5 -5
  557. package/src/cli/platform-lib/services/VercelApi.ts +4 -4
  558. package/src/cli/platform-lib/services/VercelCli.ts +6 -15
  559. package/src/cli/platform-lib/services/WranglerApi.ts +6 -15
  560. package/src/cli/vendor/atoms/vendorOptions.ts +9 -9
  561. package/src/cli/vendor/commands/VendorCommand.ts +11 -12
  562. package/src/command/__tests__/$command.spec.ts +82 -83
  563. package/src/command/__tests__/Asker.spec.ts +6 -13
  564. package/src/command/__tests__/CliProvider.spec.ts +136 -149
  565. package/src/command/__tests__/Runner.spec.ts +86 -110
  566. package/src/command/helpers/Asker.ts +23 -58
  567. package/src/command/helpers/Runner.ts +34 -110
  568. package/src/command/index.ts +4 -9
  569. package/src/command/primitives/$command.ts +10 -10
  570. package/src/command/providers/CliProvider.ts +183 -161
  571. package/src/core/Alepha.ts +62 -13
  572. package/src/core/__tests__/$atom.spec.ts +52 -3
  573. package/src/core/__tests__/$computed.spec.ts +129 -0
  574. package/src/core/__tests__/$env.spec.ts +13 -13
  575. package/src/core/__tests__/$inject.spec.ts +4 -4
  576. package/src/core/__tests__/$module.spec.ts +1 -1
  577. package/src/core/__tests__/Alepha-graph.spec.ts +1 -1
  578. package/src/core/__tests__/Alepha-parseEnv.spec.ts +32 -32
  579. package/src/core/__tests__/Alepha-start.spec.ts +3 -3
  580. package/src/core/__tests__/CodecManager.spec.ts +113 -94
  581. package/src/core/__tests__/KeylessJsonSchemaCodec.spec.ts +138 -138
  582. package/src/core/__tests__/SchemaValidator.spec.ts +43 -44
  583. package/src/core/__tests__/StateManager.persist.browser.spec.ts +87 -0
  584. package/src/core/__tests__/StateManager.spec.ts +423 -0
  585. package/src/core/__tests__/TypeBox-usecases.spec.ts +8 -8
  586. package/src/core/__tests__/TypeProvider.spec.ts +314 -309
  587. package/src/core/__tests__/dump.spec.ts +6 -6
  588. package/src/core/__tests__/pagination.spec.ts +4 -4
  589. package/src/core/__tests__/scoped-after-start.spec.ts +43 -0
  590. package/src/core/errors/TypeBoxError.ts +10 -4
  591. package/src/core/helpers/FileLike.ts +5 -5
  592. package/src/core/helpers/coerceStrings.ts +70 -0
  593. package/src/core/helpers/jsonSchemaToZod.ts +112 -0
  594. package/src/core/index.shared.ts +4 -1
  595. package/src/core/primitives/$atom.ts +95 -27
  596. package/src/core/primitives/$computed.ts +148 -0
  597. package/src/core/primitives/$env.ts +5 -5
  598. package/src/core/primitives/$state.ts +1 -1
  599. package/src/core/providers/AlsProvider.ts +26 -0
  600. package/src/core/providers/CodecManager.ts +1 -2
  601. package/src/core/providers/JsonSchemaCodec.ts +1 -2
  602. package/src/core/providers/KeylessJsonSchemaCodec.ts +82 -57
  603. package/src/core/providers/SchemaValidator.ts +48 -158
  604. package/src/core/providers/StateManager.ts +383 -9
  605. package/src/core/providers/TypeProvider.ts +80 -734
  606. package/src/core/providers/ZodProvider.ts +380 -0
  607. package/src/core/providers/zodAugment.ts +69 -0
  608. package/src/core/schemas/pageQuerySchema.ts +19 -21
  609. package/src/core/schemas/pageSchema.ts +47 -57
  610. package/src/crypto/__tests__/SecretProvider.spec.ts +31 -0
  611. package/src/crypto/providers/SecretProvider.ts +16 -10
  612. package/src/datetime/primitives/$throttle.ts +6 -1
  613. package/src/email/brevo/providers/BrevoEmailProvider.ts +4 -4
  614. package/src/email/cloudflare/providers/CloudflareEmailProvider.ts +6 -6
  615. package/src/email/core/index.ts +7 -2
  616. package/src/email/core/primitives/$email.ts +5 -1
  617. package/src/email/core/providers/LocalEmailProvider.ts +5 -5
  618. package/src/email/smtp/providers/NodemailerEmailProvider.ts +41 -52
  619. package/src/fake/__tests__/FakeProvider.spec.ts +110 -110
  620. package/src/fake/__tests__/keyName.example.ts +21 -21
  621. package/src/fake/__tests__/keyName.spec.ts +41 -41
  622. package/src/fake/__tests__/module.example.ts +8 -8
  623. package/src/fake/providers/FakeProvider.ts +122 -121
  624. package/src/lock/core/__tests__/lock-mutual-exclusion.spec.ts +44 -0
  625. package/src/lock/core/index.ts +1 -0
  626. package/src/lock/core/primitives/$lock.ts +13 -6
  627. package/src/logger/__tests__/CliFormatterProvider.spec.ts +76 -0
  628. package/src/logger/__tests__/Logger.spec.ts +49 -0
  629. package/src/logger/index.ts +25 -18
  630. package/src/logger/providers/CliFormatterProvider.ts +75 -0
  631. package/src/logger/schemas/logEntrySchema.ts +10 -10
  632. package/src/logger/services/Logger.ts +18 -0
  633. package/src/mcp/__tests__/$prompt.spec.ts +21 -23
  634. package/src/mcp/__tests__/$tool.spec.ts +22 -22
  635. package/src/mcp/__tests__/McpServerProvider.spec.ts +82 -11
  636. package/src/mcp/__tests__/StreamableHttpMcpTransport.spec.ts +2 -2
  637. package/src/mcp/__tests__/integration.spec.ts +33 -33
  638. package/src/mcp/primitives/$prompt.ts +11 -9
  639. package/src/mcp/primitives/$tool.ts +27 -86
  640. package/src/mcp/providers/McpServerProvider.ts +55 -0
  641. package/src/mcp/transports/StreamableHttpMcpTransport.ts +7 -7
  642. package/src/orm/__tests__/$repository-tests.ts +133 -27
  643. package/src/orm/__tests__/$repository.spec.ts +23 -0
  644. package/src/orm/__tests__/$transactional-tests.ts +4 -4
  645. package/src/orm/__tests__/ModelBuilder-tests.ts +28 -28
  646. package/src/orm/__tests__/ModelBuilder.spec.ts +124 -106
  647. package/src/orm/__tests__/QueryManager.spec.ts +5 -5
  648. package/src/orm/__tests__/delete-returning-tests.ts +11 -11
  649. package/src/orm/__tests__/deletedAt-tests.ts +3 -3
  650. package/src/orm/__tests__/enums.spec.ts +29 -25
  651. package/src/orm/__tests__/execute-tests.ts +8 -8
  652. package/src/orm/__tests__/fixtures/bigEntitySchema.ts +48 -48
  653. package/src/orm/__tests__/fixtures/userEntitySchema.ts +6 -6
  654. package/src/orm/__tests__/joins-tests.ts +30 -30
  655. package/src/orm/__tests__/organization-tests.ts +105 -3
  656. package/src/orm/__tests__/organization.spec.ts +46 -0
  657. package/src/orm/__tests__/orm-errors.spec.ts +10 -10
  658. package/src/orm/__tests__/orm-next-tests.ts +29 -29
  659. package/src/orm/__tests__/orm-showcase-tests.ts +9 -9
  660. package/src/orm/__tests__/primaryKey.spec.ts +4 -4
  661. package/src/orm/__tests__/query-date-encoding-tests.ts +17 -17
  662. package/src/orm/__tests__/ref-auto-onDelete.spec.ts +14 -14
  663. package/src/orm/__tests__/references.spec.ts +7 -7
  664. package/src/orm/__tests__/security.spec.ts +17 -17
  665. package/src/orm/__tests__/string-operators-tests.ts +5 -5
  666. package/src/orm/__tests__/timestamps-tests.ts +14 -14
  667. package/src/orm/__tests__/validation-tests.ts +5 -5
  668. package/src/orm/core/__tests__/BunSqliteProvider.bun.spec.ts +8 -8
  669. package/src/orm/core/constants/PG_SYMBOLS.ts +13 -1
  670. package/src/orm/core/entities/alephaSequences.ts +8 -8
  671. package/src/orm/core/helpers/pgAttr.ts +4 -4
  672. package/src/orm/core/primitives/$entity.ts +10 -6
  673. package/src/orm/core/providers/DatabaseTypeProvider.ts +46 -53
  674. package/src/orm/core/providers/drivers/BunSqliteProvider.ts +8 -8
  675. package/src/orm/core/providers/drivers/CloudflareD1Provider.ts +3 -5
  676. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +8 -8
  677. package/src/orm/core/schemas/databaseEnvSchema.ts +4 -4
  678. package/src/orm/core/schemas/insertSchema.ts +14 -18
  679. package/src/orm/core/schemas/legacyIdSchema.ts +2 -2
  680. package/src/orm/core/schemas/updateSchema.ts +10 -16
  681. package/src/orm/core/services/PgRelationManager.ts +2 -2
  682. package/src/orm/core/services/QueryManager.ts +13 -2
  683. package/src/orm/core/services/Repository.ts +88 -33
  684. package/src/orm/core/services/SqliteModelBuilder.ts +38 -45
  685. package/src/orm/postgres/__tests__/BunPostgresProvider.bun.spec.ts +4 -4
  686. package/src/orm/postgres/providers/CloudflareHyperdriveProvider.ts +4 -6
  687. package/src/orm/postgres/schemas/postgresEnvSchema.ts +6 -6
  688. package/src/orm/postgres/services/PostgresModelBuilder.ts +127 -114
  689. package/src/queue/core/__tests__/$consumer.spec.ts +4 -4
  690. package/src/queue/core/__tests__/WorkerProvider.spec.ts +4 -4
  691. package/src/queue/core/__tests__/shared.ts +6 -6
  692. package/src/queue/core/primitives/$consumer.ts +5 -5
  693. package/src/queue/core/primitives/$queue.ts +44 -61
  694. package/src/queue/core/providers/CloudflareQueueProvider.ts +6 -0
  695. package/src/queue/core/providers/WorkerProvider.ts +17 -14
  696. package/src/queue/redis/providers/RedisQueueProvider.ts +3 -3
  697. package/src/react/core/__tests__/ErrorBoundary.browser.spec.tsx +92 -0
  698. package/src/react/core/__tests__/Router.spec.tsx +4 -4
  699. package/src/react/core/__tests__/useComputed.browser.spec.tsx +192 -0
  700. package/src/react/core/__tests__/useQuery.browser.spec.tsx +48 -0
  701. package/src/react/core/__tests__/useSelector.browser.spec.tsx +105 -0
  702. package/src/react/core/__tests__/useStore.browser.spec.tsx +113 -0
  703. package/src/react/core/components/ErrorBoundary.tsx +42 -0
  704. package/src/react/core/hooks/useAction.ts +56 -19
  705. package/src/react/core/hooks/useComputed.ts +91 -0
  706. package/src/react/core/hooks/useSelector.ts +67 -0
  707. package/src/react/core/hooks/useStore.ts +36 -17
  708. package/src/react/core/index.ts +3 -0
  709. package/src/react/core/utils/shallowEqual.ts +36 -0
  710. package/src/react/form/__tests__/FormModel-submit-loading.spec.ts +71 -0
  711. package/src/react/form/__tests__/form-submitting-reactive.browser.spec.tsx +96 -0
  712. package/src/react/form/__tests__/useForm.browser.spec.tsx +54 -54
  713. package/src/react/form/errors/FormValidationError.ts +0 -2
  714. package/src/react/form/hooks/useForm.ts +19 -4
  715. package/src/react/form/hooks/useFormQuerySync.ts +0 -0
  716. package/src/react/form/services/FormModel.ts +124 -86
  717. package/src/react/form/services/parseField.ts +66 -27
  718. package/src/react/i18n/__tests__/I18nProvider.spec.ts +89 -0
  719. package/src/react/i18n/__tests__/Localize.spec.tsx +1 -1
  720. package/src/react/i18n/__tests__/locale-routing.spec.ts +107 -0
  721. package/src/react/i18n/providers/I18nProvider.ts +173 -14
  722. package/src/react/router/__tests__/$page.browser.spec.tsx +19 -19
  723. package/src/react/router/__tests__/$page.spec.tsx +21 -21
  724. package/src/react/router/__tests__/ReactBrowserProvider.browser.spec.ts +87 -1
  725. package/src/react/router/__tests__/RouterLocaleProvider.spec.ts +127 -0
  726. package/src/react/router/atoms/ssrManifestAtom.ts +16 -16
  727. package/src/react/router/components/NestedView.tsx +11 -3
  728. package/src/react/router/hooks/useQueryParams.ts +1 -1
  729. package/src/react/router/index.browser.ts +4 -0
  730. package/src/react/router/index.shared.ts +1 -0
  731. package/src/react/router/index.ts +9 -0
  732. package/src/react/router/primitives/$page.ts +2 -2
  733. package/src/react/router/providers/ReactBrowserProvider.ts +64 -13
  734. package/src/react/router/providers/ReactBrowserRouterProvider.ts +15 -1
  735. package/src/react/router/providers/ReactPageProvider.ts +38 -13
  736. package/src/react/router/providers/ReactServerProvider.ts +105 -16
  737. package/src/react/router/providers/RootComponentsProvider.ts +13 -0
  738. package/src/react/router/providers/RouterLocaleProvider.ts +125 -0
  739. package/src/react/router/providers/__tests__/RootComponentsProvider.spec.ts +15 -0
  740. package/src/react/router/providers/__tests__/rootComponents.ssr.browser.spec.tsx +67 -0
  741. package/src/react/sitemap/__tests__/$sitemap.spec.ts +131 -0
  742. package/src/react/sitemap/index.browser.ts +21 -0
  743. package/src/react/sitemap/index.ts +25 -0
  744. package/src/react/sitemap/primitives/$sitemap.browser.ts +26 -0
  745. package/src/react/sitemap/primitives/$sitemap.ts +196 -0
  746. package/src/react/ui/atoms/uiAtom.ts +6 -6
  747. package/src/react/ui/atoms/uiThemeListAtom.ts +7 -7
  748. package/src/react/ui/hooks/useColorMode.ts +11 -4
  749. package/src/react/ui/services/SchemaControl.ts +4 -4
  750. package/src/redis/providers/BunRedisProvider.ts +19 -11
  751. package/src/redis/providers/NodeRedisProvider.ts +3 -3
  752. package/src/scheduler/primitives/$scheduler.ts +21 -8
  753. package/src/security/__tests__/assertRealmScope.spec.ts +29 -0
  754. package/src/security/atoms/currentTenantAtom.ts +6 -6
  755. package/src/security/atoms/currentUserAtom.ts +2 -2
  756. package/src/security/primitives/$issuer.ts +24 -2
  757. package/src/security/providers/JwtProvider.ts +100 -0
  758. package/src/security/providers/SecurityProvider.ts +43 -2
  759. package/src/security/schemas/permissionSchema.ts +19 -19
  760. package/src/security/schemas/roleSchema.ts +22 -28
  761. package/src/security/schemas/userAccountInfoSchema.ts +47 -37
  762. package/src/server/auth/__tests__/appleClientSecret.spec.ts +34 -0
  763. package/src/server/auth/__tests__/federationRedirectReplay.spec.ts +44 -0
  764. package/src/server/auth/helpers/appleClientSecret.ts +24 -0
  765. package/src/server/auth/helpers/jtiReplayGuard.ts +41 -0
  766. package/src/server/auth/helpers/safeRedirectPath.ts +19 -0
  767. package/src/server/auth/index.ts +1 -0
  768. package/src/server/auth/primitives/$auth.ts +6 -6
  769. package/src/server/auth/primitives/$authApple.ts +10 -10
  770. package/src/server/auth/primitives/$authFacebook.ts +10 -10
  771. package/src/server/auth/primitives/$authFranceConnect.ts +10 -10
  772. package/src/server/auth/primitives/$authGithub.ts +10 -10
  773. package/src/server/auth/primitives/$authGoogle.ts +10 -10
  774. package/src/server/auth/primitives/$authMicrosoft.ts +14 -14
  775. package/src/server/auth/providers/ServerAuthProvider.ts +67 -52
  776. package/src/server/auth/schemas/authenticationProviderSchema.ts +9 -12
  777. package/src/server/auth/schemas/tokenResponseSchema.ts +2 -2
  778. package/src/server/auth/schemas/tokensSchema.ts +16 -16
  779. package/src/server/auth/schemas/userinfoResponseSchema.ts +3 -3
  780. package/src/server/cookies/__tests__/AtomCookieBinding.spec.ts +80 -0
  781. package/src/server/cookies/__tests__/AtomCookiePersistence.browser.spec.ts +169 -0
  782. package/src/server/cookies/__tests__/AtomCookiePersistence.spec.ts +294 -0
  783. package/src/server/cookies/__tests__/ServerCookiesProvider.spec.ts +82 -12
  784. package/src/server/cookies/index.browser.ts +4 -1
  785. package/src/server/cookies/index.ts +8 -1
  786. package/src/server/cookies/primitives/$cookie.browser.ts +1 -1
  787. package/src/server/cookies/primitives/$cookie.ts +16 -0
  788. package/src/server/cookies/providers/AtomCookiePersistence.browser.ts +133 -0
  789. package/src/server/cookies/providers/AtomCookiePersistence.ts +148 -0
  790. package/src/server/cookies/providers/ServerCookiesProvider.ts +32 -4
  791. package/src/server/cookies/services/CookieParser.ts +6 -1
  792. package/src/server/core/__tests__/$action.spec.ts +13 -13
  793. package/src/server/core/__tests__/$middleware.spec.ts +10 -10
  794. package/src/server/core/__tests__/$route.spec.ts +9 -9
  795. package/src/server/core/__tests__/$sse.spec.ts +26 -26
  796. package/src/server/core/__tests__/BunHttpServerProvider.bun.spec.ts +6 -6
  797. package/src/server/core/__tests__/HttpClient.spec.ts +2 -2
  798. package/src/server/core/__tests__/NodeHttpServerProvider.spec.ts +15 -3
  799. package/src/server/core/__tests__/ServerBodyParserProvider.spec.ts +14 -14
  800. package/src/server/core/__tests__/ServerMultipartProvider.spec.ts +33 -33
  801. package/src/server/core/__tests__/ServerRouterProvider-errorHandler.spec.ts +5 -1
  802. package/src/server/core/__tests__/ServerRouterProvider-getRoutes.spec.ts +25 -25
  803. package/src/server/core/__tests__/ServerRouterProvider-serializationError.spec.ts +9 -5
  804. package/src/server/core/__tests__/ServerRouterProvider-validationError.spec.ts +56 -24
  805. package/src/server/core/errors/ValidationError.ts +6 -3
  806. package/src/server/core/helpers/isMultipart.ts +2 -1
  807. package/src/server/core/index.ts +5 -2
  808. package/src/server/core/interfaces/ServerRequest.ts +14 -14
  809. package/src/server/core/primitives/$action.ts +26 -36
  810. package/src/server/core/primitives/$route.ts +27 -0
  811. package/src/server/core/primitives/$sse.ts +3 -3
  812. package/src/server/core/providers/BunHttpServerProvider.ts +8 -9
  813. package/src/server/core/providers/NodeHttpServerProvider.ts +8 -9
  814. package/src/server/core/providers/ServerBodyParserProvider.ts +20 -12
  815. package/src/server/core/providers/ServerCompressProvider.ts +9 -10
  816. package/src/server/core/providers/ServerHelmetProvider.ts +26 -27
  817. package/src/server/core/providers/ServerMultipartProvider.ts +19 -19
  818. package/src/server/core/providers/ServerRouterProvider.ts +44 -15
  819. package/src/server/core/schemas/errorSchema.ts +20 -25
  820. package/src/server/core/schemas/okSchema.ts +9 -14
  821. package/src/server/core/services/HttpClient.ts +13 -1
  822. package/src/server/core/services/ServerRequestParser.ts +6 -6
  823. package/src/server/cors/providers/ServerCorsProvider.ts +26 -28
  824. package/src/server/health/schemas/healthSchema.ts +6 -6
  825. package/src/server/links/__tests__/$remote.spec.ts +3 -3
  826. package/src/server/links/__tests__/BatchEndpoint.spec.ts +9 -9
  827. package/src/server/links/__tests__/LinkProvider.spec.ts +9 -9
  828. package/src/server/links/__tests__/ServerLinksProvider.spec.ts +23 -23
  829. package/src/server/links/__tests__/fixtures/CrudApp.ts +21 -21
  830. package/src/server/links/atoms/apiLinksAtom.ts +2 -2
  831. package/src/server/links/atoms/linkOptionsAtom.ts +6 -6
  832. package/src/server/links/primitives/$remote.ts +3 -3
  833. package/src/server/links/providers/LinkProvider.ts +3 -3
  834. package/src/server/links/providers/ServerLinksProvider.ts +20 -20
  835. package/src/server/links/schemas/apiLinksResponseSchema.ts +23 -23
  836. package/src/server/proxy/__tests__/$proxy.spec.ts +9 -9
  837. package/src/server/proxy/providers/ServerProxyProvider.ts +5 -0
  838. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +18 -20
  839. package/src/server/swagger/__tests__/$swagger.spec.ts +91 -94
  840. package/src/server/swagger/__tests__/ui.spec.ts +3 -3
  841. package/src/server/swagger/providers/ServerSwaggerProvider.ts +66 -43
  842. package/src/system/__tests__/NodeShellProvider.spec.ts +46 -0
  843. package/src/system/providers/NodeShellProvider.ts +4 -1
  844. package/src/topic/core/__tests__/$subscriber.spec.ts +4 -4
  845. package/src/topic/core/__tests__/shared.ts +8 -8
  846. package/src/topic/core/primitives/$subscriber.ts +5 -5
  847. package/src/topic/core/primitives/$topic.ts +14 -14
  848. package/src/topic/redis/providers/RedisTopicProvider.ts +3 -3
  849. package/dist/container/core/index.d.ts +0 -236
  850. package/dist/container/core/index.d.ts.map +0 -1
  851. package/dist/container/core/index.js +0 -231
  852. package/dist/container/core/index.js.map +0 -1
  853. package/dist/container/core/index.workerd.js +0 -192
  854. package/dist/container/core/index.workerd.js.map +0 -1
  855. package/src/cli/core/tasks/BuildSitemapTask.ts +0 -130
  856. package/src/command/helpers/PrettyAsker.ts +0 -256
  857. package/src/command/helpers/PrettyPrint.ts +0 -332
  858. package/src/container/core/__tests__/$container.spec.ts +0 -83
  859. package/src/container/core/index.ts +0 -50
  860. package/src/container/core/index.workerd.ts +0 -53
  861. package/src/container/core/interfaces/ContainerOptions.ts +0 -69
  862. package/src/container/core/primitives/$container.ts +0 -100
  863. package/src/container/core/providers/CloudflareContainerProvider.ts +0 -70
  864. package/src/container/core/providers/ContainerProvider.ts +0 -92
  865. package/src/container/core/providers/MockContainerProvider.ts +0 -62
  866. package/src/container/core/providers/NodeContainerProvider.ts +0 -53
  867. package/src/core/__tests__/jsonSchemaToTypeBox.spec.ts +0 -771
  868. package/src/core/helpers/jsonSchemaToTypeBox.ts +0 -359
  869. /package/dist/orm/core/{chunk-B4FMCO8f.js → rolldown-runtime-B4FMCO8f.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  import { $module, Alepha, AlephaError, Atom } from "alepha";
2
- import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
2
+ import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  import { DateTimeProvider } from "alepha/datetime";
5
5
  import { LinkProvider } from "alepha/server/links";
@@ -59,6 +59,18 @@ var ErrorBoundary = class extends React.Component {
59
59
  componentDidCatch(error, info) {
60
60
  if (this.props.onError) this.props.onError(error, info);
61
61
  }
62
+ /**
63
+ * Recover once the caller signals the failing input is gone.
64
+ */
65
+ componentDidUpdate(prevProps) {
66
+ if (!this.state.error) return;
67
+ if (this.hasResetKeyChanged(prevProps.resetKeys, this.props.resetKeys)) this.setState({ error: void 0 });
68
+ }
69
+ hasResetKeyChanged(previous, next) {
70
+ if (previous === next) return false;
71
+ if (!previous || !next || previous.length !== next.length) return true;
72
+ return previous.some((value, i) => !Object.is(value, next[i]));
73
+ }
62
74
  render() {
63
75
  if (this.state.error) {
64
76
  const reset = () => {
@@ -242,6 +254,7 @@ function useAction(options, deps) {
242
254
  const abortControllerRef = useRef(void 0);
243
255
  const isMountedRef = useRef(true);
244
256
  const intervalRef = useRef(void 0);
257
+ const runIdRef = useRef(0);
245
258
  useEffect(() => {
246
259
  isMountedRef.current = true;
247
260
  return () => {
@@ -261,11 +274,13 @@ function useAction(options, deps) {
261
274
  isExecutingRef.current = false;
262
275
  };
263
276
  }, []);
264
- const executeAction = useCallback(async (...args) => {
265
- if (isExecutingRef.current) return;
277
+ const executeAction = useCallback(async (args, { supersede = false } = {}) => {
278
+ if (isExecutingRef.current && !supersede) return;
266
279
  if (abortControllerRef.current) abortControllerRef.current.abort();
267
280
  const abortController = new AbortController();
268
281
  abortControllerRef.current = abortController;
282
+ const runId = ++runIdRef.current;
283
+ const isLatestRun = () => runIdRef.current === runId;
269
284
  isExecutingRef.current = true;
270
285
  setLoading(true);
271
286
  setError(void 0);
@@ -275,7 +290,7 @@ function useAction(options, deps) {
275
290
  id: options.id
276
291
  });
277
292
  const result = await options.handler(...args, { signal: abortController.signal });
278
- if (!isMountedRef.current || abortController.signal.aborted) return;
293
+ if (!isMountedRef.current || abortController.signal.aborted || !isLatestRun()) return;
279
294
  setResult(result);
280
295
  await alepha.events.emit("react:action:success", {
281
296
  type: "custom",
@@ -285,7 +300,7 @@ function useAction(options, deps) {
285
300
  return result;
286
301
  } catch (err) {
287
302
  if (err instanceof Error && err.name === "AbortError") return;
288
- if (!isMountedRef.current) return;
303
+ if (!isMountedRef.current || !isLatestRun()) return;
289
304
  const error = err;
290
305
  setError(error);
291
306
  await alepha.events.emit("react:action:error", {
@@ -295,8 +310,10 @@ function useAction(options, deps) {
295
310
  });
296
311
  if (options.onError) await options.onError(error);
297
312
  } finally {
298
- isExecutingRef.current = false;
299
- if (isMountedRef.current) setLoading(false);
313
+ if (isLatestRun()) {
314
+ isExecutingRef.current = false;
315
+ if (isMountedRef.current) setLoading(false);
316
+ }
300
317
  await alepha.events.emit("react:action:end", {
301
318
  type: "custom",
302
319
  id: options.id
@@ -309,17 +326,22 @@ function useAction(options, deps) {
309
326
  options.onError,
310
327
  options.onSuccess
311
328
  ]);
312
- const handler = useCallback(async (...args) => {
329
+ const runAction = useCallback(async (args, options_ = {}) => {
313
330
  if (options.debounce) {
314
331
  if (debounceTimerRef.current) dateTimeProvider.clearTimeout(debounceTimerRef.current);
315
332
  return new Promise((resolve) => {
316
333
  debounceTimerRef.current = dateTimeProvider.createTimeout(async () => {
317
- resolve(await executeAction(...args));
334
+ resolve(await executeAction(args, options_));
318
335
  }, options.debounce ?? 0);
319
336
  });
320
337
  }
321
- return executeAction(...args);
338
+ return executeAction(args, options_);
322
339
  }, [executeAction, options.debounce]);
340
+ /**
341
+ * Public `run()` — a user-initiated call. Deduped while one is in flight so a
342
+ * double-clicked mutation submits once.
343
+ */
344
+ const handler = useCallback((...args) => runAction(args), [runAction]);
323
345
  const cancel = useCallback(() => {
324
346
  if (debounceTimerRef.current) {
325
347
  dateTimeProvider.clearTimeout(debounceTimerRef.current);
@@ -335,18 +357,18 @@ function useAction(options, deps) {
335
357
  }
336
358
  }, []);
337
359
  useEffect(() => {
338
- if (options.runOnInit) handler(...[]);
360
+ if (options.runOnInit) runAction([], { supersede: true });
339
361
  }, deps);
340
362
  useEffect(() => {
341
363
  if (!options.runEvery) return;
342
- intervalRef.current = dateTimeProvider.createInterval(() => handler(...[]), options.runEvery, true);
364
+ intervalRef.current = dateTimeProvider.createInterval(() => runAction([], { supersede: true }), options.runEvery, true);
343
365
  return () => {
344
366
  if (intervalRef.current) {
345
367
  dateTimeProvider.clearInterval(intervalRef.current);
346
368
  intervalRef.current = void 0;
347
369
  }
348
370
  };
349
- }, [handler, options.runEvery]);
371
+ }, [runAction, options.runEvery]);
350
372
  return {
351
373
  run: handler,
352
374
  loading,
@@ -369,6 +391,66 @@ const useClient = (scope) => {
369
391
  }, [scope]);
370
392
  };
371
393
  //#endregion
394
+ //#region ../../src/react/core/hooks/useComputed.ts
395
+ /**
396
+ * Subscribes to a `$computed` value.
397
+ *
398
+ * `getSnapshot` always reads the dependency atoms **live** off the store —
399
+ * never through a subscription-set dirty flag. A dirty flag is only ever
400
+ * flipped by the `state:mutate` listener registered in `subscribe`, which
401
+ * React wires up in a passive effect (after commit); `EventManager.emit` is
402
+ * async on top of that. A mutation dispatched between the initial render and
403
+ * that effect committing would be invisible to the flag, so `getSnapshot`
404
+ * (including React's own post-subscribe consistency re-check) would keep
405
+ * returning the stale pre-mutation value. See `useStore.ts` and
406
+ * `useSelector.ts` for the same rationale.
407
+ *
408
+ * Referential stability for `useSyncExternalStore` comes from comparing the
409
+ * *inputs* (the resolved values of the computed's transitive atom
410
+ * dependencies) by identity, not from caching on a mount-time ref: when none
411
+ * of the inputs changed since the last snapshot, the previous output
412
+ * reference is returned as-is; when any input changed (or `target` itself
413
+ * was swapped for a different `Computed`), the value is recomputed and a new
414
+ * reference is cached.
415
+ *
416
+ * A `Computed` passed here should be declared at module scope, like an
417
+ * atom — constructing one inline in a component body creates a new
418
+ * instance every render, which (because `subscribe`/`getSnapshot` are keyed
419
+ * on `target.key`, matching `useStore`/`useSelector`) is tolerated for
420
+ * resubscription purposes, but any closures captured by that instance's
421
+ * `get()` will be locked to whichever render first created the subscription
422
+ * until `target.key` itself changes.
423
+ *
424
+ * ```tsx
425
+ * const total = useComputed(cartTotal);
426
+ * ```
427
+ */
428
+ function useComputed(target) {
429
+ const alepha = useAlepha();
430
+ const key = target.key;
431
+ const cache = useRef(null);
432
+ const subscribe = useCallback((onStoreChange) => {
433
+ if (!alepha.isBrowser()) return () => {};
434
+ const keys = new Set(target.keys());
435
+ return alepha.events.on("state:mutate", (ev) => {
436
+ if (keys.has(ev.key)) onStoreChange();
437
+ });
438
+ }, [alepha, key]);
439
+ const getSnapshot = useCallback(() => {
440
+ const inputs = target.keys().map((depKey) => alepha.store.get(depKey));
441
+ const prev = cache.current;
442
+ if (prev && prev.target === target && prev.inputs.length === inputs.length && prev.inputs.every((value, index) => Object.is(value, inputs[index]))) return prev.value;
443
+ const value = alepha.store.get(target);
444
+ cache.current = {
445
+ target,
446
+ inputs,
447
+ value
448
+ };
449
+ return value;
450
+ }, [alepha, key]);
451
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
452
+ }
453
+ //#endregion
372
454
  //#region ../../src/react/core/hooks/useEvents.ts
373
455
  /**
374
456
  * Allow subscribing to multiple Alepha events. See {@link Hooks} for available events.
@@ -472,25 +554,90 @@ function useQuery(options, deps) {
472
554
  };
473
555
  }
474
556
  //#endregion
557
+ //#region ../../src/react/core/hooks/useSelector.ts
558
+ /**
559
+ * Subscribes to a slice of an atom's state.
560
+ *
561
+ * Unlike {@link useStore}, which re-renders on every mutation of the atom,
562
+ * `useSelector` re-renders only when the selected slice actually changes
563
+ * according to `equality` (default: `Object.is`). Pass {@link shallowEqual}
564
+ * when the selector builds a fresh object on each call.
565
+ *
566
+ * ```tsx
567
+ * const theme = useSelector(uiAtom, (s) => s.theme);
568
+ * ```
569
+ */
570
+ function useSelector(target, select, equality = Object.is) {
571
+ const alepha = useAlepha();
572
+ const key = target.key;
573
+ const cache = useRef(null);
574
+ const selectRef = useRef(select);
575
+ selectRef.current = select;
576
+ const equalityRef = useRef(equality);
577
+ equalityRef.current = equality;
578
+ const subscribe = useCallback((onStoreChange) => {
579
+ if (!alepha.isBrowser()) return () => {};
580
+ return alepha.events.on("state:mutate", (ev) => {
581
+ if (ev.key === key) onStoreChange();
582
+ });
583
+ }, [alepha, key]);
584
+ const getSnapshot = useCallback(() => {
585
+ const input = alepha.store.get(target);
586
+ const prev = cache.current;
587
+ if (prev && Object.is(prev.input, input)) return prev.selected;
588
+ const selected = selectRef.current(input);
589
+ if (prev && equalityRef.current(prev.selected, selected)) {
590
+ cache.current = {
591
+ input,
592
+ selected: prev.selected
593
+ };
594
+ return prev.selected;
595
+ }
596
+ cache.current = {
597
+ input,
598
+ selected
599
+ };
600
+ return selected;
601
+ }, [alepha, key]);
602
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
603
+ }
604
+ //#endregion
475
605
  //#region ../../src/react/core/hooks/useStore.ts
476
606
  function useStore(target, defaultValue) {
477
607
  const alepha = useAlepha();
608
+ const key = target instanceof Atom ? target.key : target;
478
609
  useMemo(() => {
479
610
  if (defaultValue != null && alepha.store.get(target) == null) alepha.store.set(target, defaultValue);
480
- }, [defaultValue]);
481
- const [state, setState] = useState(alepha.store.get(target));
482
- useEffect(() => {
483
- if (!alepha.isBrowser()) return;
484
- const key = target instanceof Atom ? target.key : target;
611
+ }, [defaultValue, key]);
612
+ const subscribe = useCallback((onStoreChange) => {
613
+ if (!alepha.isBrowser()) return () => {};
485
614
  return alepha.events.on("state:mutate", (ev) => {
486
- if (ev.key === key) setState(ev.value);
615
+ if (ev.key === key) onStoreChange();
487
616
  });
488
- }, []);
489
- return [state, (value) => {
617
+ }, [alepha, key]);
618
+ const getSnapshot = useCallback(() => alepha.store.get(target), [alepha, key]);
619
+ return [useSyncExternalStore(subscribe, getSnapshot, getSnapshot), useCallback((value) => {
490
620
  alepha.store.set(target, value);
491
- }];
621
+ }, [alepha, key])];
492
622
  }
493
623
  //#endregion
624
+ //#region ../../src/react/core/utils/shallowEqual.ts
625
+ /**
626
+ * Shallow structural equality over own enumerable keys.
627
+ *
628
+ * Intended as the `equality` argument of `useSelector` when the selector
629
+ * builds a fresh object/array on every call (e.g. `(s) => ({ a: s.a })`).
630
+ */
631
+ const shallowEqual = (a, b) => {
632
+ if (Object.is(a, b)) return true;
633
+ if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
634
+ const keysA = Object.keys(a);
635
+ const keysB = Object.keys(b);
636
+ if (keysA.length !== keysB.length) return false;
637
+ for (const key of keysA) if (!Object.hasOwn(b, key) || !Object.is(a[key], b[key])) return false;
638
+ return true;
639
+ };
640
+ //#endregion
494
641
  //#region ../../src/react/core/index.ts
495
642
  /**
496
643
  * Full-stack React framework with server-side rendering.
@@ -518,6 +665,6 @@ function useStore(target, defaultValue) {
518
665
  */
519
666
  const AlephaReact = $module({ name: "alepha.react.core" });
520
667
  //#endregion
521
- export { AlephaContext, AlephaProvider, AlephaReact, ClientOnly, ErrorBoundary, useAction, useAlepha, useClient, useEvents, useInject, useQuery, useStore };
668
+ export { AlephaContext, AlephaProvider, AlephaReact, ClientOnly, ErrorBoundary, shallowEqual, useAction, useAlepha, useClient, useComputed, useEvents, useInject, useQuery, useSelector, useStore };
522
669
 
523
670
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/react/core/components/ClientOnly.tsx","../../../src/react/core/components/ErrorBoundary.tsx","../../../src/react/core/contexts/AlephaContext.ts","../../../src/react/core/contexts/AlephaProvider.tsx","../../../src/react/core/hooks/useAlepha.ts","../../../src/react/core/hooks/useInject.ts","../../../src/react/core/hooks/useAction.ts","../../../src/react/core/hooks/useClient.ts","../../../src/react/core/hooks/useEvents.ts","../../../src/react/core/hooks/useQuery.ts","../../../src/react/core/hooks/useStore.ts","../../../src/react/core/index.ts"],"sourcesContent":["import {\n type PropsWithChildren,\n type ReactNode,\n useEffect,\n useState,\n} from \"react\";\n\nexport interface ClientOnlyProps {\n fallback?: ReactNode;\n disabled?: boolean;\n}\n\n/**\n * A small utility component that renders its children only on the client side.\n *\n * Optionally, you can provide a fallback React node that will be rendered.\n *\n * You should use this component when\n * - you have code that relies on browser-specific APIs\n * - you want to avoid server-side rendering for a specific part of your application\n * - you want to prevent pre-rendering of a component\n *\n * @example\n * ```tsx\n * import { ClientOnly } from \"alepha/react\";\n *\n * const MyComponent = () => {\n * // Avoids SSR issues with Date API\n * return (\n * <ClientOnly>\n * {new Date().toLocaleTimeString()}\n * </ClientOnly>\n * );\n * }\n * ```\n */\nconst ClientOnly = (props: PropsWithChildren<ClientOnlyProps>) => {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => setMounted(true), []);\n\n if (props.disabled) {\n return props.children;\n }\n\n return mounted ? props.children : props.fallback;\n};\n\nexport default ClientOnly;\n","import React, {\n type ErrorInfo,\n type PropsWithChildren,\n type ReactNode,\n} from \"react\";\n\n/**\n * Props for the ErrorBoundary component.\n */\nexport interface ErrorBoundaryProps {\n /**\n * Fallback React node to render when an error is caught.\n * If not provided, a default error message will be shown.\n */\n fallback: (error: Error, reset: () => void) => ReactNode;\n\n /**\n * Optional callback that receives the error and error info.\n * Use this to log errors to a monitoring service.\n */\n onError?: (error: Error, info: ErrorInfo) => void;\n}\n\n/**\n * State of the ErrorBoundary component.\n */\ninterface ErrorBoundaryState {\n error?: Error;\n}\n\n/**\n * A reusable error boundary for catching rendering errors in any part of the React component tree.\n *\n * It's already included in the Alepha React framework when using page or layout components.\n */\nexport class ErrorBoundary extends React.Component<\n PropsWithChildren<ErrorBoundaryProps>,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = {};\n }\n\n /**\n * Update state so the next render shows the fallback UI.\n */\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return {\n error,\n };\n }\n\n /**\n * Lifecycle method called when an error is caught.\n * You can log the error or perform side effects here.\n */\n componentDidCatch(error: Error, info: ErrorInfo): void {\n if (this.props.onError) {\n this.props.onError(error, info);\n }\n }\n\n render(): ReactNode {\n if (this.state.error) {\n const reset = () => {\n this.setState({ error: undefined });\n };\n return this.props.fallback(this.state.error, reset);\n }\n\n return this.props.children;\n }\n}\n\nexport default ErrorBoundary;\n","import type { Alepha } from \"alepha\";\nimport { createContext } from \"react\";\n\n/**\n * React context to provide the Alepha instance throughout the component tree.\n */\nexport const AlephaContext = createContext<Alepha | undefined>(undefined);\n","import { Alepha } from \"alepha\";\nimport { type ReactNode, useEffect, useMemo, useState } from \"react\";\nimport { AlephaContext } from \"./AlephaContext.ts\";\n\nexport interface AlephaProviderProps {\n children: ReactNode;\n onError: (error: Error) => ReactNode;\n onLoading: () => ReactNode;\n}\n\n/**\n * AlephaProvider component to initialize and provide Alepha instance to the app.\n *\n * This isn't recommended for apps using `alepha/react/router`, as Router will handle this for you.\n */\nexport const AlephaProvider = (props: AlephaProviderProps) => {\n const alepha = useMemo(() => Alepha.create(), []);\n\n const [started, setStarted] = useState(false);\n const [error, setError] = useState<Error | undefined>();\n\n useEffect(() => {\n alepha\n .start()\n .then(() => setStarted(true))\n .catch((err) => setError(err));\n }, [alepha]);\n\n if (error) {\n return props.onError(error);\n }\n\n if (!started) {\n return props.onLoading();\n }\n\n return (\n <AlephaContext.Provider value={alepha}>\n {props.children}\n </AlephaContext.Provider>\n );\n};\n","import { type Alepha, AlephaError } from \"alepha\";\nimport { useContext } from \"react\";\nimport { AlephaContext } from \"../contexts/AlephaContext.ts\";\n\n/**\n * Main Alepha hook.\n *\n * It provides access to the Alepha instance within a React component.\n *\n * With Alepha, you can access the core functionalities of the framework:\n *\n * - alepha.state() for state management\n * - alepha.inject() for dependency injection\n * - alepha.events.emit() for event handling\n * etc...\n */\nexport const useAlepha = (): Alepha => {\n const alepha = useContext(AlephaContext);\n if (!alepha) {\n throw new AlephaError(\n \"Hook 'useAlepha()' must be used within an AlephaContext.Provider\",\n );\n }\n\n return alepha;\n};\n","import type { Service } from \"alepha\";\nimport { useMemo } from \"react\";\nimport { useAlepha } from \"./useAlepha.ts\";\n\n/**\n * Hook to inject a service instance.\n * It's a wrapper of `useAlepha().inject(service)` with a memoization.\n */\nexport const useInject = <T extends object>(service: Service<T>): T => {\n const alepha = useAlepha();\n return useMemo(() => alepha.inject(service), []);\n};\n","import type { Async } from \"alepha\";\nimport {\n DateTimeProvider,\n type DurationLike,\n type Interval,\n type Timeout,\n} from \"alepha/datetime\";\nimport {\n type DependencyList,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useAlepha } from \"./useAlepha.ts\";\nimport { useInject } from \"./useInject.ts\";\n\n/**\n * Hook for handling async actions with automatic error handling and event emission.\n *\n * By default, prevents concurrent executions - if an action is running and you call it again,\n * the second call will be ignored. Use `debounce` option to delay execution instead.\n *\n * Emits lifecycle events:\n * - `react:action:begin` - When action starts\n * - `react:action:success` - When action completes successfully\n * - `react:action:error` - When action throws an error\n * - `react:action:end` - Always emitted at the end\n *\n * @example Basic usage\n * ```tsx\n * const action = useAction({\n * handler: async (data) => {\n * await api.save(data);\n * }\n * }, []);\n *\n * <button onClick={() => action.run(data)} disabled={action.loading}>\n * Save\n * </button>\n * ```\n *\n * @example With debounce (search input)\n * ```tsx\n * const search = useAction({\n * handler: async (query: string) => {\n * await api.search(query);\n * },\n * debounce: 300 // Wait 300ms after last call\n * }, []);\n *\n * <input onChange={(e) => search.run(e.target.value)} />\n * ```\n *\n * @example Run on component mount\n * ```tsx\n * const fetchData = useAction({\n * handler: async () => {\n * const data = await api.getData();\n * return data;\n * },\n * runOnInit: true // Runs once when component mounts\n * }, []);\n * ```\n *\n * @example Run periodically (polling)\n * ```tsx\n * const pollStatus = useAction({\n * handler: async () => {\n * const status = await api.getStatus();\n * return status;\n * },\n * runEvery: 5000 // Run every 5 seconds\n * }, []);\n *\n * // Or with duration tuple\n * const pollStatus = useAction({\n * handler: async () => {\n * const status = await api.getStatus();\n * return status;\n * },\n * runEvery: [30, 'seconds'] // Run every 30 seconds\n * }, []);\n * ```\n *\n * @example With AbortController\n * ```tsx\n * const fetch = useAction({\n * handler: async (url, { signal }) => {\n * const response = await fetch(url, { signal });\n * return response.json();\n * }\n * }, []);\n * // Automatically cancelled on unmount or when new request starts\n * ```\n *\n * @example With error handling\n * ```tsx\n * const deleteAction = useAction({\n * handler: async (id: string) => {\n * await api.delete(id);\n * },\n * onError: (error) => {\n * if (error.code === 'NOT_FOUND') {\n * // Custom error handling\n * }\n * }\n * }, []);\n *\n * {deleteAction.error && <div>Error: {deleteAction.error.message}</div>}\n * ```\n *\n * @example Global error handling\n * ```tsx\n * // In your root app setup\n * alepha.events.on(\"react:action:error\", ({ error }) => {\n * toast.danger(error.message);\n * Sentry.captureException(error);\n * });\n * ```\n */\nexport function useAction<Args extends any[], Result = void>(\n options: UseActionOptions<Args, Result>,\n deps: DependencyList,\n): UseActionReturn<Args, Result> {\n const alepha = useAlepha();\n const dateTimeProvider = useInject(DateTimeProvider);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | undefined>();\n const [result, setResult] = useState<Result | undefined>();\n const isExecutingRef = useRef(false);\n const debounceTimerRef = useRef<Timeout | undefined>(undefined);\n const abortControllerRef = useRef<AbortController | undefined>(undefined);\n const isMountedRef = useRef(true);\n const intervalRef = useRef<Interval | undefined>(undefined);\n\n // Track mount state — must set true in body for React StrictMode double-invoke\n useEffect(() => {\n isMountedRef.current = true;\n\n return () => {\n isMountedRef.current = false;\n\n // clear debounce timer\n if (debounceTimerRef.current) {\n dateTimeProvider.clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = undefined;\n }\n\n // clear interval\n if (intervalRef.current) {\n dateTimeProvider.clearInterval(intervalRef.current);\n intervalRef.current = undefined;\n }\n\n // abort in-flight request\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = undefined;\n }\n\n // Release the concurrency guard: we've just abandoned the in-flight run\n // (its result is discarded by the aborted-signal check), so the *next*\n // lifecycle must be free to start. Without this, a remount that reuses\n // the same refs — React StrictMode's double-invoke, or a Suspense/router\n // remount on client-side navigation — would hit `if (isExecutingRef\n // .current) return` and never re-run, leaving a `useQuery` stuck on its\n // loading skeleton forever (the original request 200s but is dropped).\n isExecutingRef.current = false;\n };\n }, []);\n\n const executeAction = useCallback(\n async (...args: Args): Promise<Result | undefined> => {\n // Prevent concurrent executions\n if (isExecutingRef.current) {\n return;\n }\n\n // Abort previous request if still running\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n\n // Create new AbortController for this request\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n isExecutingRef.current = true;\n setLoading(true);\n setError(undefined);\n\n try {\n await alepha.events.emit(\"react:action:begin\", {\n type: \"custom\",\n id: options.id,\n });\n // Pass abort signal as last argument to handler\n const result = await options.handler(...args, {\n signal: abortController.signal,\n } as any);\n\n // Only update state if still mounted and not aborted\n if (!isMountedRef.current || abortController.signal.aborted) {\n return;\n }\n\n setResult(result as Result);\n\n await alepha.events.emit(\"react:action:success\", {\n type: \"custom\",\n id: options.id,\n });\n\n if (options.onSuccess) {\n await options.onSuccess(result);\n }\n\n return result;\n } catch (err) {\n // Ignore abort errors\n if (err instanceof Error && err.name === \"AbortError\") {\n return;\n }\n\n // Only update state if still mounted\n if (!isMountedRef.current) {\n return;\n }\n\n const error = err as Error;\n setError(error);\n\n await alepha.events.emit(\"react:action:error\", {\n type: \"custom\",\n id: options.id,\n error,\n });\n\n if (options.onError) {\n await options.onError(error);\n }\n // Without a custom `onError`, the error is NOT re-thrown: it is captured\n // in `error` state and emitted as `react:action:error` (a mounted\n // <ActionErrorToaster /> surfaces it as a toast). This keeps\n // fire-and-forget `action.run()` calls from producing unhandled\n // promise rejections.\n } finally {\n isExecutingRef.current = false;\n if (isMountedRef.current) {\n setLoading(false);\n }\n\n await alepha.events.emit(\"react:action:end\", {\n type: \"custom\",\n id: options.id,\n });\n\n // Clean up abort controller\n if (abortControllerRef.current === abortController) {\n abortControllerRef.current = undefined;\n }\n }\n },\n [...deps, options.id, options.onError, options.onSuccess],\n );\n\n const handler = useCallback(\n async (...args: Args): Promise<Result | undefined> => {\n if (options.debounce) {\n // clear existing timer\n if (debounceTimerRef.current) {\n dateTimeProvider.clearTimeout(debounceTimerRef.current);\n }\n\n // Set new timer\n return new Promise((resolve) => {\n debounceTimerRef.current = dateTimeProvider.createTimeout(\n async () => {\n const result = await executeAction(...args);\n resolve(result);\n },\n options.debounce ?? 0,\n );\n });\n }\n\n return executeAction(...args);\n },\n [executeAction, options.debounce],\n );\n\n const cancel = useCallback(() => {\n // clear debounce timer\n if (debounceTimerRef.current) {\n dateTimeProvider.clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = undefined;\n }\n\n // abort in-flight request\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = undefined;\n }\n\n // reset state\n if (isMountedRef.current) {\n isExecutingRef.current = false;\n setLoading(false);\n }\n }, []);\n\n // Run action on mount if runOnInit is true\n useEffect(() => {\n if (options.runOnInit) {\n handler(...([] as any));\n }\n }, deps);\n\n // Run action periodically if runEvery is specified\n useEffect(() => {\n if (!options.runEvery) {\n return;\n }\n\n // Set up interval\n intervalRef.current = dateTimeProvider.createInterval(\n () => handler(...([] as any)),\n options.runEvery,\n true,\n );\n\n // cleanup on unmount or when runEvery changes\n return () => {\n if (intervalRef.current) {\n dateTimeProvider.clearInterval(intervalRef.current);\n intervalRef.current = undefined;\n }\n };\n }, [handler, options.runEvery]);\n\n return {\n run: handler,\n loading,\n error,\n cancel,\n result,\n };\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Context object passed as the last argument to action handlers.\n * Contains an AbortSignal that can be used to cancel the request.\n */\nexport interface ActionContext {\n /**\n * AbortSignal that can be passed to fetch or other async operations.\n * The signal will be aborted when:\n * - The component unmounts\n * - A new action is triggered (cancels previous)\n * - The cancel() method is called\n *\n * @example\n * ```tsx\n * const action = useAction({\n * handler: async (url, { signal }) => {\n * const response = await fetch(url, { signal });\n * return response.json();\n * }\n * }, []);\n * ```\n */\n signal: AbortSignal;\n}\n\nexport interface UseActionOptions<Args extends any[] = any[], Result = any> {\n /**\n * The async action handler function.\n * Receives the action arguments plus an ActionContext as the last parameter.\n */\n handler: (...args: [...Args, ActionContext]) => Async<Result>;\n\n /**\n * Custom error handler. If provided, prevents default error re-throw.\n */\n onError?: (error: Error) => void | Promise<void>;\n\n /**\n * Custom success handler.\n */\n onSuccess?: (result: Result) => void | Promise<void>;\n\n /**\n * Optional identifier for this action (useful for debugging/analytics)\n */\n id?: string;\n\n name?: string;\n\n /**\n * Debounce delay in milliseconds. If specified, the action will only execute\n * after the specified delay has passed since the last call. Useful for search inputs\n * or other high-frequency events.\n *\n * @example\n * ```tsx\n * // Execute search 300ms after user stops typing\n * const search = useAction({ handler: search, debounce: 300 }, [])\n * ```\n */\n debounce?: number;\n\n /**\n * If true, the action will be executed once when the component mounts.\n *\n * @example\n * ```tsx\n * const fetchData = useAction({\n * handler: async () => await api.getData(),\n * runOnInit: true\n * }, []);\n * ```\n */\n runOnInit?: boolean;\n\n /**\n * If specified, the action will be executed periodically at the given interval.\n * The interval is specified as a DurationLike value (number in ms, Duration object, or [number, unit] tuple).\n *\n * @example\n * ```tsx\n * // Run every 5 seconds\n * const poll = useAction({\n * handler: async () => await api.poll(),\n * runEvery: 5000\n * }, []);\n * ```\n *\n * @example\n * ```tsx\n * // Run every 1 minute\n * const poll = useAction({\n * handler: async () => await api.poll(),\n * runEvery: [1, 'minute']\n * }, []);\n * ```\n */\n runEvery?: DurationLike;\n}\n\nexport interface UseActionReturn<Args extends any[], Result> {\n /**\n * Execute the action with the provided arguments.\n *\n * @example\n * ```tsx\n * const action = useAction({ handler: async (data) => { ... } }, []);\n * action.run(data);\n * ```\n */\n run: (...args: Args) => Promise<Result | undefined>;\n\n /**\n * Loading state - true when action is executing.\n */\n loading: boolean;\n\n /**\n * Error state - contains error if action failed, undefined otherwise.\n */\n error?: Error;\n\n /**\n * Cancel any pending debounced action or abort the current in-flight request.\n *\n * @example\n * ```tsx\n * const action = useAction({ ... }, []);\n *\n * <button onClick={action.cancel} disabled={!action.loading}>\n * Cancel\n * </button>\n * ```\n */\n cancel: () => void;\n\n /**\n * The result data from the last successful action execution.\n */\n result?: Result;\n}\n","import {\n type ClientScope,\n type HttpVirtualClient,\n LinkProvider,\n} from \"alepha/server/links\";\nimport { useMemo } from \"react\";\nimport { useInject } from \"./useInject.ts\";\n\n/**\n * Hook to get a virtual client for the specified scope.\n *\n * It's the React-hook version of `$client()`, from `AlephaServerLinks` module.\n */\nexport const useClient = <T extends object>(\n scope?: ClientScope,\n): HttpVirtualClient<T> => {\n const linkProvider = useInject(LinkProvider);\n\n return useMemo(() => {\n return linkProvider.client<T>(scope);\n }, [scope]);\n};\n","import type { Async, Hook, Hooks } from \"alepha\";\nimport { type DependencyList, useEffect } from \"react\";\nimport { useAlepha } from \"./useAlepha.ts\";\n\n/**\n * Allow subscribing to multiple Alepha events. See {@link Hooks} for available events.\n *\n * useEvents is fully typed to ensure correct event callback signatures.\n *\n * @example\n * ```tsx\n * useEvents(\n * {\n * \"react:transition:begin\": (ev) => {\n * console.log(\"Transition began to:\", ev.to);\n * },\n * \"react:transition:error\": {\n * priority: \"first\",\n * callback: (ev) => {\n * console.error(\"Transition error:\", ev.error);\n * },\n * },\n * },\n * [],\n * );\n * ```\n */\nexport const useEvents = (opts: UseEvents, deps: DependencyList) => {\n const alepha = useAlepha();\n\n useEffect(() => {\n if (!alepha.isBrowser()) {\n return;\n }\n\n const subs: Function[] = [];\n for (const [name, hook] of Object.entries(opts)) {\n subs.push(alepha.events.on(name as any, hook as any));\n }\n\n return () => {\n for (const clear of subs) {\n clear();\n }\n };\n }, deps);\n};\n\ntype UseEvents = {\n [T in keyof Hooks]?: Hook<T> | ((payload: Hooks[T]) => Async<void>);\n};\n","import type { Async } from \"alepha\";\nimport type { DurationLike } from \"alepha/datetime\";\nimport { type DependencyList, useCallback, useRef, useState } from \"react\";\nimport type { ActionContext } from \"./useAction.ts\";\nimport { useAction } from \"./useAction.ts\";\n\n/**\n * Hook for declarative data fetching with automatic execution and refetch.\n *\n * Thin wrapper over {@link useAction}: it pre-applies `runOnInit: true`,\n * exposes the last result as `data`, and provides a stable `refetch()` to\n * re-run the query on demand. For optimistic mutations and side-effects,\n * use {@link useAction} directly — `useQuery` is for the read path.\n *\n * Caching, request deduplication, and AbortSignal cancellation come from\n * `useAction` + `HttpClient`. There is no separate cache layer — pass\n * `localCache` to your `HttpClient.fetch()`/`fetchAction()` call inside\n * the query handler if you want per-call caching.\n *\n * @example Basic\n * ```tsx\n * const client = useInject(HttpClient);\n * const { data, loading, error, refetch } = useQuery({\n * handler: async ({ signal }) => {\n * const res = await client.fetch(\"/api/users\", { request: { signal } });\n * return res.data;\n * },\n * }, []);\n * ```\n *\n * @example Re-fetch when a dep changes\n * ```tsx\n * const { data } = useQuery({\n * handler: async () => api.getUser(userId),\n * }, [userId]);\n * ```\n *\n * @example Polling\n * ```tsx\n * const { data } = useQuery({\n * handler: async () => api.getStatus(),\n * runEvery: [5, \"seconds\"],\n * }, []);\n * ```\n */\nexport function useQuery<Result>(\n options: UseQueryOptions<Result>,\n deps: DependencyList,\n): UseQueryReturn<Result> {\n const enabled = options.enabled !== false;\n const [data, setData] = useState<Result | undefined>(options.initialData);\n // Tracks whether the auto-run has completed at least once, so we can keep\n // `loading` true on the very first render — before `runOnInit`'s effect\n // fires — instead of briefly reporting `loading: false` with no data.\n const settledRef = useRef(false);\n\n const action = useAction<[], Result>(\n {\n id: options.id,\n handler: options.handler,\n runOnInit: enabled,\n runEvery: options.runEvery,\n debounce: options.debounce,\n onError: options.onError,\n onSuccess: async (result) => {\n settledRef.current = true;\n setData(result);\n if (options.onSuccess) {\n await options.onSuccess(result);\n }\n },\n },\n deps,\n );\n\n const refetch = useCallback(() => action.run(), [action.run]);\n\n // `loading` is true while a fetch is in flight, AND during the initial gap\n // between first render and the auto-run effect — so consumers can render a\n // skeleton immediately instead of flashing an empty/not-found state. Only\n // applies to enabled queries with no `initialData` seed; an error settles\n // it (the error path keeps the caller's `onError` re-throw semantics).\n const loading =\n action.loading ||\n (enabled &&\n options.initialData === undefined &&\n !settledRef.current &&\n action.error === undefined);\n\n return {\n data,\n loading,\n error: action.error,\n refetch,\n cancel: action.cancel,\n };\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface UseQueryOptions<Result> {\n /**\n * Async query handler. Receives an {@link ActionContext} with an\n * AbortSignal that fires on unmount, dependency change, or `cancel()`.\n */\n handler: (context: ActionContext) => Async<Result>;\n\n /**\n * Optional identifier (used in lifecycle events for debugging/analytics).\n */\n id?: string;\n\n /**\n * If `false`, skip automatic execution on mount and dep change. Use\n * `refetch()` to trigger manually. Defaults to `true`.\n */\n enabled?: boolean;\n\n /**\n * Initial value for `data` before the first successful fetch.\n */\n initialData?: Result;\n\n /**\n * Re-run periodically. See {@link useAction} `runEvery`.\n */\n runEvery?: DurationLike;\n\n /**\n * Debounce delay in milliseconds. See {@link useAction} `debounce`.\n */\n debounce?: number;\n\n /**\n * Called on success with the resolved value.\n */\n onSuccess?: (result: Result) => void | Promise<void>;\n\n /**\n * Custom error handler. If provided, prevents default error re-throw.\n */\n onError?: (error: Error) => void | Promise<void>;\n}\n\nexport interface UseQueryReturn<Result> {\n /**\n * The last successful result. `undefined` until the first fetch resolves\n * (or the value of `initialData` if provided).\n */\n data: Result | undefined;\n\n /**\n * Loading state — `true` while a fetch is in flight, and also from the\n * first render until the initial auto-run settles (for enabled queries\n * with no `initialData`), so a skeleton can render without a flash.\n */\n loading: boolean;\n\n /**\n * Error from the last failed fetch, if any.\n */\n error?: Error;\n\n /**\n * Re-run the query. The previous in-flight request, if any, is aborted.\n */\n refetch: () => Promise<Result | undefined>;\n\n /**\n * Abort the in-flight request without scheduling another.\n */\n cancel: () => void;\n}\n","import type { State, Static, TAtomObject } from \"alepha\";\nimport { Atom } from \"alepha\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useAlepha } from \"./useAlepha.ts\";\n\n/**\n * Hook to access and mutate the Alepha state.\n */\nfunction useStore<T extends TAtomObject>(\n target: Atom<T>,\n defaultValue?: Static<T>,\n): UseStoreReturn<Static<T>>;\nfunction useStore<Key extends keyof State>(\n target: Key,\n defaultValue?: State[Key],\n): UseStoreReturn<State[Key]>;\nfunction useStore(target: any, defaultValue?: any): any {\n const alepha = useAlepha();\n\n useMemo(() => {\n if (defaultValue != null && alepha.store.get(target) == null) {\n alepha.store.set(target, defaultValue);\n }\n }, [defaultValue]);\n\n const [state, setState] = useState(alepha.store.get(target));\n\n useEffect(() => {\n if (!alepha.isBrowser()) {\n return;\n }\n\n const key = target instanceof Atom ? target.key : target;\n\n return alepha.events.on(\"state:mutate\", (ev) => {\n if (ev.key === key) {\n setState(ev.value);\n }\n });\n }, []);\n\n return [\n state,\n (value: any) => {\n alepha.store.set(target, value);\n },\n ] as const;\n}\n\nexport type UseStoreReturn<T> = [T, (value: T) => void];\n\nexport { useStore };\n","import { $module } from \"alepha\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type * from \"./components/ClientOnly.tsx\";\nexport { default as ClientOnly } from \"./components/ClientOnly.tsx\";\nexport type * from \"./components/ErrorBoundary.tsx\";\nexport { default as ErrorBoundary } from \"./components/ErrorBoundary.tsx\";\nexport * from \"./contexts/AlephaContext.ts\";\nexport * from \"./contexts/AlephaProvider.tsx\";\nexport * from \"./hooks/useAction.ts\";\nexport * from \"./hooks/useAlepha.ts\";\nexport * from \"./hooks/useClient.ts\";\nexport * from \"./hooks/useEvents.ts\";\nexport * from \"./hooks/useInject.ts\";\nexport * from \"./hooks/useQuery.ts\";\nexport * from \"./hooks/useStore.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n interface Hooks {\n /**\n * Fires when a user action is starting.\n * Action can be a form submission, a route transition, or a custom action.\n */\n \"react:action:begin\": {\n type: string;\n id?: string;\n };\n /**\n * Fires when a user action has succeeded.\n * Action can be a form submission, a route transition, or a custom action.\n */\n \"react:action:success\": {\n type: string;\n id?: string;\n };\n /**\n * Fires when a user action has failed.\n * Action can be a form submission, a route transition, or a custom action.\n */\n \"react:action:error\": {\n type: string;\n id?: string;\n error: Error;\n };\n /**\n * Fires when a user action has completed, regardless of success or failure.\n * Action can be a form submission, a route transition, or a custom action.\n */\n \"react:action:end\": {\n type: string;\n id?: string;\n };\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Full-stack React framework with server-side rendering.\n *\n * **Features:**\n * - React page routes with type-safe params\n * - Async action handler with loading/error/cancel states\n * - Type-safe HTTP client access\n * - Dependency injection in components\n * - Global state management\n * - Router navigation methods\n * - Current route state access\n * - Check if path is active\n * - URL query parameters\n * - Access route schema\n * - Subscribe to Alepha events\n * - Type-safe form handling with validation\n * - Error handling wrapper component\n * - Client-side only rendering component\n * - Server-side rendering with hydration\n * - Automatic code splitting\n * - Event system for action tracking\n *\n * @module alepha.react\n */\nexport const AlephaReact = $module({\n name: \"alepha.react.core\",\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/react/core/components/ClientOnly.tsx","../../../src/react/core/components/ErrorBoundary.tsx","../../../src/react/core/contexts/AlephaContext.ts","../../../src/react/core/contexts/AlephaProvider.tsx","../../../src/react/core/hooks/useAlepha.ts","../../../src/react/core/hooks/useInject.ts","../../../src/react/core/hooks/useAction.ts","../../../src/react/core/hooks/useClient.ts","../../../src/react/core/hooks/useComputed.ts","../../../src/react/core/hooks/useEvents.ts","../../../src/react/core/hooks/useQuery.ts","../../../src/react/core/hooks/useSelector.ts","../../../src/react/core/hooks/useStore.ts","../../../src/react/core/utils/shallowEqual.ts","../../../src/react/core/index.ts"],"sourcesContent":["import {\n type PropsWithChildren,\n type ReactNode,\n useEffect,\n useState,\n} from \"react\";\n\nexport interface ClientOnlyProps {\n fallback?: ReactNode;\n disabled?: boolean;\n}\n\n/**\n * A small utility component that renders its children only on the client side.\n *\n * Optionally, you can provide a fallback React node that will be rendered.\n *\n * You should use this component when\n * - you have code that relies on browser-specific APIs\n * - you want to avoid server-side rendering for a specific part of your application\n * - you want to prevent pre-rendering of a component\n *\n * @example\n * ```tsx\n * import { ClientOnly } from \"alepha/react\";\n *\n * const MyComponent = () => {\n * // Avoids SSR issues with Date API\n * return (\n * <ClientOnly>\n * {new Date().toLocaleTimeString()}\n * </ClientOnly>\n * );\n * }\n * ```\n */\nconst ClientOnly = (props: PropsWithChildren<ClientOnlyProps>) => {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => setMounted(true), []);\n\n if (props.disabled) {\n return props.children;\n }\n\n return mounted ? props.children : props.fallback;\n};\n\nexport default ClientOnly;\n","import React, {\n type ErrorInfo,\n type PropsWithChildren,\n type ReactNode,\n} from \"react\";\n\n/**\n * Props for the ErrorBoundary component.\n */\nexport interface ErrorBoundaryProps {\n /**\n * Fallback React node to render when an error is caught.\n * If not provided, a default error message will be shown.\n */\n fallback: (error: Error, reset: () => void) => ReactNode;\n\n /**\n * Optional callback that receives the error and error info.\n * Use this to log errors to a monitoring service.\n */\n onError?: (error: Error, info: ErrorInfo) => void;\n\n /**\n * Clear a caught error whenever any of these values changes (compared with\n * `Object.is`, positionally).\n *\n * A boundary that catches has to be told when the reason to fail is gone —\n * otherwise the fallback latches and every later render keeps showing the\n * stale error. The router passes the current path, so navigating away from a\n * page that threw recovers on its own.\n *\n * Unlike remounting via `key`, this clears the error WITHOUT tearing down the\n * children, so unrelated component state survives an ordinary navigation.\n */\n resetKeys?: readonly unknown[];\n}\n\n/**\n * State of the ErrorBoundary component.\n */\ninterface ErrorBoundaryState {\n error?: Error;\n}\n\n/**\n * A reusable error boundary for catching rendering errors in any part of the React component tree.\n *\n * It's already included in the Alepha React framework when using page or layout components.\n */\nexport class ErrorBoundary extends React.Component<\n PropsWithChildren<ErrorBoundaryProps>,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = {};\n }\n\n /**\n * Update state so the next render shows the fallback UI.\n */\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return {\n error,\n };\n }\n\n /**\n * Lifecycle method called when an error is caught.\n * You can log the error or perform side effects here.\n */\n componentDidCatch(error: Error, info: ErrorInfo): void {\n if (this.props.onError) {\n this.props.onError(error, info);\n }\n }\n\n /**\n * Recover once the caller signals the failing input is gone.\n */\n componentDidUpdate(prevProps: PropsWithChildren<ErrorBoundaryProps>): void {\n if (!this.state.error) {\n return;\n }\n\n if (this.hasResetKeyChanged(prevProps.resetKeys, this.props.resetKeys)) {\n this.setState({ error: undefined });\n }\n }\n\n protected hasResetKeyChanged(\n previous: readonly unknown[] | undefined,\n next: readonly unknown[] | undefined,\n ): boolean {\n if (previous === next) {\n return false;\n }\n\n if (!previous || !next || previous.length !== next.length) {\n return true;\n }\n\n return previous.some((value, i) => !Object.is(value, next[i]));\n }\n\n render(): ReactNode {\n if (this.state.error) {\n const reset = () => {\n this.setState({ error: undefined });\n };\n return this.props.fallback(this.state.error, reset);\n }\n\n return this.props.children;\n }\n}\n\nexport default ErrorBoundary;\n","import type { Alepha } from \"alepha\";\nimport { createContext } from \"react\";\n\n/**\n * React context to provide the Alepha instance throughout the component tree.\n */\nexport const AlephaContext = createContext<Alepha | undefined>(undefined);\n","import { Alepha } from \"alepha\";\nimport { type ReactNode, useEffect, useMemo, useState } from \"react\";\nimport { AlephaContext } from \"./AlephaContext.ts\";\n\nexport interface AlephaProviderProps {\n children: ReactNode;\n onError: (error: Error) => ReactNode;\n onLoading: () => ReactNode;\n}\n\n/**\n * AlephaProvider component to initialize and provide Alepha instance to the app.\n *\n * This isn't recommended for apps using `alepha/react/router`, as Router will handle this for you.\n */\nexport const AlephaProvider = (props: AlephaProviderProps) => {\n const alepha = useMemo(() => Alepha.create(), []);\n\n const [started, setStarted] = useState(false);\n const [error, setError] = useState<Error | undefined>();\n\n useEffect(() => {\n alepha\n .start()\n .then(() => setStarted(true))\n .catch((err) => setError(err));\n }, [alepha]);\n\n if (error) {\n return props.onError(error);\n }\n\n if (!started) {\n return props.onLoading();\n }\n\n return (\n <AlephaContext.Provider value={alepha}>\n {props.children}\n </AlephaContext.Provider>\n );\n};\n","import { type Alepha, AlephaError } from \"alepha\";\nimport { useContext } from \"react\";\nimport { AlephaContext } from \"../contexts/AlephaContext.ts\";\n\n/**\n * Main Alepha hook.\n *\n * It provides access to the Alepha instance within a React component.\n *\n * With Alepha, you can access the core functionalities of the framework:\n *\n * - alepha.state() for state management\n * - alepha.inject() for dependency injection\n * - alepha.events.emit() for event handling\n * etc...\n */\nexport const useAlepha = (): Alepha => {\n const alepha = useContext(AlephaContext);\n if (!alepha) {\n throw new AlephaError(\n \"Hook 'useAlepha()' must be used within an AlephaContext.Provider\",\n );\n }\n\n return alepha;\n};\n","import type { Service } from \"alepha\";\nimport { useMemo } from \"react\";\nimport { useAlepha } from \"./useAlepha.ts\";\n\n/**\n * Hook to inject a service instance.\n * It's a wrapper of `useAlepha().inject(service)` with a memoization.\n */\nexport const useInject = <T extends object>(service: Service<T>): T => {\n const alepha = useAlepha();\n return useMemo(() => alepha.inject(service), []);\n};\n","import type { Async } from \"alepha\";\nimport {\n DateTimeProvider,\n type DurationLike,\n type Interval,\n type Timeout,\n} from \"alepha/datetime\";\nimport {\n type DependencyList,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useAlepha } from \"./useAlepha.ts\";\nimport { useInject } from \"./useInject.ts\";\n\n/**\n * Hook for handling async actions with automatic error handling and event emission.\n *\n * By default, prevents concurrent executions - if an action is running and you call it again,\n * the second call will be ignored. Use `debounce` option to delay execution instead.\n *\n * Emits lifecycle events:\n * - `react:action:begin` - When action starts\n * - `react:action:success` - When action completes successfully\n * - `react:action:error` - When action throws an error\n * - `react:action:end` - Always emitted at the end\n *\n * @example Basic usage\n * ```tsx\n * const action = useAction({\n * handler: async (data) => {\n * await api.save(data);\n * }\n * }, []);\n *\n * <button onClick={() => action.run(data)} disabled={action.loading}>\n * Save\n * </button>\n * ```\n *\n * @example With debounce (search input)\n * ```tsx\n * const search = useAction({\n * handler: async (query: string) => {\n * await api.search(query);\n * },\n * debounce: 300 // Wait 300ms after last call\n * }, []);\n *\n * <input onChange={(e) => search.run(e.target.value)} />\n * ```\n *\n * @example Run on component mount\n * ```tsx\n * const fetchData = useAction({\n * handler: async () => {\n * const data = await api.getData();\n * return data;\n * },\n * runOnInit: true // Runs once when component mounts\n * }, []);\n * ```\n *\n * @example Run periodically (polling)\n * ```tsx\n * const pollStatus = useAction({\n * handler: async () => {\n * const status = await api.getStatus();\n * return status;\n * },\n * runEvery: 5000 // Run every 5 seconds\n * }, []);\n *\n * // Or with duration tuple\n * const pollStatus = useAction({\n * handler: async () => {\n * const status = await api.getStatus();\n * return status;\n * },\n * runEvery: [30, 'seconds'] // Run every 30 seconds\n * }, []);\n * ```\n *\n * @example With AbortController\n * ```tsx\n * const fetch = useAction({\n * handler: async (url, { signal }) => {\n * const response = await fetch(url, { signal });\n * return response.json();\n * }\n * }, []);\n * // Automatically cancelled on unmount or when new request starts\n * ```\n *\n * @example With error handling\n * ```tsx\n * const deleteAction = useAction({\n * handler: async (id: string) => {\n * await api.delete(id);\n * },\n * onError: (error) => {\n * if (error.code === 'NOT_FOUND') {\n * // Custom error handling\n * }\n * }\n * }, []);\n *\n * {deleteAction.error && <div>Error: {deleteAction.error.message}</div>}\n * ```\n *\n * @example Global error handling\n * ```tsx\n * // In your root app setup\n * alepha.events.on(\"react:action:error\", ({ error }) => {\n * toast.danger(error.message);\n * Sentry.captureException(error);\n * });\n * ```\n */\nexport function useAction<Args extends any[], Result = void>(\n options: UseActionOptions<Args, Result>,\n deps: DependencyList,\n): UseActionReturn<Args, Result> {\n const alepha = useAlepha();\n const dateTimeProvider = useInject(DateTimeProvider);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | undefined>();\n const [result, setResult] = useState<Result | undefined>();\n const isExecutingRef = useRef(false);\n const debounceTimerRef = useRef<Timeout | undefined>(undefined);\n const abortControllerRef = useRef<AbortController | undefined>(undefined);\n const isMountedRef = useRef(true);\n const intervalRef = useRef<Interval | undefined>(undefined);\n // Monotonic id of the latest run. A superseded run keeps executing until its\n // abort lands, so every state write is gated on \"am I still the latest?\" —\n // otherwise the stale run's `finally` would clear the newer run's `loading`.\n const runIdRef = useRef(0);\n\n // Track mount state — must set true in body for React StrictMode double-invoke\n useEffect(() => {\n isMountedRef.current = true;\n\n return () => {\n isMountedRef.current = false;\n\n // clear debounce timer\n if (debounceTimerRef.current) {\n dateTimeProvider.clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = undefined;\n }\n\n // clear interval\n if (intervalRef.current) {\n dateTimeProvider.clearInterval(intervalRef.current);\n intervalRef.current = undefined;\n }\n\n // abort in-flight request\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = undefined;\n }\n\n // Release the concurrency guard: we've just abandoned the in-flight run\n // (its result is discarded by the aborted-signal check), so the *next*\n // lifecycle must be free to start. Without this, a remount that reuses\n // the same refs — React StrictMode's double-invoke, or a Suspense/router\n // remount on client-side navigation — would hit `if (isExecutingRef\n // .current) return` and never re-run, leaving a `useQuery` stuck on its\n // loading skeleton forever (the original request 200s but is dropped).\n isExecutingRef.current = false;\n };\n }, []);\n\n const executeAction = useCallback(\n async (\n args: Args,\n { supersede = false }: { supersede?: boolean } = {},\n ): Promise<Result | undefined> => {\n if (isExecutingRef.current && !supersede) {\n // A manual `run()` must not fire twice — this is what stops a\n // double-clicked mutation from being submitted twice.\n return;\n }\n\n // A dep-change or interval run supersedes: the in-flight request was\n // issued for inputs that are now stale, so its result must never win.\n // (This is why the guard above is skipped rather than short-circuiting —\n // otherwise `useQuery([userId])` whose `userId` changes mid-flight would\n // never refetch, and the old user's data would stay on screen.)\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n\n // Create new AbortController for this request\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n\n const runId = ++runIdRef.current;\n const isLatestRun = () => runIdRef.current === runId;\n\n isExecutingRef.current = true;\n setLoading(true);\n setError(undefined);\n\n try {\n await alepha.events.emit(\"react:action:begin\", {\n type: \"custom\",\n id: options.id,\n });\n // Pass abort signal as last argument to handler\n const result = await options.handler(...args, {\n signal: abortController.signal,\n } as any);\n\n // Only update state if still mounted, not aborted, and not superseded\n if (\n !isMountedRef.current ||\n abortController.signal.aborted ||\n !isLatestRun()\n ) {\n return;\n }\n\n setResult(result as Result);\n\n await alepha.events.emit(\"react:action:success\", {\n type: \"custom\",\n id: options.id,\n });\n\n if (options.onSuccess) {\n await options.onSuccess(result);\n }\n\n return result;\n } catch (err) {\n // Ignore abort errors\n if (err instanceof Error && err.name === \"AbortError\") {\n return;\n }\n\n // Only update state if still mounted and not superseded\n if (!isMountedRef.current || !isLatestRun()) {\n return;\n }\n\n const error = err as Error;\n setError(error);\n\n await alepha.events.emit(\"react:action:error\", {\n type: \"custom\",\n id: options.id,\n error,\n });\n\n if (options.onError) {\n await options.onError(error);\n }\n // Without a custom `onError`, the error is NOT re-thrown: it is captured\n // in `error` state and emitted as `react:action:error` (a mounted\n // <ActionErrorToaster /> surfaces it as a toast). This keeps\n // fire-and-forget `action.run()` calls from producing unhandled\n // promise rejections.\n } finally {\n // A superseded run must not release the guard or drop `loading` — the\n // run that replaced it is still in flight.\n if (isLatestRun()) {\n isExecutingRef.current = false;\n if (isMountedRef.current) {\n setLoading(false);\n }\n }\n\n await alepha.events.emit(\"react:action:end\", {\n type: \"custom\",\n id: options.id,\n });\n\n // Clean up abort controller\n if (abortControllerRef.current === abortController) {\n abortControllerRef.current = undefined;\n }\n }\n },\n [...deps, options.id, options.onError, options.onSuccess],\n );\n\n const runAction = useCallback(\n async (\n args: Args,\n options_: { supersede?: boolean } = {},\n ): Promise<Result | undefined> => {\n if (options.debounce) {\n // clear existing timer\n if (debounceTimerRef.current) {\n dateTimeProvider.clearTimeout(debounceTimerRef.current);\n }\n\n // Set new timer\n return new Promise((resolve) => {\n debounceTimerRef.current = dateTimeProvider.createTimeout(\n async () => {\n const result = await executeAction(args, options_);\n resolve(result);\n },\n options.debounce ?? 0,\n );\n });\n }\n\n return executeAction(args, options_);\n },\n [executeAction, options.debounce],\n );\n\n /**\n * Public `run()` — a user-initiated call. Deduped while one is in flight so a\n * double-clicked mutation submits once.\n */\n const handler = useCallback(\n (...args: Args): Promise<Result | undefined> => runAction(args),\n [runAction],\n );\n\n const cancel = useCallback(() => {\n // clear debounce timer\n if (debounceTimerRef.current) {\n dateTimeProvider.clearTimeout(debounceTimerRef.current);\n debounceTimerRef.current = undefined;\n }\n\n // abort in-flight request\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = undefined;\n }\n\n // reset state\n if (isMountedRef.current) {\n isExecutingRef.current = false;\n setLoading(false);\n }\n }, []);\n\n // Run action on mount, and again whenever `deps` change. These runs supersede\n // an in-flight request: it was issued for the previous deps, so its result is\n // already stale.\n useEffect(() => {\n if (options.runOnInit) {\n runAction([] as any, { supersede: true });\n }\n }, deps);\n\n // Run action periodically if runEvery is specified\n useEffect(() => {\n if (!options.runEvery) {\n return;\n }\n\n // Set up interval\n intervalRef.current = dateTimeProvider.createInterval(\n () => runAction([] as any, { supersede: true }),\n options.runEvery,\n true,\n );\n\n // cleanup on unmount or when runEvery changes\n return () => {\n if (intervalRef.current) {\n dateTimeProvider.clearInterval(intervalRef.current);\n intervalRef.current = undefined;\n }\n };\n }, [runAction, options.runEvery]);\n\n return {\n run: handler,\n loading,\n error,\n cancel,\n result,\n };\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Context object passed as the last argument to action handlers.\n * Contains an AbortSignal that can be used to cancel the request.\n */\nexport interface ActionContext {\n /**\n * AbortSignal that can be passed to fetch or other async operations.\n * The signal will be aborted when:\n * - The component unmounts\n * - A new action is triggered (cancels previous)\n * - The cancel() method is called\n *\n * @example\n * ```tsx\n * const action = useAction({\n * handler: async (url, { signal }) => {\n * const response = await fetch(url, { signal });\n * return response.json();\n * }\n * }, []);\n * ```\n */\n signal: AbortSignal;\n}\n\nexport interface UseActionOptions<Args extends any[] = any[], Result = any> {\n /**\n * The async action handler function.\n * Receives the action arguments plus an ActionContext as the last parameter.\n */\n handler: (...args: [...Args, ActionContext]) => Async<Result>;\n\n /**\n * Custom error handler. If provided, prevents default error re-throw.\n */\n onError?: (error: Error) => void | Promise<void>;\n\n /**\n * Custom success handler.\n */\n onSuccess?: (result: Result) => void | Promise<void>;\n\n /**\n * Optional identifier for this action (useful for debugging/analytics)\n */\n id?: string;\n\n name?: string;\n\n /**\n * Debounce delay in milliseconds. If specified, the action will only execute\n * after the specified delay has passed since the last call. Useful for search inputs\n * or other high-frequency events.\n *\n * @example\n * ```tsx\n * // Execute search 300ms after user stops typing\n * const search = useAction({ handler: search, debounce: 300 }, [])\n * ```\n */\n debounce?: number;\n\n /**\n * If true, the action will be executed once when the component mounts.\n *\n * @example\n * ```tsx\n * const fetchData = useAction({\n * handler: async () => await api.getData(),\n * runOnInit: true\n * }, []);\n * ```\n */\n runOnInit?: boolean;\n\n /**\n * If specified, the action will be executed periodically at the given interval.\n * The interval is specified as a DurationLike value (number in ms, Duration object, or [number, unit] tuple).\n *\n * @example\n * ```tsx\n * // Run every 5 seconds\n * const poll = useAction({\n * handler: async () => await api.poll(),\n * runEvery: 5000\n * }, []);\n * ```\n *\n * @example\n * ```tsx\n * // Run every 1 minute\n * const poll = useAction({\n * handler: async () => await api.poll(),\n * runEvery: [1, 'minute']\n * }, []);\n * ```\n */\n runEvery?: DurationLike;\n}\n\nexport interface UseActionReturn<Args extends any[], Result> {\n /**\n * Execute the action with the provided arguments.\n *\n * @example\n * ```tsx\n * const action = useAction({ handler: async (data) => { ... } }, []);\n * action.run(data);\n * ```\n */\n run: (...args: Args) => Promise<Result | undefined>;\n\n /**\n * Loading state - true when action is executing.\n */\n loading: boolean;\n\n /**\n * Error state - contains error if action failed, undefined otherwise.\n */\n error?: Error;\n\n /**\n * Cancel any pending debounced action or abort the current in-flight request.\n *\n * @example\n * ```tsx\n * const action = useAction({ ... }, []);\n *\n * <button onClick={action.cancel} disabled={!action.loading}>\n * Cancel\n * </button>\n * ```\n */\n cancel: () => void;\n\n /**\n * The result data from the last successful action execution.\n */\n result?: Result;\n}\n","import {\n type ClientScope,\n type HttpVirtualClient,\n LinkProvider,\n} from \"alepha/server/links\";\nimport { useMemo } from \"react\";\nimport { useInject } from \"./useInject.ts\";\n\n/**\n * Hook to get a virtual client for the specified scope.\n *\n * It's the React-hook version of `$client()`, from `AlephaServerLinks` module.\n */\nexport const useClient = <T extends object>(\n scope?: ClientScope,\n): HttpVirtualClient<T> => {\n const linkProvider = useInject(LinkProvider);\n\n return useMemo(() => {\n return linkProvider.client<T>(scope);\n }, [scope]);\n};\n","import type { Computed } from \"alepha\";\nimport { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport { useAlepha } from \"./useAlepha.ts\";\n\n/**\n * Subscribes to a `$computed` value.\n *\n * `getSnapshot` always reads the dependency atoms **live** off the store —\n * never through a subscription-set dirty flag. A dirty flag is only ever\n * flipped by the `state:mutate` listener registered in `subscribe`, which\n * React wires up in a passive effect (after commit); `EventManager.emit` is\n * async on top of that. A mutation dispatched between the initial render and\n * that effect committing would be invisible to the flag, so `getSnapshot`\n * (including React's own post-subscribe consistency re-check) would keep\n * returning the stale pre-mutation value. See `useStore.ts` and\n * `useSelector.ts` for the same rationale.\n *\n * Referential stability for `useSyncExternalStore` comes from comparing the\n * *inputs* (the resolved values of the computed's transitive atom\n * dependencies) by identity, not from caching on a mount-time ref: when none\n * of the inputs changed since the last snapshot, the previous output\n * reference is returned as-is; when any input changed (or `target` itself\n * was swapped for a different `Computed`), the value is recomputed and a new\n * reference is cached.\n *\n * A `Computed` passed here should be declared at module scope, like an\n * atom — constructing one inline in a component body creates a new\n * instance every render, which (because `subscribe`/`getSnapshot` are keyed\n * on `target.key`, matching `useStore`/`useSelector`) is tolerated for\n * resubscription purposes, but any closures captured by that instance's\n * `get()` will be locked to whichever render first created the subscription\n * until `target.key` itself changes.\n *\n * ```tsx\n * const total = useComputed(cartTotal);\n * ```\n */\nfunction useComputed<R>(target: Computed<R>): R {\n const alepha = useAlepha();\n const key = target.key;\n\n // A ref, not state: the cached snapshot must survive re-renders without\n // scheduling them. It exists purely to give `useSyncExternalStore` a\n // stable reference when the resolved dependency values haven't changed —\n // it is never the source of truth for staleness (see rationale above).\n const cache = useRef<{\n target: Computed<R>;\n inputs: unknown[];\n value: R;\n } | null>(null);\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n if (!alepha.isBrowser()) {\n return () => {};\n }\n\n const keys = new Set(target.keys());\n return alepha.events.on(\"state:mutate\", (ev) => {\n if (keys.has(ev.key as string)) {\n onStoreChange();\n }\n });\n },\n [alepha, key],\n );\n\n const getSnapshot = useCallback((): R => {\n const inputs = target\n .keys()\n .map((depKey) => alepha.store.get(depKey as any));\n\n const prev = cache.current;\n if (\n prev &&\n prev.target === target &&\n prev.inputs.length === inputs.length &&\n prev.inputs.every((value, index) => Object.is(value, inputs[index]))\n ) {\n return prev.value;\n }\n\n const value = alepha.store.get(target);\n cache.current = { target, inputs, value };\n return value;\n }, [alepha, key]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nexport { useComputed };\n","import type { Async, Hook, Hooks } from \"alepha\";\nimport { type DependencyList, useEffect } from \"react\";\nimport { useAlepha } from \"./useAlepha.ts\";\n\n/**\n * Allow subscribing to multiple Alepha events. See {@link Hooks} for available events.\n *\n * useEvents is fully typed to ensure correct event callback signatures.\n *\n * @example\n * ```tsx\n * useEvents(\n * {\n * \"react:transition:begin\": (ev) => {\n * console.log(\"Transition began to:\", ev.to);\n * },\n * \"react:transition:error\": {\n * priority: \"first\",\n * callback: (ev) => {\n * console.error(\"Transition error:\", ev.error);\n * },\n * },\n * },\n * [],\n * );\n * ```\n */\nexport const useEvents = (opts: UseEvents, deps: DependencyList) => {\n const alepha = useAlepha();\n\n useEffect(() => {\n if (!alepha.isBrowser()) {\n return;\n }\n\n const subs: Function[] = [];\n for (const [name, hook] of Object.entries(opts)) {\n subs.push(alepha.events.on(name as any, hook as any));\n }\n\n return () => {\n for (const clear of subs) {\n clear();\n }\n };\n }, deps);\n};\n\ntype UseEvents = {\n [T in keyof Hooks]?: Hook<T> | ((payload: Hooks[T]) => Async<void>);\n};\n","import type { Async } from \"alepha\";\nimport type { DurationLike } from \"alepha/datetime\";\nimport { type DependencyList, useCallback, useRef, useState } from \"react\";\nimport type { ActionContext } from \"./useAction.ts\";\nimport { useAction } from \"./useAction.ts\";\n\n/**\n * Hook for declarative data fetching with automatic execution and refetch.\n *\n * Thin wrapper over {@link useAction}: it pre-applies `runOnInit: true`,\n * exposes the last result as `data`, and provides a stable `refetch()` to\n * re-run the query on demand. For optimistic mutations and side-effects,\n * use {@link useAction} directly — `useQuery` is for the read path.\n *\n * Caching, request deduplication, and AbortSignal cancellation come from\n * `useAction` + `HttpClient`. There is no separate cache layer — pass\n * `localCache` to your `HttpClient.fetch()`/`fetchAction()` call inside\n * the query handler if you want per-call caching.\n *\n * @example Basic\n * ```tsx\n * const client = useInject(HttpClient);\n * const { data, loading, error, refetch } = useQuery({\n * handler: async ({ signal }) => {\n * const res = await client.fetch(\"/api/users\", { request: { signal } });\n * return res.data;\n * },\n * }, []);\n * ```\n *\n * @example Re-fetch when a dep changes\n * ```tsx\n * const { data } = useQuery({\n * handler: async () => api.getUser(userId),\n * }, [userId]);\n * ```\n *\n * @example Polling\n * ```tsx\n * const { data } = useQuery({\n * handler: async () => api.getStatus(),\n * runEvery: [5, \"seconds\"],\n * }, []);\n * ```\n */\nexport function useQuery<Result>(\n options: UseQueryOptions<Result>,\n deps: DependencyList,\n): UseQueryReturn<Result> {\n const enabled = options.enabled !== false;\n const [data, setData] = useState<Result | undefined>(options.initialData);\n // Tracks whether the auto-run has completed at least once, so we can keep\n // `loading` true on the very first render — before `runOnInit`'s effect\n // fires — instead of briefly reporting `loading: false` with no data.\n const settledRef = useRef(false);\n\n const action = useAction<[], Result>(\n {\n id: options.id,\n handler: options.handler,\n runOnInit: enabled,\n runEvery: options.runEvery,\n debounce: options.debounce,\n onError: options.onError,\n onSuccess: async (result) => {\n settledRef.current = true;\n setData(result);\n if (options.onSuccess) {\n await options.onSuccess(result);\n }\n },\n },\n deps,\n );\n\n const refetch = useCallback(() => action.run(), [action.run]);\n\n // `loading` is true while a fetch is in flight, AND during the initial gap\n // between first render and the auto-run effect — so consumers can render a\n // skeleton immediately instead of flashing an empty/not-found state. Only\n // applies to enabled queries with no `initialData` seed; an error settles\n // it (the error path keeps the caller's `onError` re-throw semantics).\n const loading =\n action.loading ||\n (enabled &&\n options.initialData === undefined &&\n !settledRef.current &&\n action.error === undefined);\n\n return {\n data,\n loading,\n error: action.error,\n refetch,\n cancel: action.cancel,\n };\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface UseQueryOptions<Result> {\n /**\n * Async query handler. Receives an {@link ActionContext} with an\n * AbortSignal that fires on unmount, dependency change, or `cancel()`.\n */\n handler: (context: ActionContext) => Async<Result>;\n\n /**\n * Optional identifier (used in lifecycle events for debugging/analytics).\n */\n id?: string;\n\n /**\n * If `false`, skip automatic execution on mount and dep change. Use\n * `refetch()` to trigger manually. Defaults to `true`.\n */\n enabled?: boolean;\n\n /**\n * Initial value for `data` before the first successful fetch.\n */\n initialData?: Result;\n\n /**\n * Re-run periodically. See {@link useAction} `runEvery`.\n */\n runEvery?: DurationLike;\n\n /**\n * Debounce delay in milliseconds. See {@link useAction} `debounce`.\n */\n debounce?: number;\n\n /**\n * Called on success with the resolved value.\n */\n onSuccess?: (result: Result) => void | Promise<void>;\n\n /**\n * Custom error handler. If provided, prevents default error re-throw.\n */\n onError?: (error: Error) => void | Promise<void>;\n}\n\nexport interface UseQueryReturn<Result> {\n /**\n * The last successful result. `undefined` until the first fetch resolves\n * (or the value of `initialData` if provided).\n */\n data: Result | undefined;\n\n /**\n * Loading state — `true` while a fetch is in flight, and also from the\n * first render until the initial auto-run settles (for enabled queries\n * with no `initialData`), so a skeleton can render without a flash.\n */\n loading: boolean;\n\n /**\n * Error from the last failed fetch, if any.\n */\n error?: Error;\n\n /**\n * Re-run the query. The previous in-flight request, if any, is aborted.\n */\n refetch: () => Promise<Result | undefined>;\n\n /**\n * Abort the in-flight request without scheduling another.\n */\n cancel: () => void;\n}\n","import type { Atom, Static, TAtomObject } from \"alepha\";\nimport { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport { useAlepha } from \"./useAlepha.ts\";\n\n/**\n * Subscribes to a slice of an atom's state.\n *\n * Unlike {@link useStore}, which re-renders on every mutation of the atom,\n * `useSelector` re-renders only when the selected slice actually changes\n * according to `equality` (default: `Object.is`). Pass {@link shallowEqual}\n * when the selector builds a fresh object on each call.\n *\n * ```tsx\n * const theme = useSelector(uiAtom, (s) => s.theme);\n * ```\n */\nfunction useSelector<T extends TAtomObject, R>(\n target: Atom<T>,\n select: (state: Static<T>) => R,\n equality: (a: R, b: R) => boolean = Object.is,\n): R {\n const alepha = useAlepha();\n const key = target.key;\n\n // Refs, not state: the memoized snapshot must survive re-renders without\n // scheduling them, and `getSnapshot` must return a referentially stable\n // value for unchanged slices or `useSyncExternalStore` re-renders forever.\n const cache = useRef<{ input: unknown; selected: R } | null>(null);\n const selectRef = useRef(select);\n selectRef.current = select;\n const equalityRef = useRef(equality);\n equalityRef.current = equality;\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n if (!alepha.isBrowser()) {\n return () => {};\n }\n\n return alepha.events.on(\"state:mutate\", (ev) => {\n if (ev.key === key) {\n onStoreChange();\n }\n });\n },\n [alepha, key],\n );\n\n const getSnapshot = useCallback(() => {\n const input = alepha.store.get(target);\n const prev = cache.current;\n if (prev && Object.is(prev.input, input)) {\n return prev.selected;\n }\n const selected = selectRef.current(input);\n if (prev && equalityRef.current(prev.selected, selected)) {\n cache.current = { input, selected: prev.selected };\n return prev.selected;\n }\n cache.current = { input, selected };\n return selected;\n }, [alepha, key]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\nexport { useSelector };\n","import type { State, Static, TAtomObject } from \"alepha\";\nimport { Atom } from \"alepha\";\nimport { useCallback, useMemo, useSyncExternalStore } from \"react\";\nimport { useAlepha } from \"./useAlepha.ts\";\n\n/**\n * Hook to access and mutate the Alepha state.\n *\n * Reads through `useSyncExternalStore`, so the store — not a `useState` copy of\n * it — is the single source of truth. That is what keeps the value correct when\n * a mutation lands between render and effect-commit, when the component swaps\n * which `target` it watches, and when React renders concurrently (no tearing).\n */\nfunction useStore<T extends TAtomObject>(\n target: Atom<T>,\n defaultValue?: Static<T>,\n): UseStoreReturn<Static<T>>;\nfunction useStore<Key extends keyof State>(\n target: Key,\n defaultValue?: State[Key],\n): UseStoreReturn<State[Key]>;\nfunction useStore(target: any, defaultValue?: any): any {\n const alepha = useAlepha();\n const key: string = target instanceof Atom ? target.key : target;\n\n // Seed during render (not in an effect) on purpose: effects don't run during\n // SSR, and the default has to be in the store before `exportAtoms` serializes\n // the hydration payload. Idempotent — only fills an empty slot.\n useMemo(() => {\n if (defaultValue != null && alepha.store.get(target) == null) {\n alepha.store.set(target, defaultValue);\n }\n }, [defaultValue, key]);\n\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n if (!alepha.isBrowser()) {\n return () => {};\n }\n\n return alepha.events.on(\"state:mutate\", (ev) => {\n if (ev.key === key) {\n onStoreChange();\n }\n });\n },\n [alepha, key],\n );\n\n // Read straight from the store rather than caching the event payload, so the\n // snapshot stays correct no matter who mutated the key or when.\n const getSnapshot = useCallback(\n () => alepha.store.get(target),\n [alepha, key],\n );\n\n const state = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n const setState = useCallback(\n (value: any) => {\n alepha.store.set(target, value);\n },\n [alepha, key],\n );\n\n return [state, setState] as const;\n}\n\nexport type UseStoreReturn<T> = [T, (value: T) => void];\n\nexport { useStore };\n","/**\n * Shallow structural equality over own enumerable keys.\n *\n * Intended as the `equality` argument of `useSelector` when the selector\n * builds a fresh object/array on every call (e.g. `(s) => ({ a: s.a })`).\n */\nexport const shallowEqual = (a: unknown, b: unknown): boolean => {\n if (Object.is(a, b)) {\n return true;\n }\n if (\n typeof a !== \"object\" ||\n a === null ||\n typeof b !== \"object\" ||\n b === null\n ) {\n return false;\n }\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) {\n return false;\n }\n for (const key of keysA) {\n if (\n !Object.hasOwn(b, key) ||\n !Object.is(\n (a as Record<string, unknown>)[key],\n (b as Record<string, unknown>)[key],\n )\n ) {\n return false;\n }\n }\n return true;\n};\n","import { $module } from \"alepha\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport type * from \"./components/ClientOnly.tsx\";\nexport { default as ClientOnly } from \"./components/ClientOnly.tsx\";\nexport type * from \"./components/ErrorBoundary.tsx\";\nexport { default as ErrorBoundary } from \"./components/ErrorBoundary.tsx\";\nexport * from \"./contexts/AlephaContext.ts\";\nexport * from \"./contexts/AlephaProvider.tsx\";\nexport * from \"./hooks/useAction.ts\";\nexport * from \"./hooks/useAlepha.ts\";\nexport * from \"./hooks/useClient.ts\";\nexport * from \"./hooks/useComputed.ts\";\nexport * from \"./hooks/useEvents.ts\";\nexport * from \"./hooks/useInject.ts\";\nexport * from \"./hooks/useQuery.ts\";\nexport * from \"./hooks/useSelector.ts\";\nexport * from \"./hooks/useStore.ts\";\nexport * from \"./utils/shallowEqual.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n interface Hooks {\n /**\n * Fires when a user action is starting.\n * Action can be a form submission, a route transition, or a custom action.\n */\n \"react:action:begin\": {\n type: string;\n id?: string;\n };\n /**\n * Fires when a user action has succeeded.\n * Action can be a form submission, a route transition, or a custom action.\n */\n \"react:action:success\": {\n type: string;\n id?: string;\n };\n /**\n * Fires when a user action has failed.\n * Action can be a form submission, a route transition, or a custom action.\n */\n \"react:action:error\": {\n type: string;\n id?: string;\n error: Error;\n };\n /**\n * Fires when a user action has completed, regardless of success or failure.\n * Action can be a form submission, a route transition, or a custom action.\n */\n \"react:action:end\": {\n type: string;\n id?: string;\n };\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Full-stack React framework with server-side rendering.\n *\n * **Features:**\n * - React page routes with type-safe params\n * - Async action handler with loading/error/cancel states\n * - Type-safe HTTP client access\n * - Dependency injection in components\n * - Global state management\n * - Router navigation methods\n * - Current route state access\n * - Check if path is active\n * - URL query parameters\n * - Access route schema\n * - Subscribe to Alepha events\n * - Type-safe form handling with validation\n * - Error handling wrapper component\n * - Client-side only rendering component\n * - Server-side rendering with hydration\n * - Automatic code splitting\n * - Event system for action tracking\n *\n * @module alepha.react\n */\nexport const AlephaReact = $module({\n name: \"alepha.react.core\",\n});\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import { Alepha, Static, TArray, TObject, TSchema, TypeBoxError } from "alepha";
2
2
  import { InputHTMLAttributes, ReactNode } from "react";
3
-
4
3
  //#region ../../src/react/form/services/FormModel.d.ts
5
4
  /**
6
5
  * FormModel is a dynamic form handler that generates form inputs based on a provided TypeBox schema.
@@ -19,11 +18,10 @@ declare class FormModel<T extends TObject> {
19
18
  protected readonly initialValues: Record<string, any>;
20
19
  protected submitInProgress: boolean;
21
20
  input: SchemaToInput<T>;
22
- get submitting(): boolean;
23
21
  constructor(id: string, options: FormCtrlOptions<T>);
24
22
  /**
25
- * Extract default values from a TypeBox schema.
26
- * Recursively handles nested objects.
23
+ * Extract default values from a zod object schema.
24
+ * Recursively handles nested objects, unwrapping optional/nullable/default.
27
25
  */
28
26
  protected extractSchemaDefaults(schema: TObject, prefix?: string): Record<string, any>;
29
27
  get currentValues(): Record<string, any>;
@@ -60,7 +58,7 @@ declare class FormModel<T extends TObject> {
60
58
  */
61
59
  protected getValueFromInput(input: any, schema: TSchema): any;
62
60
  }
63
- type SchemaToInput<T extends TObject> = { [K in keyof T["properties"]]: InputField<T["properties"][K]> };
61
+ type SchemaToInput<T extends TObject> = { [K in keyof T["properties"]]: InputField<T["properties"][K]>; };
64
62
  interface FormEventLike {
65
63
  preventDefault?: () => void;
66
64
  stopPropagation?: () => void;
@@ -179,7 +177,7 @@ interface UseFormQuerySyncOptions<TKey extends string> {
179
177
  * navigable via back/forward.
180
178
  *
181
179
  * @example
182
- * const form = useForm({ schema: t.object({ status: t.string(), q: t.string() }) });
180
+ * const form = useForm({ schema: z.object({ status: z.string(), q: z.string() }) });
183
181
  * useFormQuerySync(form, { keys: ["status", "q"] });
184
182
  */
185
183
  declare const useFormQuerySync: <T extends TObject, TKey extends string>(form: FormModel<T>, options: UseFormQuerySyncOptions<TKey>) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/react/form/services/FormModel.ts","../../../src/react/form/components/FormState.tsx","../../../src/react/form/errors/FormValidationError.ts","../../../src/react/form/hooks/useFieldValue.ts","../../../src/react/form/hooks/useForm.ts","../../../src/react/form/hooks/useFormQuerySync.ts","../../../src/react/form/hooks/useFormState.ts","../../../src/react/form/hooks/useFormValues.ts","../../../src/react/form/services/parseField.ts","../../../src/react/form/services/prettyName.ts","../../../src/react/form/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/react/form/services/FormModel.ts","../../../src/react/form/components/FormState.tsx","../../../src/react/form/errors/FormValidationError.ts","../../../src/react/form/hooks/useFieldValue.ts","../../../src/react/form/hooks/useForm.ts","../../../src/react/form/hooks/useFormQuerySync.ts","../../../src/react/form/hooks/useFormState.ts","../../../src/react/form/hooks/useFormValues.ts","../../../src/react/form/services/parseField.ts","../../../src/react/form/services/prettyName.ts","../../../src/react/form/index.ts"],"mappings":";;;;;;;;;;;cAqBa,UAAU,UAAU;WAUb;WACA,SAAS,gBAAgB;qBAVxB,6BAAG;qBACH,QAAM;qBACN,QAAQ;qBACR,eAAe;YACxB;EAEH,OAAO,cAAc;EAE5B,YACkB,YACA,SAAS,gBAAgB;;;;;YAkCjC,sBACR,QAAQ,SACR,kBACC;MA0CQ,iBAAiB;MAIjB;IAEP;IACA;IACA,WAAQ,KAAQ;IAIhB,UAAO,OAAU;;WAIL,mBAAgB,QAAY;WAmC5B,QAAK,QAAY;WA0BjB,cAAM;;;;;YAiGZ,kBAAkB,OAAO,sBAAsB;;;;;YAoB/C,uBACR,QAAQ,qBACR,aACA;YAoBQ,sBAAsB,UAAU,SACxC,SAAS,gBAAgB,IACzB,QAAQ,SACR;IACE;IACA,OAAO;MAER,cAAc;YAiCP,sBAAsB,UAAU,SACxC,YAAY,OAAO,aACnB,SAAS,gBAAgB,IACzB,QAAQ,SACR,mBACA;IACE;IACA,OAAO;MAER;;;;;YA2IO,kBAAkB,YAAY,QAAQ;;KAmDtC,cAAc,UAAU,cACjC,WAAW,kBAAkB,WAAW,gBAAgB;UAG1C;EACf;EACA;;KAGU,WAAW,UAAU,WAAW,UAAU,UAClD,iBAAiB,KACjB,UAAU,aAAa,KACrB,gBAAgB,KAChB;UAEW;EACf;EACA;EACA;EACA,OAAO;EACP,QAAQ;EACR,MAAM;EACN,MAAM;EACN;;UAGe,iBAAiB,UAAU,iBAAiB;EAC3D,OAAO,cAAc;;UAGN,gBAAgB,UAAU,iBAAiB;EAC1D,OAAO,MAAM,WAAW;;KAGd,0BAA0B,KACpC;EAUA;;KAGU,gBAAgB,UAAU;;;;;EAKpC,QAAQ;;;;;EAMR,UAAU,QAAQ,OAAO;;;;;EAMzB,gBAAgB,QAAQ,OAAO;;;;;EAM/B,iBACE,YAAY,OAAO,aACnB,QAAQ,YACL;;;;;;;;EASL;EAEA,WAAW,OAAO;EAElB,YAAY,aAAa,YAAY,OAAO;EAE5C;;;;cC3oBI,YAAa,UAAU,SAAO;EAClC,MAAM,UAAU;EAChB,WAAW;IAAS;IAAkB;QAAqB;MAC5D;;;cCNY,4BAA4B;WAC9B;EAET,YAAY;IACV;IACA;;;;;;;;;;;cCGS,gBAAa,OACjB,0BACC;;;cCqCG,UAAW,UAAU,SAAO,SAC9B,gBAAgB,IAAE,iBAE1B,UAAU;;;UC9CI,wBAAwB;;;;;EAKvC,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;cA4BJ,mBAAoB,UAAU,SAAS,qBAAmB,MAC/D,UAAU,IAAE,SACT,wBAAwB;;;UCpClB;EACf;EACA;EACA,SAAS;EACT,QAAQ;;cAGG,eACX,UAAU,SACV,mBAAmB,oBAAkB,QAE7B,UAAU;EAAO,MAAM,UAAU;EAAI;GAAc,UAClD,WACR,KAAK,oBAAoB;;;;;;;cCTf,gBAAiB,UAAU,SAAO,MACvC,UAAU,OACf;;;;;;;KCHS;UAcK;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,WAAW;EACX,aAAa;EACb;EACA,QAAQ;;;;;;EAMR;;UAGe;EACf;EACA;EACA,QAAQ;;;;;;;;;cAUG,aAAU,OACd,gBAAc,UACZ,sBACR;;;;;;;;;;;;;;cC5DU,aAAU;;;;YCOX;IACR;MACE;MACA;MACA;;;;;MAKA;;IAEF;MAAuB;;IACvB;MAAyB;MAAY,QAAQ;;IAC7C;MAAuB;MAAY,OAAO;;IAC1C;MAAqB;;IACrB;MAAgB;;;;;;;;;;;;;;;;cAkBP,kCAAe,yBAAA"}