alepha 0.15.1 → 0.15.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 (523) hide show
  1. package/README.md +68 -80
  2. package/dist/api/audits/index.d.ts +10 -33
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js +10 -33
  5. package/dist/api/audits/index.js.map +1 -1
  6. package/dist/api/files/index.d.ts +10 -3
  7. package/dist/api/files/index.d.ts.map +1 -1
  8. package/dist/api/files/index.js +10 -3
  9. package/dist/api/files/index.js.map +1 -1
  10. package/dist/api/jobs/index.d.ts +162 -155
  11. package/dist/api/jobs/index.d.ts.map +1 -1
  12. package/dist/api/jobs/index.js +10 -3
  13. package/dist/api/jobs/index.js.map +1 -1
  14. package/dist/api/keys/index.d.ts +413 -0
  15. package/dist/api/keys/index.d.ts.map +1 -0
  16. package/dist/api/keys/index.js +476 -0
  17. package/dist/api/keys/index.js.map +1 -0
  18. package/dist/api/notifications/index.d.ts +10 -4
  19. package/dist/api/notifications/index.d.ts.map +1 -1
  20. package/dist/api/notifications/index.js +10 -4
  21. package/dist/api/notifications/index.js.map +1 -1
  22. package/dist/api/parameters/index.d.ts +43 -50
  23. package/dist/api/parameters/index.d.ts.map +1 -1
  24. package/dist/api/parameters/index.js +30 -37
  25. package/dist/api/parameters/index.js.map +1 -1
  26. package/dist/api/users/index.d.ts +1081 -760
  27. package/dist/api/users/index.d.ts.map +1 -1
  28. package/dist/api/users/index.js +2539 -218
  29. package/dist/api/users/index.js.map +1 -1
  30. package/dist/api/verifications/index.d.ts +138 -132
  31. package/dist/api/verifications/index.d.ts.map +1 -1
  32. package/dist/api/verifications/index.js +12 -4
  33. package/dist/api/verifications/index.js.map +1 -1
  34. package/dist/batch/index.d.ts +20 -40
  35. package/dist/batch/index.d.ts.map +1 -1
  36. package/dist/batch/index.js +31 -44
  37. package/dist/batch/index.js.map +1 -1
  38. package/dist/bucket/index.d.ts +440 -8
  39. package/dist/bucket/index.d.ts.map +1 -1
  40. package/dist/bucket/index.js +1861 -12
  41. package/dist/bucket/index.js.map +1 -1
  42. package/dist/cache/core/index.d.ts +179 -7
  43. package/dist/cache/core/index.d.ts.map +1 -1
  44. package/dist/cache/core/index.js +213 -7
  45. package/dist/cache/core/index.js.map +1 -1
  46. package/dist/cache/redis/index.d.ts +1 -0
  47. package/dist/cache/redis/index.d.ts.map +1 -1
  48. package/dist/cache/redis/index.js +4 -0
  49. package/dist/cache/redis/index.js.map +1 -1
  50. package/dist/cli/index.d.ts +638 -5645
  51. package/dist/cli/index.d.ts.map +1 -1
  52. package/dist/cli/index.js +2550 -368
  53. package/dist/cli/index.js.map +1 -1
  54. package/dist/command/index.d.ts +203 -45
  55. package/dist/command/index.d.ts.map +1 -1
  56. package/dist/command/index.js +2060 -71
  57. package/dist/command/index.js.map +1 -1
  58. package/dist/core/index.browser.js +70 -40
  59. package/dist/core/index.browser.js.map +1 -1
  60. package/dist/core/index.d.ts +34 -13
  61. package/dist/core/index.d.ts.map +1 -1
  62. package/dist/core/index.js +90 -40
  63. package/dist/core/index.js.map +1 -1
  64. package/dist/core/index.native.js +70 -40
  65. package/dist/core/index.native.js.map +1 -1
  66. package/dist/datetime/index.d.ts +15 -0
  67. package/dist/datetime/index.d.ts.map +1 -1
  68. package/dist/datetime/index.js +15 -0
  69. package/dist/datetime/index.js.map +1 -1
  70. package/dist/email/index.d.ts +323 -20
  71. package/dist/email/index.d.ts.map +1 -1
  72. package/dist/email/index.js +1857 -7
  73. package/dist/email/index.js.map +1 -1
  74. package/dist/fake/index.d.ts +90 -8
  75. package/dist/fake/index.d.ts.map +1 -1
  76. package/dist/fake/index.js +91 -20
  77. package/dist/fake/index.js.map +1 -1
  78. package/dist/lock/core/index.d.ts +11 -4
  79. package/dist/lock/core/index.d.ts.map +1 -1
  80. package/dist/lock/core/index.js +11 -4
  81. package/dist/lock/core/index.js.map +1 -1
  82. package/dist/logger/index.d.ts +17 -66
  83. package/dist/logger/index.d.ts.map +1 -1
  84. package/dist/logger/index.js +14 -63
  85. package/dist/logger/index.js.map +1 -1
  86. package/dist/mcp/index.d.ts +10 -30
  87. package/dist/mcp/index.d.ts.map +1 -1
  88. package/dist/mcp/index.js +12 -35
  89. package/dist/mcp/index.js.map +1 -1
  90. package/dist/orm/index.browser.js +3 -3
  91. package/dist/orm/index.browser.js.map +1 -1
  92. package/dist/orm/index.bun.js +39 -20
  93. package/dist/orm/index.bun.js.map +1 -1
  94. package/dist/orm/index.d.ts +517 -540
  95. package/dist/orm/index.d.ts.map +1 -1
  96. package/dist/orm/index.js +58 -71
  97. package/dist/orm/index.js.map +1 -1
  98. package/dist/queue/core/index.d.ts +18 -10
  99. package/dist/queue/core/index.d.ts.map +1 -1
  100. package/dist/queue/core/index.js +14 -6
  101. package/dist/queue/core/index.js.map +1 -1
  102. package/dist/react/auth/index.browser.js +108 -0
  103. package/dist/react/auth/index.browser.js.map +1 -0
  104. package/dist/react/auth/index.d.ts +100 -0
  105. package/dist/react/auth/index.d.ts.map +1 -0
  106. package/dist/react/auth/index.js +145 -0
  107. package/dist/react/auth/index.js.map +1 -0
  108. package/dist/react/core/index.d.ts +469 -0
  109. package/dist/react/core/index.d.ts.map +1 -0
  110. package/dist/react/core/index.js +464 -0
  111. package/dist/react/core/index.js.map +1 -0
  112. package/dist/react/form/index.d.ts +232 -0
  113. package/dist/react/form/index.d.ts.map +1 -0
  114. package/dist/react/form/index.js +432 -0
  115. package/dist/react/form/index.js.map +1 -0
  116. package/dist/react/head/index.browser.js +423 -0
  117. package/dist/react/head/index.browser.js.map +1 -0
  118. package/dist/react/head/index.d.ts +288 -0
  119. package/dist/react/head/index.d.ts.map +1 -0
  120. package/dist/react/head/index.js +465 -0
  121. package/dist/react/head/index.js.map +1 -0
  122. package/dist/react/i18n/index.d.ts +175 -0
  123. package/dist/react/i18n/index.d.ts.map +1 -0
  124. package/dist/react/i18n/index.js +224 -0
  125. package/dist/react/i18n/index.js.map +1 -0
  126. package/dist/react/router/index.browser.js +1974 -0
  127. package/dist/react/router/index.browser.js.map +1 -0
  128. package/dist/react/router/index.d.ts +1956 -0
  129. package/dist/react/router/index.d.ts.map +1 -0
  130. package/dist/react/router/index.js +4722 -0
  131. package/dist/react/router/index.js.map +1 -0
  132. package/dist/react/websocket/index.d.ts +117 -0
  133. package/dist/react/websocket/index.d.ts.map +1 -0
  134. package/dist/react/websocket/index.js +107 -0
  135. package/dist/react/websocket/index.js.map +1 -0
  136. package/dist/redis/index.bun.js +4 -0
  137. package/dist/redis/index.bun.js.map +1 -1
  138. package/dist/redis/index.d.ts +41 -44
  139. package/dist/redis/index.d.ts.map +1 -1
  140. package/dist/redis/index.js +16 -25
  141. package/dist/redis/index.js.map +1 -1
  142. package/dist/retry/index.d.ts +11 -2
  143. package/dist/retry/index.d.ts.map +1 -1
  144. package/dist/retry/index.js +11 -2
  145. package/dist/retry/index.js.map +1 -1
  146. package/dist/scheduler/index.d.ts +11 -2
  147. package/dist/scheduler/index.d.ts.map +1 -1
  148. package/dist/scheduler/index.js +11 -2
  149. package/dist/scheduler/index.js.map +1 -1
  150. package/dist/security/index.d.ts +140 -49
  151. package/dist/security/index.d.ts.map +1 -1
  152. package/dist/security/index.js +164 -32
  153. package/dist/security/index.js.map +1 -1
  154. package/dist/server/auth/index.d.ts +12 -7
  155. package/dist/server/auth/index.d.ts.map +1 -1
  156. package/dist/server/auth/index.js +12 -7
  157. package/dist/server/auth/index.js.map +1 -1
  158. package/dist/server/cache/index.d.ts +7 -22
  159. package/dist/server/cache/index.d.ts.map +1 -1
  160. package/dist/server/cache/index.js +7 -22
  161. package/dist/server/cache/index.js.map +1 -1
  162. package/dist/server/compress/index.d.ts +10 -2
  163. package/dist/server/compress/index.d.ts.map +1 -1
  164. package/dist/server/compress/index.js +10 -2
  165. package/dist/server/compress/index.js.map +1 -1
  166. package/dist/server/cookies/index.d.ts +40 -16
  167. package/dist/server/cookies/index.d.ts.map +1 -1
  168. package/dist/server/cookies/index.js +7 -5
  169. package/dist/server/cookies/index.js.map +1 -1
  170. package/dist/server/core/index.d.ts +124 -23
  171. package/dist/server/core/index.d.ts.map +1 -1
  172. package/dist/server/core/index.js +231 -14
  173. package/dist/server/core/index.js.map +1 -1
  174. package/dist/server/cors/index.d.ts +13 -23
  175. package/dist/server/cors/index.d.ts.map +1 -1
  176. package/dist/server/cors/index.js +7 -21
  177. package/dist/server/cors/index.js.map +1 -1
  178. package/dist/server/health/index.d.ts +8 -2
  179. package/dist/server/health/index.d.ts.map +1 -1
  180. package/dist/server/health/index.js +8 -2
  181. package/dist/server/health/index.js.map +1 -1
  182. package/dist/server/helmet/index.d.ts +11 -3
  183. package/dist/server/helmet/index.d.ts.map +1 -1
  184. package/dist/server/helmet/index.js +11 -3
  185. package/dist/server/helmet/index.js.map +1 -1
  186. package/dist/server/links/index.d.ts +11 -6
  187. package/dist/server/links/index.d.ts.map +1 -1
  188. package/dist/server/links/index.js +11 -6
  189. package/dist/server/links/index.js.map +1 -1
  190. package/dist/server/metrics/index.d.ts +10 -3
  191. package/dist/server/metrics/index.d.ts.map +1 -1
  192. package/dist/server/metrics/index.js +10 -3
  193. package/dist/server/metrics/index.js.map +1 -1
  194. package/dist/server/multipart/index.d.ts +9 -3
  195. package/dist/server/multipart/index.d.ts.map +1 -1
  196. package/dist/server/multipart/index.js +9 -3
  197. package/dist/server/multipart/index.js.map +1 -1
  198. package/dist/server/proxy/index.d.ts +8 -2
  199. package/dist/server/proxy/index.d.ts.map +1 -1
  200. package/dist/server/proxy/index.js +8 -2
  201. package/dist/server/proxy/index.js.map +1 -1
  202. package/dist/server/rate-limit/index.d.ts +30 -35
  203. package/dist/server/rate-limit/index.d.ts.map +1 -1
  204. package/dist/server/rate-limit/index.js +18 -55
  205. package/dist/server/rate-limit/index.js.map +1 -1
  206. package/dist/server/static/index.d.ts +137 -4
  207. package/dist/server/static/index.d.ts.map +1 -1
  208. package/dist/server/static/index.js +1853 -5
  209. package/dist/server/static/index.js.map +1 -1
  210. package/dist/server/swagger/index.d.ts +309 -6
  211. package/dist/server/swagger/index.d.ts.map +1 -1
  212. package/dist/server/swagger/index.js +1854 -6
  213. package/dist/server/swagger/index.js.map +1 -1
  214. package/dist/sms/index.d.ts +309 -7
  215. package/dist/sms/index.d.ts.map +1 -1
  216. package/dist/sms/index.js +1856 -7
  217. package/dist/sms/index.js.map +1 -1
  218. package/dist/system/index.browser.js +1218 -0
  219. package/dist/system/index.browser.js.map +1 -0
  220. package/dist/{file → system}/index.d.ts +343 -16
  221. package/dist/system/index.d.ts.map +1 -0
  222. package/dist/{file → system}/index.js +419 -22
  223. package/dist/system/index.js.map +1 -0
  224. package/dist/thread/index.d.ts +11 -2
  225. package/dist/thread/index.d.ts.map +1 -1
  226. package/dist/thread/index.js +11 -2
  227. package/dist/thread/index.js.map +1 -1
  228. package/dist/topic/core/index.d.ts +12 -5
  229. package/dist/topic/core/index.d.ts.map +1 -1
  230. package/dist/topic/core/index.js +12 -5
  231. package/dist/topic/core/index.js.map +1 -1
  232. package/dist/vite/index.d.ts +5 -6272
  233. package/dist/vite/index.d.ts.map +1 -1
  234. package/dist/vite/index.js +23 -10
  235. package/dist/vite/index.js.map +1 -1
  236. package/dist/websocket/index.d.ts +12 -8
  237. package/dist/websocket/index.d.ts.map +1 -1
  238. package/dist/websocket/index.js +12 -8
  239. package/dist/websocket/index.js.map +1 -1
  240. package/package.json +82 -11
  241. package/src/api/audits/index.ts +10 -33
  242. package/src/api/files/__tests__/$bucket.spec.ts +1 -1
  243. package/src/api/files/controllers/AdminFileStatsController.spec.ts +1 -1
  244. package/src/api/files/controllers/FileController.spec.ts +1 -1
  245. package/src/api/files/index.ts +10 -3
  246. package/src/api/files/jobs/FileJobs.spec.ts +1 -1
  247. package/src/api/files/services/FileService.spec.ts +1 -1
  248. package/src/api/jobs/index.ts +10 -3
  249. package/src/api/keys/controllers/AdminApiKeyController.ts +75 -0
  250. package/src/api/keys/controllers/ApiKeyController.ts +103 -0
  251. package/src/api/keys/entities/apiKeyEntity.ts +41 -0
  252. package/src/api/keys/index.ts +49 -0
  253. package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +7 -0
  254. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +17 -0
  255. package/src/api/keys/schemas/createApiKeyBodySchema.ts +7 -0
  256. package/src/api/keys/schemas/createApiKeyResponseSchema.ts +11 -0
  257. package/src/api/keys/schemas/listApiKeyResponseSchema.ts +15 -0
  258. package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +5 -0
  259. package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +5 -0
  260. package/src/api/keys/services/ApiKeyService.spec.ts +553 -0
  261. package/src/api/keys/services/ApiKeyService.ts +306 -0
  262. package/src/api/logs/TODO.md +55 -0
  263. package/src/api/notifications/index.ts +10 -4
  264. package/src/api/parameters/index.ts +9 -30
  265. package/src/api/parameters/primitives/$config.ts +12 -4
  266. package/src/api/parameters/services/ConfigStore.ts +9 -3
  267. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1035 -0
  268. package/src/api/users/__tests__/ApiKeys.spec.ts +401 -0
  269. package/src/api/users/index.ts +14 -3
  270. package/src/api/users/primitives/$realm.ts +33 -5
  271. package/src/api/users/providers/RealmProvider.ts +1 -12
  272. package/src/api/users/services/SessionService.ts +1 -1
  273. package/src/api/verifications/controllers/VerificationController.ts +2 -0
  274. package/src/api/verifications/index.ts +10 -4
  275. package/src/batch/index.ts +9 -36
  276. package/src/batch/primitives/$batch.ts +0 -8
  277. package/src/batch/providers/BatchProvider.ts +29 -2
  278. package/src/bucket/__tests__/shared.ts +1 -1
  279. package/src/bucket/index.ts +13 -6
  280. package/src/bucket/primitives/$bucket.ts +1 -1
  281. package/src/bucket/providers/LocalFileStorageProvider.ts +1 -1
  282. package/src/bucket/providers/MemoryFileStorageProvider.ts +1 -1
  283. package/src/cache/core/__tests__/shared.ts +30 -0
  284. package/src/cache/core/index.ts +11 -6
  285. package/src/cache/core/primitives/$cache.spec.ts +5 -0
  286. package/src/cache/core/providers/CacheProvider.ts +17 -0
  287. package/src/cache/core/providers/MemoryCacheProvider.ts +300 -1
  288. package/src/cache/redis/__tests__/cache-redis.spec.ts +5 -0
  289. package/src/cache/redis/providers/RedisCacheProvider.ts +9 -0
  290. package/src/cli/apps/AlephaCli.ts +1 -14
  291. package/src/cli/apps/AlephaPackageBuilderCli.ts +10 -1
  292. package/src/cli/atoms/buildOptions.ts +99 -9
  293. package/src/cli/commands/build.ts +150 -37
  294. package/src/cli/commands/db.ts +22 -18
  295. package/src/cli/commands/deploy.ts +1 -1
  296. package/src/cli/commands/dev.ts +1 -20
  297. package/src/cli/commands/gen/env.ts +5 -2
  298. package/src/cli/commands/gen/openapi.ts +5 -2
  299. package/src/cli/commands/init.spec.ts +588 -0
  300. package/src/cli/commands/init.ts +115 -58
  301. package/src/cli/commands/lint.ts +7 -1
  302. package/src/cli/commands/typecheck.ts +11 -0
  303. package/src/cli/providers/AppEntryProvider.ts +1 -1
  304. package/src/cli/providers/ViteBuildProvider.ts +8 -50
  305. package/src/cli/providers/ViteDevServerProvider.ts +35 -16
  306. package/src/cli/services/AlephaCliUtils.ts +52 -121
  307. package/src/cli/services/PackageManagerUtils.ts +129 -11
  308. package/src/cli/services/ProjectScaffolder.spec.ts +97 -0
  309. package/src/cli/services/ProjectScaffolder.ts +148 -81
  310. package/src/cli/services/ViteUtils.ts +82 -0
  311. package/src/cli/{assets/claudeMd.ts → templates/agentMd.ts} +37 -24
  312. package/src/cli/templates/apiAppSecurityTs.ts +11 -0
  313. package/src/cli/templates/apiIndexTs.ts +30 -0
  314. package/src/cli/templates/gitignore.ts +39 -0
  315. package/src/cli/{assets → templates}/mainCss.ts +11 -2
  316. package/src/cli/templates/mainServerTs.ts +33 -0
  317. package/src/cli/templates/webAppRouterTs.ts +74 -0
  318. package/src/cli/templates/webHelloComponentTsx.ts +30 -0
  319. package/src/command/helpers/Runner.spec.ts +139 -0
  320. package/src/command/helpers/Runner.ts +7 -22
  321. package/src/command/index.ts +12 -4
  322. package/src/command/providers/CliProvider.spec.ts +1392 -0
  323. package/src/command/providers/CliProvider.ts +320 -47
  324. package/src/core/Alepha.ts +34 -27
  325. package/src/core/__tests__/Alepha-start.spec.ts +4 -4
  326. package/src/core/helpers/jsonSchemaToTypeBox.spec.ts +771 -0
  327. package/src/core/helpers/jsonSchemaToTypeBox.ts +62 -10
  328. package/src/core/index.shared.ts +1 -0
  329. package/src/core/index.ts +20 -0
  330. package/src/core/providers/EventManager.spec.ts +0 -71
  331. package/src/core/providers/EventManager.ts +3 -15
  332. package/src/core/providers/Json.ts +2 -14
  333. package/src/datetime/index.ts +15 -0
  334. package/src/email/index.ts +10 -5
  335. package/src/email/providers/LocalEmailProvider.spec.ts +1 -1
  336. package/src/email/providers/LocalEmailProvider.ts +1 -1
  337. package/src/fake/__tests__/keyName.example.ts +1 -1
  338. package/src/fake/__tests__/keyName.spec.ts +5 -5
  339. package/src/fake/index.ts +9 -6
  340. package/src/fake/providers/FakeProvider.spec.ts +258 -40
  341. package/src/fake/providers/FakeProvider.ts +133 -19
  342. package/src/lock/core/index.ts +11 -4
  343. package/src/logger/index.ts +17 -66
  344. package/src/mcp/index.ts +10 -27
  345. package/src/mcp/transports/SseMcpTransport.ts +0 -11
  346. package/src/orm/__tests__/PostgresProvider.spec.ts +2 -2
  347. package/src/orm/index.browser.ts +2 -2
  348. package/src/orm/index.bun.ts +5 -3
  349. package/src/orm/index.ts +23 -53
  350. package/src/orm/providers/drivers/BunSqliteProvider.ts +5 -1
  351. package/src/orm/providers/drivers/CloudflareD1Provider.ts +57 -30
  352. package/src/orm/providers/drivers/DatabaseProvider.ts +9 -1
  353. package/src/orm/providers/drivers/NodeSqliteProvider.ts +4 -1
  354. package/src/orm/services/Repository.ts +7 -3
  355. package/src/queue/core/index.ts +14 -6
  356. package/src/react/auth/__tests__/$auth.spec.ts +202 -0
  357. package/src/react/auth/hooks/useAuth.ts +32 -0
  358. package/src/react/auth/index.browser.ts +13 -0
  359. package/src/react/auth/index.shared.ts +2 -0
  360. package/src/react/auth/index.ts +48 -0
  361. package/src/react/auth/providers/ReactAuthProvider.ts +16 -0
  362. package/src/react/auth/services/ReactAuth.ts +135 -0
  363. package/src/react/core/__tests__/Router.spec.tsx +169 -0
  364. package/src/react/core/components/ClientOnly.tsx +49 -0
  365. package/src/react/core/components/ErrorBoundary.tsx +73 -0
  366. package/src/react/core/contexts/AlephaContext.ts +7 -0
  367. package/src/react/core/contexts/AlephaProvider.tsx +42 -0
  368. package/src/react/core/hooks/useAction.browser.spec.tsx +569 -0
  369. package/src/react/core/hooks/useAction.ts +480 -0
  370. package/src/react/core/hooks/useAlepha.ts +26 -0
  371. package/src/react/core/hooks/useClient.ts +17 -0
  372. package/src/react/core/hooks/useEvents.ts +51 -0
  373. package/src/react/core/hooks/useInject.ts +12 -0
  374. package/src/react/core/hooks/useStore.ts +52 -0
  375. package/src/react/core/index.ts +90 -0
  376. package/src/react/form/components/FormState.tsx +17 -0
  377. package/src/react/form/errors/FormValidationError.ts +18 -0
  378. package/src/react/form/hooks/useForm.browser.spec.tsx +366 -0
  379. package/src/react/form/hooks/useForm.ts +47 -0
  380. package/src/react/form/hooks/useFormState.ts +130 -0
  381. package/src/react/form/index.ts +44 -0
  382. package/src/react/form/services/FormModel.ts +614 -0
  383. package/src/react/head/helpers/SeoExpander.spec.ts +203 -0
  384. package/src/react/head/helpers/SeoExpander.ts +142 -0
  385. package/src/react/head/hooks/useHead.spec.tsx +288 -0
  386. package/src/react/head/hooks/useHead.ts +62 -0
  387. package/src/react/head/index.browser.ts +26 -0
  388. package/src/react/head/index.ts +44 -0
  389. package/src/react/head/interfaces/Head.ts +105 -0
  390. package/src/react/head/primitives/$head.ts +25 -0
  391. package/src/react/head/providers/BrowserHeadProvider.browser.spec.ts +196 -0
  392. package/src/react/head/providers/BrowserHeadProvider.ts +212 -0
  393. package/src/react/head/providers/HeadProvider.ts +168 -0
  394. package/src/react/head/providers/ServerHeadProvider.ts +31 -0
  395. package/src/react/i18n/__tests__/integration.spec.tsx +239 -0
  396. package/src/react/i18n/components/Localize.spec.tsx +357 -0
  397. package/src/react/i18n/components/Localize.tsx +35 -0
  398. package/src/react/i18n/hooks/useI18n.browser.spec.tsx +438 -0
  399. package/src/react/i18n/hooks/useI18n.ts +18 -0
  400. package/src/react/i18n/index.ts +41 -0
  401. package/src/react/i18n/primitives/$dictionary.ts +69 -0
  402. package/src/react/i18n/providers/I18nProvider.spec.ts +389 -0
  403. package/src/react/i18n/providers/I18nProvider.ts +278 -0
  404. package/src/react/router/__tests__/page-head-browser.browser.spec.ts +95 -0
  405. package/src/react/router/__tests__/page-head.spec.ts +48 -0
  406. package/src/react/router/__tests__/seo-head.spec.ts +125 -0
  407. package/src/react/router/atoms/ssrManifestAtom.ts +58 -0
  408. package/src/react/router/components/ErrorViewer.tsx +872 -0
  409. package/src/react/router/components/Link.tsx +23 -0
  410. package/src/react/router/components/NestedView.tsx +223 -0
  411. package/src/react/router/components/NotFound.tsx +30 -0
  412. package/src/react/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
  413. package/src/react/router/contexts/RouterLayerContext.ts +12 -0
  414. package/src/react/router/errors/Redirection.ts +28 -0
  415. package/src/react/router/hooks/useActive.ts +52 -0
  416. package/src/react/router/hooks/useQueryParams.ts +63 -0
  417. package/src/react/router/hooks/useRouter.ts +20 -0
  418. package/src/react/router/hooks/useRouterState.ts +11 -0
  419. package/src/react/router/index.browser.ts +45 -0
  420. package/src/react/router/index.shared.ts +19 -0
  421. package/src/react/router/index.ts +146 -0
  422. package/src/react/router/primitives/$page.browser.spec.tsx +851 -0
  423. package/src/react/router/primitives/$page.spec.tsx +676 -0
  424. package/src/react/router/primitives/$page.ts +489 -0
  425. package/src/react/router/providers/ReactBrowserProvider.ts +312 -0
  426. package/src/react/router/providers/ReactBrowserRendererProvider.ts +25 -0
  427. package/src/react/router/providers/ReactBrowserRouterProvider.ts +168 -0
  428. package/src/react/router/providers/ReactPageProvider.ts +726 -0
  429. package/src/react/router/providers/ReactPreloadProvider.spec.ts +142 -0
  430. package/src/react/router/providers/ReactPreloadProvider.ts +85 -0
  431. package/src/react/router/providers/ReactServerProvider.spec.tsx +316 -0
  432. package/src/react/router/providers/ReactServerProvider.ts +487 -0
  433. package/src/react/router/providers/ReactServerTemplateProvider.spec.ts +210 -0
  434. package/src/react/router/providers/ReactServerTemplateProvider.ts +542 -0
  435. package/src/react/router/providers/SSRManifestProvider.ts +334 -0
  436. package/src/react/router/services/ReactPageServerService.ts +48 -0
  437. package/src/react/router/services/ReactPageService.ts +27 -0
  438. package/src/react/router/services/ReactRouter.ts +262 -0
  439. package/src/react/websocket/hooks/useRoom.tsx +242 -0
  440. package/src/react/websocket/index.ts +7 -0
  441. package/src/redis/__tests__/redis.spec.ts +13 -0
  442. package/src/redis/index.ts +9 -25
  443. package/src/redis/providers/BunRedisProvider.ts +9 -0
  444. package/src/redis/providers/NodeRedisProvider.ts +8 -0
  445. package/src/redis/providers/RedisProvider.ts +16 -0
  446. package/src/retry/index.ts +11 -2
  447. package/src/router/index.ts +15 -0
  448. package/src/scheduler/index.ts +11 -2
  449. package/src/security/__tests__/BasicAuth.spec.ts +2 -0
  450. package/src/security/__tests__/ServerSecurityProvider.spec.ts +90 -5
  451. package/src/security/index.ts +15 -10
  452. package/src/security/interfaces/IssuerResolver.ts +27 -0
  453. package/src/security/primitives/$issuer.ts +55 -0
  454. package/src/security/providers/SecurityProvider.ts +179 -0
  455. package/src/security/providers/ServerBasicAuthProvider.ts +6 -2
  456. package/src/security/providers/ServerSecurityProvider.ts +63 -41
  457. package/src/server/auth/index.ts +12 -7
  458. package/src/server/cache/index.ts +7 -22
  459. package/src/server/compress/index.ts +10 -2
  460. package/src/server/cookies/index.ts +7 -5
  461. package/src/server/cookies/primitives/$cookie.ts +33 -11
  462. package/src/server/core/index.ts +16 -6
  463. package/src/server/core/interfaces/ServerRequest.ts +83 -1
  464. package/src/server/core/primitives/$action.spec.ts +1 -1
  465. package/src/server/core/primitives/$action.ts +8 -3
  466. package/src/server/core/providers/NodeHttpServerProvider.spec.ts +9 -3
  467. package/src/server/core/providers/NodeHttpServerProvider.ts +9 -3
  468. package/src/server/core/services/ServerRequestParser.spec.ts +520 -0
  469. package/src/server/core/services/ServerRequestParser.ts +306 -13
  470. package/src/server/cors/index.ts +7 -21
  471. package/src/server/cors/primitives/$cors.ts +6 -2
  472. package/src/server/health/index.ts +8 -2
  473. package/src/server/helmet/index.ts +11 -3
  474. package/src/server/links/index.ts +11 -6
  475. package/src/server/metrics/index.ts +10 -3
  476. package/src/server/multipart/index.ts +9 -3
  477. package/src/server/proxy/index.ts +8 -2
  478. package/src/server/rate-limit/index.ts +21 -25
  479. package/src/server/rate-limit/primitives/$rateLimit.ts +6 -2
  480. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +38 -14
  481. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +22 -56
  482. package/src/server/static/index.ts +8 -2
  483. package/src/server/static/providers/ServerStaticProvider.ts +1 -1
  484. package/src/server/swagger/index.ts +9 -4
  485. package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
  486. package/src/sms/index.ts +9 -5
  487. package/src/sms/providers/LocalSmsProvider.spec.ts +1 -1
  488. package/src/sms/providers/LocalSmsProvider.ts +1 -1
  489. package/src/system/index.browser.ts +36 -0
  490. package/src/system/index.ts +62 -0
  491. package/src/system/index.workerd.ts +1 -0
  492. package/src/{file → system}/providers/FileSystemProvider.ts +24 -0
  493. package/src/{file → system}/providers/MemoryFileSystemProvider.ts +116 -3
  494. package/src/system/providers/MemoryShellProvider.ts +164 -0
  495. package/src/{file → system}/providers/NodeFileSystemProvider.spec.ts +2 -2
  496. package/src/{file → system}/providers/NodeFileSystemProvider.ts +47 -2
  497. package/src/system/providers/NodeShellProvider.ts +184 -0
  498. package/src/system/providers/ShellProvider.ts +74 -0
  499. package/src/{file → system}/services/FileDetector.spec.ts +2 -2
  500. package/src/thread/index.ts +11 -2
  501. package/src/topic/core/index.ts +12 -5
  502. package/src/vite/tasks/buildClient.ts +2 -7
  503. package/src/vite/tasks/buildServer.ts +19 -13
  504. package/src/vite/tasks/generateCloudflare.ts +10 -7
  505. package/src/vite/tasks/generateDocker.ts +4 -0
  506. package/src/websocket/index.ts +12 -8
  507. package/dist/file/index.d.ts.map +0 -1
  508. package/dist/file/index.js.map +0 -1
  509. package/src/cli/assets/apiIndexTs.ts +0 -16
  510. package/src/cli/assets/mainServerTs.ts +0 -24
  511. package/src/cli/assets/webAppRouterTs.ts +0 -16
  512. package/src/cli/assets/webHelloComponentTsx.ts +0 -20
  513. package/src/cli/providers/ViteTemplateProvider.ts +0 -27
  514. package/src/file/index.ts +0 -43
  515. /package/src/cli/{assets → templates}/apiHelloControllerTs.ts +0 -0
  516. /package/src/cli/{assets → templates}/biomeJson.ts +0 -0
  517. /package/src/cli/{assets → templates}/dummySpecTs.ts +0 -0
  518. /package/src/cli/{assets → templates}/editorconfig.ts +0 -0
  519. /package/src/cli/{assets → templates}/mainBrowserTs.ts +0 -0
  520. /package/src/cli/{assets → templates}/tsconfigJson.ts +0 -0
  521. /package/src/cli/{assets → templates}/webIndexTs.ts +0 -0
  522. /package/src/{file → system}/errors/FileError.ts +0 -0
  523. /package/src/{file → system}/services/FileDetector.ts +0 -0
@@ -0,0 +1,232 @@
1
+ import * as alepha0 from "alepha";
2
+ import { Alepha, Static, TArray, TObject, TSchema, TypeBoxError } from "alepha";
3
+ import { InputHTMLAttributes, ReactNode } from "react";
4
+ import * as alepha_logger0 from "alepha/logger";
5
+
6
+ //#region ../../src/react/form/services/FormModel.d.ts
7
+ /**
8
+ * FormModel is a dynamic form handler that generates form inputs based on a provided TypeBox schema.
9
+ * It manages form state, handles input changes, and processes form submissions with validation.
10
+ *
11
+ * It means to be injected and used within React components to provide a structured way to create and manage forms.
12
+ *
13
+ * @see {@link useForm}
14
+ */
15
+ declare class FormModel<T extends TObject> {
16
+ readonly id: string;
17
+ readonly options: FormCtrlOptions<T>;
18
+ protected readonly log: alepha_logger0.Logger;
19
+ protected readonly alepha: Alepha;
20
+ protected readonly values: Record<string, any>;
21
+ protected submitInProgress: boolean;
22
+ input: SchemaToInput<T>;
23
+ get submitting(): boolean;
24
+ constructor(id: string, options: FormCtrlOptions<T>);
25
+ get element(): HTMLFormElement;
26
+ get currentValues(): Record<string, any>;
27
+ get props(): {
28
+ id: string;
29
+ noValidate: boolean;
30
+ onSubmit: (ev?: FormEventLike) => void;
31
+ onReset: (event: FormEventLike) => Promise<void>;
32
+ };
33
+ readonly reset: (event: FormEventLike) => Promise<void>;
34
+ readonly submit: () => Promise<void>;
35
+ /**
36
+ * Restructures flat keys like "address.city" into nested objects like { address: { city: ... } }
37
+ * Values are already typed from onChange, so no conversion is needed.
38
+ */
39
+ protected restructureValues(store: Record<string, any>): Record<string, any>;
40
+ /**
41
+ * Helper to restructure a flat key like "address.city" into nested object structure.
42
+ * The value is already typed, so we just assign it to the nested path.
43
+ */
44
+ protected restructureNestedValue(values: Record<string, any>, key: string, value: any): void;
45
+ protected createProxyFromSchema<T extends TObject>(options: FormCtrlOptions<T>, schema: TSchema, context: {
46
+ parent: string;
47
+ store: Record<string, any>;
48
+ }): SchemaToInput<T>;
49
+ protected createInputFromSchema<T extends TObject>(name: keyof Static<T> & string, options: FormCtrlOptions<T>, schema: TObject, required: boolean, context: {
50
+ parent: string;
51
+ store: Record<string, any>;
52
+ }): BaseInputField;
53
+ /**
54
+ * Convert an input value to the correct type based on the schema.
55
+ * Handles raw DOM values (strings, booleans from checkboxes, Files, etc.)
56
+ */
57
+ protected getValueFromInput(input: any, schema: TSchema): any;
58
+ protected valueToInputEntry(value: any): string | number | boolean;
59
+ }
60
+ type SchemaToInput<T extends TObject> = { [K in keyof T["properties"]]: InputField<T["properties"][K]> };
61
+ interface FormEventLike {
62
+ preventDefault?: () => void;
63
+ stopPropagation?: () => void;
64
+ }
65
+ type InputField<T extends TSchema> = T extends TObject ? ObjectInputField<T> : T extends TArray<infer U> ? ArrayInputField<U> : BaseInputField;
66
+ interface BaseInputField {
67
+ path: string;
68
+ required: boolean;
69
+ props: InputHTMLAttributesLike;
70
+ schema: TSchema;
71
+ set: (value: any) => void;
72
+ form: FormModel<any>;
73
+ items?: any;
74
+ }
75
+ interface ObjectInputField<T extends TObject> extends BaseInputField {
76
+ items: SchemaToInput<T>;
77
+ }
78
+ interface ArrayInputField<T extends TSchema> extends BaseInputField {
79
+ items: Array<InputField<T>>;
80
+ }
81
+ type InputHTMLAttributesLike = Pick<InputHTMLAttributes<unknown>, "id" | "name" | "type" | "value" | "defaultValue" | "required" | "maxLength" | "minLength" | "aria-label" | "autoComplete"> & {
82
+ value?: any;
83
+ defaultValue?: any;
84
+ onChange?: (event: any) => void;
85
+ };
86
+ type FormCtrlOptions<T extends TObject> = {
87
+ /**
88
+ * The schema defining the structure and validation rules for the form.
89
+ * This should be a TypeBox schema object.
90
+ */
91
+ schema: T;
92
+ /**
93
+ * Callback function to handle form submission.
94
+ * This function will receive the parsed and validated form values.
95
+ */
96
+ handler: (values: Static<T>, args: {
97
+ form: HTMLFormElement;
98
+ }) => unknown;
99
+ /**
100
+ * Optional initial values for the form fields.
101
+ * This can be used to pre-populate the form with existing data.
102
+ */
103
+ initialValues?: Partial<Static<T>>;
104
+ /**
105
+ * Optional function to create custom field attributes.
106
+ * This can be used to add custom validation, styles, or other attributes.
107
+ */
108
+ onCreateField?: (name: keyof Static<T> & string, schema: TSchema) => InputHTMLAttributes<unknown>;
109
+ /**
110
+ * If defined, this will generate a unique ID for each field, prefixed with this string.
111
+ *
112
+ * > "username" with id="form-123" will become "form-123-username".
113
+ *
114
+ * If omitted, IDs will not be generated.
115
+ */
116
+ id?: string;
117
+ onError?: (error: Error, args: {
118
+ form: HTMLFormElement;
119
+ }) => void;
120
+ onChange?: (key: string, value: any, store: Record<string, any>) => void;
121
+ onReset?: () => void;
122
+ };
123
+ //#endregion
124
+ //#region ../../src/react/form/components/FormState.d.ts
125
+ declare const FormState: <T extends TObject>(props: {
126
+ form: FormModel<T>;
127
+ children: (state: {
128
+ loading: boolean;
129
+ dirty: boolean;
130
+ }) => ReactNode;
131
+ }) => ReactNode;
132
+ //#endregion
133
+ //#region ../../src/react/form/errors/FormValidationError.d.ts
134
+ declare class FormValidationError extends TypeBoxError {
135
+ readonly name = "ValidationError";
136
+ constructor(options: {
137
+ message: string;
138
+ path: string;
139
+ });
140
+ }
141
+ //#endregion
142
+ //#region ../../src/react/form/hooks/useForm.d.ts
143
+ /**
144
+ * Custom hook to create a form with validation and field management.
145
+ * This hook uses TypeBox schemas to define the structure and validation rules for the form.
146
+ * It provides a way to handle form submission, field creation, and value management.
147
+ *
148
+ * @example
149
+ * ```tsx
150
+ * import { t } from "alepha";
151
+ *
152
+ * const form = useForm({
153
+ * schema: t.object({
154
+ * username: t.text(),
155
+ * password: t.text(),
156
+ * }),
157
+ * handler: (values) => {
158
+ * console.log("Form submitted with values:", values);
159
+ * },
160
+ * });
161
+ *
162
+ * return (
163
+ * <form {...form.props}>
164
+ * <input {...form.input.username.props} />
165
+ * <input {...form.input.password.props} />
166
+ * <button type="submit">Submit</button>
167
+ * </form>
168
+ * );
169
+ * ```
170
+ */
171
+ declare const useForm: <T extends TObject>(options: FormCtrlOptions<T>, deps?: any[]) => FormModel<T>;
172
+ //#endregion
173
+ //#region ../../src/react/form/hooks/useFormState.d.ts
174
+ interface UseFormStateReturn {
175
+ loading: boolean;
176
+ dirty: boolean;
177
+ values?: Record<string, any>;
178
+ error?: Error;
179
+ }
180
+ declare const useFormState: <T extends TObject, Keys extends keyof UseFormStateReturn>(target: FormModel<T> | {
181
+ form: FormModel<T>;
182
+ path: string;
183
+ }, _events?: Keys[]) => Pick<UseFormStateReturn, Keys>;
184
+ //#endregion
185
+ //#region ../../src/react/form/index.d.ts
186
+ declare module "alepha" {
187
+ interface Hooks {
188
+ "form:change": {
189
+ id: string;
190
+ path: string;
191
+ value: any;
192
+ };
193
+ "form:reset": {
194
+ id: string;
195
+ values: Record<string, any>;
196
+ };
197
+ "form:submit:begin": {
198
+ id: string;
199
+ };
200
+ "form:submit:success": {
201
+ id: string;
202
+ values: Record<string, any>;
203
+ };
204
+ "form:submit:error": {
205
+ id: string;
206
+ error: Error;
207
+ };
208
+ "form:submit:end": {
209
+ id: string;
210
+ };
211
+ }
212
+ }
213
+ /**
214
+ * | type | quality | stability |
215
+ * |------|---------|-----------|
216
+ * | frontend | rare | stable |
217
+ *
218
+ * Type-safe forms with validation.
219
+ *
220
+ * **Features:**
221
+ * - Form state management
222
+ * - TypeBox schema validation
223
+ * - Field-level error handling
224
+ * - Submit handling with loading state
225
+ * - Form reset
226
+ *
227
+ * @module alepha.react.form
228
+ */
229
+ declare const AlephaReactForm: alepha0.Service<alepha0.Module>;
230
+ //#endregion
231
+ export { AlephaReactForm, ArrayInputField, BaseInputField, FormCtrlOptions, FormEventLike, FormModel, FormState, FormValidationError, InputField, InputHTMLAttributesLike, ObjectInputField, SchemaToInput, UseFormStateReturn, useForm, useFormState };
232
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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/useForm.ts","../../../src/react/form/hooks/useFormState.ts","../../../src/react/form/index.ts"],"mappings":"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"}
@@ -0,0 +1,432 @@
1
+ import { $inject, $module, Alepha, TypeBoxError, t } from "alepha";
2
+ import { useAlepha } from "alepha/react";
3
+ import { useEffect, useId, useMemo, useState } from "react";
4
+ import { $logger } from "alepha/logger";
5
+
6
+ //#region ../../src/react/form/hooks/useFormState.ts
7
+ const useFormState = (target, _events = [
8
+ "loading",
9
+ "dirty",
10
+ "error"
11
+ ]) => {
12
+ const alepha = useAlepha();
13
+ const events = _events;
14
+ const [dirty, setDirty] = useState(false);
15
+ const [loading, setLoading] = useState(false);
16
+ const [error, setError] = useState(void 0);
17
+ const [values, setValues] = useState(void 0);
18
+ const form = "form" in target ? target.form : target;
19
+ const path = "path" in target ? target.path : void 0;
20
+ const hasValues = events.includes("values");
21
+ const hasErrors = events.includes("error");
22
+ const hasDirty = events.includes("dirty");
23
+ const hasLoading = events.includes("loading");
24
+ useEffect(() => {
25
+ const listeners = [];
26
+ if (hasErrors || hasValues || hasDirty) listeners.push(alepha.events.on("form:change", (event) => {
27
+ if (event.id === form.id) {
28
+ if (!path || event.path === path) {
29
+ if (hasDirty) setDirty(true);
30
+ if (hasErrors) setError(void 0);
31
+ }
32
+ if (hasValues) setValues(form.currentValues);
33
+ }
34
+ }));
35
+ if (hasValues) listeners.push(alepha.events.on("form:reset", (event) => {
36
+ if (event.id === form.id) setValues(event.values);
37
+ }));
38
+ if (hasLoading) listeners.push(alepha.events.on("form:submit:begin", (event) => {
39
+ if (event.id === form.id) setLoading(true);
40
+ }), alepha.events.on("form:submit:end", (event) => {
41
+ if (event.id === form.id) setLoading(false);
42
+ }));
43
+ if (hasValues || hasDirty) listeners.push(alepha.events.on("form:submit:success", (event) => {
44
+ if (event.id === form.id) {
45
+ if (hasValues) setValues(event.values);
46
+ if (hasDirty) setDirty(false);
47
+ }
48
+ }));
49
+ if (hasErrors) listeners.push(alepha.events.on("form:submit:error", (event) => {
50
+ if (event.id === form.id) {
51
+ if (!path || event.error instanceof TypeBoxError && event.error.value.path === path) setError(event.error);
52
+ }
53
+ }));
54
+ return () => {
55
+ for (const unsub of listeners) unsub();
56
+ };
57
+ }, []);
58
+ return {
59
+ dirty,
60
+ loading,
61
+ error,
62
+ values
63
+ };
64
+ };
65
+
66
+ //#endregion
67
+ //#region ../../src/react/form/components/FormState.tsx
68
+ const FormState = (props) => {
69
+ const formState = useFormState(props.form);
70
+ return props.children({
71
+ loading: formState.loading,
72
+ dirty: formState.dirty
73
+ });
74
+ };
75
+ var FormState_default = FormState;
76
+
77
+ //#endregion
78
+ //#region ../../src/react/form/errors/FormValidationError.ts
79
+ var FormValidationError = class extends TypeBoxError {
80
+ name = "ValidationError";
81
+ constructor(options) {
82
+ super({
83
+ message: options.message,
84
+ instancePath: options.path,
85
+ schemaPath: "",
86
+ keyword: "not",
87
+ params: {}
88
+ });
89
+ }
90
+ };
91
+
92
+ //#endregion
93
+ //#region ../../src/react/form/services/FormModel.ts
94
+ /**
95
+ * FormModel is a dynamic form handler that generates form inputs based on a provided TypeBox schema.
96
+ * It manages form state, handles input changes, and processes form submissions with validation.
97
+ *
98
+ * It means to be injected and used within React components to provide a structured way to create and manage forms.
99
+ *
100
+ * @see {@link useForm}
101
+ */
102
+ var FormModel = class {
103
+ log = $logger();
104
+ alepha = $inject(Alepha);
105
+ values = {};
106
+ submitInProgress = false;
107
+ input;
108
+ get submitting() {
109
+ return this.submitInProgress;
110
+ }
111
+ constructor(id, options) {
112
+ this.id = id;
113
+ this.options = options;
114
+ this.options = options;
115
+ if (options.initialValues) this.values = this.alepha.codec.decode(options.schema, options.initialValues);
116
+ this.input = this.createProxyFromSchema(options, options.schema, {
117
+ store: this.values,
118
+ parent: ""
119
+ });
120
+ }
121
+ get element() {
122
+ return window.document.getElementById(this.id);
123
+ }
124
+ get currentValues() {
125
+ return this.restructureValues(this.values);
126
+ }
127
+ get props() {
128
+ return {
129
+ id: this.id,
130
+ noValidate: true,
131
+ onSubmit: (ev) => {
132
+ ev?.preventDefault?.();
133
+ this.submit();
134
+ },
135
+ onReset: (event) => this.reset(event)
136
+ };
137
+ }
138
+ reset = (event) => {
139
+ for (const key in this.values) delete this.values[key];
140
+ this.options.onReset?.();
141
+ return this.alepha.events.emit("form:reset", {
142
+ id: this.id,
143
+ values: this.values
144
+ }, { catch: true });
145
+ };
146
+ submit = async () => {
147
+ if (this.submitInProgress) {
148
+ this.log.warn("Form submission already in progress, ignoring duplicate submit.");
149
+ return;
150
+ }
151
+ await this.alepha.events.emit("react:action:begin", {
152
+ type: "form",
153
+ id: this.id
154
+ });
155
+ await this.alepha.events.emit("form:submit:begin", { id: this.id });
156
+ this.submitInProgress = true;
157
+ const options = this.options;
158
+ const args = { form: this.element };
159
+ try {
160
+ let values = this.restructureValues(this.values);
161
+ if (t.schema.isSchema(options.schema)) values = this.alepha.codec.decode(options.schema, values);
162
+ await options.handler(values, args);
163
+ await this.alepha.events.emit("react:action:success", {
164
+ type: "form",
165
+ id: this.id
166
+ });
167
+ await this.alepha.events.emit("form:submit:success", {
168
+ id: this.id,
169
+ values
170
+ });
171
+ } catch (error) {
172
+ this.log.error("Form submission error:", error);
173
+ options.onError?.(error, args);
174
+ await this.alepha.events.emit("react:action:error", {
175
+ type: "form",
176
+ id: this.id,
177
+ error
178
+ });
179
+ await this.alepha.events.emit("form:submit:error", {
180
+ error,
181
+ id: this.id
182
+ });
183
+ } finally {
184
+ this.submitInProgress = false;
185
+ }
186
+ await this.alepha.events.emit("react:action:end", {
187
+ type: "form",
188
+ id: this.id
189
+ });
190
+ await this.alepha.events.emit("form:submit:end", { id: this.id });
191
+ };
192
+ /**
193
+ * Restructures flat keys like "address.city" into nested objects like { address: { city: ... } }
194
+ * Values are already typed from onChange, so no conversion is needed.
195
+ */
196
+ restructureValues(store) {
197
+ const values = {};
198
+ for (const [key, value] of Object.entries(store)) if (key.includes(".")) this.restructureNestedValue(values, key, value);
199
+ else values[key] = value;
200
+ return values;
201
+ }
202
+ /**
203
+ * Helper to restructure a flat key like "address.city" into nested object structure.
204
+ * The value is already typed, so we just assign it to the nested path.
205
+ */
206
+ restructureNestedValue(values, key, value) {
207
+ const pathSegments = key.split(".");
208
+ const finalPropertyKey = pathSegments.pop();
209
+ if (!finalPropertyKey) return;
210
+ let currentObjectLevel = values;
211
+ for (const segment of pathSegments) {
212
+ currentObjectLevel[segment] ??= {};
213
+ currentObjectLevel = currentObjectLevel[segment];
214
+ }
215
+ currentObjectLevel[finalPropertyKey] = value;
216
+ }
217
+ createProxyFromSchema(options, schema, context) {
218
+ context.parent;
219
+ return new Proxy({}, { get: (_, prop) => {
220
+ if (!options.schema || !t.schema.isObject(schema)) return {};
221
+ if (prop in schema.properties) return this.createInputFromSchema(prop, options, schema, schema.required?.includes(prop) || false, context);
222
+ } });
223
+ }
224
+ createInputFromSchema(name, options, schema, required, context) {
225
+ const parent = context.parent || "";
226
+ const field = schema.properties?.[name];
227
+ if (!field) return {
228
+ path: "",
229
+ required,
230
+ props: {},
231
+ schema,
232
+ set: () => {},
233
+ form: this
234
+ };
235
+ const isRequired = schema.required?.includes(name) ?? false;
236
+ const key = parent ? `${parent}.${name}` : name;
237
+ const path = `/${key.replaceAll(".", "/")}`;
238
+ const set = (value, sync = true) => {
239
+ const typedValue = this.getValueFromInput(value, field);
240
+ if (context.store[key] === typedValue) {}
241
+ context.store[key] = typedValue;
242
+ if (options.onChange) options.onChange(key, typedValue, context.store);
243
+ this.alepha.events.emit("form:change", {
244
+ id: this.id,
245
+ path,
246
+ value: typedValue
247
+ }, { catch: true });
248
+ if (sync) {
249
+ const inputElement = window.document.querySelector(`[data-path="${path}"]`);
250
+ if (inputElement instanceof HTMLInputElement) if (t.schema.isBoolean(field)) {
251
+ inputElement.value = value;
252
+ inputElement.checked = Boolean(value);
253
+ } else inputElement.value = value;
254
+ }
255
+ };
256
+ const attr = {
257
+ name: key,
258
+ autoComplete: "off",
259
+ onChange: (event) => {
260
+ if (typeof event === "string") {
261
+ set(event, false);
262
+ return;
263
+ }
264
+ if (typeof event === "number") {
265
+ set(event, false);
266
+ return;
267
+ }
268
+ if (t.schema.isBoolean(field)) if (event.target.value === "true") set(true, false);
269
+ else if (event.target.value === "false") set(false, false);
270
+ else if (event.target.value === "") set(void 0, false);
271
+ else set(event.target.checked, false);
272
+ else set(event.target.value, false);
273
+ }
274
+ };
275
+ attr["data-path"] = path;
276
+ if (options.id) {
277
+ attr.id = `${options.id}-${key}`;
278
+ attr["data-testid"] = attr.id;
279
+ }
280
+ if (t.schema.isString(field)) {
281
+ if (field.maxLength != null) attr.maxLength = Number(field.maxLength);
282
+ if (field.minLength != null) attr.minLength = Number(field.minLength);
283
+ }
284
+ if (options.initialValues?.[name] != null) attr.defaultValue = this.valueToInputEntry(options.initialValues[name]);
285
+ else if ("default" in field && field.default != null) attr.defaultValue = this.valueToInputEntry(field.default);
286
+ if (isRequired) attr.required = true;
287
+ if ("description" in field && typeof field.description === "string") attr["aria-label"] = field.description;
288
+ if (t.schema.isInteger(field) || t.schema.isNumber(field)) attr.type = "number";
289
+ else if (name === "password") attr.type = "password";
290
+ else if (name === "email") attr.type = "email";
291
+ else if (name === "url") attr.type = "url";
292
+ else if (t.schema.isString(field)) if (field.format === "binary") attr.type = "file";
293
+ else if (field.format === "date") attr.type = "date";
294
+ else if (field.format === "time") attr.type = "time";
295
+ else if (field.format === "date-time") attr.type = "datetime-local";
296
+ else attr.type = "text";
297
+ else if (t.schema.isBoolean(field)) attr.type = "checkbox";
298
+ if (options.onCreateField) {
299
+ const customAttr = options.onCreateField(name, field);
300
+ Object.assign(attr, customAttr);
301
+ }
302
+ if (t.schema.isObject(field)) return {
303
+ path,
304
+ props: attr,
305
+ schema: field,
306
+ set,
307
+ form: this,
308
+ required,
309
+ items: this.createProxyFromSchema(options, field, {
310
+ parent: key,
311
+ store: context.store
312
+ })
313
+ };
314
+ if (t.schema.isArray(field)) return {
315
+ path,
316
+ props: attr,
317
+ schema: field,
318
+ set,
319
+ form: this,
320
+ required,
321
+ items: []
322
+ };
323
+ return {
324
+ path,
325
+ props: attr,
326
+ schema: field,
327
+ set,
328
+ form: this,
329
+ required
330
+ };
331
+ }
332
+ /**
333
+ * Convert an input value to the correct type based on the schema.
334
+ * Handles raw DOM values (strings, booleans from checkboxes, Files, etc.)
335
+ */
336
+ getValueFromInput(input, schema) {
337
+ if (input instanceof File) {
338
+ if (t.schema.isString(schema) && schema.format === "binary") return input;
339
+ return null;
340
+ }
341
+ if (t.schema.isBoolean(schema)) {
342
+ if (input === "true") return true;
343
+ if (input === "false") return false;
344
+ if (input === "" || input === null || input === void 0) return void 0;
345
+ return !!input;
346
+ }
347
+ if (t.schema.isNumber(schema)) {
348
+ const num = Number(input);
349
+ return Number.isNaN(num) ? null : num;
350
+ }
351
+ if (t.schema.isString(schema)) {
352
+ if (schema.format === "date") return new Date(input).toISOString().slice(0, 10);
353
+ if (schema.format === "time") return (/* @__PURE__ */ new Date(`1970-01-01T${input}`)).toISOString().slice(11, 16);
354
+ if (schema.format === "date-time") return new Date(input).toISOString();
355
+ return String(input);
356
+ }
357
+ return input;
358
+ }
359
+ valueToInputEntry(value) {
360
+ if (value === null || value === void 0) return "";
361
+ if (typeof value === "boolean") return value;
362
+ if (typeof value === "number") return value;
363
+ if (typeof value === "string") return value;
364
+ if (value instanceof Date) return value.toISOString().slice(0, 16);
365
+ return value;
366
+ }
367
+ };
368
+
369
+ //#endregion
370
+ //#region ../../src/react/form/hooks/useForm.ts
371
+ /**
372
+ * Custom hook to create a form with validation and field management.
373
+ * This hook uses TypeBox schemas to define the structure and validation rules for the form.
374
+ * It provides a way to handle form submission, field creation, and value management.
375
+ *
376
+ * @example
377
+ * ```tsx
378
+ * import { t } from "alepha";
379
+ *
380
+ * const form = useForm({
381
+ * schema: t.object({
382
+ * username: t.text(),
383
+ * password: t.text(),
384
+ * }),
385
+ * handler: (values) => {
386
+ * console.log("Form submitted with values:", values);
387
+ * },
388
+ * });
389
+ *
390
+ * return (
391
+ * <form {...form.props}>
392
+ * <input {...form.input.username.props} />
393
+ * <input {...form.input.password.props} />
394
+ * <button type="submit">Submit</button>
395
+ * </form>
396
+ * );
397
+ * ```
398
+ */
399
+ const useForm = (options, deps = []) => {
400
+ const alepha = useAlepha();
401
+ const formId = useId();
402
+ return useMemo(() => {
403
+ return alepha.inject(FormModel, {
404
+ lifetime: "transient",
405
+ args: [options.id || formId, options]
406
+ });
407
+ }, deps);
408
+ };
409
+
410
+ //#endregion
411
+ //#region ../../src/react/form/index.ts
412
+ /**
413
+ * | type | quality | stability |
414
+ * |------|---------|-----------|
415
+ * | frontend | rare | stable |
416
+ *
417
+ * Type-safe forms with validation.
418
+ *
419
+ * **Features:**
420
+ * - Form state management
421
+ * - TypeBox schema validation
422
+ * - Field-level error handling
423
+ * - Submit handling with loading state
424
+ * - Form reset
425
+ *
426
+ * @module alepha.react.form
427
+ */
428
+ const AlephaReactForm = $module({ name: "alepha.react.form" });
429
+
430
+ //#endregion
431
+ export { AlephaReactForm, FormModel, FormState_default as FormState, FormValidationError, useForm, useFormState };
432
+ //# sourceMappingURL=index.js.map