alepha 0.18.2 → 0.18.3

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 (397) hide show
  1. package/assets/devtools-ui/200.html +2 -2
  2. package/assets/devtools-ui/200.html.br +0 -0
  3. package/assets/devtools-ui/404.html +2 -2
  4. package/assets/devtools-ui/404.html.br +0 -0
  5. package/assets/devtools-ui/{asset.BfSBZ5Dd.css → asset.hG_f8HuK.css} +1 -1
  6. package/assets/devtools-ui/asset.hG_f8HuK.css.br +0 -0
  7. package/assets/devtools-ui/chunk.B3au4Lhg.js +1 -0
  8. package/assets/devtools-ui/chunk.B3au4Lhg.js.br +0 -0
  9. package/assets/devtools-ui/chunk.BLOrlnMB.js +1 -0
  10. package/assets/devtools-ui/chunk.BLOrlnMB.js.br +0 -0
  11. package/assets/devtools-ui/chunk.BLR01ljW.js +1 -0
  12. package/assets/devtools-ui/chunk.BLR01ljW.js.br +0 -0
  13. package/assets/devtools-ui/chunk.BTXaIUlA.js +1 -0
  14. package/assets/devtools-ui/chunk.BTXaIUlA.js.br +0 -0
  15. package/assets/devtools-ui/{chunk.lJL-lgnW.js → chunk.BhJaxmm8.js} +1 -1
  16. package/assets/devtools-ui/chunk.BhJaxmm8.js.br +0 -0
  17. package/assets/devtools-ui/chunk.BtoNxFuL.js +1 -0
  18. package/assets/devtools-ui/chunk.BtoNxFuL.js.br +0 -0
  19. package/assets/devtools-ui/chunk.C8YUV2Wd.js +1 -0
  20. package/assets/devtools-ui/chunk.C8YUV2Wd.js.br +0 -0
  21. package/assets/devtools-ui/{chunk.M6wyKO_3.js → chunk.CBbIgDzE.js} +2 -2
  22. package/assets/devtools-ui/chunk.CBbIgDzE.js.br +0 -0
  23. package/assets/devtools-ui/chunk.CFqIniwA.js +1 -0
  24. package/assets/devtools-ui/chunk.CFqIniwA.js.br +0 -0
  25. package/assets/devtools-ui/chunk.CLFF7f7-.js +1 -0
  26. package/assets/devtools-ui/chunk.CLFF7f7-.js.br +0 -0
  27. package/assets/devtools-ui/chunk.CRsBbA10.js +1 -0
  28. package/assets/devtools-ui/chunk.CRsBbA10.js.br +0 -0
  29. package/assets/devtools-ui/{chunk.DbEH1oOB.js → chunk.CZPo6v95.js} +1 -1
  30. package/assets/devtools-ui/chunk.CZPo6v95.js.br +0 -0
  31. package/assets/devtools-ui/chunk.D0fWgNos.js +1 -0
  32. package/assets/devtools-ui/chunk.D0fWgNos.js.br +1 -0
  33. package/assets/devtools-ui/chunk.D7-0ziQ6.js +1 -0
  34. package/assets/devtools-ui/chunk.D7-0ziQ6.js.br +0 -0
  35. package/assets/devtools-ui/chunk.DAewe0vm.js +1 -0
  36. package/assets/devtools-ui/chunk.DAewe0vm.js.br +0 -0
  37. package/assets/devtools-ui/chunk.DJRQEYqK.js +1 -0
  38. package/assets/devtools-ui/chunk.DJRQEYqK.js.br +0 -0
  39. package/assets/devtools-ui/{chunk.CZl6J9DF.js → chunk.DMAxv14p.js} +1 -1
  40. package/assets/devtools-ui/chunk.DMAxv14p.js.br +0 -0
  41. package/assets/devtools-ui/{chunk.BT2IiBkZ.js → chunk.DMImnNjU.js} +1 -1
  42. package/assets/devtools-ui/chunk.DMImnNjU.js.br +0 -0
  43. package/assets/devtools-ui/chunk.DeeQsidk.js +9 -0
  44. package/assets/devtools-ui/chunk.DeeQsidk.js.br +0 -0
  45. package/assets/devtools-ui/chunk.DqEwn9Vj.js +7 -0
  46. package/assets/devtools-ui/chunk.DqEwn9Vj.js.br +0 -0
  47. package/assets/devtools-ui/chunk.Dt8OsQey.js +1 -0
  48. package/assets/devtools-ui/chunk.Dt8OsQey.js.br +0 -0
  49. package/assets/devtools-ui/{chunk.B9pX3zit.js → chunk.Dtp8oa_f.js} +1 -1
  50. package/assets/devtools-ui/chunk.Dtp8oa_f.js.br +0 -0
  51. package/assets/devtools-ui/chunk.Dx3JzAYM.js +1 -0
  52. package/assets/devtools-ui/chunk.Dx3JzAYM.js.br +0 -0
  53. package/assets/devtools-ui/chunk.GCOj1-5E.js +1 -0
  54. package/assets/devtools-ui/chunk.GCOj1-5E.js.br +0 -0
  55. package/assets/devtools-ui/chunk.IC1LD8BH.js +1 -0
  56. package/assets/devtools-ui/chunk.IC1LD8BH.js.br +0 -0
  57. package/assets/devtools-ui/chunk.IwuB_TqW.js +1 -0
  58. package/assets/devtools-ui/chunk.IwuB_TqW.js.br +0 -0
  59. package/assets/devtools-ui/chunk.Qqapj2zq.js +1 -0
  60. package/assets/devtools-ui/chunk.Qqapj2zq.js.br +0 -0
  61. package/assets/devtools-ui/{chunk.C79YouPp.js → chunk.TKKKndOy.js} +1 -1
  62. package/assets/devtools-ui/chunk.TKKKndOy.js.br +0 -0
  63. package/assets/devtools-ui/chunk.YHTVhFQT.js +1 -0
  64. package/assets/devtools-ui/chunk.YHTVhFQT.js.br +0 -0
  65. package/assets/devtools-ui/chunk.fnod6uEi.js +1 -0
  66. package/assets/devtools-ui/chunk.fnod6uEi.js.br +0 -0
  67. package/assets/devtools-ui/chunk.mOCRmXjo.js +1 -0
  68. package/assets/devtools-ui/chunk.mOCRmXjo.js.br +0 -0
  69. package/assets/devtools-ui/chunk.qZTNEAK0.js +1 -0
  70. package/assets/devtools-ui/chunk.qZTNEAK0.js.br +0 -0
  71. package/assets/devtools-ui/chunk.rc9m0y4-.js +1 -0
  72. package/assets/devtools-ui/chunk.rc9m0y4-.js.br +0 -0
  73. package/assets/devtools-ui/entry.Cxc5QLCU.js +80 -0
  74. package/assets/devtools-ui/entry.Cxc5QLCU.js.br +0 -0
  75. package/assets/devtools-ui/index.html +2 -2
  76. package/assets/devtools-ui/index.html.br +0 -0
  77. package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
  78. package/assets/swagger-ui/swagger-ui.css +1 -1
  79. package/dist/api/audits/index.d.ts +61 -5
  80. package/dist/api/audits/index.d.ts.map +1 -1
  81. package/dist/api/files/index.d.ts +61 -5
  82. package/dist/api/files/index.d.ts.map +1 -1
  83. package/dist/api/jobs/index.d.ts +61 -5
  84. package/dist/api/jobs/index.d.ts.map +1 -1
  85. package/dist/api/jobs/index.js +4 -2
  86. package/dist/api/jobs/index.js.map +1 -1
  87. package/dist/api/keys/index.d.ts +5 -5
  88. package/dist/api/notifications/index.browser.js +44 -1
  89. package/dist/api/notifications/index.browser.js.map +1 -1
  90. package/dist/api/notifications/index.d.ts +187 -2
  91. package/dist/api/notifications/index.d.ts.map +1 -1
  92. package/dist/api/notifications/index.js +143 -8
  93. package/dist/api/notifications/index.js.map +1 -1
  94. package/dist/api/parameters/index.d.ts +61 -5
  95. package/dist/api/parameters/index.d.ts.map +1 -1
  96. package/dist/api/users/index.d.ts +330 -93
  97. package/dist/api/users/index.d.ts.map +1 -1
  98. package/dist/api/users/index.js +27 -36
  99. package/dist/api/users/index.js.map +1 -1
  100. package/dist/cli/config/index.d.ts +46 -0
  101. package/dist/cli/config/index.d.ts.map +1 -0
  102. package/dist/cli/config/index.js +20 -0
  103. package/dist/cli/config/index.js.map +1 -0
  104. package/dist/cli/core/index.d.ts +69 -66
  105. package/dist/cli/core/index.d.ts.map +1 -1
  106. package/dist/cli/core/index.js +329 -196
  107. package/dist/cli/core/index.js.map +1 -1
  108. package/dist/cli/platform/index.d.ts +302 -63
  109. package/dist/cli/platform/index.d.ts.map +1 -1
  110. package/dist/cli/platform/index.js +455 -25
  111. package/dist/cli/platform/index.js.map +1 -1
  112. package/dist/core/index.browser.js +125 -87
  113. package/dist/core/index.browser.js.map +1 -1
  114. package/dist/core/index.d.ts +62 -53
  115. package/dist/core/index.d.ts.map +1 -1
  116. package/dist/core/index.js +125 -87
  117. package/dist/core/index.js.map +1 -1
  118. package/dist/core/index.native.js +125 -87
  119. package/dist/core/index.native.js.map +1 -1
  120. package/dist/core/index.workerd.js +125 -87
  121. package/dist/core/index.workerd.js.map +1 -1
  122. package/dist/crypto/index.d.ts +18 -1
  123. package/dist/crypto/index.d.ts.map +1 -1
  124. package/dist/crypto/index.js +29 -3
  125. package/dist/crypto/index.js.map +1 -1
  126. package/dist/devtools/index.js +3 -12
  127. package/dist/devtools/index.js.map +1 -1
  128. package/dist/logger/index.d.ts +10 -1
  129. package/dist/logger/index.d.ts.map +1 -1
  130. package/dist/logger/index.js +19 -9
  131. package/dist/logger/index.js.map +1 -1
  132. package/dist/orm/core/index.browser.js +57 -1
  133. package/dist/orm/core/index.browser.js.map +1 -1
  134. package/dist/orm/core/index.bun.js +378 -19
  135. package/dist/orm/core/index.bun.js.map +1 -1
  136. package/dist/orm/core/index.d.ts +328 -9
  137. package/dist/orm/core/index.d.ts.map +1 -1
  138. package/dist/orm/core/index.js +384 -21
  139. package/dist/orm/core/index.js.map +1 -1
  140. package/dist/orm/postgres/index.bun.js +49 -17
  141. package/dist/orm/postgres/index.bun.js.map +1 -1
  142. package/dist/orm/postgres/index.d.ts +47 -21
  143. package/dist/orm/postgres/index.d.ts.map +1 -1
  144. package/dist/orm/postgres/index.js +52 -17
  145. package/dist/orm/postgres/index.js.map +1 -1
  146. package/dist/react/core/index.d.ts +1 -1
  147. package/dist/react/core/index.d.ts.map +1 -1
  148. package/dist/react/core/index.js +6 -1
  149. package/dist/react/core/index.js.map +1 -1
  150. package/dist/react/form/index.d.ts +28 -18
  151. package/dist/react/form/index.d.ts.map +1 -1
  152. package/dist/react/form/index.js +92 -56
  153. package/dist/react/form/index.js.map +1 -1
  154. package/dist/react/router/index.browser.js +448 -116
  155. package/dist/react/router/index.browser.js.map +1 -1
  156. package/dist/react/router/index.d.ts +102 -40
  157. package/dist/react/router/index.d.ts.map +1 -1
  158. package/dist/react/router/index.js +453 -92
  159. package/dist/react/router/index.js.map +1 -1
  160. package/dist/security/index.d.ts +3 -11
  161. package/dist/security/index.d.ts.map +1 -1
  162. package/dist/security/index.js +6 -11
  163. package/dist/security/index.js.map +1 -1
  164. package/dist/server/auth/index.d.ts +22 -24
  165. package/dist/server/auth/index.d.ts.map +1 -1
  166. package/dist/server/auth/index.js +102 -82
  167. package/dist/server/auth/index.js.map +1 -1
  168. package/dist/server/cookies/index.d.ts +7 -4
  169. package/dist/server/cookies/index.d.ts.map +1 -1
  170. package/dist/server/cookies/index.js +13 -12
  171. package/dist/server/cookies/index.js.map +1 -1
  172. package/dist/server/core/index.d.ts +288 -4
  173. package/dist/server/core/index.d.ts.map +1 -1
  174. package/dist/server/core/index.js +375 -2
  175. package/dist/server/core/index.js.map +1 -1
  176. package/dist/server/links/index.browser.js +10 -71
  177. package/dist/server/links/index.browser.js.map +1 -1
  178. package/dist/server/links/index.d.ts +32 -49
  179. package/dist/server/links/index.d.ts.map +1 -1
  180. package/dist/server/links/index.js +73 -100
  181. package/dist/server/links/index.js.map +1 -1
  182. package/dist/system/index.browser.js +221 -2
  183. package/dist/system/index.browser.js.map +1 -1
  184. package/dist/system/index.d.ts +63 -1
  185. package/dist/system/index.d.ts.map +1 -1
  186. package/dist/system/index.js +221 -1
  187. package/dist/system/index.js.map +1 -1
  188. package/dist/system/index.workerd.js +224 -4
  189. package/dist/system/index.workerd.js.map +1 -1
  190. package/package.json +10 -5
  191. package/src/api/jobs/providers/JobProvider.ts +6 -3
  192. package/src/api/notifications/controllers/AdminNotificationController.ts +83 -0
  193. package/src/api/notifications/index.browser.ts +3 -0
  194. package/src/api/notifications/index.ts +14 -2
  195. package/src/api/notifications/jobs/NotificationJobs.ts +11 -2
  196. package/src/api/notifications/schemas/notificationDetailResourceSchema.ts +20 -0
  197. package/src/api/notifications/schemas/notificationQuerySchema.ts +19 -0
  198. package/src/api/notifications/schemas/notificationResourceSchema.ts +18 -0
  199. package/src/api/notifications/services/NotificationSenderService.ts +15 -2
  200. package/src/api/users/atoms/realmAuthSettingsAtom.ts +28 -32
  201. package/src/api/users/buckets/UserBuckets.ts +1 -1
  202. package/src/api/users/jobs/UserJobs.ts +1 -1
  203. package/src/api/users/primitives/$realm.ts +8 -49
  204. package/src/api/users/providers/RealmProvider.ts +2 -3
  205. package/src/api/users/services/RegistrationService.spec.ts +7 -7
  206. package/src/api/users/services/RegistrationService.ts +3 -3
  207. package/src/api/users/services/SessionService.spec.ts +4 -4
  208. package/src/api/users/services/SessionService.ts +3 -3
  209. package/src/cli/{core → config}/defineConfig.ts +14 -20
  210. package/src/cli/config/index.ts +1 -0
  211. package/src/cli/core/commands/db.ts +65 -1
  212. package/src/cli/core/commands/dev.ts +1 -0
  213. package/src/cli/core/commands/init.ts +2 -192
  214. package/src/cli/core/index.ts +34 -11
  215. package/src/cli/core/providers/ViteDevServerProvider.ts +52 -13
  216. package/src/cli/core/services/PackageManagerUtils.ts +43 -21
  217. package/src/cli/core/services/ProjectScaffolder.ts +214 -2
  218. package/src/cli/core/services/ViteUtils.ts +57 -0
  219. package/src/cli/core/tasks/BuildClientTask.ts +7 -2
  220. package/src/cli/core/tasks/BuildCloudflareTask.ts +4 -12
  221. package/src/cli/core/tasks/BuildServerTask.ts +2 -0
  222. package/src/cli/core/tasks/BuildVercelTask.ts +165 -168
  223. package/src/cli/core/templates/alephaConfigTs.ts +1 -1
  224. package/src/cli/core/templates/apiAppSecurityTs.ts +5 -8
  225. package/src/cli/core/templates/tsconfigJson.ts +6 -1
  226. package/src/cli/platform/adapters/CloudflareAdapter.spec.ts +1 -1
  227. package/src/cli/platform/adapters/CloudflareAdapter.ts +30 -29
  228. package/src/cli/platform/atoms/platformOptions.ts +21 -0
  229. package/src/cli/platform/commands/SecretsCommand.spec.ts +298 -0
  230. package/src/cli/platform/commands/SecretsCommand.ts +283 -0
  231. package/src/cli/platform/commands/platform.ts +12 -0
  232. package/src/cli/platform/index.ts +14 -28
  233. package/src/cli/platform/providers/GitHubSecretStore.spec.ts +153 -0
  234. package/src/cli/platform/providers/GitHubSecretStore.ts +112 -0
  235. package/src/cli/platform/providers/MemorySecretStore.ts +114 -0
  236. package/src/cli/platform/providers/SecretStoreProvider.ts +39 -0
  237. package/src/cli/platform/schemas/cloudflare.ts +2 -0
  238. package/src/cli/platform/services/CloudflareApi.ts +5 -2
  239. package/src/cli/platform/services/DockerComposeGenerator.spec.ts +115 -0
  240. package/src/cli/platform/services/DockerComposeGenerator.ts +46 -1
  241. package/src/cli/platform/services/SecretFilterService.spec.ts +111 -0
  242. package/src/cli/platform/services/SecretFilterService.ts +54 -0
  243. package/src/core/Alepha.ts +94 -25
  244. package/src/core/__tests__/Alepha-parseEnv.spec.ts +20 -0
  245. package/src/core/primitives/$memoize.ts +38 -26
  246. package/src/core/providers/AlsProvider.ts +2 -0
  247. package/src/core/providers/EventManager.ts +4 -0
  248. package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +1 -4
  249. package/src/core/providers/KeylessJsonSchemaCodec.ts +19 -125
  250. package/src/core/providers/SchemaValidator.spec.ts +36 -0
  251. package/src/core/providers/SchemaValidator.ts +9 -0
  252. package/src/crypto/index.ts +6 -1
  253. package/src/crypto/providers/SecretProvider.ts +36 -0
  254. package/src/devtools/providers/DevToolsProvider.ts +3 -12
  255. package/src/logger/index.ts +33 -6
  256. package/src/logger/providers/PrettyFormatterProvider.ts +5 -3
  257. package/src/orm/__tests__/orm-next-tests.ts +492 -0
  258. package/src/orm/__tests__/orm-next.spec.ts +140 -0
  259. package/src/orm/core/constants/PG_SYMBOLS.ts +17 -0
  260. package/src/orm/core/index.bun.ts +3 -6
  261. package/src/orm/core/index.shared-server.ts +2 -0
  262. package/src/orm/core/index.shared.ts +2 -0
  263. package/src/orm/core/index.ts +5 -7
  264. package/src/orm/core/interfaces/AggregateQuery.ts +103 -0
  265. package/src/orm/core/interfaces/PgQueryWhere.ts +7 -0
  266. package/src/orm/core/primitives/$entity.ts +8 -0
  267. package/src/orm/core/primitives/$repository.ts +6 -3
  268. package/src/orm/core/primitives/$view.ts +88 -0
  269. package/src/orm/core/providers/DbCacheProvider.ts +66 -0
  270. package/src/orm/core/providers/DrizzleKitProvider.ts +42 -0
  271. package/src/orm/core/providers/drivers/BunSqliteProvider.ts +2 -3
  272. package/src/orm/core/providers/drivers/CloudflareD1Provider.ts +12 -0
  273. package/src/orm/core/providers/drivers/DatabaseProvider.ts +39 -0
  274. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +2 -3
  275. package/src/orm/core/schemas/databaseEnvSchema.ts +31 -0
  276. package/src/orm/core/schemas/insertSchema.ts +13 -3
  277. package/src/orm/core/schemas/updateSchema.ts +14 -3
  278. package/src/orm/core/services/ModelBuilder.ts +26 -14
  279. package/src/orm/core/services/QueryManager.ts +13 -0
  280. package/src/orm/core/services/Repository.ts +307 -5
  281. package/src/orm/core/services/SqliteModelBuilder.ts +38 -0
  282. package/src/orm/postgres/index.bun.ts +4 -7
  283. package/src/orm/postgres/index.ts +4 -7
  284. package/src/orm/postgres/providers/BunPostgresProvider.ts +12 -2
  285. package/src/orm/postgres/providers/NodePostgresProvider.ts +7 -0
  286. package/src/orm/postgres/providers/PglitePostgresProvider.ts +10 -17
  287. package/src/orm/postgres/providers/PostgresProvider.ts +7 -36
  288. package/src/orm/postgres/schemas/postgresEnvSchema.ts +32 -0
  289. package/src/orm/postgres/services/PostgresModelBuilder.ts +40 -0
  290. package/src/react/core/components/ErrorBoundary.tsx +5 -2
  291. package/src/react/form/hooks/useFieldValue.ts +34 -0
  292. package/src/react/form/hooks/useForm.browser.spec.tsx +94 -9
  293. package/src/react/form/hooks/useForm.ts +14 -2
  294. package/src/react/form/hooks/useFormState.ts +10 -10
  295. package/src/react/form/hooks/useFormValues.ts +29 -0
  296. package/src/react/form/index.ts +3 -1
  297. package/src/react/form/services/FormModel.ts +53 -122
  298. package/src/react/router/components/ErrorViewer.tsx +333 -34
  299. package/src/react/router/components/NestedView.tsx +10 -3
  300. package/src/react/router/primitives/$page.browser.spec.tsx +34 -0
  301. package/src/react/router/primitives/$page.spec.tsx +20 -0
  302. package/src/react/router/primitives/$page.ts +24 -0
  303. package/src/react/router/providers/ReactBrowserRouterProvider.ts +14 -2
  304. package/src/react/router/providers/ReactPageProvider.ts +156 -73
  305. package/src/react/router/providers/ReactServerProvider.ts +40 -2
  306. package/src/react/router/providers/ReactServerTemplateProvider.ts +13 -1
  307. package/src/security/providers/SecurityProvider.ts +5 -27
  308. package/src/server/auth/primitives/$auth.ts +52 -19
  309. package/src/server/auth/providers/ServerAuthProvider.ts +145 -139
  310. package/src/server/cookies/providers/ServerCookiesProvider.ts +12 -24
  311. package/src/server/core/index.ts +3 -1
  312. package/src/server/core/primitives/$sse.spec.ts +315 -0
  313. package/src/server/core/primitives/$sse.ts +715 -0
  314. package/src/server/links/index.browser.ts +1 -3
  315. package/src/server/links/index.ts +0 -3
  316. package/src/server/links/providers/LinkProvider.spec.ts +12 -21
  317. package/src/server/links/providers/LinkProvider.ts +20 -52
  318. package/src/server/links/providers/ServerLinksProvider.spec.ts +106 -0
  319. package/src/server/links/providers/ServerLinksProvider.ts +113 -73
  320. package/src/server/links/schemas/apiLinksResponseSchema.ts +4 -21
  321. package/src/server/links/services/BatchCollector.ts +5 -3
  322. package/src/system/index.browser.ts +1 -0
  323. package/src/system/index.ts +3 -0
  324. package/src/system/index.workerd.ts +39 -1
  325. package/src/system/providers/WorkerdFileSystemProvider.ts +365 -0
  326. package/assets/devtools-ui/asset.BfSBZ5Dd.css.br +0 -0
  327. package/assets/devtools-ui/chunk.2NYaoqWt.js +0 -1
  328. package/assets/devtools-ui/chunk.2NYaoqWt.js.br +0 -0
  329. package/assets/devtools-ui/chunk.B052Z_xQ.js +0 -1
  330. package/assets/devtools-ui/chunk.B052Z_xQ.js.br +0 -0
  331. package/assets/devtools-ui/chunk.B4kVY90C.js +0 -1
  332. package/assets/devtools-ui/chunk.B4kVY90C.js.br +0 -0
  333. package/assets/devtools-ui/chunk.B7QJXctB.js +0 -1
  334. package/assets/devtools-ui/chunk.B7QJXctB.js.br +0 -0
  335. package/assets/devtools-ui/chunk.B9pX3zit.js.br +0 -0
  336. package/assets/devtools-ui/chunk.BKF9JxIo.js +0 -1
  337. package/assets/devtools-ui/chunk.BKF9JxIo.js.br +0 -0
  338. package/assets/devtools-ui/chunk.BOHgdTP-.js +0 -1
  339. package/assets/devtools-ui/chunk.BOHgdTP-.js.br +0 -0
  340. package/assets/devtools-ui/chunk.BOVFxkYC.js +0 -1
  341. package/assets/devtools-ui/chunk.BOVFxkYC.js.br +0 -0
  342. package/assets/devtools-ui/chunk.BR842zj5.js +0 -1
  343. package/assets/devtools-ui/chunk.BR842zj5.js.br +0 -0
  344. package/assets/devtools-ui/chunk.BT2IiBkZ.js.br +0 -0
  345. package/assets/devtools-ui/chunk.C79YouPp.js.br +0 -0
  346. package/assets/devtools-ui/chunk.C8mlBrjW.js +0 -9
  347. package/assets/devtools-ui/chunk.C8mlBrjW.js.br +0 -0
  348. package/assets/devtools-ui/chunk.CK0ow3AZ.js +0 -1
  349. package/assets/devtools-ui/chunk.CK0ow3AZ.js.br +0 -0
  350. package/assets/devtools-ui/chunk.CZl6J9DF.js.br +0 -0
  351. package/assets/devtools-ui/chunk.CdNr0YzS.js +0 -1
  352. package/assets/devtools-ui/chunk.CdNr0YzS.js.br +0 -0
  353. package/assets/devtools-ui/chunk.Ce6_6iIF.js +0 -1
  354. package/assets/devtools-ui/chunk.Ce6_6iIF.js.br +0 -0
  355. package/assets/devtools-ui/chunk.CpyDMr6O.js +0 -1
  356. package/assets/devtools-ui/chunk.CpyDMr6O.js.br +0 -0
  357. package/assets/devtools-ui/chunk.CyPmvPnY.js +0 -1
  358. package/assets/devtools-ui/chunk.CyPmvPnY.js.br +0 -0
  359. package/assets/devtools-ui/chunk.DTI_geWu.js +0 -1
  360. package/assets/devtools-ui/chunk.DTI_geWu.js.br +0 -0
  361. package/assets/devtools-ui/chunk.DbEH1oOB.js.br +0 -0
  362. package/assets/devtools-ui/chunk.Ddeqj5gv.js +0 -1
  363. package/assets/devtools-ui/chunk.Ddeqj5gv.js.br +0 -0
  364. package/assets/devtools-ui/chunk.DpRnB4vJ.js +0 -1
  365. package/assets/devtools-ui/chunk.DpRnB4vJ.js.br +0 -0
  366. package/assets/devtools-ui/chunk.DxPGTlsg.js +0 -1
  367. package/assets/devtools-ui/chunk.DxPGTlsg.js.br +0 -0
  368. package/assets/devtools-ui/chunk.G7_MMBJS.js +0 -1
  369. package/assets/devtools-ui/chunk.G7_MMBJS.js.br +0 -0
  370. package/assets/devtools-ui/chunk.M6wyKO_3.js.br +0 -0
  371. package/assets/devtools-ui/chunk.OUxNGmQ6.js +0 -1
  372. package/assets/devtools-ui/chunk.OUxNGmQ6.js.br +0 -0
  373. package/assets/devtools-ui/chunk.T1kle-fF.js +0 -1
  374. package/assets/devtools-ui/chunk.T1kle-fF.js.br +0 -0
  375. package/assets/devtools-ui/chunk.WjpsbQAv.js +0 -1
  376. package/assets/devtools-ui/chunk.WjpsbQAv.js.br +0 -0
  377. package/assets/devtools-ui/chunk.c6YgVx86.js +0 -1
  378. package/assets/devtools-ui/chunk.c6YgVx86.js.br +0 -0
  379. package/assets/devtools-ui/chunk.dwU3E_MU.js +0 -1
  380. package/assets/devtools-ui/chunk.dwU3E_MU.js.br +0 -0
  381. package/assets/devtools-ui/chunk.lJL-lgnW.js.br +0 -0
  382. package/assets/devtools-ui/chunk.lPWRmvA-.js +0 -7
  383. package/assets/devtools-ui/chunk.lPWRmvA-.js.br +0 -0
  384. package/assets/devtools-ui/chunk.p3HJvugM.js +0 -1
  385. package/assets/devtools-ui/chunk.p3HJvugM.js.br +0 -0
  386. package/assets/devtools-ui/chunk.r_Xoa_CI.js +0 -1
  387. package/assets/devtools-ui/chunk.r_Xoa_CI.js.br +0 -0
  388. package/assets/devtools-ui/chunk.sRNuTYXb.js +0 -1
  389. package/assets/devtools-ui/chunk.sRNuTYXb.js.br +0 -0
  390. package/assets/devtools-ui/chunk.tUjcyX5C.js +0 -1
  391. package/assets/devtools-ui/chunk.tUjcyX5C.js.br +0 -0
  392. package/assets/devtools-ui/chunk.thjBxvCA.js +0 -1
  393. package/assets/devtools-ui/chunk.thjBxvCA.js.br +0 -0
  394. package/assets/devtools-ui/entry.GYhBVRpC.js +0 -78
  395. package/assets/devtools-ui/entry.GYhBVRpC.js.br +0 -0
  396. package/src/server/links/services/DefinitionsPool.spec.ts +0 -86
  397. package/src/server/links/services/DefinitionsPool.ts +0 -43
@@ -1,5 +1,5 @@
1
- import { $module, type Alepha, t } from "alepha";
2
- import { AlephaOrm, DatabaseProvider } from "alepha/orm";
1
+ import { $module, type Alepha } from "alepha";
2
+ import { AlephaOrm, DatabaseProvider, databaseEnvSchema } from "alepha/orm";
3
3
  import { BunPostgresProvider } from "./providers/BunPostgresProvider.ts";
4
4
  import { CloudflareHyperdriveProvider } from "./providers/CloudflareHyperdriveProvider.ts";
5
5
  import { NodePostgresProvider } from "./providers/NodePostgresProvider.ts";
@@ -14,6 +14,7 @@ export * from "./providers/CloudflareHyperdriveProvider.ts";
14
14
  export * from "./providers/NodePostgresProvider.ts";
15
15
  export * from "./providers/PglitePostgresProvider.ts";
16
16
  export * from "./providers/PostgresProvider.ts";
17
+ export * from "./schemas/postgresEnvSchema.ts";
17
18
  export * from "./services/PostgresModelBuilder.ts";
18
19
  export * from "./types/byte.ts";
19
20
 
@@ -31,11 +32,7 @@ export const AlephaOrmPostgres = $module({
31
32
  PostgresModelBuilder,
32
33
  ],
33
34
  register: (alepha: Alepha) => {
34
- const env = alepha.parseEnv(
35
- t.object({
36
- DATABASE_URL: t.optional(t.text()),
37
- }),
38
- );
35
+ const env = alepha.parseEnv(databaseEnvSchema);
39
36
 
40
37
  const url = env.DATABASE_URL;
41
38
  const isBun = alepha.isBun();
@@ -66,8 +66,18 @@ export class BunPostgresProvider extends PostgresProvider {
66
66
 
67
67
  const { drizzle } = await import("drizzle-orm/bun-sql");
68
68
 
69
- // Create Bun SQL client
70
- this.client = new Bun.SQL(this.url);
69
+ // Create Bun SQL client with pool options
70
+ const bunOptions: Record<string, any> = { url: this.url };
71
+ if (this.pgEnv.POOL_MAX != null) {
72
+ bunOptions.max = this.pgEnv.POOL_MAX;
73
+ }
74
+ if (this.pgEnv.POOL_IDLE_TIMEOUT != null) {
75
+ bunOptions.idleTimeout = this.pgEnv.POOL_IDLE_TIMEOUT;
76
+ }
77
+ if (this.pgEnv.POOL_CONNECT_TIMEOUT != null) {
78
+ bunOptions.connectionTimeout = this.pgEnv.POOL_CONNECT_TIMEOUT;
79
+ }
80
+ this.client = new Bun.SQL(bunOptions);
71
81
 
72
82
  // Test connection
73
83
  await this.client.unsafe("SELECT 1");
@@ -104,6 +104,13 @@ export class NodePostgresProvider extends PostgresProvider {
104
104
  },
105
105
  };
106
106
 
107
+ // Pool options — only set when explicitly configured via env vars
108
+ if (this.pgEnv.POOL_MAX != null) options.max = this.pgEnv.POOL_MAX;
109
+ if (this.pgEnv.POOL_IDLE_TIMEOUT != null)
110
+ options.idle_timeout = this.pgEnv.POOL_IDLE_TIMEOUT;
111
+ if (this.pgEnv.POOL_CONNECT_TIMEOUT != null)
112
+ options.connect_timeout = this.pgEnv.POOL_CONNECT_TIMEOUT;
113
+
107
114
  // Set search_path at connection level so schema-free migration SQL
108
115
  // resolves to the correct PostgreSQL schema across all pool connections.
109
116
  if (this.schema !== "public") {
@@ -1,26 +1,14 @@
1
1
  import { mkdir } from "node:fs/promises";
2
2
  import { createRequire } from "node:module";
3
3
  import type { PGlite } from "@electric-sql/pglite";
4
- import { $env, $hook, $inject, AlephaError, t } from "alepha";
5
- import { DatabaseProvider, type SQLLike } from "alepha/orm";
4
+ import { $env, $hook, $inject, AlephaError } from "alepha";
5
+ import { DatabaseProvider, databaseEnvSchema, type SQLLike } from "alepha/orm";
6
6
  import { sql } from "drizzle-orm";
7
7
  import type { PgliteDatabase } from "drizzle-orm/pglite";
8
8
  import { migrate } from "drizzle-orm/pglite/migrator";
9
+ import { postgresEnvSchema } from "../schemas/postgresEnvSchema.ts";
9
10
  import { PostgresModelBuilder } from "../services/PostgresModelBuilder.ts";
10
11
 
11
- const envSchema = t.object({
12
- /**
13
- * Same as NodePostgresProvider connection string.
14
- * But, will accept only `file:` protocol for the database path.
15
- *
16
- * DATABASE_URL=memory://
17
- * DATABASE_URL=./db
18
- * DATABASE_URL=file://absolute/path/to/db
19
- */
20
- DATABASE_URL: t.optional(t.text()),
21
- POSTGRES_SCHEMA: t.optional(t.text()),
22
- });
23
-
24
12
  export interface PgLiteModule {
25
13
  PGlite: typeof PGlite;
26
14
  }
@@ -35,10 +23,11 @@ export class PglitePostgresProvider extends DatabaseProvider {
35
23
  }
36
24
 
37
25
  public override get schema(): string {
38
- return this.env.POSTGRES_SCHEMA ?? "public";
26
+ return this.pgEnv.POSTGRES_SCHEMA ?? "public";
39
27
  }
40
28
 
41
- protected readonly env = $env(envSchema);
29
+ protected readonly env = $env(databaseEnvSchema);
30
+ protected readonly pgEnv = $env(postgresEnvSchema);
42
31
  protected readonly builder = $inject(PostgresModelBuilder);
43
32
 
44
33
  protected client?: PGlite;
@@ -54,6 +43,10 @@ export class PglitePostgresProvider extends DatabaseProvider {
54
43
 
55
44
  public override readonly dialect = "postgresql";
56
45
 
46
+ public override get supportsTransactions(): boolean {
47
+ return false;
48
+ }
49
+
57
50
  public override get url(): string {
58
51
  let path = this.env.DATABASE_URL;
59
52
 
@@ -1,49 +1,19 @@
1
- import {
2
- $env,
3
- $hook,
4
- $inject,
5
- $pipeline,
6
- AlephaError,
7
- type Static,
8
- t,
9
- } from "alepha";
1
+ import { $env, $hook, $inject, $pipeline, AlephaError } from "alepha";
10
2
  import { $lock } from "alepha/lock";
11
3
  import {
12
4
  DatabaseProvider,
13
5
  DbError,
14
6
  DbMigrationError,
7
+ databaseEnvSchema,
15
8
  type SQLLike,
16
9
  } from "alepha/orm";
17
10
  import { sql } from "drizzle-orm";
18
11
  import type { PgDatabase } from "drizzle-orm/pg-core";
12
+ import { postgresEnvSchema } from "../schemas/postgresEnvSchema.ts";
19
13
  import { PostgresModelBuilder } from "../services/PostgresModelBuilder.ts";
20
14
 
21
15
  // ---------------------------------------------------------------------------------------------------------------------
22
16
 
23
- const envSchema = t.object({
24
- /**
25
- * Main configuration for database connection.
26
- * Accept a string in the format of a Postgres connection URL.
27
- * Example: postgres://user:password@localhost:5432/database
28
- * or
29
- * Example: postgres://user:password@localhost:5432/database?sslmode=require
30
- */
31
- DATABASE_URL: t.optional(t.text()),
32
-
33
- /**
34
- * In addition to the DATABASE_URL, you can specify the postgres schema name.
35
- *
36
- * It will monkey patch drizzle tables.
37
- */
38
- POSTGRES_SCHEMA: t.optional(t.text()),
39
- });
40
-
41
- declare module "alepha" {
42
- interface Env extends Partial<Static<typeof envSchema>> {}
43
- }
44
-
45
- // ---------------------------------------------------------------------------------------------------------------------
46
-
47
17
  /**
48
18
  * Abstract base class for PostgreSQL database providers.
49
19
  *
@@ -56,7 +26,8 @@ declare module "alepha" {
56
26
  * Subclasses must implement `connect()`, `close()`, and `executeMigrations()`.
57
27
  */
58
28
  export abstract class PostgresProvider extends DatabaseProvider {
59
- protected readonly env = $env(envSchema);
29
+ protected readonly env = $env(databaseEnvSchema);
30
+ protected readonly pgEnv = $env(postgresEnvSchema);
60
31
  protected readonly builder = $inject(PostgresModelBuilder);
61
32
 
62
33
  public override readonly dialect = "postgresql";
@@ -101,8 +72,8 @@ export abstract class PostgresProvider extends DatabaseProvider {
101
72
  return this.schemaForTesting;
102
73
  }
103
74
 
104
- if (this.env.POSTGRES_SCHEMA) {
105
- return this.env.POSTGRES_SCHEMA;
75
+ if (this.pgEnv.POSTGRES_SCHEMA) {
76
+ return this.pgEnv.POSTGRES_SCHEMA;
106
77
  }
107
78
 
108
79
  return "public";
@@ -0,0 +1,32 @@
1
+ import { type Static, t } from "alepha";
2
+
3
+ /**
4
+ * PostgreSQL-specific environment schema.
5
+ *
6
+ * Additional env vars for PostgreSQL providers on top of `databaseEnvSchema`.
7
+ */
8
+ export const postgresEnvSchema = t.object({
9
+ /**
10
+ * PostgreSQL schema name (defaults to `"public"` when unset).
11
+ */
12
+ POSTGRES_SCHEMA: t.optional(t.text()),
13
+
14
+ /**
15
+ * Maximum number of connections in the pool.
16
+ */
17
+ POOL_MAX: t.optional(t.integer()),
18
+
19
+ /**
20
+ * Seconds a connection can be idle before being closed.
21
+ */
22
+ POOL_IDLE_TIMEOUT: t.optional(t.integer()),
23
+
24
+ /**
25
+ * Seconds to wait when establishing a new connection.
26
+ */
27
+ POOL_CONNECT_TIMEOUT: t.optional(t.integer()),
28
+ });
29
+
30
+ declare module "alepha" {
31
+ interface Env extends Partial<Static<typeof postgresEnvSchema>> {}
32
+ }
@@ -5,16 +5,19 @@ import {
5
5
  ModelBuilder,
6
6
  PG_CREATED_AT,
7
7
  PG_ENUM,
8
+ PG_GENERATED,
8
9
  PG_IDENTITY,
9
10
  PG_PRIMARY_KEY,
10
11
  PG_REF,
11
12
  PG_SERIAL,
12
13
  PG_UPDATED_AT,
13
14
  type PgEnumOptions,
15
+ type PgGeneratedOptions,
14
16
  type PgIdentityOptions,
15
17
  type PgRefOptions,
16
18
  type SequencePrimitive,
17
19
  schema,
20
+ type ViewPrimitive,
18
21
  } from "alepha/orm";
19
22
  import type { BuildExtraConfigColumns } from "drizzle-orm";
20
23
  import * as pg from "drizzle-orm/pg-core";
@@ -27,9 +30,11 @@ import {
27
30
  type PgTableExtraConfigValue,
28
31
  type PgTableWithColumns,
29
32
  pgEnum,
33
+ pgMaterializedView,
30
34
  pgSchema,
31
35
  pgSequence,
32
36
  pgTable,
37
+ pgView,
33
38
  unique,
34
39
  uniqueIndex,
35
40
  } from "drizzle-orm/pg-core";
@@ -97,6 +102,36 @@ export class PostgresModelBuilder extends ModelBuilder {
97
102
  options.tables.set(tableName, table);
98
103
  }
99
104
 
105
+ public buildView(
106
+ view: ViewPrimitive,
107
+ options: {
108
+ tables: Map<string, unknown>;
109
+ schema: string;
110
+ },
111
+ ) {
112
+ const viewName = view.name;
113
+ if (options.tables.has(viewName)) {
114
+ return;
115
+ }
116
+
117
+ const columns = this.schemaToPgColumns(
118
+ viewName,
119
+ view.schema,
120
+ { enum: pgEnum, table: pgTable, sequence: pgSequence } as any,
121
+ new Map(),
122
+ options.tables,
123
+ );
124
+
125
+ let drizzleView: unknown;
126
+ if (view.materialized) {
127
+ drizzleView = pgMaterializedView(viewName, columns).existing();
128
+ } else {
129
+ drizzleView = pgView(viewName, columns).existing();
130
+ }
131
+
132
+ options.tables.set(viewName, drizzleView);
133
+ }
134
+
100
135
  public buildSequence(
101
136
  sequence: SequencePrimitive,
102
137
  options: {
@@ -194,6 +229,11 @@ export class PostgresModelBuilder extends ModelBuilder {
194
229
  }, config.actions);
195
230
  }
196
231
 
232
+ if (PG_GENERATED in value) {
233
+ const gen = value[PG_GENERATED] as PgGeneratedOptions;
234
+ col = col.generatedAlwaysAs(gen.expression);
235
+ }
236
+
197
237
  if (schema.required?.includes(key)) {
198
238
  col = col.notNull();
199
239
  }
@@ -12,7 +12,7 @@ export interface ErrorBoundaryProps {
12
12
  * Fallback React node to render when an error is caught.
13
13
  * If not provided, a default error message will be shown.
14
14
  */
15
- fallback: (error: Error) => ReactNode;
15
+ fallback: (error: Error, reset: () => void) => ReactNode;
16
16
 
17
17
  /**
18
18
  * Optional callback that receives the error and error info.
@@ -63,7 +63,10 @@ export class ErrorBoundary extends React.Component<
63
63
 
64
64
  render(): ReactNode {
65
65
  if (this.state.error) {
66
- return this.props.fallback(this.state.error);
66
+ const reset = () => {
67
+ this.setState({ error: undefined });
68
+ };
69
+ return this.props.fallback(this.state.error, reset);
67
70
  }
68
71
 
69
72
  return this.props.children;
@@ -0,0 +1,34 @@
1
+ import { useAlepha } from "alepha/react";
2
+ import { useEffect, useState } from "react";
3
+ import type { BaseInputField } from "../services/FormModel.ts";
4
+
5
+ /**
6
+ * Hook to subscribe to a single form field's value.
7
+ * Only re-renders when this specific field changes.
8
+ *
9
+ * @returns A tuple of [value, setValue] similar to useState.
10
+ */
11
+ export const useFieldValue = (
12
+ input: BaseInputField,
13
+ ): [any, (value: any) => void] => {
14
+ const alepha = useAlepha();
15
+ const [value, setValue] = useState(input?.initialValue);
16
+
17
+ useEffect(() => {
18
+ if (!input?.form || !alepha.isBrowser()) {
19
+ return;
20
+ }
21
+
22
+ return alepha.events.on("form:change", (ev) => {
23
+ if (ev.id === input.form.id && ev.path === input.path) {
24
+ setValue(ev.value);
25
+ }
26
+ });
27
+ }, []);
28
+
29
+ const setFieldValue = (newValue: any) => {
30
+ input.set(newValue);
31
+ };
32
+
33
+ return [value, setFieldValue];
34
+ };
@@ -3,8 +3,20 @@ import { Alepha, t } from "alepha";
3
3
  import { AlephaLogger } from "alepha/logger";
4
4
  import { AlephaContext } from "alepha/react";
5
5
  import type { ReactNode } from "react";
6
+ import { useState } from "react";
6
7
  import { describe, it } from "vitest";
7
- import { useForm } from "../index.ts";
8
+ import { useFieldValue, useForm } from "../index.ts";
9
+
10
+ const TestInput = ({ input, testId }: { input: any; testId: string }) => {
11
+ const [value, setValue] = useFieldValue(input);
12
+ return (
13
+ <input
14
+ data-testid={testId}
15
+ value={value ?? ""}
16
+ onChange={(ev) => setValue(ev.target.value)}
17
+ />
18
+ );
19
+ };
8
20
 
9
21
  describe("useForm", () => {
10
22
  const renderWithAlepha = (alepha: Alepha, element: ReactNode) => {
@@ -29,17 +41,23 @@ describe("useForm", () => {
29
41
  }),
30
42
  }),
31
43
  }),
32
- handler: (values, args) => {
44
+ handler: (values) => {
33
45
  calls.push(values);
34
46
  },
35
47
  });
36
48
 
37
49
  return (
38
50
  <form {...form.props} data-testid="test-form">
39
- <input {...form.input.str.props} />
40
- <input {...form.input.int.props} />
41
- <input {...form.input.nested.items.str.props} />
42
- <input {...form.input.nested.items.another.items.level.props} />
51
+ <TestInput input={form.input.str} testId="test-str" />
52
+ <TestInput input={form.input.int} testId="test-int" />
53
+ <TestInput
54
+ input={form.input.nested.items.str}
55
+ testId="test-nested.str"
56
+ />
57
+ <TestInput
58
+ input={form.input.nested.items.another.items.level}
59
+ testId="test-nested.another.level"
60
+ />
43
61
  <button type="submit">Submit</button>
44
62
  </form>
45
63
  );
@@ -312,9 +330,18 @@ describe("useForm", () => {
312
330
 
313
331
  return (
314
332
  <form {...form.props} data-testid="complex-form">
315
- <input {...form.input.company.items.name.props} />
316
- <input {...form.input.company.items.address.items.street.props} />
317
- <input {...form.input.company.items.address.items.city.props} />
333
+ <TestInput
334
+ input={form.input.company.items.name}
335
+ testId="complex-test-company.name"
336
+ />
337
+ <TestInput
338
+ input={form.input.company.items.address.items.street}
339
+ testId="complex-test-company.address.street"
340
+ />
341
+ <TestInput
342
+ input={form.input.company.items.address.items.city}
343
+ testId="complex-test-company.address.city"
344
+ />
318
345
  <button
319
346
  type="button"
320
347
  data-testid="set-employees"
@@ -363,4 +390,62 @@ describe("useForm", () => {
363
390
  ],
364
391
  });
365
392
  });
393
+
394
+ it("should update initialValues after save so reset uses new values", async ({
395
+ expect,
396
+ }) => {
397
+ const alepha = Alepha.create().with(AlephaLogger);
398
+
399
+ const Form = () => {
400
+ const [saved, setSaved] = useState({ name: "original" });
401
+
402
+ const form = useForm({
403
+ id: "reset-test",
404
+ schema: t.object({
405
+ name: t.text(),
406
+ }),
407
+ initialValues: saved,
408
+ handler: async (values) => {
409
+ setSaved({ ...values });
410
+ },
411
+ });
412
+
413
+ return (
414
+ <form {...form.props} data-testid="reset-form">
415
+ <TestInput input={form.input.name} testId="reset-name" />
416
+ <button type="submit">Save</button>
417
+ <button type="reset">Reset</button>
418
+ </form>
419
+ );
420
+ };
421
+
422
+ await alepha.start();
423
+ const ui = renderWithAlepha(alepha, <Form />);
424
+
425
+ const input = () =>
426
+ (ui.getByTestId("reset-name") as HTMLInputElement).value;
427
+
428
+ // Initial value
429
+ expect(input()).toBe("original");
430
+
431
+ // Edit and save
432
+ fireEvent.change(ui.getByTestId("reset-name"), {
433
+ target: { value: "updated" },
434
+ });
435
+ fireEvent.submit(ui.getByText("Save"));
436
+ await new Promise((resolve) => setTimeout(resolve, 100));
437
+
438
+ // After save, initialValues should be updated
439
+ // Edit again
440
+ fireEvent.change(ui.getByTestId("reset-name"), {
441
+ target: { value: "temporary" },
442
+ });
443
+ expect(input()).toBe("temporary");
444
+
445
+ // Reset should go back to saved value, not original
446
+ fireEvent.click(ui.getByText("Reset"));
447
+ await new Promise((resolve) => setTimeout(resolve, 100));
448
+
449
+ expect(input()).toBe("updated");
450
+ });
366
451
  });
@@ -1,6 +1,6 @@
1
1
  import type { TObject } from "alepha";
2
2
  import { useAlepha } from "alepha/react";
3
- import { useId, useMemo } from "react";
3
+ import { useEffect, useId, useMemo, useRef } from "react";
4
4
  import { type FormCtrlOptions, FormModel } from "../services/FormModel.ts";
5
5
 
6
6
  /**
@@ -37,11 +37,23 @@ export const useForm = <T extends TObject>(
37
37
  ): FormModel<T> => {
38
38
  const alepha = useAlepha();
39
39
  const formId = useId();
40
+ const initialValuesRef = useRef(options.initialValues);
40
41
 
41
- return useMemo(() => {
42
+ const form = useMemo(() => {
42
43
  return alepha.inject(FormModel<T>, {
43
44
  lifetime: "transient",
44
45
  args: [options.id || formId, options],
45
46
  });
46
47
  }, deps);
48
+
49
+ useEffect(() => {
50
+ if (initialValuesRef.current !== options.initialValues) {
51
+ initialValuesRef.current = options.initialValues;
52
+ if (options.initialValues) {
53
+ form.setInitialValues(options.initialValues as Record<string, any>);
54
+ }
55
+ }
56
+ }, [options.initialValues]);
57
+
58
+ return form;
47
59
  };
@@ -58,16 +58,6 @@ export const useFormState = <
58
58
  );
59
59
  }
60
60
 
61
- if (hasValues) {
62
- listeners.push(
63
- alepha.events.on("form:reset", (event) => {
64
- if (event.id === form.id) {
65
- setValues(event.values);
66
- }
67
- }),
68
- );
69
- }
70
-
71
61
  if (hasLoading) {
72
62
  listeners.push(
73
63
  alepha.events.on("form:submit:begin", (event) => {
@@ -98,6 +88,16 @@ export const useFormState = <
98
88
  );
99
89
  }
100
90
 
91
+ if (hasDirty) {
92
+ listeners.push(
93
+ alepha.events.on("form:reset", (event) => {
94
+ if (event.id === form.id) {
95
+ setDirty(false);
96
+ }
97
+ }),
98
+ );
99
+ }
100
+
101
101
  if (hasErrors) {
102
102
  listeners.push(
103
103
  alepha.events.on("form:submit:error", (event) => {
@@ -0,0 +1,29 @@
1
+ import type { TObject } from "alepha";
2
+ import { useAlepha } from "alepha/react";
3
+ import { useEffect, useState } from "react";
4
+ import type { FormModel } from "../services/FormModel.ts";
5
+
6
+ /**
7
+ * Hook to subscribe to all form values.
8
+ * Re-renders on every field change — use only when needed (debug panels, live previews).
9
+ */
10
+ export const useFormValues = <T extends TObject>(
11
+ form: FormModel<T>,
12
+ ): Record<string, any> => {
13
+ const alepha = useAlepha();
14
+ const [values, setValues] = useState<Record<string, any>>(form.currentValues);
15
+
16
+ useEffect(() => {
17
+ if (!alepha.isBrowser()) {
18
+ return;
19
+ }
20
+
21
+ return alepha.events.on("form:change", (ev) => {
22
+ if (ev.id === form.id) {
23
+ setValues(form.currentValues);
24
+ }
25
+ });
26
+ }, []);
27
+
28
+ return values;
29
+ };
@@ -4,8 +4,10 @@ import { $module } from "alepha";
4
4
 
5
5
  export { default as FormState } from "./components/FormState.tsx";
6
6
  export * from "./errors/FormValidationError.ts";
7
+ export * from "./hooks/useFieldValue.ts";
7
8
  export * from "./hooks/useForm.ts";
8
9
  export * from "./hooks/useFormState.ts";
10
+ export * from "./hooks/useFormValues.ts";
9
11
  export * from "./services/FormModel.ts";
10
12
 
11
13
  // ---------------------------------------------------------------------------------------------------------------------
@@ -13,11 +15,11 @@ export * from "./services/FormModel.ts";
13
15
  declare module "alepha" {
14
16
  interface Hooks {
15
17
  "form:change": { id: string; path: string; value: any };
16
- "form:reset": { id: string; values: Record<string, any> };
17
18
  "form:submit:begin": { id: string };
18
19
  "form:submit:success": { id: string; values: Record<string, any> };
19
20
  "form:submit:error": { id: string; error: Error };
20
21
  "form:submit:end": { id: string };
22
+ "form:reset": { id: string };
21
23
  }
22
24
  }
23
25