alepha 0.15.0 → 0.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (551) hide show
  1. package/README.md +43 -98
  2. package/dist/api/audits/index.d.ts +630 -653
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js +12 -35
  5. package/dist/api/audits/index.js.map +1 -1
  6. package/dist/api/files/index.d.ts +365 -358
  7. package/dist/api/files/index.d.ts.map +1 -1
  8. package/dist/api/files/index.js +12 -5
  9. package/dist/api/files/index.js.map +1 -1
  10. package/dist/api/jobs/index.d.ts +255 -248
  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.browser.js +4 -4
  19. package/dist/api/notifications/index.browser.js.map +1 -1
  20. package/dist/api/notifications/index.d.ts +84 -78
  21. package/dist/api/notifications/index.d.ts.map +1 -1
  22. package/dist/api/notifications/index.js +14 -8
  23. package/dist/api/notifications/index.js.map +1 -1
  24. package/dist/api/parameters/index.d.ts +528 -535
  25. package/dist/api/parameters/index.d.ts.map +1 -1
  26. package/dist/api/parameters/index.js +30 -37
  27. package/dist/api/parameters/index.js.map +1 -1
  28. package/dist/api/users/index.d.ts +1221 -910
  29. package/dist/api/users/index.d.ts.map +1 -1
  30. package/dist/api/users/index.js +2556 -248
  31. package/dist/api/users/index.js.map +1 -1
  32. package/dist/api/verifications/index.d.ts +142 -136
  33. package/dist/api/verifications/index.d.ts.map +1 -1
  34. package/dist/api/verifications/index.js +12 -4
  35. package/dist/api/verifications/index.js.map +1 -1
  36. package/dist/batch/index.d.ts +142 -162
  37. package/dist/batch/index.d.ts.map +1 -1
  38. package/dist/batch/index.js +31 -44
  39. package/dist/batch/index.js.map +1 -1
  40. package/dist/bucket/index.d.ts +595 -171
  41. package/dist/bucket/index.d.ts.map +1 -1
  42. package/dist/bucket/index.js +1856 -12
  43. package/dist/bucket/index.js.map +1 -1
  44. package/dist/cache/core/index.d.ts +225 -53
  45. package/dist/cache/core/index.d.ts.map +1 -1
  46. package/dist/cache/core/index.js +213 -7
  47. package/dist/cache/core/index.js.map +1 -1
  48. package/dist/cache/redis/index.d.ts +1 -0
  49. package/dist/cache/redis/index.d.ts.map +1 -1
  50. package/dist/cache/redis/index.js +6 -2
  51. package/dist/cache/redis/index.js.map +1 -1
  52. package/dist/cli/index.d.ts +834 -226
  53. package/dist/cli/index.d.ts.map +1 -1
  54. package/dist/cli/index.js +2872 -417
  55. package/dist/cli/index.js.map +1 -1
  56. package/dist/command/index.d.ts +458 -310
  57. package/dist/command/index.d.ts.map +1 -1
  58. package/dist/command/index.js +2011 -76
  59. package/dist/command/index.js.map +1 -1
  60. package/dist/core/index.browser.js +309 -97
  61. package/dist/core/index.browser.js.map +1 -1
  62. package/dist/core/index.d.ts +796 -701
  63. package/dist/core/index.d.ts.map +1 -1
  64. package/dist/core/index.js +329 -97
  65. package/dist/core/index.js.map +1 -1
  66. package/dist/core/index.native.js +309 -97
  67. package/dist/core/index.native.js.map +1 -1
  68. package/dist/datetime/index.d.ts +59 -44
  69. package/dist/datetime/index.d.ts.map +1 -1
  70. package/dist/datetime/index.js +15 -0
  71. package/dist/datetime/index.js.map +1 -1
  72. package/dist/email/index.d.ts +314 -19
  73. package/dist/email/index.d.ts.map +1 -1
  74. package/dist/email/index.js +1852 -7
  75. package/dist/email/index.js.map +1 -1
  76. package/dist/fake/index.d.ts +5500 -5418
  77. package/dist/fake/index.d.ts.map +1 -1
  78. package/dist/fake/index.js +113 -42
  79. package/dist/fake/index.js.map +1 -1
  80. package/dist/lock/core/index.d.ts +219 -212
  81. package/dist/lock/core/index.d.ts.map +1 -1
  82. package/dist/lock/core/index.js +11 -4
  83. package/dist/lock/core/index.js.map +1 -1
  84. package/dist/lock/redis/index.d.ts.map +1 -1
  85. package/dist/logger/index.d.ts +41 -90
  86. package/dist/logger/index.d.ts.map +1 -1
  87. package/dist/logger/index.js +15 -68
  88. package/dist/logger/index.js.map +1 -1
  89. package/dist/mcp/index.d.ts +228 -230
  90. package/dist/mcp/index.d.ts.map +1 -1
  91. package/dist/mcp/index.js +32 -31
  92. package/dist/mcp/index.js.map +1 -1
  93. package/dist/orm/index.browser.js +12 -12
  94. package/dist/orm/index.browser.js.map +1 -1
  95. package/dist/orm/index.bun.js +90 -80
  96. package/dist/orm/index.bun.js.map +1 -1
  97. package/dist/orm/index.d.ts +1434 -1459
  98. package/dist/orm/index.d.ts.map +1 -1
  99. package/dist/orm/index.js +112 -130
  100. package/dist/orm/index.js.map +1 -1
  101. package/dist/queue/core/index.d.ts +262 -254
  102. package/dist/queue/core/index.d.ts.map +1 -1
  103. package/dist/queue/core/index.js +14 -6
  104. package/dist/queue/core/index.js.map +1 -1
  105. package/dist/queue/redis/index.d.ts.map +1 -1
  106. package/dist/react/auth/index.browser.js +108 -0
  107. package/dist/react/auth/index.browser.js.map +1 -0
  108. package/dist/react/auth/index.d.ts +100 -0
  109. package/dist/react/auth/index.d.ts.map +1 -0
  110. package/dist/react/auth/index.js +145 -0
  111. package/dist/react/auth/index.js.map +1 -0
  112. package/dist/react/core/index.d.ts +469 -0
  113. package/dist/react/core/index.d.ts.map +1 -0
  114. package/dist/react/core/index.js +464 -0
  115. package/dist/react/core/index.js.map +1 -0
  116. package/dist/react/form/index.d.ts +232 -0
  117. package/dist/react/form/index.d.ts.map +1 -0
  118. package/dist/react/form/index.js +432 -0
  119. package/dist/react/form/index.js.map +1 -0
  120. package/dist/react/head/index.browser.js +423 -0
  121. package/dist/react/head/index.browser.js.map +1 -0
  122. package/dist/react/head/index.d.ts +288 -0
  123. package/dist/react/head/index.d.ts.map +1 -0
  124. package/dist/react/head/index.js +465 -0
  125. package/dist/react/head/index.js.map +1 -0
  126. package/dist/react/i18n/index.d.ts +175 -0
  127. package/dist/react/i18n/index.d.ts.map +1 -0
  128. package/dist/react/i18n/index.js +224 -0
  129. package/dist/react/i18n/index.js.map +1 -0
  130. package/dist/react/router/index.browser.js +1980 -0
  131. package/dist/react/router/index.browser.js.map +1 -0
  132. package/dist/react/router/index.d.ts +2068 -0
  133. package/dist/react/router/index.d.ts.map +1 -0
  134. package/dist/react/router/index.js +4932 -0
  135. package/dist/react/router/index.js.map +1 -0
  136. package/dist/react/websocket/index.d.ts +117 -0
  137. package/dist/react/websocket/index.d.ts.map +1 -0
  138. package/dist/react/websocket/index.js +107 -0
  139. package/dist/react/websocket/index.js.map +1 -0
  140. package/dist/redis/index.bun.js +4 -0
  141. package/dist/redis/index.bun.js.map +1 -1
  142. package/dist/redis/index.d.ts +127 -130
  143. package/dist/redis/index.d.ts.map +1 -1
  144. package/dist/redis/index.js +16 -25
  145. package/dist/redis/index.js.map +1 -1
  146. package/dist/retry/index.d.ts +80 -71
  147. package/dist/retry/index.d.ts.map +1 -1
  148. package/dist/retry/index.js +11 -2
  149. package/dist/retry/index.js.map +1 -1
  150. package/dist/router/index.d.ts +6 -6
  151. package/dist/router/index.d.ts.map +1 -1
  152. package/dist/scheduler/index.d.ts +119 -28
  153. package/dist/scheduler/index.d.ts.map +1 -1
  154. package/dist/scheduler/index.js +404 -3
  155. package/dist/scheduler/index.js.map +1 -1
  156. package/dist/security/index.d.ts +642 -228
  157. package/dist/security/index.d.ts.map +1 -1
  158. package/dist/security/index.js +1579 -37
  159. package/dist/security/index.js.map +1 -1
  160. package/dist/server/auth/index.d.ts +1141 -111
  161. package/dist/server/auth/index.d.ts.map +1 -1
  162. package/dist/server/auth/index.js +1261 -25
  163. package/dist/server/auth/index.js.map +1 -1
  164. package/dist/server/cache/index.d.ts +63 -78
  165. package/dist/server/cache/index.d.ts.map +1 -1
  166. package/dist/server/cache/index.js +7 -22
  167. package/dist/server/cache/index.js.map +1 -1
  168. package/dist/server/compress/index.d.ts +13 -5
  169. package/dist/server/compress/index.d.ts.map +1 -1
  170. package/dist/server/compress/index.js +10 -2
  171. package/dist/server/compress/index.js.map +1 -1
  172. package/dist/server/cookies/index.d.ts +46 -22
  173. package/dist/server/cookies/index.d.ts.map +1 -1
  174. package/dist/server/cookies/index.js +7 -5
  175. package/dist/server/cookies/index.js.map +1 -1
  176. package/dist/server/core/index.d.ts +307 -196
  177. package/dist/server/core/index.d.ts.map +1 -1
  178. package/dist/server/core/index.js +271 -38
  179. package/dist/server/core/index.js.map +1 -1
  180. package/dist/server/cors/index.d.ts +24 -34
  181. package/dist/server/cors/index.d.ts.map +1 -1
  182. package/dist/server/cors/index.js +7 -21
  183. package/dist/server/cors/index.js.map +1 -1
  184. package/dist/server/health/index.d.ts +25 -19
  185. package/dist/server/health/index.d.ts.map +1 -1
  186. package/dist/server/health/index.js +8 -2
  187. package/dist/server/health/index.js.map +1 -1
  188. package/dist/server/helmet/index.d.ts +13 -5
  189. package/dist/server/helmet/index.d.ts.map +1 -1
  190. package/dist/server/helmet/index.js +11 -3
  191. package/dist/server/helmet/index.js.map +1 -1
  192. package/dist/server/links/index.browser.js +9 -1
  193. package/dist/server/links/index.browser.js.map +1 -1
  194. package/dist/server/links/index.d.ts +133 -128
  195. package/dist/server/links/index.d.ts.map +1 -1
  196. package/dist/server/links/index.js +24 -11
  197. package/dist/server/links/index.js.map +1 -1
  198. package/dist/server/metrics/index.d.ts +524 -4
  199. package/dist/server/metrics/index.d.ts.map +1 -1
  200. package/dist/server/metrics/index.js +4472 -7
  201. package/dist/server/metrics/index.js.map +1 -1
  202. package/dist/server/multipart/index.d.ts +15 -9
  203. package/dist/server/multipart/index.d.ts.map +1 -1
  204. package/dist/server/multipart/index.js +9 -3
  205. package/dist/server/multipart/index.js.map +1 -1
  206. package/dist/server/proxy/index.d.ts +110 -104
  207. package/dist/server/proxy/index.d.ts.map +1 -1
  208. package/dist/server/proxy/index.js +8 -2
  209. package/dist/server/proxy/index.js.map +1 -1
  210. package/dist/server/rate-limit/index.d.ts +46 -51
  211. package/dist/server/rate-limit/index.d.ts.map +1 -1
  212. package/dist/server/rate-limit/index.js +18 -55
  213. package/dist/server/rate-limit/index.js.map +1 -1
  214. package/dist/server/static/index.d.ts +181 -48
  215. package/dist/server/static/index.d.ts.map +1 -1
  216. package/dist/server/static/index.js +1848 -5
  217. package/dist/server/static/index.js.map +1 -1
  218. package/dist/server/swagger/index.d.ts +348 -53
  219. package/dist/server/swagger/index.d.ts.map +1 -1
  220. package/dist/server/swagger/index.js +1849 -6
  221. package/dist/server/swagger/index.js.map +1 -1
  222. package/dist/sms/index.d.ts +312 -18
  223. package/dist/sms/index.d.ts.map +1 -1
  224. package/dist/sms/index.js +1854 -10
  225. package/dist/sms/index.js.map +1 -1
  226. package/dist/system/index.browser.js +496 -0
  227. package/dist/system/index.browser.js.map +1 -0
  228. package/dist/system/index.d.ts +1158 -0
  229. package/dist/system/index.d.ts.map +1 -0
  230. package/dist/{file → system}/index.js +412 -20
  231. package/dist/system/index.js.map +1 -0
  232. package/dist/thread/index.d.ts +82 -73
  233. package/dist/thread/index.d.ts.map +1 -1
  234. package/dist/thread/index.js +13 -4
  235. package/dist/thread/index.js.map +1 -1
  236. package/dist/topic/core/index.d.ts +330 -323
  237. package/dist/topic/core/index.d.ts.map +1 -1
  238. package/dist/topic/core/index.js +12 -5
  239. package/dist/topic/core/index.js.map +1 -1
  240. package/dist/topic/redis/index.d.ts +6 -6
  241. package/dist/topic/redis/index.d.ts.map +1 -1
  242. package/dist/vite/index.d.ts +163 -5825
  243. package/dist/vite/index.d.ts.map +1 -1
  244. package/dist/vite/index.js +130 -477
  245. package/dist/vite/index.js.map +1 -1
  246. package/dist/websocket/index.browser.js +3 -3
  247. package/dist/websocket/index.browser.js.map +1 -1
  248. package/dist/websocket/index.d.ts +287 -283
  249. package/dist/websocket/index.d.ts.map +1 -1
  250. package/dist/websocket/index.js +15 -11
  251. package/dist/websocket/index.js.map +1 -1
  252. package/package.json +86 -17
  253. package/src/api/audits/index.ts +10 -33
  254. package/src/api/files/__tests__/$bucket.spec.ts +1 -1
  255. package/src/api/files/controllers/AdminFileStatsController.spec.ts +1 -1
  256. package/src/api/files/controllers/FileController.spec.ts +1 -1
  257. package/src/api/files/index.ts +10 -3
  258. package/src/api/files/jobs/FileJobs.spec.ts +1 -1
  259. package/src/api/files/services/FileService.spec.ts +1 -1
  260. package/src/api/jobs/index.ts +10 -3
  261. package/src/api/keys/controllers/AdminApiKeyController.ts +75 -0
  262. package/src/api/keys/controllers/ApiKeyController.ts +103 -0
  263. package/src/api/keys/entities/apiKeyEntity.ts +41 -0
  264. package/src/api/keys/index.ts +49 -0
  265. package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +7 -0
  266. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +17 -0
  267. package/src/api/keys/schemas/createApiKeyBodySchema.ts +7 -0
  268. package/src/api/keys/schemas/createApiKeyResponseSchema.ts +11 -0
  269. package/src/api/keys/schemas/listApiKeyResponseSchema.ts +15 -0
  270. package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +5 -0
  271. package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +5 -0
  272. package/src/api/keys/services/ApiKeyService.spec.ts +553 -0
  273. package/src/api/keys/services/ApiKeyService.ts +306 -0
  274. package/src/api/logs/TODO.md +52 -0
  275. package/src/api/notifications/index.ts +10 -4
  276. package/src/api/parameters/index.ts +9 -30
  277. package/src/api/parameters/primitives/$config.ts +12 -4
  278. package/src/api/parameters/services/ConfigStore.ts +9 -3
  279. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1035 -0
  280. package/src/api/users/__tests__/ApiKeys.spec.ts +401 -0
  281. package/src/api/users/index.ts +14 -3
  282. package/src/api/users/primitives/$realm.ts +33 -5
  283. package/src/api/users/providers/RealmProvider.ts +1 -12
  284. package/src/api/users/services/SessionService.ts +1 -11
  285. package/src/api/verifications/controllers/VerificationController.ts +2 -0
  286. package/src/api/verifications/index.ts +10 -4
  287. package/src/batch/index.ts +9 -36
  288. package/src/batch/primitives/$batch.ts +0 -8
  289. package/src/batch/providers/BatchProvider.ts +29 -2
  290. package/src/bucket/__tests__/shared.ts +1 -1
  291. package/src/bucket/index.ts +13 -6
  292. package/src/bucket/primitives/$bucket.ts +1 -1
  293. package/src/bucket/providers/LocalFileStorageProvider.ts +1 -1
  294. package/src/bucket/providers/MemoryFileStorageProvider.ts +1 -1
  295. package/src/cache/core/__tests__/shared.ts +30 -0
  296. package/src/cache/core/index.ts +11 -6
  297. package/src/cache/core/primitives/$cache.spec.ts +5 -0
  298. package/src/cache/core/providers/CacheProvider.ts +17 -0
  299. package/src/cache/core/providers/MemoryCacheProvider.ts +300 -1
  300. package/src/cache/redis/__tests__/cache-redis.spec.ts +5 -0
  301. package/src/cache/redis/providers/RedisCacheProvider.ts +9 -0
  302. package/src/cli/apps/AlephaCli.ts +3 -16
  303. package/src/cli/apps/AlephaPackageBuilderCli.ts +10 -2
  304. package/src/cli/atoms/appEntryOptions.ts +13 -0
  305. package/src/cli/atoms/buildOptions.ts +1 -1
  306. package/src/cli/atoms/changelogOptions.ts +1 -1
  307. package/src/cli/commands/build.ts +64 -52
  308. package/src/cli/commands/db.ts +17 -11
  309. package/src/cli/commands/deploy.ts +1 -1
  310. package/src/cli/commands/dev.ts +13 -49
  311. package/src/cli/commands/gen/env.ts +6 -3
  312. package/src/cli/commands/gen/openapi.ts +5 -2
  313. package/src/cli/commands/init.spec.ts +544 -0
  314. package/src/cli/commands/init.ts +101 -58
  315. package/src/cli/commands/lint.ts +8 -2
  316. package/src/cli/commands/typecheck.ts +11 -0
  317. package/src/cli/defineConfig.ts +9 -0
  318. package/src/cli/index.ts +2 -1
  319. package/src/cli/providers/AppEntryProvider.ts +131 -0
  320. package/src/cli/providers/ViteBuildProvider.ts +40 -0
  321. package/src/cli/providers/ViteDevServerProvider.ts +378 -0
  322. package/src/cli/services/AlephaCliUtils.ts +39 -93
  323. package/src/cli/services/PackageManagerUtils.ts +140 -17
  324. package/src/cli/services/ProjectScaffolder.ts +169 -101
  325. package/src/cli/services/ViteUtils.ts +82 -0
  326. package/src/cli/{assets/claudeMd.ts → templates/agentMd.ts} +41 -28
  327. package/src/cli/{assets → templates}/apiHelloControllerTs.ts +2 -1
  328. package/src/cli/{assets → templates}/biomeJson.ts +2 -1
  329. package/src/cli/{assets → templates}/dummySpecTs.ts +2 -1
  330. package/src/cli/{assets → templates}/editorconfig.ts +2 -1
  331. package/src/cli/templates/gitignore.ts +39 -0
  332. package/src/cli/{assets → templates}/mainBrowserTs.ts +2 -1
  333. package/src/cli/templates/mainCss.ts +33 -0
  334. package/src/cli/templates/mainServerTs.ts +33 -0
  335. package/src/cli/{assets → templates}/tsconfigJson.ts +2 -1
  336. package/src/cli/templates/webAppRouterTs.ts +50 -0
  337. package/src/cli/templates/webHelloComponentTsx.ts +20 -0
  338. package/src/command/helpers/Runner.spec.ts +4 -0
  339. package/src/command/helpers/Runner.ts +3 -21
  340. package/src/command/index.ts +12 -4
  341. package/src/command/providers/CliProvider.spec.ts +1067 -0
  342. package/src/command/providers/CliProvider.ts +203 -40
  343. package/src/core/Alepha.ts +3 -9
  344. package/src/core/__tests__/Alepha-start.spec.ts +4 -4
  345. package/src/core/helpers/jsonSchemaToTypeBox.spec.ts +771 -0
  346. package/src/core/helpers/jsonSchemaToTypeBox.ts +62 -10
  347. package/src/core/index.shared.ts +1 -0
  348. package/src/core/index.ts +20 -0
  349. package/src/core/primitives/$module.ts +12 -0
  350. package/src/core/providers/EventManager.spec.ts +0 -71
  351. package/src/core/providers/EventManager.ts +3 -15
  352. package/src/core/providers/Json.ts +2 -14
  353. package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +257 -0
  354. package/src/core/providers/KeylessJsonSchemaCodec.ts +396 -14
  355. package/src/core/providers/SchemaValidator.spec.ts +236 -0
  356. package/src/datetime/index.ts +15 -0
  357. package/src/email/index.ts +10 -5
  358. package/src/email/providers/LocalEmailProvider.spec.ts +1 -1
  359. package/src/email/providers/LocalEmailProvider.ts +1 -1
  360. package/src/fake/__tests__/keyName.example.ts +1 -1
  361. package/src/fake/__tests__/keyName.spec.ts +5 -5
  362. package/src/fake/index.ts +9 -6
  363. package/src/fake/providers/FakeProvider.spec.ts +258 -40
  364. package/src/fake/providers/FakeProvider.ts +133 -19
  365. package/src/lock/core/index.ts +11 -4
  366. package/src/logger/index.ts +17 -66
  367. package/src/logger/providers/PrettyFormatterProvider.ts +0 -9
  368. package/src/mcp/errors/McpError.ts +30 -0
  369. package/src/mcp/index.ts +13 -27
  370. package/src/mcp/transports/SseMcpTransport.ts +6 -7
  371. package/src/orm/__tests__/PostgresProvider.spec.ts +2 -2
  372. package/src/orm/index.browser.ts +2 -2
  373. package/src/orm/index.bun.ts +4 -2
  374. package/src/orm/index.ts +21 -47
  375. package/src/orm/providers/DrizzleKitProvider.ts +3 -5
  376. package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -0
  377. package/src/orm/services/Repository.ts +18 -3
  378. package/src/queue/core/index.ts +14 -6
  379. package/src/react/auth/__tests__/$auth.spec.ts +202 -0
  380. package/src/react/auth/hooks/useAuth.ts +32 -0
  381. package/src/react/auth/index.browser.ts +13 -0
  382. package/src/react/auth/index.shared.ts +2 -0
  383. package/src/react/auth/index.ts +48 -0
  384. package/src/react/auth/providers/ReactAuthProvider.ts +16 -0
  385. package/src/react/auth/services/ReactAuth.ts +135 -0
  386. package/src/react/core/__tests__/Router.spec.tsx +169 -0
  387. package/src/react/core/components/ClientOnly.tsx +49 -0
  388. package/src/react/core/components/ErrorBoundary.tsx +73 -0
  389. package/src/react/core/contexts/AlephaContext.ts +7 -0
  390. package/src/react/core/contexts/AlephaProvider.tsx +42 -0
  391. package/src/react/core/hooks/useAction.browser.spec.tsx +569 -0
  392. package/src/react/core/hooks/useAction.ts +480 -0
  393. package/src/react/core/hooks/useAlepha.ts +26 -0
  394. package/src/react/core/hooks/useClient.ts +17 -0
  395. package/src/react/core/hooks/useEvents.ts +51 -0
  396. package/src/react/core/hooks/useInject.ts +12 -0
  397. package/src/react/core/hooks/useStore.ts +52 -0
  398. package/src/react/core/index.ts +90 -0
  399. package/src/react/form/components/FormState.tsx +17 -0
  400. package/src/react/form/errors/FormValidationError.ts +18 -0
  401. package/src/react/form/hooks/useForm.browser.spec.tsx +366 -0
  402. package/src/react/form/hooks/useForm.ts +47 -0
  403. package/src/react/form/hooks/useFormState.ts +130 -0
  404. package/src/react/form/index.ts +44 -0
  405. package/src/react/form/services/FormModel.ts +614 -0
  406. package/src/react/head/helpers/SeoExpander.spec.ts +203 -0
  407. package/src/react/head/helpers/SeoExpander.ts +142 -0
  408. package/src/react/head/hooks/useHead.spec.tsx +288 -0
  409. package/src/react/head/hooks/useHead.ts +62 -0
  410. package/src/react/head/index.browser.ts +26 -0
  411. package/src/react/head/index.ts +44 -0
  412. package/src/react/head/interfaces/Head.ts +105 -0
  413. package/src/react/head/primitives/$head.ts +25 -0
  414. package/src/react/head/providers/BrowserHeadProvider.browser.spec.ts +196 -0
  415. package/src/react/head/providers/BrowserHeadProvider.ts +212 -0
  416. package/src/react/head/providers/HeadProvider.ts +168 -0
  417. package/src/react/head/providers/ServerHeadProvider.ts +31 -0
  418. package/src/react/i18n/__tests__/integration.spec.tsx +239 -0
  419. package/src/react/i18n/components/Localize.spec.tsx +357 -0
  420. package/src/react/i18n/components/Localize.tsx +35 -0
  421. package/src/react/i18n/hooks/useI18n.browser.spec.tsx +438 -0
  422. package/src/react/i18n/hooks/useI18n.ts +18 -0
  423. package/src/react/i18n/index.ts +41 -0
  424. package/src/react/i18n/primitives/$dictionary.ts +69 -0
  425. package/src/react/i18n/providers/I18nProvider.spec.ts +389 -0
  426. package/src/react/i18n/providers/I18nProvider.ts +278 -0
  427. package/src/react/router/__tests__/page-head-browser.browser.spec.ts +95 -0
  428. package/src/react/router/__tests__/page-head.spec.ts +48 -0
  429. package/src/react/router/__tests__/seo-head.spec.ts +125 -0
  430. package/src/react/router/atoms/ssrManifestAtom.ts +58 -0
  431. package/src/react/router/components/ErrorViewer.tsx +872 -0
  432. package/src/react/router/components/Link.tsx +23 -0
  433. package/src/react/router/components/NestedView.tsx +223 -0
  434. package/src/react/router/components/NotFound.tsx +30 -0
  435. package/src/react/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
  436. package/src/react/router/contexts/RouterLayerContext.ts +12 -0
  437. package/src/react/router/errors/Redirection.ts +28 -0
  438. package/src/react/router/hooks/useActive.ts +52 -0
  439. package/src/react/router/hooks/useQueryParams.ts +63 -0
  440. package/src/react/router/hooks/useRouter.ts +20 -0
  441. package/src/react/router/hooks/useRouterState.ts +11 -0
  442. package/src/react/router/index.browser.ts +45 -0
  443. package/src/react/router/index.shared.ts +19 -0
  444. package/src/react/router/index.ts +142 -0
  445. package/src/react/router/primitives/$page.browser.spec.tsx +851 -0
  446. package/src/react/router/primitives/$page.spec.tsx +708 -0
  447. package/src/react/router/primitives/$page.ts +497 -0
  448. package/src/react/router/providers/ReactBrowserProvider.ts +309 -0
  449. package/src/react/router/providers/ReactBrowserRendererProvider.ts +25 -0
  450. package/src/react/router/providers/ReactBrowserRouterProvider.ts +168 -0
  451. package/src/react/router/providers/ReactPageProvider.ts +726 -0
  452. package/src/react/router/providers/ReactServerProvider.spec.tsx +316 -0
  453. package/src/react/router/providers/ReactServerProvider.ts +558 -0
  454. package/src/react/router/providers/ReactServerTemplateProvider.ts +979 -0
  455. package/src/react/router/providers/SSRManifestProvider.ts +334 -0
  456. package/src/react/router/services/ReactPageServerService.ts +48 -0
  457. package/src/react/router/services/ReactPageService.ts +27 -0
  458. package/src/react/router/services/ReactRouter.ts +262 -0
  459. package/src/react/websocket/hooks/useRoom.tsx +242 -0
  460. package/src/react/websocket/index.ts +7 -0
  461. package/src/redis/__tests__/redis.spec.ts +13 -0
  462. package/src/redis/index.ts +9 -25
  463. package/src/redis/providers/BunRedisProvider.ts +9 -0
  464. package/src/redis/providers/NodeRedisProvider.ts +8 -0
  465. package/src/redis/providers/RedisProvider.ts +16 -0
  466. package/src/retry/index.ts +11 -2
  467. package/src/router/index.ts +15 -0
  468. package/src/scheduler/index.ts +11 -2
  469. package/src/security/__tests__/BasicAuth.spec.ts +2 -0
  470. package/src/security/__tests__/ServerSecurityProvider.spec.ts +13 -5
  471. package/src/security/index.ts +15 -10
  472. package/src/security/interfaces/IssuerResolver.ts +27 -0
  473. package/src/security/primitives/$issuer.ts +55 -0
  474. package/src/security/providers/SecurityProvider.ts +179 -0
  475. package/src/security/providers/ServerBasicAuthProvider.ts +6 -2
  476. package/src/security/providers/ServerSecurityProvider.ts +36 -22
  477. package/src/server/auth/index.ts +12 -7
  478. package/src/server/cache/index.ts +7 -22
  479. package/src/server/compress/index.ts +10 -2
  480. package/src/server/cookies/index.ts +7 -5
  481. package/src/server/cookies/primitives/$cookie.ts +33 -11
  482. package/src/server/core/index.ts +17 -7
  483. package/src/server/core/interfaces/ServerRequest.ts +83 -1
  484. package/src/server/core/primitives/$action.spec.ts +1 -1
  485. package/src/server/core/primitives/$action.ts +8 -3
  486. package/src/server/core/providers/BunHttpServerProvider.ts +1 -1
  487. package/src/server/core/providers/NodeHttpServerProvider.spec.ts +125 -0
  488. package/src/server/core/providers/NodeHttpServerProvider.ts +77 -22
  489. package/src/server/core/providers/ServerLoggerProvider.ts +2 -2
  490. package/src/server/core/providers/ServerProvider.ts +9 -12
  491. package/src/server/core/services/ServerRequestParser.spec.ts +520 -0
  492. package/src/server/core/services/ServerRequestParser.ts +306 -13
  493. package/src/server/cors/index.ts +7 -21
  494. package/src/server/cors/primitives/$cors.ts +6 -2
  495. package/src/server/health/index.ts +8 -2
  496. package/src/server/helmet/index.ts +11 -3
  497. package/src/server/links/atoms/apiLinksAtom.ts +7 -0
  498. package/src/server/links/index.browser.ts +2 -0
  499. package/src/server/links/index.ts +13 -6
  500. package/src/server/metrics/index.ts +10 -3
  501. package/src/server/multipart/index.ts +9 -3
  502. package/src/server/proxy/index.ts +8 -2
  503. package/src/server/rate-limit/index.ts +21 -25
  504. package/src/server/rate-limit/primitives/$rateLimit.ts +6 -2
  505. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +38 -14
  506. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +22 -56
  507. package/src/server/static/index.ts +8 -2
  508. package/src/server/static/providers/ServerStaticProvider.ts +1 -1
  509. package/src/server/swagger/index.ts +9 -4
  510. package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
  511. package/src/sms/index.ts +9 -5
  512. package/src/sms/providers/LocalSmsProvider.spec.ts +1 -1
  513. package/src/sms/providers/LocalSmsProvider.ts +1 -1
  514. package/src/system/index.browser.ts +11 -0
  515. package/src/system/index.ts +62 -0
  516. package/src/{file → system}/providers/FileSystemProvider.ts +16 -0
  517. package/src/{file → system}/providers/MemoryFileSystemProvider.ts +116 -3
  518. package/src/system/providers/MemoryShellProvider.ts +164 -0
  519. package/src/{file → system}/providers/NodeFileSystemProvider.spec.ts +2 -2
  520. package/src/{file → system}/providers/NodeFileSystemProvider.ts +36 -0
  521. package/src/system/providers/NodeShellProvider.ts +184 -0
  522. package/src/system/providers/ShellProvider.ts +74 -0
  523. package/src/{file → system}/services/FileDetector.spec.ts +2 -2
  524. package/src/thread/index.ts +11 -2
  525. package/src/topic/core/index.ts +12 -5
  526. package/src/vite/index.ts +3 -2
  527. package/src/vite/tasks/buildClient.ts +2 -8
  528. package/src/vite/tasks/buildServer.ts +84 -21
  529. package/src/vite/tasks/copyAssets.ts +5 -4
  530. package/src/vite/tasks/generateSitemap.ts +64 -23
  531. package/src/vite/tasks/index.ts +0 -2
  532. package/src/vite/tasks/prerenderPages.ts +49 -24
  533. package/src/websocket/index.ts +12 -8
  534. package/dist/file/index.d.ts +0 -839
  535. package/dist/file/index.d.ts.map +0 -1
  536. package/dist/file/index.js.map +0 -1
  537. package/src/cli/assets/indexHtml.ts +0 -15
  538. package/src/cli/assets/mainServerTs.ts +0 -24
  539. package/src/cli/assets/webAppRouterTs.ts +0 -15
  540. package/src/cli/assets/webHelloComponentTsx.ts +0 -16
  541. package/src/cli/commands/format.ts +0 -23
  542. package/src/file/index.ts +0 -43
  543. package/src/vite/helpers/boot.ts +0 -117
  544. package/src/vite/plugins/viteAlephaDev.ts +0 -177
  545. package/src/vite/tasks/devServer.ts +0 -71
  546. package/src/vite/tasks/runAlepha.ts +0 -270
  547. /package/dist/orm/{chunk-DtkW-qnP.js → chunk-DH6iiROE.js} +0 -0
  548. /package/src/cli/{assets → templates}/apiIndexTs.ts +0 -0
  549. /package/src/cli/{assets → templates}/webIndexTs.ts +0 -0
  550. /package/src/{file → system}/errors/FileError.ts +0 -0
  551. /package/src/{file → system}/services/FileDetector.ts +0 -0
@@ -0,0 +1,480 @@
1
+ import type { Async } from "alepha";
2
+ import {
3
+ DateTimeProvider,
4
+ type DurationLike,
5
+ type Interval,
6
+ type Timeout,
7
+ } from "alepha/datetime";
8
+ import {
9
+ type DependencyList,
10
+ useCallback,
11
+ useEffect,
12
+ useRef,
13
+ useState,
14
+ } from "react";
15
+ import { useAlepha } from "./useAlepha.ts";
16
+ import { useInject } from "./useInject.ts";
17
+
18
+ /**
19
+ * Hook for handling async actions with automatic error handling and event emission.
20
+ *
21
+ * By default, prevents concurrent executions - if an action is running and you call it again,
22
+ * the second call will be ignored. Use `debounce` option to delay execution instead.
23
+ *
24
+ * Emits lifecycle events:
25
+ * - `react:action:begin` - When action starts
26
+ * - `react:action:success` - When action completes successfully
27
+ * - `react:action:error` - When action throws an error
28
+ * - `react:action:end` - Always emitted at the end
29
+ *
30
+ * @example Basic usage
31
+ * ```tsx
32
+ * const action = useAction({
33
+ * handler: async (data) => {
34
+ * await api.save(data);
35
+ * }
36
+ * }, []);
37
+ *
38
+ * <button onClick={() => action.run(data)} disabled={action.loading}>
39
+ * Save
40
+ * </button>
41
+ * ```
42
+ *
43
+ * @example With debounce (search input)
44
+ * ```tsx
45
+ * const search = useAction({
46
+ * handler: async (query: string) => {
47
+ * await api.search(query);
48
+ * },
49
+ * debounce: 300 // Wait 300ms after last call
50
+ * }, []);
51
+ *
52
+ * <input onChange={(e) => search.run(e.target.value)} />
53
+ * ```
54
+ *
55
+ * @example Run on component mount
56
+ * ```tsx
57
+ * const fetchData = useAction({
58
+ * handler: async () => {
59
+ * const data = await api.getData();
60
+ * return data;
61
+ * },
62
+ * runOnInit: true // Runs once when component mounts
63
+ * }, []);
64
+ * ```
65
+ *
66
+ * @example Run periodically (polling)
67
+ * ```tsx
68
+ * const pollStatus = useAction({
69
+ * handler: async () => {
70
+ * const status = await api.getStatus();
71
+ * return status;
72
+ * },
73
+ * runEvery: 5000 // Run every 5 seconds
74
+ * }, []);
75
+ *
76
+ * // Or with duration tuple
77
+ * const pollStatus = useAction({
78
+ * handler: async () => {
79
+ * const status = await api.getStatus();
80
+ * return status;
81
+ * },
82
+ * runEvery: [30, 'seconds'] // Run every 30 seconds
83
+ * }, []);
84
+ * ```
85
+ *
86
+ * @example With AbortController
87
+ * ```tsx
88
+ * const fetch = useAction({
89
+ * handler: async (url, { signal }) => {
90
+ * const response = await fetch(url, { signal });
91
+ * return response.json();
92
+ * }
93
+ * }, []);
94
+ * // Automatically cancelled on unmount or when new request starts
95
+ * ```
96
+ *
97
+ * @example With error handling
98
+ * ```tsx
99
+ * const deleteAction = useAction({
100
+ * handler: async (id: string) => {
101
+ * await api.delete(id);
102
+ * },
103
+ * onError: (error) => {
104
+ * if (error.code === 'NOT_FOUND') {
105
+ * // Custom error handling
106
+ * }
107
+ * }
108
+ * }, []);
109
+ *
110
+ * {deleteAction.error && <div>Error: {deleteAction.error.message}</div>}
111
+ * ```
112
+ *
113
+ * @example Global error handling
114
+ * ```tsx
115
+ * // In your root app setup
116
+ * alepha.events.on("react:action:error", ({ error }) => {
117
+ * toast.danger(error.message);
118
+ * Sentry.captureException(error);
119
+ * });
120
+ * ```
121
+ */
122
+ export function useAction<Args extends any[], Result = void>(
123
+ options: UseActionOptions<Args, Result>,
124
+ deps: DependencyList,
125
+ ): UseActionReturn<Args, Result> {
126
+ const alepha = useAlepha();
127
+ const dateTimeProvider = useInject(DateTimeProvider);
128
+ const [loading, setLoading] = useState(false);
129
+ const [error, setError] = useState<Error | undefined>();
130
+ const [result, setResult] = useState<Result | undefined>();
131
+ const isExecutingRef = useRef(false);
132
+ const debounceTimerRef = useRef<Timeout | undefined>(undefined);
133
+ const abortControllerRef = useRef<AbortController | undefined>(undefined);
134
+ const isMountedRef = useRef(true);
135
+ const intervalRef = useRef<Interval | undefined>(undefined);
136
+
137
+ // Cleanup on unmount
138
+ useEffect(() => {
139
+ return () => {
140
+ isMountedRef.current = false;
141
+
142
+ // clear debounce timer
143
+ if (debounceTimerRef.current) {
144
+ dateTimeProvider.clearTimeout(debounceTimerRef.current);
145
+ debounceTimerRef.current = undefined;
146
+ }
147
+
148
+ // clear interval
149
+ if (intervalRef.current) {
150
+ dateTimeProvider.clearInterval(intervalRef.current);
151
+ intervalRef.current = undefined;
152
+ }
153
+
154
+ // abort in-flight request
155
+ if (abortControllerRef.current) {
156
+ abortControllerRef.current.abort();
157
+ abortControllerRef.current = undefined;
158
+ }
159
+ };
160
+ }, []);
161
+
162
+ const executeAction = useCallback(
163
+ async (...args: Args): Promise<Result | undefined> => {
164
+ // Prevent concurrent executions
165
+ if (isExecutingRef.current) {
166
+ return;
167
+ }
168
+
169
+ // Abort previous request if still running
170
+ if (abortControllerRef.current) {
171
+ abortControllerRef.current.abort();
172
+ }
173
+
174
+ // Create new AbortController for this request
175
+ const abortController = new AbortController();
176
+ abortControllerRef.current = abortController;
177
+
178
+ isExecutingRef.current = true;
179
+ setLoading(true);
180
+ setError(undefined);
181
+
182
+ await alepha.events.emit("react:action:begin", {
183
+ type: "custom",
184
+ id: options.id,
185
+ });
186
+
187
+ try {
188
+ // Pass abort signal as last argument to handler
189
+ const result = await options.handler(...args, {
190
+ signal: abortController.signal,
191
+ } as any);
192
+
193
+ // TODO: it should be after onSuccess?
194
+ setResult(result as Result);
195
+
196
+ // Only update state if still mounted and not aborted
197
+ if (!isMountedRef.current || abortController.signal.aborted) {
198
+ return;
199
+ }
200
+
201
+ await alepha.events.emit("react:action:success", {
202
+ type: "custom",
203
+ id: options.id,
204
+ });
205
+
206
+ if (options.onSuccess) {
207
+ await options.onSuccess(result);
208
+ }
209
+
210
+ return result;
211
+ } catch (err) {
212
+ // Ignore abort errors
213
+ if (err instanceof Error && err.name === "AbortError") {
214
+ return;
215
+ }
216
+
217
+ // Only update state if still mounted
218
+ if (!isMountedRef.current) {
219
+ return;
220
+ }
221
+
222
+ const error = err as Error;
223
+ setError(error);
224
+
225
+ await alepha.events.emit("react:action:error", {
226
+ type: "custom",
227
+ id: options.id,
228
+ error,
229
+ });
230
+
231
+ if (options.onError) {
232
+ await options.onError(error);
233
+ } else {
234
+ // Re-throw if no custom error handler
235
+ throw error;
236
+ }
237
+ } finally {
238
+ isExecutingRef.current = false;
239
+ setLoading(false);
240
+
241
+ await alepha.events.emit("react:action:end", {
242
+ type: "custom",
243
+ id: options.id,
244
+ });
245
+
246
+ // Clean up abort controller
247
+ if (abortControllerRef.current === abortController) {
248
+ abortControllerRef.current = undefined;
249
+ }
250
+ }
251
+ },
252
+ [...deps, options.id, options.onError, options.onSuccess],
253
+ );
254
+
255
+ const handler = useCallback(
256
+ async (...args: Args): Promise<Result | undefined> => {
257
+ if (options.debounce) {
258
+ // clear existing timer
259
+ if (debounceTimerRef.current) {
260
+ dateTimeProvider.clearTimeout(debounceTimerRef.current);
261
+ }
262
+
263
+ // Set new timer
264
+ return new Promise((resolve) => {
265
+ debounceTimerRef.current = dateTimeProvider.createTimeout(
266
+ async () => {
267
+ const result = await executeAction(...args);
268
+ resolve(result);
269
+ },
270
+ options.debounce ?? 0,
271
+ );
272
+ });
273
+ }
274
+
275
+ return executeAction(...args);
276
+ },
277
+ [executeAction, options.debounce],
278
+ );
279
+
280
+ const cancel = useCallback(() => {
281
+ // clear debounce timer
282
+ if (debounceTimerRef.current) {
283
+ dateTimeProvider.clearTimeout(debounceTimerRef.current);
284
+ debounceTimerRef.current = undefined;
285
+ }
286
+
287
+ // abort in-flight request
288
+ if (abortControllerRef.current) {
289
+ abortControllerRef.current.abort();
290
+ abortControllerRef.current = undefined;
291
+ }
292
+
293
+ // reset state
294
+ if (isMountedRef.current) {
295
+ isExecutingRef.current = false;
296
+ setLoading(false);
297
+ }
298
+ }, []);
299
+
300
+ // Run action on mount if runOnInit is true
301
+ useEffect(() => {
302
+ if (options.runOnInit) {
303
+ handler(...([] as any));
304
+ }
305
+ }, deps);
306
+
307
+ // Run action periodically if runEvery is specified
308
+ useEffect(() => {
309
+ if (!options.runEvery) {
310
+ return;
311
+ }
312
+
313
+ // Set up interval
314
+ intervalRef.current = dateTimeProvider.createInterval(
315
+ () => handler(...([] as any)),
316
+ options.runEvery,
317
+ true,
318
+ );
319
+
320
+ // cleanup on unmount or when runEvery changes
321
+ return () => {
322
+ if (intervalRef.current) {
323
+ dateTimeProvider.clearInterval(intervalRef.current);
324
+ intervalRef.current = undefined;
325
+ }
326
+ };
327
+ }, [handler, options.runEvery]);
328
+
329
+ return {
330
+ run: handler,
331
+ loading,
332
+ error,
333
+ cancel,
334
+ result,
335
+ };
336
+ }
337
+
338
+ // ---------------------------------------------------------------------------------------------------------------------
339
+
340
+ /**
341
+ * Context object passed as the last argument to action handlers.
342
+ * Contains an AbortSignal that can be used to cancel the request.
343
+ */
344
+ export interface ActionContext {
345
+ /**
346
+ * AbortSignal that can be passed to fetch or other async operations.
347
+ * The signal will be aborted when:
348
+ * - The component unmounts
349
+ * - A new action is triggered (cancels previous)
350
+ * - The cancel() method is called
351
+ *
352
+ * @example
353
+ * ```tsx
354
+ * const action = useAction({
355
+ * handler: async (url, { signal }) => {
356
+ * const response = await fetch(url, { signal });
357
+ * return response.json();
358
+ * }
359
+ * }, []);
360
+ * ```
361
+ */
362
+ signal: AbortSignal;
363
+ }
364
+
365
+ export interface UseActionOptions<Args extends any[] = any[], Result = any> {
366
+ /**
367
+ * The async action handler function.
368
+ * Receives the action arguments plus an ActionContext as the last parameter.
369
+ */
370
+ handler: (...args: [...Args, ActionContext]) => Async<Result>;
371
+
372
+ /**
373
+ * Custom error handler. If provided, prevents default error re-throw.
374
+ */
375
+ onError?: (error: Error) => void | Promise<void>;
376
+
377
+ /**
378
+ * Custom success handler.
379
+ */
380
+ onSuccess?: (result: Result) => void | Promise<void>;
381
+
382
+ /**
383
+ * Optional identifier for this action (useful for debugging/analytics)
384
+ */
385
+ id?: string;
386
+
387
+ name?: string;
388
+
389
+ /**
390
+ * Debounce delay in milliseconds. If specified, the action will only execute
391
+ * after the specified delay has passed since the last call. Useful for search inputs
392
+ * or other high-frequency events.
393
+ *
394
+ * @example
395
+ * ```tsx
396
+ * // Execute search 300ms after user stops typing
397
+ * const search = useAction({ handler: search, debounce: 300 }, [])
398
+ * ```
399
+ */
400
+ debounce?: number;
401
+
402
+ /**
403
+ * If true, the action will be executed once when the component mounts.
404
+ *
405
+ * @example
406
+ * ```tsx
407
+ * const fetchData = useAction({
408
+ * handler: async () => await api.getData(),
409
+ * runOnInit: true
410
+ * }, []);
411
+ * ```
412
+ */
413
+ runOnInit?: boolean;
414
+
415
+ /**
416
+ * If specified, the action will be executed periodically at the given interval.
417
+ * The interval is specified as a DurationLike value (number in ms, Duration object, or [number, unit] tuple).
418
+ *
419
+ * @example
420
+ * ```tsx
421
+ * // Run every 5 seconds
422
+ * const poll = useAction({
423
+ * handler: async () => await api.poll(),
424
+ * runEvery: 5000
425
+ * }, []);
426
+ * ```
427
+ *
428
+ * @example
429
+ * ```tsx
430
+ * // Run every 1 minute
431
+ * const poll = useAction({
432
+ * handler: async () => await api.poll(),
433
+ * runEvery: [1, 'minute']
434
+ * }, []);
435
+ * ```
436
+ */
437
+ runEvery?: DurationLike;
438
+ }
439
+
440
+ export interface UseActionReturn<Args extends any[], Result> {
441
+ /**
442
+ * Execute the action with the provided arguments.
443
+ *
444
+ * @example
445
+ * ```tsx
446
+ * const action = useAction({ handler: async (data) => { ... } }, []);
447
+ * action.run(data);
448
+ * ```
449
+ */
450
+ run: (...args: Args) => Promise<Result | undefined>;
451
+
452
+ /**
453
+ * Loading state - true when action is executing.
454
+ */
455
+ loading: boolean;
456
+
457
+ /**
458
+ * Error state - contains error if action failed, undefined otherwise.
459
+ */
460
+ error?: Error;
461
+
462
+ /**
463
+ * Cancel any pending debounced action or abort the current in-flight request.
464
+ *
465
+ * @example
466
+ * ```tsx
467
+ * const action = useAction({ ... }, []);
468
+ *
469
+ * <button onClick={action.cancel} disabled={!action.loading}>
470
+ * Cancel
471
+ * </button>
472
+ * ```
473
+ */
474
+ cancel: () => void;
475
+
476
+ /**
477
+ * The result data from the last successful action execution.
478
+ */
479
+ result?: Result;
480
+ }
@@ -0,0 +1,26 @@
1
+ import { type Alepha, AlephaError } from "alepha";
2
+ import { useContext } from "react";
3
+ import { AlephaContext } from "../contexts/AlephaContext.ts";
4
+
5
+ /**
6
+ * Main Alepha hook.
7
+ *
8
+ * It provides access to the Alepha instance within a React component.
9
+ *
10
+ * With Alepha, you can access the core functionalities of the framework:
11
+ *
12
+ * - alepha.state() for state management
13
+ * - alepha.inject() for dependency injection
14
+ * - alepha.events.emit() for event handling
15
+ * etc...
16
+ */
17
+ export const useAlepha = (): Alepha => {
18
+ const alepha = useContext(AlephaContext);
19
+ if (!alepha) {
20
+ throw new AlephaError(
21
+ "Hook 'useAlepha()' must be used within an AlephaContext.Provider",
22
+ );
23
+ }
24
+
25
+ return alepha;
26
+ };
@@ -0,0 +1,17 @@
1
+ import {
2
+ type ClientScope,
3
+ type HttpVirtualClient,
4
+ LinkProvider,
5
+ } from "alepha/server/links";
6
+ import { useInject } from "./useInject.ts";
7
+
8
+ /**
9
+ * Hook to get a virtual client for the specified scope.
10
+ *
11
+ * It's the React-hook version of `$client()`, from `AlephaServerLinks` module.
12
+ */
13
+ export const useClient = <T extends object>(
14
+ scope?: ClientScope,
15
+ ): HttpVirtualClient<T> => {
16
+ return useInject(LinkProvider).client<T>(scope);
17
+ };
@@ -0,0 +1,51 @@
1
+ import type { Async, Hook, Hooks } from "alepha";
2
+ import { type DependencyList, useEffect } from "react";
3
+ import { useAlepha } from "./useAlepha.ts";
4
+
5
+ /**
6
+ * Allow subscribing to multiple Alepha events. See {@link Hooks} for available events.
7
+ *
8
+ * useEvents is fully typed to ensure correct event callback signatures.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * useEvents(
13
+ * {
14
+ * "react:transition:begin": (ev) => {
15
+ * console.log("Transition began to:", ev.to);
16
+ * },
17
+ * "react:transition:error": {
18
+ * priority: "first",
19
+ * callback: (ev) => {
20
+ * console.error("Transition error:", ev.error);
21
+ * },
22
+ * },
23
+ * },
24
+ * [],
25
+ * );
26
+ * ```
27
+ */
28
+ export const useEvents = (opts: UseEvents, deps: DependencyList) => {
29
+ const alepha = useAlepha();
30
+
31
+ useEffect(() => {
32
+ if (!alepha.isBrowser()) {
33
+ return;
34
+ }
35
+
36
+ const subs: Function[] = [];
37
+ for (const [name, hook] of Object.entries(opts)) {
38
+ subs.push(alepha.events.on(name as any, hook as any));
39
+ }
40
+
41
+ return () => {
42
+ for (const clear of subs) {
43
+ clear();
44
+ }
45
+ };
46
+ }, deps);
47
+ };
48
+
49
+ type UseEvents = {
50
+ [T in keyof Hooks]?: Hook<T> | ((payload: Hooks[T]) => Async<void>);
51
+ };
@@ -0,0 +1,12 @@
1
+ import type { Service } from "alepha";
2
+ import { useMemo } from "react";
3
+ import { useAlepha } from "./useAlepha.ts";
4
+
5
+ /**
6
+ * Hook to inject a service instance.
7
+ * It's a wrapper of `useAlepha().inject(service)` with a memoization.
8
+ */
9
+ export const useInject = <T extends object>(service: Service<T>): T => {
10
+ const alepha = useAlepha();
11
+ return useMemo(() => alepha.inject(service), []);
12
+ };
@@ -0,0 +1,52 @@
1
+ import type { State, Static, TAtomObject } from "alepha";
2
+ import { Atom } from "alepha";
3
+ import { useEffect, useMemo, useState } from "react";
4
+ import { useAlepha } from "./useAlepha.ts";
5
+
6
+ /**
7
+ * Hook to access and mutate the Alepha state.
8
+ */
9
+ function useStore<T extends TAtomObject>(
10
+ target: Atom<T>,
11
+ defaultValue?: Static<T>,
12
+ ): UseStoreReturn<Static<T>>;
13
+ function useStore<Key extends keyof State>(
14
+ target: Key,
15
+ defaultValue?: State[Key],
16
+ ): UseStoreReturn<State[Key]>;
17
+ function useStore(target: any, defaultValue?: any): any {
18
+ const alepha = useAlepha();
19
+
20
+ useMemo(() => {
21
+ if (defaultValue != null && alepha.store.get(target) == null) {
22
+ alepha.store.set(target, defaultValue);
23
+ }
24
+ }, [defaultValue]);
25
+
26
+ const [state, setState] = useState(alepha.store.get(target));
27
+
28
+ useEffect(() => {
29
+ if (!alepha.isBrowser()) {
30
+ return;
31
+ }
32
+
33
+ const key = target instanceof Atom ? target.key : target;
34
+
35
+ return alepha.events.on("state:mutate", (ev) => {
36
+ if (ev.key === key) {
37
+ setState(ev.value);
38
+ }
39
+ });
40
+ }, []);
41
+
42
+ return [
43
+ state,
44
+ (value: any) => {
45
+ alepha.store.set(target, value);
46
+ },
47
+ ] as const;
48
+ }
49
+
50
+ export type UseStoreReturn<T> = [T, (value: T) => void];
51
+
52
+ export { useStore };