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,401 @@
1
+ import { Alepha } from "alepha";
2
+ import { ApiKeyService } from "alepha/api/keys";
3
+ import { DateTimeProvider } from "alepha/datetime";
4
+ import { AlephaEmail } from "alepha/email";
5
+ import { AlephaSecurity } from "alepha/security";
6
+ import { AlephaServer, ForbiddenError } from "alepha/server";
7
+ import { describe, it } from "vitest";
8
+ import { $realm, AlephaApiUsers, SessionService } from "../index.ts";
9
+
10
+ const setup = async () => {
11
+ const alepha = Alepha.create({
12
+ env: { LOG_LEVEL: "error" },
13
+ });
14
+
15
+ alepha.with(AlephaServer);
16
+ alepha.with(AlephaSecurity);
17
+ alepha.with(AlephaEmail);
18
+ alepha.with(AlephaApiUsers);
19
+
20
+ // Create a realm with API keys enabled
21
+ class TestApp {
22
+ realm = $realm({
23
+ apiKeys: true,
24
+ });
25
+ }
26
+
27
+ alepha.inject(TestApp);
28
+ await alepha.start();
29
+
30
+ const sessionService = alepha.inject(SessionService);
31
+ const apiKeyService = alepha.inject(ApiKeyService);
32
+ const dateTimeProvider = alepha.inject(DateTimeProvider);
33
+
34
+ return {
35
+ alepha,
36
+ sessionService,
37
+ apiKeyService,
38
+ dateTimeProvider,
39
+ };
40
+ };
41
+
42
+ describe("alepha/api/users - API Keys Integration", () => {
43
+ it("should create an API key for a user", async ({ expect }) => {
44
+ const { sessionService, apiKeyService } = await setup();
45
+
46
+ // Create a user
47
+ const user = await sessionService.users().create({
48
+ username: "testuser",
49
+ email: "test@example.com",
50
+ roles: ["user"],
51
+ });
52
+
53
+ // Create an API key
54
+ const { apiKey, token } = await apiKeyService.create({
55
+ userId: user.id,
56
+ name: "My API Key",
57
+ roles: ["user"],
58
+ });
59
+
60
+ expect(apiKey.name).toBe("My API Key");
61
+ expect(apiKey.userId).toBe(user.id);
62
+ expect(apiKey.roles).toEqual(["user"]);
63
+ expect(token).toMatch(/^ak_/);
64
+ });
65
+
66
+ it("should validate API key and return user info", async ({ expect }) => {
67
+ const { sessionService, apiKeyService } = await setup();
68
+
69
+ // Create a user
70
+ const user = await sessionService.users().create({
71
+ username: "testuser",
72
+ email: "test@example.com",
73
+ roles: ["user"],
74
+ });
75
+
76
+ // Create an API key
77
+ const { token } = await apiKeyService.create({
78
+ userId: user.id,
79
+ name: "My API Key",
80
+ roles: ["user"],
81
+ });
82
+
83
+ // Validate the API key
84
+ const userInfo = await apiKeyService.validate(token);
85
+
86
+ expect(userInfo).not.toBeNull();
87
+ expect(userInfo?.id).toBe(user.id);
88
+ expect(userInfo?.roles).toEqual(["user"]);
89
+ });
90
+
91
+ it("should resolve user from API key in query param via resolver", async ({
92
+ expect,
93
+ }) => {
94
+ const { sessionService, apiKeyService } = await setup();
95
+
96
+ // Create a user
97
+ const user = await sessionService.users().create({
98
+ username: "testuser",
99
+ email: "test@example.com",
100
+ roles: ["user"],
101
+ });
102
+
103
+ // Create an API key
104
+ const { token } = await apiKeyService.create({
105
+ userId: user.id,
106
+ name: "My API Key",
107
+ roles: ["user"],
108
+ });
109
+
110
+ // Create resolver and test with query param
111
+ const resolver = apiKeyService.createResolver();
112
+ const userInfo = await resolver.onRequest({
113
+ url: new URL(`http://localhost/profile?api_key=${token}`),
114
+ headers: {},
115
+ } as any);
116
+
117
+ expect(userInfo).not.toBeNull();
118
+ expect(userInfo?.id).toBe(user.id);
119
+ expect(userInfo?.roles).toEqual(["user"]);
120
+ });
121
+
122
+ it("should resolve user from API key in Bearer header via resolver", async ({
123
+ expect,
124
+ }) => {
125
+ const { sessionService, apiKeyService } = await setup();
126
+
127
+ // Create a user
128
+ const user = await sessionService.users().create({
129
+ username: "testuser",
130
+ email: "test@example.com",
131
+ roles: ["user"],
132
+ });
133
+
134
+ // Create an API key
135
+ const { token } = await apiKeyService.create({
136
+ userId: user.id,
137
+ name: "My API Key",
138
+ roles: ["user"],
139
+ });
140
+
141
+ // Create resolver and test with Bearer header
142
+ const resolver = apiKeyService.createResolver();
143
+ const userInfo = await resolver.onRequest({
144
+ url: new URL("http://localhost/profile"),
145
+ headers: { authorization: `Bearer ${token}` },
146
+ } as any);
147
+
148
+ expect(userInfo).not.toBeNull();
149
+ expect(userInfo?.id).toBe(user.id);
150
+ expect(userInfo?.roles).toEqual(["user"]);
151
+ });
152
+
153
+ it("should not resolve JWT tokens as API keys", async ({ expect }) => {
154
+ const { apiKeyService } = await setup();
155
+
156
+ // Create resolver and test with a JWT-like token (contains dots)
157
+ const resolver = apiKeyService.createResolver();
158
+ const userInfo = await resolver.onRequest({
159
+ url: new URL("http://localhost/profile"),
160
+ headers: {
161
+ authorization:
162
+ "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.test.signature",
163
+ },
164
+ } as any);
165
+
166
+ // Should return null because JWT tokens should be handled by JWT resolver
167
+ expect(userInfo).toBeNull();
168
+ });
169
+
170
+ it("should reject revoked API key", async ({ expect }) => {
171
+ const { sessionService, apiKeyService } = await setup();
172
+
173
+ // Create a user
174
+ const user = await sessionService.users().create({
175
+ username: "testuser",
176
+ email: "test@example.com",
177
+ roles: ["user"],
178
+ });
179
+
180
+ // Create an API key
181
+ const { apiKey, token } = await apiKeyService.create({
182
+ userId: user.id,
183
+ name: "My API Key",
184
+ roles: ["user"],
185
+ });
186
+
187
+ // Verify key is valid
188
+ const beforeRevoke = await apiKeyService.validate(token);
189
+ expect(beforeRevoke).not.toBeNull();
190
+
191
+ // Revoke the key
192
+ await apiKeyService.revoke(apiKey.id, user.id);
193
+
194
+ // Verify key is now invalid
195
+ const afterRevoke = await apiKeyService.validate(token);
196
+ expect(afterRevoke).toBeNull();
197
+ });
198
+
199
+ it("should reject expired API key", async ({ expect }) => {
200
+ const { sessionService, apiKeyService, dateTimeProvider } = await setup();
201
+
202
+ // Create a user
203
+ const user = await sessionService.users().create({
204
+ username: "testuser",
205
+ email: "test@example.com",
206
+ roles: ["user"],
207
+ });
208
+
209
+ // Create an API key that expires in 1 hour
210
+ const expiresAt = dateTimeProvider.now().add(1, "hour").toDate();
211
+ const { token } = await apiKeyService.create({
212
+ userId: user.id,
213
+ name: "Expiring Key",
214
+ roles: ["user"],
215
+ expiresAt,
216
+ });
217
+
218
+ // Verify key is valid
219
+ const beforeExpiry = await apiKeyService.validate(token);
220
+ expect(beforeExpiry).not.toBeNull();
221
+
222
+ // Travel forward in time past expiry
223
+ dateTimeProvider.travel(2, "hours");
224
+
225
+ // Verify key is now invalid
226
+ const afterExpiry = await apiKeyService.validate(token);
227
+ expect(afterExpiry).toBeNull();
228
+ });
229
+
230
+ it("should reject invalid API key", async ({ expect }) => {
231
+ await setup();
232
+
233
+ const { apiKeyService } = await setup();
234
+
235
+ // Try to validate an invalid token
236
+ const result = await apiKeyService.validate("ak_invalid_token_12345678");
237
+ expect(result).toBeNull();
238
+ });
239
+
240
+ it("should list user's API keys", async ({ expect }) => {
241
+ const { sessionService, apiKeyService } = await setup();
242
+
243
+ // Create a user
244
+ const user = await sessionService.users().create({
245
+ username: "testuser",
246
+ email: "test@example.com",
247
+ roles: ["user"],
248
+ });
249
+
250
+ // Create multiple API keys
251
+ await apiKeyService.create({
252
+ userId: user.id,
253
+ name: "Key 1",
254
+ roles: ["user"],
255
+ });
256
+ await apiKeyService.create({
257
+ userId: user.id,
258
+ name: "Key 2",
259
+ roles: ["user"],
260
+ });
261
+
262
+ // List keys
263
+ const keys = await apiKeyService.list(user.id);
264
+
265
+ expect(keys).toHaveLength(2);
266
+ expect(keys.map((k) => k.name).sort()).toEqual(["Key 1", "Key 2"]);
267
+ });
268
+
269
+ it("should not allow revoking another user's API key", async ({ expect }) => {
270
+ const { sessionService, apiKeyService } = await setup();
271
+
272
+ // Create two users
273
+ const user1 = await sessionService.users().create({
274
+ username: "user1",
275
+ email: "user1@example.com",
276
+ roles: ["user"],
277
+ });
278
+ const user2 = await sessionService.users().create({
279
+ username: "user2",
280
+ email: "user2@example.com",
281
+ roles: ["user"],
282
+ });
283
+
284
+ // Create an API key for user1
285
+ const { apiKey } = await apiKeyService.create({
286
+ userId: user1.id,
287
+ name: "User1 Key",
288
+ roles: ["user"],
289
+ });
290
+
291
+ // Try to revoke user1's key as user2
292
+ await expect(
293
+ apiKeyService.revoke(apiKey.id, user2.id),
294
+ ).rejects.toThrowError(ForbiddenError);
295
+ });
296
+
297
+ it("should create API key with description", async ({ expect }) => {
298
+ const { sessionService, apiKeyService } = await setup();
299
+
300
+ // Create a user
301
+ const user = await sessionService.users().create({
302
+ username: "testuser",
303
+ email: "test@example.com",
304
+ roles: ["user", "admin"],
305
+ });
306
+
307
+ // Create API key with description
308
+ const { apiKey, token } = await apiKeyService.create({
309
+ userId: user.id,
310
+ name: "My Key",
311
+ description: "Used for CI/CD pipeline",
312
+ roles: ["user", "admin"],
313
+ });
314
+
315
+ expect(apiKey.name).toBe("My Key");
316
+ expect(apiKey.description).toBe("Used for CI/CD pipeline");
317
+ expect(apiKey.roles).toEqual(["user", "admin"]);
318
+ expect(token).toMatch(/^ak_/);
319
+
320
+ // Validate works
321
+ const userInfo = await apiKeyService.validate(token);
322
+ expect(userInfo?.id).toBe(user.id);
323
+ expect(userInfo?.roles).toEqual(["user", "admin"]);
324
+ });
325
+
326
+ it("should support API key with admin role", async ({ expect }) => {
327
+ const { sessionService, apiKeyService } = await setup();
328
+
329
+ // Create an admin user
330
+ const adminUser = await sessionService.users().create({
331
+ username: "admin",
332
+ email: "admin@example.com",
333
+ roles: ["admin"],
334
+ });
335
+
336
+ // Create an API key with admin role
337
+ const { token } = await apiKeyService.create({
338
+ userId: adminUser.id,
339
+ name: "Admin API Key",
340
+ roles: ["admin"],
341
+ });
342
+
343
+ // Validate API key returns admin role
344
+ const userInfo = await apiKeyService.validate(token);
345
+ expect(userInfo).not.toBeNull();
346
+ expect(userInfo?.id).toBe(adminUser.id);
347
+ expect(userInfo?.roles).toEqual(["admin"]);
348
+ });
349
+
350
+ it("should not revoke already revoked keys twice", async ({ expect }) => {
351
+ const { sessionService, apiKeyService } = await setup();
352
+
353
+ // Create a user
354
+ const user = await sessionService.users().create({
355
+ username: "testuser",
356
+ email: "test@example.com",
357
+ roles: ["user"],
358
+ });
359
+
360
+ // Create and revoke an API key
361
+ const { apiKey, token } = await apiKeyService.create({
362
+ userId: user.id,
363
+ name: "My Key",
364
+ roles: ["user"],
365
+ });
366
+
367
+ await apiKeyService.revoke(apiKey.id, user.id);
368
+
369
+ // Verify key is revoked
370
+ const result = await apiKeyService.validate(token);
371
+ expect(result).toBeNull();
372
+
373
+ // Admin revoke should not fail on already revoked key
374
+ await apiKeyService.revokeByAdmin(apiKey.id);
375
+ });
376
+
377
+ it("should create API key with custom prefix", async ({ expect }) => {
378
+ const { sessionService, apiKeyService } = await setup();
379
+
380
+ // Create a user
381
+ const user = await sessionService.users().create({
382
+ username: "testuser",
383
+ email: "test@example.com",
384
+ roles: ["user"],
385
+ });
386
+
387
+ // Create an API key with custom prefix
388
+ const { token } = await apiKeyService.create({
389
+ userId: user.id,
390
+ name: "Custom Key",
391
+ roles: ["user"],
392
+ prefix: "prod",
393
+ });
394
+
395
+ expect(token).toMatch(/^prod_/);
396
+
397
+ // Should still validate
398
+ const userInfo = await apiKeyService.validate(token);
399
+ expect(userInfo).not.toBeNull();
400
+ });
401
+ });
@@ -57,10 +57,21 @@ export * from "./services/UserService.ts";
57
57
  // ---------------------------------------------------------------------------------------------------------------------
58
58
 
59
59
  /**
60
- * Provides user management API endpoints for Alepha applications.
60
+ * | type | quality | stability |
61
+ * |------|---------|-----------|
62
+ * | backend | epic | stable |
61
63
  *
62
- * This module includes user CRUD operations, authentication endpoints,
63
- * password reset functionality, and user profile management capabilities.
64
+ * Complete user management with multi-realm support for multi-tenant applications.
65
+ *
66
+ * **Features:**
67
+ * - User registration, login, and profile management
68
+ * - Password reset workflows
69
+ * - Email verification
70
+ * - Session management with multiple devices
71
+ * - Identity management (social logins, SSO)
72
+ * - Multi-realm support for tenant isolation
73
+ * - Credential management
74
+ * - Entities: `users`, `identities`, `sessions`
64
75
  *
65
76
  * @module alepha.api.users
66
77
  */
@@ -1,11 +1,14 @@
1
1
  import { $context } from "alepha";
2
2
  import { AlephaApiAudits } from "alepha/api/audits";
3
3
  import { AlephaApiFiles } from "alepha/api/files";
4
+ import { AlephaApiJobs } from "alepha/api/jobs";
5
+ import { AlephaApiKeys, ApiKeyService } from "alepha/api/keys";
4
6
  import type { Repository } from "alepha/orm";
5
7
  import {
6
8
  $issuer,
7
9
  type IssuerPrimitive,
8
10
  type IssuerPrimitiveOptions,
11
+ type IssuerResolver,
9
12
  SecurityProvider,
10
13
  } from "alepha/security";
11
14
  import {
@@ -65,13 +68,29 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
65
68
 
66
69
  const realmRegistration = realmProvider.register(name, options);
67
70
 
71
+ // For now, all modules are enabled
68
72
  alepha.with(AlephaApiFiles);
69
73
  alepha.with(AlephaApiAudits);
74
+ alepha.with(AlephaApiJobs);
75
+
76
+ // Collect custom resolvers that will be registered during $issuer.onInit()
77
+ // This ensures they are registered AFTER the realm is created (not on the default test realm)
78
+ const customResolvers: IssuerResolver[] = [
79
+ ...(options.issuer?.resolvers ?? []),
80
+ ];
81
+
82
+ // Enable API key authentication - must be added to customResolvers before $issuer() call
83
+ if (options.apiKeys) {
84
+ alepha.with(AlephaApiKeys);
85
+ const apiKeyService = alepha.inject(ApiKeyService);
86
+ customResolvers.push(apiKeyService.createResolver());
87
+ }
70
88
 
71
89
  const realm: RealmPrimitive = $issuer({
72
90
  ...options.issuer,
73
91
  name,
74
92
  secret: options.secret ?? securityProvider.secretKey,
93
+ resolvers: customResolvers,
75
94
  roles: options.issuer?.roles ?? [
76
95
  {
77
96
  name: "admin",
@@ -189,9 +208,18 @@ export interface RealmOptions {
189
208
  github?: true;
190
209
  };
191
210
 
192
- modules?: {
193
- files?: boolean;
194
- audits?: boolean;
195
- jobs?: boolean;
196
- };
211
+ /**
212
+ * Enable API key authentication.
213
+ *
214
+ * When enabled, users can create API keys to access protected endpoints
215
+ * without using JWT tokens. API keys are useful for:
216
+ * - Programmatic access (CLI tools, scripts)
217
+ * - Long-lived authentication tokens
218
+ * - Third-party integrations
219
+ *
220
+ * API keys can be passed via:
221
+ * - Query parameter: `?api_key=ak_xxx`
222
+ * - Bearer header: `Authorization: Bearer ak_xxx`
223
+ */
224
+ apiKeys?: boolean;
197
225
  }
@@ -1,4 +1,4 @@
1
- import { $hook, $inject, Alepha, AlephaError } from "alepha";
1
+ import { $inject, Alepha, AlephaError } from "alepha";
2
2
  import { $bucket } from "alepha/bucket";
3
3
  import { $repository, type Repository } from "alepha/orm";
4
4
  import {
@@ -36,17 +36,6 @@ export class RealmProvider {
36
36
  mimeTypes: ["image/jpeg", "image/png", "image/gif", "image/webp"],
37
37
  });
38
38
 
39
- protected readonly onConfigure = $hook({
40
- on: "configure",
41
- handler: () => {
42
- this.alepha.store.set("alepha.server.security.system.user", {
43
- id: "00000000-0000-0000-0000-000000000000",
44
- name: "system",
45
- roles: ["admin"], // TODO: use realm config
46
- });
47
- },
48
- });
49
-
50
39
  public register(realmName: string, realmOptions: RealmOptions = {}) {
51
40
  this.realms.set(realmName, {
52
41
  name: realmName,
@@ -3,7 +3,6 @@ import { $inject, Alepha } from "alepha";
3
3
  import { AuditService } from "alepha/api/audits";
4
4
  import type { FileController } from "alepha/api/files";
5
5
  import { DateTimeProvider } from "alepha/datetime";
6
- import { FileSystemProvider } from "alepha/file";
7
6
  import { $logger } from "alepha/logger";
8
7
  import {
9
8
  CryptoProvider,
@@ -13,6 +12,7 @@ import {
13
12
  import { type ServerRequest, UnauthorizedError } from "alepha/server";
14
13
  import type { OAuth2Profile } from "alepha/server/auth";
15
14
  import { $client } from "alepha/server/links";
15
+ import { FileSystemProvider } from "alepha/system";
16
16
  import type { UserEntity } from "../entities/users.ts";
17
17
  import { RealmProvider } from "../providers/RealmProvider.ts";
18
18
 
@@ -15,6 +15,7 @@ export class VerificationController {
15
15
  path: `${this.url}/:type`,
16
16
  group: this.group,
17
17
  method: "POST",
18
+ secure: false,
18
19
  schema: {
19
20
  params: t.object({
20
21
  type: verificationTypeEnumSchema,
@@ -36,6 +37,7 @@ export class VerificationController {
36
37
  path: `${this.url}/:type/validate`,
37
38
  group: this.group,
38
39
  method: "POST",
40
+ secure: false,
39
41
  schema: {
40
42
  params: t.object({
41
43
  type: verificationTypeEnumSchema,
@@ -18,11 +18,17 @@ export * from "./services/VerificationService.ts";
18
18
  // ---------------------------------------------------------------------------------------------------------------------
19
19
 
20
20
  /**
21
- * Provides email/phone verification management API endpoints for Alepha applications.
21
+ * | type | quality | stability |
22
+ * |------|---------|-----------|
23
+ * | backend | standard | stable |
22
24
  *
23
- * This module includes verification code generation, validation,
24
- * and related functionalities. Notifications are handled by the consuming module
25
- * (e.g., api-users) for context-specific messaging.
25
+ * Email and phone verification workflows.
26
+ *
27
+ * **Features:**
28
+ * - Verification token generation
29
+ * - Verification code sending
30
+ * - Verification completion tracking
31
+ * - Resend functionality
26
32
  *
27
33
  * @module alepha.api.verifications
28
34
  */
@@ -10,45 +10,18 @@ export * from "./providers/BatchProvider.ts";
10
10
  // ---------------------------------------------------------------------------------------------------------------------
11
11
 
12
12
  /**
13
- * This module allows you to group multiple asynchronous operations into a single "batch," which is then processed together.
14
- * This is an essential pattern for improving performance, reducing I/O, and interacting efficiently with rate-limited APIs or databases.
13
+ * | type | quality | stability |
14
+ * |------|---------|-----------|
15
+ * | backend | standard | stable |
15
16
  *
16
- * ```ts
17
- * import { Alepha, $hook, run, t } from "alepha";
18
- * import { $batch } from "alepha/batch";
17
+ * Batch accumulation and processing.
19
18
  *
20
- * class LoggingService {
21
- * // define the batch processor
22
- * logBatch = $batch({
23
- * schema: t.text(),
24
- * maxSize: 10,
25
- * maxDuration: [5, "seconds"],
26
- * handler: async (items) => {
27
- * console.log(`[BATCH LOG] Processing ${items.length} events:`, items);
28
- * },
29
- * });
19
+ * **Features:**
20
+ * - Batch accumulator with handler
21
+ * - Configurable batch size
22
+ * - Time-based triggers
23
+ * - Status tracking
30
24
  *
31
- * // example of how to use it
32
- * onReady = $hook({
33
- * on: "ready",
34
- * handler: async () => {
35
- * // push() returns an ID immediately
36
- * const id1 = await this.logBatch.push("Application started.");
37
- * const id2 = await this.logBatch.push("User authenticated.");
38
- *
39
- * // optionally wait for processing to complete
40
- * await this.logBatch.wait(id1);
41
- *
42
- * // or check the status
43
- * const status = this.logBatch.status(id2);
44
- * console.log(status?.status); // "pending" | "processing" | "completed" | "failed"
45
- * },
46
- * });
47
- * }
48
- * ```
49
- *
50
- * @see {@link $batch}
51
- * @see {@link BatchProvider}
52
25
  * @module alepha.batch
53
26
  */
54
27
  export const AlephaBatch = $module({
@@ -159,14 +159,6 @@ export class BatchPrimitive<
159
159
  await this.batchProvider.markReady(this.context);
160
160
  },
161
161
  });
162
-
163
- protected readonly dispose = $hook({
164
- on: "stop",
165
- priority: "first",
166
- handler: async () => {
167
- await this.batchProvider.shutdown(this.context);
168
- },
169
- });
170
162
  }
171
163
 
172
164
  $batch[KIND] = BatchPrimitive;