alepha 0.13.1 → 0.13.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 (329) hide show
  1. package/README.md +1 -1
  2. package/dist/api-files/index.browser.js +80 -0
  3. package/dist/api-files/index.browser.js.map +1 -0
  4. package/dist/api-files/index.d.ts +28 -91
  5. package/dist/api-files/index.js +10 -755
  6. package/dist/api-files/index.js.map +1 -1
  7. package/dist/api-jobs/index.browser.js +56 -0
  8. package/dist/api-jobs/index.browser.js.map +1 -0
  9. package/dist/api-jobs/index.d.ts +46 -46
  10. package/dist/api-jobs/index.js +13 -13
  11. package/dist/api-jobs/index.js.map +1 -1
  12. package/dist/api-notifications/index.browser.js +382 -0
  13. package/dist/api-notifications/index.browser.js.map +1 -0
  14. package/dist/api-notifications/index.d.ts +231 -193
  15. package/dist/api-notifications/index.js +108 -78
  16. package/dist/api-notifications/index.js.map +1 -1
  17. package/dist/api-parameters/index.browser.js +29 -0
  18. package/dist/api-parameters/index.browser.js.map +1 -0
  19. package/dist/api-parameters/index.d.ts +21 -22
  20. package/dist/api-parameters/index.js +22 -22
  21. package/dist/api-parameters/index.js.map +1 -1
  22. package/dist/api-users/index.d.ts +237 -2001
  23. package/dist/api-users/index.js +969 -4795
  24. package/dist/api-users/index.js.map +1 -1
  25. package/dist/api-verifications/index.browser.js +52 -0
  26. package/dist/api-verifications/index.browser.js.map +1 -0
  27. package/dist/api-verifications/index.d.ts +119 -97
  28. package/dist/api-verifications/index.js +1 -1
  29. package/dist/api-verifications/index.js.map +1 -1
  30. package/dist/batch/index.d.ts +13 -13
  31. package/dist/batch/index.js +8 -13
  32. package/dist/batch/index.js.map +1 -1
  33. package/dist/bucket/index.d.ts +14 -14
  34. package/dist/bucket/index.js +19 -17
  35. package/dist/bucket/index.js.map +1 -1
  36. package/dist/cache/index.d.ts +11 -11
  37. package/dist/cache/index.js +9 -9
  38. package/dist/cache/index.js.map +1 -1
  39. package/dist/cli/{dist-Dl9Vl7Ur.js → dist-lGnqsKpu.js} +11 -15
  40. package/dist/cli/dist-lGnqsKpu.js.map +1 -0
  41. package/dist/cli/index.d.ts +32 -49
  42. package/dist/cli/index.js +90 -71
  43. package/dist/cli/index.js.map +1 -1
  44. package/dist/command/index.d.ts +20 -19
  45. package/dist/command/index.js +34 -25
  46. package/dist/command/index.js.map +1 -1
  47. package/dist/core/index.browser.js +218 -218
  48. package/dist/core/index.browser.js.map +1 -1
  49. package/dist/core/index.d.ts +232 -232
  50. package/dist/core/index.js +218 -218
  51. package/dist/core/index.js.map +1 -1
  52. package/dist/core/index.native.js +2113 -0
  53. package/dist/core/index.native.js.map +1 -0
  54. package/dist/datetime/index.d.ts +9 -9
  55. package/dist/datetime/index.js +7 -7
  56. package/dist/datetime/index.js.map +1 -1
  57. package/dist/email/index.d.ts +16 -16
  58. package/dist/email/index.js +14 -9
  59. package/dist/email/index.js.map +1 -1
  60. package/dist/file/index.js +1 -1
  61. package/dist/file/index.js.map +1 -1
  62. package/dist/lock/index.d.ts +9 -9
  63. package/dist/lock/index.js +8 -8
  64. package/dist/lock/index.js.map +1 -1
  65. package/dist/lock-redis/index.js +3 -66
  66. package/dist/lock-redis/index.js.map +1 -1
  67. package/dist/logger/index.d.ts +5 -5
  68. package/dist/logger/index.js +8 -8
  69. package/dist/logger/index.js.map +1 -1
  70. package/dist/orm/index.browser.js +114 -114
  71. package/dist/orm/index.browser.js.map +1 -1
  72. package/dist/orm/index.d.ts +218 -218
  73. package/dist/orm/index.js +49 -49
  74. package/dist/orm/index.js.map +1 -1
  75. package/dist/queue/index.d.ts +29 -29
  76. package/dist/queue/index.js +20 -20
  77. package/dist/queue/index.js.map +1 -1
  78. package/dist/queue-redis/index.d.ts +2 -2
  79. package/dist/redis/index.d.ts +4 -4
  80. package/dist/retry/index.d.ts +19 -19
  81. package/dist/retry/index.js +7 -7
  82. package/dist/retry/index.js.map +1 -1
  83. package/dist/scheduler/index.d.ts +16 -16
  84. package/dist/scheduler/index.js +9 -9
  85. package/dist/scheduler/index.js.map +1 -1
  86. package/dist/security/index.d.ts +53 -53
  87. package/dist/security/index.js +35 -35
  88. package/dist/security/index.js.map +1 -1
  89. package/dist/server/index.browser.js +1 -1
  90. package/dist/server/index.browser.js.map +1 -1
  91. package/dist/server/index.d.ts +92 -92
  92. package/dist/server/index.js +16 -16
  93. package/dist/server/index.js.map +1 -1
  94. package/dist/server-auth/index.browser.js +4 -982
  95. package/dist/server-auth/index.browser.js.map +1 -1
  96. package/dist/server-auth/index.d.ts +204 -785
  97. package/dist/server-auth/index.js +47 -1239
  98. package/dist/server-auth/index.js.map +1 -1
  99. package/dist/server-cache/index.d.ts +10 -10
  100. package/dist/server-cache/index.js +2 -2
  101. package/dist/server-cache/index.js.map +1 -1
  102. package/dist/server-compress/index.d.ts +4 -4
  103. package/dist/server-compress/index.js +1 -1
  104. package/dist/server-compress/index.js.map +1 -1
  105. package/dist/server-cookies/index.browser.js +8 -8
  106. package/dist/server-cookies/index.browser.js.map +1 -1
  107. package/dist/server-cookies/index.d.ts +17 -17
  108. package/dist/server-cookies/index.js +11 -11
  109. package/dist/server-cookies/index.js.map +1 -1
  110. package/dist/server-cors/index.d.ts +17 -17
  111. package/dist/server-cors/index.js +9 -9
  112. package/dist/server-cors/index.js.map +1 -1
  113. package/dist/server-health/index.d.ts +19 -19
  114. package/dist/server-helmet/index.d.ts +1 -1
  115. package/dist/server-links/index.browser.js +12 -12
  116. package/dist/server-links/index.browser.js.map +1 -1
  117. package/dist/server-links/index.d.ts +59 -251
  118. package/dist/server-links/index.js +23 -502
  119. package/dist/server-links/index.js.map +1 -1
  120. package/dist/server-metrics/index.d.ts +4 -4
  121. package/dist/server-multipart/index.d.ts +2 -2
  122. package/dist/server-proxy/index.d.ts +12 -12
  123. package/dist/server-proxy/index.js +10 -10
  124. package/dist/server-proxy/index.js.map +1 -1
  125. package/dist/server-rate-limit/index.d.ts +22 -22
  126. package/dist/server-rate-limit/index.js +12 -12
  127. package/dist/server-rate-limit/index.js.map +1 -1
  128. package/dist/server-security/index.d.ts +22 -22
  129. package/dist/server-security/index.js +15 -15
  130. package/dist/server-security/index.js.map +1 -1
  131. package/dist/server-static/index.d.ts +14 -14
  132. package/dist/server-static/index.js +26 -10
  133. package/dist/server-static/index.js.map +1 -1
  134. package/dist/server-swagger/index.d.ts +25 -184
  135. package/dist/server-swagger/index.js +21 -724
  136. package/dist/server-swagger/index.js.map +1 -1
  137. package/dist/sms/index.d.ts +14 -14
  138. package/dist/sms/index.js +9 -9
  139. package/dist/sms/index.js.map +1 -1
  140. package/dist/thread/index.d.ts +11 -11
  141. package/dist/thread/index.js +17 -17
  142. package/dist/thread/index.js.map +1 -1
  143. package/dist/topic/index.d.ts +26 -26
  144. package/dist/topic/index.js +16 -16
  145. package/dist/topic/index.js.map +1 -1
  146. package/dist/topic-redis/index.d.ts +1 -1
  147. package/dist/vite/index.d.ts +3 -3
  148. package/dist/vite/index.js +8 -8
  149. package/dist/vite/index.js.map +1 -1
  150. package/dist/websocket/index.browser.js +11 -11
  151. package/dist/websocket/index.browser.js.map +1 -1
  152. package/dist/websocket/index.d.ts +58 -58
  153. package/dist/websocket/index.js +13 -13
  154. package/dist/websocket/index.js.map +1 -1
  155. package/package.json +128 -57
  156. package/src/api-files/index.browser.ts +17 -0
  157. package/src/api-files/services/FileService.ts +5 -7
  158. package/src/api-jobs/index.browser.ts +15 -0
  159. package/src/api-jobs/index.ts +1 -1
  160. package/src/api-jobs/{descriptors → primitives}/$job.ts +8 -8
  161. package/src/api-jobs/providers/JobProvider.ts +9 -9
  162. package/src/api-jobs/services/JobService.ts +5 -5
  163. package/src/api-notifications/controllers/NotificationController.ts +26 -1
  164. package/src/api-notifications/index.browser.ts +17 -0
  165. package/src/api-notifications/index.ts +6 -15
  166. package/src/api-notifications/{descriptors → primitives}/$notification.ts +10 -10
  167. package/src/api-notifications/schemas/notificationQuerySchema.ts +13 -0
  168. package/src/api-notifications/services/NotificationSenderService.ts +3 -3
  169. package/src/api-notifications/services/NotificationService.ts +45 -2
  170. package/src/api-parameters/index.browser.ts +12 -0
  171. package/src/api-parameters/index.ts +1 -1
  172. package/src/api-parameters/{descriptors → primitives}/$config.ts +7 -12
  173. package/src/api-users/atoms/realmAuthSettingsAtom.ts +3 -1
  174. package/src/api-users/controllers/UserController.ts +21 -1
  175. package/src/api-users/index.ts +1 -1
  176. package/src/api-users/{descriptors → primitives}/$userRealm.ts +40 -17
  177. package/src/api-users/providers/UserRealmProvider.ts +2 -1
  178. package/src/api-users/services/SessionService.ts +2 -0
  179. package/src/api-users/services/UserService.ts +56 -16
  180. package/src/api-verifications/index.browser.ts +15 -0
  181. package/src/api-verifications/index.ts +1 -0
  182. package/src/batch/index.ts +3 -3
  183. package/src/batch/{descriptors → primitives}/$batch.ts +13 -16
  184. package/src/batch/providers/BatchProvider.ts +0 -7
  185. package/src/bucket/index.ts +15 -13
  186. package/src/bucket/{descriptors → primitives}/$bucket.ts +8 -8
  187. package/src/bucket/providers/LocalFileStorageProvider.ts +3 -3
  188. package/src/cache/index.ts +4 -4
  189. package/src/cache/{descriptors → primitives}/$cache.ts +15 -15
  190. package/src/cli/apps/AlephaCli.ts +27 -1
  191. package/src/cli/apps/AlephaPackageBuilderCli.ts +27 -2
  192. package/src/cli/commands/CoreCommands.ts +6 -2
  193. package/src/cli/commands/DrizzleCommands.ts +6 -6
  194. package/src/cli/commands/VerifyCommands.ts +1 -1
  195. package/src/cli/commands/ViteCommands.ts +8 -2
  196. package/src/cli/services/ProjectUtils.ts +74 -78
  197. package/src/command/helpers/Asker.ts +10 -0
  198. package/src/command/index.ts +5 -5
  199. package/src/command/{descriptors → primitives}/$command.ts +9 -12
  200. package/src/command/providers/CliProvider.ts +10 -10
  201. package/src/core/Alepha.ts +30 -33
  202. package/src/core/constants/KIND.ts +1 -1
  203. package/src/core/constants/OPTIONS.ts +1 -1
  204. package/src/core/helpers/{descriptor.ts → primitive.ts} +18 -18
  205. package/src/core/helpers/ref.ts +1 -1
  206. package/src/core/index.shared.ts +8 -8
  207. package/src/core/{descriptors → primitives}/$context.ts +5 -5
  208. package/src/core/{descriptors → primitives}/$hook.ts +4 -4
  209. package/src/core/{descriptors → primitives}/$inject.ts +2 -2
  210. package/src/core/{descriptors → primitives}/$module.ts +9 -9
  211. package/src/core/{descriptors → primitives}/$use.ts +2 -2
  212. package/src/core/providers/CodecManager.ts +1 -1
  213. package/src/core/providers/JsonSchemaCodec.ts +1 -1
  214. package/src/core/providers/StateManager.ts +2 -2
  215. package/src/datetime/index.ts +3 -3
  216. package/src/datetime/{descriptors → primitives}/$interval.ts +6 -6
  217. package/src/email/index.ts +17 -9
  218. package/src/email/{descriptors → primitives}/$email.ts +8 -8
  219. package/src/file/index.ts +1 -1
  220. package/src/lock/index.ts +3 -3
  221. package/src/lock/{descriptors → primitives}/$lock.ts +10 -10
  222. package/src/logger/index.ts +8 -8
  223. package/src/logger/{descriptors → primitives}/$logger.ts +2 -2
  224. package/src/logger/services/Logger.ts +1 -1
  225. package/src/orm/constants/PG_SYMBOLS.ts +2 -2
  226. package/src/orm/index.browser.ts +2 -2
  227. package/src/orm/index.ts +8 -8
  228. package/src/orm/{descriptors → primitives}/$entity.ts +11 -11
  229. package/src/orm/{descriptors → primitives}/$repository.ts +2 -2
  230. package/src/orm/{descriptors → primitives}/$sequence.ts +8 -8
  231. package/src/orm/{descriptors → primitives}/$transaction.ts +4 -4
  232. package/src/orm/providers/PostgresTypeProvider.ts +3 -3
  233. package/src/orm/providers/RepositoryProvider.ts +4 -4
  234. package/src/orm/providers/drivers/DatabaseProvider.ts +7 -7
  235. package/src/orm/providers/drivers/NodeSqliteProvider.ts +3 -3
  236. package/src/orm/services/ModelBuilder.ts +9 -9
  237. package/src/orm/services/PgRelationManager.ts +2 -2
  238. package/src/orm/services/PostgresModelBuilder.ts +5 -5
  239. package/src/orm/services/Repository.ts +7 -7
  240. package/src/orm/services/SqliteModelBuilder.ts +5 -5
  241. package/src/queue/index.ts +7 -7
  242. package/src/queue/{descriptors → primitives}/$consumer.ts +15 -15
  243. package/src/queue/{descriptors → primitives}/$queue.ts +12 -12
  244. package/src/queue/providers/WorkerProvider.ts +7 -7
  245. package/src/retry/index.ts +3 -3
  246. package/src/retry/{descriptors → primitives}/$retry.ts +14 -14
  247. package/src/scheduler/index.ts +3 -3
  248. package/src/scheduler/{descriptors → primitives}/$scheduler.ts +9 -9
  249. package/src/scheduler/providers/CronProvider.ts +1 -1
  250. package/src/security/index.ts +9 -9
  251. package/src/security/{descriptors → primitives}/$permission.ts +7 -7
  252. package/src/security/{descriptors → primitives}/$realm.ts +6 -12
  253. package/src/security/{descriptors → primitives}/$role.ts +12 -12
  254. package/src/security/{descriptors → primitives}/$serviceAccount.ts +8 -8
  255. package/src/server/index.browser.ts +1 -1
  256. package/src/server/index.ts +14 -14
  257. package/src/server/{descriptors → primitives}/$action.ts +13 -13
  258. package/src/server/{descriptors → primitives}/$route.ts +9 -9
  259. package/src/server/providers/NodeHttpServerProvider.ts +1 -1
  260. package/src/server/services/HttpClient.ts +1 -1
  261. package/src/server-auth/index.browser.ts +1 -1
  262. package/src/server-auth/index.ts +6 -6
  263. package/src/server-auth/{descriptors → primitives}/$auth.ts +10 -10
  264. package/src/server-auth/{descriptors → primitives}/$authCredentials.ts +4 -4
  265. package/src/server-auth/{descriptors → primitives}/$authGithub.ts +4 -4
  266. package/src/server-auth/{descriptors → primitives}/$authGoogle.ts +4 -4
  267. package/src/server-auth/providers/ServerAuthProvider.ts +4 -4
  268. package/src/server-cache/providers/ServerCacheProvider.ts +7 -7
  269. package/src/server-compress/providers/ServerCompressProvider.ts +3 -3
  270. package/src/server-cookies/index.browser.ts +2 -2
  271. package/src/server-cookies/index.ts +5 -5
  272. package/src/server-cookies/{descriptors → primitives}/$cookie.browser.ts +12 -12
  273. package/src/server-cookies/{descriptors → primitives}/$cookie.ts +13 -13
  274. package/src/server-cookies/providers/ServerCookiesProvider.ts +6 -5
  275. package/src/server-cookies/services/CookieParser.ts +1 -1
  276. package/src/server-cors/index.ts +3 -3
  277. package/src/server-cors/{descriptors → primitives}/$cors.ts +11 -13
  278. package/src/server-cors/providers/ServerCorsProvider.ts +5 -5
  279. package/src/server-links/index.browser.ts +5 -5
  280. package/src/server-links/index.ts +9 -9
  281. package/src/server-links/{descriptors → primitives}/$remote.ts +11 -11
  282. package/src/server-links/providers/LinkProvider.ts +7 -7
  283. package/src/server-links/providers/{RemoteDescriptorProvider.ts → RemotePrimitiveProvider.ts} +6 -6
  284. package/src/server-links/providers/ServerLinksProvider.ts +3 -3
  285. package/src/server-proxy/index.ts +3 -3
  286. package/src/server-proxy/{descriptors → primitives}/$proxy.ts +8 -8
  287. package/src/server-proxy/providers/ServerProxyProvider.ts +4 -4
  288. package/src/server-rate-limit/index.ts +6 -6
  289. package/src/server-rate-limit/{descriptors → primitives}/$rateLimit.ts +13 -13
  290. package/src/server-rate-limit/providers/ServerRateLimitProvider.ts +5 -5
  291. package/src/server-security/index.ts +3 -3
  292. package/src/server-security/{descriptors → primitives}/$basicAuth.ts +13 -13
  293. package/src/server-security/providers/ServerBasicAuthProvider.ts +5 -5
  294. package/src/server-security/providers/ServerSecurityProvider.ts +4 -4
  295. package/src/server-static/index.ts +3 -3
  296. package/src/server-static/{descriptors → primitives}/$serve.ts +8 -10
  297. package/src/server-static/providers/ServerStaticProvider.ts +24 -9
  298. package/src/server-swagger/index.ts +5 -5
  299. package/src/server-swagger/{descriptors → primitives}/$swagger.ts +9 -9
  300. package/src/server-swagger/providers/ServerSwaggerProvider.ts +11 -10
  301. package/src/sms/index.ts +4 -4
  302. package/src/sms/{descriptors → primitives}/$sms.ts +8 -8
  303. package/src/thread/index.ts +3 -3
  304. package/src/thread/{descriptors → primitives}/$thread.ts +13 -13
  305. package/src/thread/providers/ThreadProvider.ts +7 -9
  306. package/src/topic/index.ts +5 -5
  307. package/src/topic/{descriptors → primitives}/$subscriber.ts +14 -14
  308. package/src/topic/{descriptors → primitives}/$topic.ts +10 -10
  309. package/src/topic/providers/TopicProvider.ts +4 -4
  310. package/src/vite/tasks/copyAssets.ts +1 -1
  311. package/src/vite/tasks/generateSitemap.ts +3 -3
  312. package/src/vite/tasks/prerenderPages.ts +2 -2
  313. package/src/vite/tasks/runAlepha.ts +2 -2
  314. package/src/websocket/index.browser.ts +3 -3
  315. package/src/websocket/index.shared.ts +2 -2
  316. package/src/websocket/index.ts +4 -4
  317. package/src/websocket/interfaces/WebSocketInterfaces.ts +3 -3
  318. package/src/websocket/{descriptors → primitives}/$channel.ts +10 -10
  319. package/src/websocket/{descriptors → primitives}/$websocket.ts +8 -8
  320. package/src/websocket/providers/NodeWebSocketServerProvider.ts +7 -7
  321. package/src/websocket/providers/WebSocketServerProvider.ts +3 -3
  322. package/src/websocket/services/WebSocketClient.ts +5 -5
  323. package/dist/cli/dist-Dl9Vl7Ur.js.map +0 -1
  324. package/src/api-notifications/providers/MemorySmsProvider.ts +0 -20
  325. package/src/api-notifications/providers/SmsProvider.ts +0 -8
  326. /package/src/core/{descriptors → primitives}/$atom.ts +0 -0
  327. /package/src/core/{descriptors → primitives}/$env.ts +0 -0
  328. /package/src/server-auth/{descriptors → primitives}/$authApple.ts +0 -0
  329. /package/src/server-links/{descriptors → primitives}/$client.ts +0 -0
@@ -1,9 +1,7 @@
1
1
  import { $module } from "alepha";
2
2
  import { NotificationController } from "./controllers/NotificationController.ts";
3
- import { $notification } from "./descriptors/$notification.ts";
4
3
  import { NotificationJobs } from "./jobs/NotificationJobs.ts";
5
- import { MemorySmsProvider } from "./providers/MemorySmsProvider.ts";
6
- import { SmsProvider } from "./providers/SmsProvider.ts";
4
+ import { $notification } from "./primitives/$notification.ts";
7
5
  import { NotificationQueues } from "./queues/NotificationQueues.ts";
8
6
  import { NotificationSenderService } from "./services/NotificationSenderService.ts";
9
7
  import {
@@ -14,14 +12,13 @@ import {
14
12
  // ---------------------------------------------------------------------------------------------------------------------
15
13
 
16
14
  export * from "./controllers/NotificationController.ts";
17
- export * from "./descriptors/$notification.ts";
18
15
  export * from "./entities/notifications.ts";
19
16
  export * from "./jobs/NotificationJobs.ts";
20
- export * from "./providers/MemorySmsProvider.ts";
21
- export * from "./providers/SmsProvider.ts";
17
+ export * from "./primitives/$notification.ts";
22
18
  export * from "./queues/NotificationQueues.ts";
23
19
  export * from "./schemas/notificationContactPreferencesSchema.ts";
24
20
  export * from "./schemas/notificationCreateSchema.ts";
21
+ export * from "./schemas/notificationQuerySchema.ts";
25
22
  export * from "./services/NotificationSenderService.ts";
26
23
  export * from "./services/NotificationService.ts";
27
24
 
@@ -33,27 +30,21 @@ export * from "./services/NotificationService.ts";
33
30
  * This module includes notification sending, retrieval, status tracking,
34
31
  * and user notification preferences management.
35
32
  *
33
+ * Requires `AlephaSms` module to be loaded for SMS notifications.
34
+ *
36
35
  * @module alepha.api.notifications
37
36
  */
38
37
  export const AlephaApiNotifications = $module({
39
38
  name: "alepha.api.notifications",
40
- descriptors: [$notification],
39
+ primitives: [$notification],
41
40
  services: [
42
41
  NotificationController,
43
42
  NotificationService,
44
43
  NotificationSenderService,
45
44
  NotificationQueues,
46
45
  NotificationJobs,
47
- SmsProvider,
48
- MemorySmsProvider,
49
46
  ],
50
47
  register: (alepha) => {
51
- alepha.with({
52
- optional: true,
53
- provide: SmsProvider,
54
- use: MemorySmsProvider,
55
- });
56
-
57
48
  const env = alepha.parseEnv(notificationServiceEnvSchema);
58
49
  if (env.NOTIFICATION_QUEUE) {
59
50
  alepha.with(NotificationQueues);
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  $inject,
3
- createDescriptor,
4
- Descriptor,
3
+ createPrimitive,
5
4
  KIND,
5
+ Primitive,
6
6
  type Static,
7
7
  type StaticEncode,
8
8
  type TObject,
@@ -10,7 +10,7 @@ import {
10
10
  import { NotificationService } from "../services/NotificationService.ts";
11
11
 
12
12
  /**
13
- * Creates a notification descriptor for managing email/SMS notification templates.
13
+ * Creates a notification primitive for managing email/SMS notification templates.
14
14
  *
15
15
  * Provides type-safe, reusable notification templates with multi-language support,
16
16
  * variable substitution, and categorization for different notification channels.
@@ -38,12 +38,12 @@ import { NotificationService } from "../services/NotificationService.ts";
38
38
  * ```
39
39
  */
40
40
  export const $notification = <T extends TObject>(
41
- options: NotificationDescriptorOptions<T>,
42
- ) => createDescriptor(NotificationDescriptor<T>, options);
41
+ options: NotificationPrimitiveOptions<T>,
42
+ ) => createPrimitive(NotificationPrimitive<T>, options);
43
43
 
44
44
  // ---------------------------------------------------------------------------------------------------------------------
45
45
 
46
- export interface NotificationDescriptorOptions<T extends TObject>
46
+ export interface NotificationPrimitiveOptions<T extends TObject>
47
47
  extends NotificationMessage<T> {
48
48
  name?: string;
49
49
  description?: string;
@@ -59,8 +59,8 @@ export interface NotificationDescriptorOptions<T extends TObject>
59
59
 
60
60
  // ---------------------------------------------------------------------------------------------------------------------
61
61
 
62
- export class NotificationDescriptor<T extends TObject> extends Descriptor<
63
- NotificationDescriptorOptions<T>
62
+ export class NotificationPrimitive<T extends TObject> extends Primitive<
63
+ NotificationPrimitiveOptions<T>
64
64
  > {
65
65
  protected readonly notificationService = $inject(NotificationService);
66
66
 
@@ -78,12 +78,12 @@ export class NotificationDescriptor<T extends TObject> extends Descriptor<
78
78
  }
79
79
  }
80
80
 
81
- public configure(options: Partial<NotificationDescriptorOptions<T>>) {
81
+ public configure(options: Partial<NotificationPrimitiveOptions<T>>) {
82
82
  Object.assign(this.options, options);
83
83
  }
84
84
  }
85
85
 
86
- $notification[KIND] = NotificationDescriptor;
86
+ $notification[KIND] = NotificationPrimitive;
87
87
 
88
88
  // ---------------------------------------------------------------------------------------------------------------------
89
89
 
@@ -0,0 +1,13 @@
1
+ import type { Static } from "alepha";
2
+ import { t } from "alepha";
3
+ import { pageQuerySchema } from "alepha/orm";
4
+
5
+ export const notificationQuerySchema = t.extend(pageQuerySchema, {
6
+ type: t.optional(t.enum(["email", "sms"])),
7
+ template: t.optional(t.string()),
8
+ contact: t.optional(t.string()),
9
+ category: t.optional(t.string()),
10
+ status: t.optional(t.enum(["pending", "sent", "failed"])),
11
+ });
12
+
13
+ export type NotificationQuery = Static<typeof notificationQuerySchema>;
@@ -3,12 +3,12 @@ import { DateTimeProvider } from "alepha/datetime";
3
3
  import { EmailProvider } from "alepha/email";
4
4
  import { $logger } from "alepha/logger";
5
5
  import { $repository } from "alepha/orm";
6
- import { $notification } from "../descriptors/$notification.ts";
6
+ import { SmsProvider } from "alepha/sms";
7
7
  import {
8
8
  type NotificationEntity,
9
9
  notifications,
10
10
  } from "../entities/notifications.ts";
11
- import { SmsProvider } from "../providers/SmsProvider.ts";
11
+ import { $notification } from "../primitives/$notification.ts";
12
12
 
13
13
  export class NotificationSenderService {
14
14
  protected readonly alepha = $inject(Alepha);
@@ -161,7 +161,7 @@ export class NotificationSenderService {
161
161
  const variables = notification.variables || {};
162
162
  const contact = notification.contact;
163
163
  const template = this.alepha
164
- .descriptors($notification)
164
+ .primitives($notification)
165
165
  .find((it) => it.name === notification.template);
166
166
 
167
167
  if (!template) {
@@ -2,13 +2,17 @@ import { $env, $inject, Alepha, type Static, t } from "alepha";
2
2
  import { $batch } from "alepha/batch";
3
3
  import { DateTimeProvider } from "alepha/datetime";
4
4
  import { $logger } from "alepha/logger";
5
- import { $repository } from "alepha/orm";
6
- import { notifications } from "../entities/notifications.ts";
5
+ import { $repository, type Page } from "alepha/orm";
6
+ import {
7
+ type NotificationEntity,
8
+ notifications,
9
+ } from "../entities/notifications.ts";
7
10
  import { NotificationQueues } from "../queues/NotificationQueues.ts";
8
11
  import {
9
12
  type NotificationCreate,
10
13
  notificationCreateSchema,
11
14
  } from "../schemas/notificationCreateSchema.ts";
15
+ import type { NotificationQuery } from "../schemas/notificationQuerySchema.ts";
12
16
  import { NotificationSenderService } from "./NotificationSenderService.ts";
13
17
 
14
18
  export const notificationServiceEnvSchema = t.object({
@@ -65,6 +69,45 @@ export class NotificationService {
65
69
  return this.notificationRepository.findOne({ where: { id } });
66
70
  }
67
71
 
72
+ public async findNotifications(
73
+ q: NotificationQuery = {},
74
+ ): Promise<Page<NotificationEntity>> {
75
+ this.log.trace("Finding notifications", { query: q });
76
+ q.sort ??= "-createdAt";
77
+
78
+ const where = this.notificationRepository.createQueryWhere();
79
+
80
+ if (q.type) {
81
+ where.type = { eq: q.type };
82
+ }
83
+
84
+ if (q.template) {
85
+ where.template = { like: `%${q.template}%` };
86
+ }
87
+
88
+ if (q.contact) {
89
+ where.contact = { like: `%${q.contact}%` };
90
+ }
91
+
92
+ if (q.category) {
93
+ where.category = { eq: q.category };
94
+ }
95
+
96
+ if (q.status) {
97
+ if (q.status === "sent") {
98
+ where.sentAt = { isNotNull: true };
99
+ where.error = { isNull: true };
100
+ } else if (q.status === "failed") {
101
+ where.error = { isNotNull: true };
102
+ } else if (q.status === "pending") {
103
+ where.sentAt = { isNull: true };
104
+ where.error = { isNull: true };
105
+ }
106
+ }
107
+
108
+ return this.notificationRepository.paginate(q, { where }, { count: true });
109
+ }
110
+
68
111
  /**
69
112
  * Create a new notification.
70
113
  */
@@ -0,0 +1,12 @@
1
+ import { $module } from "alepha";
2
+
3
+ // ---------------------------------------------------------------------------------------------------------------------
4
+
5
+ export * from "./entities/parameters.ts";
6
+
7
+ // ---------------------------------------------------------------------------------------------------------------------
8
+
9
+ export const AlephaApiParameters = $module({
10
+ name: "alepha.api.parameters",
11
+ services: [],
12
+ });
@@ -2,8 +2,8 @@ import { $module } from "alepha";
2
2
 
3
3
  // ---------------------------------------------------------------------------------------------------------------------
4
4
 
5
- export * from "./descriptors/$config.ts";
6
5
  export * from "./entities/parameters.ts";
6
+ export * from "./primitives/$config.ts";
7
7
 
8
8
  // ---------------------------------------------------------------------------------------------------------------------
9
9
 
@@ -1,13 +1,8 @@
1
- import {
2
- createDescriptor,
3
- Descriptor,
4
- type Static,
5
- type TObject,
6
- } from "alepha";
1
+ import { createPrimitive, Primitive, type Static, type TObject } from "alepha";
7
2
  import type { UserAccount } from "alepha/security";
8
3
 
9
4
  /**
10
- * Creates a configuration parameter descriptor for managing application settings.
5
+ * Creates a configuration parameter primitive for managing application settings.
11
6
  *
12
7
  * Provides type-safe, versioned configuration with schema validation, default values,
13
8
  * and scheduled activation. Useful for feature flags, system parameters, and runtime settings.
@@ -33,15 +28,15 @@ import type { UserAccount } from "alepha/security";
33
28
  * }
34
29
  * ```
35
30
  */
36
- export interface ConfigDescriptorOptions<T extends TObject> {
31
+ export interface ConfigPrimitiveOptions<T extends TObject> {
37
32
  name?: string;
38
33
  description?: string;
39
34
  schema: T;
40
35
  default: Static<T>;
41
36
  }
42
37
 
43
- export class ConfigDescriptor<T extends TObject> extends Descriptor<
44
- ConfigDescriptorOptions<T>
38
+ export class ConfigPrimitive<T extends TObject> extends Primitive<
39
+ ConfigPrimitiveOptions<T>
45
40
  > {
46
41
  public get name() {
47
42
  return this.options.name || this.config.propertyKey;
@@ -78,7 +73,7 @@ export class ConfigDescriptor<T extends TObject> extends Descriptor<
78
73
  }
79
74
 
80
75
  export const $config = <T extends TObject>(
81
- options: ConfigDescriptorOptions<T>,
76
+ options: ConfigPrimitiveOptions<T>,
82
77
  ) => {
83
- return createDescriptor(ConfigDescriptor<T>, options);
78
+ return createPrimitive(ConfigPrimitive<T>, options);
84
79
  };
@@ -60,10 +60,11 @@ export const realmAuthSettingsAtom = $atom({
60
60
  }),
61
61
  }),
62
62
  default: {
63
+ // for a fresh hello world setup, we accept registration and email login
63
64
  registrationAllowed: true,
64
65
  emailEnabled: true,
65
66
  emailRequired: true,
66
- usernameEnabled: true,
67
+ usernameEnabled: false,
67
68
  usernameRequired: false,
68
69
  phoneEnabled: false,
69
70
  phoneRequired: false,
@@ -72,6 +73,7 @@ export const realmAuthSettingsAtom = $atom({
72
73
  resetPasswordAllowed: false,
73
74
  firstNameLastNameEnabled: false,
74
75
  firstNameLastNameRequired: false,
76
+ // TODO: not implemented yet
75
77
  passwordPolicy: {
76
78
  minLength: 8,
77
79
  requireUppercase: true,
@@ -310,6 +310,8 @@ export class UserController {
310
310
  /**
311
311
  * Request email verification.
312
312
  * Generates a verification token using verification service and sends an email to the user.
313
+ * @param method - The verification method: "code" (default) sends a 6-digit code, "link" sends a clickable verification link.
314
+ * @param verifyUrl - Required when method is "link". The base URL for the verification link. Token and email will be appended as query params.
313
315
  */
314
316
  public requestEmailVerification = $action({
315
317
  path: "/users/email-verification/request",
@@ -317,6 +319,19 @@ export class UserController {
317
319
  schema: {
318
320
  query: t.object({
319
321
  userRealmName: t.optional(t.string()),
322
+ method: t.optional(
323
+ t.enum(["code", "link"], {
324
+ default: "code",
325
+ description:
326
+ 'Verification method: "code" sends a 6-digit code, "link" sends a clickable verification link.',
327
+ }),
328
+ ),
329
+ verifyUrl: t.optional(
330
+ t.string({
331
+ description:
332
+ 'Base URL for verification link. Required when method is "link". Token and email will be appended as query params.',
333
+ }),
334
+ ),
320
335
  }),
321
336
  body: t.object({
322
337
  email: t.email(),
@@ -327,15 +342,20 @@ export class UserController {
327
342
  }),
328
343
  },
329
344
  handler: async ({ body, query }) => {
345
+ const method = query.method ?? "code";
330
346
  await this.userService.requestEmailVerification(
331
347
  body.email,
332
348
  query.userRealmName,
349
+ method,
350
+ query.verifyUrl,
333
351
  );
334
352
 
335
353
  return {
336
354
  success: true,
337
355
  message:
338
- "If an account exists with this email, a verification code has been sent.",
356
+ method === "link"
357
+ ? "If an account exists with this email, a verification link has been sent."
358
+ : "If an account exists with this email, a verification code has been sent.",
339
359
  };
340
360
  },
341
361
  });
@@ -21,10 +21,10 @@ export * from "./controllers/IdentityController.ts";
21
21
  export * from "./controllers/SessionController.ts";
22
22
  export * from "./controllers/UserController.ts";
23
23
  export * from "./controllers/UserRealmController.ts";
24
- export * from "./descriptors/$userRealm.ts";
25
24
  export * from "./entities/identities.ts";
26
25
  export * from "./entities/sessions.ts";
27
26
  export * from "./entities/users.ts";
27
+ export * from "./primitives/$userRealm.ts";
28
28
  export * from "./providers/UserRealmProvider.ts";
29
29
  export * from "./schemas/completePasswordResetRequestSchema.ts";
30
30
  export * from "./schemas/completeRegistrationRequestSchema.ts";
@@ -1,16 +1,17 @@
1
1
  import { $context } from "alepha";
2
+ import { AlephaApiFiles } from "alepha/api/files";
2
3
  import type { Repository } from "alepha/orm";
3
4
  import {
4
5
  $realm,
5
- type RealmDescriptor,
6
- type RealmDescriptorOptions,
6
+ type RealmPrimitive,
7
+ type RealmPrimitiveOptions,
7
8
  SecurityProvider,
8
9
  } from "alepha/security";
9
10
  import {
10
11
  $authCredentials,
11
12
  $authGithub,
12
13
  $authGoogle,
13
- type AuthDescriptor,
14
+ type AuthPrimitive,
14
15
  type Credentials,
15
16
  type LinkAccountOptions,
16
17
  type WithLinkFn,
@@ -23,7 +24,7 @@ import { DEFAULT_USER_REALM_NAME, type users } from "../entities/users.ts";
23
24
  import { UserRealmProvider } from "../providers/UserRealmProvider.ts";
24
25
  import { SessionService } from "../services/SessionService.ts";
25
26
 
26
- export type UserRealmDescriptor = RealmDescriptor & WithLinkFn & WithLoginFn;
27
+ export type UserRealmPrimitive = RealmPrimitive & WithLinkFn & WithLoginFn;
27
28
 
28
29
  /**
29
30
  * Already configured realm for user management.
@@ -41,16 +42,23 @@ export type UserRealmDescriptor = RealmDescriptor & WithLinkFn & WithLoginFn;
41
42
 
42
43
  export const $userRealm = (
43
44
  options: UserRealmOptions = {},
44
- ): UserRealmDescriptor => {
45
+ ): UserRealmPrimitive => {
45
46
  const { alepha } = $context();
46
47
  const sessionService = alepha.inject(SessionService);
47
48
  const securityProvider = alepha.inject(SecurityProvider);
48
49
  const userRealmProvider = alepha.inject(UserRealmProvider);
49
50
  const name = options.realm?.name ?? DEFAULT_USER_REALM_NAME;
50
51
 
51
- userRealmProvider.register(name, options);
52
+ const userRealm = userRealmProvider.register(name, options);
52
53
 
53
- const realm: UserRealmDescriptor = $realm({
54
+ if (options.modules?.audits) {
55
+ }
56
+
57
+ if (options.modules?.files) {
58
+ alepha.with(AlephaApiFiles);
59
+ }
60
+
61
+ const realm: UserRealmPrimitive = $realm({
54
62
  ...options.realm,
55
63
  name,
56
64
  secret: options.secret ?? securityProvider.secretKey,
@@ -103,18 +111,28 @@ export const $userRealm = (
103
111
  sessionService.login(name, credentials.username, credentials.password);
104
112
  };
105
113
 
106
- if (options.identities) {
107
- const identities: Record<string, AuthDescriptor> = {};
108
- if (options.identities?.credentials) {
109
- identities.credentials = $authCredentials(realm);
114
+ const identities = options.identities ?? {
115
+ credentials: true,
116
+ };
117
+
118
+ if (identities) {
119
+ const auth: Record<string, AuthPrimitive> = {};
120
+ if (identities.credentials) {
121
+ auth.credentials = $authCredentials(realm);
122
+ } else {
123
+ // if credentials auth is disabled, disable registration as well
124
+ userRealm.settings.registrationAllowed = false;
110
125
  }
111
- if (options.identities?.google) {
112
- identities.google = $authGoogle(realm);
126
+
127
+ if (identities.google) {
128
+ auth.google = $authGoogle(realm);
113
129
  }
114
- if (options.identities?.github) {
115
- identities.github = $authGithub(realm);
130
+
131
+ if (identities.github) {
132
+ auth.github = $authGithub(realm);
116
133
  }
117
- alepha.with(() => identities);
134
+
135
+ alepha.with(() => auth);
118
136
  }
119
137
 
120
138
  return realm;
@@ -135,7 +153,7 @@ export interface UserRealmOptions {
135
153
  *
136
154
  * It's already pre-configured for user management with admin and user roles.
137
155
  */
138
- realm?: Partial<RealmDescriptorOptions>;
156
+ realm?: Partial<RealmPrimitiveOptions>;
139
157
 
140
158
  /**
141
159
  * Override entities.
@@ -153,4 +171,9 @@ export interface UserRealmOptions {
153
171
  google?: true;
154
172
  github?: true;
155
173
  };
174
+
175
+ modules?: {
176
+ files?: boolean;
177
+ audits?: boolean;
178
+ };
156
179
  }
@@ -40,7 +40,7 @@ export class UserRealmProvider {
40
40
  protected readonly onConfigure = $hook({
41
41
  on: "configure",
42
42
  handler: () => {
43
- this.alepha.state.set("alepha.server.security.system.user", {
43
+ this.alepha.store.set("alepha.server.security.system.user", {
44
44
  id: "00000000-0000-0000-0000-000000000000",
45
45
  name: "system",
46
46
  roles: ["admin"], // TODO: use realm config
@@ -70,6 +70,7 @@ export class UserRealmProvider {
70
70
  },
71
71
  },
72
72
  });
73
+ return this.getRealm(userRealmName);
73
74
  }
74
75
 
75
76
  /**
@@ -290,6 +290,8 @@ export class SessionService {
290
290
  realm: realm.name,
291
291
  username: profile.email.split("@")[0],
292
292
  email: profile.email,
293
+ // we trust the OAuth2 provider
294
+ emailVerified: true,
293
295
  roles: ["user"], // TODO: make default roles configurable via realm settings
294
296
  });
295
297
 
@@ -23,12 +23,22 @@ export class UserService {
23
23
 
24
24
  /**
25
25
  * Request email verification for a user.
26
+ * @param email - The email address to verify.
27
+ * @param userRealmName - Optional realm name.
28
+ * @param method - The verification method: "code" (default) or "link".
29
+ * @param verifyUrl - Base URL for verification link (required when method is "link").
26
30
  */
27
31
  public async requestEmailVerification(
28
32
  email: string,
29
33
  userRealmName?: string,
34
+ method: "code" | "link" = "code",
35
+ verifyUrl?: string,
30
36
  ): Promise<boolean> {
31
- this.log.trace("Requesting email verification", { email, userRealmName });
37
+ this.log.trace("Requesting email verification", {
38
+ email,
39
+ userRealmName,
40
+ method,
41
+ });
32
42
 
33
43
  const user = await this.users(userRealmName)
34
44
  .findOne({
@@ -54,23 +64,47 @@ export class UserService {
54
64
  try {
55
65
  const verification =
56
66
  await this.verificationController.requestVerificationCode({
57
- params: { type: "code" },
67
+ params: { type: method },
58
68
  body: { target: email },
59
69
  });
60
70
 
61
- await this.userNotifications.emailVerification.push({
62
- contact: email,
63
- variables: {
71
+ if (method === "link") {
72
+ // Build verification URL with token
73
+ const url = new URL(verifyUrl || "/verify-email", "http://localhost");
74
+ url.searchParams.set("email", email);
75
+ url.searchParams.set("token", verification.token);
76
+ const fullVerifyUrl = verifyUrl
77
+ ? `${verifyUrl}${url.search}`
78
+ : url.pathname + url.search;
79
+
80
+ await this.userNotifications.emailVerificationLink.push({
81
+ contact: email,
82
+ variables: {
83
+ email,
84
+ verifyUrl: fullVerifyUrl,
85
+ expiresInMinutes: Math.floor(verification.codeExpiration / 60),
86
+ },
87
+ });
88
+
89
+ this.log.debug("Email verification link sent", {
64
90
  email,
65
- code: verification.token,
66
- expiresInMinutes: Math.floor(verification.codeExpiration / 60),
67
- },
68
- });
91
+ userId: user.id,
92
+ });
93
+ } else {
94
+ await this.userNotifications.emailVerification.push({
95
+ contact: email,
96
+ variables: {
97
+ email,
98
+ code: verification.token,
99
+ expiresInMinutes: Math.floor(verification.codeExpiration / 60),
100
+ },
101
+ });
69
102
 
70
- this.log.debug("Email verification code sent", {
71
- email,
72
- userId: user.id,
73
- });
103
+ this.log.debug("Email verification code sent", {
104
+ email,
105
+ userId: user.id,
106
+ });
107
+ }
74
108
  } catch (error) {
75
109
  // Silent fail for security
76
110
  this.log.warn("Failed to send email verification", { email, error });
@@ -81,6 +115,7 @@ export class UserService {
81
115
 
82
116
  /**
83
117
  * Verify a user's email using a valid verification token.
118
+ * Supports both code (6-digit) and link (UUID) verification tokens.
84
119
  */
85
120
  public async verifyEmail(
86
121
  email: string,
@@ -89,13 +124,18 @@ export class UserService {
89
124
  ): Promise<void> {
90
125
  this.log.trace("Verifying email", { email, userRealmName });
91
126
 
127
+ // Detect verification type based on token format
128
+ // Codes are 6-digit numbers, links are UUIDs
129
+ const isCode = /^\d{6}$/.test(token);
130
+ const type = isCode ? "code" : "link";
131
+
92
132
  const result = await this.verificationController
93
133
  .validateVerificationCode({
94
- params: { type: "code" },
134
+ params: { type },
95
135
  body: { target: email, token },
96
136
  })
97
137
  .catch(() => {
98
- this.log.warn("Invalid email verification token", { email });
138
+ this.log.warn("Invalid email verification token", { email, type });
99
139
  throw new BadRequestError("Invalid or expired verification token");
100
140
  });
101
141
 
@@ -112,7 +152,7 @@ export class UserService {
112
152
  emailVerified: true,
113
153
  });
114
154
 
115
- this.log.info("Email verified", { email, userId: user.id });
155
+ this.log.info("Email verified", { email, userId: user.id, type });
116
156
  }
117
157
 
118
158
  /**
@@ -0,0 +1,15 @@
1
+ import { $module } from "alepha";
2
+
3
+ // ---------------------------------------------------------------------------------------------------------------------
4
+
5
+ export * from "./entities/verifications.ts";
6
+ export * from "./schemas/requestVerificationCodeResponseSchema.ts";
7
+ export * from "./schemas/validateVerificationCodeResponseSchema.ts";
8
+ export * from "./schemas/verificationTypeEnumSchema.ts";
9
+
10
+ // ---------------------------------------------------------------------------------------------------------------------
11
+
12
+ export const AlephaApiVerification = $module({
13
+ name: "alepha.api.verifications",
14
+ services: [],
15
+ });
@@ -6,6 +6,7 @@ import { VerificationService } from "./services/VerificationService.ts";
6
6
  // ---------------------------------------------------------------------------------------------------------------------
7
7
 
8
8
  export * from "./controllers/VerificationController.ts";
9
+ export * from "./entities/verifications.ts";
9
10
  export * from "./schemas/requestVerificationCodeResponseSchema.ts";
10
11
  export * from "./schemas/validateVerificationCodeResponseSchema.ts";
11
12
  export * from "./schemas/verificationTypeEnumSchema.ts";