alepha 0.18.2 → 0.18.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 (397) hide show
  1. package/assets/devtools-ui/200.html +2 -2
  2. package/assets/devtools-ui/200.html.br +0 -0
  3. package/assets/devtools-ui/404.html +2 -2
  4. package/assets/devtools-ui/404.html.br +0 -0
  5. package/assets/devtools-ui/{asset.BfSBZ5Dd.css → asset.hG_f8HuK.css} +1 -1
  6. package/assets/devtools-ui/asset.hG_f8HuK.css.br +0 -0
  7. package/assets/devtools-ui/chunk.B3au4Lhg.js +1 -0
  8. package/assets/devtools-ui/chunk.B3au4Lhg.js.br +0 -0
  9. package/assets/devtools-ui/chunk.BLOrlnMB.js +1 -0
  10. package/assets/devtools-ui/chunk.BLOrlnMB.js.br +0 -0
  11. package/assets/devtools-ui/chunk.BLR01ljW.js +1 -0
  12. package/assets/devtools-ui/chunk.BLR01ljW.js.br +0 -0
  13. package/assets/devtools-ui/chunk.BTXaIUlA.js +1 -0
  14. package/assets/devtools-ui/chunk.BTXaIUlA.js.br +0 -0
  15. package/assets/devtools-ui/{chunk.lJL-lgnW.js → chunk.BhJaxmm8.js} +1 -1
  16. package/assets/devtools-ui/chunk.BhJaxmm8.js.br +0 -0
  17. package/assets/devtools-ui/chunk.BtoNxFuL.js +1 -0
  18. package/assets/devtools-ui/chunk.BtoNxFuL.js.br +0 -0
  19. package/assets/devtools-ui/chunk.C8YUV2Wd.js +1 -0
  20. package/assets/devtools-ui/chunk.C8YUV2Wd.js.br +0 -0
  21. package/assets/devtools-ui/{chunk.M6wyKO_3.js → chunk.CBbIgDzE.js} +2 -2
  22. package/assets/devtools-ui/chunk.CBbIgDzE.js.br +0 -0
  23. package/assets/devtools-ui/chunk.CFqIniwA.js +1 -0
  24. package/assets/devtools-ui/chunk.CFqIniwA.js.br +0 -0
  25. package/assets/devtools-ui/chunk.CLFF7f7-.js +1 -0
  26. package/assets/devtools-ui/chunk.CLFF7f7-.js.br +0 -0
  27. package/assets/devtools-ui/chunk.CRsBbA10.js +1 -0
  28. package/assets/devtools-ui/chunk.CRsBbA10.js.br +0 -0
  29. package/assets/devtools-ui/{chunk.DbEH1oOB.js → chunk.CZPo6v95.js} +1 -1
  30. package/assets/devtools-ui/chunk.CZPo6v95.js.br +0 -0
  31. package/assets/devtools-ui/chunk.D0fWgNos.js +1 -0
  32. package/assets/devtools-ui/chunk.D0fWgNos.js.br +1 -0
  33. package/assets/devtools-ui/chunk.D7-0ziQ6.js +1 -0
  34. package/assets/devtools-ui/chunk.D7-0ziQ6.js.br +0 -0
  35. package/assets/devtools-ui/chunk.DAewe0vm.js +1 -0
  36. package/assets/devtools-ui/chunk.DAewe0vm.js.br +0 -0
  37. package/assets/devtools-ui/chunk.DJRQEYqK.js +1 -0
  38. package/assets/devtools-ui/chunk.DJRQEYqK.js.br +0 -0
  39. package/assets/devtools-ui/{chunk.CZl6J9DF.js → chunk.DMAxv14p.js} +1 -1
  40. package/assets/devtools-ui/chunk.DMAxv14p.js.br +0 -0
  41. package/assets/devtools-ui/{chunk.BT2IiBkZ.js → chunk.DMImnNjU.js} +1 -1
  42. package/assets/devtools-ui/chunk.DMImnNjU.js.br +0 -0
  43. package/assets/devtools-ui/chunk.DeeQsidk.js +9 -0
  44. package/assets/devtools-ui/chunk.DeeQsidk.js.br +0 -0
  45. package/assets/devtools-ui/chunk.DqEwn9Vj.js +7 -0
  46. package/assets/devtools-ui/chunk.DqEwn9Vj.js.br +0 -0
  47. package/assets/devtools-ui/chunk.Dt8OsQey.js +1 -0
  48. package/assets/devtools-ui/chunk.Dt8OsQey.js.br +0 -0
  49. package/assets/devtools-ui/{chunk.B9pX3zit.js → chunk.Dtp8oa_f.js} +1 -1
  50. package/assets/devtools-ui/chunk.Dtp8oa_f.js.br +0 -0
  51. package/assets/devtools-ui/chunk.Dx3JzAYM.js +1 -0
  52. package/assets/devtools-ui/chunk.Dx3JzAYM.js.br +0 -0
  53. package/assets/devtools-ui/chunk.GCOj1-5E.js +1 -0
  54. package/assets/devtools-ui/chunk.GCOj1-5E.js.br +0 -0
  55. package/assets/devtools-ui/chunk.IC1LD8BH.js +1 -0
  56. package/assets/devtools-ui/chunk.IC1LD8BH.js.br +0 -0
  57. package/assets/devtools-ui/chunk.IwuB_TqW.js +1 -0
  58. package/assets/devtools-ui/chunk.IwuB_TqW.js.br +0 -0
  59. package/assets/devtools-ui/chunk.Qqapj2zq.js +1 -0
  60. package/assets/devtools-ui/chunk.Qqapj2zq.js.br +0 -0
  61. package/assets/devtools-ui/{chunk.C79YouPp.js → chunk.TKKKndOy.js} +1 -1
  62. package/assets/devtools-ui/chunk.TKKKndOy.js.br +0 -0
  63. package/assets/devtools-ui/chunk.YHTVhFQT.js +1 -0
  64. package/assets/devtools-ui/chunk.YHTVhFQT.js.br +0 -0
  65. package/assets/devtools-ui/chunk.fnod6uEi.js +1 -0
  66. package/assets/devtools-ui/chunk.fnod6uEi.js.br +0 -0
  67. package/assets/devtools-ui/chunk.mOCRmXjo.js +1 -0
  68. package/assets/devtools-ui/chunk.mOCRmXjo.js.br +0 -0
  69. package/assets/devtools-ui/chunk.qZTNEAK0.js +1 -0
  70. package/assets/devtools-ui/chunk.qZTNEAK0.js.br +0 -0
  71. package/assets/devtools-ui/chunk.rc9m0y4-.js +1 -0
  72. package/assets/devtools-ui/chunk.rc9m0y4-.js.br +0 -0
  73. package/assets/devtools-ui/entry.Cxc5QLCU.js +80 -0
  74. package/assets/devtools-ui/entry.Cxc5QLCU.js.br +0 -0
  75. package/assets/devtools-ui/index.html +2 -2
  76. package/assets/devtools-ui/index.html.br +0 -0
  77. package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
  78. package/assets/swagger-ui/swagger-ui.css +1 -1
  79. package/dist/api/audits/index.d.ts +61 -5
  80. package/dist/api/audits/index.d.ts.map +1 -1
  81. package/dist/api/files/index.d.ts +61 -5
  82. package/dist/api/files/index.d.ts.map +1 -1
  83. package/dist/api/jobs/index.d.ts +61 -5
  84. package/dist/api/jobs/index.d.ts.map +1 -1
  85. package/dist/api/jobs/index.js +4 -2
  86. package/dist/api/jobs/index.js.map +1 -1
  87. package/dist/api/keys/index.d.ts +5 -5
  88. package/dist/api/notifications/index.browser.js +44 -1
  89. package/dist/api/notifications/index.browser.js.map +1 -1
  90. package/dist/api/notifications/index.d.ts +187 -2
  91. package/dist/api/notifications/index.d.ts.map +1 -1
  92. package/dist/api/notifications/index.js +143 -8
  93. package/dist/api/notifications/index.js.map +1 -1
  94. package/dist/api/parameters/index.d.ts +61 -5
  95. package/dist/api/parameters/index.d.ts.map +1 -1
  96. package/dist/api/users/index.d.ts +330 -93
  97. package/dist/api/users/index.d.ts.map +1 -1
  98. package/dist/api/users/index.js +27 -36
  99. package/dist/api/users/index.js.map +1 -1
  100. package/dist/cli/config/index.d.ts +46 -0
  101. package/dist/cli/config/index.d.ts.map +1 -0
  102. package/dist/cli/config/index.js +20 -0
  103. package/dist/cli/config/index.js.map +1 -0
  104. package/dist/cli/core/index.d.ts +69 -66
  105. package/dist/cli/core/index.d.ts.map +1 -1
  106. package/dist/cli/core/index.js +329 -196
  107. package/dist/cli/core/index.js.map +1 -1
  108. package/dist/cli/platform/index.d.ts +302 -63
  109. package/dist/cli/platform/index.d.ts.map +1 -1
  110. package/dist/cli/platform/index.js +455 -25
  111. package/dist/cli/platform/index.js.map +1 -1
  112. package/dist/core/index.browser.js +125 -87
  113. package/dist/core/index.browser.js.map +1 -1
  114. package/dist/core/index.d.ts +62 -53
  115. package/dist/core/index.d.ts.map +1 -1
  116. package/dist/core/index.js +125 -87
  117. package/dist/core/index.js.map +1 -1
  118. package/dist/core/index.native.js +125 -87
  119. package/dist/core/index.native.js.map +1 -1
  120. package/dist/core/index.workerd.js +125 -87
  121. package/dist/core/index.workerd.js.map +1 -1
  122. package/dist/crypto/index.d.ts +18 -1
  123. package/dist/crypto/index.d.ts.map +1 -1
  124. package/dist/crypto/index.js +29 -3
  125. package/dist/crypto/index.js.map +1 -1
  126. package/dist/devtools/index.js +3 -12
  127. package/dist/devtools/index.js.map +1 -1
  128. package/dist/logger/index.d.ts +10 -1
  129. package/dist/logger/index.d.ts.map +1 -1
  130. package/dist/logger/index.js +19 -9
  131. package/dist/logger/index.js.map +1 -1
  132. package/dist/orm/core/index.browser.js +57 -1
  133. package/dist/orm/core/index.browser.js.map +1 -1
  134. package/dist/orm/core/index.bun.js +378 -19
  135. package/dist/orm/core/index.bun.js.map +1 -1
  136. package/dist/orm/core/index.d.ts +328 -9
  137. package/dist/orm/core/index.d.ts.map +1 -1
  138. package/dist/orm/core/index.js +384 -21
  139. package/dist/orm/core/index.js.map +1 -1
  140. package/dist/orm/postgres/index.bun.js +49 -17
  141. package/dist/orm/postgres/index.bun.js.map +1 -1
  142. package/dist/orm/postgres/index.d.ts +47 -21
  143. package/dist/orm/postgres/index.d.ts.map +1 -1
  144. package/dist/orm/postgres/index.js +52 -17
  145. package/dist/orm/postgres/index.js.map +1 -1
  146. package/dist/react/core/index.d.ts +1 -1
  147. package/dist/react/core/index.d.ts.map +1 -1
  148. package/dist/react/core/index.js +6 -1
  149. package/dist/react/core/index.js.map +1 -1
  150. package/dist/react/form/index.d.ts +28 -18
  151. package/dist/react/form/index.d.ts.map +1 -1
  152. package/dist/react/form/index.js +92 -56
  153. package/dist/react/form/index.js.map +1 -1
  154. package/dist/react/router/index.browser.js +448 -116
  155. package/dist/react/router/index.browser.js.map +1 -1
  156. package/dist/react/router/index.d.ts +102 -40
  157. package/dist/react/router/index.d.ts.map +1 -1
  158. package/dist/react/router/index.js +453 -92
  159. package/dist/react/router/index.js.map +1 -1
  160. package/dist/security/index.d.ts +3 -11
  161. package/dist/security/index.d.ts.map +1 -1
  162. package/dist/security/index.js +6 -11
  163. package/dist/security/index.js.map +1 -1
  164. package/dist/server/auth/index.d.ts +22 -24
  165. package/dist/server/auth/index.d.ts.map +1 -1
  166. package/dist/server/auth/index.js +102 -82
  167. package/dist/server/auth/index.js.map +1 -1
  168. package/dist/server/cookies/index.d.ts +7 -4
  169. package/dist/server/cookies/index.d.ts.map +1 -1
  170. package/dist/server/cookies/index.js +13 -12
  171. package/dist/server/cookies/index.js.map +1 -1
  172. package/dist/server/core/index.d.ts +288 -4
  173. package/dist/server/core/index.d.ts.map +1 -1
  174. package/dist/server/core/index.js +375 -2
  175. package/dist/server/core/index.js.map +1 -1
  176. package/dist/server/links/index.browser.js +10 -71
  177. package/dist/server/links/index.browser.js.map +1 -1
  178. package/dist/server/links/index.d.ts +32 -49
  179. package/dist/server/links/index.d.ts.map +1 -1
  180. package/dist/server/links/index.js +73 -100
  181. package/dist/server/links/index.js.map +1 -1
  182. package/dist/system/index.browser.js +221 -2
  183. package/dist/system/index.browser.js.map +1 -1
  184. package/dist/system/index.d.ts +63 -1
  185. package/dist/system/index.d.ts.map +1 -1
  186. package/dist/system/index.js +221 -1
  187. package/dist/system/index.js.map +1 -1
  188. package/dist/system/index.workerd.js +224 -4
  189. package/dist/system/index.workerd.js.map +1 -1
  190. package/package.json +10 -5
  191. package/src/api/jobs/providers/JobProvider.ts +6 -3
  192. package/src/api/notifications/controllers/AdminNotificationController.ts +83 -0
  193. package/src/api/notifications/index.browser.ts +3 -0
  194. package/src/api/notifications/index.ts +14 -2
  195. package/src/api/notifications/jobs/NotificationJobs.ts +11 -2
  196. package/src/api/notifications/schemas/notificationDetailResourceSchema.ts +20 -0
  197. package/src/api/notifications/schemas/notificationQuerySchema.ts +19 -0
  198. package/src/api/notifications/schemas/notificationResourceSchema.ts +18 -0
  199. package/src/api/notifications/services/NotificationSenderService.ts +15 -2
  200. package/src/api/users/atoms/realmAuthSettingsAtom.ts +28 -32
  201. package/src/api/users/buckets/UserBuckets.ts +1 -1
  202. package/src/api/users/jobs/UserJobs.ts +1 -1
  203. package/src/api/users/primitives/$realm.ts +8 -49
  204. package/src/api/users/providers/RealmProvider.ts +2 -3
  205. package/src/api/users/services/RegistrationService.spec.ts +7 -7
  206. package/src/api/users/services/RegistrationService.ts +3 -3
  207. package/src/api/users/services/SessionService.spec.ts +4 -4
  208. package/src/api/users/services/SessionService.ts +3 -3
  209. package/src/cli/{core → config}/defineConfig.ts +14 -20
  210. package/src/cli/config/index.ts +1 -0
  211. package/src/cli/core/commands/db.ts +65 -1
  212. package/src/cli/core/commands/dev.ts +1 -0
  213. package/src/cli/core/commands/init.ts +2 -192
  214. package/src/cli/core/index.ts +34 -11
  215. package/src/cli/core/providers/ViteDevServerProvider.ts +52 -13
  216. package/src/cli/core/services/PackageManagerUtils.ts +43 -21
  217. package/src/cli/core/services/ProjectScaffolder.ts +214 -2
  218. package/src/cli/core/services/ViteUtils.ts +57 -0
  219. package/src/cli/core/tasks/BuildClientTask.ts +7 -2
  220. package/src/cli/core/tasks/BuildCloudflareTask.ts +4 -12
  221. package/src/cli/core/tasks/BuildServerTask.ts +2 -0
  222. package/src/cli/core/tasks/BuildVercelTask.ts +165 -168
  223. package/src/cli/core/templates/alephaConfigTs.ts +1 -1
  224. package/src/cli/core/templates/apiAppSecurityTs.ts +5 -8
  225. package/src/cli/core/templates/tsconfigJson.ts +6 -1
  226. package/src/cli/platform/adapters/CloudflareAdapter.spec.ts +1 -1
  227. package/src/cli/platform/adapters/CloudflareAdapter.ts +30 -29
  228. package/src/cli/platform/atoms/platformOptions.ts +21 -0
  229. package/src/cli/platform/commands/SecretsCommand.spec.ts +298 -0
  230. package/src/cli/platform/commands/SecretsCommand.ts +283 -0
  231. package/src/cli/platform/commands/platform.ts +12 -0
  232. package/src/cli/platform/index.ts +14 -28
  233. package/src/cli/platform/providers/GitHubSecretStore.spec.ts +153 -0
  234. package/src/cli/platform/providers/GitHubSecretStore.ts +112 -0
  235. package/src/cli/platform/providers/MemorySecretStore.ts +114 -0
  236. package/src/cli/platform/providers/SecretStoreProvider.ts +39 -0
  237. package/src/cli/platform/schemas/cloudflare.ts +2 -0
  238. package/src/cli/platform/services/CloudflareApi.ts +5 -2
  239. package/src/cli/platform/services/DockerComposeGenerator.spec.ts +115 -0
  240. package/src/cli/platform/services/DockerComposeGenerator.ts +46 -1
  241. package/src/cli/platform/services/SecretFilterService.spec.ts +111 -0
  242. package/src/cli/platform/services/SecretFilterService.ts +54 -0
  243. package/src/core/Alepha.ts +94 -25
  244. package/src/core/__tests__/Alepha-parseEnv.spec.ts +20 -0
  245. package/src/core/primitives/$memoize.ts +38 -26
  246. package/src/core/providers/AlsProvider.ts +2 -0
  247. package/src/core/providers/EventManager.ts +4 -0
  248. package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +1 -4
  249. package/src/core/providers/KeylessJsonSchemaCodec.ts +19 -125
  250. package/src/core/providers/SchemaValidator.spec.ts +36 -0
  251. package/src/core/providers/SchemaValidator.ts +9 -0
  252. package/src/crypto/index.ts +6 -1
  253. package/src/crypto/providers/SecretProvider.ts +36 -0
  254. package/src/devtools/providers/DevToolsProvider.ts +3 -12
  255. package/src/logger/index.ts +33 -6
  256. package/src/logger/providers/PrettyFormatterProvider.ts +5 -3
  257. package/src/orm/__tests__/orm-next-tests.ts +492 -0
  258. package/src/orm/__tests__/orm-next.spec.ts +140 -0
  259. package/src/orm/core/constants/PG_SYMBOLS.ts +17 -0
  260. package/src/orm/core/index.bun.ts +3 -6
  261. package/src/orm/core/index.shared-server.ts +2 -0
  262. package/src/orm/core/index.shared.ts +2 -0
  263. package/src/orm/core/index.ts +5 -7
  264. package/src/orm/core/interfaces/AggregateQuery.ts +103 -0
  265. package/src/orm/core/interfaces/PgQueryWhere.ts +7 -0
  266. package/src/orm/core/primitives/$entity.ts +8 -0
  267. package/src/orm/core/primitives/$repository.ts +6 -3
  268. package/src/orm/core/primitives/$view.ts +88 -0
  269. package/src/orm/core/providers/DbCacheProvider.ts +66 -0
  270. package/src/orm/core/providers/DrizzleKitProvider.ts +42 -0
  271. package/src/orm/core/providers/drivers/BunSqliteProvider.ts +2 -3
  272. package/src/orm/core/providers/drivers/CloudflareD1Provider.ts +12 -0
  273. package/src/orm/core/providers/drivers/DatabaseProvider.ts +39 -0
  274. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +2 -3
  275. package/src/orm/core/schemas/databaseEnvSchema.ts +31 -0
  276. package/src/orm/core/schemas/insertSchema.ts +13 -3
  277. package/src/orm/core/schemas/updateSchema.ts +14 -3
  278. package/src/orm/core/services/ModelBuilder.ts +26 -14
  279. package/src/orm/core/services/QueryManager.ts +13 -0
  280. package/src/orm/core/services/Repository.ts +307 -5
  281. package/src/orm/core/services/SqliteModelBuilder.ts +38 -0
  282. package/src/orm/postgres/index.bun.ts +4 -7
  283. package/src/orm/postgres/index.ts +4 -7
  284. package/src/orm/postgres/providers/BunPostgresProvider.ts +12 -2
  285. package/src/orm/postgres/providers/NodePostgresProvider.ts +7 -0
  286. package/src/orm/postgres/providers/PglitePostgresProvider.ts +10 -17
  287. package/src/orm/postgres/providers/PostgresProvider.ts +7 -36
  288. package/src/orm/postgres/schemas/postgresEnvSchema.ts +32 -0
  289. package/src/orm/postgres/services/PostgresModelBuilder.ts +40 -0
  290. package/src/react/core/components/ErrorBoundary.tsx +5 -2
  291. package/src/react/form/hooks/useFieldValue.ts +34 -0
  292. package/src/react/form/hooks/useForm.browser.spec.tsx +94 -9
  293. package/src/react/form/hooks/useForm.ts +14 -2
  294. package/src/react/form/hooks/useFormState.ts +10 -10
  295. package/src/react/form/hooks/useFormValues.ts +29 -0
  296. package/src/react/form/index.ts +3 -1
  297. package/src/react/form/services/FormModel.ts +53 -122
  298. package/src/react/router/components/ErrorViewer.tsx +333 -34
  299. package/src/react/router/components/NestedView.tsx +10 -3
  300. package/src/react/router/primitives/$page.browser.spec.tsx +34 -0
  301. package/src/react/router/primitives/$page.spec.tsx +20 -0
  302. package/src/react/router/primitives/$page.ts +24 -0
  303. package/src/react/router/providers/ReactBrowserRouterProvider.ts +14 -2
  304. package/src/react/router/providers/ReactPageProvider.ts +156 -73
  305. package/src/react/router/providers/ReactServerProvider.ts +40 -2
  306. package/src/react/router/providers/ReactServerTemplateProvider.ts +13 -1
  307. package/src/security/providers/SecurityProvider.ts +5 -27
  308. package/src/server/auth/primitives/$auth.ts +52 -19
  309. package/src/server/auth/providers/ServerAuthProvider.ts +145 -139
  310. package/src/server/cookies/providers/ServerCookiesProvider.ts +12 -24
  311. package/src/server/core/index.ts +3 -1
  312. package/src/server/core/primitives/$sse.spec.ts +315 -0
  313. package/src/server/core/primitives/$sse.ts +715 -0
  314. package/src/server/links/index.browser.ts +1 -3
  315. package/src/server/links/index.ts +0 -3
  316. package/src/server/links/providers/LinkProvider.spec.ts +12 -21
  317. package/src/server/links/providers/LinkProvider.ts +20 -52
  318. package/src/server/links/providers/ServerLinksProvider.spec.ts +106 -0
  319. package/src/server/links/providers/ServerLinksProvider.ts +113 -73
  320. package/src/server/links/schemas/apiLinksResponseSchema.ts +4 -21
  321. package/src/server/links/services/BatchCollector.ts +5 -3
  322. package/src/system/index.browser.ts +1 -0
  323. package/src/system/index.ts +3 -0
  324. package/src/system/index.workerd.ts +39 -1
  325. package/src/system/providers/WorkerdFileSystemProvider.ts +365 -0
  326. package/assets/devtools-ui/asset.BfSBZ5Dd.css.br +0 -0
  327. package/assets/devtools-ui/chunk.2NYaoqWt.js +0 -1
  328. package/assets/devtools-ui/chunk.2NYaoqWt.js.br +0 -0
  329. package/assets/devtools-ui/chunk.B052Z_xQ.js +0 -1
  330. package/assets/devtools-ui/chunk.B052Z_xQ.js.br +0 -0
  331. package/assets/devtools-ui/chunk.B4kVY90C.js +0 -1
  332. package/assets/devtools-ui/chunk.B4kVY90C.js.br +0 -0
  333. package/assets/devtools-ui/chunk.B7QJXctB.js +0 -1
  334. package/assets/devtools-ui/chunk.B7QJXctB.js.br +0 -0
  335. package/assets/devtools-ui/chunk.B9pX3zit.js.br +0 -0
  336. package/assets/devtools-ui/chunk.BKF9JxIo.js +0 -1
  337. package/assets/devtools-ui/chunk.BKF9JxIo.js.br +0 -0
  338. package/assets/devtools-ui/chunk.BOHgdTP-.js +0 -1
  339. package/assets/devtools-ui/chunk.BOHgdTP-.js.br +0 -0
  340. package/assets/devtools-ui/chunk.BOVFxkYC.js +0 -1
  341. package/assets/devtools-ui/chunk.BOVFxkYC.js.br +0 -0
  342. package/assets/devtools-ui/chunk.BR842zj5.js +0 -1
  343. package/assets/devtools-ui/chunk.BR842zj5.js.br +0 -0
  344. package/assets/devtools-ui/chunk.BT2IiBkZ.js.br +0 -0
  345. package/assets/devtools-ui/chunk.C79YouPp.js.br +0 -0
  346. package/assets/devtools-ui/chunk.C8mlBrjW.js +0 -9
  347. package/assets/devtools-ui/chunk.C8mlBrjW.js.br +0 -0
  348. package/assets/devtools-ui/chunk.CK0ow3AZ.js +0 -1
  349. package/assets/devtools-ui/chunk.CK0ow3AZ.js.br +0 -0
  350. package/assets/devtools-ui/chunk.CZl6J9DF.js.br +0 -0
  351. package/assets/devtools-ui/chunk.CdNr0YzS.js +0 -1
  352. package/assets/devtools-ui/chunk.CdNr0YzS.js.br +0 -0
  353. package/assets/devtools-ui/chunk.Ce6_6iIF.js +0 -1
  354. package/assets/devtools-ui/chunk.Ce6_6iIF.js.br +0 -0
  355. package/assets/devtools-ui/chunk.CpyDMr6O.js +0 -1
  356. package/assets/devtools-ui/chunk.CpyDMr6O.js.br +0 -0
  357. package/assets/devtools-ui/chunk.CyPmvPnY.js +0 -1
  358. package/assets/devtools-ui/chunk.CyPmvPnY.js.br +0 -0
  359. package/assets/devtools-ui/chunk.DTI_geWu.js +0 -1
  360. package/assets/devtools-ui/chunk.DTI_geWu.js.br +0 -0
  361. package/assets/devtools-ui/chunk.DbEH1oOB.js.br +0 -0
  362. package/assets/devtools-ui/chunk.Ddeqj5gv.js +0 -1
  363. package/assets/devtools-ui/chunk.Ddeqj5gv.js.br +0 -0
  364. package/assets/devtools-ui/chunk.DpRnB4vJ.js +0 -1
  365. package/assets/devtools-ui/chunk.DpRnB4vJ.js.br +0 -0
  366. package/assets/devtools-ui/chunk.DxPGTlsg.js +0 -1
  367. package/assets/devtools-ui/chunk.DxPGTlsg.js.br +0 -0
  368. package/assets/devtools-ui/chunk.G7_MMBJS.js +0 -1
  369. package/assets/devtools-ui/chunk.G7_MMBJS.js.br +0 -0
  370. package/assets/devtools-ui/chunk.M6wyKO_3.js.br +0 -0
  371. package/assets/devtools-ui/chunk.OUxNGmQ6.js +0 -1
  372. package/assets/devtools-ui/chunk.OUxNGmQ6.js.br +0 -0
  373. package/assets/devtools-ui/chunk.T1kle-fF.js +0 -1
  374. package/assets/devtools-ui/chunk.T1kle-fF.js.br +0 -0
  375. package/assets/devtools-ui/chunk.WjpsbQAv.js +0 -1
  376. package/assets/devtools-ui/chunk.WjpsbQAv.js.br +0 -0
  377. package/assets/devtools-ui/chunk.c6YgVx86.js +0 -1
  378. package/assets/devtools-ui/chunk.c6YgVx86.js.br +0 -0
  379. package/assets/devtools-ui/chunk.dwU3E_MU.js +0 -1
  380. package/assets/devtools-ui/chunk.dwU3E_MU.js.br +0 -0
  381. package/assets/devtools-ui/chunk.lJL-lgnW.js.br +0 -0
  382. package/assets/devtools-ui/chunk.lPWRmvA-.js +0 -7
  383. package/assets/devtools-ui/chunk.lPWRmvA-.js.br +0 -0
  384. package/assets/devtools-ui/chunk.p3HJvugM.js +0 -1
  385. package/assets/devtools-ui/chunk.p3HJvugM.js.br +0 -0
  386. package/assets/devtools-ui/chunk.r_Xoa_CI.js +0 -1
  387. package/assets/devtools-ui/chunk.r_Xoa_CI.js.br +0 -0
  388. package/assets/devtools-ui/chunk.sRNuTYXb.js +0 -1
  389. package/assets/devtools-ui/chunk.sRNuTYXb.js.br +0 -0
  390. package/assets/devtools-ui/chunk.tUjcyX5C.js +0 -1
  391. package/assets/devtools-ui/chunk.tUjcyX5C.js.br +0 -0
  392. package/assets/devtools-ui/chunk.thjBxvCA.js +0 -1
  393. package/assets/devtools-ui/chunk.thjBxvCA.js.br +0 -0
  394. package/assets/devtools-ui/entry.GYhBVRpC.js +0 -78
  395. package/assets/devtools-ui/entry.GYhBVRpC.js.br +0 -0
  396. package/src/server/links/services/DefinitionsPool.spec.ts +0 -86
  397. package/src/server/links/services/DefinitionsPool.ts +0 -43
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "alepha",
3
3
  "description": "Easy-to-use modern TypeScript framework for building many kind of applications.",
4
4
  "author": "Nicolas Foures",
5
- "version": "0.18.2",
5
+ "version": "0.18.3",
6
6
  "type": "module",
7
7
  "engines": {
8
8
  "node": ">=22.0.0"
@@ -25,18 +25,18 @@
25
25
  "drizzle-orm": "^0.45.1",
26
26
  "postgres": "^3.4.8",
27
27
  "tsx": "^4.21.0",
28
- "typebox": "^1.1.1",
28
+ "typebox": "^1.1.5",
29
29
  "typescript": "^5.9.3",
30
30
  "vite-bundle-analyzer": "^1.3.6",
31
31
  "ws": "^8.19.0"
32
32
  },
33
33
  "devDependencies": {
34
- "@biomejs/biome": "^2.4.4",
34
+ "@biomejs/biome": "^2.4.5",
35
35
  "@electric-sql/pglite": "^0.3.15",
36
36
  "@faker-js/faker": "^10.3.0",
37
37
  "@testing-library/dom": "^10.4.1",
38
38
  "@testing-library/react": "^16.3.2",
39
- "@types/node": "^25.3.0",
39
+ "@types/node": "^25.3.3",
40
40
  "@types/nodemailer": "^7.0.11",
41
41
  "@types/react": "^19.2.14",
42
42
  "@types/react-dom": "^19.2.3",
@@ -51,7 +51,7 @@
51
51
  "prom-client": "^15.1.3",
52
52
  "react": "^19.2.4",
53
53
  "react-dom": "^19.2.4",
54
- "swagger-ui-dist": "^5.31.2",
54
+ "swagger-ui-dist": "^5.32.0",
55
55
  "tsdown": "^0.20.3",
56
56
  "vite": "^7.3.1",
57
57
  "vitest": "^4.0.18"
@@ -174,6 +174,11 @@
174
174
  "import": "./dist/cache/redis/index.js",
175
175
  "default": "./dist/cache/redis/index.js"
176
176
  },
177
+ "./cli/config": {
178
+ "types": "./dist/cli/config/index.d.ts",
179
+ "import": "./dist/cli/config/index.js",
180
+ "default": "./dist/cli/config/index.js"
181
+ },
177
182
  "./cli": {
178
183
  "types": "./dist/cli/core/index.d.ts",
179
184
  "import": "./dist/cli/core/index.js",
@@ -796,9 +796,12 @@ export class JobProvider {
796
796
  entries.push(entry);
797
797
  });
798
798
 
799
- // Run initial sweeps to recover from previous crashes
800
- await this.delayedDispatchSweep();
801
- await this.recoverySweep();
799
+ // Run initial sweeps to recover from previous crashes.
800
+ // Skipped on serverless — cron triggers handle periodic sweeps instead.
801
+ if (!this.alepha.isServerless()) {
802
+ await this.delayedDispatchSweep();
803
+ await this.recoverySweep();
804
+ }
802
805
 
803
806
  // Periodic sweeps via cron (works in serverless environments like Cloudflare Workers)
804
807
  this.cronProvider.createCronJob(
@@ -0,0 +1,83 @@
1
+ import { $inject, t } from "alepha";
2
+ import { JobService } from "alepha/api/jobs";
3
+ import { $secure } from "alepha/security";
4
+ import { $action } from "alepha/server";
5
+ import { NotificationJobs } from "../jobs/NotificationJobs.ts";
6
+ import { notificationDetailResourceSchema } from "../schemas/notificationDetailResourceSchema.ts";
7
+ import { notificationQuerySchema } from "../schemas/notificationQuerySchema.ts";
8
+ import { notificationResourceSchema } from "../schemas/notificationResourceSchema.ts";
9
+
10
+ export class AdminNotificationController {
11
+ protected readonly url: string = "/notifications";
12
+ protected readonly group: string = "admin:notifications";
13
+ protected readonly jobService = $inject(JobService);
14
+ protected readonly notificationJobs = $inject(NotificationJobs);
15
+
16
+ protected get jobName(): string {
17
+ return this.notificationJobs.sendNotification.name;
18
+ }
19
+
20
+ public readonly findNotifications = $action({
21
+ path: this.url,
22
+ group: this.group,
23
+ use: [$secure({ permissions: ["admin:notification:read"] })],
24
+ schema: {
25
+ query: notificationQuerySchema,
26
+ response: t.page(notificationResourceSchema),
27
+ },
28
+ handler: async ({ query }) => {
29
+ const result = await this.jobService.findExecutions({
30
+ ...query,
31
+ job: this.jobName,
32
+ });
33
+ return {
34
+ ...result,
35
+ content: result.content.map((exec) => this.toResource(exec)),
36
+ } as any;
37
+ },
38
+ });
39
+
40
+ public readonly getNotification = $action({
41
+ path: `${this.url}/:id`,
42
+ group: this.group,
43
+ use: [$secure({ permissions: ["admin:notification:read"] })],
44
+ schema: {
45
+ params: t.object({
46
+ id: t.uuid(),
47
+ }),
48
+ response: notificationDetailResourceSchema,
49
+ },
50
+ handler: async ({ params }) => {
51
+ const detail = await this.jobService.getExecution(params.id);
52
+ return this.toDetailResource(detail) as any;
53
+ },
54
+ });
55
+
56
+ protected toResource(exec: Record<string, unknown>) {
57
+ const payload = (exec.payload ?? {}) as Record<string, unknown>;
58
+ return {
59
+ id: exec.id,
60
+ createdAt: exec.createdAt,
61
+ status: exec.status,
62
+ template: payload.template,
63
+ type: payload.type,
64
+ contact: payload.contact,
65
+ category: payload.category,
66
+ critical: payload.critical,
67
+ sensitive: payload.sensitive,
68
+ startedAt: exec.startedAt,
69
+ completedAt: exec.completedAt,
70
+ error: exec.error,
71
+ };
72
+ }
73
+
74
+ protected toDetailResource(exec: Record<string, unknown>) {
75
+ const payload = (exec.payload ?? {}) as Record<string, unknown>;
76
+ return {
77
+ ...this.toResource(exec),
78
+ variables: payload.variables,
79
+ rendered: exec.result,
80
+ logs: exec.logs,
81
+ };
82
+ }
83
+ }
@@ -4,7 +4,10 @@ import { $module } from "alepha";
4
4
 
5
5
  export * from "./schemas/notificationContactPreferencesSchema.ts";
6
6
  export * from "./schemas/notificationContactSchema.ts";
7
+ export * from "./schemas/notificationDetailResourceSchema.ts";
7
8
  export * from "./schemas/notificationPayloadSchema.ts";
9
+ export * from "./schemas/notificationQuerySchema.ts";
10
+ export * from "./schemas/notificationResourceSchema.ts";
8
11
 
9
12
  // ---------------------------------------------------------------------------------------------------------------------
10
13
 
@@ -1,15 +1,20 @@
1
1
  import { $module } from "alepha";
2
+ import { AdminNotificationController } from "./controllers/AdminNotificationController.ts";
2
3
  import { NotificationJobs } from "./jobs/NotificationJobs.ts";
3
4
  import { $notification } from "./primitives/$notification.ts";
4
5
  import { NotificationSenderService } from "./services/NotificationSenderService.ts";
5
6
 
6
7
  // ---------------------------------------------------------------------------------------------------------------------
7
8
 
9
+ export * from "./controllers/AdminNotificationController.ts";
8
10
  export * from "./jobs/NotificationJobs.ts";
9
11
  export * from "./primitives/$notification.ts";
10
12
  export * from "./schemas/notificationContactPreferencesSchema.ts";
11
13
  export * from "./schemas/notificationContactSchema.ts";
14
+ export * from "./schemas/notificationDetailResourceSchema.ts";
12
15
  export * from "./schemas/notificationPayloadSchema.ts";
16
+ export * from "./schemas/notificationQuerySchema.ts";
17
+ export * from "./schemas/notificationResourceSchema.ts";
13
18
  export * from "./services/NotificationSenderService.ts";
14
19
 
15
20
  // ---------------------------------------------------------------------------------------------------------------------
@@ -28,8 +33,15 @@ export * from "./services/NotificationSenderService.ts";
28
33
  export const AlephaApiNotifications = $module({
29
34
  name: "alepha.api.notifications",
30
35
  primitives: [$notification],
31
- services: [NotificationSenderService, NotificationJobs],
36
+ services: [
37
+ NotificationSenderService,
38
+ NotificationJobs,
39
+ AdminNotificationController,
40
+ ],
32
41
  register: (alepha) => {
33
- alepha.with(NotificationSenderService).with(NotificationJobs);
42
+ alepha
43
+ .with(NotificationSenderService)
44
+ .with(NotificationJobs)
45
+ .with(AdminNotificationController);
34
46
  },
35
47
  });
@@ -1,5 +1,6 @@
1
1
  import { $inject } from "alepha";
2
- import { $job } from "alepha/api/jobs";
2
+ import { $job, jobExecutionEntity } from "alepha/api/jobs";
3
+ import { $repository } from "alepha/orm";
3
4
  import { notificationPayloadSchema } from "../schemas/notificationPayloadSchema.ts";
4
5
  import { NotificationSenderService } from "../services/NotificationSenderService.ts";
5
6
 
@@ -7,6 +8,7 @@ export class NotificationJobs {
7
8
  protected readonly notificationSenderService = $inject(
8
9
  NotificationSenderService,
9
10
  );
11
+ protected readonly executions = $repository(jobExecutionEntity);
10
12
 
11
13
  public readonly sendNotification = $job({
12
14
  schema: notificationPayloadSchema,
@@ -23,7 +25,14 @@ export class NotificationJobs {
23
25
  concurrency: 5,
24
26
  handler: async ({ items }) => {
25
27
  for (const item of items) {
26
- await this.notificationSenderService.send(item.payload);
28
+ const rendered = await this.notificationSenderService.send(
29
+ item.payload,
30
+ );
31
+ if (rendered) {
32
+ await this.executions.updateById(item.id, {
33
+ result: rendered as Record<string, unknown>,
34
+ });
35
+ }
27
36
  }
28
37
  },
29
38
  });
@@ -0,0 +1,20 @@
1
+ import { type Static, t } from "alepha";
2
+ import { logEntrySchema } from "alepha/logger";
3
+ import { notificationResourceSchema } from "./notificationResourceSchema.ts";
4
+
5
+ export const notificationDetailResourceSchema = t.extend(
6
+ notificationResourceSchema,
7
+ {
8
+ variables: t.optional(t.record(t.text(), t.any())),
9
+ rendered: t.optional(t.record(t.text(), t.any())),
10
+ logs: t.optional(t.array(logEntrySchema)),
11
+ },
12
+ {
13
+ title: "NotificationDetailResource",
14
+ description: "A notification resource with rendered content and logs.",
15
+ },
16
+ );
17
+
18
+ export type NotificationDetailResource = Static<
19
+ typeof notificationDetailResourceSchema
20
+ >;
@@ -0,0 +1,19 @@
1
+ import { type Static, t } from "alepha";
2
+ import { pageQuerySchema } from "alepha/orm";
3
+
4
+ export const notificationQuerySchema = t.extend(pageQuerySchema, {
5
+ status: t.optional(
6
+ t.enum([
7
+ "pending",
8
+ "scheduled",
9
+ "retrying",
10
+ "running",
11
+ "completed",
12
+ "failed",
13
+ "dead",
14
+ "cancelled",
15
+ ]),
16
+ ),
17
+ });
18
+
19
+ export type NotificationQuery = Static<typeof notificationQuerySchema>;
@@ -0,0 +1,18 @@
1
+ import { type Static, t } from "alepha";
2
+
3
+ export const notificationResourceSchema = t.object({
4
+ id: t.uuid(),
5
+ createdAt: t.datetime(),
6
+ status: t.text(),
7
+ template: t.optional(t.text()),
8
+ type: t.optional(t.text()),
9
+ contact: t.optional(t.text()),
10
+ category: t.optional(t.text()),
11
+ critical: t.optional(t.boolean()),
12
+ sensitive: t.optional(t.boolean()),
13
+ startedAt: t.optional(t.datetime()),
14
+ completedAt: t.optional(t.datetime()),
15
+ error: t.optional(t.text()),
16
+ });
17
+
18
+ export type NotificationResource = Static<typeof notificationResourceSchema>;
@@ -19,19 +19,32 @@ export class NotificationSenderService {
19
19
  });
20
20
 
21
21
  if (payload.type === "email") {
22
- await this.emailProvider.send(this.renderEmail(payload));
22
+ const rendered = this.renderEmail(payload);
23
+ await this.emailProvider.send(rendered);
23
24
  this.log.info("Email notification sent", {
24
25
  template: payload.template,
25
26
  contact: payload.contact,
26
27
  });
28
+ return {
29
+ type: "email" as const,
30
+ to: rendered.to,
31
+ subject: rendered.subject,
32
+ body: rendered.body,
33
+ };
27
34
  }
28
35
 
29
36
  if (payload.type === "sms") {
30
- await this.smsProvider.send(this.renderSms(payload));
37
+ const rendered = this.renderSms(payload);
38
+ await this.smsProvider.send(rendered);
31
39
  this.log.info("SMS notification sent", {
32
40
  template: payload.template,
33
41
  contact: payload.contact,
34
42
  });
43
+ return {
44
+ type: "sms" as const,
45
+ to: rendered.to,
46
+ message: rendered.message,
47
+ };
35
48
  }
36
49
  }
37
50
 
@@ -1,5 +1,19 @@
1
1
  import { $atom, type Static, t } from "alepha";
2
2
 
3
+ /**
4
+ * Tri-state field requirement for realm auth settings.
5
+ *
6
+ * - `"none"`: Field is disabled and not shown.
7
+ * - `"optional"`: Field is shown but not required.
8
+ * - `"required"`: Field is shown and required.
9
+ */
10
+ export type FieldRequirement = "none" | "optional" | "required";
11
+
12
+ const fieldRequirement = (description: string) =>
13
+ t.union([t.const("none"), t.const("optional"), t.const("required")], {
14
+ description,
15
+ });
16
+
3
17
  export const realmAuthSettingsAtom = $atom({
4
18
  name: "alepha.api.users.realmAuthSettings",
5
19
  schema: t.object({
@@ -25,40 +39,26 @@ export const realmAuthSettingsAtom = $atom({
25
39
  registrationAllowed: t.boolean({
26
40
  description: "Enable user self-registration",
27
41
  }),
28
- emailEnabled: t.boolean({
29
- description: "Enable email address as a login/registration credential",
30
- }),
31
- emailRequired: t.boolean({
32
- description: "Require email address for user accounts",
33
- }),
34
- usernameEnabled: t.boolean({
35
- description: "Enable username as a login/registration credential",
36
- }),
37
- usernameRequired: t.boolean({
38
- description: "Require username for user accounts",
39
- }),
42
+ email: fieldRequirement(
43
+ "Email address field requirement for user accounts",
44
+ ),
45
+ username: fieldRequirement("Username field requirement for user accounts"),
40
46
  usernameRegExp: t.string({
41
47
  description:
42
48
  "Regular expression that usernames must match (if username is enabled)",
43
49
  }),
44
- phoneEnabled: t.boolean({
45
- description: "Enable phone number as a login/registration credential",
46
- }),
47
- phoneRequired: t.boolean({
48
- description: "Require phone number for user accounts",
49
- }),
50
+ phoneNumber: fieldRequirement(
51
+ "Phone number field requirement for user accounts",
52
+ ),
50
53
  verifyEmailRequired: t.boolean({
51
54
  description: "Require email verification for user accounts",
52
55
  }),
53
56
  verifyPhoneRequired: t.boolean({
54
57
  description: "Require phone verification for user accounts",
55
58
  }),
56
- firstNameLastNameEnabled: t.boolean({
57
- description: "Enable first and last name for user accounts",
58
- }),
59
- firstNameLastNameRequired: t.boolean({
60
- description: "Require first and last name for user accounts",
61
- }),
59
+ firstNameLastName: fieldRequirement(
60
+ "First and last name field requirement for user accounts",
61
+ ),
62
62
  resetPasswordAllowed: t.boolean({
63
63
  description: "Enable forgot password functionality",
64
64
  }),
@@ -93,18 +93,14 @@ export const realmAuthSettingsAtom = $atom({
93
93
  default: {
94
94
  // for a fresh hello world setup, we accept registration and email login
95
95
  registrationAllowed: true,
96
- emailEnabled: true,
97
- emailRequired: true,
98
- usernameEnabled: false,
99
- usernameRequired: false,
96
+ email: "required" as FieldRequirement,
97
+ username: "none" as FieldRequirement,
100
98
  usernameRegExp: "^[a-zA-Z0-9_]{3,30}$",
101
- phoneEnabled: false,
102
- phoneRequired: false,
99
+ phoneNumber: "none" as FieldRequirement,
103
100
  verifyEmailRequired: false,
104
101
  verifyPhoneRequired: false,
105
102
  resetPasswordAllowed: false,
106
- firstNameLastNameEnabled: false,
107
- firstNameLastNameRequired: false,
103
+ firstNameLastName: "none" as FieldRequirement,
108
104
  adminEmails: [],
109
105
  adminUsernames: [],
110
106
  // TODO: not implemented yet
@@ -6,7 +6,7 @@ import { $bucket } from "alepha/bucket";
6
6
  * This service provides file storage for user-related files such as:
7
7
  * - User avatars/profile pictures
8
8
  *
9
- * It is lazy-loaded when the `files` feature is enabled in the realm.
9
+ * It is lazy-loaded when the `avatars` feature is enabled in the realm.
10
10
  */
11
11
  export class UserBuckets {
12
12
  /**
@@ -13,7 +13,7 @@ import { sessions } from "../entities/sessions.ts";
13
13
  * - Verification code cleanup
14
14
  * - Inactive user notifications
15
15
  *
16
- * It is lazy-loaded when the `jobs` feature is enabled in the realm.
16
+ * It is lazy-loaded when the `sessionPurge` feature is enabled in the realm.
17
17
  */
18
18
  export class UserJobs {
19
19
  protected readonly log = $logger();
@@ -57,28 +57,14 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
57
57
 
58
58
  options.settings ??= {};
59
59
 
60
- if (options.settings.emailRequired) {
61
- options.settings.emailEnabled = true;
62
- }
63
-
64
- if (options.settings.usernameRequired) {
65
- options.settings.usernameEnabled = true;
66
- }
67
-
68
- if (options.settings.phoneRequired) {
69
- options.settings.phoneEnabled = true;
70
- }
71
-
72
60
  // Merge features with defaults
73
61
  const features: RealmFeatures = {
74
- jobs: false,
62
+ sessionPurge: false,
75
63
  notifications: false,
76
64
  apiKeys: false,
77
- clients: false,
78
65
  parameters: false,
79
- files: false,
66
+ avatars: false,
80
67
  audits: false,
81
- organizations: false,
82
68
  ...options.features,
83
69
  };
84
70
 
@@ -97,7 +83,7 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
97
83
  // Enable features based on configuration
98
84
  // Each feature registers its wrapper service which internally uses the module primitives
99
85
 
100
- if (features.files) {
86
+ if (features.avatars) {
101
87
  alepha.with(UserBuckets);
102
88
  }
103
89
 
@@ -105,7 +91,7 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
105
91
  alepha.with(UserAudits);
106
92
  }
107
93
 
108
- if (features.jobs) {
94
+ if (features.sessionPurge) {
109
95
  alepha.with(UserJobs);
110
96
  }
111
97
 
@@ -226,11 +212,11 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
226
212
 
227
213
  export interface RealmFeatures {
228
214
  /**
229
- * Enable job execution tracking and purge functionality.
215
+ * Enable session purge functionality for cleaning up expired sessions.
230
216
  *
231
217
  * @default false
232
218
  */
233
- jobs?: boolean;
219
+ sessionPurge?: boolean;
234
220
 
235
221
  /**
236
222
  * Enable notification system for password reset, verification emails, etc.
@@ -256,26 +242,6 @@ export interface RealmFeatures {
256
242
  */
257
243
  apiKeys?: boolean;
258
244
 
259
- /**
260
- * Enable OAuth2 Authorization Server for third-party client authentication.
261
- *
262
- * When enabled, Alepha acts as an OAuth2 Authorization Server, allowing
263
- * third-party applications to authenticate users via standard OAuth2 flows:
264
- * - Authorization Code + PKCE (OAuth 2.1)
265
- * - Client Credentials (machine-to-machine)
266
- * - Refresh Token
267
- *
268
- * Also provides:
269
- * - Token introspection (RFC 7662)
270
- * - Token revocation (RFC 7009)
271
- * - AS metadata (RFC 8414)
272
- * - Protected Resource metadata (RFC 9728)
273
- * - MCP-compatible OAuth2 flow
274
- *
275
- * @default false
276
- */
277
- clients?: boolean;
278
-
279
245
  /**
280
246
  * Enable runtime configuration management.
281
247
  *
@@ -286,11 +252,11 @@ export interface RealmFeatures {
286
252
  parameters?: boolean;
287
253
 
288
254
  /**
289
- * Enable file management for avatar uploads and attachments.
255
+ * Enable avatar uploads for user profiles.
290
256
  *
291
257
  * @default false
292
258
  */
293
- files?: boolean;
259
+ avatars?: boolean;
294
260
 
295
261
  /**
296
262
  * Enable audit trail for compliance and event logging.
@@ -298,13 +264,6 @@ export interface RealmFeatures {
298
264
  * @default false
299
265
  */
300
266
  audits?: boolean;
301
-
302
- /**
303
- * Enable organization management to group users.
304
- *
305
- * @default false
306
- */
307
- organizations?: boolean;
308
267
  }
309
268
 
310
269
  // ---------------------------------------------------------------------------------------------------------------------
@@ -34,13 +34,12 @@ export class RealmProvider {
34
34
  public register(realmName: string, realmOptions: RealmOptions = {}) {
35
35
  // Merge features with defaults
36
36
  const features: RealmFeatures = {
37
- jobs: false,
37
+ sessionPurge: false,
38
38
  notifications: false,
39
39
  apiKeys: false,
40
40
  parameters: false,
41
- files: false,
41
+ avatars: false,
42
42
  audits: false,
43
- organizations: false,
44
43
  ...realmOptions.features,
45
44
  };
46
45
 
@@ -146,7 +146,7 @@ describe("alepha/api/users - RegistrationService", () => {
146
146
 
147
147
  realmProvider.register("username-required-realm", {
148
148
  settings: {
149
- usernameRequired: true,
149
+ username: "required",
150
150
  } as never,
151
151
  });
152
152
 
@@ -180,8 +180,8 @@ describe("alepha/api/users - RegistrationService", () => {
180
180
 
181
181
  realmProvider.register("phone-required-realm", {
182
182
  settings: {
183
- phoneRequired: true,
184
- emailRequired: false,
183
+ phoneNumber: "required",
184
+ email: "optional",
185
185
  } as never,
186
186
  });
187
187
 
@@ -240,8 +240,8 @@ describe("alepha/api/users - RegistrationService", () => {
240
240
 
241
241
  realmProvider.register("phone-realm", {
242
242
  settings: {
243
- phoneEnabled: true,
244
- emailRequired: false,
243
+ phoneNumber: "optional",
244
+ email: "optional",
245
245
  } as never,
246
246
  });
247
247
 
@@ -530,7 +530,7 @@ describe("alepha/api/users - RegistrationService", () => {
530
530
  expect,
531
531
  }) => {
532
532
  const { registrationService, sessionService } = await setup({
533
- usernameEnabled: true,
533
+ username: "optional",
534
534
  });
535
535
 
536
536
  const intent = await registrationService.createRegistrationIntent({
@@ -559,7 +559,7 @@ describe("alepha/api/users - RegistrationService", () => {
559
559
  expect,
560
560
  }) => {
561
561
  const { registrationService, sessionService } = await setup({
562
- usernameEnabled: true,
562
+ username: "optional",
563
563
  });
564
564
 
565
565
  // Phase 1: Create intent
@@ -97,7 +97,7 @@ export class RegistrationService {
97
97
  }
98
98
 
99
99
  // Validate required fields based on settings
100
- if (realmSettings?.usernameRequired && !body.username) {
100
+ if (realmSettings?.username === "required" && !body.username) {
101
101
  this.log.debug("Registration rejected: username required", {
102
102
  userRealmName,
103
103
  });
@@ -120,14 +120,14 @@ export class RegistrationService {
120
120
  }
121
121
  }
122
122
 
123
- if (realmSettings?.emailRequired !== false && !body.email) {
123
+ if (realmSettings?.email === "required" && !body.email) {
124
124
  this.log.debug("Registration rejected: email required", {
125
125
  userRealmName,
126
126
  });
127
127
  throw new BadRequestError("Email is required");
128
128
  }
129
129
 
130
- if (realmSettings?.phoneRequired && !body.phoneNumber) {
130
+ if (realmSettings?.phoneNumber === "required" && !body.phoneNumber) {
131
131
  this.log.debug("Registration rejected: phone required", {
132
132
  userRealmName,
133
133
  });