alepha 0.15.4 → 0.15.5

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 (282) hide show
  1. package/README.md +26 -11
  2. package/dist/api/audits/index.d.ts +3 -3
  3. package/dist/api/audits/index.js +3 -3
  4. package/dist/api/audits/index.js.map +1 -1
  5. package/dist/api/files/index.d.ts +3 -3
  6. package/dist/api/files/index.js +3 -3
  7. package/dist/api/files/index.js.map +1 -1
  8. package/dist/api/jobs/index.d.ts +47 -4
  9. package/dist/api/jobs/index.d.ts.map +1 -1
  10. package/dist/api/jobs/index.js +100 -5
  11. package/dist/api/jobs/index.js.map +1 -1
  12. package/dist/api/keys/index.d.ts +3 -3
  13. package/dist/api/keys/index.js +3 -3
  14. package/dist/api/keys/index.js.map +1 -1
  15. package/dist/api/notifications/index.d.ts +3 -3
  16. package/dist/api/notifications/index.js +3 -3
  17. package/dist/api/notifications/index.js.map +1 -1
  18. package/dist/api/parameters/index.d.ts +263 -263
  19. package/dist/api/parameters/index.d.ts.map +1 -1
  20. package/dist/api/parameters/index.js +31 -30
  21. package/dist/api/parameters/index.js.map +1 -1
  22. package/dist/api/users/index.d.ts +373 -67
  23. package/dist/api/users/index.d.ts.map +1 -1
  24. package/dist/api/users/index.js +273 -72
  25. package/dist/api/users/index.js.map +1 -1
  26. package/dist/api/verifications/index.d.ts +3 -3
  27. package/dist/api/verifications/index.js +3 -3
  28. package/dist/api/verifications/index.js.map +1 -1
  29. package/dist/batch/index.d.ts +7 -7
  30. package/dist/batch/index.js +3 -3
  31. package/dist/batch/index.js.map +1 -1
  32. package/dist/bucket/index.d.ts +3 -3
  33. package/dist/bucket/index.js +6 -6
  34. package/dist/bucket/index.js.map +1 -1
  35. package/dist/cache/core/index.d.ts +3 -3
  36. package/dist/cache/core/index.js +3 -3
  37. package/dist/cache/core/index.js.map +1 -1
  38. package/dist/cli/index.d.ts +5607 -20
  39. package/dist/cli/index.d.ts.map +1 -1
  40. package/dist/cli/index.js +103 -89
  41. package/dist/cli/index.js.map +1 -1
  42. package/dist/command/index.d.ts +11 -4
  43. package/dist/command/index.d.ts.map +1 -1
  44. package/dist/command/index.js +8 -6
  45. package/dist/command/index.js.map +1 -1
  46. package/dist/core/index.browser.js.map +1 -1
  47. package/dist/core/index.d.ts +4 -8
  48. package/dist/core/index.d.ts.map +1 -1
  49. package/dist/core/index.js +3 -3
  50. package/dist/core/index.js.map +1 -1
  51. package/dist/core/index.native.js.map +1 -1
  52. package/dist/datetime/index.d.ts +3 -3
  53. package/dist/datetime/index.js +3 -3
  54. package/dist/datetime/index.js.map +1 -1
  55. package/dist/email/index.d.ts +3 -3
  56. package/dist/email/index.js +8 -8
  57. package/dist/email/index.js.map +1 -1
  58. package/dist/fake/index.d.ts +3 -3
  59. package/dist/fake/index.js +3 -3
  60. package/dist/fake/index.js.map +1 -1
  61. package/dist/lock/core/index.d.ts +3 -3
  62. package/dist/lock/core/index.js +3 -3
  63. package/dist/lock/core/index.js.map +1 -1
  64. package/dist/logger/index.d.ts +3 -3
  65. package/dist/logger/index.js +6 -3
  66. package/dist/logger/index.js.map +1 -1
  67. package/dist/mcp/index.d.ts +3 -3
  68. package/dist/mcp/index.js +3 -3
  69. package/dist/mcp/index.js.map +1 -1
  70. package/dist/orm/index.d.ts +12 -12
  71. package/dist/orm/index.js +4 -4
  72. package/dist/orm/index.js.map +1 -1
  73. package/dist/queue/core/index.d.ts +3 -3
  74. package/dist/queue/core/index.js +3 -3
  75. package/dist/queue/core/index.js.map +1 -1
  76. package/dist/react/auth/index.d.ts +3 -3
  77. package/dist/react/auth/index.js +3 -3
  78. package/dist/react/auth/index.js.map +1 -1
  79. package/dist/react/core/index.d.ts +3 -3
  80. package/dist/react/core/index.js +3 -3
  81. package/dist/react/core/index.js.map +1 -1
  82. package/dist/react/form/index.d.ts +3 -3
  83. package/dist/react/form/index.js +3 -3
  84. package/dist/react/form/index.js.map +1 -1
  85. package/dist/react/head/index.d.ts +3 -3
  86. package/dist/react/head/index.js +3 -3
  87. package/dist/react/head/index.js.map +1 -1
  88. package/dist/react/i18n/index.d.ts +3 -3
  89. package/dist/react/i18n/index.js +3 -3
  90. package/dist/react/i18n/index.js.map +1 -1
  91. package/dist/react/intro/index.css +337 -0
  92. package/dist/react/intro/index.css.map +1 -0
  93. package/dist/react/intro/index.d.ts +10 -0
  94. package/dist/react/intro/index.d.ts.map +1 -0
  95. package/dist/react/intro/index.js +222 -0
  96. package/dist/react/intro/index.js.map +1 -0
  97. package/dist/react/router/index.browser.js +2 -2
  98. package/dist/react/router/index.browser.js.map +1 -1
  99. package/dist/react/router/index.d.ts +1 -1
  100. package/dist/react/router/index.d.ts.map +1 -1
  101. package/dist/react/router/index.js +5 -5
  102. package/dist/react/router/index.js.map +1 -1
  103. package/dist/redis/index.d.ts +17 -17
  104. package/dist/redis/index.js +3 -3
  105. package/dist/redis/index.js.map +1 -1
  106. package/dist/retry/index.d.ts +3 -3
  107. package/dist/retry/index.js +3 -3
  108. package/dist/retry/index.js.map +1 -1
  109. package/dist/scheduler/index.d.ts +3 -3
  110. package/dist/scheduler/index.js +3 -3
  111. package/dist/scheduler/index.js.map +1 -1
  112. package/dist/security/index.d.ts +3 -3
  113. package/dist/security/index.js +5 -5
  114. package/dist/security/index.js.map +1 -1
  115. package/dist/server/auth/index.d.ts +3 -3
  116. package/dist/server/auth/index.js +3 -3
  117. package/dist/server/auth/index.js.map +1 -1
  118. package/dist/server/cache/index.d.ts +3 -3
  119. package/dist/server/cache/index.js +3 -3
  120. package/dist/server/cache/index.js.map +1 -1
  121. package/dist/server/compress/index.d.ts +3 -3
  122. package/dist/server/compress/index.js +3 -3
  123. package/dist/server/compress/index.js.map +1 -1
  124. package/dist/server/cookies/index.d.ts +3 -3
  125. package/dist/server/cookies/index.js +3 -3
  126. package/dist/server/cookies/index.js.map +1 -1
  127. package/dist/server/core/index.d.ts +5 -16
  128. package/dist/server/core/index.d.ts.map +1 -1
  129. package/dist/server/core/index.js +13 -29
  130. package/dist/server/core/index.js.map +1 -1
  131. package/dist/server/cors/index.d.ts +3 -3
  132. package/dist/server/cors/index.js +3 -3
  133. package/dist/server/cors/index.js.map +1 -1
  134. package/dist/server/health/index.d.ts +20 -20
  135. package/dist/server/health/index.js +3 -3
  136. package/dist/server/health/index.js.map +1 -1
  137. package/dist/server/helmet/index.d.ts +3 -3
  138. package/dist/server/helmet/index.js +3 -3
  139. package/dist/server/helmet/index.js.map +1 -1
  140. package/dist/server/links/index.d.ts +42 -42
  141. package/dist/server/links/index.d.ts.map +1 -1
  142. package/dist/server/links/index.js +3 -3
  143. package/dist/server/links/index.js.map +1 -1
  144. package/dist/server/metrics/index.d.ts +3 -3
  145. package/dist/server/metrics/index.js +3 -3
  146. package/dist/server/metrics/index.js.map +1 -1
  147. package/dist/server/multipart/index.d.ts +3 -3
  148. package/dist/server/multipart/index.js +3 -3
  149. package/dist/server/multipart/index.js.map +1 -1
  150. package/dist/server/proxy/index.d.ts +3 -3
  151. package/dist/server/proxy/index.js +3 -3
  152. package/dist/server/proxy/index.js.map +1 -1
  153. package/dist/server/rate-limit/index.d.ts +3 -3
  154. package/dist/server/rate-limit/index.js +3 -3
  155. package/dist/server/rate-limit/index.js.map +1 -1
  156. package/dist/server/static/index.d.ts +3 -3
  157. package/dist/server/static/index.js +6 -6
  158. package/dist/server/static/index.js.map +1 -1
  159. package/dist/server/swagger/index.d.ts +3 -3
  160. package/dist/server/swagger/index.js +6 -6
  161. package/dist/server/swagger/index.js.map +1 -1
  162. package/dist/sms/index.d.ts +3 -3
  163. package/dist/sms/index.js +6 -6
  164. package/dist/sms/index.js.map +1 -1
  165. package/dist/system/index.d.ts +3 -3
  166. package/dist/system/index.js +3 -3
  167. package/dist/system/index.js.map +1 -1
  168. package/dist/thread/index.d.ts +3 -3
  169. package/dist/thread/index.js +3 -3
  170. package/dist/thread/index.js.map +1 -1
  171. package/dist/topic/core/index.d.ts +3 -3
  172. package/dist/topic/core/index.js +3 -3
  173. package/dist/topic/core/index.js.map +1 -1
  174. package/dist/vite/index.d.ts +6284 -3
  175. package/dist/vite/index.d.ts.map +1 -1
  176. package/dist/websocket/index.d.ts +3 -3
  177. package/dist/websocket/index.js +3 -3
  178. package/dist/websocket/index.js.map +1 -1
  179. package/package.json +7 -2
  180. package/src/api/audits/index.ts +3 -3
  181. package/src/api/files/index.ts +3 -3
  182. package/src/api/jobs/controllers/AdminJobController.ts +15 -2
  183. package/src/api/jobs/index.ts +4 -3
  184. package/src/api/jobs/services/JobAudits.spec.ts +89 -0
  185. package/src/api/jobs/services/JobAudits.ts +101 -0
  186. package/src/api/keys/index.ts +3 -3
  187. package/src/api/notifications/index.ts +3 -3
  188. package/src/api/parameters/index.ts +5 -3
  189. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1 -1
  190. package/src/api/users/__tests__/ApiKeys.spec.ts +1 -1
  191. package/src/api/users/__tests__/EmailVerification.spec.ts +16 -1
  192. package/src/api/users/__tests__/PasswordReset.spec.ts +11 -0
  193. package/src/api/users/atoms/realmAuthSettingsAtom.ts +10 -0
  194. package/src/api/users/index.ts +8 -9
  195. package/src/api/users/primitives/$realm.ts +117 -19
  196. package/src/api/users/providers/RealmProvider.ts +15 -7
  197. package/src/api/users/services/CredentialService.spec.ts +11 -0
  198. package/src/api/users/services/CredentialService.ts +47 -24
  199. package/src/api/users/services/IdentityService.ts +12 -4
  200. package/src/api/users/services/RegistrationService.spec.ts +11 -0
  201. package/src/api/users/services/RegistrationService.ts +33 -12
  202. package/src/api/users/services/SessionService.ts +83 -12
  203. package/src/api/users/services/UserAudits.ts +47 -0
  204. package/src/api/users/services/UserFiles.ts +19 -0
  205. package/src/api/users/services/UserJobs.spec.ts +107 -0
  206. package/src/api/users/services/UserJobs.ts +62 -0
  207. package/src/api/users/services/UserParameters.ts +23 -0
  208. package/src/api/users/services/UserService.ts +34 -17
  209. package/src/api/verifications/index.ts +3 -3
  210. package/src/batch/index.ts +3 -3
  211. package/src/bucket/index.ts +3 -3
  212. package/src/cache/core/index.ts +3 -3
  213. package/src/cli/commands/db.ts +9 -0
  214. package/src/cli/commands/init.spec.ts +2 -17
  215. package/src/cli/commands/init.ts +37 -1
  216. package/src/cli/providers/ViteDevServerProvider.ts +5 -2
  217. package/src/cli/services/AlephaCliUtils.ts +17 -0
  218. package/src/cli/services/PackageManagerUtils.ts +15 -1
  219. package/src/cli/services/ProjectScaffolder.ts +8 -13
  220. package/src/cli/templates/agentMd.ts +2 -25
  221. package/src/cli/templates/apiAppSecurityTs.ts +37 -2
  222. package/src/cli/templates/mainCss.ts +2 -32
  223. package/src/cli/templates/webAppRouterTs.ts +5 -5
  224. package/src/cli/templates/webHomeComponentTsx.ts +10 -0
  225. package/src/command/helpers/Runner.ts +14 -1
  226. package/src/command/index.ts +3 -3
  227. package/src/core/helpers/primitive.ts +0 -5
  228. package/src/core/index.ts +3 -3
  229. package/src/datetime/index.ts +3 -3
  230. package/src/email/index.ts +3 -3
  231. package/src/email/providers/LocalEmailProvider.ts +2 -2
  232. package/src/fake/index.ts +3 -3
  233. package/src/lock/core/index.ts +3 -3
  234. package/src/logger/index.ts +3 -3
  235. package/src/logger/providers/PrettyFormatterProvider.ts +7 -0
  236. package/src/mcp/index.ts +3 -3
  237. package/src/orm/index.ts +3 -3
  238. package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
  239. package/src/queue/core/index.ts +3 -3
  240. package/src/react/auth/index.ts +3 -3
  241. package/src/react/core/index.ts +3 -3
  242. package/src/react/form/index.ts +3 -3
  243. package/src/react/head/index.ts +3 -3
  244. package/src/react/i18n/index.ts +3 -3
  245. package/src/react/intro/components/GettingStarted.css +334 -0
  246. package/src/react/intro/components/GettingStarted.tsx +276 -0
  247. package/src/react/intro/index.ts +1 -0
  248. package/src/react/router/index.browser.ts +2 -0
  249. package/src/react/router/index.ts +2 -0
  250. package/src/redis/index.ts +3 -3
  251. package/src/retry/index.ts +3 -3
  252. package/src/router/index.ts +3 -3
  253. package/src/scheduler/index.ts +3 -3
  254. package/src/security/index.ts +3 -3
  255. package/src/security/providers/JwtProvider.ts +2 -2
  256. package/src/server/auth/index.ts +3 -3
  257. package/src/server/cache/index.ts +3 -3
  258. package/src/server/compress/index.ts +3 -3
  259. package/src/server/cookies/index.ts +3 -3
  260. package/src/server/core/index.ts +3 -3
  261. package/src/server/core/primitives/$action.spec.ts +3 -2
  262. package/src/server/core/primitives/$action.ts +6 -2
  263. package/src/server/core/providers/NodeHttpServerProvider.ts +2 -15
  264. package/src/server/core/providers/ServerProvider.ts +4 -2
  265. package/src/server/core/providers/ServerRouterProvider.ts +5 -27
  266. package/src/server/cors/index.ts +3 -3
  267. package/src/server/health/index.ts +3 -3
  268. package/src/server/helmet/index.ts +3 -3
  269. package/src/server/links/index.ts +3 -3
  270. package/src/server/metrics/index.ts +3 -3
  271. package/src/server/multipart/index.ts +3 -3
  272. package/src/server/proxy/index.ts +3 -3
  273. package/src/server/rate-limit/index.ts +3 -3
  274. package/src/server/static/index.ts +3 -3
  275. package/src/server/swagger/index.ts +3 -3
  276. package/src/sms/index.ts +3 -3
  277. package/src/system/index.ts +3 -3
  278. package/src/thread/index.ts +3 -3
  279. package/src/topic/core/index.ts +3 -3
  280. package/src/websocket/index.ts +3 -3
  281. package/src/cli/templates/webHelloComponentTsx.ts +0 -30
  282. /package/src/api/users/{notifications → services}/UserNotifications.ts +0 -0
@@ -146,9 +146,9 @@ interface RouteCacheEntry {
146
146
  //#endregion
147
147
  //#region ../../src/server/cache/index.d.ts
148
148
  /**
149
- * | type | quality | stability |
150
- * |------|---------|-----------|
151
- * | backend | standard | stable |
149
+ * | Stability | Since | Runtime |
150
+ * |-----------|-------|---------|
151
+ * | 3 - stable | 0.10.0 | node, bun, workerd|
152
152
  *
153
153
  * ETag-based response caching.
154
154
  *
@@ -267,9 +267,9 @@ var ServerCacheProvider = class {
267
267
  //#endregion
268
268
  //#region ../../src/server/cache/index.ts
269
269
  /**
270
- * | type | quality | stability |
271
- * |------|---------|-----------|
272
- * | backend | standard | stable |
270
+ * | Stability | Since | Runtime |
271
+ * |-----------|-------|---------|
272
+ * | 3 - stable | 0.10.0 | node, bun, workerd|
273
273
  *
274
274
  * ETag-based response caching.
275
275
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/server/cache/providers/ServerCacheProvider.ts","../../../src/server/cache/index.ts"],"sourcesContent":["import type { BinaryLike } from \"node:crypto\";\nimport { createHash } from \"node:crypto\";\nimport { $hook, $inject, Alepha } from \"alepha\";\nimport { $cache, type CachePrimitiveOptions } from \"alepha/cache\";\nimport { DateTimeProvider, type DurationLike } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport {\n ActionPrimitive,\n type RequestConfigSchema,\n type ServerRequest,\n type ServerRoute,\n} from \"alepha/server\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha/server\" {\n interface ServerRoute {\n /**\n * Enable caching for this route.\n * - If true: enables both store and etag\n * - If object: fine-grained control over store, etag, and cache-control headers\n *\n * @default false\n */\n cache?: ServerRouteCache;\n }\n\n interface ActionPrimitive<TConfig extends RequestConfigSchema> {\n invalidate: () => Promise<void>;\n }\n}\n\nActionPrimitive.prototype.invalidate = async function (\n this: ActionPrimitive<RequestConfigSchema>,\n) {\n await this.alepha.inject(ServerCacheProvider).invalidate(this.route);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class ServerCacheProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly time = $inject(DateTimeProvider);\n protected readonly cache = $cache<RouteCacheEntry>({\n provider: \"memory\",\n });\n\n public generateETag(content: BinaryLike): string {\n return `\"${createHash(\"md5\").update(content).digest(\"hex\")}\"`;\n }\n\n public async invalidate(route: ServerRoute) {\n const cache = route.cache;\n if (!cache) {\n return;\n }\n\n await this.cache.invalidate(this.createCacheKey(route));\n }\n\n protected readonly onActionRequest = $hook({\n on: \"action:onRequest\",\n handler: async ({ action, request }) => {\n const cache = action.route.cache;\n\n const shouldStore = this.shouldStore(cache);\n\n // Only check cache if storing is enabled\n if (shouldStore) {\n const key = this.createCacheKey(action.route, request);\n const cached = await this.cache.get(key);\n\n if (cached) {\n const body =\n cached.contentType === \"application/json\"\n ? JSON.parse(cached.body)\n : cached.body;\n\n this.log.trace(\"Cache hit for action\", {\n key,\n action: action.name,\n });\n\n request.reply.body = body; // just re-use, full trust\n } else {\n this.log.trace(\"Cache miss for action\", {\n key,\n action: action.name,\n });\n }\n }\n },\n });\n\n protected readonly onActionResponse = $hook({\n on: \"action:onResponse\",\n handler: async ({ action, request, response }) => {\n const cache = action.route.cache;\n\n const shouldStore = this.shouldStore(cache);\n\n if (!shouldStore || !response) {\n return;\n }\n\n // Don't cache error responses (status >= 400)\n if (request.reply.status && request.reply.status >= 400) {\n return;\n }\n\n // TODO: serialize the response body, exactly like in the server response hook\n // this is bad\n const contentType =\n typeof response === \"string\" ? \"text/plain\" : \"application/json\";\n const body =\n contentType === \"text/plain\" ? response : JSON.stringify(response);\n\n const generatedEtag = this.generateETag(body);\n const lastModified = this.time.toISOString();\n\n // Store response for cached actions\n const key = this.createCacheKey(action.route, request);\n\n this.log.trace(\"Storing response\", {\n key,\n action: action.name,\n });\n\n await this.cache.set(key, {\n body: body,\n lastModified,\n contentType: contentType,\n hash: generatedEtag,\n });\n\n // Set Cache-Control header if configured (for HTTP responses)\n const cacheControl = this.buildCacheControlHeader(cache);\n if (cacheControl) {\n request.reply.setHeader(\"cache-control\", cacheControl);\n }\n },\n });\n\n protected readonly onRequest = $hook({\n on: \"server:onRequest\",\n handler: async ({ route, request }) => {\n const cache = route.cache;\n\n const shouldStore = this.shouldStore(cache);\n const shouldUseEtag = this.shouldUseEtag(cache);\n\n // Check for cached response or ETag\n if (!shouldStore && !shouldUseEtag) {\n return;\n }\n\n const key = this.createCacheKey(route, request);\n const cached = await this.cache.get(key);\n\n if (cached) {\n // Check if client has matching ETag - return 304 for both cached and etag-only routes\n if (\n request.headers[\"if-none-match\"] === cached.hash ||\n request.headers[\"if-modified-since\"] === cached.lastModified\n ) {\n request.reply.status = 304;\n request.reply.setHeader(\"etag\", cached.hash);\n request.reply.setHeader(\"last-modified\", cached.lastModified);\n this.log.trace(\"ETag match, returning 304\", {\n route: route.path,\n etag: cached.hash,\n });\n return;\n }\n\n // Only serve cached content if storing is enabled (not for etag-only routes)\n if (shouldStore) {\n this.log.trace(\"Cache hit for route\", {\n key,\n route: route.path,\n });\n\n // if the cache is found, we can skip the request processing\n // and return the cached response\n request.reply.body = cached.body;\n request.reply.status = cached.status ?? 200;\n\n if (cached.contentType) {\n request.reply.setHeader(\"Content-Type\", cached.contentType);\n }\n\n request.reply.setHeader(\"etag\", cached.hash);\n request.reply.setHeader(\"last-modified\", cached.lastModified);\n }\n } else if (shouldStore) {\n this.log.trace(\"Cache miss for route\", {\n key,\n route: route.path,\n });\n }\n },\n });\n\n protected readonly onSend = $hook({\n on: \"server:onSend\",\n handler: ({ route, request }) => {\n // before sending the response, check if the ETag matches\n // and if so, return a 304 Not Modified response\n // -> this is only relevant for etag-only routes, not cached routes <-\n const cache = route.cache;\n\n const shouldStore = this.shouldStore(cache);\n const shouldUseEtag = this.shouldUseEtag(cache);\n\n if (request.reply.headers.etag) {\n // ETag already set, skip\n return;\n }\n\n if (\n !shouldStore &&\n shouldUseEtag &&\n request.reply.body != null &&\n (typeof request.reply.body === \"string\" ||\n Buffer.isBuffer(request.reply.body))\n ) {\n const generatedEtag = this.generateETag(request.reply.body);\n\n if (request.headers[\"if-none-match\"] === generatedEtag) {\n request.reply.status = 304;\n request.reply.body = undefined;\n request.reply.setHeader(\"etag\", generatedEtag);\n this.log.trace(\"ETag match on send, returning 304\", {\n route: route.path,\n etag: generatedEtag,\n });\n return;\n }\n }\n },\n });\n\n protected readonly onResponse = $hook({\n on: \"server:onResponse\",\n priority: \"first\",\n handler: async ({ route, request, response }) => {\n const cache = route.cache;\n\n // Set Cache-Control header if configured\n const cacheControl = this.buildCacheControlHeader(cache);\n if (cacheControl) {\n response.headers[\"cache-control\"] = cacheControl;\n }\n\n const shouldStore = this.shouldStore(cache);\n const shouldUseEtag = this.shouldUseEtag(cache);\n\n // Skip if neither cache nor etag is enabled\n if (!shouldStore && !shouldUseEtag) {\n return;\n }\n\n // Don't cache error responses (status >= 400)\n if (response.status && response.status >= 400) {\n return;\n }\n\n // Initialize headers if not present\n response.headers ??= {};\n\n const key = this.createCacheKey(route, request);\n\n // Handle ReadableStream responses (e.g., SSR streaming)\n if (response.body instanceof ReadableStream && shouldStore) {\n // Tee the stream: one for client, one for cache collection\n const [clientStream, cacheStream] = (\n response.body as ReadableStream<Uint8Array>\n ).tee();\n\n // Replace response body with client stream (continues streaming to client)\n response.body = clientStream as typeof response.body;\n\n // Collect cache stream in background (non-blocking)\n this.collectStreamForCache(\n cacheStream,\n key,\n response.status,\n response.headers?.[\"content-type\"],\n shouldUseEtag,\n )\n .then((hash) => {\n if (shouldUseEtag && hash) {\n // Note: headers already sent for streaming, etag only useful for future requests\n this.log.trace(\"Stream cached with hash\", { key, hash });\n }\n })\n .catch((err) => {\n this.log.warn(\"Failed to cache stream\", { key, error: err });\n });\n\n return;\n }\n\n // Only process string responses (text, html, json, etc.)\n if (typeof response.body !== \"string\") {\n return;\n }\n\n const generatedEtag = this.generateETag(response.body);\n const lastModified = this.time.toISOString();\n\n // Store response if storing is enabled\n if (shouldStore) {\n this.log.trace(\"Storing response\", {\n key,\n route: route.path,\n cache: !!cache,\n etag: shouldUseEtag,\n });\n\n await this.cache.set(key, {\n body: response.body,\n status: response.status,\n contentType: response.headers?.[\"content-type\"],\n lastModified,\n hash: generatedEtag,\n });\n }\n\n // Set ETag headers if etag is enabled\n if (shouldUseEtag) {\n response.headers.etag = generatedEtag;\n response.headers[\"last-modified\"] = lastModified;\n }\n },\n });\n\n public buildCacheControlHeader(cache?: ServerRouteCache): string | undefined {\n if (!cache) {\n return undefined;\n }\n\n // If cache is true or a DurationLike, no Cache-Control header is set\n if (\n cache === true ||\n typeof cache === \"string\" ||\n typeof cache === \"number\"\n ) {\n return undefined;\n }\n\n const control = cache.control;\n if (!control) {\n return undefined;\n }\n\n // If control is a string, return it directly\n if (typeof control === \"string\") {\n return control;\n }\n\n // If control is true, return default Cache-Control\n if (control === true) {\n return \"public, max-age=300\";\n }\n\n // Build Cache-Control from object directives\n const directives: string[] = [];\n\n if (control.public) {\n directives.push(\"public\");\n }\n if (control.private) {\n directives.push(\"private\");\n }\n if (control.noCache) {\n directives.push(\"no-cache\");\n }\n if (control.noStore) {\n directives.push(\"no-store\");\n }\n if (control.maxAge !== undefined) {\n const maxAgeSeconds = this.durationToSeconds(control.maxAge);\n directives.push(`max-age=${maxAgeSeconds}`);\n }\n if (control.sMaxAge !== undefined) {\n const sMaxAgeSeconds = this.durationToSeconds(control.sMaxAge);\n directives.push(`s-maxage=${sMaxAgeSeconds}`);\n }\n if (control.mustRevalidate) {\n directives.push(\"must-revalidate\");\n }\n if (control.proxyRevalidate) {\n directives.push(\"proxy-revalidate\");\n }\n if (control.immutable) {\n directives.push(\"immutable\");\n }\n\n return directives.length > 0 ? directives.join(\", \") : undefined;\n }\n\n protected durationToSeconds(duration: number | DurationLike): number {\n if (typeof duration === \"number\") {\n return duration;\n }\n\n return this.time.duration(duration).asSeconds();\n }\n\n protected shouldStore(cache?: ServerRouteCache): boolean {\n if (!cache) return false;\n if (cache === true) return true;\n if (typeof cache === \"object\" && cache.store) return true;\n return false;\n }\n\n protected shouldUseEtag(cache?: ServerRouteCache): boolean {\n // cache: true enables etag\n if (cache === true) return true;\n // Check object form\n if (typeof cache === \"object\" && cache.etag) return true;\n return false;\n }\n\n protected createCacheKey(route: ServerRoute, config?: ServerRequest): string {\n const params: string[] = [];\n for (const [key, value] of Object.entries(config?.params ?? {})) {\n params.push(`${key}=${value}`);\n }\n for (const [key, value] of Object.entries(config?.query ?? {})) {\n params.push(`${key}=${value}`);\n }\n\n return `${route.method}:${route.path.replaceAll(\":\", \"\")}:${params.join(\",\").replaceAll(\":\", \"\")}`;\n }\n\n /**\n * Collect a ReadableStream into a string and store it in the cache.\n * This runs in the background while the original stream is sent to the client.\n *\n * @param stream - The stream to collect\n * @param key - Cache key\n * @param status - HTTP status code\n * @param contentType - Content-Type header\n * @param generateEtag - Whether to generate and return an ETag\n * @returns The generated ETag hash, or undefined\n */\n protected async collectStreamForCache(\n stream: ReadableStream<Uint8Array>,\n key: string,\n status: number | undefined,\n contentType: string | undefined,\n generateEtag: boolean,\n ): Promise<string | undefined> {\n const chunks: Uint8Array[] = [];\n const reader = stream.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n\n // Combine chunks into a single string\n const decoder = new TextDecoder();\n const body =\n chunks\n .map((chunk) => decoder.decode(chunk, { stream: true }))\n .join(\"\") + decoder.decode(); // Flush remaining\n\n const hash = this.generateETag(body);\n const lastModified = this.time.toISOString();\n\n this.log.trace(\"Storing streamed response\", { key });\n\n await this.cache.set(key, {\n body,\n status,\n contentType,\n lastModified,\n hash,\n });\n\n return generateEtag ? hash : undefined;\n } finally {\n reader.releaseLock();\n }\n }\n}\n\nexport type ServerRouteCache =\n /**\n * If true, enables caching with:\n * - store: true\n * - etag: true\n */\n | boolean\n /**\n * Object configuration for fine-grained cache control.\n *\n * If empty, no caching will be applied.\n */\n | {\n /**\n * If true, enables storing cached responses. (in-memory, Redis, @see alepha/cache for other providers)\n * If a DurationLike is provided, it will be used as the TTL for the cache.\n * If CachePrimitiveOptions is provided, it will be used to configure the cache storage.\n *\n * @default false\n */\n store?: true | DurationLike | CachePrimitiveOptions;\n /**\n * If true, enables ETag support for the cached responses.\n */\n etag?: true;\n /**\n * - If true, sets Cache-Control to \"public, max-age=300\" (5 minutes).\n * - If string, sets Cache-Control to the provided value directly.\n * - If object, configures Cache-Control directives.\n */\n control?: /**\n * If true, sets Cache-Control to \"public, max-age=300\" (5 minutes).\n */\n | true\n /**\n * If string, sets Cache-Control to the provided value directly.\n */\n | string\n /**\n * If object, configures Cache-Control directives.\n */\n | {\n /**\n * Indicates that the response may be cached by any cache.\n */\n public?: boolean;\n /**\n * Indicates that the response is intended for a single user and must not be stored by a shared cache.\n */\n private?: boolean;\n /**\n * Forces caches to submit the request to the origin server for validation before releasing a cached copy.\n */\n noCache?: boolean;\n /**\n * Instructs caches not to store the response.\n */\n noStore?: boolean;\n /**\n * Maximum amount of time a resource is considered fresh.\n * Can be specified as a number (seconds) or as a DurationLike object.\n *\n * @example 300 // 5 minutes in seconds\n * @example { minutes: 5 } // 5 minutes\n * @example { hours: 1 } // 1 hour\n */\n maxAge?: number | DurationLike;\n /**\n * Overrides max-age for shared caches (e.g., CDNs).\n * Can be specified as a number (seconds) or as a DurationLike object.\n */\n sMaxAge?: number | DurationLike;\n /**\n * Indicates that once a resource becomes stale, caches must not use it without successful validation.\n */\n mustRevalidate?: boolean;\n /**\n * Similar to must-revalidate, but only for shared caches.\n */\n proxyRevalidate?: boolean;\n /**\n * Indicates that the response can be stored but must be revalidated before each use.\n */\n immutable?: boolean;\n };\n };\n\ninterface RouteCacheEntry {\n contentType?: string;\n body: any;\n status?: number;\n lastModified: string;\n hash: string;\n}\n","import { $module } from \"alepha\";\nimport { AlephaCache } from \"alepha/cache\";\nimport { ServerCacheProvider } from \"./providers/ServerCacheProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/ServerCacheProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * | type | quality | stability |\n * |------|---------|-----------|\n * | backend | standard | stable |\n *\n * ETag-based response caching.\n *\n * **Features:**\n * - ETag generation and validation\n * - Conditional request handling\n *\n * @module alepha.server.cache\n */\nexport const AlephaServerCache = $module({\n name: \"alepha.server.cache\",\n services: [AlephaCache, ServerCacheProvider],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/server/cache/providers/ServerCacheProvider.ts","../../../src/server/cache/index.ts"],"sourcesContent":["import type { BinaryLike } from \"node:crypto\";\nimport { createHash } from \"node:crypto\";\nimport { $hook, $inject, Alepha } from \"alepha\";\nimport { $cache, type CachePrimitiveOptions } from \"alepha/cache\";\nimport { DateTimeProvider, type DurationLike } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport {\n ActionPrimitive,\n type RequestConfigSchema,\n type ServerRequest,\n type ServerRoute,\n} from \"alepha/server\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha/server\" {\n interface ServerRoute {\n /**\n * Enable caching for this route.\n * - If true: enables both store and etag\n * - If object: fine-grained control over store, etag, and cache-control headers\n *\n * @default false\n */\n cache?: ServerRouteCache;\n }\n\n interface ActionPrimitive<TConfig extends RequestConfigSchema> {\n invalidate: () => Promise<void>;\n }\n}\n\nActionPrimitive.prototype.invalidate = async function (\n this: ActionPrimitive<RequestConfigSchema>,\n) {\n await this.alepha.inject(ServerCacheProvider).invalidate(this.route);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class ServerCacheProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly time = $inject(DateTimeProvider);\n protected readonly cache = $cache<RouteCacheEntry>({\n provider: \"memory\",\n });\n\n public generateETag(content: BinaryLike): string {\n return `\"${createHash(\"md5\").update(content).digest(\"hex\")}\"`;\n }\n\n public async invalidate(route: ServerRoute) {\n const cache = route.cache;\n if (!cache) {\n return;\n }\n\n await this.cache.invalidate(this.createCacheKey(route));\n }\n\n protected readonly onActionRequest = $hook({\n on: \"action:onRequest\",\n handler: async ({ action, request }) => {\n const cache = action.route.cache;\n\n const shouldStore = this.shouldStore(cache);\n\n // Only check cache if storing is enabled\n if (shouldStore) {\n const key = this.createCacheKey(action.route, request);\n const cached = await this.cache.get(key);\n\n if (cached) {\n const body =\n cached.contentType === \"application/json\"\n ? JSON.parse(cached.body)\n : cached.body;\n\n this.log.trace(\"Cache hit for action\", {\n key,\n action: action.name,\n });\n\n request.reply.body = body; // just re-use, full trust\n } else {\n this.log.trace(\"Cache miss for action\", {\n key,\n action: action.name,\n });\n }\n }\n },\n });\n\n protected readonly onActionResponse = $hook({\n on: \"action:onResponse\",\n handler: async ({ action, request, response }) => {\n const cache = action.route.cache;\n\n const shouldStore = this.shouldStore(cache);\n\n if (!shouldStore || !response) {\n return;\n }\n\n // Don't cache error responses (status >= 400)\n if (request.reply.status && request.reply.status >= 400) {\n return;\n }\n\n // TODO: serialize the response body, exactly like in the server response hook\n // this is bad\n const contentType =\n typeof response === \"string\" ? \"text/plain\" : \"application/json\";\n const body =\n contentType === \"text/plain\" ? response : JSON.stringify(response);\n\n const generatedEtag = this.generateETag(body);\n const lastModified = this.time.toISOString();\n\n // Store response for cached actions\n const key = this.createCacheKey(action.route, request);\n\n this.log.trace(\"Storing response\", {\n key,\n action: action.name,\n });\n\n await this.cache.set(key, {\n body: body,\n lastModified,\n contentType: contentType,\n hash: generatedEtag,\n });\n\n // Set Cache-Control header if configured (for HTTP responses)\n const cacheControl = this.buildCacheControlHeader(cache);\n if (cacheControl) {\n request.reply.setHeader(\"cache-control\", cacheControl);\n }\n },\n });\n\n protected readonly onRequest = $hook({\n on: \"server:onRequest\",\n handler: async ({ route, request }) => {\n const cache = route.cache;\n\n const shouldStore = this.shouldStore(cache);\n const shouldUseEtag = this.shouldUseEtag(cache);\n\n // Check for cached response or ETag\n if (!shouldStore && !shouldUseEtag) {\n return;\n }\n\n const key = this.createCacheKey(route, request);\n const cached = await this.cache.get(key);\n\n if (cached) {\n // Check if client has matching ETag - return 304 for both cached and etag-only routes\n if (\n request.headers[\"if-none-match\"] === cached.hash ||\n request.headers[\"if-modified-since\"] === cached.lastModified\n ) {\n request.reply.status = 304;\n request.reply.setHeader(\"etag\", cached.hash);\n request.reply.setHeader(\"last-modified\", cached.lastModified);\n this.log.trace(\"ETag match, returning 304\", {\n route: route.path,\n etag: cached.hash,\n });\n return;\n }\n\n // Only serve cached content if storing is enabled (not for etag-only routes)\n if (shouldStore) {\n this.log.trace(\"Cache hit for route\", {\n key,\n route: route.path,\n });\n\n // if the cache is found, we can skip the request processing\n // and return the cached response\n request.reply.body = cached.body;\n request.reply.status = cached.status ?? 200;\n\n if (cached.contentType) {\n request.reply.setHeader(\"Content-Type\", cached.contentType);\n }\n\n request.reply.setHeader(\"etag\", cached.hash);\n request.reply.setHeader(\"last-modified\", cached.lastModified);\n }\n } else if (shouldStore) {\n this.log.trace(\"Cache miss for route\", {\n key,\n route: route.path,\n });\n }\n },\n });\n\n protected readonly onSend = $hook({\n on: \"server:onSend\",\n handler: ({ route, request }) => {\n // before sending the response, check if the ETag matches\n // and if so, return a 304 Not Modified response\n // -> this is only relevant for etag-only routes, not cached routes <-\n const cache = route.cache;\n\n const shouldStore = this.shouldStore(cache);\n const shouldUseEtag = this.shouldUseEtag(cache);\n\n if (request.reply.headers.etag) {\n // ETag already set, skip\n return;\n }\n\n if (\n !shouldStore &&\n shouldUseEtag &&\n request.reply.body != null &&\n (typeof request.reply.body === \"string\" ||\n Buffer.isBuffer(request.reply.body))\n ) {\n const generatedEtag = this.generateETag(request.reply.body);\n\n if (request.headers[\"if-none-match\"] === generatedEtag) {\n request.reply.status = 304;\n request.reply.body = undefined;\n request.reply.setHeader(\"etag\", generatedEtag);\n this.log.trace(\"ETag match on send, returning 304\", {\n route: route.path,\n etag: generatedEtag,\n });\n return;\n }\n }\n },\n });\n\n protected readonly onResponse = $hook({\n on: \"server:onResponse\",\n priority: \"first\",\n handler: async ({ route, request, response }) => {\n const cache = route.cache;\n\n // Set Cache-Control header if configured\n const cacheControl = this.buildCacheControlHeader(cache);\n if (cacheControl) {\n response.headers[\"cache-control\"] = cacheControl;\n }\n\n const shouldStore = this.shouldStore(cache);\n const shouldUseEtag = this.shouldUseEtag(cache);\n\n // Skip if neither cache nor etag is enabled\n if (!shouldStore && !shouldUseEtag) {\n return;\n }\n\n // Don't cache error responses (status >= 400)\n if (response.status && response.status >= 400) {\n return;\n }\n\n // Initialize headers if not present\n response.headers ??= {};\n\n const key = this.createCacheKey(route, request);\n\n // Handle ReadableStream responses (e.g., SSR streaming)\n if (response.body instanceof ReadableStream && shouldStore) {\n // Tee the stream: one for client, one for cache collection\n const [clientStream, cacheStream] = (\n response.body as ReadableStream<Uint8Array>\n ).tee();\n\n // Replace response body with client stream (continues streaming to client)\n response.body = clientStream as typeof response.body;\n\n // Collect cache stream in background (non-blocking)\n this.collectStreamForCache(\n cacheStream,\n key,\n response.status,\n response.headers?.[\"content-type\"],\n shouldUseEtag,\n )\n .then((hash) => {\n if (shouldUseEtag && hash) {\n // Note: headers already sent for streaming, etag only useful for future requests\n this.log.trace(\"Stream cached with hash\", { key, hash });\n }\n })\n .catch((err) => {\n this.log.warn(\"Failed to cache stream\", { key, error: err });\n });\n\n return;\n }\n\n // Only process string responses (text, html, json, etc.)\n if (typeof response.body !== \"string\") {\n return;\n }\n\n const generatedEtag = this.generateETag(response.body);\n const lastModified = this.time.toISOString();\n\n // Store response if storing is enabled\n if (shouldStore) {\n this.log.trace(\"Storing response\", {\n key,\n route: route.path,\n cache: !!cache,\n etag: shouldUseEtag,\n });\n\n await this.cache.set(key, {\n body: response.body,\n status: response.status,\n contentType: response.headers?.[\"content-type\"],\n lastModified,\n hash: generatedEtag,\n });\n }\n\n // Set ETag headers if etag is enabled\n if (shouldUseEtag) {\n response.headers.etag = generatedEtag;\n response.headers[\"last-modified\"] = lastModified;\n }\n },\n });\n\n public buildCacheControlHeader(cache?: ServerRouteCache): string | undefined {\n if (!cache) {\n return undefined;\n }\n\n // If cache is true or a DurationLike, no Cache-Control header is set\n if (\n cache === true ||\n typeof cache === \"string\" ||\n typeof cache === \"number\"\n ) {\n return undefined;\n }\n\n const control = cache.control;\n if (!control) {\n return undefined;\n }\n\n // If control is a string, return it directly\n if (typeof control === \"string\") {\n return control;\n }\n\n // If control is true, return default Cache-Control\n if (control === true) {\n return \"public, max-age=300\";\n }\n\n // Build Cache-Control from object directives\n const directives: string[] = [];\n\n if (control.public) {\n directives.push(\"public\");\n }\n if (control.private) {\n directives.push(\"private\");\n }\n if (control.noCache) {\n directives.push(\"no-cache\");\n }\n if (control.noStore) {\n directives.push(\"no-store\");\n }\n if (control.maxAge !== undefined) {\n const maxAgeSeconds = this.durationToSeconds(control.maxAge);\n directives.push(`max-age=${maxAgeSeconds}`);\n }\n if (control.sMaxAge !== undefined) {\n const sMaxAgeSeconds = this.durationToSeconds(control.sMaxAge);\n directives.push(`s-maxage=${sMaxAgeSeconds}`);\n }\n if (control.mustRevalidate) {\n directives.push(\"must-revalidate\");\n }\n if (control.proxyRevalidate) {\n directives.push(\"proxy-revalidate\");\n }\n if (control.immutable) {\n directives.push(\"immutable\");\n }\n\n return directives.length > 0 ? directives.join(\", \") : undefined;\n }\n\n protected durationToSeconds(duration: number | DurationLike): number {\n if (typeof duration === \"number\") {\n return duration;\n }\n\n return this.time.duration(duration).asSeconds();\n }\n\n protected shouldStore(cache?: ServerRouteCache): boolean {\n if (!cache) return false;\n if (cache === true) return true;\n if (typeof cache === \"object\" && cache.store) return true;\n return false;\n }\n\n protected shouldUseEtag(cache?: ServerRouteCache): boolean {\n // cache: true enables etag\n if (cache === true) return true;\n // Check object form\n if (typeof cache === \"object\" && cache.etag) return true;\n return false;\n }\n\n protected createCacheKey(route: ServerRoute, config?: ServerRequest): string {\n const params: string[] = [];\n for (const [key, value] of Object.entries(config?.params ?? {})) {\n params.push(`${key}=${value}`);\n }\n for (const [key, value] of Object.entries(config?.query ?? {})) {\n params.push(`${key}=${value}`);\n }\n\n return `${route.method}:${route.path.replaceAll(\":\", \"\")}:${params.join(\",\").replaceAll(\":\", \"\")}`;\n }\n\n /**\n * Collect a ReadableStream into a string and store it in the cache.\n * This runs in the background while the original stream is sent to the client.\n *\n * @param stream - The stream to collect\n * @param key - Cache key\n * @param status - HTTP status code\n * @param contentType - Content-Type header\n * @param generateEtag - Whether to generate and return an ETag\n * @returns The generated ETag hash, or undefined\n */\n protected async collectStreamForCache(\n stream: ReadableStream<Uint8Array>,\n key: string,\n status: number | undefined,\n contentType: string | undefined,\n generateEtag: boolean,\n ): Promise<string | undefined> {\n const chunks: Uint8Array[] = [];\n const reader = stream.getReader();\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n }\n\n // Combine chunks into a single string\n const decoder = new TextDecoder();\n const body =\n chunks\n .map((chunk) => decoder.decode(chunk, { stream: true }))\n .join(\"\") + decoder.decode(); // Flush remaining\n\n const hash = this.generateETag(body);\n const lastModified = this.time.toISOString();\n\n this.log.trace(\"Storing streamed response\", { key });\n\n await this.cache.set(key, {\n body,\n status,\n contentType,\n lastModified,\n hash,\n });\n\n return generateEtag ? hash : undefined;\n } finally {\n reader.releaseLock();\n }\n }\n}\n\nexport type ServerRouteCache =\n /**\n * If true, enables caching with:\n * - store: true\n * - etag: true\n */\n | boolean\n /**\n * Object configuration for fine-grained cache control.\n *\n * If empty, no caching will be applied.\n */\n | {\n /**\n * If true, enables storing cached responses. (in-memory, Redis, @see alepha/cache for other providers)\n * If a DurationLike is provided, it will be used as the TTL for the cache.\n * If CachePrimitiveOptions is provided, it will be used to configure the cache storage.\n *\n * @default false\n */\n store?: true | DurationLike | CachePrimitiveOptions;\n /**\n * If true, enables ETag support for the cached responses.\n */\n etag?: true;\n /**\n * - If true, sets Cache-Control to \"public, max-age=300\" (5 minutes).\n * - If string, sets Cache-Control to the provided value directly.\n * - If object, configures Cache-Control directives.\n */\n control?: /**\n * If true, sets Cache-Control to \"public, max-age=300\" (5 minutes).\n */\n | true\n /**\n * If string, sets Cache-Control to the provided value directly.\n */\n | string\n /**\n * If object, configures Cache-Control directives.\n */\n | {\n /**\n * Indicates that the response may be cached by any cache.\n */\n public?: boolean;\n /**\n * Indicates that the response is intended for a single user and must not be stored by a shared cache.\n */\n private?: boolean;\n /**\n * Forces caches to submit the request to the origin server for validation before releasing a cached copy.\n */\n noCache?: boolean;\n /**\n * Instructs caches not to store the response.\n */\n noStore?: boolean;\n /**\n * Maximum amount of time a resource is considered fresh.\n * Can be specified as a number (seconds) or as a DurationLike object.\n *\n * @example 300 // 5 minutes in seconds\n * @example { minutes: 5 } // 5 minutes\n * @example { hours: 1 } // 1 hour\n */\n maxAge?: number | DurationLike;\n /**\n * Overrides max-age for shared caches (e.g., CDNs).\n * Can be specified as a number (seconds) or as a DurationLike object.\n */\n sMaxAge?: number | DurationLike;\n /**\n * Indicates that once a resource becomes stale, caches must not use it without successful validation.\n */\n mustRevalidate?: boolean;\n /**\n * Similar to must-revalidate, but only for shared caches.\n */\n proxyRevalidate?: boolean;\n /**\n * Indicates that the response can be stored but must be revalidated before each use.\n */\n immutable?: boolean;\n };\n };\n\ninterface RouteCacheEntry {\n contentType?: string;\n body: any;\n status?: number;\n lastModified: string;\n hash: string;\n}\n","import { $module } from \"alepha\";\nimport { AlephaCache } from \"alepha/cache\";\nimport { ServerCacheProvider } from \"./providers/ServerCacheProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/ServerCacheProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * | Stability | Since | Runtime |\n * |-----------|-------|---------|\n * | 3 - stable | 0.10.0 | node, bun, workerd|\n *\n * ETag-based response caching.\n *\n * **Features:**\n * - ETag generation and validation\n * - Conditional request handling\n *\n * @module alepha.server.cache\n */\nexport const AlephaServerCache = $module({\n name: \"alepha.server.cache\",\n services: [AlephaCache, ServerCacheProvider],\n});\n"],"mappings":"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"}
@@ -34,9 +34,9 @@ interface ServerCompressProviderOptions {
34
34
  //#endregion
35
35
  //#region ../../src/server/compress/index.d.ts
36
36
  /**
37
- * | type | quality | stability |
38
- * |------|---------|-----------|
39
- * | backend | standard | stable |
37
+ * | Stability | Since | Runtime |
38
+ * |-----------|-------|---------|
39
+ * | 3 - stable | 0.13.0 | node, bun|
40
40
  *
41
41
  * Response compression.
42
42
  *
@@ -136,9 +136,9 @@ var ServerCompressProvider = class ServerCompressProvider {
136
136
  //#endregion
137
137
  //#region ../../src/server/compress/index.ts
138
138
  /**
139
- * | type | quality | stability |
140
- * |------|---------|-----------|
141
- * | backend | standard | stable |
139
+ * | Stability | Since | Runtime |
140
+ * |-----------|-------|---------|
141
+ * | 3 - stable | 0.13.0 | node, bun|
142
142
  *
143
143
  * Response compression.
144
144
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/server/compress/providers/ServerCompressProvider.ts","../../../src/server/compress/index.ts"],"sourcesContent":["import { Readable, type Transform } from \"node:stream\";\nimport { ReadableStream } from \"node:stream/web\";\nimport { promisify } from \"node:util\";\nimport * as zlib from \"node:zlib\";\nimport { $hook, $inject, Alepha } from \"alepha\";\nimport type { ServerResponse } from \"alepha/server\";\n\nconst gzip = promisify(zlib.gzip);\nconst createGzip = zlib.createGzip;\nconst brotli = promisify(zlib.brotliCompress);\nconst createBrotliCompress = zlib.createBrotliCompress;\nconst zstd = zlib.zstdCompress ? promisify(zlib.zstdCompress) : undefined;\nconst createZstdCompress = zstd ? zlib.createZstdCompress : undefined;\n\ndeclare module \"alepha\" {\n interface State {\n \"alepha.server.compress.options\"?: ServerCompressProviderOptions;\n }\n}\n\nexport class ServerCompressProvider {\n static compressors: Record<\n string,\n | {\n compress: (...args: any[]) => Promise<Buffer>;\n stream: (options?: any) => Transform;\n }\n | undefined\n > = {\n gzip: {\n compress: gzip,\n stream: createGzip,\n },\n br: {\n compress: brotli,\n stream: createBrotliCompress,\n },\n zstd:\n zstd && createZstdCompress\n ? {\n compress: zstd,\n stream: createZstdCompress,\n }\n : undefined,\n };\n\n protected readonly alepha = $inject(Alepha);\n\n protected get options(): ServerCompressProviderOptions {\n return {\n allowedContentTypes: [\n \"application/json\",\n \"text/html\",\n \"application/javascript\",\n \"text/plain\",\n \"text/css\",\n ],\n ...this.alepha.store.get(\"alepha.server.compress.options\"),\n };\n }\n\n public readonly onResponse = $hook({\n on: \"server:onResponse\",\n handler: async ({ request, response }) => {\n // In serverless (Cloudflare Workers), skip compression entirely:\n // Cloudflare's edge network automatically compresses responses\n if (this.alepha.isServerless()) {\n return;\n }\n\n // skip if already compressed\n if (response.headers[\"content-encoding\"]) {\n return;\n }\n\n const acceptEncoding = request.headers[\"accept-encoding\"]; // skip if no accept-encoding header\n if (!acceptEncoding) {\n return;\n }\n\n // skip if not json or html (for now)\n if (!this.isAllowedContentType(response.headers[\"content-type\"])) {\n return;\n }\n\n for (const encoding of [\"zstd\", \"br\", \"gzip\"] as const) {\n if (\n acceptEncoding.includes(encoding) &&\n ServerCompressProvider.compressors[encoding]\n ) {\n await this.compress(encoding, response);\n return;\n }\n }\n },\n });\n\n protected isAllowedContentType(contentType: string | undefined): boolean {\n if (!contentType) {\n return false;\n }\n\n const lowerContentType = contentType.toLowerCase();\n\n return !!this.options.allowedContentTypes.find((it) =>\n lowerContentType.includes(it),\n );\n }\n\n protected async compress(\n encoding: keyof typeof ServerCompressProvider.compressors,\n response: ServerResponse,\n ): Promise<void> {\n const body = response.body; // can be string or Buffer or ArrayBuffer or Readable\n\n const compressor = ServerCompressProvider.compressors[encoding];\n if (!compressor) {\n return;\n }\n\n const params = this.getParams(encoding);\n\n if (\n typeof body === \"string\" ||\n Buffer.isBuffer(body) ||\n body instanceof ArrayBuffer\n ) {\n const compressed = await compressor.compress(body, {\n params,\n });\n this.setHeaders(response, encoding);\n response.headers[\"content-length\"] = compressed.length.toString();\n response.body = compressed;\n return;\n }\n\n if (typeof body === \"object\" && body instanceof Readable) {\n this.setHeaders(response, encoding);\n response.body = body.pipe(compressor.stream({ params }));\n return;\n }\n\n if (typeof body === \"object\" && body instanceof ReadableStream) {\n this.setHeaders(response, encoding);\n // For streaming responses, use flush mode to avoid buffering\n response.body = this.createFlushingCompressStream(\n body,\n compressor.stream,\n encoding,\n params,\n );\n }\n }\n\n /**\n * Create a compressed stream that flushes after each chunk.\n * This is essential for streaming SSR - ensures each chunk is sent immediately.\n */\n protected createFlushingCompressStream(\n input: ReadableStream,\n createCompressor: (options?: any) => Transform,\n encoding: string,\n params: Record<number, any>,\n ): ReadableStream<Uint8Array> {\n const compressor = createCompressor({\n params,\n flush: zlib.constants.Z_SYNC_FLUSH,\n });\n const reader = Readable.fromWeb(input);\n\n return new ReadableStream<Uint8Array>({\n start(controller) {\n compressor.on(\"data\", (chunk: Buffer) => {\n controller.enqueue(new Uint8Array(chunk));\n });\n\n compressor.on(\"end\", () => {\n controller.close();\n });\n\n compressor.on(\"error\", (err) => {\n controller.error(err);\n });\n\n reader.on(\"data\", (chunk: Buffer) => {\n compressor.write(chunk);\n // Force flush after each chunk for streaming\n // Cast to any because flush() exists on zlib streams but not in Transform type\n const zlibStream = compressor as any;\n if (encoding === \"gzip\") {\n zlibStream.flush(zlib.constants.Z_SYNC_FLUSH);\n } else if (encoding === \"br\") {\n zlibStream.flush(zlib.constants.BROTLI_OPERATION_FLUSH);\n } else if (encoding === \"zstd\") {\n zlibStream.flush();\n }\n });\n\n reader.on(\"end\", () => {\n compressor.end();\n });\n\n reader.on(\"error\", (err) => {\n controller.error(err);\n });\n },\n });\n }\n\n protected getParams(\n encoding: keyof typeof ServerCompressProvider.compressors,\n ): Record<number, any> {\n if (encoding === \"zstd\") {\n return {\n [zlib.constants.ZSTD_c_compressionLevel]: 3, // default compression level for zstd\n };\n }\n if (encoding === \"br\") {\n return {};\n }\n if (encoding === \"gzip\") {\n return {};\n }\n return {};\n }\n\n protected setHeaders(\n response: ServerResponse,\n encoding: keyof typeof ServerCompressProvider.compressors,\n ): void {\n response.headers.vary = \"content-encoding\";\n response.headers[\"content-encoding\"] = encoding;\n response.headers[\"cache-control\"] = \"no-cache\";\n }\n}\n\nexport interface ServerCompressProviderOptions {\n allowedContentTypes: string[];\n}\n","import { $module } from \"alepha\";\nimport { AlephaServer } from \"alepha/server\";\nimport { ServerCompressProvider } from \"./providers/ServerCompressProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/ServerCompressProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * | type | quality | stability |\n * |------|---------|-----------|\n * | backend | standard | stable |\n *\n * Response compression.\n *\n * **Features:**\n * - Gzip compression\n * - Brotli compression\n *\n * @module alepha.server.compress\n */\nexport const AlephaServerCompress = $module({\n name: \"alepha.server.compress\",\n services: [AlephaServer, ServerCompressProvider],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/server/compress/providers/ServerCompressProvider.ts","../../../src/server/compress/index.ts"],"sourcesContent":["import { Readable, type Transform } from \"node:stream\";\nimport { ReadableStream } from \"node:stream/web\";\nimport { promisify } from \"node:util\";\nimport * as zlib from \"node:zlib\";\nimport { $hook, $inject, Alepha } from \"alepha\";\nimport type { ServerResponse } from \"alepha/server\";\n\nconst gzip = promisify(zlib.gzip);\nconst createGzip = zlib.createGzip;\nconst brotli = promisify(zlib.brotliCompress);\nconst createBrotliCompress = zlib.createBrotliCompress;\nconst zstd = zlib.zstdCompress ? promisify(zlib.zstdCompress) : undefined;\nconst createZstdCompress = zstd ? zlib.createZstdCompress : undefined;\n\ndeclare module \"alepha\" {\n interface State {\n \"alepha.server.compress.options\"?: ServerCompressProviderOptions;\n }\n}\n\nexport class ServerCompressProvider {\n static compressors: Record<\n string,\n | {\n compress: (...args: any[]) => Promise<Buffer>;\n stream: (options?: any) => Transform;\n }\n | undefined\n > = {\n gzip: {\n compress: gzip,\n stream: createGzip,\n },\n br: {\n compress: brotli,\n stream: createBrotliCompress,\n },\n zstd:\n zstd && createZstdCompress\n ? {\n compress: zstd,\n stream: createZstdCompress,\n }\n : undefined,\n };\n\n protected readonly alepha = $inject(Alepha);\n\n protected get options(): ServerCompressProviderOptions {\n return {\n allowedContentTypes: [\n \"application/json\",\n \"text/html\",\n \"application/javascript\",\n \"text/plain\",\n \"text/css\",\n ],\n ...this.alepha.store.get(\"alepha.server.compress.options\"),\n };\n }\n\n public readonly onResponse = $hook({\n on: \"server:onResponse\",\n handler: async ({ request, response }) => {\n // In serverless (Cloudflare Workers), skip compression entirely:\n // Cloudflare's edge network automatically compresses responses\n if (this.alepha.isServerless()) {\n return;\n }\n\n // skip if already compressed\n if (response.headers[\"content-encoding\"]) {\n return;\n }\n\n const acceptEncoding = request.headers[\"accept-encoding\"]; // skip if no accept-encoding header\n if (!acceptEncoding) {\n return;\n }\n\n // skip if not json or html (for now)\n if (!this.isAllowedContentType(response.headers[\"content-type\"])) {\n return;\n }\n\n for (const encoding of [\"zstd\", \"br\", \"gzip\"] as const) {\n if (\n acceptEncoding.includes(encoding) &&\n ServerCompressProvider.compressors[encoding]\n ) {\n await this.compress(encoding, response);\n return;\n }\n }\n },\n });\n\n protected isAllowedContentType(contentType: string | undefined): boolean {\n if (!contentType) {\n return false;\n }\n\n const lowerContentType = contentType.toLowerCase();\n\n return !!this.options.allowedContentTypes.find((it) =>\n lowerContentType.includes(it),\n );\n }\n\n protected async compress(\n encoding: keyof typeof ServerCompressProvider.compressors,\n response: ServerResponse,\n ): Promise<void> {\n const body = response.body; // can be string or Buffer or ArrayBuffer or Readable\n\n const compressor = ServerCompressProvider.compressors[encoding];\n if (!compressor) {\n return;\n }\n\n const params = this.getParams(encoding);\n\n if (\n typeof body === \"string\" ||\n Buffer.isBuffer(body) ||\n body instanceof ArrayBuffer\n ) {\n const compressed = await compressor.compress(body, {\n params,\n });\n this.setHeaders(response, encoding);\n response.headers[\"content-length\"] = compressed.length.toString();\n response.body = compressed;\n return;\n }\n\n if (typeof body === \"object\" && body instanceof Readable) {\n this.setHeaders(response, encoding);\n response.body = body.pipe(compressor.stream({ params }));\n return;\n }\n\n if (typeof body === \"object\" && body instanceof ReadableStream) {\n this.setHeaders(response, encoding);\n // For streaming responses, use flush mode to avoid buffering\n response.body = this.createFlushingCompressStream(\n body,\n compressor.stream,\n encoding,\n params,\n );\n }\n }\n\n /**\n * Create a compressed stream that flushes after each chunk.\n * This is essential for streaming SSR - ensures each chunk is sent immediately.\n */\n protected createFlushingCompressStream(\n input: ReadableStream,\n createCompressor: (options?: any) => Transform,\n encoding: string,\n params: Record<number, any>,\n ): ReadableStream<Uint8Array> {\n const compressor = createCompressor({\n params,\n flush: zlib.constants.Z_SYNC_FLUSH,\n });\n const reader = Readable.fromWeb(input);\n\n return new ReadableStream<Uint8Array>({\n start(controller) {\n compressor.on(\"data\", (chunk: Buffer) => {\n controller.enqueue(new Uint8Array(chunk));\n });\n\n compressor.on(\"end\", () => {\n controller.close();\n });\n\n compressor.on(\"error\", (err) => {\n controller.error(err);\n });\n\n reader.on(\"data\", (chunk: Buffer) => {\n compressor.write(chunk);\n // Force flush after each chunk for streaming\n // Cast to any because flush() exists on zlib streams but not in Transform type\n const zlibStream = compressor as any;\n if (encoding === \"gzip\") {\n zlibStream.flush(zlib.constants.Z_SYNC_FLUSH);\n } else if (encoding === \"br\") {\n zlibStream.flush(zlib.constants.BROTLI_OPERATION_FLUSH);\n } else if (encoding === \"zstd\") {\n zlibStream.flush();\n }\n });\n\n reader.on(\"end\", () => {\n compressor.end();\n });\n\n reader.on(\"error\", (err) => {\n controller.error(err);\n });\n },\n });\n }\n\n protected getParams(\n encoding: keyof typeof ServerCompressProvider.compressors,\n ): Record<number, any> {\n if (encoding === \"zstd\") {\n return {\n [zlib.constants.ZSTD_c_compressionLevel]: 3, // default compression level for zstd\n };\n }\n if (encoding === \"br\") {\n return {};\n }\n if (encoding === \"gzip\") {\n return {};\n }\n return {};\n }\n\n protected setHeaders(\n response: ServerResponse,\n encoding: keyof typeof ServerCompressProvider.compressors,\n ): void {\n response.headers.vary = \"content-encoding\";\n response.headers[\"content-encoding\"] = encoding;\n response.headers[\"cache-control\"] = \"no-cache\";\n }\n}\n\nexport interface ServerCompressProviderOptions {\n allowedContentTypes: string[];\n}\n","import { $module } from \"alepha\";\nimport { AlephaServer } from \"alepha/server\";\nimport { ServerCompressProvider } from \"./providers/ServerCompressProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/ServerCompressProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * | Stability | Since | Runtime |\n * |-----------|-------|---------|\n * | 3 - stable | 0.13.0 | node, bun|\n *\n * Response compression.\n *\n * **Features:**\n * - Gzip compression\n * - Brotli compression\n *\n * @module alepha.server.compress\n */\nexport const AlephaServerCompress = $module({\n name: \"alepha.server.compress\",\n services: [AlephaServer, ServerCompressProvider],\n});\n"],"mappings":"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"}
@@ -151,9 +151,9 @@ declare module "alepha/server" {
151
151
  }
152
152
  }
153
153
  /**
154
- * | type | quality | stability |
155
- * |------|---------|-----------|
156
- * | backend | standard | stable |
154
+ * | Stability | Since | Runtime |
155
+ * |-----------|-------|---------|
156
+ * | 3 - stable | 0.3.0 | node, bun, workerd|
157
157
  *
158
158
  * Server and browser-safe cookie handling.
159
159
  *
@@ -211,9 +211,9 @@ $cookie[KIND] = CookiePrimitive;
211
211
  //#endregion
212
212
  //#region ../../src/server/cookies/index.ts
213
213
  /**
214
- * | type | quality | stability |
215
- * |------|---------|-----------|
216
- * | backend | standard | stable |
214
+ * | Stability | Since | Runtime |
215
+ * |-----------|-------|---------|
216
+ * | 3 - stable | 0.3.0 | node, bun, workerd|
217
217
  *
218
218
  * Server and browser-safe cookie handling.
219
219
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/server/cookies/services/CookieParser.ts","../../../src/server/cookies/providers/ServerCookiesProvider.ts","../../../src/server/cookies/primitives/$cookie.ts","../../../src/server/cookies/index.ts"],"sourcesContent":["import type { Cookie } from \"../primitives/$cookie.ts\";\n\nexport class CookieParser {\n public parseRequestCookies(header: string): Record<string, string> {\n const cookies: Record<string, string> = {};\n const parts = header.split(\";\");\n for (const part of parts) {\n const [key, value] = part.split(\"=\");\n if (!key || !value) {\n continue;\n }\n\n cookies[key.trim()] = value.trim();\n }\n\n return cookies;\n }\n\n public serializeResponseCookies(\n cookies: Record<string, Cookie | null>,\n isHttps: boolean,\n ): string[] {\n const headers = [];\n\n for (const [name, cookie] of Object.entries(cookies)) {\n // If the cookie is null, we need to delete it\n if (cookie == null) {\n headers.push(`${name}=; Path=/; Max-Age=0`);\n continue;\n }\n\n if (!cookie.value) {\n continue;\n }\n\n headers.push(this.cookieToString(name, cookie, isHttps));\n }\n\n return headers;\n }\n\n public cookieToString(\n name: string,\n cookie: Cookie,\n isHttps?: boolean,\n ): string {\n const parts: string[] = [];\n\n parts.push(`${name}=${cookie.value}`);\n\n if (cookie.path) {\n parts.push(`Path=${cookie.path}`);\n }\n if (cookie.maxAge) {\n parts.push(`Max-Age=${cookie.maxAge}`);\n }\n if (cookie.secure !== false && isHttps) {\n parts.push(\"Secure\");\n }\n if (cookie.httpOnly) {\n parts.push(\"HttpOnly\");\n }\n if (cookie.sameSite) {\n parts.push(`SameSite=${cookie.sameSite}`);\n }\n if (cookie.domain) {\n parts.push(`Domain=${cookie.domain}`);\n }\n\n return parts.join(\"; \");\n }\n}\n","import {\n createCipheriv,\n createDecipheriv,\n createHmac,\n randomBytes,\n timingSafeEqual,\n} from \"node:crypto\";\nimport { deflateRawSync, inflateRawSync } from \"node:zlib\";\nimport {\n $env,\n $hook,\n $inject,\n Alepha,\n AlephaError,\n type Static,\n type TSchema,\n t,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { DEFAULT_APP_SECRET } from \"alepha/security\";\nimport type { ServerRequest } from \"alepha/server\";\nimport type {\n Cookie,\n CookiePrimitiveOptions,\n Cookies,\n} from \"../primitives/$cookie.ts\";\nimport { CookieParser } from \"../services/CookieParser.ts\";\n\nconst envSchema = t.object({\n APP_SECRET: t.text({\n default: DEFAULT_APP_SECRET,\n }),\n});\n\nexport class ServerCookiesProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly cookieParser = $inject(CookieParser);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly env = $env(envSchema);\n\n // crypto constants\n protected readonly ALGORITHM = \"aes-256-gcm\";\n protected readonly IV_LENGTH = 16; // For GCM\n protected readonly AUTH_TAG_LENGTH = 16;\n protected readonly SIGNATURE_LENGTH = 32; // For SHA256\n\n public readonly onRequest = $hook({\n on: \"server:onRequest\",\n handler: ({ request }) => {\n request.cookies = {\n req: this.cookieParser.parseRequestCookies(\n request.headers.cookie ?? \"\",\n ),\n res: {},\n };\n },\n });\n\n public readonly onAction = $hook({\n on: \"action:onRequest\",\n handler: ({ request }) => {\n request.cookies = {\n req: this.cookieParser.parseRequestCookies(\n request.headers.cookie ?? \"\",\n ),\n res: {},\n };\n },\n });\n\n public readonly onSend = $hook({\n on: \"server:onSend\",\n handler: ({ request }) => {\n if (request.cookies && Object.keys(request.cookies.res).length > 0) {\n const setCookieHeaders = this.cookieParser.serializeResponseCookies(\n request.cookies.res,\n request.url.protocol === \"https:\",\n );\n if (setCookieHeaders.length > 0) {\n request.reply.headers[\"set-cookie\"] = setCookieHeaders;\n }\n }\n },\n });\n\n protected getCookiesFromContext(cookies?: Cookies): Cookies {\n const contextCookies =\n this.alepha.context.get<ServerRequest>(\"request\")?.cookies;\n if (cookies) return cookies;\n if (contextCookies) return contextCookies;\n throw new AlephaError(\n \"Cookie context is not available. This method must be called within a server request cycle.\",\n );\n }\n\n public getCookie<T extends TSchema>(\n name: string,\n options: CookiePrimitiveOptions<T>,\n contextCookies?: Cookies,\n ): Static<T> | undefined {\n const cookies = this.getCookiesFromContext(contextCookies);\n let rawValue = cookies.req[name];\n\n if (!rawValue) return undefined;\n\n try {\n rawValue = decodeURIComponent(rawValue);\n\n if (options.sign) {\n const signature = rawValue.substring(0, this.SIGNATURE_LENGTH * 2);\n const value = rawValue.substring(this.SIGNATURE_LENGTH * 2);\n const expectedSignature = this.sign(value);\n\n if (\n !timingSafeEqual(\n Buffer.from(signature, \"hex\"),\n Buffer.from(expectedSignature, \"hex\"),\n )\n ) {\n this.log.warn(`Invalid signature for cookie \"${name}\".`);\n return undefined;\n }\n rawValue = value;\n }\n\n if (options.encrypt) {\n rawValue = this.decrypt(rawValue);\n }\n\n if (options.compress) {\n rawValue = inflateRawSync(Buffer.from(rawValue, \"base64\")).toString(\n \"utf8\",\n );\n }\n\n return this.alepha.codec.decode(options.schema, JSON.parse(rawValue));\n } catch (error) {\n this.log.warn(`Failed to parse cookie \"${name}\"`, error);\n // corrupted or invalid cookie, instruct browser to delete it on next response\n this.deleteCookie(name, cookies);\n return undefined;\n }\n }\n\n public setCookie<T extends TSchema>(\n name: string,\n options: CookiePrimitiveOptions<T>,\n data: Static<T>,\n contextCookies?: Cookies,\n ): void {\n const cookies = this.getCookiesFromContext(contextCookies);\n let value = JSON.stringify(this.alepha.codec.decode(options.schema, data));\n\n if (options.compress) {\n value = deflateRawSync(value).toString(\"base64\");\n }\n\n if (options.encrypt) {\n value = this.encrypt(value);\n }\n\n if (options.sign) {\n value = this.sign(value) + value;\n }\n\n const cookie: Cookie = {\n value: encodeURIComponent(value),\n path: options.path ?? \"/\",\n sameSite: options.sameSite ?? \"lax\",\n secure: options.secure ?? this.alepha.isProduction(),\n httpOnly: options.httpOnly,\n domain: options.domain,\n };\n\n if (options.ttl) {\n cookie.maxAge = this.dateTimeProvider.duration(options.ttl).as(\"seconds\");\n }\n\n cookies.res[name] = cookie;\n }\n\n public deleteCookie<T extends TSchema>(\n name: string,\n contextCookies?: Cookies,\n ): void {\n const cookies = this.getCookiesFromContext(contextCookies);\n cookies.res[name] = null;\n }\n\n // --- Crypto & Parsing ---\n\n protected encrypt(text: string): string {\n const iv = randomBytes(this.IV_LENGTH);\n const cipher = createCipheriv(\n this.ALGORITHM,\n Buffer.from(this.secretKey()),\n iv,\n );\n const encrypted = Buffer.concat([\n cipher.update(text, \"utf8\"),\n cipher.final(),\n ]);\n const authTag = cipher.getAuthTag();\n return Buffer.concat([iv, authTag, encrypted]).toString(\"base64\");\n }\n\n protected decrypt(encryptedText: string): string {\n const data = Buffer.from(encryptedText, \"base64\");\n const iv = data.subarray(0, this.IV_LENGTH);\n const authTag = data.subarray(\n this.IV_LENGTH,\n this.IV_LENGTH + this.AUTH_TAG_LENGTH,\n );\n\n const encrypted = data.subarray(this.IV_LENGTH + this.AUTH_TAG_LENGTH);\n const decipher = createDecipheriv(\n this.ALGORITHM,\n Buffer.from(this.secretKey()),\n iv,\n );\n\n decipher.setAuthTag(authTag);\n\n const decrypted = Buffer.concat([\n decipher.update(encrypted),\n decipher.final(),\n ]);\n\n return decrypted.toString(\"utf8\");\n }\n\n public secretKey(): string {\n let secret = this.env.APP_SECRET;\n if (secret.length < 32) {\n // pad secret to 32 bytes\n secret = secret.padEnd(32, \"0\");\n } else if (secret.length > 32) {\n // truncate secret to 32 bytes\n secret = secret.substring(0, 32);\n }\n return secret;\n }\n\n protected sign(data: string): string {\n return createHmac(\"sha256\", this.secretKey()).update(data).digest(\"hex\");\n }\n}\n","import {\n $inject,\n createPrimitive,\n KIND,\n Primitive,\n type Static,\n type TSchema,\n} from \"alepha\";\nimport type { DurationLike } from \"alepha/datetime\";\nimport { ServerCookiesProvider } from \"../providers/ServerCookiesProvider.ts\";\n\n/**\n * Declares a type-safe, configurable HTTP cookie.\n * This primitive provides methods to get, set, and delete the cookie\n * within the server request/response cycle.\n */\nexport const $cookie = <T extends TSchema>(\n options: CookiePrimitiveOptions<T>,\n): AbstractCookiePrimitive<T> => {\n return createPrimitive(CookiePrimitive<T>, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface CookiePrimitiveOptions<T extends TSchema> {\n /**\n * The schema for the cookie's value, used for validation and type safety.\n */\n schema: T;\n\n /**\n * The name of the cookie.\n */\n name?: string;\n\n /**\n * The cookie's path. Defaults to \"/\".\n */\n path?: string;\n\n /**\n * Time-to-live for the cookie. Maps to `Max-Age`.\n */\n ttl?: DurationLike;\n\n /**\n * If true, the cookie is only sent over HTTPS. Defaults to true in production.\n */\n secure?: boolean;\n\n /**\n * If true, the cookie cannot be accessed by client-side scripts.\n */\n httpOnly?: boolean;\n\n /**\n * SameSite policy for the cookie. Defaults to \"lax\".\n */\n sameSite?: \"strict\" | \"lax\" | \"none\";\n\n /**\n * The domain for the cookie.\n */\n domain?: string;\n\n /**\n * If true, the cookie value will be compressed using zlib.\n */\n compress?: boolean;\n\n /**\n * If true, the cookie value will be encrypted. Requires `COOKIE_SECRET` env var.\n */\n encrypt?: boolean;\n\n /**\n * If true, the cookie will be signed to prevent tampering. Requires `COOKIE_SECRET` env var.\n */\n sign?: boolean;\n}\n\nexport interface AbstractCookiePrimitive<T extends TSchema> {\n readonly name: string;\n readonly options: CookiePrimitiveOptions<T>;\n set(\n value: Static<T>,\n options?: { cookies?: Cookies; ttl?: DurationLike },\n ): void;\n get(options?: { cookies?: Cookies }): Static<T> | undefined;\n del(options?: { cookies?: Cookies }): void;\n}\n\nexport class CookiePrimitive<T extends TSchema>\n extends Primitive<CookiePrimitiveOptions<T>>\n implements AbstractCookiePrimitive<T>\n{\n protected readonly serverCookiesProvider = $inject(ServerCookiesProvider);\n\n public get schema(): T {\n return this.options.schema;\n }\n\n public get name(): string {\n return this.options.name ?? `${this.config.propertyKey}`;\n }\n\n /**\n * Sets the cookie with the given value in the current request's response.\n */\n public set(\n value: Static<T>,\n options?: { cookies?: Cookies; ttl?: DurationLike },\n ): void {\n this.serverCookiesProvider.setCookie(\n this.name,\n {\n ...this.options,\n ttl: options?.ttl ?? this.options.ttl,\n },\n value,\n options?.cookies,\n );\n }\n\n /**\n * Gets the cookie value from the current request. Returns undefined if not found or invalid.\n */\n public get(options?: { cookies?: Cookies }): Static<T> | undefined {\n return this.serverCookiesProvider.getCookie(\n this.name,\n this.options,\n options?.cookies,\n );\n }\n\n /**\n * Deletes the cookie in the current request's response.\n */\n public del(options?: { cookies?: Cookies }): void {\n this.serverCookiesProvider.deleteCookie(this.name, options?.cookies);\n }\n}\n\n$cookie[KIND] = CookiePrimitive;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface Cookies {\n req: Record<string, string>;\n res: Record<string, Cookie | null>;\n}\n\nexport interface Cookie {\n value: string;\n path?: string;\n maxAge?: number;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n domain?: string;\n}\n","import { $module } from \"alepha\";\nimport { AlephaServer } from \"alepha/server\";\nimport { $cookie, type Cookies } from \"./primitives/$cookie.ts\";\nimport { ServerCookiesProvider } from \"./providers/ServerCookiesProvider.ts\";\nimport { CookieParser } from \"./services/CookieParser.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./primitives/$cookie.ts\";\nexport * from \"./providers/ServerCookiesProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha/server\" {\n interface ServerRequest {\n cookies: Cookies;\n }\n}\n\n/**\n * | type | quality | stability |\n * |------|---------|-----------|\n * | backend | standard | stable |\n *\n * Server and browser-safe cookie handling.\n *\n * **Features:**\n * - Cookie management on server and browser\n *\n * @module alepha.server.cookies\n */\nexport const AlephaServerCookies = $module({\n name: \"alepha.server.cookies\",\n primitives: [$cookie],\n services: [AlephaServer, ServerCookiesProvider, CookieParser],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/server/cookies/services/CookieParser.ts","../../../src/server/cookies/providers/ServerCookiesProvider.ts","../../../src/server/cookies/primitives/$cookie.ts","../../../src/server/cookies/index.ts"],"sourcesContent":["import type { Cookie } from \"../primitives/$cookie.ts\";\n\nexport class CookieParser {\n public parseRequestCookies(header: string): Record<string, string> {\n const cookies: Record<string, string> = {};\n const parts = header.split(\";\");\n for (const part of parts) {\n const [key, value] = part.split(\"=\");\n if (!key || !value) {\n continue;\n }\n\n cookies[key.trim()] = value.trim();\n }\n\n return cookies;\n }\n\n public serializeResponseCookies(\n cookies: Record<string, Cookie | null>,\n isHttps: boolean,\n ): string[] {\n const headers = [];\n\n for (const [name, cookie] of Object.entries(cookies)) {\n // If the cookie is null, we need to delete it\n if (cookie == null) {\n headers.push(`${name}=; Path=/; Max-Age=0`);\n continue;\n }\n\n if (!cookie.value) {\n continue;\n }\n\n headers.push(this.cookieToString(name, cookie, isHttps));\n }\n\n return headers;\n }\n\n public cookieToString(\n name: string,\n cookie: Cookie,\n isHttps?: boolean,\n ): string {\n const parts: string[] = [];\n\n parts.push(`${name}=${cookie.value}`);\n\n if (cookie.path) {\n parts.push(`Path=${cookie.path}`);\n }\n if (cookie.maxAge) {\n parts.push(`Max-Age=${cookie.maxAge}`);\n }\n if (cookie.secure !== false && isHttps) {\n parts.push(\"Secure\");\n }\n if (cookie.httpOnly) {\n parts.push(\"HttpOnly\");\n }\n if (cookie.sameSite) {\n parts.push(`SameSite=${cookie.sameSite}`);\n }\n if (cookie.domain) {\n parts.push(`Domain=${cookie.domain}`);\n }\n\n return parts.join(\"; \");\n }\n}\n","import {\n createCipheriv,\n createDecipheriv,\n createHmac,\n randomBytes,\n timingSafeEqual,\n} from \"node:crypto\";\nimport { deflateRawSync, inflateRawSync } from \"node:zlib\";\nimport {\n $env,\n $hook,\n $inject,\n Alepha,\n AlephaError,\n type Static,\n type TSchema,\n t,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { DEFAULT_APP_SECRET } from \"alepha/security\";\nimport type { ServerRequest } from \"alepha/server\";\nimport type {\n Cookie,\n CookiePrimitiveOptions,\n Cookies,\n} from \"../primitives/$cookie.ts\";\nimport { CookieParser } from \"../services/CookieParser.ts\";\n\nconst envSchema = t.object({\n APP_SECRET: t.text({\n default: DEFAULT_APP_SECRET,\n }),\n});\n\nexport class ServerCookiesProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly cookieParser = $inject(CookieParser);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly env = $env(envSchema);\n\n // crypto constants\n protected readonly ALGORITHM = \"aes-256-gcm\";\n protected readonly IV_LENGTH = 16; // For GCM\n protected readonly AUTH_TAG_LENGTH = 16;\n protected readonly SIGNATURE_LENGTH = 32; // For SHA256\n\n public readonly onRequest = $hook({\n on: \"server:onRequest\",\n handler: ({ request }) => {\n request.cookies = {\n req: this.cookieParser.parseRequestCookies(\n request.headers.cookie ?? \"\",\n ),\n res: {},\n };\n },\n });\n\n public readonly onAction = $hook({\n on: \"action:onRequest\",\n handler: ({ request }) => {\n request.cookies = {\n req: this.cookieParser.parseRequestCookies(\n request.headers.cookie ?? \"\",\n ),\n res: {},\n };\n },\n });\n\n public readonly onSend = $hook({\n on: \"server:onSend\",\n handler: ({ request }) => {\n if (request.cookies && Object.keys(request.cookies.res).length > 0) {\n const setCookieHeaders = this.cookieParser.serializeResponseCookies(\n request.cookies.res,\n request.url.protocol === \"https:\",\n );\n if (setCookieHeaders.length > 0) {\n request.reply.headers[\"set-cookie\"] = setCookieHeaders;\n }\n }\n },\n });\n\n protected getCookiesFromContext(cookies?: Cookies): Cookies {\n const contextCookies =\n this.alepha.context.get<ServerRequest>(\"request\")?.cookies;\n if (cookies) return cookies;\n if (contextCookies) return contextCookies;\n throw new AlephaError(\n \"Cookie context is not available. This method must be called within a server request cycle.\",\n );\n }\n\n public getCookie<T extends TSchema>(\n name: string,\n options: CookiePrimitiveOptions<T>,\n contextCookies?: Cookies,\n ): Static<T> | undefined {\n const cookies = this.getCookiesFromContext(contextCookies);\n let rawValue = cookies.req[name];\n\n if (!rawValue) return undefined;\n\n try {\n rawValue = decodeURIComponent(rawValue);\n\n if (options.sign) {\n const signature = rawValue.substring(0, this.SIGNATURE_LENGTH * 2);\n const value = rawValue.substring(this.SIGNATURE_LENGTH * 2);\n const expectedSignature = this.sign(value);\n\n if (\n !timingSafeEqual(\n Buffer.from(signature, \"hex\"),\n Buffer.from(expectedSignature, \"hex\"),\n )\n ) {\n this.log.warn(`Invalid signature for cookie \"${name}\".`);\n return undefined;\n }\n rawValue = value;\n }\n\n if (options.encrypt) {\n rawValue = this.decrypt(rawValue);\n }\n\n if (options.compress) {\n rawValue = inflateRawSync(Buffer.from(rawValue, \"base64\")).toString(\n \"utf8\",\n );\n }\n\n return this.alepha.codec.decode(options.schema, JSON.parse(rawValue));\n } catch (error) {\n this.log.warn(`Failed to parse cookie \"${name}\"`, error);\n // corrupted or invalid cookie, instruct browser to delete it on next response\n this.deleteCookie(name, cookies);\n return undefined;\n }\n }\n\n public setCookie<T extends TSchema>(\n name: string,\n options: CookiePrimitiveOptions<T>,\n data: Static<T>,\n contextCookies?: Cookies,\n ): void {\n const cookies = this.getCookiesFromContext(contextCookies);\n let value = JSON.stringify(this.alepha.codec.decode(options.schema, data));\n\n if (options.compress) {\n value = deflateRawSync(value).toString(\"base64\");\n }\n\n if (options.encrypt) {\n value = this.encrypt(value);\n }\n\n if (options.sign) {\n value = this.sign(value) + value;\n }\n\n const cookie: Cookie = {\n value: encodeURIComponent(value),\n path: options.path ?? \"/\",\n sameSite: options.sameSite ?? \"lax\",\n secure: options.secure ?? this.alepha.isProduction(),\n httpOnly: options.httpOnly,\n domain: options.domain,\n };\n\n if (options.ttl) {\n cookie.maxAge = this.dateTimeProvider.duration(options.ttl).as(\"seconds\");\n }\n\n cookies.res[name] = cookie;\n }\n\n public deleteCookie<T extends TSchema>(\n name: string,\n contextCookies?: Cookies,\n ): void {\n const cookies = this.getCookiesFromContext(contextCookies);\n cookies.res[name] = null;\n }\n\n // --- Crypto & Parsing ---\n\n protected encrypt(text: string): string {\n const iv = randomBytes(this.IV_LENGTH);\n const cipher = createCipheriv(\n this.ALGORITHM,\n Buffer.from(this.secretKey()),\n iv,\n );\n const encrypted = Buffer.concat([\n cipher.update(text, \"utf8\"),\n cipher.final(),\n ]);\n const authTag = cipher.getAuthTag();\n return Buffer.concat([iv, authTag, encrypted]).toString(\"base64\");\n }\n\n protected decrypt(encryptedText: string): string {\n const data = Buffer.from(encryptedText, \"base64\");\n const iv = data.subarray(0, this.IV_LENGTH);\n const authTag = data.subarray(\n this.IV_LENGTH,\n this.IV_LENGTH + this.AUTH_TAG_LENGTH,\n );\n\n const encrypted = data.subarray(this.IV_LENGTH + this.AUTH_TAG_LENGTH);\n const decipher = createDecipheriv(\n this.ALGORITHM,\n Buffer.from(this.secretKey()),\n iv,\n );\n\n decipher.setAuthTag(authTag);\n\n const decrypted = Buffer.concat([\n decipher.update(encrypted),\n decipher.final(),\n ]);\n\n return decrypted.toString(\"utf8\");\n }\n\n public secretKey(): string {\n let secret = this.env.APP_SECRET;\n if (secret.length < 32) {\n // pad secret to 32 bytes\n secret = secret.padEnd(32, \"0\");\n } else if (secret.length > 32) {\n // truncate secret to 32 bytes\n secret = secret.substring(0, 32);\n }\n return secret;\n }\n\n protected sign(data: string): string {\n return createHmac(\"sha256\", this.secretKey()).update(data).digest(\"hex\");\n }\n}\n","import {\n $inject,\n createPrimitive,\n KIND,\n Primitive,\n type Static,\n type TSchema,\n} from \"alepha\";\nimport type { DurationLike } from \"alepha/datetime\";\nimport { ServerCookiesProvider } from \"../providers/ServerCookiesProvider.ts\";\n\n/**\n * Declares a type-safe, configurable HTTP cookie.\n * This primitive provides methods to get, set, and delete the cookie\n * within the server request/response cycle.\n */\nexport const $cookie = <T extends TSchema>(\n options: CookiePrimitiveOptions<T>,\n): AbstractCookiePrimitive<T> => {\n return createPrimitive(CookiePrimitive<T>, options);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface CookiePrimitiveOptions<T extends TSchema> {\n /**\n * The schema for the cookie's value, used for validation and type safety.\n */\n schema: T;\n\n /**\n * The name of the cookie.\n */\n name?: string;\n\n /**\n * The cookie's path. Defaults to \"/\".\n */\n path?: string;\n\n /**\n * Time-to-live for the cookie. Maps to `Max-Age`.\n */\n ttl?: DurationLike;\n\n /**\n * If true, the cookie is only sent over HTTPS. Defaults to true in production.\n */\n secure?: boolean;\n\n /**\n * If true, the cookie cannot be accessed by client-side scripts.\n */\n httpOnly?: boolean;\n\n /**\n * SameSite policy for the cookie. Defaults to \"lax\".\n */\n sameSite?: \"strict\" | \"lax\" | \"none\";\n\n /**\n * The domain for the cookie.\n */\n domain?: string;\n\n /**\n * If true, the cookie value will be compressed using zlib.\n */\n compress?: boolean;\n\n /**\n * If true, the cookie value will be encrypted. Requires `COOKIE_SECRET` env var.\n */\n encrypt?: boolean;\n\n /**\n * If true, the cookie will be signed to prevent tampering. Requires `COOKIE_SECRET` env var.\n */\n sign?: boolean;\n}\n\nexport interface AbstractCookiePrimitive<T extends TSchema> {\n readonly name: string;\n readonly options: CookiePrimitiveOptions<T>;\n set(\n value: Static<T>,\n options?: { cookies?: Cookies; ttl?: DurationLike },\n ): void;\n get(options?: { cookies?: Cookies }): Static<T> | undefined;\n del(options?: { cookies?: Cookies }): void;\n}\n\nexport class CookiePrimitive<T extends TSchema>\n extends Primitive<CookiePrimitiveOptions<T>>\n implements AbstractCookiePrimitive<T>\n{\n protected readonly serverCookiesProvider = $inject(ServerCookiesProvider);\n\n public get schema(): T {\n return this.options.schema;\n }\n\n public get name(): string {\n return this.options.name ?? `${this.config.propertyKey}`;\n }\n\n /**\n * Sets the cookie with the given value in the current request's response.\n */\n public set(\n value: Static<T>,\n options?: { cookies?: Cookies; ttl?: DurationLike },\n ): void {\n this.serverCookiesProvider.setCookie(\n this.name,\n {\n ...this.options,\n ttl: options?.ttl ?? this.options.ttl,\n },\n value,\n options?.cookies,\n );\n }\n\n /**\n * Gets the cookie value from the current request. Returns undefined if not found or invalid.\n */\n public get(options?: { cookies?: Cookies }): Static<T> | undefined {\n return this.serverCookiesProvider.getCookie(\n this.name,\n this.options,\n options?.cookies,\n );\n }\n\n /**\n * Deletes the cookie in the current request's response.\n */\n public del(options?: { cookies?: Cookies }): void {\n this.serverCookiesProvider.deleteCookie(this.name, options?.cookies);\n }\n}\n\n$cookie[KIND] = CookiePrimitive;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface Cookies {\n req: Record<string, string>;\n res: Record<string, Cookie | null>;\n}\n\nexport interface Cookie {\n value: string;\n path?: string;\n maxAge?: number;\n secure?: boolean;\n httpOnly?: boolean;\n sameSite?: \"strict\" | \"lax\" | \"none\";\n domain?: string;\n}\n","import { $module } from \"alepha\";\nimport { AlephaServer } from \"alepha/server\";\nimport { $cookie, type Cookies } from \"./primitives/$cookie.ts\";\nimport { ServerCookiesProvider } from \"./providers/ServerCookiesProvider.ts\";\nimport { CookieParser } from \"./services/CookieParser.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./primitives/$cookie.ts\";\nexport * from \"./providers/ServerCookiesProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha/server\" {\n interface ServerRequest {\n cookies: Cookies;\n }\n}\n\n/**\n * | Stability | Since | Runtime |\n * |-----------|-------|---------|\n * | 3 - stable | 0.3.0 | node, bun, workerd|\n *\n * Server and browser-safe cookie handling.\n *\n * **Features:**\n * - Cookie management on server and browser\n *\n * @module alepha.server.cookies\n */\nexport const AlephaServerCookies = $module({\n name: \"alepha.server.cookies\",\n primitives: [$cookie],\n services: [AlephaServer, ServerCookiesProvider, CookieParser],\n});\n"],"mappings":"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"}
@@ -344,13 +344,6 @@ declare class ServerRouterProvider extends RouterProvider<ServerRouteMatcher> {
344
344
  protected compiledOnSend?: CompiledEventExecutor<Hooks["server:onSend"]>;
345
345
  protected compiledOnResponse?: CompiledEventExecutor<Hooks["server:onResponse"]>;
346
346
  protected compiledOnError?: CompiledEventExecutor<Hooks["server:onError"]>;
347
- protected readonly contextRunOptions: {
348
- context: string;
349
- _request: ServerRequest;
350
- _route: ServerRoute;
351
- _responseKind: ResponseKind;
352
- };
353
- protected readonly processRequestBound: () => Promise<any>;
354
347
  protected readonly queryKeysCache: WeakMap<object, string[]>;
355
348
  /**
356
349
  * Get cached keys for a query schema, computing them lazily on first access.
@@ -693,8 +686,8 @@ interface ActionPrimitiveOptions<TConfig extends RequestConfigSchema> extends Om
693
686
  */
694
687
  description?: string;
695
688
  /**
696
- * Disable the route. Useful with env variables do disable one specific route.
697
- * Route won't be available in the API but can still be called locally!
689
+ * Disable the route. Useful with env variables to disable one specific route.
690
+ * Route won't be available in the API nor locally.
698
691
  */
699
692
  disabled?: boolean;
700
693
  /**
@@ -904,10 +897,6 @@ declare class NodeHttpServerProvider extends ServerProvider {
904
897
  };
905
898
  get hostname(): string;
906
899
  protected readonly handleRequestError: (res: ServerResponse$1, err: Error) => void;
907
- protected readonly nodeRequestEvent: {
908
- req: IncomingMessage;
909
- res: ServerResponse$1;
910
- };
911
900
  readonly server: Server<typeof IncomingMessage, typeof ServerResponse$1>;
912
901
  readonly start: alepha19.HookPrimitive<"start">;
913
902
  protected createHttpServer(func: (req: IncomingMessage, res: ServerResponse$1) => void): Server;
@@ -995,9 +984,9 @@ declare module "alepha" {
995
984
  }
996
985
  }
997
986
  /**
998
- * | type | quality | stability |
999
- * |------|---------|-----------|
1000
- * | backend | epic | stable |
987
+ * | Stability | Since | Runtime |
988
+ * |-----------|-------|---------|
989
+ * | 3 - stable | 0.1.0 | node, bun, workerd|
1001
990
  *
1002
991
  * Convention-driven HTTP server with automatic validation and type inference.
1003
992
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/server/core/schemas/errorSchema.ts","../../../src/server/core/errors/HttpError.ts","../../../src/server/core/constants/routeMethods.ts","../../../src/server/core/helpers/ServerReply.ts","../../../src/server/core/services/UserAgentParser.ts","../../../src/server/core/interfaces/ServerRequest.ts","../../../src/server/core/services/ServerRequestParser.ts","../../../src/server/core/providers/ServerTimingProvider.ts","../../../src/server/core/providers/ServerRouterProvider.ts","../../../src/server/core/providers/ServerProvider.ts","../../../src/server/core/services/HttpClient.ts","../../../src/server/core/primitives/$action.ts","../../../src/server/core/errors/BadRequestError.ts","../../../src/server/core/errors/ConflictError.ts","../../../src/server/core/errors/ForbiddenError.ts","../../../src/server/core/errors/NotFoundError.ts","../../../src/server/core/errors/UnauthorizedError.ts","../../../src/server/core/errors/ValidationError.ts","../../../src/server/core/helpers/isMultipart.ts","../../../src/server/core/schemas/okSchema.ts","../../../src/server/core/primitives/$route.ts","../../../src/server/core/providers/BunHttpServerProvider.ts","../../../src/server/core/providers/NodeHttpServerProvider.ts","../../../src/server/core/providers/ServerLoggerProvider.ts","../../../src/server/core/providers/ServerNotReadyProvider.ts","../../../src/server/core/index.ts"],"mappings":";;;;;;;;;;;;cAEa,WAAA,WAAW,OAAA;SA+BvB,QAAA,CAAA,OAAA;;;;;;;;;;KAEW,WAAA,GAAc,MAAA,QAAc,WAAA;;;cChC3B,WAAA,GACX,KAAA,WACA,MAAA,cACC,KAAA,IAAS,aAAA;AAAA,cAoBC,SAAA,SAAkB,WAAA;EACtB,IAAA;EAAA,OAEA,EAAA,GAAE,KAAA,WAzBK,MAAA,cAEb,KAAA,IAAS,aAAA;EAAA,OAyBH,MAAA,CAAO,KAAA,EAAO,SAAA,GAAY,WAAA;EAAA,SAcjB,KAAA;EAAA,SACA,MAAA;EAAA,SAEA,SAAA;EAAA,SACA,OAAA;EAAA,SACA,MAAA;IACd,IAAA;IACA,OAAA;EAAA;cAGU,OAAA,EAAS,OAAA,CAAQ,WAAA,GAAc,KAAA;AAAA;AAAA,cA8BhC,iBAAA,EAAmB,MAAA;AAAA,UAkBf,aAAA,SAAsB,KAAA;EACrC,MAAA;AAAA;;;cCxGW,YAAA;AAAA,KAaD,WAAA,WAAsB,YAAA;;;;;;cCVrB,WAAA;EAEJ,OAAA,EAAS,MAAA;IACd,YAAA;EAAA;EAGK,MAAA;EAEA,IAAA;;;;EAKA,QAAA,CAAS,GAAA,UAAa,MAAA;EHiB9B;;;EGPQ,SAAA,CAAU,MAAA;;;;EAQV,SAAA,CAAU,IAAA,UAAc,KAAA;;;;EAQxB,OAAA,CAAQ,IAAA;AAAA;;;UC1CA,aAAA;EACf,EAAA;EAaA,OAAA;EAYA,MAAA;AAAA;;;;;;;cASW,eAAA;EACJ,KAAA,CAAM,SAAA,YAAyB,aAAA;AAAA;;;KCb5B,YAAA,GAAe,OAAA,GAAU,OAAA,GAAU,MAAA,GAAS,OAAA,GAAU,OAAA;AAAA,KACtD,aAAA,GACR,OAAA,GACA,OAAA,GACA,OAAA,GACA,KAAA,GACA,MAAA,GACA,OAAA,GACA,KAAA;AAAA,UAEa,mBAAA;EACf,IAAA,GAAO,YAAA;EACP,MAAA,GAAS,OAAA;EACT,KAAA,GAAQ,OAAA;EACR,OAAA,GAAU,OAAA;EACV,QAAA,GAAW,aAAA;AAAA;AAAA,UAGI,mBAAA,iBACC,mBAAA,GAAsB,mBAAA;EAEtC,IAAA,EAAM,OAAA,iBAAwB,YAAA,GAAe,MAAA,CAAO,OAAA;EAEpD,OAAA,EAAS,OAAA,oBAA2B,OAAA,GAChC,MAAA,CAAO,OAAA,eACP,MAAA;EAEJ,MAAA,EAAQ,OAAA,mBAA0B,OAAA,GAC9B,MAAA,CAAO,OAAA,cACP,MAAA;EAEJ,KAAA,EAAO,OAAA,kBAAyB,OAAA,GAC5B,MAAA,CAAO,OAAA,aACP,MAAA;AAAA;AAAA,KAGM,wBAAA,iBACM,mBAAA,GAAsB,mBAAA,IACpC,OAAA,CAAQ,mBAAA,CAAoB,OAAA;AAAA,UAIf,aAAA,iBACC,mBAAA,GAAsB,mBAAA,UAC9B,mBAAA,CAAoB,OAAA;;;;EAI5B,MAAA,EAAQ,WAAA;ELrEc;;;EK0EtB,GAAA,EAAK,GAAA;;;;EAKL,SAAA;;;;;EAMA,EAAA;;;;EAKA,IAAA;;;;;;ALzDF;EKiEE,SAAA,EAAW,aAAA;;;;;EAMX,GAAA,EAAK,UAAA;;AJvGP;;;EI6GE,KAAA;EJ5GA;;;;EIkHA,QAAA;EJ9FD;AAED;;;EIkGE,QAAA;EJ7FqB;;;;EImGrB,QAAA;EJxGwC;;;;EI8GxC,OAAA,GAAU,cAAA;EJ3GD;;;EIgHT,QAAA,EAAU,MAAA;EJ9GH;;;EImHP,KAAA,EAAO,WAAA;EJrGS;;;EI0GhB,GAAA,EAAK,gBAAA;AAAA;AAAA,UAKU,WAAA,iBACC,mBAAA,GAAsB,mBAAA,UAC9B,KAAA;EJ1GN;;;EI8GF,OAAA,EAAS,aAAA,CAAc,OAAA;EJ3GX;;;EIgHZ,MAAA,GAAS,WAAA;EJlFE;;;;;AAkBb;;;;;;;;ACvGA;EGuLE,MAAA,GAAS,OAAA;;;;EAKT,MAAA;AAAA;AAAA,KAKU,kBAAA,iBACM,mBAAA,GAAsB,mBAAA,IACpC,OAAA,qBAA4B,aAAA,GAC5B,MAAA,CAAO,OAAA,gBACP,gBAAA;AAAA,KAEQ,YAAA;AAAA,KAEA,gBAAA,YAED,MAAA,GAAS,UAAA;AAAA,KAER,aAAA,iBACM,mBAAA,GAAsB,mBAAA,KACnC,OAAA,EAAS,aAAA,CAAc,OAAA,MAAa,KAAA,CAAM,kBAAA,CAAmB,OAAA;AAAA,UAEjD,cAAA;EACf,IAAA,WAAe,MAAA,GAAS,WAAA,GAAc,QAAA,GAAa,cAAA;EACnD,OAAA,EAAS,MAAA;EACT,MAAA;AAAA;AAAA,KAGU,yBAAA,IACV,OAAA,EAAS,iBAAA,KACN,OAAA,CAAQ,cAAA;AAAA,UAEI,kBAAA,SAA2B,KAAA;EAC1C,OAAA,EAAS,yBAAA;AAAA;AAAA,UAGM,iBAAA;EACf,MAAA,EAAQ,WAAA;EACR,GAAA,EAAK,GAAA;EACL,OAAA,EAAS,MAAA;EACT,KAAA,EAAO,MAAA;EACP,MAAA,EAAQ,MAAA;EACR,GAAA,EAAK,gBAAA;AAAA;AAAA,UAGU,gBAAA;EACf,IAAA,GAAO,gBAAA;EACP,GAAA,GAAM,eAAA;AAAA;AAAA,UAGS,gBAAA;EACf,GAAA,EAAK,eAAA;EACL,GAAA,EAAK,gBAAA;AAAA;AAAA,UAGU,eAAA;EACf,GAAA,EAAK,OAAA;EACL,GAAA,GAAM,QAAA;AAAA;;;;UAQS,UAAA;EDlOT;;AASR;EC6NE,OAAA;;;;EAIA,IAAA;EDhOsC;;;ECoOtC,MAAA;;;AAjPF;EAqPE,QAAA;;;;EAIA,SAAA;AAAA;;;;UAMe,cAAA;EA/PoB;;;EAmQnC,GAAA;EAnQuE;;AACzE;EAsQE,QAAA;;;;EAIA,QAAA;AAAA;;;cCzQW,mBAAA;EAAA,mBACQ,MAAA,EAAM,MAAA;EAAA,mBACN,eAAA,EAAe,eAAA;EAAA,mBACf,GAAA;;;EAEZ,mBAAA,CAAoB,UAAA,EAAY,iBAAA,GAAoB,aAAA;EAyCpD,YAAA,CAAa,OAAA,EAAS,iBAAA;EAItB,mBAAA,CAAoB,OAAA,EAAS,iBAAA,GAAiB,aAAA;EAI9C,YAAA,CAAa,OAAA,EAAS,iBAAA;EAAA,UAwBnB,eAAA,CAAgB,OAAA,EAAS,iBAAA;EAa5B,aAAA,CAAc,OAAA,EAAS,iBAAA,GAAoB,UAAA;EAAA,0BA6BxB,YAAA,EAAY,MAAA;EAoG/B,QAAA,CAAS,OAAA,EAAS,iBAAA;EAAA,0BAWC,eAAA,EAAe,MAAA;EAqBlC,WAAA,CAAY,OAAA,EAAS,iBAAA;EAarB,WAAA,CAAY,OAAA,EAAS,iBAAA;EA8BrB,WAAA,CAAY,OAAA,EAAS,iBAAA;EAmBrB,UAAA,CAAW,OAAA,EAAS,iBAAA,GAAoB,cAAA;AAAA;;;KC/U5C,SAAA,GAAY,MAAA;AAAA,cAEJ,oBAAA;EAAA,mBACQ,GAAA,EADY,cAAA,CACT,MAAA;EAAA,mBACH,MAAA,EAAM,MAAA;EAElB,OAAA;;;;WAOS,SAAA,EATS,QAAA,CASA,aAAA;EAAA,SAaT,UAAA,EAbS,QAAA,CAaC,aAAA;EAAA,cAqCZ,WAAA,CAAA;EAIP,WAAA,CAAY,IAAA;EAeZ,SAAA,CAAU,IAAA;EAAA,UAwBP,WAAA,CAAY,IAAA,UAAc,MAAA,EAAQ,SAAA;AAAA;;;;;;;;AP5G9C;;;cQ4Ba,oBAAA,SAA6B,cAAA,CAAe,kBAAA;EAAA,mBACpC,GAAA,EADsD,cAAA,CACnD,MAAA;EAAA,mBACH,MAAA,EAAM,MAAA;EAAA,mBACN,MAAA,EAAQ,WAAA;EAAA,mBACR,oBAAA,EAAoB,oBAAA;EAAA,mBACpB,mBAAA,EAAmB,mBAAA;EAAA,UAG5B,iBAAA,GAAoB,qBAAA,CAC5B,KAAA;EAAA,UAEQ,cAAA,GAAiB,qBAAA,CAAsB,KAAA;EAAA,UACvC,kBAAA,GAAqB,qBAAA,CAC7B,KAAA;EAAA,UAEQ,eAAA,GAAkB,qBAAA,CAAsB,KAAA;EAAA,mBAI/B,iBAAA;;cAGY,aAAA;YACF,WAAA;mBACH,YAAA;EAAA;EAAA,mBAKP,mBAAA,QAA0B,OAAA;EAAA,mBAO1B,cAAA,EAAc,OAAA;;;;YAKvB,kBAAA,CAAmB,MAAA;IAAU,UAAA;EAAA;;;;;YAa7B,aAAA,CAAA;;;;;;;EAmBH,SAAA,CAAU,OAAA,YAAmB,WAAA;ERpE1B;;;EQqFH,WAAA,iBAA4B,mBAAA,GAAsB,mBAAA,CAAA,CACvD,KAAA,EAAO,WAAA,CAAY,OAAA;ERtF4B;;;EAAA,UQyHvC,YAAA,CAAa,OAAA,EAAS,MAAA;EPzJrB;;;;;;;;EAAA,UO4KK,cAAA,CACd,OAAA,EAAS,aAAA,EACT,KAAA,EAAO,WAAA,EACP,YAAA,EAAc,YAAA,GAAY,OAAA;;;;;;;EPnJK;;;EAAA,UO6LjB,eAAA,CACd,KAAA,EAAO,WAAA,EACP,OAAA,EAAS,aAAA,EACT,YAAA,EAAc,YAAA,GAAY,OAAA;EPrMY;;;EOgQjC,iBAAA,CACL,KAAA,EAAO,WAAA,EACP,KAAA,EAAO,WAAA,EACP,YAAA,EAAc,YAAA;EPhQT;;;EAAA,UOuUG,eAAA,CAAgB,MAAA,GAAS,mBAAA,GAAsB,YAAA;EP9V/C;;;EAAA,UOgYM,YAAA,CACd,KAAA,EAAO,WAAA,EACP,OAAA,EAAS,aAAA,EACT,KAAA,EAAO,KAAA,GAAK,OAAA;EP1WmB;;;EOoa1B,eAAA,CACL,KAAA;IAAS,MAAA,GAAS,mBAAA;EAAA,GAClB,OAAA,EAAS,mBAAA;AAAA;;;;;;;;;;cClaA,cAAA;EAAA,mBACQ,GAAA,EADM,cAAA,CACH,MAAA;EAAA,mBACH,MAAA,EAAM,MAAA;EAAA,mBACN,gBAAA,EAAgB,gBAAA;EAAA,mBAChB,MAAA,EAAM,oBAAA;EAAA,mBAEN,0BAAA;EAAA,mBAGA,qBAAA,EAAqB,QAAA;;;;;;;qBAOrB,mBAAA,QAAmB,QAAA;;;;;;;qBAMnB,YAAA,EAAY,GAAA;;;;;YAMrB,UAAA,CAAW,OAAA,EAAS,MAAA;;;;;YA0BpB,gBAAA,CAAiB,MAAA,WAAiB,MAAA;;;;YAwClC,UAAA,CAAW,GAAA;EAAA,IAaV,QAAA,CAAA;;;;qBAUQ,aAAA,EA/D+B,QAAA,CA+DlB,aAAA;ETrHX;;;EAAA,mBS6HF,YAAA,EARa,QAAA,CAQD,aAAA;;;;AR7JjC;;EQyKe,iBAAA,CACX,gBAAA,EAAkB,gBAAA,GACjB,OAAA;ERtJJ;;;EQuPc,gBAAA,CAAiB,EAAA,EAAI,eAAA,GAAkB,OAAA;ERzQ1C;;;EAAA,UQkXA,cAAA,CACR,GAAA,WACA,KAAA,GAAQ,KAAA,EACR,MAAA,GAAS,MAAA;AAAA;;;cCrWA,UAAA;EAAA,mBACQ,GAAA,EADE,cAAA,CACC,MAAA;EAAA,mBACH,MAAA,EAAM,MAAA;EAAA,SAET,KAAA,EAAK,aAAA,CAAA,gBAAA,CAAA,eAAA;EAAA,mBAEF,eAAA,EAAiB,yBAAA;EAEvB,WAAA,CAAY,IAAA,EAAM,eAAA,GAAkB,OAAA,CAAQ,aAAA;EAuC5C,KAAA,WAAgB,OAAA,CAAA,CAC3B,GAAA,UACA,OAAA,GAAS,sBAAA,CAAuB,CAAA,IAC/B,OAAA,CAAQ,aAAA,CAAc,MAAA,CAAO,CAAA;EAAA,UAiGtB,GAAA,CACR,IAAA,UACA,MAAA,EAAQ,UAAA,EACR,IAAA,EAAM,wBAAA;EAAA,UAeQ,IAAA,CACd,IAAA,EAAM,WAAA,EACN,OAAA,EAAS,MAAA,kBACT,MAAA,EAAQ,UAAA,EACR,IAAA,GAAM,wBAAA,GAA6B,OAAA;EAAA,UA+CrB,YAAA,CACd,QAAA,EAAU,QAAA,EACV,OAAA,EAAS,YAAA,GACR,OAAA;EAAA,UAiEO,WAAA,CAAY,QAAA,EAAU,QAAA;EAAA,UAoBtB,cAAA,CAAe,QAAA,EAAU,QAAA,EAAU,eAAA,YAAuB,QAAA;EAqB7D,aAAA,CACL,GAAA,UACA,MAAA;IAAU,MAAA;MAAW,MAAA,GAAS,OAAA;IAAA;EAAA,GAC9B,IAAA,GAAM,wBAAA;EAmBD,WAAA,CACL,GAAA,UACA,MAAA;IAAU,MAAA;MAAW,KAAA,GAAQ,OAAA;IAAA;EAAA,GAC7B,IAAA,GAAM,wBAAA;AAAA;AAAA,UA0BO,YAAA,WAAuB,OAAA,GAAU,OAAA;EV5Y1B;;;EUgZtB,GAAA;;;;EAKA,MAAA;IACE,QAAA,GAAW,CAAA;EAAA;;;;EAMb,UAAA,sBAAgC,YAAA;AAAA;AAAA,KAGtB,sBAAA,WAAiC,OAAA,GAAU,OAAA,IAAW,WAAA,GAChE,YAAA,CAAa,CAAA;AAAA,UAEE,aAAA;EACf,IAAA,EAAM,CAAA;EACN,MAAA;EACA,UAAA;EACA,OAAA,EAAS,OAAA;EACT,GAAA,GAAM,QAAA;AAAA;AAAA,KAGI,yBAAA,GAA4B,MAAA,SAEtC,OAAA;AAAA,UAGQ,eAAA;EACR,IAAA;EACA,IAAA;AAAA;AAAA,UAGe,eAAA;EACf,MAAA,EAAQ,UAAA;EACR,IAAA;EACA,MAAA,GAAS,wBAAA;EACT,OAAA,GAAU,oBAAA;AAAA;AAAA,UAGK,UAAA;EACf,MAAA;EACA,MAAA;EACA,IAAA;EACA,eAAA;EACA,MAAA;IACE,MAAA,GAAS,OAAA;IACT,KAAA,GAAQ,OAAA;IACR,IAAA,GAAO,YAAA;IACP,QAAA,GAAW,aAAA;EAAA;AAAA;;;;;;;;;AVpcf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA;;;;;;;;AChCA;;;;;;;;;;AAuBA;;;;;;;;;;;cUgFa,OAAA;EAAA,iBAA2B,mBAAA,EAAmB,OAAA,EAChD,sBAAA,CAAuB,OAAA,IAC/B,iBAAA,CAAkB,OAAA;EAAA;;UAkBJ,sBAAA,iBAAuC,mBAAA,UAC9C,IAAA,CAAK,WAAA;EVzHZ;;;;;;EUgID,IAAA;EVxFgB;;;;;;;;;;;;;AAuClB;;;;;AAkBA;;;;EUuDE,KAAA;;;;EAKA,IAAA;ETxJQ;;;;AAEV;;;;ESgKE,MAAA,GAAS,WAAA;;;;AR1KX;;;;EQmLE,MAAA,GAAS,OAAA;ERjLO;;;EQsLhB,WAAA;ER3KO;;;;EQiLP,QAAA;ER/JO;;;EQoKP,OAAA,EAAS,mBAAA,CAAoB,OAAA;AAAA;AAAA,cAYlB,eAAA,iBACK,mBAAA,UACR,SAAA,CAAU,sBAAA,CAAuB,OAAA;EAAA,mBACtB,GAAA,EADqB,cAAA,CAClB,MAAA;EAAA,mBACH,GAAA;;;qBACA,UAAA,EAAU,UAAA;EAAA,mBACV,cAAA,EAAc,cAAA;EAAA,mBACd,oBAAA,EAAoB,oBAAA;EAAA,UAE7B,MAAA,CAAA;EAAA,IAUC,MAAA,CAAA;EAAA,IAIA,KAAA,CAAA,GAAS,WAAA;EP/MpB;;;EAAA,IO0NW,IAAA,CAAA;EPjNe;;;EAAA,IOwNf,KAAA,CAAA;EPvNE;;;EAAA,IO8NF,MAAA,CAAA,GAAU,WAAA;;;;AN3OvB;;MMoPa,IAAA,CAAA;EAAA,IAkBA,MAAA,CAAA,GAAU,OAAA;EAId,kBAAA,CAAA;EN1QsC;;;;EMoShC,GAAA,CACX,MAAA,GAAS,kBAAA,CAAmB,OAAA,GAC5B,OAAA,GAAS,oBAAA,GACR,OAAA,CAAQ,qBAAA,CAAsB,OAAA;ENvSR;;;EMwYlB,KAAA,CACL,MAAA,GAAS,kBAAA,CAAmB,OAAA,GAC5B,OAAA,GAAU,oBAAA,GACT,OAAA,CAAQ,aAAA,CAAc,qBAAA,CAAsB,OAAA;AAAA;AAAA,UAUhC,iBAAA,iBAAkC,mBAAA,UACzC,eAAA,CAAgB,OAAA;EAAA,CAEtB,MAAA,GAAS,kBAAA,CAAmB,OAAA,GAC5B,OAAA,GAAU,oBAAA,GACT,OAAA,CAAQ,qBAAA,CAAsB,OAAA;AAAA;AAAA,KAOvB,kBAAA,iBACM,mBAAA,MACZ,2BAAA,CAA4B,OAAA,mBAEpB,CAAA,IAAK,CAAA,CAAE,CAAA,8BAA+B,CAAA,GAAI,CAAA,CAAE,CAAA;AAAA,KAG9C,2BAAA,iBAA4C,mBAAA;EACtD,IAAA,EAAM,OAAA,iBAAwB,YAAA,GAC1B,MAAA,CAAO,OAAA;EAGX,MAAA,EAAQ,OAAA,mBAA0B,OAAA,GAC9B,MAAA,CAAO,OAAA;EAGX,OAAA,GAAU,OAAA,oBAA2B,OAAA,GACjC,MAAA,CAAO,OAAA,eACP,MAAA;EAEJ,KAAA,GAAQ,OAAA,kBAAyB,OAAA,GAC7B,OAAA,CAAQ,MAAA,CAAO,OAAA,cACf,MAAA;AAAA;AAAA,UAGW,oBAAA,SAA6B,YAAA;ENlbrC;;;EMsbP,OAAA,GAAU,WAAA;EAEV,KAAA,GAAQ,MAAA;AAAA;AAAA,KAGE,qBAAA,iBAAsC,mBAAA,IAChD,OAAA,qBAA4B,OAAA,GAAU,MAAA,CAAO,OAAA;;;;KAKnC,mBAAA,iBACM,mBAAA,GAAsB,mBAAA,KAEtC,OAAA,EAAS,mBAAA,CAAoB,OAAA,MAC1B,KAAA,CAAM,kBAAA,CAAmB,OAAA;;;;;;;;UASb,mBAAA,iBAAoC,mBAAA,UAC3C,aAAA,CAAc,OAAA;;;cC5eX,eAAA,SAAwB,SAAA;cACvB,OAAA,WAAkC,KAAA;AAAA;;;cCDnC,aAAA,SAAsB,SAAA;cACrB,OAAA,WAAmC,KAAA;AAAA;;;cCDpC,cAAA,SAAuB,SAAA;cAEhC,OAAA,WACA,KAAA;AAAA;;;cCHS,aAAA,SAAsB,SAAA;cACrB,OAAA,WAAgC,KAAA;AAAA;;;cCDjC,iBAAA,SAA0B,SAAA;EAAA,SAC5B,IAAA;cAGP,OAAA,WACA,KAAA;AAAA;;;cCLS,eAAA,SAAwB,SAAA;cACvB,OAAA,WAAmC,KAAA;AAAA;;;;;;cCEpC,WAAA,GAAe,OAAA;EAC1B,MAAA,GAAS,mBAAA;EACT,eAAA;AAAA;;;cCJW,QAAA,WAAQ,OAAA;MAYpB,QAAA,CAAA,QAAA;;;;KAEW,EAAA,GAAK,MAAA,QAAc,QAAA;;;;;;;;;;;cCFlB,MAAA;EAAA,iBAA0B,mBAAA,EAAmB,OAAA,EAC/C,qBAAA,CAAsB,OAAA,IAC9B,cAAA,CAAe,OAAA;EAAA;;UAMD,qBAAA,iBACC,mBAAA,GAAsB,mBAAA,UAC9B,WAAA,CAAY,OAAA;AAAA,cAIT,cAAA,iBACK,mBAAA,UACR,SAAA,CAAU,qBAAA,CAAsB,OAAA;EAAA,mBACrB,oBAAA,EAAoB,oBAAA;EAAA,UAE7B,MAAA,CAAA;AAAA;;;cC5BN,WAAA,WAAS,OAAA;eAWb,QAAA,CAAA,QAAA;;;;YAGU,GAAA,SAAY,OAAA,CAAQ,MAAA,QAAc,WAAA;AAAA;AAAA,cAGjC,qBAAA,SAA8B,cAAA;EAAA,mBACtB,MAAA,EAAM,MAAA;EAAA,mBACN,gBAAA,EAAgB,gBAAA;EAAA,mBAChB,GAAA,EADgB,cAAA,CACb,MAAA;EAAA,mBACH,GAAA;;;;qBACA,MAAA,EAAM,oBAAA;EAAA,UAEf,SAAA,GAAY,UAAA,QAAkB,GAAA,CAAI,KAAA;EAAA,IAEjC,QAAA,CAAA;EAAA,SAOK,KAAA,EATgB,QAAA,CASX,aAAA;EAAA,mBAOF,IAAA,EAPE,QAAA,CAOE,aAAA;EAAA,UAaP,MAAA,CAAA,GAAM,OAAA;EAAA,UAyDN,KAAA,CAAA,GAAK,OAAA;AAAA;;;cCvGjB,SAAA,WAAS,OAAA;eAWb,QAAA,CAAA,QAAA;;;;YAGU,GAAA,SAAY,OAAA,CAAQ,MAAA,QAAc,SAAA;AAAA;AAAA,cAGjC,sBAAA,SAA+B,cAAA;EAAA,mBACvB,MAAA,EAAM,MAAA;EAAA,mBACN,gBAAA,EAAgB,gBAAA;EAAA,mBAChB,GAAA,EADgB,cAAA,CACb,MAAA;EAAA,mBACH,GAAA;;;;qBACA,MAAA,EAAM,oBAAA;;;;qBAKN,WAAA,EAAW,GAAA,CAAA,MAAA;EtBtCR;;;EsB2Cf,mBAAA,CAAA;;;;WAOS,OAAA;;;;;;;;MASL,QAAA,CAAA;EAAA,mBAWQ,kBAAA,GAAsB,GAAA,EAAK,gBAAA,EAAgB,GAAA,EAAK,KAAA;EAAA,mBAQhD,gBAAA;SACO,eAAA;SACA,gBAAA;EAAA;EAAA,SAGV,MAAA,EAAM,MAAA,QAAA,eAAA,SAAA,gBAAA;EAAA,SAWN,KAAA,EAXM,QAAA,CAWD,aAAA;EAAA,UAQX,gBAAA,CACR,IAAA,GAAO,GAAA,EAAK,eAAA,EAAiB,GAAA,EAAK,gBAAA,YACjC,MAAA;EAAA,mBAkBgB,IAAA,EAlBV,QAAA,CAkBc,aAAA;EAAA,UAOP,MAAA,CAAA,GAAM,OAAA;EAAA,UAoBN,KAAA,CAAA,GAAK,OAAA;EAAA,UAwCX,qBAAA,CAAA;AAAA;;;cC5LC,oBAAA;EAAA,mBACQ,GAAA,EADY,cAAA,CACT,MAAA;EAAA,mBACH,MAAA,EAAM,MAAA;EAAA,SAET,SAAA,EAFS,QAAA,CAEA,aAAA;EAAA,SA2BT,OAAA,EA3BS,QAAA,CA2BF,aAAA;EAAA,SAQP,UAAA,EARO,QAAA,CAQG,aAAA;AAAA;;;;;;;;;;cChCf,sBAAA;EAAA,mBACQ,MAAA,EAAM,MAAA;EAAA,SAET,SAAA,EAFS,QAAA,CAEA,aAAA;AAAA;;;;YCqBf,KAAA;IACR,oBAAA,GAAuB,MAAA;EAAA;EAAA,UAEf,KAAA;IAGR,kBAAA;MACE,MAAA,EAAQ,eAAA,CAAgB,mBAAA;MACxB,OAAA,EAAS,aAAA;MACT,OAAA,EAAS,oBAAA;IAAA;IAEX,mBAAA;MACE,MAAA,EAAQ,eAAA,CAAgB,mBAAA;MACxB,OAAA,EAAS,aAAA;MACT,OAAA,EAAS,oBAAA;MACT,QAAA;IAAA;IAIF,kBAAA;MACE,KAAA,EAAO,WAAA;MACP,OAAA,EAAS,aAAA;IAAA;IAEX,gBAAA;MACE,KAAA,EAAO,WAAA;MACP,OAAA,EAAS,aAAA;MACT,KAAA,EAAO,KAAA;IAAA;IAIT,eAAA;MACE,KAAA,EAAO,WAAA;MACP,OAAA,EAAS,aAAA;IAAA;IAGX,mBAAA;MACE,KAAA,EAAO,WAAA;MACP,OAAA,EAAS,aAAA;MACT,QAAA,EAAU,cAAA;IAAA;IAIZ,kBAAA;MACE,KAAA,EAAO,UAAA;MACP,MAAA,EAAQ,wBAAA;MACR,OAAA,EAAS,oBAAA;MACT,OAAA,EAAS,MAAA;MACT,OAAA,EAAS,WAAA;IAAA;IAEX,oBAAA;MACE,GAAA;MACA,OAAA,EAAS,YAAA;MACT,OAAA,EAAS,WAAA;IAAA;IAEX,gBAAA;MACE,KAAA,GAAQ,UAAA;MACR,KAAA,EAAO,SAAA;IAAA;IAIT,cAAA,EAAgB,gBAAA;IAChB,aAAA,EAAe,eAAA;EAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;cAyCN,YAAA,EAAY,QAAA,CAAA,OAAA,CA2CvB,QAAA,CA3CuB,MAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/server/core/schemas/errorSchema.ts","../../../src/server/core/errors/HttpError.ts","../../../src/server/core/constants/routeMethods.ts","../../../src/server/core/helpers/ServerReply.ts","../../../src/server/core/services/UserAgentParser.ts","../../../src/server/core/interfaces/ServerRequest.ts","../../../src/server/core/services/ServerRequestParser.ts","../../../src/server/core/providers/ServerTimingProvider.ts","../../../src/server/core/providers/ServerRouterProvider.ts","../../../src/server/core/providers/ServerProvider.ts","../../../src/server/core/services/HttpClient.ts","../../../src/server/core/primitives/$action.ts","../../../src/server/core/errors/BadRequestError.ts","../../../src/server/core/errors/ConflictError.ts","../../../src/server/core/errors/ForbiddenError.ts","../../../src/server/core/errors/NotFoundError.ts","../../../src/server/core/errors/UnauthorizedError.ts","../../../src/server/core/errors/ValidationError.ts","../../../src/server/core/helpers/isMultipart.ts","../../../src/server/core/schemas/okSchema.ts","../../../src/server/core/primitives/$route.ts","../../../src/server/core/providers/BunHttpServerProvider.ts","../../../src/server/core/providers/NodeHttpServerProvider.ts","../../../src/server/core/providers/ServerLoggerProvider.ts","../../../src/server/core/providers/ServerNotReadyProvider.ts","../../../src/server/core/index.ts"],"mappings":"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"}
@@ -536,16 +536,6 @@ var ServerRouterProvider = class extends RouterProvider {
536
536
  compiledOnSend;
537
537
  compiledOnResponse;
538
538
  compiledOnError;
539
- contextRunOptions = {
540
- context: "",
541
- _request: null,
542
- _route: null,
543
- _responseKind: "any"
544
- };
545
- processRequestBound = () => {
546
- const opts = this.contextRunOptions;
547
- return this.processRequest(opts._request, opts._route, opts._responseKind);
548
- };
549
539
  queryKeysCache = /* @__PURE__ */ new WeakMap();
550
540
  /**
551
541
  * Get cached keys for a query schema, computing them lazily on first access.
@@ -596,12 +586,7 @@ var ServerRouterProvider = class extends RouterProvider {
596
586
  path,
597
587
  handler: (rawRequest) => {
598
588
  const request = this.serverRequestParser.createServerRequest(rawRequest);
599
- const opts = this.contextRunOptions;
600
- opts.context = this.getContextId(rawRequest.headers);
601
- opts._request = request;
602
- opts._route = route;
603
- opts._responseKind = responseKind;
604
- return this.alepha.context.run(this.processRequestBound, opts);
589
+ return this.alepha.context.run(() => this.processRequest(request, route, responseKind), { context: this.getContextId(rawRequest.headers) });
605
590
  }
606
591
  });
607
592
  }
@@ -955,11 +940,13 @@ var ServerProvider = class {
955
940
  const response = await route.handler(request).catch(this.handleInternalError);
956
941
  if (res.headersSent) return;
957
942
  if (!response.body) {
958
- res.writeHead(response.status, response.headers).end();
943
+ res.writeHead(response.status, response.headers);
944
+ res.end();
959
945
  return;
960
946
  }
961
947
  if (typeof response.body === "string" || Buffer.isBuffer(response.body)) {
962
- res.writeHead(response.status, response.headers).end(response.body);
948
+ res.writeHead(response.status, response.headers);
949
+ res.end(response.body);
963
950
  return;
964
951
  }
965
952
  if (response.body instanceof Readable) {
@@ -1462,6 +1449,7 @@ var ActionPrimitive = class extends Primitive {
1462
1449
  * There is no HTTP layer involved.
1463
1450
  */
1464
1451
  async run(config, options = {}) {
1452
+ if (this.options.disabled) throw new AlephaError(`Action '${this.name}' is disabled.`);
1465
1453
  const handler = this.options.handler;
1466
1454
  const { body, params = {}, query = {}, headers = {} } = config ?? {};
1467
1455
  const reply = new ServerReply();
@@ -1674,15 +1662,11 @@ var NodeHttpServerProvider = class extends ServerProvider {
1674
1662
  res.statusCode = 500;
1675
1663
  res.end("Internal Server Error");
1676
1664
  };
1677
- nodeRequestEvent = {
1678
- req: null,
1679
- res: null
1680
- };
1681
1665
  server = this.createHttpServer((req, res) => {
1682
- const ev = this.nodeRequestEvent;
1683
- ev.req = req;
1684
- ev.res = res;
1685
- this.handleNodeRequest(ev).catch((err) => this.handleRequestError(res, err));
1666
+ this.handleNodeRequest({
1667
+ req,
1668
+ res
1669
+ }).catch((err) => this.handleRequestError(res, err));
1686
1670
  });
1687
1671
  start = $hook({
1688
1672
  on: "start",
@@ -2010,9 +1994,9 @@ const okSchema = t.object({
2010
1994
  //#endregion
2011
1995
  //#region ../../src/server/core/index.ts
2012
1996
  /**
2013
- * | type | quality | stability |
2014
- * |------|---------|-----------|
2015
- * | backend | epic | stable |
1997
+ * | Stability | Since | Runtime |
1998
+ * |-----------|-------|---------|
1999
+ * | 3 - stable | 0.1.0 | node, bun, workerd|
2016
2000
  *
2017
2001
  * Convention-driven HTTP server with automatic validation and type inference.
2018
2002
  *