alepha 0.19.0 → 0.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (638) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +6 -9
  3. package/dist/api/audits/index.d.ts +378 -346
  4. package/dist/api/audits/index.d.ts.map +1 -1
  5. package/dist/api/files/index.d.ts +216 -184
  6. package/dist/api/files/index.d.ts.map +1 -1
  7. package/dist/api/files/index.js +5 -1
  8. package/dist/api/files/index.js.map +1 -1
  9. package/dist/api/jobs/index.d.ts +528 -496
  10. package/dist/api/jobs/index.d.ts.map +1 -1
  11. package/dist/api/jobs/index.js +3 -3
  12. package/dist/api/jobs/index.js.map +1 -1
  13. package/dist/api/keys/index.d.ts +202 -202
  14. package/dist/api/keys/index.d.ts.map +1 -1
  15. package/dist/api/notifications/index.d.ts +152 -152
  16. package/dist/api/notifications/index.d.ts.map +1 -1
  17. package/dist/api/organizations/index.browser.js +48 -0
  18. package/dist/api/organizations/index.browser.js.map +1 -0
  19. package/dist/api/organizations/index.d.ts +516 -0
  20. package/dist/api/organizations/index.d.ts.map +1 -0
  21. package/dist/api/organizations/index.js +202 -0
  22. package/dist/api/organizations/index.js.map +1 -0
  23. package/dist/api/parameters/index.d.ts +391 -358
  24. package/dist/api/parameters/index.d.ts.map +1 -1
  25. package/dist/api/parameters/index.js +5 -1
  26. package/dist/api/parameters/index.js.map +1 -1
  27. package/dist/api/users/index.browser.js +7 -5
  28. package/dist/api/users/index.browser.js.map +1 -1
  29. package/dist/api/users/index.d.ts +989 -931
  30. package/dist/api/users/index.d.ts.map +1 -1
  31. package/dist/api/users/index.js +292 -146
  32. package/dist/api/users/index.js.map +1 -1
  33. package/dist/api/verifications/index.d.ts +132 -132
  34. package/dist/api/verifications/index.d.ts.map +1 -1
  35. package/dist/api/verifications/index.js +2 -2
  36. package/dist/api/verifications/index.js.map +1 -1
  37. package/dist/batch/index.d.ts +6 -6
  38. package/dist/batch/index.d.ts.map +1 -1
  39. package/dist/billing/index.d.ts +1048 -0
  40. package/dist/billing/index.d.ts.map +1 -0
  41. package/dist/billing/index.js +713 -0
  42. package/dist/billing/index.js.map +1 -0
  43. package/dist/bin/index.js +0 -2
  44. package/dist/bin/index.js.map +1 -1
  45. package/dist/bucket/index.d.ts +10 -10
  46. package/dist/bucket/index.d.ts.map +1 -1
  47. package/dist/bucket/index.js +2 -2
  48. package/dist/bucket/index.js.map +1 -1
  49. package/dist/cache/core/index.d.ts +9 -9
  50. package/dist/cache/core/index.d.ts.map +1 -1
  51. package/dist/cache/core/index.js +2 -2
  52. package/dist/cache/core/index.js.map +1 -1
  53. package/dist/cache/core/index.workerd.js +2 -2
  54. package/dist/cache/core/index.workerd.js.map +1 -1
  55. package/dist/cache/redis/index.d.ts +6 -6
  56. package/dist/cache/redis/index.d.ts.map +1 -1
  57. package/dist/cache/redis/index.js +2 -2
  58. package/dist/cache/redis/index.js.map +1 -1
  59. package/dist/cli/config/index.d.ts +12 -2
  60. package/dist/cli/config/index.d.ts.map +1 -1
  61. package/dist/cli/config/index.js +4 -0
  62. package/dist/cli/config/index.js.map +1 -1
  63. package/dist/cli/core/index.d.ts +183 -139
  64. package/dist/cli/core/index.d.ts.map +1 -1
  65. package/dist/cli/core/index.js +283 -86
  66. package/dist/cli/core/index.js.map +1 -1
  67. package/dist/cli/devtools/index.d.ts +45 -0
  68. package/dist/cli/devtools/index.d.ts.map +1 -0
  69. package/dist/cli/devtools/index.js +170 -0
  70. package/dist/cli/devtools/index.js.map +1 -0
  71. package/dist/cli/platform/index.d.ts +383 -492
  72. package/dist/cli/platform/index.d.ts.map +1 -1
  73. package/dist/cli/platform/index.js +42 -511
  74. package/dist/cli/platform/index.js.map +1 -1
  75. package/dist/cli/vendor/index.d.ts +196 -0
  76. package/dist/cli/vendor/index.d.ts.map +1 -0
  77. package/dist/cli/vendor/index.js +384 -0
  78. package/dist/cli/vendor/index.js.map +1 -0
  79. package/dist/command/index.d.ts +18 -18
  80. package/dist/command/index.d.ts.map +1 -1
  81. package/dist/command/index.js +2 -2
  82. package/dist/command/index.js.map +1 -1
  83. package/dist/core/index.browser.js +4 -4
  84. package/dist/core/index.browser.js.map +1 -1
  85. package/dist/core/index.d.ts +10 -10
  86. package/dist/core/index.d.ts.map +1 -1
  87. package/dist/core/index.js +4 -4
  88. package/dist/core/index.js.map +1 -1
  89. package/dist/core/index.native.js +4 -4
  90. package/dist/core/index.native.js.map +1 -1
  91. package/dist/core/index.workerd.js +4 -4
  92. package/dist/core/index.workerd.js.map +1 -1
  93. package/dist/crypto/index.d.ts +7 -7
  94. package/dist/crypto/index.d.ts.map +1 -1
  95. package/dist/datetime/index.d.ts +4 -4
  96. package/dist/datetime/index.d.ts.map +1 -1
  97. package/dist/email/brevo/index.d.ts +4 -4
  98. package/dist/email/brevo/index.d.ts.map +1 -1
  99. package/dist/email/core/index.d.ts +15 -11
  100. package/dist/email/core/index.d.ts.map +1 -1
  101. package/dist/email/core/index.js +12 -35
  102. package/dist/email/core/index.js.map +1 -1
  103. package/dist/email/smtp/index.d.ts +12 -12
  104. package/dist/email/smtp/index.d.ts.map +1 -1
  105. package/dist/email/smtp/index.js +7 -4
  106. package/dist/email/smtp/index.js.map +1 -1
  107. package/dist/fake/index.d.ts +4 -8
  108. package/dist/fake/index.d.ts.map +1 -1
  109. package/dist/fake/index.js +55 -889
  110. package/dist/fake/index.js.map +1 -1
  111. package/dist/lock/core/index.d.ts +13 -13
  112. package/dist/lock/core/index.d.ts.map +1 -1
  113. package/dist/lock/core/index.js +2 -2
  114. package/dist/lock/core/index.js.map +1 -1
  115. package/dist/lock/redis/index.d.ts +4 -4
  116. package/dist/lock/redis/index.d.ts.map +1 -1
  117. package/dist/logger/index.d.ts +16 -15
  118. package/dist/logger/index.d.ts.map +1 -1
  119. package/dist/logger/index.js +5 -2
  120. package/dist/logger/index.js.map +1 -1
  121. package/dist/mcp/index.d.ts +11 -11
  122. package/dist/mcp/index.d.ts.map +1 -1
  123. package/dist/mcp/index.js +2 -2
  124. package/dist/mcp/index.js.map +1 -1
  125. package/dist/orm/core/index.browser.js +11 -1
  126. package/dist/orm/core/index.browser.js.map +1 -1
  127. package/dist/orm/core/index.bun.js +53 -16
  128. package/dist/orm/core/index.bun.js.map +1 -1
  129. package/dist/orm/core/index.d.ts +95 -51
  130. package/dist/orm/core/index.d.ts.map +1 -1
  131. package/dist/orm/core/index.js +55 -14
  132. package/dist/orm/core/index.js.map +1 -1
  133. package/dist/orm/postgres/index.bun.js +17 -11
  134. package/dist/orm/postgres/index.bun.js.map +1 -1
  135. package/dist/orm/postgres/index.d.ts +21 -15
  136. package/dist/orm/postgres/index.d.ts.map +1 -1
  137. package/dist/orm/postgres/index.js +19 -13
  138. package/dist/orm/postgres/index.js.map +1 -1
  139. package/dist/queue/core/index.d.ts +14 -14
  140. package/dist/queue/core/index.d.ts.map +1 -1
  141. package/dist/queue/core/index.js +2 -2
  142. package/dist/queue/core/index.js.map +1 -1
  143. package/dist/queue/core/index.workerd.js +2 -2
  144. package/dist/queue/core/index.workerd.js.map +1 -1
  145. package/dist/queue/redis/index.d.ts +4 -4
  146. package/dist/queue/redis/index.d.ts.map +1 -1
  147. package/dist/queue/redis/index.js +2 -2
  148. package/dist/queue/redis/index.js.map +1 -1
  149. package/dist/react/auth/index.d.ts +9 -9
  150. package/dist/react/auth/index.d.ts.map +1 -1
  151. package/dist/react/core/index.d.ts +6 -6
  152. package/dist/react/core/index.d.ts.map +1 -1
  153. package/dist/react/core/index.js +5 -4
  154. package/dist/react/core/index.js.map +1 -1
  155. package/dist/react/form/index.d.ts +4 -4
  156. package/dist/react/form/index.d.ts.map +1 -1
  157. package/dist/react/head/index.d.ts +4 -4
  158. package/dist/react/head/index.d.ts.map +1 -1
  159. package/dist/react/i18n/index.d.ts +9 -9
  160. package/dist/react/i18n/index.d.ts.map +1 -1
  161. package/dist/react/intro/index.d.ts +2 -2
  162. package/dist/react/intro/index.d.ts.map +1 -1
  163. package/dist/react/intro/index.js +3 -4
  164. package/dist/react/intro/index.js.map +1 -1
  165. package/dist/react/router/index.browser.js +4 -5
  166. package/dist/react/router/index.browser.js.map +1 -1
  167. package/dist/react/router/index.d.ts +215 -215
  168. package/dist/react/router/index.d.ts.map +1 -1
  169. package/dist/react/router/index.js +6 -7
  170. package/dist/react/router/index.js.map +1 -1
  171. package/dist/react/testing/index.d.ts +2 -2
  172. package/dist/react/testing/index.d.ts.map +1 -1
  173. package/dist/react/testing/index.js +2 -4
  174. package/dist/react/testing/index.js.map +1 -1
  175. package/dist/redis/index.d.ts +19 -19
  176. package/dist/redis/index.d.ts.map +1 -1
  177. package/dist/retry/index.d.ts +4 -4
  178. package/dist/retry/index.d.ts.map +1 -1
  179. package/dist/scheduler/index.d.ts +13 -13
  180. package/dist/scheduler/index.d.ts.map +1 -1
  181. package/dist/scheduler/index.js +2 -2
  182. package/dist/scheduler/index.js.map +1 -1
  183. package/dist/scheduler/index.workerd.js +2 -2
  184. package/dist/scheduler/index.workerd.js.map +1 -1
  185. package/dist/security/index.browser.js +1 -1
  186. package/dist/security/index.browser.js.map +1 -1
  187. package/dist/security/index.d.ts +47 -47
  188. package/dist/security/index.d.ts.map +1 -1
  189. package/dist/security/index.js +9 -12
  190. package/dist/security/index.js.map +1 -1
  191. package/dist/server/auth/index.d.ts +170 -169
  192. package/dist/server/auth/index.d.ts.map +1 -1
  193. package/dist/server/auth/index.js +16 -2
  194. package/dist/server/auth/index.js.map +1 -1
  195. package/dist/server/cookies/index.d.ts +7 -7
  196. package/dist/server/cookies/index.d.ts.map +1 -1
  197. package/dist/server/core/index.d.ts +76 -76
  198. package/dist/server/core/index.d.ts.map +1 -1
  199. package/dist/server/core/index.js +23 -17
  200. package/dist/server/core/index.js.map +1 -1
  201. package/dist/server/cors/index.d.ts +13 -13
  202. package/dist/server/cors/index.d.ts.map +1 -1
  203. package/dist/server/cors/index.js +2 -2
  204. package/dist/server/cors/index.js.map +1 -1
  205. package/dist/server/etag/index.d.ts +9 -9
  206. package/dist/server/etag/index.d.ts.map +1 -1
  207. package/dist/server/health/index.d.ts +20 -20
  208. package/dist/server/health/index.d.ts.map +1 -1
  209. package/dist/server/links/index.browser.js +2 -2
  210. package/dist/server/links/index.browser.js.map +1 -1
  211. package/dist/server/links/index.d.ts +66 -66
  212. package/dist/server/links/index.d.ts.map +1 -1
  213. package/dist/server/links/index.js +4 -4
  214. package/dist/server/links/index.js.map +1 -1
  215. package/dist/server/metrics/index.d.ts +7 -7
  216. package/dist/server/metrics/index.d.ts.map +1 -1
  217. package/dist/server/proxy/index.d.ts +5 -5
  218. package/dist/server/proxy/index.d.ts.map +1 -1
  219. package/dist/server/rate-limit/index.d.ts +12 -12
  220. package/dist/server/rate-limit/index.d.ts.map +1 -1
  221. package/dist/server/rate-limit/index.js +2 -2
  222. package/dist/server/rate-limit/index.js.map +1 -1
  223. package/dist/server/static/index.d.ts +5 -5
  224. package/dist/server/static/index.d.ts.map +1 -1
  225. package/dist/server/swagger/index.d.ts +7 -7
  226. package/dist/server/swagger/index.d.ts.map +1 -1
  227. package/dist/server/swagger/index.js +2 -2
  228. package/dist/server/swagger/index.js.map +1 -1
  229. package/dist/sms/index.d.ts +11 -7
  230. package/dist/sms/index.d.ts.map +1 -1
  231. package/dist/sms/index.js +9 -15
  232. package/dist/sms/index.js.map +1 -1
  233. package/dist/system/index.d.ts +4 -4
  234. package/dist/system/index.d.ts.map +1 -1
  235. package/dist/topic/core/index.d.ts +6 -6
  236. package/dist/topic/core/index.d.ts.map +1 -1
  237. package/dist/topic/redis/index.d.ts +7 -7
  238. package/dist/topic/redis/index.d.ts.map +1 -1
  239. package/dist/topic/redis/index.js +2 -2
  240. package/dist/topic/redis/index.js.map +1 -1
  241. package/dist/websocket/index.d.ts +36 -36
  242. package/dist/websocket/index.d.ts.map +1 -1
  243. package/dist/websocket/index.js +2 -2
  244. package/dist/websocket/index.js.map +1 -1
  245. package/package.json +37 -32
  246. package/src/api/files/{controllers → __tests__}/FileController.spec.ts +189 -143
  247. package/src/api/files/{services → __tests__}/FileService.spec.ts +50 -30
  248. package/src/api/files/controllers/FileController.ts +6 -0
  249. package/src/api/jobs/{services → __tests__}/JobService.spec.ts +1 -1
  250. package/src/api/jobs/providers/JobProvider.ts +3 -3
  251. package/src/api/keys/{services → __tests__}/ApiKeyService.spec.ts +1 -1
  252. package/src/api/organizations/__tests__/OrganizationService.spec.ts +193 -0
  253. package/src/api/organizations/controllers/AdminOrganizationController.ts +103 -0
  254. package/src/api/organizations/entities/organizations.ts +20 -0
  255. package/src/api/organizations/index.browser.ts +10 -0
  256. package/src/api/organizations/index.ts +31 -0
  257. package/src/api/organizations/schemas/createOrganizationSchema.ts +10 -0
  258. package/src/api/organizations/schemas/organizationQuerySchema.ts +10 -0
  259. package/src/api/organizations/schemas/organizationResourceSchema.ts +6 -0
  260. package/src/api/organizations/schemas/updateOrganizationSchema.ts +7 -0
  261. package/src/api/organizations/services/OrganizationService.ts +75 -0
  262. package/src/api/parameters/services/ParameterProvider.ts +6 -1
  263. package/src/api/users/__tests__/$realm.spec.ts +191 -0
  264. package/src/api/users/__tests__/RealmProvider.spec.ts +53 -0
  265. package/src/api/users/__tests__/SessionService.spec.ts +778 -0
  266. package/src/api/users/{jobs → __tests__}/UserJobs.spec.ts +1 -1
  267. package/src/api/users/atoms/realmAuthSettingsAtom.ts +24 -0
  268. package/src/api/users/controllers/RealmController.ts +5 -11
  269. package/src/api/users/entities/users.ts +9 -3
  270. package/src/api/users/index.ts +23 -3
  271. package/src/api/users/primitives/$realm.ts +23 -11
  272. package/src/api/users/providers/RealmProvider.ts +23 -3
  273. package/src/api/users/services/RegistrationService.ts +3 -2
  274. package/src/api/users/services/SessionService.ts +249 -8
  275. package/src/api/users/services/UserService.ts +1 -1
  276. package/src/api/verifications/{jobs → __tests__}/VerificationJobs.spec.ts +4 -2
  277. package/src/api/verifications/parameters/VerificationParameters.ts +2 -2
  278. package/src/billing/__tests__/BillingService.spec.ts +136 -0
  279. package/src/billing/__tests__/PaymentMethodService.spec.ts +78 -0
  280. package/src/billing/controllers/AdminBillingController.ts +149 -0
  281. package/src/billing/controllers/BillingController.ts +108 -0
  282. package/src/billing/entities/paymentIntents.ts +34 -0
  283. package/src/billing/entities/paymentMethods.ts +24 -0
  284. package/src/billing/entities/refunds.ts +22 -0
  285. package/src/billing/errors/BillingError.ts +5 -0
  286. package/src/billing/index.ts +76 -0
  287. package/src/billing/providers/BillingProvider.ts +79 -0
  288. package/src/billing/providers/MemoryBillingProvider.ts +139 -0
  289. package/src/billing/schemas/intentSchemas.ts +60 -0
  290. package/src/billing/schemas/paymentMethodSchemas.ts +13 -0
  291. package/src/billing/schemas/refundSchemas.ts +6 -0
  292. package/src/billing/services/BillingService.ts +325 -0
  293. package/src/billing/services/PaymentMethodService.ts +82 -0
  294. package/src/bin/index.ts +0 -2
  295. package/src/bucket/providers/LocalFileStorageProvider.ts +2 -2
  296. package/src/cache/core/{primitives → __tests__}/$cache.middleware.spec.ts +1 -1
  297. package/src/cache/core/{providers → __tests__}/MemoryCacheProvider.spec.ts +1 -1
  298. package/src/cache/core/primitives/$cache.ts +2 -2
  299. package/src/cache/redis/providers/RedisCacheProvider.ts +2 -2
  300. package/src/cli/config/defineConfig.ts +20 -0
  301. package/src/cli/core/{services → __tests__}/ProjectScaffolder.spec.ts +1 -1
  302. package/src/cli/core/{commands/gen → __tests__}/changelog.spec.ts +1 -1
  303. package/src/cli/core/{commands → __tests__}/init.spec.ts +4 -12
  304. package/src/cli/core/assets.ts +0 -1
  305. package/src/cli/core/atoms/devOptions.ts +0 -5
  306. package/src/cli/core/commands/build.ts +2 -2
  307. package/src/cli/core/commands/dev.ts +165 -30
  308. package/src/cli/core/commands/gen/changelog.ts +2 -2
  309. package/src/cli/core/commands/init.ts +2 -7
  310. package/src/cli/core/commands/verify.ts +0 -1
  311. package/src/cli/core/providers/AppEntryProvider.ts +2 -2
  312. package/src/cli/core/providers/ViteDevServerProvider.ts +53 -46
  313. package/src/cli/core/services/PackageManagerUtils.ts +8 -3
  314. package/src/cli/core/services/ProjectScaffolder.ts +20 -20
  315. package/src/cli/core/tasks/BuildClientTask.ts +8 -0
  316. package/src/cli/core/tasks/BuildServerTask.ts +17 -4
  317. package/src/cli/core/templates/alephaConfigTs.ts +0 -6
  318. package/src/cli/core/templates/webAdminDashboardTsx.ts +17 -0
  319. package/src/cli/core/templates/webAppRouterTs.ts +85 -2
  320. package/src/cli/devtools/atoms/devtoolsOptions.ts +26 -0
  321. package/src/cli/devtools/index.ts +194 -0
  322. package/src/cli/platform/{adapters → __tests__}/CloudflareAdapter.spec.ts +2 -2
  323. package/src/cli/platform/{providers → __tests__}/GitHubSecretStore.spec.ts +1 -1
  324. package/src/cli/platform/{services → __tests__}/NamingService.spec.ts +1 -1
  325. package/src/cli/platform/{providers → __tests__}/PlatformCacheProvider.spec.ts +1 -1
  326. package/src/cli/platform/{services → __tests__}/PlatformInspector.spec.ts +1 -1
  327. package/src/cli/platform/{services → __tests__}/PlatformOrchestrator.spec.ts +3 -3
  328. package/src/cli/platform/{services → __tests__}/SecretFilterService.spec.ts +1 -1
  329. package/src/cli/platform/{commands → __tests__}/SecretsCommand.spec.ts +1 -1
  330. package/src/cli/platform/{adapters → __tests__}/VercelAdapter.spec.ts +2 -2
  331. package/src/cli/platform/atoms/platformOptions.ts +2 -10
  332. package/src/cli/platform/commands/SecretsCommand.ts +2 -2
  333. package/src/cli/platform/commands/platform.ts +2 -11
  334. package/src/cli/platform/index.ts +34 -11
  335. package/src/cli/platform/services/PlatformInspector.ts +2 -2
  336. package/src/cli/platform/services/PlatformOrchestrator.ts +0 -9
  337. package/src/cli/vendor/__tests__/VendorService.spec.ts +407 -0
  338. package/src/cli/vendor/atoms/vendorOptions.ts +41 -0
  339. package/src/cli/vendor/commands/VendorCommand.ts +204 -0
  340. package/src/cli/vendor/index.ts +43 -0
  341. package/src/cli/vendor/services/VendorService.ts +338 -0
  342. package/src/command/{providers → __tests__}/CliProvider.spec.ts +1 -1
  343. package/src/command/{helpers → __tests__}/EnvUtils.spec.ts +1 -1
  344. package/src/command/providers/CliProvider.ts +2 -2
  345. package/src/core/{primitives → __tests__}/$atom.spec.ts +2 -2
  346. package/src/core/{primitives → __tests__}/$memoize.spec.ts +1 -1
  347. package/src/core/{primitives → __tests__}/$mode.spec.ts +1 -1
  348. package/src/core/{primitives → __tests__}/$pipeline.spec.ts +1 -1
  349. package/src/core/{primitives → __tests__}/$scope.spec.ts +2 -2
  350. package/src/core/{providers → __tests__}/KeylessJsonSchemaCodec.spec.ts +1 -1
  351. package/src/core/{providers → __tests__}/SchemaValidator.spec.ts +1 -1
  352. package/src/core/{helpers → __tests__}/jsonSchemaToTypeBox.spec.ts +1 -1
  353. package/src/core/index.shared.ts +1 -1
  354. package/src/core/primitives/{$use.ts → $state.ts} +4 -4
  355. package/src/crypto/{providers → __tests__}/BrowserCryptoProvider.browser.spec.ts +1 -1
  356. package/src/crypto/{providers → __tests__}/CryptoProvider.spec.ts +1 -1
  357. package/src/datetime/{primitives → __tests__}/$debounce.spec.ts +1 -1
  358. package/src/datetime/{primitives → __tests__}/$throttle.spec.ts +1 -1
  359. package/src/datetime/{primitives → __tests__}/$timeout.spec.ts +1 -1
  360. package/src/email/brevo/{providers → __tests__}/BrevoEmailProvider.spec.ts +1 -1
  361. package/src/email/core/{providers → __tests__}/LocalEmailProvider.spec.ts +39 -150
  362. package/src/email/core/providers/LocalEmailProvider.ts +13 -51
  363. package/src/email/smtp/providers/NodemailerEmailProvider.ts +2 -2
  364. package/src/lock/core/{primitives → __tests__}/$lock.middleware.spec.ts +1 -1
  365. package/src/lock/core/primitives/$lock.ts +2 -2
  366. package/src/logger/index.ts +10 -4
  367. package/src/mcp/transports/SseMcpTransport.ts +2 -2
  368. package/src/orm/__tests__/ModelBuilder-tests.ts +53 -0
  369. package/src/orm/__tests__/ModelBuilder.spec.ts +80 -0
  370. package/src/orm/__tests__/organization-tests.ts +200 -0
  371. package/src/orm/__tests__/organization.spec.ts +103 -0
  372. package/src/orm/core/{providers/drivers → __tests__}/BunSqliteProvider.bun.spec.ts +5 -2
  373. package/src/orm/core/constants/PG_SYMBOLS.ts +2 -0
  374. package/src/orm/core/index.shared.ts +1 -0
  375. package/src/orm/core/primitives/$entity.ts +31 -0
  376. package/src/orm/core/providers/DatabaseTypeProvider.ts +11 -0
  377. package/src/orm/core/providers/DrizzleKitProvider.ts +1 -1
  378. package/src/orm/core/providers/drivers/BunSqliteProvider.ts +2 -2
  379. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +3 -3
  380. package/src/orm/core/services/ModelBuilder.ts +11 -0
  381. package/src/orm/core/services/QueryManager.ts +16 -2
  382. package/src/orm/core/services/Repository.ts +70 -10
  383. package/src/orm/postgres/{providers → __tests__}/BunPostgresProvider.bun.spec.ts +1 -1
  384. package/src/orm/postgres/services/PostgresModelBuilder.ts +9 -1
  385. package/src/queue/core/providers/WorkerProvider.ts +2 -2
  386. package/src/queue/redis/providers/RedisQueueProvider.ts +2 -2
  387. package/src/react/core/{hooks → __tests__}/useAction.browser.spec.tsx +1 -1
  388. package/src/react/core/hooks/useAction.ts +7 -6
  389. package/src/react/head/{providers → __tests__}/BrowserHeadProvider.browser.spec.ts +1 -1
  390. package/src/react/head/{helpers → __tests__}/SeoExpander.spec.ts +1 -1
  391. package/src/react/i18n/{providers → __tests__}/I18nProvider.spec.ts +1 -1
  392. package/src/react/i18n/{hooks → __tests__}/useI18n.browser.spec.tsx +1 -1
  393. package/src/react/intro/components/GettingStartedDevtoolsSlide.tsx +3 -6
  394. package/src/react/router/{providers → __tests__}/ReactBrowserProvider.browser.spec.ts +1 -1
  395. package/src/react/router/providers/ReactBrowserProvider.ts +2 -2
  396. package/src/react/router/providers/ReactPageProvider.ts +2 -2
  397. package/src/react/router/providers/ReactServerProvider.ts +3 -3
  398. package/src/redis/{providers → __tests__}/BunRedisProvider.bun.spec.ts +4 -4
  399. package/src/retry/{primitives → __tests__}/$retry.middleware.spec.ts +1 -1
  400. package/src/router/{TemplatedPathParser.spec.ts → __tests__/TemplatedPathParser.spec.ts} +1 -1
  401. package/src/scheduler/primitives/$scheduler.ts +2 -2
  402. package/src/security/{primitives → __tests__}/$secure-browser.spec.ts +1 -1
  403. package/src/security/{primitives → __tests__}/$secure.spec.ts +1 -1
  404. package/src/security/primitives/$issuer.ts +1 -1
  405. package/src/security/providers/JwtProvider.ts +6 -10
  406. package/src/security/providers/SecurityProvider.ts +6 -11
  407. package/src/security/schemas/userAccountInfoSchema.ts +3 -3
  408. package/src/server/auth/providers/ServerAuthProvider.ts +24 -2
  409. package/src/server/cookies/{services → __tests__}/CookieParser.spec.ts +1 -1
  410. package/src/server/core/{primitives → __tests__}/$circuit.spec.ts +1 -1
  411. package/src/server/core/{providers → __tests__}/NodeHttpServerProvider.spec.ts +1 -1
  412. package/src/server/core/{providers → __tests__}/ServerBodyParserProvider.spec.ts +31 -1
  413. package/src/server/core/{providers → __tests__}/ServerCompressProvider.spec.ts +1 -1
  414. package/src/server/core/{providers → __tests__}/ServerHelmetProvider.spec.ts +4 -1
  415. package/src/server/core/{providers → __tests__}/ServerMultipartProvider.spec.ts +1 -1
  416. package/src/server/core/{services → __tests__}/ServerRequestParser.spec.ts +1 -1
  417. package/src/server/core/primitives/$action.ts +2 -2
  418. package/src/server/core/primitives/$sse.ts +2 -2
  419. package/src/server/core/providers/ServerBodyParserProvider.ts +21 -12
  420. package/src/server/core/providers/ServerCompressProvider.ts +2 -2
  421. package/src/server/core/providers/ServerHelmetProvider.ts +2 -2
  422. package/src/server/core/providers/ServerMultipartProvider.ts +2 -2
  423. package/src/server/core/providers/ServerRouterProvider.ts +1 -5
  424. package/src/server/cors/{primitives → __tests__}/$cors.spec.ts +1 -1
  425. package/src/server/cors/providers/ServerCorsProvider.ts +2 -2
  426. package/src/server/links/{services → __tests__}/BatchCollector.spec.ts +1 -1
  427. package/src/server/links/providers/LinkProvider.ts +2 -2
  428. package/src/server/links/providers/RemotePrimitiveProvider.ts +2 -2
  429. package/src/server/links/providers/ServerLinksProvider.ts +2 -2
  430. package/src/server/rate-limit/{primitives → __tests__}/$rateLimit.spec.ts +1 -1
  431. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +2 -2
  432. package/src/server/swagger/providers/ServerSwaggerProvider.ts +2 -2
  433. package/src/sms/{providers → __tests__}/LocalSmsProvider.spec.ts +35 -29
  434. package/src/sms/providers/LocalSmsProvider.ts +13 -24
  435. package/src/system/{providers → __tests__}/MemoryFileSystemProvider.spec.ts +1 -1
  436. package/src/system/{providers → __tests__}/MemoryShellProvider.spec.ts +1 -1
  437. package/src/topic/redis/providers/RedisTopicProvider.ts +2 -2
  438. package/src/websocket/{services → __tests__}/RoomManager.spec.ts +1 -1
  439. package/src/websocket/providers/NodeWebSocketServerProvider.ts +2 -2
  440. package/tsconfig.base.json +1 -0
  441. package/assets/devtools-ui/200.html +0 -10
  442. package/assets/devtools-ui/200.html.br +0 -0
  443. package/assets/devtools-ui/404.html +0 -10
  444. package/assets/devtools-ui/404.html.br +0 -0
  445. package/assets/devtools-ui/CNAME +0 -1
  446. package/assets/devtools-ui/asset.CHpVij2M.css +0 -1
  447. package/assets/devtools-ui/asset.CHpVij2M.css.br +0 -0
  448. package/assets/devtools-ui/asset.DJ-i0UDz.css +0 -1
  449. package/assets/devtools-ui/asset.DJ-i0UDz.css.br +0 -0
  450. package/assets/devtools-ui/chunk.1jwpJORo.js +0 -1
  451. package/assets/devtools-ui/chunk.1jwpJORo.js.br +0 -0
  452. package/assets/devtools-ui/chunk.B0r2wfUL.js +0 -1
  453. package/assets/devtools-ui/chunk.B0r2wfUL.js.br +0 -0
  454. package/assets/devtools-ui/chunk.BScN4dVR.js +0 -84
  455. package/assets/devtools-ui/chunk.BScN4dVR.js.br +0 -0
  456. package/assets/devtools-ui/chunk.BispuoY4.js +0 -1
  457. package/assets/devtools-ui/chunk.BispuoY4.js.br +0 -0
  458. package/assets/devtools-ui/chunk.BtrPUUd7.js +0 -2
  459. package/assets/devtools-ui/chunk.BtrPUUd7.js.br +0 -0
  460. package/assets/devtools-ui/chunk.C-KMHgqf.js +0 -1
  461. package/assets/devtools-ui/chunk.C-KMHgqf.js.br +0 -0
  462. package/assets/devtools-ui/chunk.C2zQ3CF6.js +0 -7
  463. package/assets/devtools-ui/chunk.C2zQ3CF6.js.br +0 -0
  464. package/assets/devtools-ui/chunk.C619McpO.js +0 -1
  465. package/assets/devtools-ui/chunk.C619McpO.js.br +0 -0
  466. package/assets/devtools-ui/chunk.C9OsYsVl.js +0 -1
  467. package/assets/devtools-ui/chunk.C9OsYsVl.js.br +0 -3
  468. package/assets/devtools-ui/chunk.CAC_-151.js +0 -1
  469. package/assets/devtools-ui/chunk.CAC_-151.js.br +0 -0
  470. package/assets/devtools-ui/chunk.CCmesWfx.js +0 -1
  471. package/assets/devtools-ui/chunk.CCmesWfx.js.br +0 -0
  472. package/assets/devtools-ui/chunk.CFQDmrcV.js +0 -1
  473. package/assets/devtools-ui/chunk.CFQDmrcV.js.br +0 -0
  474. package/assets/devtools-ui/chunk.CgM71Zau.js +0 -1
  475. package/assets/devtools-ui/chunk.CgM71Zau.js.br +0 -0
  476. package/assets/devtools-ui/chunk.CmHq336a.js +0 -1
  477. package/assets/devtools-ui/chunk.CmHq336a.js.br +0 -0
  478. package/assets/devtools-ui/chunk.CthNMCar.js +0 -1
  479. package/assets/devtools-ui/chunk.CthNMCar.js.br +0 -0
  480. package/assets/devtools-ui/chunk.D2brVJP1.js +0 -1
  481. package/assets/devtools-ui/chunk.D2brVJP1.js.br +0 -0
  482. package/assets/devtools-ui/chunk.DgBKGkiw.js +0 -1
  483. package/assets/devtools-ui/chunk.DgBKGkiw.js.br +0 -0
  484. package/assets/devtools-ui/chunk.NNHHCQsa.js +0 -1
  485. package/assets/devtools-ui/chunk.NNHHCQsa.js.br +0 -0
  486. package/assets/devtools-ui/chunk._CDKKWMo.js +0 -1
  487. package/assets/devtools-ui/chunk._CDKKWMo.js.br +0 -0
  488. package/assets/devtools-ui/entry.B_nOjAod.js +0 -2
  489. package/assets/devtools-ui/entry.B_nOjAod.js.br +0 -0
  490. package/assets/devtools-ui/index.html +0 -10
  491. package/assets/devtools-ui/index.html.br +0 -0
  492. package/dist/devtools/index.browser.js +0 -224
  493. package/dist/devtools/index.browser.js.map +0 -1
  494. package/dist/devtools/index.d.ts +0 -499
  495. package/dist/devtools/index.d.ts.map +0 -1
  496. package/dist/devtools/index.js +0 -782
  497. package/dist/devtools/index.js.map +0 -1
  498. package/dist/mqtt/index.d.ts +0 -164
  499. package/dist/mqtt/index.d.ts.map +0 -1
  500. package/dist/mqtt/index.js +0 -214
  501. package/dist/mqtt/index.js.map +0 -1
  502. package/dist/topic/mqtt/index.d.ts +0 -87
  503. package/dist/topic/mqtt/index.d.ts.map +0 -1
  504. package/dist/topic/mqtt/index.js +0 -88
  505. package/dist/topic/mqtt/index.js.map +0 -1
  506. package/src/api/users/parameters/UserParameters.ts +0 -23
  507. package/src/api/users/services/SessionService.spec.ts +0 -303
  508. package/src/cli/platform/adapters/DockerAdapter.spec.ts +0 -378
  509. package/src/cli/platform/adapters/DockerAdapter.ts +0 -417
  510. package/src/cli/platform/services/DockerComposeGenerator.spec.ts +0 -490
  511. package/src/cli/platform/services/DockerComposeGenerator.ts +0 -353
  512. package/src/cli/platform/services/DockerSshService.spec.ts +0 -47
  513. package/src/cli/platform/services/DockerSshService.ts +0 -61
  514. package/src/devtools/__tests__/DevCollectorProvider.spec.ts +0 -7
  515. package/src/devtools/assets.ts +0 -6
  516. package/src/devtools/entities/logs.ts +0 -21
  517. package/src/devtools/index.browser.ts +0 -11
  518. package/src/devtools/index.shared.ts +0 -15
  519. package/src/devtools/index.ts +0 -39
  520. package/src/devtools/providers/DevToolsMetadataProvider.ts +0 -459
  521. package/src/devtools/providers/DevToolsProvider.ts +0 -280
  522. package/src/devtools/schemas/DevActionMetadata.ts +0 -30
  523. package/src/devtools/schemas/DevAtomMetadata.ts +0 -26
  524. package/src/devtools/schemas/DevBucketMetadata.ts +0 -11
  525. package/src/devtools/schemas/DevCacheMetadata.ts +0 -10
  526. package/src/devtools/schemas/DevEntityMetadata.ts +0 -60
  527. package/src/devtools/schemas/DevEnvMetadata.ts +0 -22
  528. package/src/devtools/schemas/DevMetadata.ts +0 -47
  529. package/src/devtools/schemas/DevModuleMetadata.ts +0 -8
  530. package/src/devtools/schemas/DevPageMetadata.ts +0 -24
  531. package/src/devtools/schemas/DevProviderMetadata.ts +0 -10
  532. package/src/devtools/schemas/DevQueueMetadata.ts +0 -10
  533. package/src/devtools/schemas/DevRealmMetadata.ts +0 -19
  534. package/src/devtools/schemas/DevRouteMetadata.ts +0 -8
  535. package/src/devtools/schemas/DevSchedulerMetadata.ts +0 -11
  536. package/src/devtools/schemas/DevTopicMetadata.ts +0 -11
  537. package/src/mqtt/index.ts +0 -32
  538. package/src/mqtt/providers/MqttClientProvider.ts +0 -63
  539. package/src/mqtt/providers/MqttJsClientProvider.spec.ts +0 -165
  540. package/src/mqtt/providers/MqttJsClientProvider.ts +0 -309
  541. package/src/topic/mqtt/index.ts +0 -30
  542. package/src/topic/mqtt/providers/MqttTopicProvider.spec.ts +0 -160
  543. package/src/topic/mqtt/providers/MqttTopicProvider.ts +0 -146
  544. /package/src/api/audits/{primitives → __tests__}/$audit.spec.ts +0 -0
  545. /package/src/api/audits/{services → __tests__}/AuditService.spec.ts +0 -0
  546. /package/src/api/files/{controllers → __tests__}/AdminFileStatsController.spec.ts +0 -0
  547. /package/src/api/files/{jobs → __tests__}/FileJobs.spec.ts +0 -0
  548. /package/src/api/jobs/{primitives → __tests__}/$job-middleware.spec.ts +0 -0
  549. /package/src/api/parameters/{primitives → __tests__}/$parameter.spec.ts +0 -0
  550. /package/src/api/users/{controllers → __tests__}/AdminIdentityController.spec.ts +0 -0
  551. /package/src/api/users/{controllers → __tests__}/AdminSessionController.spec.ts +0 -0
  552. /package/src/api/users/{controllers → __tests__}/AdminUserController.spec.ts +0 -0
  553. /package/src/api/users/{services → __tests__}/CredentialService.spec.ts +0 -0
  554. /package/src/api/users/{services → __tests__}/RegistrationService.spec.ts +0 -0
  555. /package/src/batch/{primitives → __tests__}/$batch.spec.ts +0 -0
  556. /package/src/batch/{providers → __tests__}/BatchProvider.spec.ts +0 -0
  557. /package/src/bucket/{primitives → __tests__}/$bucket.spec.ts +0 -0
  558. /package/src/bucket/{providers → __tests__}/FileStorageProvider.spec.ts +0 -0
  559. /package/src/bucket/{providers → __tests__}/LocalFileStorageProvider.spec.ts +0 -0
  560. /package/src/bucket/{providers → __tests__}/MemoryFileStorageProvider.spec.ts +0 -0
  561. /package/src/cache/core/{primitives → __tests__}/$cache.spec.ts +0 -0
  562. /package/src/cache/redis/{providers → __tests__}/RedisCacheProvider.spec.ts +0 -0
  563. /package/src/command/{primitives → __tests__}/$command.spec.ts +0 -0
  564. /package/src/command/{helpers → __tests__}/Asker.spec.ts +0 -0
  565. /package/src/command/{helpers → __tests__}/Runner.spec.ts +0 -0
  566. /package/src/core/{primitives → __tests__}/$context.spec.ts +0 -0
  567. /package/src/core/{primitives → __tests__}/$env.spec.ts +0 -0
  568. /package/src/core/{primitives → __tests__}/$hook.spec.ts +0 -0
  569. /package/src/core/{primitives → __tests__}/$inject.spec.ts +0 -0
  570. /package/src/core/{primitives → __tests__}/$module.spec.ts +0 -0
  571. /package/src/core/{providers → __tests__}/CodecManager.spec.ts +0 -0
  572. /package/src/core/{providers → __tests__}/EventManager.spec.ts +0 -0
  573. /package/src/core/{providers → __tests__}/StateManager.spec.ts +0 -0
  574. /package/src/core/{providers → __tests__}/TypeProvider.spec.ts +0 -0
  575. /package/src/datetime/{primitives → __tests__}/$interval.spec.ts +0 -0
  576. /package/src/datetime/{providers → __tests__}/DateTimeProvider.spec.ts +0 -0
  577. /package/src/email/core/{primitives → __tests__}/$email.spec.ts +0 -0
  578. /package/src/fake/{providers → __tests__}/FakeProvider.spec.ts +0 -0
  579. /package/src/lock/core/{providers → __tests__}/MemoryLockProvider.spec.ts +0 -0
  580. /package/src/lock/redis/{providers → __tests__}/RedisLockProvider.spec.ts +0 -0
  581. /package/src/logger/{primitives → __tests__}/$logger.spec.ts +0 -0
  582. /package/src/logger/{services → __tests__}/Logger.spec.ts +0 -0
  583. /package/src/mcp/{primitives → __tests__}/$prompt.spec.ts +0 -0
  584. /package/src/mcp/{primitives → __tests__}/$resource.spec.ts +0 -0
  585. /package/src/mcp/{primitives → __tests__}/$tool.spec.ts +0 -0
  586. /package/src/mcp/{providers → __tests__}/McpServerProvider.spec.ts +0 -0
  587. /package/src/mcp/{helpers → __tests__}/jsonrpc.spec.ts +0 -0
  588. /package/src/orm/core/{helpers → __tests__}/parseQueryString.spec.ts +0 -0
  589. /package/src/queue/core/{primitives → __tests__}/$consumer.spec.ts +0 -0
  590. /package/src/queue/core/{providers → __tests__}/MemoryQueueProvider.spec.ts +0 -0
  591. /package/src/queue/core/{providers → __tests__}/WorkerProvider.spec.ts +0 -0
  592. /package/src/queue/redis/{providers → __tests__}/RedisQueueProvider.spec.ts +0 -0
  593. /package/src/react/form/{hooks → __tests__}/useForm.browser.spec.tsx +0 -0
  594. /package/src/react/head/{hooks → __tests__}/useHead.spec.tsx +0 -0
  595. /package/src/react/i18n/{components → __tests__}/Localize.spec.tsx +0 -0
  596. /package/src/react/router/{primitives → __tests__}/$page.browser.spec.tsx +0 -0
  597. /package/src/react/router/{primitives → __tests__}/$page.middleware.spec.tsx +0 -0
  598. /package/src/react/router/{primitives → __tests__}/$page.spec.tsx +0 -0
  599. /package/src/react/router/{providers → __tests__}/ReactPreloadProvider.spec.ts +0 -0
  600. /package/src/react/router/{providers → __tests__}/ReactServerProvider.spec.tsx +0 -0
  601. /package/src/react/router/{providers → __tests__}/ReactServerTemplateProvider.spec.ts +0 -0
  602. /package/src/retry/{primitives → __tests__}/$retry.spec.ts +0 -0
  603. /package/src/retry/{providers → __tests__}/RetryProvider.spec.ts +0 -0
  604. /package/src/router/{providers → __tests__}/RouterProvider.spec.ts +0 -0
  605. /package/src/security/{primitives → __tests__}/$issuer.spec.ts +0 -0
  606. /package/src/security/{primitives → __tests__}/$permission.spec.ts +0 -0
  607. /package/src/security/{primitives → __tests__}/$role.spec.ts +0 -0
  608. /package/src/security/{primitives → __tests__}/$serviceAccount.spec.ts +0 -0
  609. /package/src/security/{providers → __tests__}/SecurityProvider.spec.ts +0 -0
  610. /package/src/server/cookies/{providers → __tests__}/ServerCookiesProvider.spec.ts +0 -0
  611. /package/src/server/core/{primitives → __tests__}/$action.spec.ts +0 -0
  612. /package/src/server/core/{primitives → __tests__}/$middleware.spec.ts +0 -0
  613. /package/src/server/core/{primitives → __tests__}/$route.spec.ts +0 -0
  614. /package/src/server/core/{primitives → __tests__}/$sse.spec.ts +0 -0
  615. /package/src/server/core/{providers → __tests__}/BunHttpServerProvider.bun.spec.ts +0 -0
  616. /package/src/server/core/{services → __tests__}/HttpClient.spec.ts +0 -0
  617. /package/src/server/core/{providers → __tests__}/ServerLoggerProvider.spec.ts +0 -0
  618. /package/src/server/core/{services → __tests__}/UserAgentParser.spec.ts +0 -0
  619. /package/src/server/cors/{providers → __tests__}/ServerCorsProvider.spec.ts +0 -0
  620. /package/src/server/etag/{providers → __tests__}/ServerEtagProvider.spec.ts +0 -0
  621. /package/src/server/health/{providers → __tests__}/ServerHealthProvider.spec.ts +0 -0
  622. /package/src/server/links/{primitives → __tests__}/$remote.spec.ts +0 -0
  623. /package/src/server/links/{services → __tests__}/BatchEndpoint.spec.ts +0 -0
  624. /package/src/server/links/{providers → __tests__}/LinkProvider.spec.ts +0 -0
  625. /package/src/server/links/{providers → __tests__}/ServerLinksProvider.spec.ts +0 -0
  626. /package/src/server/metrics/{providers → __tests__}/ServerMetricsProvider.spec.ts +0 -0
  627. /package/src/server/proxy/{primitives → __tests__}/$proxy.spec.ts +0 -0
  628. /package/src/server/rate-limit/{providers → __tests__}/ServerRateLimitProvider.spec.ts +0 -0
  629. /package/src/server/static/{primitives → __tests__}/$serve.spec.ts +0 -0
  630. /package/src/server/swagger/{primitives → __tests__}/$swagger.spec.ts +0 -0
  631. /package/src/sms/{primitives → __tests__}/$sms.spec.ts +0 -0
  632. /package/src/sms/{providers → __tests__}/MemorySmsProvider.spec.ts +0 -0
  633. /package/src/system/{services → __tests__}/FileDetector.spec.ts +0 -0
  634. /package/src/system/{providers → __tests__}/NodeFileSystemProvider.spec.ts +0 -0
  635. /package/src/topic/core/{primitives → __tests__}/$subscriber.spec.ts +0 -0
  636. /package/src/topic/core/{providers → __tests__}/MemoryTopicProvider.spec.ts +0 -0
  637. /package/src/topic/redis/{providers → __tests__}/RedisTopicProvider.spec.ts +0 -0
  638. /package/src/websocket/{primitives → __tests__}/$channel.spec.ts +0 -0
@@ -5,7 +5,7 @@ import { AlephaOrmPostgres } from "alepha/orm/postgres";
5
5
  import { describe, test, vi } from "vitest";
6
6
  import { sessions } from "../entities/sessions.ts";
7
7
  import { users } from "../entities/users.ts";
8
- import { UserJobs } from "./UserJobs.ts";
8
+ import { UserJobs } from "../jobs/UserJobs.ts";
9
9
 
10
10
  describe("UserJobs", () => {
11
11
  describe("purgeExpiredSessions", () => {
@@ -89,6 +89,25 @@ export const realmAuthSettingsAtom = $atom({
89
89
  description: "Require at least one special character",
90
90
  }),
91
91
  }),
92
+ loginRateLimit: t.object({
93
+ ipMaxAttempts: t.integer({
94
+ description:
95
+ "Max failed login attempts per IP before temporary lockout",
96
+ default: 15,
97
+ minimum: 1,
98
+ }),
99
+ accountMaxAttempts: t.integer({
100
+ description:
101
+ "Max failed login attempts per account before temporary lockout",
102
+ default: 5,
103
+ minimum: 1,
104
+ }),
105
+ windowMs: t.integer({
106
+ description: "Rate limit window duration in milliseconds",
107
+ default: 15 * 60 * 1000,
108
+ minimum: 1000,
109
+ }),
110
+ }),
92
111
  }),
93
112
  default: {
94
113
  // for a fresh hello world setup, we accept registration and email login
@@ -111,6 +130,11 @@ export const realmAuthSettingsAtom = $atom({
111
130
  requireNumbers: true,
112
131
  requireSpecialCharacters: false,
113
132
  },
133
+ loginRateLimit: {
134
+ ipMaxAttempts: 15,
135
+ accountMaxAttempts: 5,
136
+ windowMs: 15 * 60 * 1000,
137
+ },
114
138
  },
115
139
  });
116
140
 
@@ -23,23 +23,17 @@ export class RealmController {
23
23
  group: this.group,
24
24
  method: "GET",
25
25
  path: `${this.url}/config`,
26
- use: [
27
- $etag({
28
- control: {
29
- maxAge: [24, "hours"],
30
- },
31
- }),
32
- ],
26
+ use: [$etag()],
33
27
  schema: {
34
28
  query: t.object({
35
29
  realmName: t.optional(t.string()),
36
30
  }),
37
31
  response: realmConfigSchema,
38
32
  },
39
- handler: ({ query }) => {
40
- const { name: realmName, settings } = this.realmProvider.getRealm(
41
- query.realmName,
42
- );
33
+ handler: async ({ query }) => {
34
+ const realm = this.realmProvider.getRealm(query.realmName);
35
+ const settings = await realm.getSettings();
36
+ const realmName = realm.name;
43
37
 
44
38
  const authenticationMethods =
45
39
  this.serverAuthProvider.getAuthenticationProviders({
@@ -1,5 +1,5 @@
1
1
  import { type Static, t } from "alepha";
2
- import { $entity, db } from "alepha/orm";
2
+ import { $entity, db, sql } from "alepha/orm";
3
3
 
4
4
  export const DEFAULT_USER_REALM_NAME = "default";
5
5
 
@@ -16,7 +16,7 @@ export const users = $entity({
16
16
  username: t.optional(
17
17
  t.shortText({
18
18
  minLength: 3,
19
- maxLength: 50,
19
+ maxLength: 30,
20
20
  // pattern is handled at the realm settings level
21
21
  }),
22
22
  ),
@@ -32,9 +32,15 @@ export const users = $entity({
32
32
  enabled: db.default(t.boolean(), true),
33
33
 
34
34
  emailVerified: db.default(t.boolean(), false),
35
+
36
+ organizationId: db.organization(),
35
37
  }),
36
38
  indexes: [
37
- { columns: ["realm", "username"], unique: true },
39
+ {
40
+ expressions: (self) => [self.realm, sql`LOWER(${self.username})`],
41
+ unique: true,
42
+ name: "users_realm_username_lower_idx",
43
+ },
38
44
  { columns: ["realm", "email"], unique: true },
39
45
  { columns: ["realm", "phoneNumber"], unique: true },
40
46
  ],
@@ -1,10 +1,13 @@
1
1
  import { $module } from "alepha";
2
- import { AlephaEmail } from "alepha/email";
2
+ import { UserAudits } from "./audits/UserAudits.ts";
3
+ import { UserBuckets } from "./buckets/UserBuckets.ts";
3
4
  import { AdminIdentityController } from "./controllers/AdminIdentityController.ts";
4
5
  import { AdminSessionController } from "./controllers/AdminSessionController.ts";
5
6
  import { AdminUserController } from "./controllers/AdminUserController.ts";
6
7
  import { RealmController } from "./controllers/RealmController.ts";
7
8
  import { UserController } from "./controllers/UserController.ts";
9
+ import { UserJobs } from "./jobs/UserJobs.ts";
10
+ import { UserNotifications } from "./notifications/UserNotifications.ts";
8
11
  import { RealmProvider } from "./providers/RealmProvider.ts";
9
12
  import { CredentialService } from "./services/CredentialService.ts";
10
13
  import { IdentityService } from "./services/IdentityService.ts";
@@ -28,7 +31,6 @@ export * from "./entities/sessions.ts";
28
31
  export * from "./entities/users.ts";
29
32
  export * from "./jobs/UserJobs.ts";
30
33
  export * from "./notifications/UserNotifications.ts";
31
- export * from "./parameters/UserParameters.ts";
32
34
  export * from "./primitives/$realm.ts";
33
35
  export * from "./providers/RealmProvider.ts";
34
36
  export * from "./schemas/completePasswordResetRequestSchema.ts";
@@ -74,7 +76,6 @@ export * from "./services/UserService.ts";
74
76
  export const AlephaApiUsers = $module({
75
77
  name: "alepha.api.users",
76
78
  services: [
77
- AlephaEmail,
78
79
  RealmProvider,
79
80
  SessionService,
80
81
  SessionCrudService,
@@ -87,5 +88,24 @@ export const AlephaApiUsers = $module({
87
88
  AdminSessionController,
88
89
  AdminIdentityController,
89
90
  RealmController,
91
+ UserJobs,
92
+ UserNotifications,
93
+ UserAudits,
94
+ UserBuckets,
90
95
  ],
96
+ register: (alepha) => {
97
+ alepha
98
+ .with(RealmProvider)
99
+ .with(SessionService)
100
+ .with(SessionCrudService)
101
+ .with(CredentialService)
102
+ .with(RegistrationService)
103
+ .with(UserService)
104
+ .with(IdentityService)
105
+ .with(UserController)
106
+ .with(AdminUserController)
107
+ .with(AdminSessionController)
108
+ .with(AdminIdentityController)
109
+ .with(RealmController);
110
+ },
91
111
  });
@@ -1,6 +1,6 @@
1
1
  import { $context } from "alepha";
2
2
  import { AlephaApiKeys, ApiKeyService } from "alepha/api/keys";
3
- import { AlephaApiParameters } from "alepha/api/parameters";
3
+ import { $parameter, AlephaApiParameters } from "alepha/api/parameters";
4
4
  import { AlephaApiVerification } from "alepha/api/verifications";
5
5
  import type { Repository } from "alepha/orm";
6
6
  import {
@@ -21,7 +21,10 @@ import {
21
21
  type WithLinkFn,
22
22
  type WithLoginFn,
23
23
  } from "alepha/server/auth";
24
- import type { RealmAuthSettings } from "../atoms/realmAuthSettingsAtom.ts";
24
+ import {
25
+ type RealmAuthSettings,
26
+ realmAuthSettingsAtom,
27
+ } from "../atoms/realmAuthSettingsAtom.ts";
25
28
  import { UserAudits } from "../audits/UserAudits.ts";
26
29
  import { UserBuckets } from "../buckets/UserBuckets.ts";
27
30
  import type { identities } from "../entities/identities.ts";
@@ -60,7 +63,7 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
60
63
 
61
64
  // Merge features with defaults
62
65
  const features: RealmFeatures = {
63
- sessionPurge: false,
66
+ jobs: false,
64
67
  notifications: false,
65
68
  apiKeys: false,
66
69
  parameters: false,
@@ -92,7 +95,7 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
92
95
  alepha.with(UserAudits);
93
96
  }
94
97
 
95
- if (features.sessionPurge) {
98
+ if (features.jobs) {
96
99
  alepha.with(UserJobs);
97
100
  }
98
101
 
@@ -101,11 +104,6 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
101
104
  alepha.with(AlephaApiVerification);
102
105
  }
103
106
 
104
- if (features.parameters) {
105
- // for now, we don't have $parameter related to users, we just register the module
106
- alepha.with(AlephaApiParameters);
107
- }
108
-
109
107
  // -------------------------------------------------------------------------------------------------------------------
110
108
 
111
109
  // Collect custom resolvers that will be registered during $issuer.onInit()
@@ -210,6 +208,18 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
210
208
  alepha.with(() => auth);
211
209
  }
212
210
 
211
+ if (features.parameters) {
212
+ alepha.with(AlephaApiParameters);
213
+ const settingsParam = $parameter({
214
+ name: `api.realms.settings.${name}`,
215
+ description: `Authentication and registration settings for realm "${name}"`,
216
+ schema: realmAuthSettingsAtom.schema,
217
+ default: realmRegistration.settings,
218
+ });
219
+ realmRegistration.settingsParameter = settingsParam;
220
+ alepha.with(() => ({ [`realmSettings_${name}`]: settingsParam }));
221
+ }
222
+
213
223
  return realm;
214
224
  };
215
225
 
@@ -217,11 +227,13 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
217
227
 
218
228
  export interface RealmFeatures {
219
229
  /**
220
- * Enable session purge functionality for cleaning up expired sessions.
230
+ * Will enable Job module.
231
+ *
232
+ * - Enable session purge functionality for cleaning up expired sessions.
221
233
  *
222
234
  * @default false
223
235
  */
224
- sessionPurge?: boolean;
236
+ jobs?: boolean;
225
237
 
226
238
  /**
227
239
  * Enable notification system for password reset, verification emails, etc.
@@ -1,4 +1,5 @@
1
1
  import { $inject, Alepha, AlephaError } from "alepha";
2
+ import type { ParameterPrimitive } from "alepha/api/parameters";
2
3
  import { $repository, type Repository } from "alepha/orm";
3
4
  import {
4
5
  type RealmAuthSettings,
@@ -20,6 +21,8 @@ export interface Realm {
20
21
  repositories: RealmRepositories;
21
22
  settings: RealmAuthSettings;
22
23
  features: RealmFeatures;
24
+ settingsParameter?: ParameterPrimitive<typeof realmAuthSettingsAtom.schema>;
25
+ getSettings(): Promise<RealmAuthSettings>;
23
26
  }
24
27
 
25
28
  export class RealmProvider {
@@ -32,9 +35,15 @@ export class RealmProvider {
32
35
  protected realms = new Map<string, Realm>();
33
36
 
34
37
  public register(realmName: string, realmOptions: RealmOptions = {}) {
38
+ if (realmName.includes(".")) {
39
+ throw new AlephaError(
40
+ `Realm name "${realmName}" must not contain dots — dots are reserved for parameter tree paths`,
41
+ );
42
+ }
43
+
35
44
  // Merge features with defaults
36
45
  const features: RealmFeatures = {
37
- sessionPurge: false,
46
+ jobs: false,
38
47
  notifications: false,
39
48
  apiKeys: false,
40
49
  parameters: false,
@@ -43,7 +52,7 @@ export class RealmProvider {
43
52
  ...realmOptions.features,
44
53
  };
45
54
 
46
- this.realms.set(realmName, {
55
+ const realm: Realm = {
47
56
  name: realmName,
48
57
  repositories: {
49
58
  identities: realmOptions.entities?.identities ?? this.defaultIdentities,
@@ -58,9 +67,20 @@ export class RealmProvider {
58
67
  ...realmAuthSettingsAtom.options.default.passwordPolicy,
59
68
  ...realmOptions.settings?.passwordPolicy,
60
69
  },
70
+ loginRateLimit: {
71
+ ...realmAuthSettingsAtom.options.default.loginRateLimit,
72
+ ...realmOptions.settings?.loginRateLimit,
73
+ },
61
74
  },
62
75
  features,
63
- });
76
+ getSettings: async function () {
77
+ if (this.settingsParameter) {
78
+ return await this.settingsParameter.get();
79
+ }
80
+ return this.settings;
81
+ },
82
+ };
83
+ this.realms.set(realmName, realm);
64
84
  return this.getRealm(realmName);
65
85
  }
66
86
 
@@ -88,7 +88,8 @@ export class RegistrationService {
88
88
  userRealmName,
89
89
  });
90
90
 
91
- const realmSettings = this.realmProvider.getRealm(userRealmName).settings;
91
+ const realm = this.realmProvider.getRealm(userRealmName);
92
+ const realmSettings = await realm.getSettings();
92
93
 
93
94
  // Check if registration is allowed
94
95
  if (realmSettings?.registrationAllowed === false) {
@@ -338,7 +339,7 @@ export class RegistrationService {
338
339
 
339
340
  if (body.username) {
340
341
  const existingUser = await userRepository.findOne({
341
- where: { username: { eq: body.username } },
342
+ where: { username: { ilike: body.username } },
342
343
  });
343
344
  if (existingUser) {
344
345
  this.log.debug("Username already taken", { username: body.username });
@@ -1,6 +1,7 @@
1
1
  import { randomInt } from "node:crypto";
2
2
  import { $inject, Alepha } from "alepha";
3
3
  import type { FileController } from "alepha/api/files";
4
+ import { CacheProvider } from "alepha/cache";
4
5
  import { DateTimeProvider } from "alepha/datetime";
5
6
  import { $logger } from "alepha/logger";
6
7
  import {
@@ -8,7 +9,7 @@ import {
8
9
  InvalidCredentialsError,
9
10
  type UserAccount,
10
11
  } from "alepha/security";
11
- import { UnauthorizedError } from "alepha/server";
12
+ import { BadRequestError, UnauthorizedError } from "alepha/server";
12
13
  import type { OAuth2Profile } from "alepha/server/auth";
13
14
  import { $client } from "alepha/server/links";
14
15
  import { FileSystemProvider } from "alepha/system";
@@ -24,6 +25,7 @@ export class SessionService {
24
25
  protected readonly log = $logger();
25
26
  protected readonly realmProvider = $inject(RealmProvider);
26
27
  protected readonly fileController = $client<FileController>();
28
+ protected readonly cacheProvider = $inject(CacheProvider);
27
29
 
28
30
  protected userAudits(realmName?: string) {
29
31
  const realm = this.realmProvider.getRealm(realmName);
@@ -60,7 +62,9 @@ export class SessionService {
60
62
  ): Promise<boolean> {
61
63
  if (user.roles.includes("admin")) return false;
62
64
 
63
- const { settings, name } = this.realmProvider.getRealm(userRealmName);
65
+ const realm = this.realmProvider.getRealm(userRealmName);
66
+ const settings = await realm.getSettings();
67
+ const { name } = realm;
64
68
  const adminEmails = settings.adminEmails ?? [];
65
69
  const adminUsernames = settings.adminUsernames ?? [];
66
70
 
@@ -94,6 +98,78 @@ export class SessionService {
94
98
  return true;
95
99
  }
96
100
 
101
+ /**
102
+ * Generate a unique username from an OAuth profile.
103
+ *
104
+ * 1. Extract candidate from email prefix
105
+ * 2. Sanitize against realm's usernameRegExp (strip invalid chars, truncate)
106
+ * 3. Check case-insensitive uniqueness, append suffix (2, 3, ...) if taken
107
+ * 4. Fall back to "user" + random 6-char alphanumeric if all else fails
108
+ */
109
+ protected async generateUniqueUsername(
110
+ profile: OAuth2Profile,
111
+ realmSettings: any,
112
+ users: any,
113
+ ): Promise<string> {
114
+ const maxLength = 30;
115
+ const maxSuffixAttempts = 10;
116
+
117
+ // Extract candidate from email or profile name
118
+ let candidate = profile.email?.split("@")[0] ?? profile.name ?? "";
119
+
120
+ // Strip characters not allowed in usernames (keep alphanumeric, underscore, dot, hyphen)
121
+ candidate = candidate.replace(/[^a-zA-Z0-9_.-]/g, "");
122
+
123
+ // If realm has a custom regex, further sanitize
124
+ if (realmSettings?.usernameRegExp) {
125
+ try {
126
+ const regex = new RegExp(realmSettings.usernameRegExp);
127
+ if (!regex.test(candidate)) {
128
+ // Strip to basic alphanumeric as safe fallback
129
+ candidate = candidate.replace(/[^a-zA-Z0-9_]/g, "");
130
+ }
131
+ } catch {
132
+ // Invalid regex, continue with sanitized candidate
133
+ }
134
+ }
135
+
136
+ // Ensure minimum length
137
+ if (candidate.length < 3) {
138
+ candidate = `user${candidate}`;
139
+ }
140
+
141
+ // Truncate to leave room for suffix
142
+ candidate = candidate.slice(0, maxLength - 2);
143
+
144
+ // Check uniqueness (case-insensitive)
145
+ const isAvailable = async (name: string) => {
146
+ const existing = await users.findMany({
147
+ where: { username: { contains: name } },
148
+ limit: 1,
149
+ });
150
+ // Case-insensitive check
151
+ return !existing.some(
152
+ (u: any) => u.username?.toLowerCase() === name.toLowerCase(),
153
+ );
154
+ };
155
+
156
+ if (await isAvailable(candidate)) {
157
+ return candidate;
158
+ }
159
+
160
+ // Try with numeric suffix
161
+ for (let i = 2; i <= maxSuffixAttempts + 1; i++) {
162
+ const withSuffix = `${candidate}${i}`;
163
+ if (withSuffix.length <= maxLength && (await isAvailable(withSuffix))) {
164
+ return withSuffix;
165
+ }
166
+ }
167
+
168
+ // Final fallback: random username
169
+ const random = Math.random().toString(36).slice(2, 8);
170
+ return `user${random}`;
171
+ }
172
+
97
173
  /**
98
174
  * Random delay to prevent timing attacks (50-200ms)
99
175
  * Uses cryptographically secure random number generation
@@ -102,6 +178,59 @@ export class SessionService {
102
178
  return new Promise((resolve) => setTimeout(resolve, randomInt(50, 201)));
103
179
  }
104
180
 
181
+ protected static readonly LOGIN_CACHE_NAME = "login-rate-limit";
182
+
183
+ /**
184
+ * Check if a login key is currently locked out.
185
+ * Read-only — does not increment the counter.
186
+ */
187
+ protected async isLoginLocked(key: string, max: number): Promise<boolean> {
188
+ try {
189
+ const count = await this.cacheProvider.getTyped<number>(
190
+ SessionService.LOGIN_CACHE_NAME,
191
+ key,
192
+ );
193
+ return count != null && count >= max;
194
+ } catch (error) {
195
+ this.log.warn(
196
+ "Failed to check login rate limit, allowing attempt",
197
+ error,
198
+ );
199
+ return false;
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Record a failed login attempt. Uses getTyped + setTyped (not incr) so that
205
+ * each write refreshes the TTL — implementing sliding-window behavior.
206
+ *
207
+ * Returns `true` if this failure just crossed the lockout threshold.
208
+ */
209
+ protected async recordFailedLogin(
210
+ key: string,
211
+ max: number,
212
+ windowMs: number,
213
+ ): Promise<boolean> {
214
+ try {
215
+ const count =
216
+ (await this.cacheProvider.getTyped<number>(
217
+ SessionService.LOGIN_CACHE_NAME,
218
+ key,
219
+ )) ?? 0;
220
+ const newCount = count + 1;
221
+ await this.cacheProvider.setTyped(
222
+ SessionService.LOGIN_CACHE_NAME,
223
+ key,
224
+ newCount,
225
+ { ttl: windowMs },
226
+ );
227
+ return newCount === max;
228
+ } catch (error) {
229
+ this.log.warn("Failed to record failed login attempt", error);
230
+ return false;
231
+ }
232
+ }
233
+
105
234
  /**
106
235
  * Validate user credentials and return the user if valid.
107
236
  */
@@ -111,13 +240,33 @@ export class SessionService {
111
240
  password: string,
112
241
  userRealmName?: string,
113
242
  ): Promise<UserEntity> {
114
- const { settings, name } = this.realmProvider.getRealm(userRealmName);
243
+ const realm = this.realmProvider.getRealm(userRealmName);
244
+ const settings = await realm.getSettings();
245
+ const { name } = realm;
246
+ const { loginRateLimit } = settings;
115
247
  const isEmail = username.includes("@");
116
248
  const isPhone = /^[+\d][\d\s()-]+$/.test(username);
117
249
  const isUsername = !isEmail && !isPhone;
118
250
  const identities = this.identities(userRealmName);
119
251
  const users = this.users(userRealmName);
120
252
 
253
+ // IP rate limit check (global, cross-realm) — before any DB work
254
+ const request = this.alepha.store.get("alepha.http.request");
255
+ const ipKey = request?.ip ? `login:ip:${request.ip}` : undefined;
256
+
257
+ if (ipKey) {
258
+ const ipLocked = await this.isLoginLocked(
259
+ ipKey,
260
+ loginRateLimit.ipMaxAttempts,
261
+ );
262
+ if (ipLocked) {
263
+ this.log.warn("Login blocked — IP rate limit exceeded", {
264
+ ip: request?.ip,
265
+ });
266
+ throw new InvalidCredentialsError();
267
+ }
268
+ }
269
+
121
270
  await this.randomDelay();
122
271
 
123
272
  try {
@@ -145,7 +294,7 @@ export class SessionService {
145
294
  throw new InvalidCredentialsError();
146
295
  }
147
296
  }
148
- where.username = username;
297
+ where.username = { ilike: username };
149
298
  } else if (settings.email !== "none" && isEmail) {
150
299
  where.email = username;
151
300
  } else if (settings.phoneNumber !== "none" && isPhone) {
@@ -180,6 +329,42 @@ export class SessionService {
180
329
  metadata: { provider, username },
181
330
  });
182
331
 
332
+ // Only increment IP counter (no user ID to track)
333
+ if (ipKey) {
334
+ const justLocked = await this.recordFailedLogin(
335
+ ipKey,
336
+ loginRateLimit.ipMaxAttempts,
337
+ loginRateLimit.windowMs,
338
+ );
339
+ if (justLocked) {
340
+ await this.userAudits(userRealmName)?.record(
341
+ "security",
342
+ "rate_limited",
343
+ {
344
+ userRealm: name,
345
+ success: false,
346
+ description:
347
+ "IP temporarily locked due to too many failed login attempts",
348
+ metadata: { ip: request?.ip },
349
+ },
350
+ );
351
+ }
352
+ }
353
+
354
+ throw new InvalidCredentialsError();
355
+ }
356
+
357
+ // Account rate limit check (per-realm)
358
+ const accountKey = `login:account:${name}:${user.id}`;
359
+ const accountLocked = await this.isLoginLocked(
360
+ accountKey,
361
+ loginRateLimit.accountMaxAttempts,
362
+ );
363
+ if (accountLocked) {
364
+ this.log.warn("Login blocked — account rate limit exceeded", {
365
+ userId: user.id,
366
+ realm: name,
367
+ });
183
368
  throw new InvalidCredentialsError();
184
369
  }
185
370
 
@@ -220,6 +405,48 @@ export class SessionService {
220
405
  metadata: { provider, username },
221
406
  });
222
407
 
408
+ // Record failed attempt on both IP and account counters
409
+ if (ipKey) {
410
+ const ipJustLocked = await this.recordFailedLogin(
411
+ ipKey,
412
+ loginRateLimit.ipMaxAttempts,
413
+ loginRateLimit.windowMs,
414
+ );
415
+ if (ipJustLocked) {
416
+ await this.userAudits(userRealmName)?.record(
417
+ "security",
418
+ "rate_limited",
419
+ {
420
+ userRealm: name,
421
+ success: false,
422
+ description:
423
+ "IP temporarily locked due to too many failed login attempts",
424
+ metadata: { ip: request?.ip },
425
+ },
426
+ );
427
+ }
428
+ }
429
+
430
+ const accountJustLocked = await this.recordFailedLogin(
431
+ accountKey,
432
+ loginRateLimit.accountMaxAttempts,
433
+ loginRateLimit.windowMs,
434
+ );
435
+ if (accountJustLocked) {
436
+ await this.userAudits(userRealmName)?.record(
437
+ "security",
438
+ "rate_limited",
439
+ {
440
+ userRealm: name,
441
+ resourceId: user.id,
442
+ success: false,
443
+ description:
444
+ "Account temporarily locked due to too many failed login attempts",
445
+ metadata: { userId: user.id },
446
+ },
447
+ );
448
+ }
449
+
223
450
  throw new InvalidCredentialsError();
224
451
  }
225
452
 
@@ -238,7 +465,6 @@ export class SessionService {
238
465
  return user;
239
466
  } catch (error) {
240
467
  if (error instanceof InvalidCredentialsError) {
241
- // TODO: store failed login attempts (with request data) and lock account after threshold
242
468
  throw error;
243
469
  }
244
470
 
@@ -442,12 +668,27 @@ export class SessionService {
442
668
  return existing;
443
669
  }
444
670
 
445
- // TODO: check usernames for uniqueness, add suffix if needed (e.g. john.doe1)
446
- // TODO: username must match a-zA-Z0-9._-
671
+ const realmSettings = await realm.getSettings();
672
+ const adminEmails = realmSettings?.adminEmails ?? [];
673
+ const isAdmin = profile.email && adminEmails.includes(profile.email);
674
+
675
+ if (realmSettings?.registrationAllowed === false && !isAdmin) {
676
+ this.log.warn("Registration not allowed for realm via OAuth2", {
677
+ provider,
678
+ userRealmName,
679
+ });
680
+ throw new BadRequestError("Account doesn't exist");
681
+ }
682
+
683
+ const username = await this.generateUniqueUsername(
684
+ profile,
685
+ realmSettings,
686
+ users,
687
+ );
447
688
 
448
689
  const user = await users.create({
449
690
  realm: realm.name,
450
- username: profile.email.split("@")[0],
691
+ username,
451
692
  email: profile.email,
452
693
  // we trust the OAuth2 provider
453
694
  emailVerified: true,
@@ -276,7 +276,7 @@ export class UserService {
276
276
  // Check for existing user based on provided unique fields
277
277
  if (data.username) {
278
278
  const existingUser = await this.users(userRealmName).findOne({
279
- where: { username: { eq: data.username } },
279
+ where: { username: { ilike: data.username } },
280
280
  });
281
281
 
282
282
  if (existingUser) {