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,301 @@
1
+ import { Alepha } from "alepha";
2
+ import {
3
+ AlephaSecurity,
4
+ CryptoProvider,
5
+ InvalidCredentialsError,
6
+ } from "alepha/security";
7
+ import { describe, it } from "vitest";
8
+ import {
9
+ AlephaApiUsers,
10
+ SessionService,
11
+ UserRealmProvider,
12
+ UserService,
13
+ } from "../index.ts";
14
+
15
+ const setup = async (options?: { usernameEnabled?: boolean }) => {
16
+ const alepha = Alepha.create({
17
+ env: { LOG_LEVEL: "error" },
18
+ });
19
+
20
+ alepha.with(AlephaSecurity);
21
+ alepha.with(AlephaApiUsers);
22
+
23
+ await alepha.start();
24
+
25
+ const sessionService = alepha.inject(SessionService);
26
+
27
+ // Configure realm settings if provided
28
+ if (options?.usernameEnabled) {
29
+ const userRealmProvider = alepha.inject(UserRealmProvider);
30
+ userRealmProvider.register("default", {
31
+ settings: {
32
+ usernameEnabled: true,
33
+ } as never,
34
+ });
35
+ }
36
+
37
+ return {
38
+ alepha,
39
+ sessionService,
40
+ userService: alepha.inject(UserService),
41
+ cryptoProvider: alepha.inject(CryptoProvider),
42
+ identities: sessionService.identities(),
43
+ };
44
+ };
45
+
46
+ describe("alepha/api/users - SessionService.login", () => {
47
+ it("should login successfully with valid credentials", async ({ expect }) => {
48
+ const { sessionService, userService, cryptoProvider, identities } =
49
+ await setup();
50
+
51
+ // Create a test user
52
+ const user = await userService.users().create({
53
+ username: "loginsuccessuser",
54
+ email: "login-success@example.com",
55
+ roles: ["user"],
56
+ });
57
+
58
+ // Create identity with password
59
+ const password = "securePassword123!";
60
+ const hashedPassword = await cryptoProvider.hashPassword(password);
61
+
62
+ await identities.create({
63
+ provider: "local",
64
+ providerUserId: "login-success@example.com",
65
+ userId: user.id,
66
+ password: hashedPassword,
67
+ });
68
+
69
+ // Test login
70
+ const result = await sessionService.login(
71
+ "local",
72
+ "login-success@example.com",
73
+ password,
74
+ );
75
+
76
+ expect(result?.id).toBe(user.id);
77
+ expect(result?.email).toBe("login-success@example.com");
78
+ });
79
+
80
+ it("should throw InvalidCredentialsError when identity not found", async ({
81
+ expect,
82
+ }) => {
83
+ const { sessionService } = await setup();
84
+
85
+ await expect(
86
+ sessionService.login("local", "nonexistent@example.com", "password"),
87
+ ).rejects.toThrowError(InvalidCredentialsError);
88
+ });
89
+
90
+ it("should throw InvalidCredentialsError when password is invalid", async ({
91
+ expect,
92
+ }) => {
93
+ const { sessionService, userService, cryptoProvider, identities } =
94
+ await setup();
95
+
96
+ // Create a test user
97
+ const user = await userService.users().create({
98
+ username: "invalidpassworduser",
99
+ email: "invalid-password@example.com",
100
+ roles: ["user"],
101
+ });
102
+
103
+ // Create identity with password
104
+ const hashedPassword = await cryptoProvider.hashPassword("correctPassword");
105
+
106
+ await identities.create({
107
+ provider: "local",
108
+ providerUserId: "invalid-password@example.com",
109
+ userId: user.id,
110
+ password: hashedPassword,
111
+ });
112
+
113
+ // Test login with wrong password
114
+ await expect(
115
+ sessionService.login(
116
+ "local",
117
+ "invalid-password@example.com",
118
+ "wrongPassword",
119
+ ),
120
+ ).rejects.toThrowError(InvalidCredentialsError);
121
+ });
122
+
123
+ it("should throw InvalidCredentialsError when identity has no password configured", async ({
124
+ expect,
125
+ }) => {
126
+ const { sessionService, userService, identities } = await setup();
127
+
128
+ // Create a test user
129
+ const user = await userService.users().create({
130
+ username: "nopassworduser",
131
+ email: "no-password@example.com",
132
+ roles: ["user"],
133
+ });
134
+
135
+ // Create identity without password
136
+ await identities.create({
137
+ provider: "local",
138
+ providerUserId: "no-password@example.com",
139
+ userId: user.id,
140
+ providerData: {}, // No password
141
+ });
142
+
143
+ await expect(
144
+ sessionService.login("local", "no-password@example.com", "anyPassword"),
145
+ ).rejects.toThrowError(InvalidCredentialsError);
146
+ });
147
+
148
+ it("should throw InvalidCredentialsError when user is deleted after identity creation", async ({
149
+ expect,
150
+ }) => {
151
+ const { sessionService, userService, cryptoProvider, identities } =
152
+ await setup();
153
+
154
+ // Create a user, then delete them to simulate orphan identity
155
+ const user = await userService.users().create({
156
+ username: "orphanidentityuser",
157
+ email: "orphan-identity@example.com",
158
+ roles: ["user"],
159
+ });
160
+
161
+ const hashedPassword = await cryptoProvider.hashPassword("password123");
162
+
163
+ await identities.create({
164
+ provider: "local",
165
+ providerUserId: "orphan-identity@example.com",
166
+ userId: user.id,
167
+ password: hashedPassword,
168
+ });
169
+
170
+ // Delete the user to create orphan identity scenario
171
+ await userService.users().deleteById(user.id);
172
+
173
+ await expect(
174
+ sessionService.login(
175
+ "local",
176
+ "orphan-identity@example.com",
177
+ "password123",
178
+ ),
179
+ ).rejects.toThrowError(InvalidCredentialsError);
180
+ });
181
+
182
+ it("should throw InvalidCredentialsError with same message for all failure types", async ({
183
+ expect,
184
+ }) => {
185
+ const { sessionService, userService, cryptoProvider, identities } =
186
+ await setup();
187
+
188
+ // Setup for invalid password test
189
+ const user = await userService.users().create({
190
+ username: "sameerroruser",
191
+ email: "same-error@example.com",
192
+ roles: ["user"],
193
+ });
194
+ const hashedPassword = await cryptoProvider.hashPassword("correctPass");
195
+ await identities.create({
196
+ provider: "local",
197
+ providerUserId: "same-error@example.com",
198
+ userId: user.id,
199
+ password: hashedPassword,
200
+ });
201
+
202
+ // Test identity not found
203
+ try {
204
+ await sessionService.login("local", "notfound@example.com", "password");
205
+ } catch (error) {
206
+ expect(error).toBeInstanceOf(InvalidCredentialsError);
207
+ expect((error as Error).message).toBe("Invalid credentials");
208
+ }
209
+
210
+ // Test invalid password
211
+ try {
212
+ await sessionService.login(
213
+ "local",
214
+ "same-error@example.com",
215
+ "wrongPassword",
216
+ );
217
+ } catch (error) {
218
+ expect(error).toBeInstanceOf(InvalidCredentialsError);
219
+ expect((error as Error).message).toBe("Invalid credentials");
220
+ }
221
+ });
222
+
223
+ it("should include random delay to prevent timing attacks", async ({
224
+ expect,
225
+ }) => {
226
+ const { sessionService } = await setup();
227
+
228
+ const start = Date.now();
229
+
230
+ try {
231
+ await sessionService.login(
232
+ "local",
233
+ "timing-attack@example.com",
234
+ "password",
235
+ );
236
+ } catch {
237
+ // Expected to fail
238
+ }
239
+
240
+ const elapsed = Date.now() - start;
241
+
242
+ // Should take at least 50ms due to random delay
243
+ expect(elapsed).toBeGreaterThanOrEqual(50);
244
+ });
245
+
246
+ it("should handle different providers correctly", async ({ expect }) => {
247
+ const { sessionService, userService, cryptoProvider, identities } =
248
+ await setup({ usernameEnabled: true });
249
+
250
+ const user = await userService.users().create({
251
+ username: "multiprovideruser",
252
+ email: "multi-provider@example.com",
253
+ roles: ["user"],
254
+ });
255
+
256
+ // Create identity for 'custom' provider
257
+ const hashedPassword = await cryptoProvider.hashPassword("customPass");
258
+ await identities.create({
259
+ provider: "custom",
260
+ userId: user.id,
261
+ password: hashedPassword,
262
+ });
263
+
264
+ // Login with correct provider
265
+ const result = await sessionService.login(
266
+ "custom",
267
+ "multiprovideruser",
268
+ "customPass",
269
+ );
270
+ expect(result?.id).toBe(user.id);
271
+
272
+ // Should fail with wrong provider
273
+ await expect(
274
+ sessionService.login("local", "custom-user-id", "customPass"),
275
+ ).rejects.toThrowError(InvalidCredentialsError);
276
+ });
277
+
278
+ it("should handle empty password correctly", async ({ expect }) => {
279
+ const { sessionService, userService, cryptoProvider, identities } =
280
+ await setup();
281
+
282
+ const user = await userService.users().create({
283
+ username: "emptypassworduser",
284
+ email: "empty-password@example.com",
285
+ roles: ["user"],
286
+ });
287
+
288
+ const hashedPassword = await cryptoProvider.hashPassword("realPassword");
289
+ await identities.create({
290
+ provider: "local",
291
+ providerUserId: "empty-password@example.com",
292
+ userId: user.id,
293
+ password: hashedPassword,
294
+ });
295
+
296
+ // Empty password should fail
297
+ await expect(
298
+ sessionService.login("local", "empty-password@example.com", ""),
299
+ ).rejects.toThrowError(InvalidCredentialsError);
300
+ });
301
+ });
@@ -1,5 +1,6 @@
1
1
  import { randomInt } from "node:crypto";
2
2
  import { $inject, Alepha } from "alepha";
3
+ import { AuditService } from "alepha/api/audits";
3
4
  import type { FileController } from "alepha/api/files";
4
5
  import { DateTimeProvider } from "alepha/datetime";
5
6
  import { FileSystemProvider } from "alepha/file";
@@ -23,6 +24,7 @@ export class SessionService {
23
24
  protected readonly log = $logger();
24
25
  protected readonly userRealmProvider = $inject(UserRealmProvider);
25
26
  protected readonly fileController = $client<FileController>();
27
+ protected readonly auditService = $inject(AuditService);
26
28
 
27
29
  public users(userRealmName?: string) {
28
30
  return this.userRealmProvider.userRepository(userRealmName);
@@ -79,6 +81,13 @@ export class SessionService {
79
81
  username,
80
82
  realm: name,
81
83
  });
84
+
85
+ await this.auditService.recordAuth("login_failed", {
86
+ userRealm: name,
87
+ description: "Invalid login identifier format",
88
+ metadata: { provider, username },
89
+ });
90
+
82
91
  throw new InvalidCredentialsError();
83
92
  }
84
93
 
@@ -89,6 +98,13 @@ export class SessionService {
89
98
  username,
90
99
  realm: name,
91
100
  });
101
+
102
+ await this.auditService.recordAuth("login_failed", {
103
+ userRealm: name,
104
+ description: "User not found",
105
+ metadata: { provider, username },
106
+ });
107
+
92
108
  throw new InvalidCredentialsError();
93
109
  }
94
110
 
@@ -121,9 +137,26 @@ export class SessionService {
121
137
  username,
122
138
  realm: name,
123
139
  });
140
+
141
+ await this.auditService.recordAuth("login_failed", {
142
+ userRealm: name,
143
+ resourceId: user.id,
144
+ description: "Invalid password",
145
+ metadata: { provider, username },
146
+ });
147
+
124
148
  throw new InvalidCredentialsError();
125
149
  }
126
150
 
151
+ await this.auditService.recordAuth("login", {
152
+ userId: user.id,
153
+ userEmail: user.email ?? undefined,
154
+ userRealm: name,
155
+ resourceId: user.id,
156
+ description: `User logged in via ${provider}`,
157
+ metadata: { provider, username },
158
+ });
159
+
127
160
  return user;
128
161
  } catch (error) {
129
162
  if (error instanceof InvalidCredentialsError) {
@@ -204,6 +237,16 @@ export class SessionService {
204
237
  userId: session.userId,
205
238
  });
206
239
 
240
+ const { name } = this.userRealmProvider.getRealm(userRealmName);
241
+
242
+ await this.auditService.recordAuth("token_refresh", {
243
+ userId: user.id,
244
+ userEmail: user.email ?? undefined,
245
+ userRealm: name,
246
+ sessionId: session.id,
247
+ description: "Session token refreshed",
248
+ });
249
+
207
250
  return {
208
251
  user,
209
252
  expiresIn: expiresAt.unix() - now.unix(),
@@ -213,10 +256,29 @@ export class SessionService {
213
256
 
214
257
  public async deleteSession(refreshToken: string, userRealmName?: string) {
215
258
  this.log.trace("Deleting session");
259
+
260
+ // Get session info before deletion for audit
261
+ const session = await this.sessions(userRealmName)
262
+ .findOne({
263
+ where: { refreshToken: { eq: refreshToken } },
264
+ })
265
+ .catch(() => undefined);
266
+
216
267
  await this.sessions(userRealmName).deleteOne({
217
268
  refreshToken,
218
269
  });
219
270
  this.log.debug("Session deleted");
271
+
272
+ if (session) {
273
+ const { name } = this.userRealmProvider.getRealm(userRealmName);
274
+
275
+ await this.auditService.recordAuth("logout", {
276
+ userId: session.userId,
277
+ userRealm: name,
278
+ sessionId: session.id,
279
+ description: "User logged out",
280
+ });
281
+ }
220
282
  }
221
283
 
222
284
  public async link(
@@ -250,7 +312,19 @@ export class SessionService {
250
312
  identityId: identity.id,
251
313
  userId: identity.userId,
252
314
  });
253
- return users.findById(identity.userId);
315
+
316
+ const user = await users.findById(identity.userId);
317
+
318
+ await this.auditService.recordAuth("login", {
319
+ userId: user.id,
320
+ userEmail: user.email ?? undefined,
321
+ userRealm: realm.name,
322
+ resourceId: user.id,
323
+ description: `User logged in via OAuth2 (${provider})`,
324
+ metadata: { provider, providerUserId: profile.sub },
325
+ });
326
+
327
+ return user;
254
328
  }
255
329
 
256
330
  if (!profile.email) {
@@ -284,6 +358,16 @@ export class SessionService {
284
358
  providerUserId: profile.sub,
285
359
  userId: existing.id,
286
360
  });
361
+
362
+ await this.auditService.recordAuth("login", {
363
+ userId: existing.id,
364
+ userEmail: existing.email ?? undefined,
365
+ userRealm: realm.name,
366
+ resourceId: existing.id,
367
+ description: `OAuth2 identity linked to existing user (${provider})`,
368
+ metadata: { provider, providerUserId: profile.sub, linked: true },
369
+ });
370
+
287
371
  return existing;
288
372
  }
289
373
 
@@ -338,6 +422,31 @@ export class SessionService {
338
422
  username: user.username,
339
423
  });
340
424
 
425
+ // Audit: user created via OAuth
426
+ await this.auditService.recordUser("create", {
427
+ userId: user.id,
428
+ userEmail: user.email ?? undefined,
429
+ userRealm: realm.name,
430
+ resourceId: user.id,
431
+ description: `User created via OAuth2 (${provider})`,
432
+ metadata: {
433
+ provider,
434
+ providerUserId: profile.sub,
435
+ username: user.username,
436
+ email: user.email,
437
+ },
438
+ });
439
+
440
+ // Audit: login event
441
+ await this.auditService.recordAuth("login", {
442
+ userId: user.id,
443
+ userEmail: user.email ?? undefined,
444
+ userRealm: realm.name,
445
+ resourceId: user.id,
446
+ description: `First login via OAuth2 (${provider})`,
447
+ metadata: { provider, providerUserId: profile.sub, firstLogin: true },
448
+ });
449
+
341
450
  return user;
342
451
  }
343
452
  }
@@ -1,4 +1,5 @@
1
1
  import { $inject } from "alepha";
2
+ import { AuditService } from "alepha/api/audits";
2
3
  import type { VerificationController } from "alepha/api/verifications";
3
4
  import { $logger } from "alepha/logger";
4
5
  import { type Page, parseQueryString } from "alepha/orm";
@@ -16,6 +17,7 @@ export class UserService {
16
17
  protected readonly verificationController = $client<VerificationController>();
17
18
  protected readonly userNotifications = $inject(UserNotifications);
18
19
  protected readonly userRealmProvider = $inject(UserRealmProvider);
20
+ protected readonly auditService = $inject(AuditService);
19
21
 
20
22
  public users(userRealmName?: string) {
21
23
  return this.userRealmProvider.userRepository(userRealmName);
@@ -153,6 +155,17 @@ export class UserService {
153
155
  });
154
156
 
155
157
  this.log.info("Email verified", { email, userId: user.id, type });
158
+
159
+ const realm = this.userRealmProvider.getRealm(userRealmName);
160
+
161
+ await this.auditService.recordUser("update", {
162
+ userId: user.id,
163
+ userEmail: email,
164
+ userRealm: realm.name,
165
+ resourceId: user.id,
166
+ description: "Email verified",
167
+ metadata: { email, verificationType: type },
168
+ });
156
169
  }
157
170
 
158
171
  /**
@@ -301,6 +314,17 @@ export class UserService {
301
314
  email: user.email,
302
315
  });
303
316
 
317
+ await this.auditService.recordUser("create", {
318
+ userRealm: realm.name,
319
+ resourceId: user.id,
320
+ description: "User created",
321
+ metadata: {
322
+ username: user.username,
323
+ email: user.email,
324
+ roles: user.roles,
325
+ },
326
+ });
327
+
304
328
  return user;
305
329
  }
306
330
 
@@ -313,10 +337,38 @@ export class UserService {
313
337
  userRealmName?: string,
314
338
  ): Promise<UserEntity> {
315
339
  this.log.trace("Updating user", { id, userRealmName });
316
- await this.getUserById(id, userRealmName);
340
+ const before = await this.getUserById(id, userRealmName);
317
341
 
318
342
  const user = await this.users(userRealmName).updateById(id, data);
319
343
  this.log.debug("User updated", { userId: id });
344
+
345
+ const realm = this.userRealmProvider.getRealm(userRealmName);
346
+
347
+ // Build changes object showing what was updated
348
+ const changes: Record<string, { from: unknown; to: unknown }> = {};
349
+ for (const key of Object.keys(data) as (keyof UpdateUser)[]) {
350
+ if (data[key] !== undefined && before[key] !== data[key]) {
351
+ changes[key] = { from: before[key], to: data[key] };
352
+ }
353
+ }
354
+
355
+ // Detect role changes for special handling
356
+ const isRoleChange =
357
+ data.roles !== undefined &&
358
+ JSON.stringify(before.roles) !== JSON.stringify(data.roles);
359
+
360
+ await this.auditService.recordUser(
361
+ isRoleChange ? "role_change" : "update",
362
+ {
363
+ userRealm: realm.name,
364
+ resourceId: user.id,
365
+ description: isRoleChange
366
+ ? "User roles changed"
367
+ : `User updated: ${Object.keys(changes).join(", ")}`,
368
+ metadata: { changes },
369
+ },
370
+ );
371
+
320
372
  return user;
321
373
  }
322
374
 
@@ -325,9 +377,22 @@ export class UserService {
325
377
  */
326
378
  public async deleteUser(id: string, userRealmName?: string): Promise<void> {
327
379
  this.log.trace("Deleting user", { id, userRealmName });
328
- await this.getUserById(id, userRealmName);
380
+ const user = await this.getUserById(id, userRealmName);
329
381
 
330
382
  await this.users(userRealmName).deleteById(id);
331
383
  this.log.info("User deleted", { userId: id });
384
+
385
+ const realm = this.userRealmProvider.getRealm(userRealmName);
386
+
387
+ await this.auditService.recordUser("delete", {
388
+ userRealm: realm.name,
389
+ resourceId: id,
390
+ severity: "warning",
391
+ description: "User deleted",
392
+ metadata: {
393
+ username: user.username,
394
+ email: user.email,
395
+ },
396
+ });
332
397
  }
333
398
  }