alepha 0.14.2 → 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 (361) hide show
  1. package/dist/api/audits/index.browser.js +5 -5
  2. package/dist/api/audits/index.browser.js.map +1 -1
  3. package/dist/api/audits/index.d.ts +784 -784
  4. package/dist/api/audits/index.d.ts.map +1 -1
  5. package/dist/api/audits/index.js +13 -13
  6. package/dist/api/audits/index.js.map +1 -1
  7. package/dist/api/files/index.browser.js +5 -5
  8. package/dist/api/files/index.browser.js.map +1 -1
  9. package/dist/api/files/index.d.ts +57 -57
  10. package/dist/api/files/index.d.ts.map +1 -1
  11. package/dist/api/files/index.js +71 -71
  12. package/dist/api/files/index.js.map +1 -1
  13. package/dist/api/jobs/index.browser.js +5 -5
  14. package/dist/api/jobs/index.browser.js.map +1 -1
  15. package/dist/api/jobs/index.d.ts +165 -165
  16. package/dist/api/jobs/index.d.ts.map +1 -1
  17. package/dist/api/jobs/index.js +10 -10
  18. package/dist/api/jobs/index.js.map +1 -1
  19. package/dist/api/notifications/index.browser.js +10 -10
  20. package/dist/api/notifications/index.browser.js.map +1 -1
  21. package/dist/api/notifications/index.d.ts +583 -171
  22. package/dist/api/notifications/index.d.ts.map +1 -1
  23. package/dist/api/notifications/index.js +12 -12
  24. package/dist/api/notifications/index.js.map +1 -1
  25. package/dist/api/parameters/index.browser.js +163 -10
  26. package/dist/api/parameters/index.browser.js.map +1 -1
  27. package/dist/api/parameters/index.d.ts +281 -276
  28. package/dist/api/parameters/index.d.ts.map +1 -1
  29. package/dist/api/parameters/index.js +196 -91
  30. package/dist/api/parameters/index.js.map +1 -1
  31. package/dist/api/users/index.browser.js +19 -19
  32. package/dist/api/users/index.browser.js.map +1 -1
  33. package/dist/api/users/index.d.ts +1137 -1123
  34. package/dist/api/users/index.d.ts.map +1 -1
  35. package/dist/api/users/index.js +827 -596
  36. package/dist/api/users/index.js.map +1 -1
  37. package/dist/api/verifications/index.browser.js +6 -6
  38. package/dist/api/verifications/index.browser.js.map +1 -1
  39. package/dist/api/verifications/index.d.ts +13 -13
  40. package/dist/api/verifications/index.d.ts.map +1 -1
  41. package/dist/api/verifications/index.js +6 -6
  42. package/dist/api/verifications/index.js.map +1 -1
  43. package/dist/bin/index.d.ts +1 -2
  44. package/dist/bin/index.js +0 -1
  45. package/dist/bin/index.js.map +1 -1
  46. package/dist/cli/index.d.ts +137 -112
  47. package/dist/cli/index.d.ts.map +1 -1
  48. package/dist/cli/index.js +371 -259
  49. package/dist/cli/index.js.map +1 -1
  50. package/dist/command/index.d.ts +45 -5
  51. package/dist/command/index.d.ts.map +1 -1
  52. package/dist/command/index.js +97 -17
  53. package/dist/command/index.js.map +1 -1
  54. package/dist/core/index.browser.js +14 -18
  55. package/dist/core/index.browser.js.map +1 -1
  56. package/dist/core/index.d.ts +29 -0
  57. package/dist/core/index.d.ts.map +1 -1
  58. package/dist/core/index.js +14 -18
  59. package/dist/core/index.js.map +1 -1
  60. package/dist/core/index.native.js +14 -18
  61. package/dist/core/index.native.js.map +1 -1
  62. package/dist/fake/index.js +195 -168
  63. package/dist/fake/index.js.map +1 -1
  64. package/dist/file/index.d.ts +8 -0
  65. package/dist/file/index.d.ts.map +1 -1
  66. package/dist/file/index.js +3 -0
  67. package/dist/file/index.js.map +1 -1
  68. package/dist/mcp/index.d.ts.map +1 -1
  69. package/dist/orm/index.d.ts +32 -32
  70. package/dist/orm/index.d.ts.map +1 -1
  71. package/dist/orm/index.js +12 -12
  72. package/dist/orm/index.js.map +1 -1
  73. package/dist/security/index.d.ts +1 -1
  74. package/dist/security/index.d.ts.map +1 -1
  75. package/dist/security/index.js +1 -1
  76. package/dist/security/index.js.map +1 -1
  77. package/dist/server/auth/index.d.ts +171 -155
  78. package/dist/server/auth/index.d.ts.map +1 -1
  79. package/dist/server/auth/index.js +0 -1
  80. package/dist/server/auth/index.js.map +1 -1
  81. package/dist/server/compress/index.d.ts.map +1 -1
  82. package/dist/server/compress/index.js +2 -0
  83. package/dist/server/compress/index.js.map +1 -1
  84. package/dist/server/core/index.d.ts.map +1 -1
  85. package/dist/server/core/index.js +1 -1
  86. package/dist/server/core/index.js.map +1 -1
  87. package/dist/server/links/index.browser.js +22 -6
  88. package/dist/server/links/index.browser.js.map +1 -1
  89. package/dist/server/links/index.d.ts +46 -44
  90. package/dist/server/links/index.d.ts.map +1 -1
  91. package/dist/server/links/index.js +24 -41
  92. package/dist/server/links/index.js.map +1 -1
  93. package/dist/server/security/index.d.ts +9 -9
  94. package/dist/server/swagger/index.d.ts +2 -1
  95. package/dist/server/swagger/index.d.ts.map +1 -1
  96. package/dist/server/swagger/index.js +8 -3
  97. package/dist/server/swagger/index.js.map +1 -1
  98. package/dist/vite/index.d.ts.map +1 -1
  99. package/dist/vite/index.js +12 -4
  100. package/dist/vite/index.js.map +1 -1
  101. package/dist/websocket/index.d.ts +7 -7
  102. package/package.json +7 -7
  103. package/src/api/audits/controllers/{AuditController.ts → AdminAuditController.ts} +5 -6
  104. package/src/api/audits/entities/audits.ts +5 -5
  105. package/src/api/audits/index.browser.ts +1 -1
  106. package/src/api/audits/index.ts +3 -3
  107. package/src/api/audits/primitives/$audit.spec.ts +276 -0
  108. package/src/api/audits/services/AuditService.spec.ts +495 -0
  109. package/src/api/files/__tests__/$bucket.spec.ts +91 -0
  110. package/src/api/files/controllers/AdminFileStatsController.spec.ts +166 -0
  111. package/src/api/files/controllers/{StorageStatsController.ts → AdminFileStatsController.ts} +2 -2
  112. package/src/api/files/controllers/FileController.spec.ts +558 -0
  113. package/src/api/files/controllers/FileController.ts +4 -5
  114. package/src/api/files/entities/files.ts +5 -5
  115. package/src/api/files/index.browser.ts +1 -1
  116. package/src/api/files/index.ts +4 -4
  117. package/src/api/files/jobs/FileJobs.spec.ts +52 -0
  118. package/src/api/files/services/FileService.spec.ts +109 -0
  119. package/src/api/jobs/__tests__/JobController.spec.ts +343 -0
  120. package/src/api/jobs/controllers/{JobController.ts → AdminJobController.ts} +2 -2
  121. package/src/api/jobs/entities/jobExecutions.ts +5 -5
  122. package/src/api/jobs/index.ts +3 -3
  123. package/src/api/jobs/primitives/$job.spec.ts +476 -0
  124. package/src/api/notifications/controllers/{NotificationController.ts → AdminNotificationController.ts} +4 -5
  125. package/src/api/notifications/entities/notifications.ts +5 -5
  126. package/src/api/notifications/index.browser.ts +1 -1
  127. package/src/api/notifications/index.ts +4 -4
  128. package/src/api/parameters/controllers/{ConfigController.ts → AdminConfigController.ts} +46 -107
  129. package/src/api/parameters/entities/parameters.ts +7 -17
  130. package/src/api/parameters/index.ts +3 -3
  131. package/src/api/parameters/primitives/$config.spec.ts +356 -0
  132. package/src/api/parameters/schemas/activateConfigBodySchema.ts +12 -0
  133. package/src/api/parameters/schemas/checkScheduledResponseSchema.ts +8 -0
  134. package/src/api/parameters/schemas/configCurrentResponseSchema.ts +13 -0
  135. package/src/api/parameters/schemas/configHistoryResponseSchema.ts +9 -0
  136. package/src/api/parameters/schemas/configNameParamSchema.ts +10 -0
  137. package/src/api/parameters/schemas/configNamesResponseSchema.ts +8 -0
  138. package/src/api/parameters/schemas/configTreeNodeSchema.ts +13 -0
  139. package/src/api/parameters/schemas/configVersionParamSchema.ts +9 -0
  140. package/src/api/parameters/schemas/configVersionResponseSchema.ts +9 -0
  141. package/src/api/parameters/schemas/configsByStatusResponseSchema.ts +9 -0
  142. package/src/api/parameters/schemas/createConfigVersionBodySchema.ts +24 -0
  143. package/src/api/parameters/schemas/index.ts +15 -0
  144. package/src/api/parameters/schemas/parameterResponseSchema.ts +26 -0
  145. package/src/api/parameters/schemas/parameterStatusSchema.ts +13 -0
  146. package/src/api/parameters/schemas/rollbackConfigBodySchema.ts +15 -0
  147. package/src/api/parameters/schemas/statusParamSchema.ts +9 -0
  148. package/src/api/users/__tests__/EmailVerification.spec.ts +369 -0
  149. package/src/api/users/__tests__/PasswordReset.spec.ts +550 -0
  150. package/src/api/users/controllers/AdminIdentityController.spec.ts +365 -0
  151. package/src/api/users/controllers/{IdentityController.ts → AdminIdentityController.ts} +3 -4
  152. package/src/api/users/controllers/AdminSessionController.spec.ts +274 -0
  153. package/src/api/users/controllers/{SessionController.ts → AdminSessionController.ts} +3 -4
  154. package/src/api/users/controllers/AdminUserController.spec.ts +372 -0
  155. package/src/api/users/controllers/AdminUserController.ts +116 -0
  156. package/src/api/users/controllers/UserController.ts +4 -107
  157. package/src/api/users/controllers/UserRealmController.ts +3 -0
  158. package/src/api/users/entities/identities.ts +6 -6
  159. package/src/api/users/entities/sessions.ts +6 -6
  160. package/src/api/users/entities/users.ts +9 -9
  161. package/src/api/users/index.ts +9 -6
  162. package/src/api/users/primitives/$userRealm.ts +13 -8
  163. package/src/api/users/services/CredentialService.spec.ts +509 -0
  164. package/src/api/users/services/CredentialService.ts +46 -0
  165. package/src/api/users/services/IdentityService.ts +15 -0
  166. package/src/api/users/services/RegistrationService.spec.ts +630 -0
  167. package/src/api/users/services/RegistrationService.ts +18 -0
  168. package/src/api/users/services/SessionService.spec.ts +301 -0
  169. package/src/api/users/services/SessionService.ts +110 -1
  170. package/src/api/users/services/UserService.ts +67 -2
  171. package/src/api/verifications/__tests__/CodeVerification.spec.ts +318 -0
  172. package/src/api/verifications/__tests__/LinkVerification.spec.ts +279 -0
  173. package/src/api/verifications/entities/verifications.ts +6 -6
  174. package/src/api/verifications/jobs/VerificationJobs.spec.ts +50 -0
  175. package/src/batch/__tests__/startup-buffering.spec.ts +458 -0
  176. package/src/batch/primitives/$batch.spec.ts +766 -0
  177. package/src/batch/providers/BatchProvider.spec.ts +786 -0
  178. package/src/bin/index.ts +0 -1
  179. package/src/bucket/__tests__/shared.ts +194 -0
  180. package/src/bucket/primitives/$bucket.spec.ts +104 -0
  181. package/src/bucket/providers/FileStorageProvider.spec.ts +13 -0
  182. package/src/bucket/providers/LocalFileStorageProvider.spec.ts +77 -0
  183. package/src/bucket/providers/MemoryFileStorageProvider.spec.ts +82 -0
  184. package/src/cache/core/__tests__/shared.ts +377 -0
  185. package/src/cache/core/primitives/$cache.spec.ts +111 -0
  186. package/src/cache/redis/__tests__/cache-redis.spec.ts +70 -0
  187. package/src/cli/apps/AlephaCli.ts +25 -4
  188. package/src/cli/commands/dev.ts +19 -7
  189. package/src/cli/commands/gen/changelog.spec.ts +315 -0
  190. package/src/cli/commands/{changelog.ts → gen/changelog.ts} +9 -9
  191. package/src/cli/commands/gen/openapi.ts +71 -0
  192. package/src/cli/commands/gen.ts +18 -0
  193. package/src/cli/commands/init.ts +2 -0
  194. package/src/cli/commands/root.ts +12 -3
  195. package/src/cli/commands/typecheck.ts +5 -0
  196. package/src/cli/index.ts +2 -1
  197. package/src/cli/services/AlephaCliUtils.ts +71 -32
  198. package/src/cli/services/GitMessageParser.ts +1 -1
  199. package/src/command/helpers/Asker.spec.ts +127 -0
  200. package/src/command/helpers/Runner.spec.ts +126 -0
  201. package/src/command/primitives/$command.spec.ts +1588 -0
  202. package/src/command/providers/CliProvider.ts +74 -24
  203. package/src/core/Alepha.ts +45 -0
  204. package/src/core/__tests__/Alepha-emit.spec.ts +22 -0
  205. package/src/core/__tests__/Alepha-graph.spec.ts +93 -0
  206. package/src/core/__tests__/Alepha-has.spec.ts +41 -0
  207. package/src/core/__tests__/Alepha-inject.spec.ts +93 -0
  208. package/src/core/__tests__/Alepha-register.spec.ts +81 -0
  209. package/src/core/__tests__/Alepha-start.spec.ts +176 -0
  210. package/src/core/__tests__/Alepha-with.spec.ts +14 -0
  211. package/src/core/__tests__/TypeBox-usecases.spec.ts +35 -0
  212. package/src/core/__tests__/TypeBoxLocale.spec.ts +15 -0
  213. package/src/core/__tests__/descriptor.spec.ts +34 -0
  214. package/src/core/__tests__/fixtures/A.ts +5 -0
  215. package/src/core/__tests__/pagination.spec.ts +77 -0
  216. package/src/core/helpers/jsonSchemaToTypeBox.ts +2 -2
  217. package/src/core/primitives/$atom.spec.ts +43 -0
  218. package/src/core/primitives/$hook.spec.ts +130 -0
  219. package/src/core/primitives/$inject.spec.ts +175 -0
  220. package/src/core/primitives/$module.spec.ts +115 -0
  221. package/src/core/providers/CodecManager.spec.ts +740 -0
  222. package/src/core/providers/EventManager.spec.ts +762 -0
  223. package/src/core/providers/EventManager.ts +4 -0
  224. package/src/core/providers/StateManager.spec.ts +365 -0
  225. package/src/core/providers/TypeProvider.spec.ts +1607 -0
  226. package/src/core/providers/TypeProvider.ts +20 -26
  227. package/src/datetime/primitives/$interval.spec.ts +103 -0
  228. package/src/datetime/providers/DateTimeProvider.spec.ts +86 -0
  229. package/src/email/primitives/$email.spec.ts +175 -0
  230. package/src/email/providers/LocalEmailProvider.spec.ts +341 -0
  231. package/src/fake/__tests__/keyName.example.ts +40 -0
  232. package/src/fake/__tests__/keyName.spec.ts +152 -0
  233. package/src/fake/__tests__/module.example.ts +32 -0
  234. package/src/fake/providers/FakeProvider.spec.ts +438 -0
  235. package/src/file/providers/FileSystemProvider.ts +8 -0
  236. package/src/file/providers/NodeFileSystemProvider.spec.ts +418 -0
  237. package/src/file/providers/NodeFileSystemProvider.ts +5 -0
  238. package/src/file/services/FileDetector.spec.ts +591 -0
  239. package/src/lock/core/__tests__/shared.ts +190 -0
  240. package/src/lock/core/providers/MemoryLockProvider.spec.ts +25 -0
  241. package/src/lock/redis/providers/RedisLockProvider.spec.ts +25 -0
  242. package/src/logger/__tests__/SimpleFormatterProvider.spec.ts +109 -0
  243. package/src/logger/primitives/$logger.spec.ts +108 -0
  244. package/src/logger/services/Logger.spec.ts +295 -0
  245. package/src/mcp/__tests__/errors.spec.ts +175 -0
  246. package/src/mcp/__tests__/integration.spec.ts +450 -0
  247. package/src/mcp/helpers/jsonrpc.spec.ts +380 -0
  248. package/src/mcp/primitives/$prompt.spec.ts +468 -0
  249. package/src/mcp/primitives/$resource.spec.ts +390 -0
  250. package/src/mcp/primitives/$tool.spec.ts +406 -0
  251. package/src/mcp/providers/McpServerProvider.spec.ts +797 -0
  252. package/src/orm/__tests__/$repository-crud.spec.ts +276 -0
  253. package/src/orm/__tests__/$repository-hooks.spec.ts +325 -0
  254. package/src/orm/__tests__/$repository-orderBy.spec.ts +128 -0
  255. package/src/orm/__tests__/$repository-pagination-sort.spec.ts +149 -0
  256. package/src/orm/__tests__/$repository-save.spec.ts +37 -0
  257. package/src/orm/__tests__/ModelBuilder-integration.spec.ts +490 -0
  258. package/src/orm/__tests__/ModelBuilder-types.spec.ts +186 -0
  259. package/src/orm/__tests__/PostgresProvider.spec.ts +46 -0
  260. package/src/orm/__tests__/delete-returning.spec.ts +256 -0
  261. package/src/orm/__tests__/deletedAt.spec.ts +80 -0
  262. package/src/orm/__tests__/enums.spec.ts +315 -0
  263. package/src/orm/__tests__/execute.spec.ts +72 -0
  264. package/src/orm/__tests__/fixtures/bigEntitySchema.ts +65 -0
  265. package/src/orm/__tests__/fixtures/userEntitySchema.ts +27 -0
  266. package/src/orm/__tests__/joins.spec.ts +1114 -0
  267. package/src/orm/__tests__/page.spec.ts +287 -0
  268. package/src/orm/__tests__/primaryKey.spec.ts +87 -0
  269. package/src/orm/__tests__/query-date-encoding.spec.ts +402 -0
  270. package/src/orm/__tests__/ref-auto-onDelete.spec.ts +156 -0
  271. package/src/orm/__tests__/references.spec.ts +102 -0
  272. package/src/orm/__tests__/security.spec.ts +710 -0
  273. package/src/orm/__tests__/sqlite.spec.ts +111 -0
  274. package/src/orm/__tests__/string-operators.spec.ts +429 -0
  275. package/src/orm/__tests__/timestamps.spec.ts +388 -0
  276. package/src/orm/__tests__/validation.spec.ts +183 -0
  277. package/src/orm/__tests__/version.spec.ts +64 -0
  278. package/src/orm/helpers/parseQueryString.spec.ts +196 -0
  279. package/src/orm/primitives/$repository.spec.ts +137 -0
  280. package/src/orm/primitives/$sequence.spec.ts +29 -0
  281. package/src/orm/primitives/$transaction.spec.ts +82 -0
  282. package/src/orm/providers/drivers/BunPostgresProvider.ts +3 -3
  283. package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -1
  284. package/src/orm/providers/drivers/CloudflareD1Provider.ts +1 -1
  285. package/src/orm/providers/drivers/DatabaseProvider.ts +1 -1
  286. package/src/orm/providers/drivers/NodePostgresProvider.ts +3 -3
  287. package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
  288. package/src/orm/providers/drivers/PglitePostgresProvider.ts +2 -2
  289. package/src/orm/services/ModelBuilder.spec.ts +575 -0
  290. package/src/orm/services/Repository.spec.ts +137 -0
  291. package/src/queue/core/__tests__/shared.ts +143 -0
  292. package/src/queue/core/providers/MemoryQueueProvider.spec.ts +23 -0
  293. package/src/queue/core/providers/WorkerProvider.spec.ts +378 -0
  294. package/src/queue/redis/providers/RedisQueueProvider.spec.ts +23 -0
  295. package/src/redis/__tests__/redis.spec.ts +58 -0
  296. package/src/retry/primitives/$retry.spec.ts +234 -0
  297. package/src/retry/providers/RetryProvider.spec.ts +438 -0
  298. package/src/router/__tests__/match.spec.ts +252 -0
  299. package/src/router/providers/RouterProvider.spec.ts +197 -0
  300. package/src/scheduler/__tests__/$scheduler-cron.spec.ts +25 -0
  301. package/src/scheduler/__tests__/$scheduler-interval.spec.ts +25 -0
  302. package/src/scheduler/__tests__/shared.ts +77 -0
  303. package/src/security/__tests__/bug-1-wildcard-after-start.spec.ts +229 -0
  304. package/src/security/__tests__/bug-2-password-validation.spec.ts +245 -0
  305. package/src/security/__tests__/bug-3-regex-vulnerability.spec.ts +407 -0
  306. package/src/security/__tests__/bug-4-oauth2-validation.spec.ts +439 -0
  307. package/src/security/__tests__/multi-layer-permissions.spec.ts +522 -0
  308. package/src/security/primitives/$permission.spec.ts +30 -0
  309. package/src/security/primitives/$permission.ts +2 -2
  310. package/src/security/primitives/$realm.spec.ts +101 -0
  311. package/src/security/primitives/$role.spec.ts +52 -0
  312. package/src/security/primitives/$serviceAccount.spec.ts +61 -0
  313. package/src/security/providers/SecurityProvider.spec.ts +350 -0
  314. package/src/server/auth/providers/ServerAuthProvider.ts +0 -2
  315. package/src/server/cache/providers/ServerCacheProvider.spec.ts +942 -0
  316. package/src/server/compress/providers/ServerCompressProvider.spec.ts +31 -0
  317. package/src/server/compress/providers/ServerCompressProvider.ts +2 -0
  318. package/src/server/cookies/providers/ServerCookiesProvider.spec.ts +253 -0
  319. package/src/server/core/__tests__/ServerRouterProvider-getRoutes.spec.ts +334 -0
  320. package/src/server/core/__tests__/ServerRouterProvider-requestId.spec.ts +129 -0
  321. package/src/server/core/primitives/$action.spec.ts +191 -0
  322. package/src/server/core/primitives/$route.spec.ts +65 -0
  323. package/src/server/core/providers/ServerBodyParserProvider.spec.ts +93 -0
  324. package/src/server/core/providers/ServerLoggerProvider.spec.ts +100 -0
  325. package/src/server/core/providers/ServerProvider.ts +3 -1
  326. package/src/server/core/services/HttpClient.spec.ts +123 -0
  327. package/src/server/core/services/UserAgentParser.spec.ts +111 -0
  328. package/src/server/cors/providers/ServerCorsProvider.spec.ts +481 -0
  329. package/src/server/health/providers/ServerHealthProvider.spec.ts +22 -0
  330. package/src/server/helmet/providers/ServerHelmetProvider.spec.ts +105 -0
  331. package/src/server/links/__tests__/$action.spec.ts +238 -0
  332. package/src/server/links/__tests__/fixtures/CrudApp.ts +122 -0
  333. package/src/server/links/__tests__/requestId.spec.ts +120 -0
  334. package/src/server/links/primitives/$remote.spec.ts +228 -0
  335. package/src/server/links/providers/LinkProvider.spec.ts +54 -0
  336. package/src/server/links/providers/LinkProvider.ts +49 -3
  337. package/src/server/links/providers/ServerLinksProvider.ts +1 -53
  338. package/src/server/links/schemas/apiLinksResponseSchema.ts +7 -0
  339. package/src/server/metrics/providers/ServerMetricsProvider.spec.ts +25 -0
  340. package/src/server/multipart/providers/ServerMultipartProvider.spec.ts +528 -0
  341. package/src/server/proxy/primitives/$proxy.spec.ts +87 -0
  342. package/src/server/rate-limit/__tests__/ActionRateLimit.spec.ts +211 -0
  343. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +344 -0
  344. package/src/server/security/__tests__/BasicAuth.spec.ts +684 -0
  345. package/src/server/security/__tests__/ServerSecurityProvider-realm.spec.ts +388 -0
  346. package/src/server/security/providers/ServerSecurityProvider.spec.ts +123 -0
  347. package/src/server/static/primitives/$serve.spec.ts +193 -0
  348. package/src/server/swagger/__tests__/ui.spec.ts +52 -0
  349. package/src/server/swagger/primitives/$swagger.spec.ts +193 -0
  350. package/src/server/swagger/providers/ServerSwaggerProvider.ts +18 -8
  351. package/src/sms/primitives/$sms.spec.ts +165 -0
  352. package/src/sms/providers/LocalSmsProvider.spec.ts +224 -0
  353. package/src/sms/providers/MemorySmsProvider.spec.ts +193 -0
  354. package/src/thread/primitives/$thread.spec.ts +186 -0
  355. package/src/topic/core/__tests__/shared.ts +144 -0
  356. package/src/topic/core/providers/MemoryTopicProvider.spec.ts +23 -0
  357. package/src/topic/redis/providers/RedisTopicProvider.spec.ts +23 -0
  358. package/src/vite/plugins/viteAlephaDev.ts +16 -4
  359. package/src/vite/tasks/runAlepha.ts +7 -1
  360. package/src/websocket/__tests__/$websocket-new.spec.ts +195 -0
  361. package/src/websocket/primitives/$channel.spec.ts +30 -0
@@ -1,16 +1,16 @@
1
1
  import { type Static, t } from "alepha";
2
- import { $entity, pg } from "alepha/orm";
2
+ import { $entity, db } from "alepha/orm";
3
3
  import { users } from "./users.ts";
4
4
 
5
5
  export const sessions = $entity({
6
6
  name: "sessions",
7
7
  schema: t.object({
8
- id: pg.primaryKey(t.uuid()),
9
- version: pg.version(),
10
- createdAt: pg.createdAt(),
11
- updatedAt: pg.updatedAt(),
8
+ id: db.primaryKey(t.uuid()),
9
+ version: db.version(),
10
+ createdAt: db.createdAt(),
11
+ updatedAt: db.updatedAt(),
12
12
  refreshToken: t.uuid(),
13
- userId: pg.ref(t.uuid(), () => users.cols.id),
13
+ userId: db.ref(t.uuid(), () => users.cols.id),
14
14
  expiresAt: t.datetime(),
15
15
  ip: t.optional(t.text()),
16
16
  userAgent: t.optional(
@@ -1,17 +1,17 @@
1
1
  import { type Static, t } from "alepha";
2
- import { $entity, pg } from "alepha/orm";
2
+ import { $entity, db } from "alepha/orm";
3
3
 
4
4
  export const DEFAULT_USER_REALM_NAME = "default";
5
5
 
6
6
  export const users = $entity({
7
7
  name: "users",
8
8
  schema: t.object({
9
- id: pg.primaryKey(t.uuid()),
10
- version: pg.version(),
11
- createdAt: pg.createdAt(),
12
- updatedAt: pg.updatedAt(),
9
+ id: db.primaryKey(t.uuid()),
10
+ version: db.version(),
11
+ createdAt: db.createdAt(),
12
+ updatedAt: db.updatedAt(),
13
13
 
14
- realm: pg.default(t.text(), DEFAULT_USER_REALM_NAME),
14
+ realm: db.default(t.text(), DEFAULT_USER_REALM_NAME),
15
15
 
16
16
  username: t.optional(
17
17
  t.shortText({
@@ -25,13 +25,13 @@ export const users = $entity({
25
25
 
26
26
  phoneNumber: t.optional(t.e164()),
27
27
 
28
- roles: pg.default(t.array(t.string()), []),
28
+ roles: db.default(t.array(t.string()), []),
29
29
  firstName: t.optional(t.string()),
30
30
  lastName: t.optional(t.string()),
31
31
  picture: t.optional(t.string()),
32
- enabled: pg.default(t.boolean(), true),
32
+ enabled: db.default(t.boolean(), true),
33
33
 
34
- emailVerified: pg.default(t.boolean(), false),
34
+ emailVerified: db.default(t.boolean(), false),
35
35
  }),
36
36
  indexes: [
37
37
  { columns: ["realm", "username"], unique: true },
@@ -4,8 +4,9 @@ import { AlephaApiVerification } from "alepha/api/verifications";
4
4
  import { AlephaEmail } from "alepha/email";
5
5
  import { AlephaServerCompress } from "alepha/server/compress";
6
6
  import { AlephaServerHelmet } from "alepha/server/helmet";
7
- import { IdentityController } from "./controllers/IdentityController.ts";
8
- import { SessionController } from "./controllers/SessionController.ts";
7
+ import { AdminIdentityController } from "./controllers/AdminIdentityController.ts";
8
+ import { AdminSessionController } from "./controllers/AdminSessionController.ts";
9
+ import { AdminUserController } from "./controllers/AdminUserController.ts";
9
10
  import { UserController } from "./controllers/UserController.ts";
10
11
  import { UserRealmController } from "./controllers/UserRealmController.ts";
11
12
  import { UserNotifications } from "./notifications/UserNotifications.ts";
@@ -20,8 +21,9 @@ import { UserService } from "./services/UserService.ts";
20
21
  // ---------------------------------------------------------------------------------------------------------------------
21
22
 
22
23
  export * from "./atoms/realmAuthSettingsAtom.ts";
23
- export * from "./controllers/IdentityController.ts";
24
- export * from "./controllers/SessionController.ts";
24
+ export * from "./controllers/AdminIdentityController.ts";
25
+ export * from "./controllers/AdminSessionController.ts";
26
+ export * from "./controllers/AdminUserController.ts";
25
27
  export * from "./controllers/UserController.ts";
26
28
  export * from "./controllers/UserRealmController.ts";
27
29
  export * from "./entities/identities.ts";
@@ -78,8 +80,9 @@ export const AlephaApiUsers = $module({
78
80
  UserService,
79
81
  IdentityService,
80
82
  UserController,
81
- SessionController,
82
- IdentityController,
83
+ AdminUserController,
84
+ AdminSessionController,
85
+ AdminIdentityController,
83
86
  UserRealmController,
84
87
  UserNotifications,
85
88
  ],
@@ -1,7 +1,6 @@
1
1
  import { $context } from "alepha";
2
2
  import { AlephaApiAudits } from "alepha/api/audits";
3
3
  import { AlephaApiFiles } from "alepha/api/files";
4
- import { AlephaApiJobs } from "alepha/api/jobs";
5
4
  import type { Repository } from "alepha/orm";
6
5
  import {
7
6
  $realm,
@@ -49,22 +48,28 @@ export const $userRealm = (
49
48
  const sessionService = alepha.inject(SessionService);
50
49
  const securityProvider = alepha.inject(SecurityProvider);
51
50
  const userRealmProvider = alepha.inject(UserRealmProvider);
51
+
52
52
  const name = options.realm?.name ?? DEFAULT_USER_REALM_NAME;
53
53
 
54
- const userRealm = userRealmProvider.register(name, options);
54
+ options.settings ??= {};
55
55
 
56
- if (options.modules?.audits) {
57
- alepha.with(AlephaApiAudits);
56
+ if (options.settings.emailRequired) {
57
+ options.settings.emailEnabled = true;
58
58
  }
59
59
 
60
- if (options.modules?.files) {
61
- alepha.with(AlephaApiFiles);
60
+ if (options.settings.usernameRequired) {
61
+ options.settings.usernameEnabled = true;
62
62
  }
63
63
 
64
- if (options.modules?.jobs) {
65
- alepha.with(AlephaApiJobs);
64
+ if (options.settings.phoneRequired) {
65
+ options.settings.phoneEnabled = true;
66
66
  }
67
67
 
68
+ const userRealm = userRealmProvider.register(name, options);
69
+
70
+ alepha.with(AlephaApiFiles);
71
+ alepha.with(AlephaApiAudits);
72
+
68
73
  const realm: UserRealmPrimitive = $realm({
69
74
  ...options.realm,
70
75
  name,
@@ -0,0 +1,509 @@
1
+ import { Alepha } from "alepha";
2
+ import { AlephaApiVerification } from "alepha/api/verifications";
3
+ import { DateTimeProvider } from "alepha/datetime";
4
+ import { AlephaEmail, MemoryEmailProvider } from "alepha/email";
5
+ import { AlephaSecurity, CryptoProvider } from "alepha/security";
6
+ import { BadRequestError, HttpError } from "alepha/server";
7
+ import { describe, it } from "vitest";
8
+ import {
9
+ AlephaApiUsers,
10
+ CredentialService,
11
+ SessionService,
12
+ UserService,
13
+ } from "../index.ts";
14
+
15
+ const setup = async () => {
16
+ const alepha = Alepha.create({
17
+ env: { LOG_LEVEL: "error" },
18
+ });
19
+
20
+ alepha.with(AlephaSecurity);
21
+ alepha.with(AlephaEmail);
22
+ alepha.with(AlephaApiVerification);
23
+ alepha.with(AlephaApiUsers);
24
+
25
+ await alepha.start();
26
+
27
+ const emailProvider = alepha.inject(MemoryEmailProvider);
28
+ emailProvider.records = [];
29
+
30
+ return {
31
+ alepha,
32
+ credentialService: alepha.inject(CredentialService),
33
+ userService: alepha.inject(UserService),
34
+ sessionService: alepha.inject(SessionService),
35
+ cryptoProvider: alepha.inject(CryptoProvider),
36
+ dateTimeProvider: alepha.inject(DateTimeProvider),
37
+ emailProvider,
38
+ };
39
+ };
40
+
41
+ // Helper to extract code from email
42
+ const extractCode = (emailBody: string): string => {
43
+ const match = emailBody.match(/(\d{6})/);
44
+ if (!match) throw new Error("Code not found in email");
45
+ return match[1];
46
+ };
47
+
48
+ // Helper to create a user with credentials
49
+ const createUserWithCredentials = async (
50
+ userService: UserService,
51
+ credentialService: CredentialService,
52
+ cryptoProvider: CryptoProvider,
53
+ email: string,
54
+ password: string,
55
+ ) => {
56
+ const user = await userService.users().create({
57
+ email,
58
+ username: email.split("@")[0],
59
+ roles: ["user"],
60
+ });
61
+
62
+ const hashedPassword = await cryptoProvider.hashPassword(password);
63
+
64
+ await credentialService.identities().create({
65
+ userId: user.id,
66
+ provider: "credentials",
67
+ password: hashedPassword,
68
+ });
69
+
70
+ return user;
71
+ };
72
+
73
+ describe("alepha/api/users - CredentialService", () => {
74
+ describe("Phase 1: createPasswordResetIntent", () => {
75
+ it("should create a password reset intent for existing user", async ({
76
+ expect,
77
+ }) => {
78
+ const { credentialService, userService, cryptoProvider, emailProvider } =
79
+ await setup();
80
+
81
+ await createUserWithCredentials(
82
+ userService,
83
+ credentialService,
84
+ cryptoProvider,
85
+ "reset@example.com",
86
+ "OldPassword123!",
87
+ );
88
+
89
+ const result =
90
+ await credentialService.createPasswordResetIntent("reset@example.com");
91
+
92
+ expect(result.intentId).toBeDefined();
93
+ expect(result.expiresAt).toBeDefined();
94
+
95
+ // Verify email was sent
96
+ await expect.poll(() => emailProvider.records.length).toBe(1);
97
+ expect(emailProvider.records[0].to).toBe("reset@example.com");
98
+ expect(emailProvider.records[0].subject).toBe("Reset your password");
99
+ });
100
+
101
+ it("should return fake intent for non-existent email (security)", async ({
102
+ expect,
103
+ }) => {
104
+ const { credentialService, emailProvider } = await setup();
105
+
106
+ // Should still return a response (security - don't reveal if email exists)
107
+ const result = await credentialService.createPasswordResetIntent(
108
+ "nonexistent@example.com",
109
+ );
110
+
111
+ expect(result.intentId).toBeDefined();
112
+ expect(result.expiresAt).toBeDefined();
113
+
114
+ // No email should be sent
115
+ expect(emailProvider.records.length).toBe(0);
116
+ });
117
+
118
+ it("should return fake intent for user without credentials identity", async ({
119
+ expect,
120
+ }) => {
121
+ const { credentialService, userService, emailProvider } = await setup();
122
+
123
+ // Create user without credentials (OAuth-only user)
124
+ await userService.users().create({
125
+ email: "oauth@example.com",
126
+ username: "oauthuser",
127
+ roles: ["user"],
128
+ });
129
+
130
+ // Should still return a response
131
+ const result =
132
+ await credentialService.createPasswordResetIntent("oauth@example.com");
133
+
134
+ expect(result.intentId).toBeDefined();
135
+ expect(result.expiresAt).toBeDefined();
136
+
137
+ // No email should be sent
138
+ expect(emailProvider.records.length).toBe(0);
139
+ });
140
+
141
+ it("should set correct expiration time (10 minutes)", async ({
142
+ expect,
143
+ }) => {
144
+ const {
145
+ credentialService,
146
+ userService,
147
+ cryptoProvider,
148
+ dateTimeProvider,
149
+ } = await setup();
150
+
151
+ await createUserWithCredentials(
152
+ userService,
153
+ credentialService,
154
+ cryptoProvider,
155
+ "expiry@example.com",
156
+ "Password123!",
157
+ );
158
+
159
+ const before = dateTimeProvider.now();
160
+
161
+ const result =
162
+ await credentialService.createPasswordResetIntent("expiry@example.com");
163
+
164
+ const expiresAt = dateTimeProvider.of(result.expiresAt);
165
+ const expectedExpiry = before.add(10, "minutes");
166
+
167
+ // Should expire approximately 10 minutes from now
168
+ expect(expiresAt.diff(expectedExpiry, "seconds")).toBeLessThan(5);
169
+ });
170
+ });
171
+
172
+ describe("Phase 2: completePasswordReset", () => {
173
+ it("should complete password reset with valid code", async ({ expect }) => {
174
+ const {
175
+ credentialService,
176
+ userService,
177
+ sessionService,
178
+ cryptoProvider,
179
+ emailProvider,
180
+ } = await setup();
181
+
182
+ await createUserWithCredentials(
183
+ userService,
184
+ credentialService,
185
+ cryptoProvider,
186
+ "complete@example.com",
187
+ "OldPassword123!",
188
+ );
189
+
190
+ // Phase 1: Create intent
191
+ const intent = await credentialService.createPasswordResetIntent(
192
+ "complete@example.com",
193
+ );
194
+
195
+ // Extract code from email
196
+ await expect.poll(() => emailProvider.records.length).toBe(1);
197
+ const code = extractCode(emailProvider.records[0].body);
198
+
199
+ // Phase 2: Complete password reset
200
+ await credentialService.completePasswordReset({
201
+ intentId: intent.intentId,
202
+ code,
203
+ newPassword: "NewPassword456!",
204
+ });
205
+
206
+ // Verify new password works
207
+ const loggedInUser = await sessionService.login(
208
+ "credentials",
209
+ "complete@example.com",
210
+ "NewPassword456!",
211
+ );
212
+
213
+ expect(loggedInUser?.email).toBe("complete@example.com");
214
+ });
215
+
216
+ it("should reject expired intent (410 Gone)", async ({ expect }) => {
217
+ const {
218
+ credentialService,
219
+ userService,
220
+ cryptoProvider,
221
+ dateTimeProvider,
222
+ emailProvider,
223
+ } = await setup();
224
+
225
+ await createUserWithCredentials(
226
+ userService,
227
+ credentialService,
228
+ cryptoProvider,
229
+ "expired@example.com",
230
+ "OldPassword123!",
231
+ );
232
+
233
+ // Create intent
234
+ const intent = await credentialService.createPasswordResetIntent(
235
+ "expired@example.com",
236
+ );
237
+
238
+ // Extract code
239
+ await expect.poll(() => emailProvider.records.length).toBe(1);
240
+ const code = extractCode(emailProvider.records[0].body);
241
+
242
+ // Travel forward 11 minutes (intent expires at 10)
243
+ dateTimeProvider.travel(11, "minutes");
244
+
245
+ // Attempt to complete
246
+ await expect(
247
+ credentialService.completePasswordReset({
248
+ intentId: intent.intentId,
249
+ code,
250
+ newPassword: "NewPassword456!",
251
+ }),
252
+ ).rejects.toThrow(HttpError);
253
+ });
254
+
255
+ it("should reject invalid intent ID", async ({ expect }) => {
256
+ const { credentialService } = await setup();
257
+
258
+ await expect(
259
+ credentialService.completePasswordReset({
260
+ intentId: "550e8400-e29b-41d4-a716-446655440000",
261
+ code: "123456",
262
+ newPassword: "NewPassword456!",
263
+ }),
264
+ ).rejects.toThrow(HttpError);
265
+ });
266
+
267
+ it("should reject invalid verification code", async ({ expect }) => {
268
+ const { credentialService, userService, cryptoProvider, emailProvider } =
269
+ await setup();
270
+
271
+ await createUserWithCredentials(
272
+ userService,
273
+ credentialService,
274
+ cryptoProvider,
275
+ "wrongcode@example.com",
276
+ "OldPassword123!",
277
+ );
278
+
279
+ const intent = await credentialService.createPasswordResetIntent(
280
+ "wrongcode@example.com",
281
+ );
282
+
283
+ // Wait for email
284
+ await expect.poll(() => emailProvider.records.length).toBe(1);
285
+
286
+ await expect(
287
+ credentialService.completePasswordReset({
288
+ intentId: intent.intentId,
289
+ code: "000000", // Wrong code
290
+ newPassword: "NewPassword456!",
291
+ }),
292
+ ).rejects.toThrowError(BadRequestError);
293
+ });
294
+
295
+ it("should not allow intent reuse after successful reset", async ({
296
+ expect,
297
+ }) => {
298
+ const { credentialService, userService, cryptoProvider, emailProvider } =
299
+ await setup();
300
+
301
+ await createUserWithCredentials(
302
+ userService,
303
+ credentialService,
304
+ cryptoProvider,
305
+ "onetime@example.com",
306
+ "OldPassword123!",
307
+ );
308
+
309
+ const intent = await credentialService.createPasswordResetIntent(
310
+ "onetime@example.com",
311
+ );
312
+
313
+ // Extract code
314
+ await expect.poll(() => emailProvider.records.length).toBe(1);
315
+ const code = extractCode(emailProvider.records[0].body);
316
+
317
+ // First completion should succeed
318
+ await credentialService.completePasswordReset({
319
+ intentId: intent.intentId,
320
+ code,
321
+ newPassword: "NewPassword456!",
322
+ });
323
+
324
+ // Second attempt should fail (intent deleted)
325
+ await expect(
326
+ credentialService.completePasswordReset({
327
+ intentId: intent.intentId,
328
+ code,
329
+ newPassword: "AnotherPassword789!",
330
+ }),
331
+ ).rejects.toThrow(HttpError);
332
+ });
333
+
334
+ it("should invalidate all existing sessions after password reset", async ({
335
+ expect,
336
+ }) => {
337
+ const {
338
+ credentialService,
339
+ userService,
340
+ sessionService,
341
+ cryptoProvider,
342
+ emailProvider,
343
+ } = await setup();
344
+
345
+ const user = await createUserWithCredentials(
346
+ userService,
347
+ credentialService,
348
+ cryptoProvider,
349
+ "sessions@example.com",
350
+ "OldPassword123!",
351
+ );
352
+
353
+ // Create a session
354
+ await sessionService.sessions().create({
355
+ userId: user.id,
356
+ refreshToken: crypto.randomUUID(),
357
+ expiresAt: new Date(Date.now() + 3600000).toISOString(),
358
+ });
359
+
360
+ // Verify session exists
361
+ const sessionsBefore = await sessionService.sessions().findMany({
362
+ where: { userId: { eq: user.id } },
363
+ });
364
+ expect(sessionsBefore).toHaveLength(1);
365
+
366
+ // Create password reset intent
367
+ const intent = await credentialService.createPasswordResetIntent(
368
+ "sessions@example.com",
369
+ );
370
+
371
+ // Extract code
372
+ await expect.poll(() => emailProvider.records.length).toBe(1);
373
+ const code = extractCode(emailProvider.records[0].body);
374
+
375
+ // Complete password reset
376
+ await credentialService.completePasswordReset({
377
+ intentId: intent.intentId,
378
+ code,
379
+ newPassword: "NewPassword456!",
380
+ });
381
+
382
+ // Verify all sessions are invalidated
383
+ const sessionsAfter = await sessionService.sessions().findMany({
384
+ where: { userId: { eq: user.id } },
385
+ });
386
+ expect(sessionsAfter).toHaveLength(0);
387
+ });
388
+
389
+ it("should not allow old password after reset", async ({ expect }) => {
390
+ const {
391
+ credentialService,
392
+ userService,
393
+ sessionService,
394
+ cryptoProvider,
395
+ emailProvider,
396
+ } = await setup();
397
+
398
+ await createUserWithCredentials(
399
+ userService,
400
+ credentialService,
401
+ cryptoProvider,
402
+ "oldpass@example.com",
403
+ "OldPassword123!",
404
+ );
405
+
406
+ // Verify old password works before reset
407
+ const beforeReset = await sessionService.login(
408
+ "credentials",
409
+ "oldpass@example.com",
410
+ "OldPassword123!",
411
+ );
412
+ expect(beforeReset?.email).toBe("oldpass@example.com");
413
+
414
+ // Create intent and reset password
415
+ const intent = await credentialService.createPasswordResetIntent(
416
+ "oldpass@example.com",
417
+ );
418
+
419
+ await expect.poll(() => emailProvider.records.length).toBe(1);
420
+ const code = extractCode(emailProvider.records[0].body);
421
+
422
+ await credentialService.completePasswordReset({
423
+ intentId: intent.intentId,
424
+ code,
425
+ newPassword: "NewPassword456!",
426
+ });
427
+
428
+ // Old password should no longer work (login throws error for invalid credentials)
429
+ await expect(
430
+ sessionService.login(
431
+ "credentials",
432
+ "oldpass@example.com",
433
+ "OldPassword123!",
434
+ ),
435
+ ).rejects.toThrow();
436
+ });
437
+ });
438
+
439
+ describe("Full password reset flow integration", () => {
440
+ it("should complete full password reset flow", async ({ expect }) => {
441
+ const {
442
+ credentialService,
443
+ userService,
444
+ sessionService,
445
+ cryptoProvider,
446
+ emailProvider,
447
+ } = await setup();
448
+
449
+ // Create user
450
+ await createUserWithCredentials(
451
+ userService,
452
+ credentialService,
453
+ cryptoProvider,
454
+ "fullflow@example.com",
455
+ "OldPassword123!",
456
+ );
457
+
458
+ // Phase 1: Request password reset
459
+ const intent = await credentialService.createPasswordResetIntent(
460
+ "fullflow@example.com",
461
+ );
462
+
463
+ expect(intent.intentId).toBeDefined();
464
+ expect(intent.expiresAt).toBeDefined();
465
+
466
+ // Verify email was sent
467
+ await expect.poll(() => emailProvider.records.length).toBe(1);
468
+ expect(emailProvider.records[0].to).toBe("fullflow@example.com");
469
+ const code = extractCode(emailProvider.records[0].body);
470
+
471
+ // Phase 2: Complete password reset
472
+ await credentialService.completePasswordReset({
473
+ intentId: intent.intentId,
474
+ code,
475
+ newPassword: "NewSecurePassword789!",
476
+ });
477
+
478
+ // Verify new password works
479
+ const user = await sessionService.login(
480
+ "credentials",
481
+ "fullflow@example.com",
482
+ "NewSecurePassword789!",
483
+ );
484
+
485
+ expect(user?.email).toBe("fullflow@example.com");
486
+ });
487
+ });
488
+
489
+ describe("Legacy methods (backward compatibility)", () => {
490
+ it("requestPasswordReset should work as before", async ({ expect }) => {
491
+ const { credentialService, userService, cryptoProvider, emailProvider } =
492
+ await setup();
493
+
494
+ await createUserWithCredentials(
495
+ userService,
496
+ credentialService,
497
+ cryptoProvider,
498
+ "legacy@example.com",
499
+ "OldPassword123!",
500
+ );
501
+
502
+ const result =
503
+ await credentialService.requestPasswordReset("legacy@example.com");
504
+
505
+ expect(result).toBe(true);
506
+ await expect.poll(() => emailProvider.records.length).toBe(1);
507
+ });
508
+ });
509
+ });