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,722 +1,19 @@
1
- import { $atom, $hook, $inject, $module, $use, Alepha, Descriptor, KIND, createDescriptor, isTypeFile, t } from "alepha";
2
- import { $permission, $realm, $role, AlephaSecurity, JwtProvider, SecurityProvider, userAccountInfoSchema } from "alepha/security";
3
- import { $action, ActionDescriptor, AlephaServer, ForbiddenError, HttpError, ServerProvider, ServerRouterProvider, UnauthorizedError } from "alepha/server";
4
- import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
5
- import { $logger } from "alepha/logger";
6
- import { $cache, AlephaCache } from "alepha/cache";
7
- import { DateTimeProvider } from "alepha/datetime";
8
- import { createReadStream } from "node:fs";
9
- import { access, readdir, stat } from "node:fs/promises";
10
- import { basename, isAbsolute, join } from "node:path";
11
- import { FileDetector, FileSystemProvider } from "alepha/file";
1
+ import "alepha/server/security";
2
+ import { $atom, $hook, $inject, $module, $use, Alepha, KIND, Primitive, createPrimitive, isTypeFile, t } from "alepha";
3
+ import { $action, AlephaServer, ServerProvider, ServerRouterProvider } from "alepha/server";
4
+ import { AlephaServerCache } from "alepha/server/cache";
5
+ import { AlephaServerStatic, ServerStaticProvider } from "alepha/server/static";
6
+ import { join } from "node:path";
12
7
  import { fileURLToPath } from "node:url";
8
+ import { FileSystemProvider } from "alepha/file";
9
+ import { $logger } from "alepha/logger";
10
+ import { AlephaSecurity } from "alepha/security";
13
11
 
14
- //#region src/server-security/providers/ServerBasicAuthProvider.ts
15
- var ServerBasicAuthProvider = class {
16
- alepha = $inject(Alepha);
17
- log = $logger();
18
- routerProvider = $inject(ServerRouterProvider);
19
- realm = "Secure Area";
20
- /**
21
- * Registered basic auth descriptors with their configurations
22
- */
23
- registeredAuths = [];
24
- /**
25
- * Register a basic auth configuration (called by descriptors)
26
- */
27
- registerAuth(config) {
28
- this.registeredAuths.push(config);
29
- }
30
- onStart = $hook({
31
- on: "start",
32
- handler: async () => {
33
- for (const auth of this.registeredAuths) if (auth.paths) for (const pattern of auth.paths) {
34
- const matchedRoutes = this.routerProvider.getRoutes(pattern);
35
- for (const route of matchedRoutes) route.secure = { basic: {
36
- username: auth.username,
37
- password: auth.password
38
- } };
39
- }
40
- if (this.registeredAuths.length > 0) this.log.info(`Initialized with ${this.registeredAuths.length} registered basic-auth configurations.`);
41
- }
42
- });
43
- /**
44
- * Hook into server:onRequest to check basic auth
45
- */
46
- onRequest = $hook({
47
- on: "server:onRequest",
48
- handler: async ({ route, request }) => {
49
- const routeAuth = route.secure;
50
- if (typeof routeAuth === "object" && "basic" in routeAuth && routeAuth.basic) this.checkAuth(request, routeAuth.basic);
51
- }
52
- });
53
- /**
54
- * Hook into action:onRequest to check basic auth for actions
55
- */
56
- onActionRequest = $hook({
57
- on: "action:onRequest",
58
- handler: async ({ action, request }) => {
59
- const routeAuth = action.route.secure;
60
- if (isBasicAuth(routeAuth)) this.checkAuth(request, routeAuth.basic);
61
- }
62
- });
63
- /**
64
- * Check basic authentication
65
- */
66
- checkAuth(request, options) {
67
- const authHeader = request.headers?.authorization;
68
- if (!authHeader || !authHeader.startsWith("Basic ")) {
69
- this.sendAuthRequired(request);
70
- throw new HttpError({
71
- status: 401,
72
- message: "Authentication required"
73
- });
74
- }
75
- const base64Credentials = authHeader.slice(6);
76
- const credentials = Buffer.from(base64Credentials, "base64").toString("utf-8");
77
- const colonIndex = credentials.indexOf(":");
78
- const username = colonIndex !== -1 ? credentials.slice(0, colonIndex) : credentials;
79
- const password = colonIndex !== -1 ? credentials.slice(colonIndex + 1) : "";
80
- if (!this.timingSafeCredentialCheck(username, password, options.username, options.password)) {
81
- this.sendAuthRequired(request);
82
- this.log.warn(`Failed basic auth attempt for user`, { username });
83
- throw new HttpError({
84
- status: 401,
85
- message: "Invalid credentials"
86
- });
87
- }
88
- }
89
- /**
90
- * Performs a timing-safe comparison of credentials to prevent timing attacks.
91
- * Always compares both username and password to avoid leaking which one is wrong.
92
- */
93
- timingSafeCredentialCheck(inputUsername, inputPassword, expectedUsername, expectedPassword) {
94
- const inputUserBuf = Buffer.from(inputUsername, "utf-8");
95
- const expectedUserBuf = Buffer.from(expectedUsername, "utf-8");
96
- const inputPassBuf = Buffer.from(inputPassword, "utf-8");
97
- const expectedPassBuf = Buffer.from(expectedPassword, "utf-8");
98
- return (this.safeCompare(inputUserBuf, expectedUserBuf) & this.safeCompare(inputPassBuf, expectedPassBuf)) === 1;
99
- }
100
- /**
101
- * Compares two buffers in constant time, handling different lengths safely.
102
- * Returns 1 if equal, 0 if not equal.
103
- */
104
- safeCompare(input, expected) {
105
- if (input.length !== expected.length) {
106
- timingSafeEqual(input, input);
107
- return 0;
108
- }
109
- return timingSafeEqual(input, expected) ? 1 : 0;
110
- }
111
- /**
112
- * Send WWW-Authenticate header
113
- */
114
- sendAuthRequired(request) {
115
- request.reply.setHeader("WWW-Authenticate", `Basic realm="${this.realm}"`);
116
- }
117
- };
118
- const isBasicAuth = (value) => {
119
- return typeof value === "object" && !!value && "basic" in value && !!value.basic;
120
- };
121
-
122
- //#endregion
123
- //#region src/server-security/descriptors/$basicAuth.ts
124
- /**
125
- * Declares HTTP Basic Authentication for server routes.
126
- * This descriptor provides methods to protect routes with username/password authentication.
127
- */
128
- const $basicAuth = (options) => {
129
- return createDescriptor(BasicAuthDescriptor, options);
130
- };
131
- var BasicAuthDescriptor = class extends Descriptor {
132
- serverBasicAuthProvider = $inject(ServerBasicAuthProvider);
133
- get name() {
134
- return this.options.name ?? `${this.config.propertyKey}`;
135
- }
136
- onInit() {
137
- this.serverBasicAuthProvider.registerAuth(this.options);
138
- }
139
- /**
140
- * Checks basic auth for the given request using this descriptor's configuration.
141
- */
142
- check(request, options) {
143
- const mergedOptions = {
144
- ...this.options,
145
- ...options
146
- };
147
- this.serverBasicAuthProvider.checkAuth(request, mergedOptions);
148
- }
149
- };
150
- $basicAuth[KIND] = BasicAuthDescriptor;
151
-
152
- //#endregion
153
- //#region src/server-security/providers/ServerSecurityProvider.ts
154
- var ServerSecurityProvider = class {
155
- log = $logger();
156
- securityProvider = $inject(SecurityProvider);
157
- jwtProvider = $inject(JwtProvider);
158
- alepha = $inject(Alepha);
159
- onConfigure = $hook({
160
- on: "configure",
161
- handler: async () => {
162
- for (const action of this.alepha.descriptors($action)) {
163
- if (action.options.disabled || action.options.secure === false || this.securityProvider.getRealms().length === 0) continue;
164
- if (typeof action.options.secure !== "object") this.securityProvider.createPermission({
165
- name: action.name,
166
- group: action.group,
167
- method: action.route.method,
168
- path: action.route.path
169
- });
170
- }
171
- }
172
- });
173
- onActionRequest = $hook({
174
- on: "action:onRequest",
175
- handler: async ({ action, request, options }) => {
176
- if (action.options.secure === false && !options.user) {
177
- this.log.trace("Skipping security check for route");
178
- return;
179
- }
180
- if (isBasicAuth(action.route.secure)) return;
181
- const permission = this.securityProvider.getPermissions().find((it) => it.path === action.route.path && it.method === action.route.method);
182
- try {
183
- request.user = this.createUserFromLocalFunctionContext(options, permission);
184
- const route = action.route;
185
- if (typeof route.secure === "object") this.check(request.user, route.secure);
186
- this.alepha.state.set("alepha.server.request.user", this.alepha.codec.decode(userAccountInfoSchema, request.user));
187
- } catch (error) {
188
- if (action.options.secure || permission) throw error;
189
- this.log.trace("Skipping security check for action");
190
- }
191
- }
192
- });
193
- onRequest = $hook({
194
- on: "server:onRequest",
195
- priority: "last",
196
- handler: async ({ request, route }) => {
197
- if (route.secure === false) {
198
- this.log.trace("Skipping security check for route - explicitly disabled");
199
- return;
200
- }
201
- if (isBasicAuth(route.secure)) return;
202
- const permission = this.securityProvider.getPermissions().find((it) => it.path === route.path && it.method === route.method);
203
- if (!request.headers.authorization && !route.secure && !permission) {
204
- this.log.trace("Skipping security check for route - no authorization header and not secure");
205
- return;
206
- }
207
- try {
208
- request.user = await this.securityProvider.createUserFromToken(request.headers.authorization, { permission });
209
- if (typeof route.secure === "object") this.check(request.user, route.secure);
210
- this.alepha.state.set("alepha.server.request.user", this.alepha.codec.decode(userAccountInfoSchema, request.user));
211
- this.log.trace("User set from request token", {
212
- user: request.user,
213
- permission
214
- });
215
- } catch (error) {
216
- if (route.secure || permission) throw error;
217
- this.log.trace("Skipping security check for route - error occurred", error);
218
- }
219
- }
220
- });
221
- check(user, secure) {
222
- if (secure.realm) {
223
- if (user.realm !== secure.realm) throw new ForbiddenError(`User must belong to realm '${secure.realm}' to access this route`);
224
- }
225
- }
226
- /**
227
- * Get the user account token for a local action call.
228
- * There are three possible sources for the user:
229
- * - `options.user`: the user passed in the options
230
- * - `"system"`: the system user from the state (you MUST set state `server.security.system.user`)
231
- * - `"context"`: the user from the request context (you MUST be in an HTTP request context)
232
- *
233
- * Priority order: `options.user` > `"system"` > `"context"`.
234
- *
235
- * In testing environment, if no user is provided, a test user is created based on the SecurityProvider's roles.
236
- */
237
- createUserFromLocalFunctionContext(options, permission) {
238
- const fromOptions = typeof options.user === "object" ? options.user : void 0;
239
- const type = typeof options.user === "string" ? options.user : void 0;
240
- let user;
241
- const fromContext = this.alepha.context.get("request")?.user;
242
- const fromSystem = this.alepha.state.get("alepha.server.security.system.user");
243
- if (type === "system") user = fromSystem;
244
- else if (type === "context") user = fromContext;
245
- else user = fromOptions ?? fromContext ?? fromSystem;
246
- if (!user) {
247
- if (this.alepha.isTest() && !("user" in options)) return this.createTestUser();
248
- throw new UnauthorizedError("User is required for calling this action");
249
- }
250
- const roles = user.roles ?? (this.alepha.isTest() ? this.securityProvider.getRoles().map((role) => role.name) : []);
251
- let ownership;
252
- if (permission) {
253
- const result = this.securityProvider.checkPermission(permission, ...roles);
254
- if (!result.isAuthorized) throw new ForbiddenError(`Permission '${this.securityProvider.permissionToString(permission)}' is required for this route`);
255
- ownership = result.ownership;
256
- }
257
- return {
258
- ...user,
259
- ownership
260
- };
261
- }
262
- createTestUser() {
263
- return {
264
- id: randomUUID(),
265
- name: "Test",
266
- roles: this.securityProvider.getRoles().map((role) => role.name)
267
- };
268
- }
269
- onClientRequest = $hook({
270
- on: "client:onRequest",
271
- handler: async ({ request, options }) => {
272
- if (!this.alepha.isTest()) return;
273
- if ("user" in options && options.user === void 0) return;
274
- request.headers = new Headers(request.headers);
275
- if (!request.headers.has("authorization")) {
276
- const test = this.createTestUser();
277
- const user = typeof options?.user === "object" ? options.user : void 0;
278
- const sub = user?.id ?? test.id;
279
- const roles = user?.roles ?? test.roles;
280
- const token = await this.jwtProvider.create({
281
- sub,
282
- roles
283
- }, user?.realm ?? this.securityProvider.getRealms()[0]?.name);
284
- request.headers.set("authorization", `Bearer ${token}`);
285
- }
286
- }
287
- });
288
- };
289
-
290
- //#endregion
291
- //#region src/server-security/index.ts
292
- /**
293
- * Plugin for Alepha Server that provides security features. Based on the Alepha Security module.
294
- *
295
- * By default, all $action will be guarded by a permission check.
296
- *
297
- * @see {@link ServerSecurityProvider}
298
- * @module alepha.server.security
299
- */
300
- const AlephaServerSecurity = $module({
301
- name: "alepha.server.security",
302
- descriptors: [
303
- $realm,
304
- $role,
305
- $permission,
306
- $basicAuth
307
- ],
308
- services: [
309
- AlephaServer,
310
- AlephaSecurity,
311
- ServerSecurityProvider,
312
- ServerBasicAuthProvider
313
- ]
314
- });
315
-
316
- //#endregion
317
- //#region src/server-cache/providers/ServerCacheProvider.ts
318
- ActionDescriptor.prototype.invalidate = async function() {
319
- await this.alepha.inject(ServerCacheProvider).invalidate(this.route);
320
- };
321
- var ServerCacheProvider = class {
322
- log = $logger();
323
- alepha = $inject(Alepha);
324
- time = $inject(DateTimeProvider);
325
- cache = $cache({ provider: "memory" });
326
- generateETag(content) {
327
- return `"${createHash("md5").update(content).digest("hex")}"`;
328
- }
329
- async invalidate(route) {
330
- if (!route.cache) return;
331
- await this.cache.invalidate(this.createCacheKey(route));
332
- }
333
- onActionRequest = $hook({
334
- on: "action:onRequest",
335
- handler: async ({ action, request }) => {
336
- const cache = action.route.cache;
337
- if (this.shouldStore(cache)) {
338
- const key = this.createCacheKey(action.route, request);
339
- const cached = await this.cache.get(key);
340
- if (cached) {
341
- const body = cached.contentType === "application/json" ? JSON.parse(cached.body) : cached.body;
342
- this.log.trace("Cache hit for action", {
343
- key,
344
- action: action.name
345
- });
346
- request.reply.body = body;
347
- } else this.log.trace("Cache miss for action", {
348
- key,
349
- action: action.name
350
- });
351
- }
352
- }
353
- });
354
- onActionResponse = $hook({
355
- on: "action:onResponse",
356
- handler: async ({ action, request, response }) => {
357
- const cache = action.route.cache;
358
- if (!this.shouldStore(cache) || !response) return;
359
- if (request.reply.status && request.reply.status >= 400) return;
360
- const contentType = typeof response === "string" ? "text/plain" : "application/json";
361
- const body = contentType === "text/plain" ? response : JSON.stringify(response);
362
- const generatedEtag = this.generateETag(body);
363
- const lastModified = this.time.toISOString();
364
- const key = this.createCacheKey(action.route, request);
365
- this.log.trace("Storing response", {
366
- key,
367
- action: action.name
368
- });
369
- await this.cache.set(key, {
370
- body,
371
- lastModified,
372
- contentType,
373
- hash: generatedEtag
374
- });
375
- const cacheControl = this.buildCacheControlHeader(cache);
376
- if (cacheControl) request.reply.setHeader("cache-control", cacheControl);
377
- }
378
- });
379
- onRequest = $hook({
380
- on: "server:onRequest",
381
- handler: async ({ route, request }) => {
382
- const cache = route.cache;
383
- const shouldStore = this.shouldStore(cache);
384
- const shouldUseEtag = this.shouldUseEtag(cache);
385
- if (!shouldStore && !shouldUseEtag) return;
386
- const key = this.createCacheKey(route, request);
387
- const cached = await this.cache.get(key);
388
- if (cached) {
389
- if (request.headers["if-none-match"] === cached.hash || request.headers["if-modified-since"] === cached.lastModified) {
390
- request.reply.status = 304;
391
- request.reply.setHeader("etag", cached.hash);
392
- request.reply.setHeader("last-modified", cached.lastModified);
393
- this.log.trace("ETag match, returning 304", {
394
- route: route.path,
395
- etag: cached.hash
396
- });
397
- return;
398
- }
399
- if (shouldStore) {
400
- this.log.trace("Cache hit for route", {
401
- key,
402
- route: route.path
403
- });
404
- request.reply.body = cached.body;
405
- request.reply.status = cached.status ?? 200;
406
- if (cached.contentType) request.reply.setHeader("Content-Type", cached.contentType);
407
- request.reply.setHeader("etag", cached.hash);
408
- request.reply.setHeader("last-modified", cached.lastModified);
409
- }
410
- } else if (shouldStore) this.log.trace("Cache miss for route", {
411
- key,
412
- route: route.path
413
- });
414
- }
415
- });
416
- onSend = $hook({
417
- on: "server:onSend",
418
- handler: async ({ route, request }) => {
419
- const cache = route.cache;
420
- const shouldStore = this.shouldStore(cache);
421
- const shouldUseEtag = this.shouldUseEtag(cache);
422
- if (request.reply.headers.etag) return;
423
- if (!shouldStore && shouldUseEtag && request.reply.body != null && (typeof request.reply.body === "string" || Buffer.isBuffer(request.reply.body))) {
424
- const generatedEtag = this.generateETag(request.reply.body);
425
- if (request.headers["if-none-match"] === generatedEtag) {
426
- request.reply.status = 304;
427
- request.reply.body = void 0;
428
- request.reply.setHeader("etag", generatedEtag);
429
- this.log.trace("ETag match on send, returning 304", {
430
- route: route.path,
431
- etag: generatedEtag
432
- });
433
- return;
434
- }
435
- }
436
- }
437
- });
438
- onResponse = $hook({
439
- on: "server:onResponse",
440
- priority: "first",
441
- handler: async ({ route, request, response }) => {
442
- const cache = route.cache;
443
- const cacheControl = this.buildCacheControlHeader(cache);
444
- if (cacheControl) response.headers["cache-control"] = cacheControl;
445
- const shouldStore = this.shouldStore(cache);
446
- const shouldUseEtag = this.shouldUseEtag(cache);
447
- if (!shouldStore && !shouldUseEtag) return;
448
- if (typeof response.body !== "string") return;
449
- if (response.status && response.status >= 400) return;
450
- const key = this.createCacheKey(route, request);
451
- const generatedEtag = this.generateETag(response.body);
452
- const lastModified = this.time.toISOString();
453
- response.headers ??= {};
454
- if (shouldStore) {
455
- this.log.trace("Storing response", {
456
- key,
457
- route: route.path,
458
- cache: !!cache,
459
- etag: shouldUseEtag
460
- });
461
- await this.cache.set(key, {
462
- body: response.body,
463
- status: response.status,
464
- contentType: response.headers?.["content-type"],
465
- lastModified,
466
- hash: generatedEtag
467
- });
468
- }
469
- if (shouldUseEtag) {
470
- response.headers.etag = generatedEtag;
471
- response.headers["last-modified"] = lastModified;
472
- }
473
- }
474
- });
475
- buildCacheControlHeader(cache) {
476
- if (!cache) return;
477
- if (cache === true || typeof cache === "string" || typeof cache === "number") return;
478
- const control = cache.control;
479
- if (!control) return;
480
- if (typeof control === "string") return control;
481
- if (control === true) return "public, max-age=300";
482
- const directives = [];
483
- if (control.public) directives.push("public");
484
- if (control.private) directives.push("private");
485
- if (control.noCache) directives.push("no-cache");
486
- if (control.noStore) directives.push("no-store");
487
- if (control.maxAge !== void 0) {
488
- const maxAgeSeconds = this.durationToSeconds(control.maxAge);
489
- directives.push(`max-age=${maxAgeSeconds}`);
490
- }
491
- if (control.sMaxAge !== void 0) {
492
- const sMaxAgeSeconds = this.durationToSeconds(control.sMaxAge);
493
- directives.push(`s-maxage=${sMaxAgeSeconds}`);
494
- }
495
- if (control.mustRevalidate) directives.push("must-revalidate");
496
- if (control.proxyRevalidate) directives.push("proxy-revalidate");
497
- if (control.immutable) directives.push("immutable");
498
- return directives.length > 0 ? directives.join(", ") : void 0;
499
- }
500
- durationToSeconds(duration) {
501
- if (typeof duration === "number") return duration;
502
- return this.time.duration(duration).asSeconds();
503
- }
504
- shouldStore(cache) {
505
- if (!cache) return false;
506
- if (cache === true) return true;
507
- if (typeof cache === "object" && cache.store) return true;
508
- return false;
509
- }
510
- shouldUseEtag(cache) {
511
- if (cache === true) return true;
512
- if (typeof cache === "object" && cache.etag) return true;
513
- return false;
514
- }
515
- createCacheKey(route, config) {
516
- const params = [];
517
- for (const [key, value] of Object.entries(config?.params ?? {})) params.push(`${key}=${value}`);
518
- for (const [key, value] of Object.entries(config?.query ?? {})) params.push(`${key}=${value}`);
519
- return `${route.method}:${route.path.replaceAll(":", "")}:${params.join(",").replaceAll(":", "")}`;
520
- }
521
- };
522
-
523
- //#endregion
524
- //#region src/server-cache/index.ts
525
- /**
526
- * Plugin for Alepha Server that provides server-side caching capabilities.
527
- * It uses the Alepha Cache module to cache responses from server actions ($action).
528
- * It also provides a ETag-based cache invalidation mechanism.
529
- *
530
- * @example
531
- * ```ts
532
- * import { Alepha } from "alepha";
533
- * import { $action } from "alepha/server";
534
- * import { AlephaServerCache } from "alepha/server/cache";
535
- *
536
- * class ApiServer {
537
- * hello = $action({
538
- * cache: true,
539
- * handler: () => "Hello, World!",
540
- * });
541
- * }
542
- *
543
- * const alepha = Alepha.create()
544
- * .with(AlephaServerCache)
545
- * .with(ApiServer);
546
- *
547
- * run(alepha);
548
- * ```
549
- *
550
- * @see {@link ServerCacheProvider}
551
- * @module alepha.server.cache
552
- */
553
- const AlephaServerCache = $module({
554
- name: "alepha.server.cache",
555
- services: [AlephaCache, ServerCacheProvider]
556
- });
557
-
558
- //#endregion
559
- //#region src/server-static/descriptors/$serve.ts
560
- /**
561
- * Create a new static file handler.
562
- */
563
- const $serve = (options = {}) => {
564
- return createDescriptor(ServeDescriptor, options);
565
- };
566
- var ServeDescriptor = class extends Descriptor {};
567
- $serve[KIND] = ServeDescriptor;
568
-
569
- //#endregion
570
- //#region src/server-static/providers/ServerStaticProvider.ts
571
- var ServerStaticProvider = class {
572
- alepha = $inject(Alepha);
573
- routerProvider = $inject(ServerRouterProvider);
574
- dateTimeProvider = $inject(DateTimeProvider);
575
- fileDetector = $inject(FileDetector);
576
- log = $logger();
577
- directories = [];
578
- configure = $hook({
579
- on: "configure",
580
- handler: async () => {
581
- await Promise.all(this.alepha.descriptors($serve).map((it) => this.createStaticServer(it.options)));
582
- }
583
- });
584
- async createStaticServer(options) {
585
- const prefix = options.path ?? "/";
586
- let root = options.root ?? process.cwd();
587
- if (!isAbsolute(root)) root = join(process.cwd(), root);
588
- this.log.debug("Serve static files", {
589
- prefix,
590
- root
591
- });
592
- await stat(root);
593
- const files = await this.getAllFiles(root, options.ignoreDotEnvFiles);
594
- const routes = await Promise.all(files.map(async (file) => {
595
- const path = file.replace(root, "").replace(/\\/g, "/");
596
- this.log.trace(`Mount ${join(prefix, path)} -> ${join(root, path)}`);
597
- return {
598
- path: join(prefix, encodeURI(path)),
599
- handler: await this.createFileHandler(join(root, path), options)
600
- };
601
- }));
602
- for (const route of routes) {
603
- this.routerProvider.createRoute(route);
604
- if (options.indexFallback !== false && route.path.endsWith("index.html")) this.routerProvider.createRoute({
605
- path: route.path.replace(/index\.html$/, ""),
606
- handler: route.handler
607
- });
608
- }
609
- this.directories.push({
610
- options,
611
- files: files.map((file) => file.replace(root, "").replace(/\\/g, "/"))
612
- });
613
- if (options.historyApiFallback) this.routerProvider.createRoute({
614
- path: join(prefix, "*").replace(/\\/g, "/"),
615
- handler: async (request) => {
616
- const { reply } = request;
617
- if (request.url.pathname.includes(".")) {
618
- reply.headers["content-type"] = "text/plain";
619
- reply.body = "Not Found";
620
- reply.status = 404;
621
- return;
622
- }
623
- reply.headers["content-type"] = "text/html";
624
- reply.status = 200;
625
- return createReadStream(join(root, "index.html"));
626
- }
627
- });
628
- }
629
- async createFileHandler(filepath, options) {
630
- const filename = basename(filepath);
631
- const hasGzip = await access(`${filepath}.gz`).then(() => true).catch(() => false);
632
- const hasBr = await access(`${filepath}.br`).then(() => true).catch(() => false);
633
- const fileStat = await stat(filepath);
634
- const lastModified = fileStat.mtime.toUTCString();
635
- const etag = `"${fileStat.size}-${fileStat.mtime.getTime()}"`;
636
- const contentType = this.fileDetector.getContentType(filename);
637
- const cacheControl = this.getCacheControl(filename, options);
638
- return async (request) => {
639
- const { headers, reply } = request;
640
- let path = filepath;
641
- const encoding = headers["accept-encoding"];
642
- if (encoding) {
643
- if (hasBr && encoding.includes("br")) {
644
- reply.headers["content-encoding"] = "br";
645
- path += ".br";
646
- } else if (hasGzip && encoding.includes("gzip")) {
647
- reply.headers["content-encoding"] = "gzip";
648
- path += ".gz";
649
- }
650
- }
651
- reply.headers["content-type"] = contentType;
652
- reply.headers["accept-ranges"] = "bytes";
653
- reply.headers["last-modified"] = lastModified;
654
- if (cacheControl) {
655
- reply.headers["cache-control"] = `public, max-age=${cacheControl.maxAge}`;
656
- if (cacheControl.immutable) reply.headers["cache-control"] += ", immutable";
657
- }
658
- reply.headers.etag = etag;
659
- if (headers["if-none-match"] === etag || headers["if-modified-since"] === lastModified) {
660
- reply.status = 304;
661
- return;
662
- }
663
- return createReadStream(path);
664
- };
665
- }
666
- getCacheFileTypes() {
667
- return [
668
- ".js",
669
- ".css",
670
- ".woff",
671
- ".woff2",
672
- ".ttf",
673
- ".eot",
674
- ".otf",
675
- ".jpg",
676
- ".jpeg",
677
- ".png",
678
- ".svg",
679
- ".gif"
680
- ];
681
- }
682
- getCacheControl(filename, options) {
683
- if (!options.cacheControl) return;
684
- const fileTypes = options.cacheControl.fileTypes ?? this.getCacheFileTypes();
685
- for (const type of fileTypes) if (filename.endsWith(type)) return {
686
- immutable: options.cacheControl.immutable ?? true,
687
- maxAge: this.dateTimeProvider.duration(options.cacheControl.maxAge ?? [30, "days"]).as("seconds")
688
- };
689
- }
690
- async getAllFiles(dir, ignoreDotEnvFiles = true) {
691
- const entries = await readdir(dir, { withFileTypes: true });
692
- return (await Promise.all(entries.map((dirent) => {
693
- if (ignoreDotEnvFiles && dirent.name.startsWith(".")) return [];
694
- const fullPath = join(dir, dirent.name);
695
- return dirent.isDirectory() ? this.getAllFiles(fullPath) : fullPath;
696
- }))).flat();
697
- }
698
- };
699
-
700
- //#endregion
701
- //#region src/server-static/index.ts
702
- /**
703
- * Create static file server with `$static()`.
704
- *
705
- * @see {@link ServerStaticProvider}
706
- * @module alepha.server.static
707
- */
708
- const AlephaServerStatic = $module({
709
- name: "alepha.server.static",
710
- descriptors: [$serve],
711
- services: [AlephaServer, ServerStaticProvider]
712
- });
713
-
714
- //#endregion
715
- //#region src/server-swagger/descriptors/$swagger.ts
12
+ //#region src/server-swagger/primitives/$swagger.ts
716
13
  /**
717
- * Creates an OpenAPI/Swagger documentation descriptor with interactive UI.
14
+ * Creates an OpenAPI/Swagger documentation primitive with interactive UI.
718
15
  *
719
- * Automatically generates API documentation from your $action descriptors and serves
16
+ * Automatically generates API documentation from your $action primitives and serves
720
17
  * an interactive Swagger UI for testing endpoints. Supports customization, tag filtering,
721
18
  * and OAuth configuration.
722
19
  *
@@ -737,10 +34,10 @@ const AlephaServerStatic = $module({
737
34
  * ```
738
35
  */
739
36
  const $swagger = (options = {}) => {
740
- return createDescriptor(SwaggerDescriptor, options);
37
+ return createPrimitive(SwaggerPrimitive, options);
741
38
  };
742
- var SwaggerDescriptor = class extends Descriptor {};
743
- $swagger[KIND] = SwaggerDescriptor;
39
+ var SwaggerPrimitive = class extends Primitive {};
40
+ $swagger[KIND] = SwaggerPrimitive;
744
41
 
745
42
  //#endregion
746
43
  //#region src/server-swagger/providers/ServerSwaggerProvider.ts
@@ -765,14 +62,14 @@ var ServerSwaggerProvider = class {
765
62
  on: "configure",
766
63
  priority: "last",
767
64
  handler: async (alepha) => {
768
- const options = alepha.descriptors($swagger)?.[0]?.options;
65
+ const options = alepha.primitives($swagger)?.[0]?.options;
769
66
  if (!options) return;
770
67
  this.json = await this.createSwagger(options);
771
68
  }
772
69
  });
773
70
  async createSwagger(options) {
774
71
  if (options.disabled) return;
775
- const json = this.configureOpenApi(this.alepha.descriptors($action), options);
72
+ const json = this.configureOpenApi(this.alepha.primitives($action), options);
776
73
  if (options.rewrite) options.rewrite(json);
777
74
  const prefix = options.prefix ?? "/docs";
778
75
  this.configureSwaggerApi(prefix, json);
@@ -940,7 +237,7 @@ window.onload = function() {
940
237
  };
941
238
  `.trim();
942
239
  const dirname = fileURLToPath(import.meta.url);
943
- const root = await this.getAssetPath(ui.root, join(dirname, "../../assets/swagger-ui"), join(dirname, "../../../../assets/swagger-ui"));
240
+ const root = await this.getAssetPath(ui.root, join(dirname, "../../assets/swagger-ui"), join(dirname, "../../../assets/swagger-ui"), join(dirname, "../../../../assets/swagger-ui"));
944
241
  if (!root) {
945
242
  this.log.warn(`Failed to locate Swagger UI assets for path ${prefix}`);
946
243
  return;
@@ -1001,17 +298,17 @@ window.onload = function() {
1001
298
  */
1002
299
  const AlephaServerSwagger = $module({
1003
300
  name: "alepha.server.swagger",
1004
- descriptors: [$swagger],
301
+ primitives: [$swagger],
1005
302
  services: [ServerSwaggerProvider],
1006
303
  register: (alepha) => {
1007
304
  alepha.with(AlephaServer);
1008
305
  alepha.with(AlephaServerCache);
1009
306
  alepha.with(AlephaServerStatic);
1010
307
  alepha.with(ServerSwaggerProvider);
1011
- alepha.state.push("alepha.build.assets", "alepha");
308
+ alepha.store.push("alepha.build.assets", "alepha");
1012
309
  }
1013
310
  });
1014
311
 
1015
312
  //#endregion
1016
- export { $swagger, AlephaServerSwagger, ServerSwaggerProvider, SwaggerDescriptor, swaggerOptions };
313
+ export { $swagger, AlephaServerSwagger, ServerSwaggerProvider, SwaggerPrimitive, swaggerOptions };
1017
314
  //# sourceMappingURL=index.js.map