alepha 0.13.1 → 0.13.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 (296) hide show
  1. package/README.md +1 -1
  2. package/dist/api-files/index.d.ts +28 -91
  3. package/dist/api-files/index.js +10 -755
  4. package/dist/api-files/index.js.map +1 -1
  5. package/dist/api-jobs/index.d.ts +46 -46
  6. package/dist/api-jobs/index.js +13 -13
  7. package/dist/api-jobs/index.js.map +1 -1
  8. package/dist/api-notifications/index.d.ts +129 -146
  9. package/dist/api-notifications/index.js +17 -39
  10. package/dist/api-notifications/index.js.map +1 -1
  11. package/dist/api-parameters/index.d.ts +21 -22
  12. package/dist/api-parameters/index.js +22 -22
  13. package/dist/api-parameters/index.js.map +1 -1
  14. package/dist/api-users/index.d.ts +223 -2000
  15. package/dist/api-users/index.js +914 -4787
  16. package/dist/api-users/index.js.map +1 -1
  17. package/dist/api-verifications/index.d.ts +96 -96
  18. package/dist/batch/index.d.ts +13 -13
  19. package/dist/batch/index.js +8 -8
  20. package/dist/batch/index.js.map +1 -1
  21. package/dist/bucket/index.d.ts +14 -14
  22. package/dist/bucket/index.js +12 -12
  23. package/dist/bucket/index.js.map +1 -1
  24. package/dist/cache/index.d.ts +11 -11
  25. package/dist/cache/index.js +9 -9
  26. package/dist/cache/index.js.map +1 -1
  27. package/dist/cli/index.d.ts +28 -26
  28. package/dist/cli/index.js +50 -13
  29. package/dist/cli/index.js.map +1 -1
  30. package/dist/command/index.d.ts +19 -19
  31. package/dist/command/index.js +25 -25
  32. package/dist/command/index.js.map +1 -1
  33. package/dist/core/index.browser.js +218 -218
  34. package/dist/core/index.browser.js.map +1 -1
  35. package/dist/core/index.d.ts +232 -232
  36. package/dist/core/index.js +218 -218
  37. package/dist/core/index.js.map +1 -1
  38. package/dist/core/index.native.js +2113 -0
  39. package/dist/core/index.native.js.map +1 -0
  40. package/dist/datetime/index.d.ts +9 -9
  41. package/dist/datetime/index.js +7 -7
  42. package/dist/datetime/index.js.map +1 -1
  43. package/dist/email/index.d.ts +16 -16
  44. package/dist/email/index.js +9 -9
  45. package/dist/email/index.js.map +1 -1
  46. package/dist/file/index.js +1 -1
  47. package/dist/file/index.js.map +1 -1
  48. package/dist/lock/index.d.ts +9 -9
  49. package/dist/lock/index.js +8 -8
  50. package/dist/lock/index.js.map +1 -1
  51. package/dist/lock-redis/index.js +3 -66
  52. package/dist/lock-redis/index.js.map +1 -1
  53. package/dist/logger/index.d.ts +5 -5
  54. package/dist/logger/index.js +8 -8
  55. package/dist/logger/index.js.map +1 -1
  56. package/dist/orm/index.browser.js +114 -114
  57. package/dist/orm/index.browser.js.map +1 -1
  58. package/dist/orm/index.d.ts +218 -218
  59. package/dist/orm/index.js +46 -46
  60. package/dist/orm/index.js.map +1 -1
  61. package/dist/queue/index.d.ts +29 -29
  62. package/dist/queue/index.js +20 -20
  63. package/dist/queue/index.js.map +1 -1
  64. package/dist/queue-redis/index.d.ts +2 -2
  65. package/dist/redis/index.d.ts +10 -10
  66. package/dist/retry/index.d.ts +19 -19
  67. package/dist/retry/index.js +7 -7
  68. package/dist/retry/index.js.map +1 -1
  69. package/dist/scheduler/index.d.ts +16 -16
  70. package/dist/scheduler/index.js +9 -9
  71. package/dist/scheduler/index.js.map +1 -1
  72. package/dist/security/index.d.ts +80 -80
  73. package/dist/security/index.js +32 -32
  74. package/dist/security/index.js.map +1 -1
  75. package/dist/server/index.browser.js +1 -1
  76. package/dist/server/index.browser.js.map +1 -1
  77. package/dist/server/index.d.ts +101 -101
  78. package/dist/server/index.js +16 -16
  79. package/dist/server/index.js.map +1 -1
  80. package/dist/server-auth/index.browser.js +4 -982
  81. package/dist/server-auth/index.browser.js.map +1 -1
  82. package/dist/server-auth/index.d.ts +204 -785
  83. package/dist/server-auth/index.js +47 -1239
  84. package/dist/server-auth/index.js.map +1 -1
  85. package/dist/server-cache/index.d.ts +10 -10
  86. package/dist/server-cache/index.js +2 -2
  87. package/dist/server-cache/index.js.map +1 -1
  88. package/dist/server-compress/index.d.ts +4 -4
  89. package/dist/server-compress/index.js +1 -1
  90. package/dist/server-compress/index.js.map +1 -1
  91. package/dist/server-cookies/index.browser.js +8 -8
  92. package/dist/server-cookies/index.browser.js.map +1 -1
  93. package/dist/server-cookies/index.d.ts +17 -17
  94. package/dist/server-cookies/index.js +10 -10
  95. package/dist/server-cookies/index.js.map +1 -1
  96. package/dist/server-cors/index.d.ts +17 -17
  97. package/dist/server-cors/index.js +9 -9
  98. package/dist/server-cors/index.js.map +1 -1
  99. package/dist/server-health/index.d.ts +19 -19
  100. package/dist/server-helmet/index.d.ts +1 -1
  101. package/dist/server-links/index.browser.js +12 -12
  102. package/dist/server-links/index.browser.js.map +1 -1
  103. package/dist/server-links/index.d.ts +59 -251
  104. package/dist/server-links/index.js +23 -502
  105. package/dist/server-links/index.js.map +1 -1
  106. package/dist/server-metrics/index.d.ts +4 -4
  107. package/dist/server-multipart/index.d.ts +2 -2
  108. package/dist/server-proxy/index.d.ts +12 -12
  109. package/dist/server-proxy/index.js +10 -10
  110. package/dist/server-proxy/index.js.map +1 -1
  111. package/dist/server-rate-limit/index.d.ts +22 -22
  112. package/dist/server-rate-limit/index.js +12 -12
  113. package/dist/server-rate-limit/index.js.map +1 -1
  114. package/dist/server-security/index.d.ts +22 -22
  115. package/dist/server-security/index.js +15 -15
  116. package/dist/server-security/index.js.map +1 -1
  117. package/dist/server-static/index.d.ts +14 -14
  118. package/dist/server-static/index.js +8 -8
  119. package/dist/server-static/index.js.map +1 -1
  120. package/dist/server-swagger/index.d.ts +25 -184
  121. package/dist/server-swagger/index.js +21 -724
  122. package/dist/server-swagger/index.js.map +1 -1
  123. package/dist/sms/index.d.ts +14 -14
  124. package/dist/sms/index.js +9 -9
  125. package/dist/sms/index.js.map +1 -1
  126. package/dist/thread/index.d.ts +11 -11
  127. package/dist/thread/index.js +17 -17
  128. package/dist/thread/index.js.map +1 -1
  129. package/dist/topic/index.d.ts +26 -26
  130. package/dist/topic/index.js +16 -16
  131. package/dist/topic/index.js.map +1 -1
  132. package/dist/topic-redis/index.d.ts +1 -1
  133. package/dist/vite/index.d.ts +3 -3
  134. package/dist/vite/index.js +8 -8
  135. package/dist/vite/index.js.map +1 -1
  136. package/dist/websocket/index.browser.js +11 -11
  137. package/dist/websocket/index.browser.js.map +1 -1
  138. package/dist/websocket/index.d.ts +58 -58
  139. package/dist/websocket/index.js +13 -13
  140. package/dist/websocket/index.js.map +1 -1
  141. package/package.json +113 -52
  142. package/src/api-files/services/FileService.ts +5 -7
  143. package/src/api-jobs/index.ts +1 -1
  144. package/src/api-jobs/{descriptors → primitives}/$job.ts +8 -8
  145. package/src/api-jobs/providers/JobProvider.ts +9 -9
  146. package/src/api-jobs/services/JobService.ts +5 -5
  147. package/src/api-notifications/index.ts +5 -15
  148. package/src/api-notifications/{descriptors → primitives}/$notification.ts +10 -10
  149. package/src/api-notifications/services/NotificationSenderService.ts +3 -3
  150. package/src/api-parameters/index.ts +1 -1
  151. package/src/api-parameters/{descriptors → primitives}/$config.ts +7 -12
  152. package/src/api-users/index.ts +1 -1
  153. package/src/api-users/{descriptors → primitives}/$userRealm.ts +8 -8
  154. package/src/api-users/providers/UserRealmProvider.ts +1 -1
  155. package/src/batch/index.ts +3 -3
  156. package/src/batch/{descriptors → primitives}/$batch.ts +13 -16
  157. package/src/bucket/index.ts +8 -8
  158. package/src/bucket/{descriptors → primitives}/$bucket.ts +8 -8
  159. package/src/bucket/providers/LocalFileStorageProvider.ts +3 -3
  160. package/src/cache/index.ts +4 -4
  161. package/src/cache/{descriptors → primitives}/$cache.ts +15 -15
  162. package/src/cli/apps/AlephaPackageBuilderCli.ts +24 -2
  163. package/src/cli/commands/DrizzleCommands.ts +6 -6
  164. package/src/cli/commands/VerifyCommands.ts +1 -1
  165. package/src/cli/commands/ViteCommands.ts +6 -1
  166. package/src/cli/services/ProjectUtils.ts +34 -3
  167. package/src/command/index.ts +5 -5
  168. package/src/command/{descriptors → primitives}/$command.ts +9 -12
  169. package/src/command/providers/CliProvider.ts +10 -10
  170. package/src/core/Alepha.ts +30 -33
  171. package/src/core/constants/KIND.ts +1 -1
  172. package/src/core/constants/OPTIONS.ts +1 -1
  173. package/src/core/helpers/{descriptor.ts → primitive.ts} +18 -18
  174. package/src/core/helpers/ref.ts +1 -1
  175. package/src/core/index.shared.ts +8 -8
  176. package/src/core/{descriptors → primitives}/$context.ts +5 -5
  177. package/src/core/{descriptors → primitives}/$hook.ts +4 -4
  178. package/src/core/{descriptors → primitives}/$inject.ts +2 -2
  179. package/src/core/{descriptors → primitives}/$module.ts +9 -9
  180. package/src/core/{descriptors → primitives}/$use.ts +2 -2
  181. package/src/core/providers/CodecManager.ts +1 -1
  182. package/src/core/providers/JsonSchemaCodec.ts +1 -1
  183. package/src/core/providers/StateManager.ts +2 -2
  184. package/src/datetime/index.ts +3 -3
  185. package/src/datetime/{descriptors → primitives}/$interval.ts +6 -6
  186. package/src/email/index.ts +4 -4
  187. package/src/email/{descriptors → primitives}/$email.ts +8 -8
  188. package/src/file/index.ts +1 -1
  189. package/src/lock/index.ts +3 -3
  190. package/src/lock/{descriptors → primitives}/$lock.ts +10 -10
  191. package/src/logger/index.ts +8 -8
  192. package/src/logger/{descriptors → primitives}/$logger.ts +2 -2
  193. package/src/logger/services/Logger.ts +1 -1
  194. package/src/orm/constants/PG_SYMBOLS.ts +2 -2
  195. package/src/orm/index.browser.ts +2 -2
  196. package/src/orm/index.ts +8 -8
  197. package/src/orm/{descriptors → primitives}/$entity.ts +11 -11
  198. package/src/orm/{descriptors → primitives}/$repository.ts +2 -2
  199. package/src/orm/{descriptors → primitives}/$sequence.ts +8 -8
  200. package/src/orm/{descriptors → primitives}/$transaction.ts +4 -4
  201. package/src/orm/providers/PostgresTypeProvider.ts +3 -3
  202. package/src/orm/providers/RepositoryProvider.ts +4 -4
  203. package/src/orm/providers/drivers/DatabaseProvider.ts +7 -7
  204. package/src/orm/services/ModelBuilder.ts +9 -9
  205. package/src/orm/services/PgRelationManager.ts +2 -2
  206. package/src/orm/services/PostgresModelBuilder.ts +5 -5
  207. package/src/orm/services/Repository.ts +7 -7
  208. package/src/orm/services/SqliteModelBuilder.ts +5 -5
  209. package/src/queue/index.ts +7 -7
  210. package/src/queue/{descriptors → primitives}/$consumer.ts +15 -15
  211. package/src/queue/{descriptors → primitives}/$queue.ts +12 -12
  212. package/src/queue/providers/WorkerProvider.ts +7 -7
  213. package/src/retry/index.ts +3 -3
  214. package/src/retry/{descriptors → primitives}/$retry.ts +14 -14
  215. package/src/scheduler/index.ts +3 -3
  216. package/src/scheduler/{descriptors → primitives}/$scheduler.ts +9 -9
  217. package/src/scheduler/providers/CronProvider.ts +1 -1
  218. package/src/security/index.ts +9 -9
  219. package/src/security/{descriptors → primitives}/$permission.ts +7 -7
  220. package/src/security/{descriptors → primitives}/$realm.ts +6 -12
  221. package/src/security/{descriptors → primitives}/$role.ts +12 -12
  222. package/src/security/{descriptors → primitives}/$serviceAccount.ts +8 -8
  223. package/src/server/index.browser.ts +1 -1
  224. package/src/server/index.ts +14 -14
  225. package/src/server/{descriptors → primitives}/$action.ts +13 -13
  226. package/src/server/{descriptors → primitives}/$route.ts +9 -9
  227. package/src/server/providers/NodeHttpServerProvider.ts +1 -1
  228. package/src/server/services/HttpClient.ts +1 -1
  229. package/src/server-auth/index.browser.ts +1 -1
  230. package/src/server-auth/index.ts +6 -6
  231. package/src/server-auth/{descriptors → primitives}/$auth.ts +10 -10
  232. package/src/server-auth/{descriptors → primitives}/$authCredentials.ts +4 -4
  233. package/src/server-auth/{descriptors → primitives}/$authGithub.ts +4 -4
  234. package/src/server-auth/{descriptors → primitives}/$authGoogle.ts +4 -4
  235. package/src/server-auth/providers/ServerAuthProvider.ts +4 -4
  236. package/src/server-cache/providers/ServerCacheProvider.ts +7 -7
  237. package/src/server-compress/providers/ServerCompressProvider.ts +3 -3
  238. package/src/server-cookies/index.browser.ts +2 -2
  239. package/src/server-cookies/index.ts +5 -5
  240. package/src/server-cookies/{descriptors → primitives}/$cookie.browser.ts +12 -12
  241. package/src/server-cookies/{descriptors → primitives}/$cookie.ts +13 -13
  242. package/src/server-cookies/providers/ServerCookiesProvider.ts +4 -4
  243. package/src/server-cookies/services/CookieParser.ts +1 -1
  244. package/src/server-cors/index.ts +3 -3
  245. package/src/server-cors/{descriptors → primitives}/$cors.ts +11 -13
  246. package/src/server-cors/providers/ServerCorsProvider.ts +5 -5
  247. package/src/server-links/index.browser.ts +5 -5
  248. package/src/server-links/index.ts +9 -9
  249. package/src/server-links/{descriptors → primitives}/$remote.ts +11 -11
  250. package/src/server-links/providers/LinkProvider.ts +7 -7
  251. package/src/server-links/providers/{RemoteDescriptorProvider.ts → RemotePrimitiveProvider.ts} +6 -6
  252. package/src/server-links/providers/ServerLinksProvider.ts +3 -3
  253. package/src/server-proxy/index.ts +3 -3
  254. package/src/server-proxy/{descriptors → primitives}/$proxy.ts +8 -8
  255. package/src/server-proxy/providers/ServerProxyProvider.ts +4 -4
  256. package/src/server-rate-limit/index.ts +6 -6
  257. package/src/server-rate-limit/{descriptors → primitives}/$rateLimit.ts +13 -13
  258. package/src/server-rate-limit/providers/ServerRateLimitProvider.ts +5 -5
  259. package/src/server-security/index.ts +3 -3
  260. package/src/server-security/{descriptors → primitives}/$basicAuth.ts +13 -13
  261. package/src/server-security/providers/ServerBasicAuthProvider.ts +5 -5
  262. package/src/server-security/providers/ServerSecurityProvider.ts +4 -4
  263. package/src/server-static/index.ts +3 -3
  264. package/src/server-static/{descriptors → primitives}/$serve.ts +8 -10
  265. package/src/server-static/providers/ServerStaticProvider.ts +6 -6
  266. package/src/server-swagger/index.ts +5 -5
  267. package/src/server-swagger/{descriptors → primitives}/$swagger.ts +9 -9
  268. package/src/server-swagger/providers/ServerSwaggerProvider.ts +11 -10
  269. package/src/sms/index.ts +4 -4
  270. package/src/sms/{descriptors → primitives}/$sms.ts +8 -8
  271. package/src/thread/index.ts +3 -3
  272. package/src/thread/{descriptors → primitives}/$thread.ts +13 -13
  273. package/src/thread/providers/ThreadProvider.ts +7 -9
  274. package/src/topic/index.ts +5 -5
  275. package/src/topic/{descriptors → primitives}/$subscriber.ts +14 -14
  276. package/src/topic/{descriptors → primitives}/$topic.ts +10 -10
  277. package/src/topic/providers/TopicProvider.ts +4 -4
  278. package/src/vite/tasks/copyAssets.ts +1 -1
  279. package/src/vite/tasks/generateSitemap.ts +3 -3
  280. package/src/vite/tasks/prerenderPages.ts +2 -2
  281. package/src/vite/tasks/runAlepha.ts +2 -2
  282. package/src/websocket/index.browser.ts +3 -3
  283. package/src/websocket/index.shared.ts +2 -2
  284. package/src/websocket/index.ts +4 -4
  285. package/src/websocket/interfaces/WebSocketInterfaces.ts +3 -3
  286. package/src/websocket/{descriptors → primitives}/$channel.ts +10 -10
  287. package/src/websocket/{descriptors → primitives}/$websocket.ts +8 -8
  288. package/src/websocket/providers/NodeWebSocketServerProvider.ts +7 -7
  289. package/src/websocket/providers/WebSocketServerProvider.ts +3 -3
  290. package/src/websocket/services/WebSocketClient.ts +5 -5
  291. package/src/api-notifications/providers/MemorySmsProvider.ts +0 -20
  292. package/src/api-notifications/providers/SmsProvider.ts +0 -8
  293. /package/src/core/{descriptors → primitives}/$atom.ts +0 -0
  294. /package/src/core/{descriptors → primitives}/$env.ts +0 -0
  295. /package/src/server-auth/{descriptors → primitives}/$authApple.ts +0 -0
  296. /package/src/server-links/{descriptors → primitives}/$client.ts +0 -0
@@ -1,314 +1,11 @@
1
- import { $env, $hook, $inject, $module, Alepha, AlephaError, Descriptor, KIND, createDescriptor, t } from "alepha";
2
- import { $permission, $realm, $role, AlephaSecurity, JwtProvider, SecurityProvider, userAccountInfoSchema } from "alepha/security";
3
- import { $action, $route, AlephaServer, ForbiddenError, HttpClient, HttpError, ServerReply, ServerRouterProvider, ServerTimingProvider, UnauthorizedError, routeMethods } from "alepha/server";
4
- import { randomUUID, timingSafeEqual } from "node:crypto";
1
+ import "alepha/server/security";
2
+ import { $env, $hook, $inject, $module, Alepha, AlephaError, KIND, Primitive, createPrimitive, t } from "alepha";
3
+ import { $action, $route, AlephaServer, HttpClient, ServerReply, ServerTimingProvider, UnauthorizedError } from "alepha/server";
5
4
  import { $logger } from "alepha/logger";
6
5
  import { $retry } from "alepha/retry";
7
- import { ReadableStream } from "node:stream/web";
6
+ import { ServerProxyProvider } from "alepha/server/proxy";
7
+ import { SecurityProvider } from "alepha/security";
8
8
 
9
- //#region src/server-security/providers/ServerBasicAuthProvider.ts
10
- var ServerBasicAuthProvider = class {
11
- alepha = $inject(Alepha);
12
- log = $logger();
13
- routerProvider = $inject(ServerRouterProvider);
14
- realm = "Secure Area";
15
- /**
16
- * Registered basic auth descriptors with their configurations
17
- */
18
- registeredAuths = [];
19
- /**
20
- * Register a basic auth configuration (called by descriptors)
21
- */
22
- registerAuth(config) {
23
- this.registeredAuths.push(config);
24
- }
25
- onStart = $hook({
26
- on: "start",
27
- handler: async () => {
28
- for (const auth of this.registeredAuths) if (auth.paths) for (const pattern of auth.paths) {
29
- const matchedRoutes = this.routerProvider.getRoutes(pattern);
30
- for (const route of matchedRoutes) route.secure = { basic: {
31
- username: auth.username,
32
- password: auth.password
33
- } };
34
- }
35
- if (this.registeredAuths.length > 0) this.log.info(`Initialized with ${this.registeredAuths.length} registered basic-auth configurations.`);
36
- }
37
- });
38
- /**
39
- * Hook into server:onRequest to check basic auth
40
- */
41
- onRequest = $hook({
42
- on: "server:onRequest",
43
- handler: async ({ route, request }) => {
44
- const routeAuth = route.secure;
45
- if (typeof routeAuth === "object" && "basic" in routeAuth && routeAuth.basic) this.checkAuth(request, routeAuth.basic);
46
- }
47
- });
48
- /**
49
- * Hook into action:onRequest to check basic auth for actions
50
- */
51
- onActionRequest = $hook({
52
- on: "action:onRequest",
53
- handler: async ({ action, request }) => {
54
- const routeAuth = action.route.secure;
55
- if (isBasicAuth(routeAuth)) this.checkAuth(request, routeAuth.basic);
56
- }
57
- });
58
- /**
59
- * Check basic authentication
60
- */
61
- checkAuth(request, options) {
62
- const authHeader = request.headers?.authorization;
63
- if (!authHeader || !authHeader.startsWith("Basic ")) {
64
- this.sendAuthRequired(request);
65
- throw new HttpError({
66
- status: 401,
67
- message: "Authentication required"
68
- });
69
- }
70
- const base64Credentials = authHeader.slice(6);
71
- const credentials = Buffer.from(base64Credentials, "base64").toString("utf-8");
72
- const colonIndex = credentials.indexOf(":");
73
- const username = colonIndex !== -1 ? credentials.slice(0, colonIndex) : credentials;
74
- const password = colonIndex !== -1 ? credentials.slice(colonIndex + 1) : "";
75
- if (!this.timingSafeCredentialCheck(username, password, options.username, options.password)) {
76
- this.sendAuthRequired(request);
77
- this.log.warn(`Failed basic auth attempt for user`, { username });
78
- throw new HttpError({
79
- status: 401,
80
- message: "Invalid credentials"
81
- });
82
- }
83
- }
84
- /**
85
- * Performs a timing-safe comparison of credentials to prevent timing attacks.
86
- * Always compares both username and password to avoid leaking which one is wrong.
87
- */
88
- timingSafeCredentialCheck(inputUsername, inputPassword, expectedUsername, expectedPassword) {
89
- const inputUserBuf = Buffer.from(inputUsername, "utf-8");
90
- const expectedUserBuf = Buffer.from(expectedUsername, "utf-8");
91
- const inputPassBuf = Buffer.from(inputPassword, "utf-8");
92
- const expectedPassBuf = Buffer.from(expectedPassword, "utf-8");
93
- return (this.safeCompare(inputUserBuf, expectedUserBuf) & this.safeCompare(inputPassBuf, expectedPassBuf)) === 1;
94
- }
95
- /**
96
- * Compares two buffers in constant time, handling different lengths safely.
97
- * Returns 1 if equal, 0 if not equal.
98
- */
99
- safeCompare(input, expected) {
100
- if (input.length !== expected.length) {
101
- timingSafeEqual(input, input);
102
- return 0;
103
- }
104
- return timingSafeEqual(input, expected) ? 1 : 0;
105
- }
106
- /**
107
- * Send WWW-Authenticate header
108
- */
109
- sendAuthRequired(request) {
110
- request.reply.setHeader("WWW-Authenticate", `Basic realm="${this.realm}"`);
111
- }
112
- };
113
- const isBasicAuth = (value) => {
114
- return typeof value === "object" && !!value && "basic" in value && !!value.basic;
115
- };
116
-
117
- //#endregion
118
- //#region src/server-security/descriptors/$basicAuth.ts
119
- /**
120
- * Declares HTTP Basic Authentication for server routes.
121
- * This descriptor provides methods to protect routes with username/password authentication.
122
- */
123
- const $basicAuth = (options) => {
124
- return createDescriptor(BasicAuthDescriptor, options);
125
- };
126
- var BasicAuthDescriptor = class extends Descriptor {
127
- serverBasicAuthProvider = $inject(ServerBasicAuthProvider);
128
- get name() {
129
- return this.options.name ?? `${this.config.propertyKey}`;
130
- }
131
- onInit() {
132
- this.serverBasicAuthProvider.registerAuth(this.options);
133
- }
134
- /**
135
- * Checks basic auth for the given request using this descriptor's configuration.
136
- */
137
- check(request, options) {
138
- const mergedOptions = {
139
- ...this.options,
140
- ...options
141
- };
142
- this.serverBasicAuthProvider.checkAuth(request, mergedOptions);
143
- }
144
- };
145
- $basicAuth[KIND] = BasicAuthDescriptor;
146
-
147
- //#endregion
148
- //#region src/server-security/providers/ServerSecurityProvider.ts
149
- var ServerSecurityProvider = class {
150
- log = $logger();
151
- securityProvider = $inject(SecurityProvider);
152
- jwtProvider = $inject(JwtProvider);
153
- alepha = $inject(Alepha);
154
- onConfigure = $hook({
155
- on: "configure",
156
- handler: async () => {
157
- for (const action of this.alepha.descriptors($action)) {
158
- if (action.options.disabled || action.options.secure === false || this.securityProvider.getRealms().length === 0) continue;
159
- if (typeof action.options.secure !== "object") this.securityProvider.createPermission({
160
- name: action.name,
161
- group: action.group,
162
- method: action.route.method,
163
- path: action.route.path
164
- });
165
- }
166
- }
167
- });
168
- onActionRequest = $hook({
169
- on: "action:onRequest",
170
- handler: async ({ action, request, options }) => {
171
- if (action.options.secure === false && !options.user) {
172
- this.log.trace("Skipping security check for route");
173
- return;
174
- }
175
- if (isBasicAuth(action.route.secure)) return;
176
- const permission = this.securityProvider.getPermissions().find((it) => it.path === action.route.path && it.method === action.route.method);
177
- try {
178
- request.user = this.createUserFromLocalFunctionContext(options, permission);
179
- const route = action.route;
180
- if (typeof route.secure === "object") this.check(request.user, route.secure);
181
- this.alepha.state.set("alepha.server.request.user", this.alepha.codec.decode(userAccountInfoSchema, request.user));
182
- } catch (error) {
183
- if (action.options.secure || permission) throw error;
184
- this.log.trace("Skipping security check for action");
185
- }
186
- }
187
- });
188
- onRequest = $hook({
189
- on: "server:onRequest",
190
- priority: "last",
191
- handler: async ({ request, route }) => {
192
- if (route.secure === false) {
193
- this.log.trace("Skipping security check for route - explicitly disabled");
194
- return;
195
- }
196
- if (isBasicAuth(route.secure)) return;
197
- const permission = this.securityProvider.getPermissions().find((it) => it.path === route.path && it.method === route.method);
198
- if (!request.headers.authorization && !route.secure && !permission) {
199
- this.log.trace("Skipping security check for route - no authorization header and not secure");
200
- return;
201
- }
202
- try {
203
- request.user = await this.securityProvider.createUserFromToken(request.headers.authorization, { permission });
204
- if (typeof route.secure === "object") this.check(request.user, route.secure);
205
- this.alepha.state.set("alepha.server.request.user", this.alepha.codec.decode(userAccountInfoSchema, request.user));
206
- this.log.trace("User set from request token", {
207
- user: request.user,
208
- permission
209
- });
210
- } catch (error) {
211
- if (route.secure || permission) throw error;
212
- this.log.trace("Skipping security check for route - error occurred", error);
213
- }
214
- }
215
- });
216
- check(user, secure) {
217
- if (secure.realm) {
218
- if (user.realm !== secure.realm) throw new ForbiddenError(`User must belong to realm '${secure.realm}' to access this route`);
219
- }
220
- }
221
- /**
222
- * Get the user account token for a local action call.
223
- * There are three possible sources for the user:
224
- * - `options.user`: the user passed in the options
225
- * - `"system"`: the system user from the state (you MUST set state `server.security.system.user`)
226
- * - `"context"`: the user from the request context (you MUST be in an HTTP request context)
227
- *
228
- * Priority order: `options.user` > `"system"` > `"context"`.
229
- *
230
- * In testing environment, if no user is provided, a test user is created based on the SecurityProvider's roles.
231
- */
232
- createUserFromLocalFunctionContext(options, permission) {
233
- const fromOptions = typeof options.user === "object" ? options.user : void 0;
234
- const type = typeof options.user === "string" ? options.user : void 0;
235
- let user;
236
- const fromContext = this.alepha.context.get("request")?.user;
237
- const fromSystem = this.alepha.state.get("alepha.server.security.system.user");
238
- if (type === "system") user = fromSystem;
239
- else if (type === "context") user = fromContext;
240
- else user = fromOptions ?? fromContext ?? fromSystem;
241
- if (!user) {
242
- if (this.alepha.isTest() && !("user" in options)) return this.createTestUser();
243
- throw new UnauthorizedError("User is required for calling this action");
244
- }
245
- const roles = user.roles ?? (this.alepha.isTest() ? this.securityProvider.getRoles().map((role) => role.name) : []);
246
- let ownership;
247
- if (permission) {
248
- const result = this.securityProvider.checkPermission(permission, ...roles);
249
- if (!result.isAuthorized) throw new ForbiddenError(`Permission '${this.securityProvider.permissionToString(permission)}' is required for this route`);
250
- ownership = result.ownership;
251
- }
252
- return {
253
- ...user,
254
- ownership
255
- };
256
- }
257
- createTestUser() {
258
- return {
259
- id: randomUUID(),
260
- name: "Test",
261
- roles: this.securityProvider.getRoles().map((role) => role.name)
262
- };
263
- }
264
- onClientRequest = $hook({
265
- on: "client:onRequest",
266
- handler: async ({ request, options }) => {
267
- if (!this.alepha.isTest()) return;
268
- if ("user" in options && options.user === void 0) return;
269
- request.headers = new Headers(request.headers);
270
- if (!request.headers.has("authorization")) {
271
- const test = this.createTestUser();
272
- const user = typeof options?.user === "object" ? options.user : void 0;
273
- const sub = user?.id ?? test.id;
274
- const roles = user?.roles ?? test.roles;
275
- const token = await this.jwtProvider.create({
276
- sub,
277
- roles
278
- }, user?.realm ?? this.securityProvider.getRealms()[0]?.name);
279
- request.headers.set("authorization", `Bearer ${token}`);
280
- }
281
- }
282
- });
283
- };
284
-
285
- //#endregion
286
- //#region src/server-security/index.ts
287
- /**
288
- * Plugin for Alepha Server that provides security features. Based on the Alepha Security module.
289
- *
290
- * By default, all $action will be guarded by a permission check.
291
- *
292
- * @see {@link ServerSecurityProvider}
293
- * @module alepha.server.security
294
- */
295
- const AlephaServerSecurity = $module({
296
- name: "alepha.server.security",
297
- descriptors: [
298
- $realm,
299
- $role,
300
- $permission,
301
- $basicAuth
302
- ],
303
- services: [
304
- AlephaServer,
305
- AlephaSecurity,
306
- ServerSecurityProvider,
307
- ServerBasicAuthProvider
308
- ]
309
- });
310
-
311
- //#endregion
312
9
  //#region src/server-links/schemas/apiLinksResponseSchema.ts
313
10
  const apiLinkSchema = t.object({
314
11
  name: t.text({ description: "Name of the API link, used for identification." }),
@@ -361,7 +58,7 @@ var LinkProvider = class LinkProvider {
361
58
  this.serverLinks.push(link);
362
59
  }
363
60
  get links() {
364
- const apiLinks = this.alepha.state.get("alepha.server.request.apiLinks")?.links;
61
+ const apiLinks = this.alepha.store.get("alepha.server.request.apiLinks")?.links;
365
62
  if (apiLinks) {
366
63
  if (this.alepha.isBrowser()) return apiLinks;
367
64
  const links = [];
@@ -381,7 +78,7 @@ var LinkProvider = class LinkProvider {
381
78
  method: "GET",
382
79
  schema: { response: apiLinksResponseSchema }
383
80
  });
384
- this.alepha.state.set("alepha.server.request.apiLinks", data);
81
+ this.alepha.store.set("alepha.server.request.apiLinks", data);
385
82
  return data.links;
386
83
  }
387
84
  /**
@@ -485,7 +182,7 @@ var LinkProvider = class LinkProvider {
485
182
  });
486
183
  }
487
184
  async getLinkByName(name, options = {}) {
488
- if (this.alepha.isBrowser() && !this.alepha.state.get("alepha.server.request.apiLinks")) await this.fetchLinks();
185
+ if (this.alepha.isBrowser() && !this.alepha.store.get("alepha.server.request.apiLinks")) await this.fetchLinks();
489
186
  const link = this.links.find((a) => a.name === name && (!options.group || a.group === options.group) && (!options.service || options.service === a.service));
490
187
  if (!link) {
491
188
  const error = new UnauthorizedError(`Action ${name} not found.`);
@@ -504,7 +201,7 @@ var LinkProvider = class LinkProvider {
504
201
  };
505
202
 
506
203
  //#endregion
507
- //#region src/server-links/descriptors/$client.ts
204
+ //#region src/server-links/primitives/$client.ts
508
205
  /**
509
206
  * Create a new client.
510
207
  */
@@ -514,9 +211,9 @@ const $client = (scope) => {
514
211
  $client[KIND] = "$client";
515
212
 
516
213
  //#endregion
517
- //#region src/server-links/descriptors/$remote.ts
214
+ //#region src/server-links/primitives/$remote.ts
518
215
  /**
519
- * $remote is a descriptor that allows you to define remote service access.
216
+ * $remote is a primitive that allows you to define remote service access.
520
217
  *
521
218
  * Use it only when you have 2 or more services that need to communicate with each other.
522
219
  *
@@ -525,198 +222,22 @@ $client[KIND] = "$client";
525
222
  * You can add a service account if you want to use a security layer.
526
223
  */
527
224
  const $remote = (options) => {
528
- return createDescriptor(RemoteDescriptor, options);
225
+ return createPrimitive(RemotePrimitive, options);
529
226
  };
530
- var RemoteDescriptor = class extends Descriptor {
227
+ var RemotePrimitive = class extends Primitive {
531
228
  get name() {
532
229
  return this.options.name ?? this.config.propertyKey;
533
230
  }
534
231
  };
535
- $remote[KIND] = RemoteDescriptor;
536
-
537
- //#endregion
538
- //#region src/server-proxy/descriptors/$proxy.ts
539
- /**
540
- * Creates a proxy descriptor to forward requests to another server.
541
- *
542
- * This descriptor enables you to create reverse proxy functionality, allowing your Alepha server
543
- * to forward requests to other services while maintaining a unified API surface. It's particularly
544
- * useful for microservice architectures, API gateways, or when you need to aggregate multiple
545
- * services behind a single endpoint.
546
- *
547
- * **Key Features**
548
- *
549
- * - **Path-based routing**: Match specific paths or patterns to proxy
550
- * - **Dynamic targets**: Support both static and dynamic target resolution
551
- * - **Request/Response hooks**: Modify requests before forwarding and responses after receiving
552
- * - **URL rewriting**: Transform URLs before forwarding to the target
553
- * - **Conditional proxying**: Enable/disable proxies based on environment or conditions
554
- *
555
- * @example
556
- * **Basic proxy setup:**
557
- * ```ts
558
- * import { $proxy } from "alepha/server/proxy";
559
- *
560
- * class ApiGateway {
561
- * // Forward all /api/* requests to external service
562
- * api = $proxy({
563
- * path: "/api/*",
564
- * target: "https://api.example.com"
565
- * });
566
- * }
567
- * ```
568
- *
569
- * @example
570
- * **Dynamic target with environment-based routing:**
571
- * ```ts
572
- * class ApiGateway {
573
- * // Route to different environments based on configuration
574
- * api = $proxy({
575
- * path: "/api/*",
576
- * target: () => process.env.NODE_ENV === "production"
577
- * ? "https://api.prod.example.com"
578
- * : "https://api.dev.example.com"
579
- * });
580
- * }
581
- * ```
582
- *
583
- * @example
584
- * **Advanced proxy with request/response modification:**
585
- * ```ts
586
- * class SecureProxy {
587
- * secure = $proxy({
588
- * path: "/secure/*",
589
- * target: "https://secure-api.example.com",
590
- * beforeRequest: async (request, proxyRequest) => {
591
- * // Add authentication headers
592
- * proxyRequest.headers = {
593
- * ...proxyRequest.headers,
594
- * 'Authorization': `Bearer ${await getServiceToken()}`,
595
- * 'X-Forwarded-For': request.headers['x-forwarded-for'] || request.ip
596
- * };
597
- * },
598
- * afterResponse: async (request, proxyResponse) => {
599
- * // Log response for monitoring
600
- * console.log(`Proxied ${request.url} -> ${proxyResponse.status}`);
601
- * },
602
- * rewrite: (url) => {
603
- * // Remove /secure prefix when forwarding
604
- * url.pathname = url.pathname.replace('/secure', '');
605
- * }
606
- * });
607
- * }
608
- * ```
609
- *
610
- * @example
611
- * **Conditional proxy based on feature flags:**
612
- * ```ts
613
- * class FeatureProxy {
614
- * newApi = $proxy({
615
- * path: "/v2/*",
616
- * target: "https://new-api.example.com",
617
- * disabled: !process.env.ENABLE_V2_API // Disable if feature flag is off
618
- * });
619
- * }
620
- * ```
621
- */
622
- const $proxy = (options) => {
623
- return createDescriptor(ProxyDescriptor, options);
624
- };
625
- var ProxyDescriptor = class extends Descriptor {};
626
- $proxy[KIND] = ProxyDescriptor;
627
-
628
- //#endregion
629
- //#region src/server-proxy/providers/ServerProxyProvider.ts
630
- var ServerProxyProvider = class {
631
- log = $logger();
632
- routerProvider = $inject(ServerRouterProvider);
633
- alepha = $inject(Alepha);
634
- configure = $hook({
635
- on: "configure",
636
- handler: () => {
637
- for (const proxy of this.alepha.descriptors($proxy)) this.createProxy(proxy.options);
638
- }
639
- });
640
- createProxy(options) {
641
- if (options.disabled) return;
642
- const path = options.path;
643
- const target = typeof options.target === "function" ? options.target() : options.target;
644
- if (!path.endsWith("/*")) throw new AlephaError("Proxy path should end with '/*'");
645
- const handler = this.createProxyHandler(target, options);
646
- for (const method of routeMethods) this.routerProvider.createRoute({
647
- method,
648
- path,
649
- handler
650
- });
651
- this.log.info("Proxying", {
652
- path,
653
- target
654
- });
655
- }
656
- createProxyHandler(target, options) {
657
- return async (request) => {
658
- const url = new URL(target + request.url.pathname);
659
- if (request.url.search) url.search = request.url.search;
660
- options.rewrite?.(url);
661
- const requestInit = {
662
- url: url.toString(),
663
- method: request.method,
664
- headers: {
665
- ...request.headers,
666
- "accept-encoding": "identity"
667
- },
668
- body: this.getRawRequestBody(request)
669
- };
670
- if (requestInit.body) requestInit.duplex = "half";
671
- if (options.beforeRequest) await options.beforeRequest(request, requestInit);
672
- this.log.debug("Proxying request", {
673
- url: url.toString(),
674
- method: request.method,
675
- headers: request.headers
676
- });
677
- const response = await fetch(requestInit.url, requestInit);
678
- request.reply.status = response.status;
679
- request.reply.headers = Object.fromEntries(response.headers.entries());
680
- request.reply.body = response.body;
681
- this.log.debug("Received response", {
682
- status: request.reply.status,
683
- headers: request.reply.headers
684
- });
685
- if (options.afterResponse) await options.afterResponse(request, response);
686
- };
687
- }
688
- getRawRequestBody(req) {
689
- const { method } = req;
690
- if (method === "GET" || method === "HEAD" || method === "OPTIONS") return;
691
- if (req.raw?.web?.req) return req.raw.web.req.body;
692
- if (req.raw?.node?.req) {
693
- const nodeReq = req.raw.node.req;
694
- return ReadableStream.from(nodeReq);
695
- }
696
- }
697
- };
698
-
699
- //#endregion
700
- //#region src/server-proxy/index.ts
701
- /**
702
- * Plugin for Alepha that provides a proxy server functionality.
703
- *
704
- * @see {@link $proxy}
705
- * @module alepha.server.proxy
706
- */
707
- const AlephaServerProxy = $module({
708
- name: "alepha.server.proxy",
709
- descriptors: [$proxy],
710
- services: [AlephaServer, ServerProxyProvider]
711
- });
232
+ $remote[KIND] = RemotePrimitive;
712
233
 
713
234
  //#endregion
714
- //#region src/server-links/providers/RemoteDescriptorProvider.ts
235
+ //#region src/server-links/providers/RemotePrimitiveProvider.ts
715
236
  const envSchema$1 = t.object({ SERVER_API_PREFIX: t.text({
716
237
  description: "Prefix for all API routes (e.g. $action).",
717
238
  default: "/api"
718
239
  }) });
719
- var RemoteDescriptorProvider = class {
240
+ var RemotePrimitiveProvider = class {
720
241
  env = $env(envSchema$1);
721
242
  alepha = $inject(Alepha);
722
243
  proxyProvider = $inject(ServerProxyProvider);
@@ -729,7 +250,7 @@ var RemoteDescriptorProvider = class {
729
250
  configure = $hook({
730
251
  on: "configure",
731
252
  handler: async () => {
732
- const remotes = this.alepha.descriptors($remote);
253
+ const remotes = this.alepha.primitives($remote);
733
254
  for (const remote of remotes) await this.registerRemote(remote);
734
255
  }
735
256
  });
@@ -825,7 +346,7 @@ var ServerLinksProvider = class {
825
346
  env = $env(envSchema);
826
347
  alepha = $inject(Alepha);
827
348
  linkProvider = $inject(LinkProvider);
828
- remoteProvider = $inject(RemoteDescriptorProvider);
349
+ remoteProvider = $inject(RemotePrimitiveProvider);
829
350
  serverTimingProvider = $inject(ServerTimingProvider);
830
351
  get prefix() {
831
352
  return this.env.SERVER_API_PREFIX;
@@ -833,7 +354,7 @@ var ServerLinksProvider = class {
833
354
  onRoute = $hook({
834
355
  on: "configure",
835
356
  handler: () => {
836
- for (const action of this.alepha.descriptors($action)) this.linkProvider.registerLink({
357
+ for (const action of this.alepha.primitives($action)) this.linkProvider.registerLink({
837
358
  name: action.name,
838
359
  group: action.group,
839
360
  schema: action.options.schema,
@@ -960,7 +481,7 @@ var ServerLinksProvider = class {
960
481
  /**
961
482
  * Provides server-side link management and remote capabilities for client-server interactions.
962
483
  *
963
- * The server-links module enables declarative link definitions using `$remote` and `$client` descriptors,
484
+ * The server-links module enables declarative link definitions using `$remote` and `$client` primitives,
964
485
  * facilitating seamless API endpoint management and client-server communication. It integrates with server
965
486
  * security features to ensure safe and controlled access to resources.
966
487
  *
@@ -970,15 +491,15 @@ var ServerLinksProvider = class {
970
491
  */
971
492
  const AlephaServerLinks = $module({
972
493
  name: "alepha.server.links",
973
- descriptors: [$remote, $client],
494
+ primitives: [$remote, $client],
974
495
  services: [
975
496
  AlephaServer,
976
497
  ServerLinksProvider,
977
- RemoteDescriptorProvider,
498
+ RemotePrimitiveProvider,
978
499
  LinkProvider
979
500
  ]
980
501
  });
981
502
 
982
503
  //#endregion
983
- export { $client, $remote, AlephaServerLinks, LinkProvider, RemoteDescriptor, RemoteDescriptorProvider, ServerLinksProvider, apiLinkSchema, apiLinksResponseSchema };
504
+ export { $client, $remote, AlephaServerLinks, LinkProvider, RemotePrimitive, RemotePrimitiveProvider, ServerLinksProvider, apiLinkSchema, apiLinksResponseSchema };
984
505
  //# sourceMappingURL=index.js.map