alepha 0.14.1 → 0.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (402) hide show
  1. package/README.md +3 -3
  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 +784 -784
  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 +57 -57
  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 +165 -165
  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 +583 -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 +281 -276
  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 +778 -764
  35. package/dist/api/users/index.d.ts.map +1 -1
  36. package/dist/api/users/index.js +831 -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 +125 -125
  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/batch/index.js.map +1 -1
  45. package/dist/bin/index.d.ts +1 -2
  46. package/dist/bin/index.js +0 -1
  47. package/dist/bin/index.js.map +1 -1
  48. package/dist/cache/core/index.js.map +1 -1
  49. package/dist/cli/index.d.ts +249 -218
  50. package/dist/cli/index.d.ts.map +1 -1
  51. package/dist/cli/index.js +951 -821
  52. package/dist/cli/index.js.map +1 -1
  53. package/dist/command/index.d.ts +40 -0
  54. package/dist/command/index.d.ts.map +1 -1
  55. package/dist/command/index.js +97 -17
  56. package/dist/command/index.js.map +1 -1
  57. package/dist/core/index.browser.js +14 -18
  58. package/dist/core/index.browser.js.map +1 -1
  59. package/dist/core/index.d.ts +29 -0
  60. package/dist/core/index.d.ts.map +1 -1
  61. package/dist/core/index.js +21 -24
  62. package/dist/core/index.js.map +1 -1
  63. package/dist/core/index.native.js +21 -24
  64. package/dist/core/index.native.js.map +1 -1
  65. package/dist/datetime/index.js.map +1 -1
  66. package/dist/fake/index.js +195 -168
  67. package/dist/fake/index.js.map +1 -1
  68. package/dist/file/index.d.ts +8 -0
  69. package/dist/file/index.d.ts.map +1 -1
  70. package/dist/file/index.js +3 -0
  71. package/dist/file/index.js.map +1 -1
  72. package/dist/lock/redis/index.js.map +1 -1
  73. package/dist/logger/index.js.map +1 -1
  74. package/dist/mcp/index.d.ts.map +1 -1
  75. package/dist/mcp/index.js.map +1 -1
  76. package/dist/orm/index.browser.js +26 -5
  77. package/dist/orm/index.browser.js.map +1 -1
  78. package/dist/orm/index.d.ts +146 -121
  79. package/dist/orm/index.d.ts.map +1 -1
  80. package/dist/orm/index.js +49 -24
  81. package/dist/orm/index.js.map +1 -1
  82. package/dist/redis/index.js.map +1 -1
  83. package/dist/retry/index.js.map +1 -1
  84. package/dist/router/index.js.map +1 -1
  85. package/dist/scheduler/index.d.ts +6 -6
  86. package/dist/scheduler/index.js.map +1 -1
  87. package/dist/security/index.d.ts +29 -29
  88. package/dist/security/index.d.ts.map +1 -1
  89. package/dist/security/index.js +1 -1
  90. package/dist/security/index.js.map +1 -1
  91. package/dist/server/auth/index.d.ts +171 -155
  92. package/dist/server/auth/index.d.ts.map +1 -1
  93. package/dist/server/auth/index.js +0 -1
  94. package/dist/server/auth/index.js.map +1 -1
  95. package/dist/server/cache/index.js.map +1 -1
  96. package/dist/server/compress/index.d.ts.map +1 -1
  97. package/dist/server/compress/index.js +2 -0
  98. package/dist/server/compress/index.js.map +1 -1
  99. package/dist/server/cookies/index.browser.js.map +1 -1
  100. package/dist/server/cookies/index.js.map +1 -1
  101. package/dist/server/core/index.browser.js.map +1 -1
  102. package/dist/server/core/index.d.ts.map +1 -1
  103. package/dist/server/core/index.js +1 -1
  104. package/dist/server/core/index.js.map +1 -1
  105. package/dist/server/health/index.d.ts +17 -17
  106. package/dist/server/helmet/index.js.map +1 -1
  107. package/dist/server/links/index.browser.js +22 -6
  108. package/dist/server/links/index.browser.js.map +1 -1
  109. package/dist/server/links/index.d.ts +46 -44
  110. package/dist/server/links/index.d.ts.map +1 -1
  111. package/dist/server/links/index.js +24 -41
  112. package/dist/server/links/index.js.map +1 -1
  113. package/dist/server/multipart/index.js.map +1 -1
  114. package/dist/server/rate-limit/index.js.map +1 -1
  115. package/dist/server/security/index.js.map +1 -1
  116. package/dist/server/swagger/index.d.ts +2 -1
  117. package/dist/server/swagger/index.d.ts.map +1 -1
  118. package/dist/server/swagger/index.js +8 -3
  119. package/dist/server/swagger/index.js.map +1 -1
  120. package/dist/thread/index.js.map +1 -1
  121. package/dist/topic/core/index.js.map +1 -1
  122. package/dist/vite/index.d.ts.map +1 -1
  123. package/dist/vite/index.js +12 -4
  124. package/dist/vite/index.js.map +1 -1
  125. package/dist/websocket/index.browser.js.map +1 -1
  126. package/dist/websocket/index.js.map +1 -1
  127. package/package.json +7 -7
  128. package/src/api/audits/controllers/{AuditController.ts → AdminAuditController.ts} +5 -6
  129. package/src/api/audits/entities/audits.ts +5 -5
  130. package/src/api/audits/index.browser.ts +1 -1
  131. package/src/api/audits/index.ts +3 -3
  132. package/src/api/audits/primitives/$audit.spec.ts +276 -0
  133. package/src/api/audits/services/AuditService.spec.ts +495 -0
  134. package/src/api/files/__tests__/$bucket.spec.ts +91 -0
  135. package/src/api/files/controllers/AdminFileStatsController.spec.ts +166 -0
  136. package/src/api/files/controllers/{StorageStatsController.ts → AdminFileStatsController.ts} +2 -2
  137. package/src/api/files/controllers/FileController.spec.ts +558 -0
  138. package/src/api/files/controllers/FileController.ts +4 -5
  139. package/src/api/files/entities/files.ts +5 -5
  140. package/src/api/files/index.browser.ts +1 -1
  141. package/src/api/files/index.ts +4 -4
  142. package/src/api/files/jobs/FileJobs.spec.ts +52 -0
  143. package/src/api/files/services/FileService.spec.ts +109 -0
  144. package/src/api/jobs/__tests__/JobController.spec.ts +343 -0
  145. package/src/api/jobs/controllers/{JobController.ts → AdminJobController.ts} +2 -2
  146. package/src/api/jobs/entities/jobExecutions.ts +5 -5
  147. package/src/api/jobs/index.ts +3 -3
  148. package/src/api/jobs/primitives/$job.spec.ts +476 -0
  149. package/src/api/notifications/controllers/{NotificationController.ts → AdminNotificationController.ts} +4 -5
  150. package/src/api/notifications/entities/notifications.ts +5 -5
  151. package/src/api/notifications/index.browser.ts +1 -1
  152. package/src/api/notifications/index.ts +4 -4
  153. package/src/api/parameters/controllers/{ConfigController.ts → AdminConfigController.ts} +46 -107
  154. package/src/api/parameters/entities/parameters.ts +7 -17
  155. package/src/api/parameters/index.ts +3 -3
  156. package/src/api/parameters/primitives/$config.spec.ts +356 -0
  157. package/src/api/parameters/schemas/activateConfigBodySchema.ts +12 -0
  158. package/src/api/parameters/schemas/checkScheduledResponseSchema.ts +8 -0
  159. package/src/api/parameters/schemas/configCurrentResponseSchema.ts +13 -0
  160. package/src/api/parameters/schemas/configHistoryResponseSchema.ts +9 -0
  161. package/src/api/parameters/schemas/configNameParamSchema.ts +10 -0
  162. package/src/api/parameters/schemas/configNamesResponseSchema.ts +8 -0
  163. package/src/api/parameters/schemas/configTreeNodeSchema.ts +13 -0
  164. package/src/api/parameters/schemas/configVersionParamSchema.ts +9 -0
  165. package/src/api/parameters/schemas/configVersionResponseSchema.ts +9 -0
  166. package/src/api/parameters/schemas/configsByStatusResponseSchema.ts +9 -0
  167. package/src/api/parameters/schemas/createConfigVersionBodySchema.ts +24 -0
  168. package/src/api/parameters/schemas/index.ts +15 -0
  169. package/src/api/parameters/schemas/parameterResponseSchema.ts +26 -0
  170. package/src/api/parameters/schemas/parameterStatusSchema.ts +13 -0
  171. package/src/api/parameters/schemas/rollbackConfigBodySchema.ts +15 -0
  172. package/src/api/parameters/schemas/statusParamSchema.ts +9 -0
  173. package/src/api/users/__tests__/EmailVerification.spec.ts +369 -0
  174. package/src/api/users/__tests__/PasswordReset.spec.ts +550 -0
  175. package/src/api/users/controllers/AdminIdentityController.spec.ts +365 -0
  176. package/src/api/users/controllers/{IdentityController.ts → AdminIdentityController.ts} +3 -4
  177. package/src/api/users/controllers/AdminSessionController.spec.ts +274 -0
  178. package/src/api/users/controllers/{SessionController.ts → AdminSessionController.ts} +3 -4
  179. package/src/api/users/controllers/AdminUserController.spec.ts +372 -0
  180. package/src/api/users/controllers/AdminUserController.ts +116 -0
  181. package/src/api/users/controllers/UserController.ts +4 -107
  182. package/src/api/users/controllers/UserRealmController.ts +3 -0
  183. package/src/api/users/entities/identities.ts +6 -6
  184. package/src/api/users/entities/sessions.ts +6 -6
  185. package/src/api/users/entities/users.ts +9 -9
  186. package/src/api/users/index.ts +13 -6
  187. package/src/api/users/primitives/$userRealm.ts +13 -8
  188. package/src/api/users/services/CredentialService.spec.ts +509 -0
  189. package/src/api/users/services/CredentialService.ts +46 -0
  190. package/src/api/users/services/IdentityService.ts +15 -0
  191. package/src/api/users/services/RegistrationService.spec.ts +630 -0
  192. package/src/api/users/services/RegistrationService.ts +18 -0
  193. package/src/api/users/services/SessionService.spec.ts +301 -0
  194. package/src/api/users/services/SessionService.ts +110 -1
  195. package/src/api/users/services/UserService.ts +67 -2
  196. package/src/api/verifications/__tests__/CodeVerification.spec.ts +318 -0
  197. package/src/api/verifications/__tests__/LinkVerification.spec.ts +279 -0
  198. package/src/api/verifications/entities/verifications.ts +6 -6
  199. package/src/api/verifications/jobs/VerificationJobs.spec.ts +50 -0
  200. package/src/batch/__tests__/startup-buffering.spec.ts +458 -0
  201. package/src/batch/primitives/$batch.spec.ts +766 -0
  202. package/src/batch/providers/BatchProvider.spec.ts +786 -0
  203. package/src/bin/index.ts +0 -1
  204. package/src/bucket/__tests__/shared.ts +194 -0
  205. package/src/bucket/primitives/$bucket.spec.ts +104 -0
  206. package/src/bucket/providers/FileStorageProvider.spec.ts +13 -0
  207. package/src/bucket/providers/LocalFileStorageProvider.spec.ts +77 -0
  208. package/src/bucket/providers/MemoryFileStorageProvider.spec.ts +82 -0
  209. package/src/cache/core/__tests__/shared.ts +377 -0
  210. package/src/cache/core/primitives/$cache.spec.ts +111 -0
  211. package/src/cache/redis/__tests__/cache-redis.spec.ts +70 -0
  212. package/src/cli/apps/AlephaCli.ts +54 -16
  213. package/src/cli/apps/AlephaPackageBuilderCli.ts +2 -1
  214. package/src/cli/assets/appRouterTs.ts +1 -1
  215. package/src/cli/commands/{ViteCommands.ts → build.ts} +2 -105
  216. package/src/cli/commands/clean.ts +14 -0
  217. package/src/cli/commands/{DrizzleCommands.ts → db.ts} +10 -117
  218. package/src/cli/commands/{DeployCommands.ts → deploy.ts} +1 -1
  219. package/src/cli/commands/dev.ts +69 -0
  220. package/src/cli/commands/format.ts +17 -0
  221. package/src/cli/commands/gen/changelog.spec.ts +315 -0
  222. package/src/cli/commands/{ChangelogCommands.ts → gen/changelog.ts} +16 -31
  223. package/src/cli/commands/gen/openapi.ts +71 -0
  224. package/src/cli/commands/gen.ts +18 -0
  225. package/src/cli/commands/{CoreCommands.ts → init.ts} +4 -40
  226. package/src/cli/commands/lint.ts +17 -0
  227. package/src/cli/commands/root.ts +41 -0
  228. package/src/cli/commands/run.ts +24 -0
  229. package/src/cli/commands/test.ts +42 -0
  230. package/src/cli/commands/typecheck.ts +24 -0
  231. package/src/cli/commands/{VerifyCommands.ts → verify.ts} +1 -13
  232. package/src/cli/defineConfig.ts +10 -1
  233. package/src/cli/index.ts +17 -7
  234. package/src/cli/services/AlephaCliUtils.ts +71 -32
  235. package/src/cli/services/GitMessageParser.ts +1 -1
  236. package/src/command/helpers/Asker.spec.ts +127 -0
  237. package/src/command/helpers/Runner.spec.ts +126 -0
  238. package/src/command/primitives/$command.spec.ts +1588 -0
  239. package/src/command/providers/CliProvider.ts +74 -24
  240. package/src/core/Alepha.ts +52 -4
  241. package/src/core/__tests__/Alepha-emit.spec.ts +22 -0
  242. package/src/core/__tests__/Alepha-graph.spec.ts +93 -0
  243. package/src/core/__tests__/Alepha-has.spec.ts +41 -0
  244. package/src/core/__tests__/Alepha-inject.spec.ts +93 -0
  245. package/src/core/__tests__/Alepha-register.spec.ts +81 -0
  246. package/src/core/__tests__/Alepha-start.spec.ts +176 -0
  247. package/src/core/__tests__/Alepha-with.spec.ts +14 -0
  248. package/src/core/__tests__/TypeBox-usecases.spec.ts +35 -0
  249. package/src/core/__tests__/TypeBoxLocale.spec.ts +15 -0
  250. package/src/core/__tests__/descriptor.spec.ts +34 -0
  251. package/src/core/__tests__/fixtures/A.ts +5 -0
  252. package/src/core/__tests__/pagination.spec.ts +77 -0
  253. package/src/core/helpers/jsonSchemaToTypeBox.ts +2 -2
  254. package/src/core/primitives/$atom.spec.ts +43 -0
  255. package/src/core/primitives/$hook.spec.ts +130 -0
  256. package/src/core/primitives/$inject.spec.ts +175 -0
  257. package/src/core/primitives/$module.spec.ts +115 -0
  258. package/src/core/providers/CodecManager.spec.ts +740 -0
  259. package/src/core/providers/EventManager.spec.ts +762 -0
  260. package/src/core/providers/EventManager.ts +4 -0
  261. package/src/core/providers/StateManager.spec.ts +365 -0
  262. package/src/core/providers/TypeProvider.spec.ts +1607 -0
  263. package/src/core/providers/TypeProvider.ts +20 -26
  264. package/src/datetime/primitives/$interval.spec.ts +103 -0
  265. package/src/datetime/providers/DateTimeProvider.spec.ts +86 -0
  266. package/src/email/primitives/$email.spec.ts +175 -0
  267. package/src/email/providers/LocalEmailProvider.spec.ts +341 -0
  268. package/src/fake/__tests__/keyName.example.ts +40 -0
  269. package/src/fake/__tests__/keyName.spec.ts +152 -0
  270. package/src/fake/__tests__/module.example.ts +32 -0
  271. package/src/fake/providers/FakeProvider.spec.ts +438 -0
  272. package/src/file/providers/FileSystemProvider.ts +8 -0
  273. package/src/file/providers/NodeFileSystemProvider.spec.ts +418 -0
  274. package/src/file/providers/NodeFileSystemProvider.ts +5 -0
  275. package/src/file/services/FileDetector.spec.ts +591 -0
  276. package/src/lock/core/__tests__/shared.ts +190 -0
  277. package/src/lock/core/providers/MemoryLockProvider.spec.ts +25 -0
  278. package/src/lock/redis/providers/RedisLockProvider.spec.ts +25 -0
  279. package/src/logger/__tests__/SimpleFormatterProvider.spec.ts +109 -0
  280. package/src/logger/primitives/$logger.spec.ts +108 -0
  281. package/src/logger/services/Logger.spec.ts +295 -0
  282. package/src/mcp/__tests__/errors.spec.ts +175 -0
  283. package/src/mcp/__tests__/integration.spec.ts +450 -0
  284. package/src/mcp/helpers/jsonrpc.spec.ts +380 -0
  285. package/src/mcp/primitives/$prompt.spec.ts +468 -0
  286. package/src/mcp/primitives/$resource.spec.ts +390 -0
  287. package/src/mcp/primitives/$tool.spec.ts +406 -0
  288. package/src/mcp/providers/McpServerProvider.spec.ts +797 -0
  289. package/src/orm/__tests__/$repository-crud.spec.ts +276 -0
  290. package/src/orm/__tests__/$repository-hooks.spec.ts +325 -0
  291. package/src/orm/__tests__/$repository-orderBy.spec.ts +128 -0
  292. package/src/orm/__tests__/$repository-pagination-sort.spec.ts +149 -0
  293. package/src/orm/__tests__/$repository-save.spec.ts +37 -0
  294. package/src/orm/__tests__/ModelBuilder-integration.spec.ts +490 -0
  295. package/src/orm/__tests__/ModelBuilder-types.spec.ts +186 -0
  296. package/src/orm/__tests__/PostgresProvider.spec.ts +46 -0
  297. package/src/orm/__tests__/delete-returning.spec.ts +256 -0
  298. package/src/orm/__tests__/deletedAt.spec.ts +80 -0
  299. package/src/orm/__tests__/enums.spec.ts +315 -0
  300. package/src/orm/__tests__/execute.spec.ts +72 -0
  301. package/src/orm/__tests__/fixtures/bigEntitySchema.ts +65 -0
  302. package/src/orm/__tests__/fixtures/userEntitySchema.ts +27 -0
  303. package/src/orm/__tests__/joins.spec.ts +1114 -0
  304. package/src/orm/__tests__/page.spec.ts +287 -0
  305. package/src/orm/__tests__/primaryKey.spec.ts +87 -0
  306. package/src/orm/__tests__/query-date-encoding.spec.ts +402 -0
  307. package/src/orm/__tests__/ref-auto-onDelete.spec.ts +156 -0
  308. package/src/orm/__tests__/references.spec.ts +102 -0
  309. package/src/orm/__tests__/security.spec.ts +710 -0
  310. package/src/orm/__tests__/sqlite.spec.ts +111 -0
  311. package/src/orm/__tests__/string-operators.spec.ts +429 -0
  312. package/src/orm/__tests__/timestamps.spec.ts +388 -0
  313. package/src/orm/__tests__/validation.spec.ts +183 -0
  314. package/src/orm/__tests__/version.spec.ts +64 -0
  315. package/src/orm/helpers/parseQueryString.spec.ts +196 -0
  316. package/src/orm/index.browser.ts +1 -1
  317. package/src/orm/index.ts +10 -6
  318. package/src/orm/primitives/$repository.spec.ts +137 -0
  319. package/src/orm/primitives/$sequence.spec.ts +29 -0
  320. package/src/orm/primitives/$transaction.spec.ts +82 -0
  321. package/src/orm/providers/{PostgresTypeProvider.ts → DatabaseTypeProvider.ts} +25 -3
  322. package/src/orm/providers/drivers/BunPostgresProvider.ts +3 -3
  323. package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -1
  324. package/src/orm/providers/drivers/CloudflareD1Provider.ts +1 -1
  325. package/src/orm/providers/drivers/DatabaseProvider.ts +1 -1
  326. package/src/orm/providers/drivers/NodePostgresProvider.ts +3 -3
  327. package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
  328. package/src/orm/providers/drivers/PglitePostgresProvider.ts +2 -2
  329. package/src/orm/services/ModelBuilder.spec.ts +575 -0
  330. package/src/orm/services/Repository.spec.ts +137 -0
  331. package/src/queue/core/__tests__/shared.ts +143 -0
  332. package/src/queue/core/providers/MemoryQueueProvider.spec.ts +23 -0
  333. package/src/queue/core/providers/WorkerProvider.spec.ts +378 -0
  334. package/src/queue/redis/providers/RedisQueueProvider.spec.ts +23 -0
  335. package/src/redis/__tests__/redis.spec.ts +58 -0
  336. package/src/retry/primitives/$retry.spec.ts +234 -0
  337. package/src/retry/providers/RetryProvider.spec.ts +438 -0
  338. package/src/router/__tests__/match.spec.ts +252 -0
  339. package/src/router/providers/RouterProvider.spec.ts +197 -0
  340. package/src/scheduler/__tests__/$scheduler-cron.spec.ts +25 -0
  341. package/src/scheduler/__tests__/$scheduler-interval.spec.ts +25 -0
  342. package/src/scheduler/__tests__/shared.ts +77 -0
  343. package/src/security/__tests__/bug-1-wildcard-after-start.spec.ts +229 -0
  344. package/src/security/__tests__/bug-2-password-validation.spec.ts +245 -0
  345. package/src/security/__tests__/bug-3-regex-vulnerability.spec.ts +407 -0
  346. package/src/security/__tests__/bug-4-oauth2-validation.spec.ts +439 -0
  347. package/src/security/__tests__/multi-layer-permissions.spec.ts +522 -0
  348. package/src/security/primitives/$permission.spec.ts +30 -0
  349. package/src/security/primitives/$permission.ts +2 -2
  350. package/src/security/primitives/$realm.spec.ts +101 -0
  351. package/src/security/primitives/$role.spec.ts +52 -0
  352. package/src/security/primitives/$serviceAccount.spec.ts +61 -0
  353. package/src/security/providers/SecurityProvider.spec.ts +350 -0
  354. package/src/server/auth/providers/ServerAuthProvider.ts +0 -2
  355. package/src/server/cache/providers/ServerCacheProvider.spec.ts +942 -0
  356. package/src/server/compress/providers/ServerCompressProvider.spec.ts +31 -0
  357. package/src/server/compress/providers/ServerCompressProvider.ts +2 -0
  358. package/src/server/cookies/providers/ServerCookiesProvider.spec.ts +253 -0
  359. package/src/server/core/__tests__/ServerRouterProvider-getRoutes.spec.ts +334 -0
  360. package/src/server/core/__tests__/ServerRouterProvider-requestId.spec.ts +129 -0
  361. package/src/server/core/primitives/$action.spec.ts +191 -0
  362. package/src/server/core/primitives/$route.spec.ts +65 -0
  363. package/src/server/core/providers/ServerBodyParserProvider.spec.ts +93 -0
  364. package/src/server/core/providers/ServerLoggerProvider.spec.ts +100 -0
  365. package/src/server/core/providers/ServerProvider.ts +3 -1
  366. package/src/server/core/services/HttpClient.spec.ts +123 -0
  367. package/src/server/core/services/UserAgentParser.spec.ts +111 -0
  368. package/src/server/cors/providers/ServerCorsProvider.spec.ts +481 -0
  369. package/src/server/health/providers/ServerHealthProvider.spec.ts +22 -0
  370. package/src/server/helmet/providers/ServerHelmetProvider.spec.ts +105 -0
  371. package/src/server/links/__tests__/$action.spec.ts +238 -0
  372. package/src/server/links/__tests__/fixtures/CrudApp.ts +122 -0
  373. package/src/server/links/__tests__/requestId.spec.ts +120 -0
  374. package/src/server/links/primitives/$remote.spec.ts +228 -0
  375. package/src/server/links/providers/LinkProvider.spec.ts +54 -0
  376. package/src/server/links/providers/LinkProvider.ts +49 -3
  377. package/src/server/links/providers/ServerLinksProvider.ts +1 -53
  378. package/src/server/links/schemas/apiLinksResponseSchema.ts +7 -0
  379. package/src/server/metrics/providers/ServerMetricsProvider.spec.ts +25 -0
  380. package/src/server/multipart/providers/ServerMultipartProvider.spec.ts +528 -0
  381. package/src/server/proxy/primitives/$proxy.spec.ts +87 -0
  382. package/src/server/rate-limit/__tests__/ActionRateLimit.spec.ts +211 -0
  383. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +344 -0
  384. package/src/server/security/__tests__/BasicAuth.spec.ts +684 -0
  385. package/src/server/security/__tests__/ServerSecurityProvider-realm.spec.ts +388 -0
  386. package/src/server/security/providers/ServerSecurityProvider.spec.ts +123 -0
  387. package/src/server/static/primitives/$serve.spec.ts +193 -0
  388. package/src/server/swagger/__tests__/ui.spec.ts +52 -0
  389. package/src/server/swagger/primitives/$swagger.spec.ts +193 -0
  390. package/src/server/swagger/providers/ServerSwaggerProvider.ts +18 -8
  391. package/src/sms/primitives/$sms.spec.ts +165 -0
  392. package/src/sms/providers/LocalSmsProvider.spec.ts +224 -0
  393. package/src/sms/providers/MemorySmsProvider.spec.ts +193 -0
  394. package/src/thread/primitives/$thread.spec.ts +186 -0
  395. package/src/topic/core/__tests__/shared.ts +144 -0
  396. package/src/topic/core/providers/MemoryTopicProvider.spec.ts +23 -0
  397. package/src/topic/redis/providers/RedisTopicProvider.spec.ts +23 -0
  398. package/src/vite/plugins/viteAlephaDev.ts +16 -4
  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/commands/BiomeCommands.ts +0 -29
@@ -0,0 +1,528 @@
1
+ import { Alepha, t } from "alepha";
2
+ import { $action, ServerProvider } from "alepha/server";
3
+ import { describe, expect, test } from "vitest";
4
+ import { AlephaServerMultipart } from "../index.ts";
5
+
6
+ class App {
7
+ upload = $action({
8
+ schema: {
9
+ body: t.object({
10
+ file: t.file(),
11
+ }),
12
+ response: t.text(),
13
+ },
14
+ handler: ({ body }) => {
15
+ expect(body.file).toBeDefined();
16
+ expect(body.file.name).toBe("test.txt");
17
+ expect(body.file.size).toBe(12);
18
+ expect(body.file.type).toBe("text/plain");
19
+ expect(body.file.lastModified).toBeGreaterThan(0);
20
+ return `File ${body.file.name} uploaded successfully.`;
21
+ },
22
+ });
23
+ }
24
+
25
+ describe("ServerMultipartProvider", () => {
26
+ test("ServerMultipartProvider - hello", async ({ expect }) => {
27
+ const alepha = Alepha.create().with(AlephaServerMultipart).with(App);
28
+ await alepha.start();
29
+
30
+ const file = new File(["test content"], "test.txt", { type: "text/plain" });
31
+ const body = new FormData();
32
+ body.append("file", file);
33
+
34
+ const resp = await fetch(
35
+ `${alepha.inject(ServerProvider).hostname}/api/upload`,
36
+ {
37
+ method: "POST",
38
+ body,
39
+ },
40
+ );
41
+
42
+ const text = await resp.text();
43
+ expect(resp.status).toBe(200);
44
+ expect(text).toBe(`File test.txt uploaded successfully.`);
45
+ });
46
+
47
+ test("ServerMultipartProvider - local", async ({ expect }) => {
48
+ const alepha = Alepha.create().with(AlephaServerMultipart).with(App);
49
+ await alepha.start();
50
+
51
+ const file = new File(["test content"], "test.txt", { type: "text/plain" });
52
+
53
+ const resp = await alepha.inject(App).upload.run({
54
+ body: {
55
+ file,
56
+ },
57
+ });
58
+
59
+ expect(resp).toBe(`File test.txt uploaded successfully.`);
60
+ });
61
+ });
62
+
63
+ describe("ServerMultipartProvider - Size Limits", () => {
64
+ test("should reject file exceeding individual file size limit", async ({
65
+ expect,
66
+ }) => {
67
+ class LargeFileApp {
68
+ upload = $action({
69
+ schema: {
70
+ body: t.object({
71
+ file: t.file(),
72
+ }),
73
+ response: t.text(),
74
+ },
75
+ handler: ({ body }) => `File ${body.file.name} uploaded.`,
76
+ });
77
+ }
78
+
79
+ // Set a very small file limit (100 bytes) via env config
80
+ const alepha = Alepha.create({
81
+ env: { SERVER_MULTIPART_FILE_LIMIT: "100" },
82
+ })
83
+ .with(AlephaServerMultipart)
84
+ .with(LargeFileApp);
85
+ await alepha.start();
86
+
87
+ // Create a file larger than the limit
88
+ const largeContent = "x".repeat(200);
89
+ const file = new File([largeContent], "large.txt", { type: "text/plain" });
90
+ const formData = new FormData();
91
+ formData.append("file", file);
92
+
93
+ // Use HTTP request - validation happens at HTTP layer
94
+ const resp = await fetch(
95
+ `${alepha.inject(ServerProvider).hostname}/api/upload`,
96
+ {
97
+ method: "POST",
98
+ body: formData,
99
+ },
100
+ );
101
+
102
+ expect(resp.status).toBe(413);
103
+ const body = await resp.json();
104
+ expect(body.message).toMatch(/exceeds size limit/i);
105
+ });
106
+
107
+ test("should reject request exceeding total size limit", async ({
108
+ expect,
109
+ }) => {
110
+ class MultiFileApp {
111
+ upload = $action({
112
+ schema: {
113
+ body: t.object({
114
+ file1: t.file(),
115
+ file2: t.file(),
116
+ }),
117
+ response: t.text(),
118
+ },
119
+ handler: ({ body }) =>
120
+ `Files ${body.file1.name} and ${body.file2.name} uploaded.`,
121
+ });
122
+ }
123
+
124
+ // Set total limit to 150 bytes, individual file limit to 100 bytes
125
+ const alepha = Alepha.create({
126
+ env: {
127
+ SERVER_MULTIPART_LIMIT: "150",
128
+ SERVER_MULTIPART_FILE_LIMIT: "100",
129
+ },
130
+ })
131
+ .with(AlephaServerMultipart)
132
+ .with(MultiFileApp);
133
+ await alepha.start();
134
+
135
+ // Create two files that individually fit but together exceed the limit
136
+ const file1 = new File(["x".repeat(80)], "file1.txt", {
137
+ type: "text/plain",
138
+ });
139
+ const file2 = new File(["y".repeat(80)], "file2.txt", {
140
+ type: "text/plain",
141
+ });
142
+ const formData = new FormData();
143
+ formData.append("file1", file1);
144
+ formData.append("file2", file2);
145
+
146
+ // Use HTTP request - validation happens at HTTP layer
147
+ const resp = await fetch(
148
+ `${alepha.inject(ServerProvider).hostname}/api/upload`,
149
+ {
150
+ method: "POST",
151
+ body: formData,
152
+ },
153
+ );
154
+
155
+ expect(resp.status).toBe(413);
156
+ const body = await resp.json();
157
+ expect(body.message).toMatch(/size limit exceeded/i);
158
+ });
159
+
160
+ test("should reject request with too many files", async ({ expect }) => {
161
+ class ManyFilesApp {
162
+ upload = $action({
163
+ schema: {
164
+ body: t.object({
165
+ file1: t.file(),
166
+ file2: t.file(),
167
+ file3: t.file(),
168
+ }),
169
+ response: t.text(),
170
+ },
171
+ handler: () => "uploaded",
172
+ });
173
+ }
174
+
175
+ // Set file count limit to 2
176
+ const alepha = Alepha.create({
177
+ env: { SERVER_MULTIPART_FILE_COUNT: "2" },
178
+ })
179
+ .with(AlephaServerMultipart)
180
+ .with(ManyFilesApp);
181
+ await alepha.start();
182
+
183
+ const file1 = new File(["content1"], "file1.txt", { type: "text/plain" });
184
+ const file2 = new File(["content2"], "file2.txt", { type: "text/plain" });
185
+ const file3 = new File(["content3"], "file3.txt", { type: "text/plain" });
186
+ const formData = new FormData();
187
+ formData.append("file1", file1);
188
+ formData.append("file2", file2);
189
+ formData.append("file3", file3);
190
+
191
+ // Use HTTP request - validation happens at HTTP layer
192
+ const resp = await fetch(
193
+ `${alepha.inject(ServerProvider).hostname}/api/upload`,
194
+ {
195
+ method: "POST",
196
+ body: formData,
197
+ },
198
+ );
199
+
200
+ expect(resp.status).toBe(413);
201
+ const body = await resp.json();
202
+ expect(body.message).toMatch(/Too many files/i);
203
+ });
204
+
205
+ test("should accept file exactly at the size limit", async ({ expect }) => {
206
+ class ExactLimitApp {
207
+ upload = $action({
208
+ schema: {
209
+ body: t.object({
210
+ file: t.file(),
211
+ }),
212
+ response: t.text(),
213
+ },
214
+ handler: ({ body }) => `File size: ${body.file.size}`,
215
+ });
216
+ }
217
+
218
+ // Set file limit to exactly 100 bytes
219
+ const alepha = Alepha.create({
220
+ env: { SERVER_MULTIPART_FILE_LIMIT: "100" },
221
+ })
222
+ .with(AlephaServerMultipart)
223
+ .with(ExactLimitApp);
224
+ await alepha.start();
225
+
226
+ // Create a file exactly at the limit
227
+ const content = "x".repeat(100);
228
+ const file = new File([content], "exact.txt", { type: "text/plain" });
229
+
230
+ const result = await alepha.inject(ExactLimitApp).upload.run({
231
+ body: { file },
232
+ });
233
+
234
+ expect(result).toBe("File size: 100");
235
+ });
236
+
237
+ test("should accept file just under the size limit", async ({ expect }) => {
238
+ class UnderLimitApp {
239
+ upload = $action({
240
+ schema: {
241
+ body: t.object({
242
+ file: t.file(),
243
+ }),
244
+ response: t.text(),
245
+ },
246
+ handler: ({ body }) => `File size: ${body.file.size}`,
247
+ });
248
+ }
249
+
250
+ // Set file limit to 100 bytes
251
+ const alepha = Alepha.create({
252
+ env: { SERVER_MULTIPART_FILE_LIMIT: "100" },
253
+ })
254
+ .with(AlephaServerMultipart)
255
+ .with(UnderLimitApp);
256
+ await alepha.start();
257
+
258
+ // Create a file just under the limit
259
+ const content = "x".repeat(99);
260
+ const file = new File([content], "under.txt", { type: "text/plain" });
261
+
262
+ const result = await alepha.inject(UnderLimitApp).upload.run({
263
+ body: { file },
264
+ });
265
+
266
+ expect(result).toBe("File size: 99");
267
+ });
268
+
269
+ test("should reject file just over the size limit", async ({ expect }) => {
270
+ class OverLimitApp {
271
+ upload = $action({
272
+ schema: {
273
+ body: t.object({
274
+ file: t.file(),
275
+ }),
276
+ response: t.text(),
277
+ },
278
+ handler: ({ body }) => `File size: ${body.file.size}`,
279
+ });
280
+ }
281
+
282
+ // Set file limit to 100 bytes
283
+ const alepha = Alepha.create({
284
+ env: { SERVER_MULTIPART_FILE_LIMIT: "100" },
285
+ })
286
+ .with(AlephaServerMultipart)
287
+ .with(OverLimitApp);
288
+ await alepha.start();
289
+
290
+ // Create a file just over the limit
291
+ const content = "x".repeat(101);
292
+ const file = new File([content], "over.txt", { type: "text/plain" });
293
+ const formData = new FormData();
294
+ formData.append("file", file);
295
+
296
+ // Use HTTP request - validation happens at HTTP layer
297
+ const resp = await fetch(
298
+ `${alepha.inject(ServerProvider).hostname}/api/upload`,
299
+ {
300
+ method: "POST",
301
+ body: formData,
302
+ },
303
+ );
304
+
305
+ expect(resp.status).toBe(413);
306
+ const body = await resp.json();
307
+ expect(body.message).toMatch(/exceeds size limit/i);
308
+ });
309
+
310
+ test("should handle empty file upload", async ({ expect }) => {
311
+ class EmptyFileApp {
312
+ upload = $action({
313
+ schema: {
314
+ body: t.object({
315
+ file: t.file(),
316
+ }),
317
+ response: t.text(),
318
+ },
319
+ handler: ({ body }) => `File size: ${body.file.size}`,
320
+ });
321
+ }
322
+
323
+ const alepha = Alepha.create()
324
+ .with(AlephaServerMultipart)
325
+ .with(EmptyFileApp);
326
+ await alepha.start();
327
+
328
+ // Create an empty file
329
+ const file = new File([], "empty.txt", { type: "text/plain" });
330
+
331
+ const result = await alepha.inject(EmptyFileApp).upload.run({
332
+ body: { file },
333
+ });
334
+
335
+ expect(result).toBe("File size: 0");
336
+
337
+ await alepha.stop();
338
+ });
339
+
340
+ test("should reject via HTTP when content-length exceeds limit", async ({
341
+ expect,
342
+ }) => {
343
+ class ContentLengthApp {
344
+ upload = $action({
345
+ schema: {
346
+ body: t.object({
347
+ file: t.file(),
348
+ }),
349
+ response: t.text(),
350
+ },
351
+ handler: ({ body }) => `uploaded`,
352
+ });
353
+ }
354
+
355
+ // Set a very small total limit
356
+ const alepha = Alepha.create({
357
+ env: { SERVER_MULTIPART_LIMIT: "50" },
358
+ })
359
+ .with(AlephaServerMultipart)
360
+ .with(ContentLengthApp);
361
+ await alepha.start();
362
+
363
+ const largeContent = "x".repeat(1000);
364
+ const file = new File([largeContent], "large.txt", { type: "text/plain" });
365
+ const formData = new FormData();
366
+ formData.append("file", file);
367
+
368
+ const resp = await fetch(
369
+ `${alepha.inject(ServerProvider).hostname}/api/upload`,
370
+ {
371
+ method: "POST",
372
+ body: formData,
373
+ },
374
+ );
375
+
376
+ expect(resp.status).toBe(413);
377
+ const body = await resp.json();
378
+ expect(body.message).toMatch(/size limit exceeded/i);
379
+ });
380
+
381
+ test("should use default limits when env vars not set", async ({
382
+ expect,
383
+ }) => {
384
+ class DefaultLimitsApp {
385
+ upload = $action({
386
+ schema: {
387
+ body: t.object({
388
+ file: t.file(),
389
+ }),
390
+ response: t.text(),
391
+ },
392
+ handler: ({ body }) => `File size: ${body.file.size}`,
393
+ });
394
+ }
395
+
396
+ // Create with no env config to use defaults
397
+ const alepha = Alepha.create()
398
+ .with(AlephaServerMultipart)
399
+ .with(DefaultLimitsApp);
400
+ await alepha.start();
401
+
402
+ // Create a reasonable file (should work with default 5MB limit)
403
+ const content = "x".repeat(1000);
404
+ const file = new File([content], "normal.txt", { type: "text/plain" });
405
+
406
+ const result = await alepha.inject(DefaultLimitsApp).upload.run({
407
+ body: { file },
408
+ });
409
+
410
+ expect(result).toBe("File size: 1000");
411
+ });
412
+
413
+ test("should handle mixed file and text fields with size limits", async ({
414
+ expect,
415
+ }) => {
416
+ class MixedFieldsApp {
417
+ upload = $action({
418
+ schema: {
419
+ body: t.object({
420
+ name: t.text(),
421
+ description: t.text(),
422
+ file: t.file(),
423
+ }),
424
+ response: t.text(),
425
+ },
426
+ handler: ({ body }) =>
427
+ `${body.name}: ${body.description} (${body.file.size} bytes)`,
428
+ });
429
+ }
430
+
431
+ const alepha = Alepha.create({
432
+ env: { SERVER_MULTIPART_FILE_LIMIT: "1000" },
433
+ })
434
+ .with(AlephaServerMultipart)
435
+ .with(MixedFieldsApp);
436
+ await alepha.start();
437
+
438
+ const file = new File(["content"], "doc.txt", { type: "text/plain" });
439
+
440
+ const result = await alepha.inject(MixedFieldsApp).upload.run({
441
+ body: {
442
+ name: "Test Document",
443
+ description: "A test file upload",
444
+ file,
445
+ },
446
+ });
447
+
448
+ expect(result).toBe("Test Document: A test file upload (7 bytes)");
449
+ });
450
+
451
+ test("should count only file fields toward file count limit", async ({
452
+ expect,
453
+ }) => {
454
+ class TextAndFilesApp {
455
+ upload = $action({
456
+ schema: {
457
+ body: t.object({
458
+ field1: t.text(),
459
+ field2: t.text(),
460
+ field3: t.text(),
461
+ file1: t.file(),
462
+ file2: t.file(),
463
+ }),
464
+ response: t.text(),
465
+ },
466
+ handler: () => "success",
467
+ });
468
+ }
469
+
470
+ // Set file count limit to 2 - should only count file fields, not text
471
+ const alepha = Alepha.create({
472
+ env: { SERVER_MULTIPART_FILE_COUNT: "2" },
473
+ })
474
+ .with(AlephaServerMultipart)
475
+ .with(TextAndFilesApp);
476
+ await alepha.start();
477
+
478
+ const file1 = new File(["content1"], "file1.txt", { type: "text/plain" });
479
+ const file2 = new File(["content2"], "file2.txt", { type: "text/plain" });
480
+
481
+ // Should succeed - only 2 files even though 5 total fields
482
+ const result = await alepha.inject(TextAndFilesApp).upload.run({
483
+ body: {
484
+ field1: "text1",
485
+ field2: "text2",
486
+ field3: "text3",
487
+ file1,
488
+ file2,
489
+ },
490
+ });
491
+
492
+ expect(result).toBe("success");
493
+ });
494
+
495
+ test("should handle binary file uploads with size limits", async ({
496
+ expect,
497
+ }) => {
498
+ class BinaryFileApp {
499
+ upload = $action({
500
+ schema: {
501
+ body: t.object({
502
+ file: t.file(),
503
+ }),
504
+ response: t.text(),
505
+ },
506
+ handler: ({ body }) =>
507
+ `Binary file: ${body.file.name}, ${body.file.size} bytes, ${body.file.type}`,
508
+ });
509
+ }
510
+
511
+ const alepha = Alepha.create({
512
+ env: { SERVER_MULTIPART_FILE_LIMIT: "1000" },
513
+ })
514
+ .with(AlephaServerMultipart)
515
+ .with(BinaryFileApp);
516
+ await alepha.start();
517
+
518
+ // Create binary content
519
+ const binaryContent = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a]);
520
+ const file = new File([binaryContent], "image.png", { type: "image/png" });
521
+
522
+ const result = await alepha.inject(BinaryFileApp).upload.run({
523
+ body: { file },
524
+ });
525
+
526
+ expect(result).toBe("Binary file: image.png, 6 bytes, image/png");
527
+ });
528
+ });
@@ -0,0 +1,87 @@
1
+ import { Alepha, t } from "alepha";
2
+ import { $action, ServerProvider } from "alepha/server";
3
+ import { describe, expect, it } from "vitest";
4
+ import { $proxy } from "../index.ts";
5
+
6
+ describe("$proxy", () => {
7
+ it("should proxy requests to target server with headers and query params", async () => {
8
+ class App {
9
+ hello = $action({
10
+ schema: {
11
+ headers: t.object({
12
+ prefix: t.optional(t.text()),
13
+ }),
14
+ query: t.object({
15
+ transform: t.optional(t.enum(["uppercase"])),
16
+ }),
17
+ body: t.object({
18
+ name: t.text(),
19
+ }),
20
+ response: t.object({
21
+ message: t.text(),
22
+ }),
23
+ },
24
+ handler: ({ body, query, headers, reply }) => {
25
+ let name = body.name;
26
+ if (query.transform === "uppercase") {
27
+ name = name.toUpperCase();
28
+ }
29
+ if (headers.prefix) {
30
+ name = `${headers.prefix}${name}`;
31
+ }
32
+ reply.headers["x-hello"] = "world";
33
+ return {
34
+ message: `Hello ${name}!`,
35
+ };
36
+ },
37
+ });
38
+ }
39
+
40
+ const alephaApi = Alepha.create({
41
+ env: {
42
+ APP_NAME: "API",
43
+ },
44
+ }).with(App);
45
+
46
+ class AppProxy {
47
+ proxy = $proxy({
48
+ path: "/api/*",
49
+ target: () => alephaApi.inject(ServerProvider).hostname,
50
+ });
51
+ }
52
+
53
+ const alephaProxy = Alepha.create({
54
+ env: {
55
+ APP_NAME: "PROXY",
56
+ },
57
+ }).with(AppProxy);
58
+
59
+ await alephaApi.start();
60
+ await alephaProxy.start();
61
+
62
+ for (let i = 0; i < 10; i++) {
63
+ const hostname = alephaProxy.inject(ServerProvider).hostname;
64
+
65
+ const response = await fetch(
66
+ `${hostname}/api/hello?transform=uppercase`,
67
+ {
68
+ method: "POST",
69
+ body: JSON.stringify({ name: "Jack" }),
70
+ headers: {
71
+ "Content-Type": "application/json",
72
+ prefix: "Mr.",
73
+ },
74
+ },
75
+ );
76
+
77
+ expect(response.status).toBe(200);
78
+
79
+ const json = await response.json();
80
+
81
+ expect(response.headers.get("x-hello")).toBe("world");
82
+ expect(json).toEqual({
83
+ message: "Hello Mr.JACK!",
84
+ });
85
+ }
86
+ });
87
+ });