alepha 0.14.2 → 0.14.4

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 (405) hide show
  1. package/README.md +1 -1
  2. package/dist/api/audits/index.browser.js +5 -5
  3. package/dist/api/audits/index.browser.js.map +1 -1
  4. package/dist/api/audits/index.d.ts +706 -785
  5. package/dist/api/audits/index.d.ts.map +1 -1
  6. package/dist/api/audits/index.js +13 -13
  7. package/dist/api/audits/index.js.map +1 -1
  8. package/dist/api/files/index.browser.js +5 -5
  9. package/dist/api/files/index.browser.js.map +1 -1
  10. package/dist/api/files/index.d.ts +58 -137
  11. package/dist/api/files/index.d.ts.map +1 -1
  12. package/dist/api/files/index.js +71 -71
  13. package/dist/api/files/index.js.map +1 -1
  14. package/dist/api/jobs/index.browser.js +5 -5
  15. package/dist/api/jobs/index.browser.js.map +1 -1
  16. package/dist/api/jobs/index.d.ts +29 -108
  17. package/dist/api/jobs/index.d.ts.map +1 -1
  18. package/dist/api/jobs/index.js +10 -10
  19. package/dist/api/jobs/index.js.map +1 -1
  20. package/dist/api/notifications/index.browser.js +10 -10
  21. package/dist/api/notifications/index.browser.js.map +1 -1
  22. package/dist/api/notifications/index.d.ts +504 -171
  23. package/dist/api/notifications/index.d.ts.map +1 -1
  24. package/dist/api/notifications/index.js +12 -12
  25. package/dist/api/notifications/index.js.map +1 -1
  26. package/dist/api/parameters/index.browser.js +163 -10
  27. package/dist/api/parameters/index.browser.js.map +1 -1
  28. package/dist/api/parameters/index.d.ts +277 -351
  29. package/dist/api/parameters/index.d.ts.map +1 -1
  30. package/dist/api/parameters/index.js +196 -91
  31. package/dist/api/parameters/index.js.map +1 -1
  32. package/dist/api/users/index.browser.js +19 -19
  33. package/dist/api/users/index.browser.js.map +1 -1
  34. package/dist/api/users/index.d.ts +787 -852
  35. package/dist/api/users/index.d.ts.map +1 -1
  36. package/dist/api/users/index.js +827 -596
  37. package/dist/api/users/index.js.map +1 -1
  38. package/dist/api/verifications/index.browser.js +6 -6
  39. package/dist/api/verifications/index.browser.js.map +1 -1
  40. package/dist/api/verifications/index.d.ts +128 -128
  41. package/dist/api/verifications/index.d.ts.map +1 -1
  42. package/dist/api/verifications/index.js +6 -6
  43. package/dist/api/verifications/index.js.map +1 -1
  44. package/dist/bin/index.d.ts +1 -2
  45. package/dist/bin/index.js +0 -1
  46. package/dist/bin/index.js.map +1 -1
  47. package/dist/cli/index.d.ts +252 -131
  48. package/dist/cli/index.d.ts.map +1 -1
  49. package/dist/cli/index.js +595 -395
  50. package/dist/cli/index.js.map +1 -1
  51. package/dist/command/index.d.ts +46 -11
  52. package/dist/command/index.d.ts.map +1 -1
  53. package/dist/command/index.js +99 -19
  54. package/dist/command/index.js.map +1 -1
  55. package/dist/core/index.browser.js +40 -22
  56. package/dist/core/index.browser.js.map +1 -1
  57. package/dist/core/index.d.ts +45 -1
  58. package/dist/core/index.d.ts.map +1 -1
  59. package/dist/core/index.js +40 -22
  60. package/dist/core/index.js.map +1 -1
  61. package/dist/core/index.native.js +40 -22
  62. package/dist/core/index.native.js.map +1 -1
  63. package/dist/fake/index.js +195 -168
  64. package/dist/fake/index.js.map +1 -1
  65. package/dist/file/index.d.ts +8 -0
  66. package/dist/file/index.d.ts.map +1 -1
  67. package/dist/file/index.js +3 -0
  68. package/dist/file/index.js.map +1 -1
  69. package/dist/logger/index.d.ts +1 -1
  70. package/dist/logger/index.d.ts.map +1 -1
  71. package/dist/logger/index.js +12 -2
  72. package/dist/logger/index.js.map +1 -1
  73. package/dist/mcp/index.js +1 -1
  74. package/dist/mcp/index.js.map +1 -1
  75. package/dist/orm/index.d.ts +59 -195
  76. package/dist/orm/index.d.ts.map +1 -1
  77. package/dist/orm/index.js +201 -430
  78. package/dist/orm/index.js.map +1 -1
  79. package/dist/security/index.d.ts +1 -1
  80. package/dist/security/index.d.ts.map +1 -1
  81. package/dist/security/index.js +1 -1
  82. package/dist/security/index.js.map +1 -1
  83. package/dist/server/auth/index.d.ts +171 -155
  84. package/dist/server/auth/index.d.ts.map +1 -1
  85. package/dist/server/auth/index.js +0 -1
  86. package/dist/server/auth/index.js.map +1 -1
  87. package/dist/server/cache/index.d.ts +12 -0
  88. package/dist/server/cache/index.d.ts.map +1 -1
  89. package/dist/server/cache/index.js +55 -2
  90. package/dist/server/cache/index.js.map +1 -1
  91. package/dist/server/compress/index.d.ts +6 -0
  92. package/dist/server/compress/index.d.ts.map +1 -1
  93. package/dist/server/compress/index.js +38 -1
  94. package/dist/server/compress/index.js.map +1 -1
  95. package/dist/server/core/index.browser.js +2 -2
  96. package/dist/server/core/index.browser.js.map +1 -1
  97. package/dist/server/core/index.d.ts +10 -10
  98. package/dist/server/core/index.d.ts.map +1 -1
  99. package/dist/server/core/index.js +7 -4
  100. package/dist/server/core/index.js.map +1 -1
  101. package/dist/server/links/index.browser.js +22 -6
  102. package/dist/server/links/index.browser.js.map +1 -1
  103. package/dist/server/links/index.d.ts +46 -44
  104. package/dist/server/links/index.d.ts.map +1 -1
  105. package/dist/server/links/index.js +24 -41
  106. package/dist/server/links/index.js.map +1 -1
  107. package/dist/server/static/index.d.ts.map +1 -1
  108. package/dist/server/static/index.js +4 -0
  109. package/dist/server/static/index.js.map +1 -1
  110. package/dist/server/swagger/index.d.ts +2 -1
  111. package/dist/server/swagger/index.d.ts.map +1 -1
  112. package/dist/server/swagger/index.js +9 -5
  113. package/dist/server/swagger/index.js.map +1 -1
  114. package/dist/vite/index.d.ts +101 -106
  115. package/dist/vite/index.d.ts.map +1 -1
  116. package/dist/vite/index.js +574 -503
  117. package/dist/vite/index.js.map +1 -1
  118. package/dist/websocket/index.d.ts +7 -7
  119. package/package.json +7 -7
  120. package/src/api/audits/controllers/{AuditController.ts → AdminAuditController.ts} +5 -6
  121. package/src/api/audits/entities/audits.ts +5 -5
  122. package/src/api/audits/index.browser.ts +1 -1
  123. package/src/api/audits/index.ts +3 -3
  124. package/src/api/audits/primitives/$audit.spec.ts +276 -0
  125. package/src/api/audits/services/AuditService.spec.ts +495 -0
  126. package/src/api/files/__tests__/$bucket.spec.ts +91 -0
  127. package/src/api/files/controllers/AdminFileStatsController.spec.ts +166 -0
  128. package/src/api/files/controllers/{StorageStatsController.ts → AdminFileStatsController.ts} +2 -2
  129. package/src/api/files/controllers/FileController.spec.ts +558 -0
  130. package/src/api/files/controllers/FileController.ts +4 -5
  131. package/src/api/files/entities/files.ts +5 -5
  132. package/src/api/files/index.browser.ts +1 -1
  133. package/src/api/files/index.ts +4 -4
  134. package/src/api/files/jobs/FileJobs.spec.ts +52 -0
  135. package/src/api/files/services/FileService.spec.ts +109 -0
  136. package/src/api/jobs/__tests__/JobController.spec.ts +343 -0
  137. package/src/api/jobs/controllers/{JobController.ts → AdminJobController.ts} +2 -2
  138. package/src/api/jobs/entities/jobExecutions.ts +5 -5
  139. package/src/api/jobs/index.ts +3 -3
  140. package/src/api/jobs/primitives/$job.spec.ts +476 -0
  141. package/src/api/notifications/controllers/{NotificationController.ts → AdminNotificationController.ts} +4 -5
  142. package/src/api/notifications/entities/notifications.ts +5 -5
  143. package/src/api/notifications/index.browser.ts +1 -1
  144. package/src/api/notifications/index.ts +4 -4
  145. package/src/api/parameters/controllers/{ConfigController.ts → AdminConfigController.ts} +46 -107
  146. package/src/api/parameters/entities/parameters.ts +7 -17
  147. package/src/api/parameters/index.ts +3 -3
  148. package/src/api/parameters/primitives/$config.spec.ts +356 -0
  149. package/src/api/parameters/schemas/activateConfigBodySchema.ts +12 -0
  150. package/src/api/parameters/schemas/checkScheduledResponseSchema.ts +8 -0
  151. package/src/api/parameters/schemas/configCurrentResponseSchema.ts +13 -0
  152. package/src/api/parameters/schemas/configHistoryResponseSchema.ts +9 -0
  153. package/src/api/parameters/schemas/configNameParamSchema.ts +10 -0
  154. package/src/api/parameters/schemas/configNamesResponseSchema.ts +8 -0
  155. package/src/api/parameters/schemas/configTreeNodeSchema.ts +13 -0
  156. package/src/api/parameters/schemas/configVersionParamSchema.ts +9 -0
  157. package/src/api/parameters/schemas/configVersionResponseSchema.ts +9 -0
  158. package/src/api/parameters/schemas/configsByStatusResponseSchema.ts +9 -0
  159. package/src/api/parameters/schemas/createConfigVersionBodySchema.ts +24 -0
  160. package/src/api/parameters/schemas/index.ts +15 -0
  161. package/src/api/parameters/schemas/parameterResponseSchema.ts +26 -0
  162. package/src/api/parameters/schemas/parameterStatusSchema.ts +13 -0
  163. package/src/api/parameters/schemas/rollbackConfigBodySchema.ts +15 -0
  164. package/src/api/parameters/schemas/statusParamSchema.ts +9 -0
  165. package/src/api/users/__tests__/EmailVerification.spec.ts +369 -0
  166. package/src/api/users/__tests__/PasswordReset.spec.ts +550 -0
  167. package/src/api/users/controllers/AdminIdentityController.spec.ts +365 -0
  168. package/src/api/users/controllers/{IdentityController.ts → AdminIdentityController.ts} +3 -4
  169. package/src/api/users/controllers/AdminSessionController.spec.ts +274 -0
  170. package/src/api/users/controllers/{SessionController.ts → AdminSessionController.ts} +3 -4
  171. package/src/api/users/controllers/AdminUserController.spec.ts +372 -0
  172. package/src/api/users/controllers/AdminUserController.ts +116 -0
  173. package/src/api/users/controllers/UserController.ts +4 -107
  174. package/src/api/users/controllers/UserRealmController.ts +3 -0
  175. package/src/api/users/entities/identities.ts +6 -6
  176. package/src/api/users/entities/sessions.ts +6 -6
  177. package/src/api/users/entities/users.ts +9 -9
  178. package/src/api/users/index.ts +9 -6
  179. package/src/api/users/primitives/$userRealm.ts +13 -8
  180. package/src/api/users/services/CredentialService.spec.ts +509 -0
  181. package/src/api/users/services/CredentialService.ts +46 -0
  182. package/src/api/users/services/IdentityService.ts +15 -0
  183. package/src/api/users/services/RegistrationService.spec.ts +630 -0
  184. package/src/api/users/services/RegistrationService.ts +18 -0
  185. package/src/api/users/services/SessionService.spec.ts +301 -0
  186. package/src/api/users/services/SessionService.ts +110 -1
  187. package/src/api/users/services/UserService.ts +67 -2
  188. package/src/api/verifications/__tests__/CodeVerification.spec.ts +318 -0
  189. package/src/api/verifications/__tests__/LinkVerification.spec.ts +279 -0
  190. package/src/api/verifications/entities/verifications.ts +6 -6
  191. package/src/api/verifications/jobs/VerificationJobs.spec.ts +50 -0
  192. package/src/batch/__tests__/startup-buffering.spec.ts +458 -0
  193. package/src/batch/primitives/$batch.spec.ts +766 -0
  194. package/src/batch/providers/BatchProvider.spec.ts +786 -0
  195. package/src/bin/index.ts +0 -1
  196. package/src/bucket/__tests__/shared.ts +194 -0
  197. package/src/bucket/primitives/$bucket.spec.ts +104 -0
  198. package/src/bucket/providers/FileStorageProvider.spec.ts +13 -0
  199. package/src/bucket/providers/LocalFileStorageProvider.spec.ts +77 -0
  200. package/src/bucket/providers/MemoryFileStorageProvider.spec.ts +82 -0
  201. package/src/cache/core/__tests__/shared.ts +377 -0
  202. package/src/cache/core/primitives/$cache.spec.ts +111 -0
  203. package/src/cache/redis/__tests__/cache-redis.spec.ts +70 -0
  204. package/src/cli/apps/AlephaCli.ts +25 -6
  205. package/src/cli/atoms/buildOptions.ts +88 -0
  206. package/src/cli/commands/build.ts +32 -69
  207. package/src/cli/commands/db.ts +0 -4
  208. package/src/cli/commands/dev.ts +34 -10
  209. package/src/cli/commands/gen/changelog.spec.ts +315 -0
  210. package/src/cli/commands/{changelog.ts → gen/changelog.ts} +9 -9
  211. package/src/cli/commands/gen/env.ts +53 -0
  212. package/src/cli/commands/gen/openapi.ts +71 -0
  213. package/src/cli/commands/gen/resource.ts +15 -0
  214. package/src/cli/commands/gen.ts +24 -0
  215. package/src/cli/commands/init.ts +2 -1
  216. package/src/cli/commands/root.ts +12 -3
  217. package/src/cli/commands/test.ts +0 -1
  218. package/src/cli/commands/typecheck.ts +5 -0
  219. package/src/cli/commands/verify.ts +1 -1
  220. package/src/cli/defineConfig.ts +49 -7
  221. package/src/cli/index.ts +2 -2
  222. package/src/cli/services/AlephaCliUtils.ts +105 -55
  223. package/src/cli/services/GitMessageParser.ts +1 -1
  224. package/src/command/helpers/Asker.spec.ts +127 -0
  225. package/src/command/helpers/Runner.spec.ts +126 -0
  226. package/src/command/helpers/Runner.ts +1 -1
  227. package/src/command/primitives/$command.spec.ts +1588 -0
  228. package/src/command/primitives/$command.ts +0 -6
  229. package/src/command/providers/CliProvider.ts +75 -27
  230. package/src/core/Alepha.ts +87 -0
  231. package/src/core/__tests__/Alepha-emit.spec.ts +22 -0
  232. package/src/core/__tests__/Alepha-graph.spec.ts +93 -0
  233. package/src/core/__tests__/Alepha-has.spec.ts +41 -0
  234. package/src/core/__tests__/Alepha-inject.spec.ts +93 -0
  235. package/src/core/__tests__/Alepha-register.spec.ts +81 -0
  236. package/src/core/__tests__/Alepha-start.spec.ts +176 -0
  237. package/src/core/__tests__/Alepha-with.spec.ts +14 -0
  238. package/src/core/__tests__/TypeBox-usecases.spec.ts +35 -0
  239. package/src/core/__tests__/TypeBoxLocale.spec.ts +15 -0
  240. package/src/core/__tests__/descriptor.spec.ts +34 -0
  241. package/src/core/__tests__/fixtures/A.ts +5 -0
  242. package/src/core/__tests__/pagination.spec.ts +77 -0
  243. package/src/core/helpers/jsonSchemaToTypeBox.ts +2 -2
  244. package/src/core/primitives/$atom.spec.ts +43 -0
  245. package/src/core/primitives/$hook.spec.ts +130 -0
  246. package/src/core/primitives/$inject.spec.ts +175 -0
  247. package/src/core/primitives/$module.spec.ts +115 -0
  248. package/src/core/providers/CodecManager.spec.ts +740 -0
  249. package/src/core/providers/EventManager.spec.ts +762 -0
  250. package/src/core/providers/EventManager.ts +4 -0
  251. package/src/core/providers/StateManager.spec.ts +365 -0
  252. package/src/core/providers/TypeProvider.spec.ts +1607 -0
  253. package/src/core/providers/TypeProvider.ts +20 -26
  254. package/src/datetime/primitives/$interval.spec.ts +103 -0
  255. package/src/datetime/providers/DateTimeProvider.spec.ts +86 -0
  256. package/src/email/primitives/$email.spec.ts +175 -0
  257. package/src/email/providers/LocalEmailProvider.spec.ts +341 -0
  258. package/src/fake/__tests__/keyName.example.ts +40 -0
  259. package/src/fake/__tests__/keyName.spec.ts +152 -0
  260. package/src/fake/__tests__/module.example.ts +32 -0
  261. package/src/fake/providers/FakeProvider.spec.ts +438 -0
  262. package/src/file/providers/FileSystemProvider.ts +8 -0
  263. package/src/file/providers/NodeFileSystemProvider.spec.ts +418 -0
  264. package/src/file/providers/NodeFileSystemProvider.ts +5 -0
  265. package/src/file/services/FileDetector.spec.ts +591 -0
  266. package/src/lock/core/__tests__/shared.ts +190 -0
  267. package/src/lock/core/providers/MemoryLockProvider.spec.ts +25 -0
  268. package/src/lock/redis/providers/RedisLockProvider.spec.ts +25 -0
  269. package/src/logger/__tests__/SimpleFormatterProvider.spec.ts +109 -0
  270. package/src/logger/index.ts +15 -3
  271. package/src/logger/primitives/$logger.spec.ts +108 -0
  272. package/src/logger/services/Logger.spec.ts +295 -0
  273. package/src/mcp/__tests__/errors.spec.ts +175 -0
  274. package/src/mcp/__tests__/integration.spec.ts +450 -0
  275. package/src/mcp/helpers/jsonrpc.spec.ts +380 -0
  276. package/src/mcp/primitives/$prompt.spec.ts +468 -0
  277. package/src/mcp/primitives/$resource.spec.ts +390 -0
  278. package/src/mcp/primitives/$tool.spec.ts +406 -0
  279. package/src/mcp/providers/McpServerProvider.spec.ts +797 -0
  280. package/src/mcp/transports/StdioMcpTransport.ts +1 -1
  281. package/src/orm/__tests__/$repository-crud.spec.ts +276 -0
  282. package/src/orm/__tests__/$repository-hooks.spec.ts +325 -0
  283. package/src/orm/__tests__/$repository-orderBy.spec.ts +128 -0
  284. package/src/orm/__tests__/$repository-pagination-sort.spec.ts +149 -0
  285. package/src/orm/__tests__/$repository-save.spec.ts +37 -0
  286. package/src/orm/__tests__/ModelBuilder-integration.spec.ts +490 -0
  287. package/src/orm/__tests__/ModelBuilder-types.spec.ts +186 -0
  288. package/src/orm/__tests__/PostgresProvider.spec.ts +46 -0
  289. package/src/orm/__tests__/delete-returning.spec.ts +256 -0
  290. package/src/orm/__tests__/deletedAt.spec.ts +80 -0
  291. package/src/orm/__tests__/enums.spec.ts +315 -0
  292. package/src/orm/__tests__/execute.spec.ts +72 -0
  293. package/src/orm/__tests__/fixtures/bigEntitySchema.ts +65 -0
  294. package/src/orm/__tests__/fixtures/userEntitySchema.ts +27 -0
  295. package/src/orm/__tests__/joins.spec.ts +1114 -0
  296. package/src/orm/__tests__/page.spec.ts +287 -0
  297. package/src/orm/__tests__/primaryKey.spec.ts +87 -0
  298. package/src/orm/__tests__/query-date-encoding.spec.ts +402 -0
  299. package/src/orm/__tests__/ref-auto-onDelete.spec.ts +156 -0
  300. package/src/orm/__tests__/references.spec.ts +102 -0
  301. package/src/orm/__tests__/security.spec.ts +710 -0
  302. package/src/orm/__tests__/sqlite.spec.ts +111 -0
  303. package/src/orm/__tests__/string-operators.spec.ts +429 -0
  304. package/src/orm/__tests__/timestamps.spec.ts +388 -0
  305. package/src/orm/__tests__/validation.spec.ts +183 -0
  306. package/src/orm/__tests__/version.spec.ts +64 -0
  307. package/src/orm/helpers/parseQueryString.spec.ts +196 -0
  308. package/src/orm/index.ts +2 -8
  309. package/src/orm/primitives/$repository.spec.ts +137 -0
  310. package/src/orm/primitives/$sequence.spec.ts +29 -0
  311. package/src/orm/primitives/$transaction.spec.ts +82 -0
  312. package/src/orm/providers/drivers/BunPostgresProvider.ts +3 -3
  313. package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -1
  314. package/src/orm/providers/drivers/CloudflareD1Provider.ts +1 -1
  315. package/src/orm/providers/drivers/DatabaseProvider.ts +1 -1
  316. package/src/orm/providers/drivers/NodePostgresProvider.ts +3 -3
  317. package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
  318. package/src/orm/providers/drivers/PglitePostgresProvider.ts +2 -2
  319. package/src/orm/services/ModelBuilder.spec.ts +575 -0
  320. package/src/orm/services/Repository.spec.ts +137 -0
  321. package/src/queue/core/__tests__/shared.ts +143 -0
  322. package/src/queue/core/providers/MemoryQueueProvider.spec.ts +23 -0
  323. package/src/queue/core/providers/WorkerProvider.spec.ts +394 -0
  324. package/src/queue/redis/providers/RedisQueueProvider.spec.ts +23 -0
  325. package/src/redis/__tests__/redis.spec.ts +58 -0
  326. package/src/retry/primitives/$retry.spec.ts +234 -0
  327. package/src/retry/providers/RetryProvider.spec.ts +438 -0
  328. package/src/router/__tests__/match.spec.ts +252 -0
  329. package/src/router/providers/RouterProvider.spec.ts +197 -0
  330. package/src/scheduler/__tests__/$scheduler-cron.spec.ts +25 -0
  331. package/src/scheduler/__tests__/$scheduler-interval.spec.ts +25 -0
  332. package/src/scheduler/__tests__/shared.ts +77 -0
  333. package/src/security/__tests__/bug-1-wildcard-after-start.spec.ts +229 -0
  334. package/src/security/__tests__/bug-2-password-validation.spec.ts +245 -0
  335. package/src/security/__tests__/bug-3-regex-vulnerability.spec.ts +407 -0
  336. package/src/security/__tests__/bug-4-oauth2-validation.spec.ts +439 -0
  337. package/src/security/__tests__/multi-layer-permissions.spec.ts +522 -0
  338. package/src/security/primitives/$permission.spec.ts +30 -0
  339. package/src/security/primitives/$permission.ts +2 -2
  340. package/src/security/primitives/$realm.spec.ts +101 -0
  341. package/src/security/primitives/$role.spec.ts +52 -0
  342. package/src/security/primitives/$serviceAccount.spec.ts +61 -0
  343. package/src/security/providers/SecurityProvider.spec.ts +350 -0
  344. package/src/server/auth/providers/ServerAuthProvider.ts +0 -2
  345. package/src/server/cache/providers/ServerCacheProvider.spec.ts +1125 -0
  346. package/src/server/cache/providers/ServerCacheProvider.ts +94 -9
  347. package/src/server/compress/providers/ServerCompressProvider.spec.ts +31 -0
  348. package/src/server/compress/providers/ServerCompressProvider.ts +63 -2
  349. package/src/server/cookies/providers/ServerCookiesProvider.spec.ts +253 -0
  350. package/src/server/core/__tests__/ServerRouterProvider-getRoutes.spec.ts +334 -0
  351. package/src/server/core/__tests__/ServerRouterProvider-requestId.spec.ts +129 -0
  352. package/src/server/core/helpers/ServerReply.ts +2 -2
  353. package/src/server/core/primitives/$action.spec.ts +191 -0
  354. package/src/server/core/primitives/$route.spec.ts +65 -0
  355. package/src/server/core/providers/ServerBodyParserProvider.spec.ts +93 -0
  356. package/src/server/core/providers/ServerLoggerProvider.spec.ts +100 -0
  357. package/src/server/core/providers/ServerProvider.ts +14 -2
  358. package/src/server/core/services/HttpClient.spec.ts +123 -0
  359. package/src/server/core/services/UserAgentParser.spec.ts +111 -0
  360. package/src/server/cors/providers/ServerCorsProvider.spec.ts +481 -0
  361. package/src/server/health/providers/ServerHealthProvider.spec.ts +22 -0
  362. package/src/server/helmet/providers/ServerHelmetProvider.spec.ts +105 -0
  363. package/src/server/links/__tests__/$action.spec.ts +238 -0
  364. package/src/server/links/__tests__/fixtures/CrudApp.ts +122 -0
  365. package/src/server/links/__tests__/requestId.spec.ts +120 -0
  366. package/src/server/links/primitives/$remote.spec.ts +228 -0
  367. package/src/server/links/providers/LinkProvider.spec.ts +54 -0
  368. package/src/server/links/providers/LinkProvider.ts +49 -3
  369. package/src/server/links/providers/ServerLinksProvider.ts +1 -53
  370. package/src/server/links/schemas/apiLinksResponseSchema.ts +7 -0
  371. package/src/server/metrics/providers/ServerMetricsProvider.spec.ts +25 -0
  372. package/src/server/multipart/providers/ServerMultipartProvider.spec.ts +528 -0
  373. package/src/server/proxy/primitives/$proxy.spec.ts +87 -0
  374. package/src/server/rate-limit/__tests__/ActionRateLimit.spec.ts +211 -0
  375. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +344 -0
  376. package/src/server/security/__tests__/BasicAuth.spec.ts +684 -0
  377. package/src/server/security/__tests__/ServerSecurityProvider-realm.spec.ts +388 -0
  378. package/src/server/security/providers/ServerSecurityProvider.spec.ts +123 -0
  379. package/src/server/static/primitives/$serve.spec.ts +193 -0
  380. package/src/server/static/providers/ServerStaticProvider.ts +10 -0
  381. package/src/server/swagger/__tests__/ui.spec.ts +52 -0
  382. package/src/server/swagger/primitives/$swagger.spec.ts +193 -0
  383. package/src/server/swagger/providers/ServerSwaggerProvider.ts +19 -12
  384. package/src/sms/primitives/$sms.spec.ts +165 -0
  385. package/src/sms/providers/LocalSmsProvider.spec.ts +224 -0
  386. package/src/sms/providers/MemorySmsProvider.spec.ts +193 -0
  387. package/src/thread/primitives/$thread.spec.ts +186 -0
  388. package/src/topic/core/__tests__/shared.ts +144 -0
  389. package/src/topic/core/providers/MemoryTopicProvider.spec.ts +23 -0
  390. package/src/topic/redis/providers/RedisTopicProvider.spec.ts +23 -0
  391. package/src/vite/helpers/importViteReact.ts +13 -0
  392. package/src/vite/index.ts +1 -21
  393. package/src/vite/plugins/viteAlephaDev.ts +32 -5
  394. package/src/vite/plugins/viteAlephaSsrPreload.ts +222 -0
  395. package/src/vite/tasks/buildClient.ts +11 -0
  396. package/src/vite/tasks/buildServer.ts +47 -3
  397. package/src/vite/tasks/devServer.ts +69 -0
  398. package/src/vite/tasks/index.ts +2 -1
  399. package/src/vite/tasks/runAlepha.ts +7 -1
  400. package/src/websocket/__tests__/$websocket-new.spec.ts +195 -0
  401. package/src/websocket/primitives/$channel.spec.ts +30 -0
  402. package/src/cli/assets/viteConfigTs.ts +0 -14
  403. package/src/cli/commands/run.ts +0 -24
  404. package/src/vite/plugins/viteAlepha.ts +0 -37
  405. package/src/vite/plugins/viteAlephaBuild.ts +0 -281
@@ -261,24 +261,55 @@ export class ServerCacheProvider {
261
261
  return;
262
262
  }
263
263
 
264
- // Only process string responses (text, html, json, etc.)
265
- // Buffer is not supported by alepha/cache for now
266
- if (typeof response.body !== "string") {
267
- return;
268
- }
269
-
270
264
  // Don't cache error responses (status >= 400)
271
265
  if (response.status && response.status >= 400) {
272
266
  return;
273
267
  }
274
268
 
269
+ // Initialize headers if not present
270
+ response.headers ??= {};
271
+
275
272
  const key = this.createCacheKey(route, request);
273
+
274
+ // Handle ReadableStream responses (e.g., SSR streaming)
275
+ if (response.body instanceof ReadableStream && shouldStore) {
276
+ // Tee the stream: one for client, one for cache collection
277
+ const [clientStream, cacheStream] = (
278
+ response.body as ReadableStream<Uint8Array>
279
+ ).tee();
280
+
281
+ // Replace response body with client stream (continues streaming to client)
282
+ response.body = clientStream as typeof response.body;
283
+
284
+ // Collect cache stream in background (non-blocking)
285
+ this.collectStreamForCache(
286
+ cacheStream,
287
+ key,
288
+ response.status,
289
+ response.headers?.["content-type"],
290
+ shouldUseEtag,
291
+ )
292
+ .then((hash) => {
293
+ if (shouldUseEtag && hash) {
294
+ // Note: headers already sent for streaming, etag only useful for future requests
295
+ this.log.trace("Stream cached with hash", { key, hash });
296
+ }
297
+ })
298
+ .catch((err) => {
299
+ this.log.warn("Failed to cache stream", { key, error: err });
300
+ });
301
+
302
+ return;
303
+ }
304
+
305
+ // Only process string responses (text, html, json, etc.)
306
+ if (typeof response.body !== "string") {
307
+ return;
308
+ }
309
+
276
310
  const generatedEtag = this.generateETag(response.body);
277
311
  const lastModified = this.time.toISOString();
278
312
 
279
- // Initialize headers if not present
280
- response.headers ??= {};
281
-
282
313
  // Store response if storing is enabled
283
314
  if (shouldStore) {
284
315
  this.log.trace("Storing response", {
@@ -404,6 +435,60 @@ export class ServerCacheProvider {
404
435
 
405
436
  return `${route.method}:${route.path.replaceAll(":", "")}:${params.join(",").replaceAll(":", "")}`;
406
437
  }
438
+
439
+ /**
440
+ * Collect a ReadableStream into a string and store it in the cache.
441
+ * This runs in the background while the original stream is sent to the client.
442
+ *
443
+ * @param stream - The stream to collect
444
+ * @param key - Cache key
445
+ * @param status - HTTP status code
446
+ * @param contentType - Content-Type header
447
+ * @param generateEtag - Whether to generate and return an ETag
448
+ * @returns The generated ETag hash, or undefined
449
+ */
450
+ protected async collectStreamForCache(
451
+ stream: ReadableStream<Uint8Array>,
452
+ key: string,
453
+ status: number | undefined,
454
+ contentType: string | undefined,
455
+ generateEtag: boolean,
456
+ ): Promise<string | undefined> {
457
+ const chunks: Uint8Array[] = [];
458
+ const reader = stream.getReader();
459
+
460
+ try {
461
+ while (true) {
462
+ const { done, value } = await reader.read();
463
+ if (done) break;
464
+ chunks.push(value);
465
+ }
466
+
467
+ // Combine chunks into a single string
468
+ const decoder = new TextDecoder();
469
+ const body =
470
+ chunks
471
+ .map((chunk) => decoder.decode(chunk, { stream: true }))
472
+ .join("") + decoder.decode(); // Flush remaining
473
+
474
+ const hash = this.generateETag(body);
475
+ const lastModified = this.time.toISOString();
476
+
477
+ this.log.trace("Storing streamed response", { key });
478
+
479
+ await this.cache.set(key, {
480
+ body,
481
+ status,
482
+ contentType,
483
+ lastModified,
484
+ hash,
485
+ });
486
+
487
+ return generateEtag ? hash : undefined;
488
+ } finally {
489
+ reader.releaseLock();
490
+ }
491
+ }
407
492
  }
408
493
 
409
494
  export type ServerRouteCache =
@@ -0,0 +1,31 @@
1
+ import { Alepha } from "alepha";
2
+ import { $action, ServerProvider } from "alepha/server";
3
+ import { describe, it } from "vitest";
4
+ import { AlephaServerCompress } from "../index.ts";
5
+
6
+ class App {
7
+ hello = $action({
8
+ handler: () => "Hello, world!",
9
+ });
10
+ }
11
+
12
+ const a1 = Alepha.create().with(App).with(AlephaServerCompress);
13
+ const a2 = Alepha.create().with(App);
14
+
15
+ describe("ServerCompressProvider", () => {
16
+ it("should compress responses when enabled", async ({ expect }) => {
17
+ const serv1 = a1.inject(ServerProvider);
18
+ const serv2 = a2.inject(ServerProvider);
19
+
20
+ const resp1 = await fetch(`${serv1.hostname}/api/hello`, {
21
+ headers: { "Accept-Encoding": "gzip" },
22
+ });
23
+
24
+ const resp2 = await fetch(`${serv2.hostname}/api/hello`, {
25
+ headers: { "Accept-Encoding": "gzip" },
26
+ });
27
+
28
+ expect(resp1.headers.get("content-encoding")).toBe("gzip");
29
+ expect(resp2.headers.get("content-encoding")).toBeNull();
30
+ });
31
+ });
@@ -125,21 +125,82 @@ export class ServerCompressProvider {
125
125
  this.setHeaders(response, encoding);
126
126
  response.headers["content-length"] = compressed.length.toString();
127
127
  response.body = compressed;
128
+ return;
128
129
  }
129
130
 
130
131
  if (typeof body === "object" && body instanceof Readable) {
131
132
  this.setHeaders(response, encoding);
132
133
  response.body = body.pipe(compressor.stream({ params }));
134
+ return;
133
135
  }
134
136
 
135
137
  if (typeof body === "object" && body instanceof ReadableStream) {
136
138
  this.setHeaders(response, encoding);
137
- response.body = Readable.fromWeb(body).pipe(
138
- compressor.stream({ params }),
139
+ // For streaming responses, use flush mode to avoid buffering
140
+ response.body = this.createFlushingCompressStream(
141
+ body,
142
+ compressor.stream,
143
+ encoding,
144
+ params,
139
145
  );
140
146
  }
141
147
  }
142
148
 
149
+ /**
150
+ * Create a compressed stream that flushes after each chunk.
151
+ * This is essential for streaming SSR - ensures each chunk is sent immediately.
152
+ */
153
+ protected createFlushingCompressStream(
154
+ input: ReadableStream,
155
+ createCompressor: (options?: any) => Transform,
156
+ encoding: string,
157
+ params: Record<number, any>,
158
+ ): ReadableStream<Uint8Array> {
159
+ const compressor = createCompressor({
160
+ params,
161
+ flush: zlib.constants.Z_SYNC_FLUSH,
162
+ });
163
+ const reader = Readable.fromWeb(input);
164
+
165
+ return new ReadableStream<Uint8Array>({
166
+ start(controller) {
167
+ compressor.on("data", (chunk: Buffer) => {
168
+ controller.enqueue(new Uint8Array(chunk));
169
+ });
170
+
171
+ compressor.on("end", () => {
172
+ controller.close();
173
+ });
174
+
175
+ compressor.on("error", (err) => {
176
+ controller.error(err);
177
+ });
178
+
179
+ reader.on("data", (chunk: Buffer) => {
180
+ compressor.write(chunk);
181
+ // Force flush after each chunk for streaming
182
+ // Cast to any because flush() exists on zlib streams but not in Transform type
183
+ const zlibStream = compressor as any;
184
+ if (encoding === "gzip") {
185
+ zlibStream.flush(zlib.constants.Z_SYNC_FLUSH);
186
+ } else if (encoding === "br") {
187
+ zlibStream.flush(zlib.constants.BROTLI_OPERATION_FLUSH);
188
+ } else if (encoding === "zstd") {
189
+ zlibStream.flush();
190
+ }
191
+ });
192
+
193
+ reader.on("end", () => {
194
+ compressor.end();
195
+ });
196
+
197
+ reader.on("error", (err) => {
198
+ controller.error(err);
199
+ });
200
+ },
201
+ });
202
+ }
203
+
143
204
  protected getParams(
144
205
  encoding: keyof typeof ServerCompressProvider.compressors,
145
206
  ): Record<number, any> {
@@ -0,0 +1,253 @@
1
+ import { Alepha, t } from "alepha";
2
+ import { $action, AlephaServer } from "alepha/server";
3
+ import { describe, expect, test } from "vitest";
4
+ import { $cookie, AlephaServerCookies } from "../index.ts";
5
+
6
+ // A strong, 32-character secret for testing purposes
7
+ const TEST_COOKIE_SECRET = "DCf6DvpLAfwy8XdPRucMO4tPS6dVCHob";
8
+
9
+ // --- Test Application Setup ---
10
+
11
+ class CookieTestApp {
12
+ // 1. Basic Cookie
13
+ session = $cookie({
14
+ name: "session",
15
+ schema: t.object({ userId: t.number(), role: t.text() }),
16
+ });
17
+
18
+ // 2. Signed Cookie
19
+ signed = $cookie({
20
+ name: "signed_session",
21
+ schema: t.text(),
22
+ sign: true,
23
+ });
24
+
25
+ // 3. Encrypted Cookie
26
+ encrypted = $cookie({
27
+ name: "encrypted_secret",
28
+ schema: t.object({ apiKey: t.text() }),
29
+ encrypt: true,
30
+ });
31
+
32
+ // 4. Compressed, Signed, and Encrypted Cookie with TTL
33
+ secure_all = $cookie({
34
+ name: "ultra_secure",
35
+ schema: t.object({ data: t.text() }),
36
+ compress: true,
37
+ sign: true,
38
+ encrypt: true,
39
+ ttl: [1, "hour"],
40
+ });
41
+
42
+ // An action to test the cookie functionality in a request cycle
43
+ cookie_test = $action({
44
+ schema: {
45
+ response: t.object({
46
+ incomingSession: t.optional(this.session.options.schema),
47
+ reqCookies: t.object({
48
+ req: t.record(t.text(), t.text()),
49
+ res: t.record(t.text(), t.any()),
50
+ }),
51
+ }),
52
+ },
53
+ handler: ({ cookies }) => {
54
+ // Set some cookies
55
+ this.session.set({ userId: 123, role: "admin" });
56
+ this.signed.set("i-am-signed");
57
+ this.encrypted.set({ apiKey: "secret-key" });
58
+ this.secure_all.set({ data: "super sensitive data" });
59
+
60
+ // Read a cookie from the request
61
+ const incomingSession = this.session.get({ cookies });
62
+
63
+ // Delete a cookie
64
+ if (incomingSession?.role === "guest") {
65
+ this.signed.del();
66
+ }
67
+
68
+ return { incomingSession, reqCookies: cookies };
69
+ },
70
+ });
71
+ }
72
+
73
+ const alepha = Alepha.create({
74
+ env: {
75
+ COOKIE_SECRET: TEST_COOKIE_SECRET,
76
+ },
77
+ })
78
+ .with(AlephaServer)
79
+ .with(AlephaServerCookies);
80
+
81
+ const app = alepha.inject(CookieTestApp);
82
+
83
+ // Helper to simulate a request and capture the response headers
84
+ const makeRequest = async (incomingCookieHeader = "") => {
85
+ const response = await app.cookie_test.fetch(
86
+ {},
87
+ {
88
+ request: { headers: { cookie: incomingCookieHeader } },
89
+ },
90
+ );
91
+ return {
92
+ data: response.data,
93
+ // The fetch client in tests might not handle multiple headers the same way a browser does.
94
+ // We get the raw header to properly check it.
95
+ setCookieHeader: response.raw?.headers.get("set-cookie"),
96
+ };
97
+ };
98
+
99
+ describe("ServerCookiesProvider", () => {
100
+ test("should set and get a basic cookie", async () => {
101
+ const { data, setCookieHeader } = await makeRequest();
102
+
103
+ // The handler receives no initial cookie
104
+ expect(data.incomingSession).toBeUndefined();
105
+
106
+ // Check if the response sets the cookie correctly
107
+ expect(setCookieHeader).toBeDefined();
108
+ const decodedValue = JSON.parse(
109
+ decodeURIComponent(setCookieHeader!.match(/session=([^;]*)/)![1]),
110
+ );
111
+ expect(decodedValue).toEqual({ userId: 123, role: "admin" });
112
+ });
113
+
114
+ test("should correctly read an incoming cookie", async () => {
115
+ const sessionData = { userId: 456, role: "user" };
116
+ const cookieHeader = `session=${encodeURIComponent(JSON.stringify(sessionData))}`;
117
+
118
+ const { data } = await makeRequest(cookieHeader);
119
+
120
+ // The handler should have received and parsed the cookie
121
+ expect(data.incomingSession).toEqual(sessionData);
122
+ });
123
+
124
+ test("should set and get a signed cookie", async () => {
125
+ const { setCookieHeader } = await makeRequest();
126
+ const signedCookie = setCookieHeader!.match(/signed_session=([^;]*)/)![1];
127
+
128
+ // Make a new request with the signed cookie
129
+ const { data } = await makeRequest(`signed_session=${signedCookie}`);
130
+
131
+ // The `get` method should successfully validate the signature and return the value
132
+ expect(app.signed.get({ cookies: data.reqCookies })).toBe("i-am-signed");
133
+ });
134
+
135
+ test("should reject a tampered signed cookie", async () => {
136
+ const { setCookieHeader } = await makeRequest();
137
+ let tamperedCookie = setCookieHeader!.match(/signed_session=([^;]*)/)![1];
138
+ tamperedCookie += "tampered"; // alter the cookie value
139
+
140
+ const { data } = await makeRequest(`signed_session=${tamperedCookie}`);
141
+
142
+ // The get should fail and return undefined
143
+ expect(app.signed.get({ cookies: data.reqCookies })).toBeUndefined();
144
+ });
145
+
146
+ test("should set and get an encrypted cookie", async () => {
147
+ const { setCookieHeader } = await makeRequest();
148
+ const encryptedCookie = setCookieHeader!.match(
149
+ /encrypted_secret=([^;]*)/,
150
+ )![1];
151
+
152
+ // The value should not be plain text
153
+ expect(decodeURIComponent(encryptedCookie)).not.toContain("secret-key");
154
+
155
+ const { data } = await makeRequest(`encrypted_secret=${encryptedCookie}`);
156
+
157
+ expect(app.encrypted.get({ cookies: data.reqCookies })).toEqual({
158
+ apiKey: "secret-key",
159
+ });
160
+ });
161
+
162
+ test("should reject a tampered encrypted cookie", async () => {
163
+ const { setCookieHeader } = await makeRequest();
164
+ const tamperedCookie = setCookieHeader!.match(
165
+ /encrypted_secret=([^;]*)/,
166
+ )![1];
167
+
168
+ const { data } = await makeRequest(
169
+ `encrypted_secret=aa${tamperedCookie}aa`,
170
+ );
171
+
172
+ // The get should fail (throw internally) and return undefined
173
+ expect(app.encrypted.get({ cookies: data.reqCookies })).toBeUndefined();
174
+ });
175
+
176
+ test("should handle a combination of compress, sign, and encrypt", async () => {
177
+ const { setCookieHeader } = await makeRequest();
178
+ const secureCookie = setCookieHeader!.match(/ultra_secure=([^;]*)/)![1];
179
+
180
+ const { data } = await makeRequest(`ultra_secure=${secureCookie}`);
181
+
182
+ expect(app.secure_all.get({ cookies: data.reqCookies })).toEqual({
183
+ data: "super sensitive data",
184
+ });
185
+ });
186
+
187
+ test("should delete a cookie", async () => {
188
+ const sessionData = { userId: 789, role: "guest" };
189
+ const cookieHeader = `session=${encodeURIComponent(JSON.stringify(sessionData))}`;
190
+
191
+ const { setCookieHeader } = await makeRequest(cookieHeader);
192
+
193
+ // The handler should detect role === 'guest' and delete the signed cookie
194
+ expect(setCookieHeader).toContain("signed_session=; Path=/; Max-Age=0");
195
+ });
196
+
197
+ test("should serialize all cookie attributes correctly", async () => {
198
+ class AttrApp {
199
+ advanced = $cookie({
200
+ name: "advanced",
201
+ schema: t.text(),
202
+ path: "/admin",
203
+ ttl: [30, "minutes"],
204
+ httpOnly: true,
205
+ secure: true,
206
+ sameSite: "strict",
207
+ domain: "example.com",
208
+ });
209
+ test = $action({
210
+ handler: () => {
211
+ this.advanced.set("value");
212
+ },
213
+ });
214
+ }
215
+
216
+ const attrAlepha = Alepha.create({
217
+ env: { COOKIE_SECRET: TEST_COOKIE_SECRET },
218
+ })
219
+ .with(AlephaServer)
220
+ .with(AlephaServerCookies)
221
+ .with(AttrApp);
222
+
223
+ await attrAlepha.start();
224
+
225
+ const response = await attrAlepha.inject(AttrApp).test.fetch();
226
+ const setCookieHeader = response.headers.get("set-cookie");
227
+ expect(setCookieHeader).toContain("Max-Age=1800");
228
+ expect(setCookieHeader).toContain("Path=/admin");
229
+ expect(setCookieHeader).toContain("HttpOnly");
230
+ expect(setCookieHeader).toContain("SameSite=strict");
231
+ expect(setCookieHeader).toContain("Domain=example.com");
232
+ // Secure flag is not added in tests unless protocol is https, which is handled by the provider
233
+ });
234
+
235
+ // test("should throw if secret is missing for secure cookies", async () => {
236
+ // class AppWithMissingSecret {
237
+ // badCookie = $cookie({
238
+ // name: "bad",
239
+ // schema: t.text(),
240
+ // sign: true,
241
+ // });
242
+ // }
243
+ //
244
+ // const alephaWithoutSecret = Alepha.create()
245
+ // .with(AlephaServer)
246
+ // .with(AlephaServerCookies)
247
+ // .with(AppWithMissingSecret);
248
+ //
249
+ // await expect(() => alephaWithoutSecret.start()).rejects.toThrow(
250
+ // /COOKIE_SECRET environment variable is not set/,
251
+ // );
252
+ // });
253
+ });