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
@@ -15,6 +15,7 @@ import { InvalidPermissionError } from "../errors/InvalidPermissionError.ts";
15
15
  import { InvalidTokenError } from "../errors/InvalidTokenError.ts";
16
16
  import { RealmNotFoundError } from "../errors/RealmNotFoundError.ts";
17
17
  import { SecurityError } from "../errors/SecurityError.ts";
18
+ import type { IssuerResolver, UserInfo } from "../interfaces/IssuerResolver.ts";
18
19
  import type { UserAccountToken } from "../interfaces/UserAccountToken.ts";
19
20
  import type { Permission } from "../schemas/permissionSchema.ts";
20
21
  import type { Role } from "../schemas/roleSchema.ts";
@@ -90,10 +91,46 @@ export class SecurityProvider {
90
91
  typeof realm.secret === "function" ? realm.secret() : realm.secret;
91
92
  this.jwt.setKeyLoader(realm.name, secret);
92
93
  }
94
+
95
+ // Register default JWT resolver for realms without resolvers
96
+ if (!realm.resolvers || realm.resolvers.length === 0) {
97
+ this.registerResolver(
98
+ this.createDefaultJwtResolver(realm.name),
99
+ realm.name,
100
+ );
101
+ }
93
102
  }
94
103
  },
95
104
  });
96
105
 
106
+ /**
107
+ * Creates a default JWT resolver for a realm.
108
+ */
109
+ protected createDefaultJwtResolver(realmName: string): IssuerResolver {
110
+ return {
111
+ priority: 100,
112
+ onRequest: async (req) => {
113
+ const auth = req.headers.authorization;
114
+ if (!auth?.startsWith("Bearer ")) {
115
+ return null;
116
+ }
117
+
118
+ const token = auth.slice(7);
119
+
120
+ // Check if it looks like a JWT (has dots)
121
+ if (!token.includes(".")) {
122
+ return null;
123
+ }
124
+
125
+ // Parse and validate JWT
126
+ const { result } = await this.jwt.parse(token, realmName);
127
+
128
+ // Extract user info from JWT payload
129
+ return this.createUserFromPayload(result.payload, realmName);
130
+ },
131
+ };
132
+ }
133
+
97
134
  /**
98
135
  * Adds a role to one or more realms.
99
136
  *
@@ -305,6 +342,143 @@ export class SecurityProvider {
305
342
  };
306
343
  }
307
344
 
345
+ /**
346
+ * Generic user creation from any source (JWT, API key, etc.).
347
+ * Handles permission checking, ownership, default roles.
348
+ */
349
+ public createUser(
350
+ userInfo: UserInfo,
351
+ options: {
352
+ realm?: string;
353
+ permission?: Permission | string;
354
+ } = {},
355
+ ): UserAccountToken {
356
+ const realmRoles = this.getRoles(options.realm).filter((it) => it.default);
357
+ const roles = [...(userInfo.roles ?? [])];
358
+
359
+ // Add default roles
360
+ for (const role of realmRoles) {
361
+ if (!roles.includes(role.name)) {
362
+ roles.push(role.name);
363
+ }
364
+ }
365
+
366
+ let ownership: string | boolean | undefined;
367
+
368
+ // Permission check
369
+ if (options.permission) {
370
+ const check = this.checkPermission(options.permission, ...roles);
371
+ if (!check.isAuthorized) {
372
+ throw new SecurityError(
373
+ `User is not allowed to access '${this.permissionToString(options.permission)}'`,
374
+ );
375
+ }
376
+ ownership = check.ownership;
377
+ }
378
+
379
+ return {
380
+ ...userInfo,
381
+ roles,
382
+ ownership,
383
+ realm: options.realm,
384
+ };
385
+ }
386
+
387
+ /**
388
+ * Register a resolver to a realm.
389
+ * Resolvers are sorted by priority (lower = first).
390
+ */
391
+ public registerResolver(resolver: IssuerResolver, realmName?: string): void {
392
+ const realm = this.getRealm(realmName);
393
+ if (!realm.resolvers) {
394
+ realm.resolvers = [];
395
+ }
396
+
397
+ realm.resolvers.push(resolver);
398
+ realm.resolvers.sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
399
+ }
400
+
401
+ /**
402
+ * Get a realm by name.
403
+ * Throws if realm not found.
404
+ */
405
+ public getRealm(realmName?: string): Realm {
406
+ const realm = realmName
407
+ ? this.realms.find((it) => it.name === realmName)
408
+ : this.realms[0];
409
+
410
+ if (!realm) {
411
+ throw new RealmNotFoundError(realmName ?? "default");
412
+ }
413
+
414
+ return realm;
415
+ }
416
+
417
+ /**
418
+ * Resolve user from request using registered resolvers.
419
+ * Returns undefined if no resolver could authenticate (no auth provided).
420
+ * Throws UnauthorizedError if auth was provided but invalid.
421
+ *
422
+ * Note: This method tries resolvers from ALL realms to find a match,
423
+ * regardless of the `realm` option. The `realm` option is only used for
424
+ * permission checking after the user is resolved.
425
+ */
426
+ public async resolveUserFromServerRequest(
427
+ req: { url: URL | string; headers: { authorization?: string } },
428
+ options: {
429
+ realm?: string;
430
+ permission?: Permission | string;
431
+ } = {},
432
+ ): Promise<UserAccountToken | undefined> {
433
+ // Collect all resolvers from all realms with their realm name
434
+ const allResolvers: Array<{
435
+ resolver: IssuerResolver;
436
+ realmName: string;
437
+ }> = [];
438
+
439
+ for (const realm of this.realms) {
440
+ for (const resolver of realm.resolvers ?? []) {
441
+ allResolvers.push({ resolver, realmName: realm.name });
442
+ }
443
+ }
444
+
445
+ // Sort by priority
446
+ allResolvers.sort(
447
+ (a, b) => (a.resolver.priority ?? 100) - (b.resolver.priority ?? 100),
448
+ );
449
+
450
+ // Try resolvers in priority order
451
+ for (const { resolver, realmName } of allResolvers) {
452
+ let userInfo: UserInfo | null;
453
+
454
+ try {
455
+ userInfo = await resolver.onRequest(req as any);
456
+ } catch {
457
+ // Resolver failed (e.g., wrong key), try next
458
+ continue;
459
+ }
460
+
461
+ if (userInfo) {
462
+ // User was resolved - now create user and check permissions
463
+ // (errors from createUser should propagate, not be caught)
464
+ const user = this.createUser(userInfo, {
465
+ realm: realmName,
466
+ permission: options.permission,
467
+ });
468
+
469
+ await this.alepha.events.emit("security:user:created", {
470
+ realm: realmName,
471
+ user,
472
+ });
473
+
474
+ return user;
475
+ }
476
+ }
477
+
478
+ // No resolver matched = no auth provided
479
+ return undefined;
480
+ }
481
+
308
482
  /**
309
483
  * Checks if the user has the specified permission.
310
484
  *
@@ -783,6 +957,11 @@ export interface Realm {
783
957
  * By default, SecurityProvider has his own implementation, but this method allow to override it.
784
958
  */
785
959
  profile?: (raw: Record<string, any>) => UserAccount;
960
+
961
+ /**
962
+ * Custom resolvers for this realm (sorted by priority).
963
+ */
964
+ resolvers?: IssuerResolver[];
786
965
  }
787
966
 
788
967
  export interface SecurityCheckResult {
@@ -15,9 +15,13 @@ export interface BasicAuthOptions {
15
15
  }
16
16
 
17
17
  export interface BasicAuthPrimitiveConfig extends BasicAuthOptions {
18
- /** Name identifier for this basic auth (default: property key) */
18
+ /**
19
+ * Name identifier for this basic auth (default: property key).
20
+ */
19
21
  name?: string;
20
- /** Path patterns to match (supports wildcards like /devtools/*) */
22
+ /**
23
+ * Path patterns to match (supports wildcards like /devtools/*).
24
+ */
21
25
  paths?: string[];
22
26
  }
23
27
 
@@ -7,6 +7,7 @@ import {
7
7
  type ServerRequest,
8
8
  UnauthorizedError,
9
9
  } from "alepha/server";
10
+ import { InvalidTokenError } from "../errors/InvalidTokenError.ts";
10
11
  import type { UserAccountToken } from "../interfaces/UserAccountToken.ts";
11
12
  import type { Permission } from "../schemas/permissionSchema.ts";
12
13
  import { userAccountInfoSchema } from "../schemas/userAccountInfoSchema.ts";
@@ -23,6 +24,8 @@ export class ServerSecurityProvider {
23
24
  protected readonly jwtProvider = $inject(JwtProvider);
24
25
  protected readonly alepha = $inject(Alepha);
25
26
 
27
+ protected readonly resolvers: Array<ServerSecurityUserResolver> = [];
28
+
26
29
  protected readonly onConfigure = $hook({
27
30
  on: "configure",
28
31
  handler: async () => {
@@ -119,20 +122,35 @@ export class ServerSecurityProvider {
119
122
  .getPermissions()
120
123
  .find((it) => it.path === route.path && it.method === route.method);
121
124
 
122
- if (!request.headers.authorization && !route.secure && !permission) {
123
- this.log.trace(
124
- "Skipping security check for route - no authorization header and not secure",
125
- );
126
- return;
127
- }
125
+ const realm =
126
+ typeof route.secure === "object" ? route.secure.realm : undefined;
128
127
 
129
128
  try {
130
- // set user to request
131
- request.user = await this.securityProvider.createUserFromToken(
132
- request.headers.authorization,
133
- { permission },
129
+ // Try to resolve user (JWT, API key, etc.)
130
+ request.user = await this.securityProvider.resolveUserFromServerRequest(
131
+ request,
132
+ { permission, realm },
134
133
  );
135
134
 
135
+ // No user resolved?
136
+ if (!request.user) {
137
+ // Route requires auth → throw
138
+ if (route.secure || permission) {
139
+ // Provide a more specific error message when no auth header was provided
140
+ if (!request.headers.authorization) {
141
+ throw new InvalidTokenError(
142
+ "Invalid authorization header, maybe token is missing ?",
143
+ );
144
+ }
145
+ throw new UnauthorizedError("Authentication required");
146
+ }
147
+ // Route is public → skip
148
+ this.log.trace(
149
+ "Skipping security check for route - no auth provided and not required",
150
+ );
151
+ return;
152
+ }
153
+
136
154
  if (typeof route.secure === "object") {
137
155
  this.check(request.user, route.secure);
138
156
  }
@@ -143,7 +161,7 @@ export class ServerSecurityProvider {
143
161
  this.alepha.codec.decode(userAccountInfoSchema, request.user),
144
162
  );
145
163
 
146
- this.log.trace("User set from request token", {
164
+ this.log.trace("User set from request", {
147
165
  user: request.user,
148
166
  permission,
149
167
  });
@@ -209,19 +227,10 @@ export class ServerSecurityProvider {
209
227
  }
210
228
 
211
229
  if (!user) {
212
- // in testing mode, we create a test user
213
- if (this.alepha.isTest() && !("user" in options)) {
214
- return this.createTestUser();
215
- }
216
-
217
230
  throw new UnauthorizedError("User is required for calling this action");
218
231
  }
219
232
 
220
- const roles =
221
- user.roles ??
222
- (this.alepha.isTest()
223
- ? this.securityProvider.getRoles().map((role) => role.name)
224
- : []);
233
+ const roles = user.roles ?? [];
225
234
  let ownership: boolean | string | undefined;
226
235
 
227
236
  if (permission) {
@@ -264,7 +273,8 @@ export class ServerSecurityProvider {
264
273
  }
265
274
 
266
275
  // skip helper if user is explicitly set to undefined
267
- if ("user" in options && options.user === undefined) {
276
+ //if ("user" in options && options.user === undefined) {
277
+ if (!options.user) {
268
278
  return;
269
279
  }
270
280
 
@@ -295,3 +305,7 @@ export type ServerRouteSecure = {
295
305
  realm?: string;
296
306
  basic?: BasicAuthOptions;
297
307
  };
308
+
309
+ export type ServerSecurityUserResolver = (
310
+ request: ServerRequest,
311
+ ) => Promise<UserAccountToken | undefined>;
@@ -29,16 +29,21 @@ declare module "alepha" {
29
29
  // ---------------------------------------------------------------------------------------------------------------------
30
30
 
31
31
  /**
32
- * Allow authentication services for server applications.
33
- * It provides login and logout functionalities.
32
+ * | type | quality | stability |
33
+ * |------|---------|-----------|
34
+ * | backend | rare | stable |
34
35
  *
35
- * There are multiple authentication providers available (e.g., Google, GitHub).
36
- * You can also delegate authentication to your own OIDC/OAuth2, for example using Keycloak or Auth0.
36
+ * OAuth2/OIDC authentication with social login providers.
37
37
  *
38
- * It's cookie-based and SSR friendly.
38
+ * **Features:**
39
+ * - OAuth authentication provider
40
+ * - Username/password authentication
41
+ * - Google OAuth integration
42
+ * - GitHub OAuth integration
43
+ * - Apple OAuth integration
44
+ * - Cookie-based, SSR-friendly authentication
45
+ * - Token management and refresh
39
46
  *
40
- * @see {@link $auth}
41
- * @see {@link ServerAuthProvider}
42
47
  * @module alepha.server.auth
43
48
  */
44
49
  export const AlephaServerAuth = $module({
@@ -9,31 +9,16 @@ export * from "./providers/ServerCacheProvider.ts";
9
9
  // ---------------------------------------------------------------------------------------------------------------------
10
10
 
11
11
  /**
12
- * Plugin for Alepha Server that provides server-side caching capabilities.
13
- * It uses the Alepha Cache module to cache responses from server actions ($action).
14
- * It also provides a ETag-based cache invalidation mechanism.
12
+ * | type | quality | stability |
13
+ * |------|---------|-----------|
14
+ * | backend | standard | stable |
15
15
  *
16
- * @example
17
- * ```ts
18
- * import { Alepha } from "alepha";
19
- * import { $action } from "alepha/server";
20
- * import { AlephaServerCache } from "alepha/server/cache";
16
+ * ETag-based response caching.
21
17
  *
22
- * class ApiServer {
23
- * hello = $action({
24
- * cache: true,
25
- * handler: () => "Hello, World!",
26
- * });
27
- * }
18
+ * **Features:**
19
+ * - ETag generation and validation
20
+ * - Conditional request handling
28
21
  *
29
- * const alepha = Alepha.create()
30
- * .with(AlephaServerCache)
31
- * .with(ApiServer);
32
- *
33
- * run(alepha);
34
- * ```
35
- *
36
- * @see {@link ServerCacheProvider}
37
22
  * @module alepha.server.cache
38
23
  */
39
24
  export const AlephaServerCache = $module({
@@ -9,9 +9,17 @@ export * from "./providers/ServerCompressProvider.ts";
9
9
  // ---------------------------------------------------------------------------------------------------------------------
10
10
 
11
11
  /**
12
- * Plugin for Alepha Server that provides server-side compression capabilities.
12
+ * | type | quality | stability |
13
+ * |------|---------|-----------|
14
+ * | backend | standard | stable |
13
15
  *
14
- * Compresses responses using gzip, brotli, or zstd based on the `Accept-Encoding` header.
16
+ * Response compression.
17
+ *
18
+ * **Features:**
19
+ * - Gzip compression
20
+ * - Brotli compression
21
+ *
22
+ * @module alepha.server.compress
15
23
  */
16
24
  export const AlephaServerCompress = $module({
17
25
  name: "alepha.server.compress",
@@ -18,13 +18,15 @@ declare module "alepha/server" {
18
18
  }
19
19
 
20
20
  /**
21
- * Provides HTTP cookie management capabilities for server requests and responses with type-safe cookie primitives.
21
+ * | type | quality | stability |
22
+ * |------|---------|-----------|
23
+ * | backend | standard | stable |
22
24
  *
23
- * The server-cookies module enables declarative cookie handling using the `$cookie` primitive on class properties.
24
- * It offers automatic cookie parsing, secure cookie configuration, and seamless integration with server routes
25
- * for managing user sessions, preferences, and authentication tokens.
25
+ * Server and browser-safe cookie handling.
26
+ *
27
+ * **Features:**
28
+ * - Cookie management on server and browser
26
29
  *
27
- * @see {@link $cookie}
28
30
  * @module alepha.server.cookies
29
31
  */
30
32
  export const AlephaServerCookies = $module({
@@ -23,37 +23,59 @@ export const $cookie = <T extends TSchema>(
23
23
  // ---------------------------------------------------------------------------------------------------------------------
24
24
 
25
25
  export interface CookiePrimitiveOptions<T extends TSchema> {
26
- /** The schema for the cookie's value, used for validation and type safety. */
26
+ /**
27
+ * The schema for the cookie's value, used for validation and type safety.
28
+ */
27
29
  schema: T;
28
30
 
29
- /** The name of the cookie. */
31
+ /**
32
+ * The name of the cookie.
33
+ */
30
34
  name?: string;
31
35
 
32
- /** The cookie's path. Defaults to "/". */
36
+ /**
37
+ * The cookie's path. Defaults to "/".
38
+ */
33
39
  path?: string;
34
40
 
35
- /** Time-to-live for the cookie. Maps to `Max-Age`. */
41
+ /**
42
+ * Time-to-live for the cookie. Maps to `Max-Age`.
43
+ */
36
44
  ttl?: DurationLike;
37
45
 
38
- /** If true, the cookie is only sent over HTTPS. Defaults to true in production. */
46
+ /**
47
+ * If true, the cookie is only sent over HTTPS. Defaults to true in production.
48
+ */
39
49
  secure?: boolean;
40
50
 
41
- /** If true, the cookie cannot be accessed by client-side scripts. */
51
+ /**
52
+ * If true, the cookie cannot be accessed by client-side scripts.
53
+ */
42
54
  httpOnly?: boolean;
43
55
 
44
- /** SameSite policy for the cookie. Defaults to "lax". */
56
+ /**
57
+ * SameSite policy for the cookie. Defaults to "lax".
58
+ */
45
59
  sameSite?: "strict" | "lax" | "none";
46
60
 
47
- /** The domain for the cookie. */
61
+ /**
62
+ * The domain for the cookie.
63
+ */
48
64
  domain?: string;
49
65
 
50
- /** If true, the cookie value will be compressed using zlib. */
66
+ /**
67
+ * If true, the cookie value will be compressed using zlib.
68
+ */
51
69
  compress?: boolean;
52
70
 
53
- /** If true, the cookie value will be encrypted. Requires `COOKIE_SECRET` env var. */
71
+ /**
72
+ * If true, the cookie value will be encrypted. Requires `COOKIE_SECRET` env var.
73
+ */
54
74
  encrypt?: boolean;
55
75
 
56
- /** If true, the cookie will be signed to prevent tampering. Requires `COOKIE_SECRET` env var. */
76
+ /**
77
+ * If true, the cookie will be signed to prevent tampering. Requires `COOKIE_SECRET` env var.
78
+ */
57
79
  sign?: boolean;
58
80
  }
59
81
 
@@ -114,14 +114,24 @@ export * from "./services/UserAgentParser.ts";
114
114
  // ---------------------------------------------------------------------------------------------------------------------
115
115
 
116
116
  /**
117
- * Provides high-performance HTTP server capabilities with declarative routing and action primitives.
117
+ * | type | quality | stability |
118
+ * |------|---------|-----------|
119
+ * | backend | epic | stable |
118
120
  *
119
- * The server module enables building REST APIs and web applications using `$route` and `$action` primitives
120
- * on class properties. It provides automatic request/response handling, schema validation, middleware support,
121
- * and seamless integration with other Alepha modules for a complete backend solution.
121
+ * Convention-driven HTTP server with automatic validation and type inference.
122
+ *
123
+ * **Features:**
124
+ * - Type-safe API endpoints with schema validation
125
+ * - Lower-level HTTP route definitions
126
+ * - Automatic request/response validation via TypeBox
127
+ * - Convention-based URL generation (`/api/{ActionName}`)
128
+ * - Direct invocation (`run()`) or HTTP (`fetch()`)
129
+ * - Built-in authentication integration
130
+ * - Multipart file upload handling
131
+ * - Content-type auto-negotiation (JSON, form-data, text)
132
+ * - HTTP methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
133
+ * - Error handling: BadRequestError, ValidationError, ForbiddenError, UnauthorizedError, ConflictError, NotFoundError
122
134
  *
123
- * @see {@link $route}
124
- * @see {@link $action}
125
135
  * @module alepha.server
126
136
  */
127
137
  export const AlephaServer = $module({
@@ -141,7 +151,7 @@ export const AlephaServer = $module({
141
151
  ServerRouterProvider,
142
152
  ],
143
153
  register: (alepha: Alepha) => {
144
- if (!alepha.isServerless() && !alepha.isViteDev()) {
154
+ if (!alepha.isServerless()) {
145
155
  if (alepha.isBun()) {
146
156
  alepha.with({
147
157
  optional: true,
@@ -83,7 +83,7 @@ export interface ServerRequest<
83
83
 
84
84
  /**
85
85
  * Client IP address.
86
- * Will parse `X-Forwarded-For` header if present.
86
+ * Uses `X-Forwarded-For` header when `TRUST_PROXY=true`.
87
87
  */
88
88
  ip?: string;
89
89
 
@@ -100,6 +100,42 @@ export interface ServerRequest<
100
100
  */
101
101
  userAgent: UserAgentInfo;
102
102
 
103
+ /**
104
+ * Geolocation information derived from proxy headers.
105
+ * Available when behind Cloudflare, Vercel, or similar CDNs.
106
+ */
107
+ geo: RequestGeo;
108
+
109
+ /**
110
+ * Whether the request appears to be from a bot/crawler.
111
+ * Based on user-agent analysis.
112
+ */
113
+ isBot: boolean;
114
+
115
+ /**
116
+ * Whether the request is from a mobile device.
117
+ * Based on user-agent analysis.
118
+ */
119
+ isMobile: boolean;
120
+
121
+ /**
122
+ * Request protocol (http or https).
123
+ * Uses `X-Forwarded-Proto` header when behind a proxy.
124
+ */
125
+ protocol: "http" | "https";
126
+
127
+ /**
128
+ * Preferred language from `Accept-Language` header.
129
+ * Returns the first/most preferred language code (e.g., "en", "fr", "en-US").
130
+ */
131
+ language?: string;
132
+
133
+ /**
134
+ * Parsed referer information.
135
+ * Undefined if no Referer header or invalid URL.
136
+ */
137
+ referer?: RequestReferer;
138
+
103
139
  /**
104
140
  * Arbitrary metadata attached to the request. Can be used by middlewares to store information.
105
141
  */
@@ -208,3 +244,49 @@ export interface WebRequestEvent {
208
244
  req: Request;
209
245
  res?: Response;
210
246
  }
247
+
248
+ // ---------------------------------------------------------------------------------------------------------------------
249
+
250
+ /**
251
+ * Geolocation information from proxy headers (Cloudflare, Vercel, etc.)
252
+ */
253
+ export interface RequestGeo {
254
+ /**
255
+ * ISO 3166-1 alpha-2 country code (e.g., "US", "FR", "JP").
256
+ */
257
+ country?: string;
258
+ /**
259
+ * City name (e.g., "San Francisco", "Paris").
260
+ */
261
+ city?: string;
262
+ /**
263
+ * Region/state (e.g., "California", "Île-de-France").
264
+ */
265
+ region?: string;
266
+ /**
267
+ * Latitude (if available).
268
+ */
269
+ latitude?: string;
270
+ /**
271
+ * Longitude (if available).
272
+ */
273
+ longitude?: string;
274
+ }
275
+
276
+ /**
277
+ * Parsed referer information.
278
+ */
279
+ export interface RequestReferer {
280
+ /**
281
+ * Full referer URL.
282
+ */
283
+ url: string;
284
+ /**
285
+ * Hostname of the referer (e.g., "google.com").
286
+ */
287
+ hostname: string;
288
+ /**
289
+ * Path of the referer URL.
290
+ */
291
+ pathname: string;
292
+ }
@@ -1,5 +1,5 @@
1
1
  import { Alepha, t } from "alepha";
2
- import { FileSystemProvider } from "alepha/file";
2
+ import { FileSystemProvider } from "alepha/system";
3
3
  import { describe, test } from "vitest";
4
4
  import { $action } from "../index.ts";
5
5