@stacksjs/bun-router 0.0.13 → 0.0.14

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 (273) hide show
  1. package/CHANGELOG.md +770 -0
  2. package/README.md +584 -261
  3. package/package.json +43 -47
  4. package/bin/cli.ts +0 -9
  5. package/dist/auth.d.ts +0 -134
  6. package/dist/cache/lru-cache.d.ts +0 -139
  7. package/dist/cache/middleware-memoization.d.ts +0 -151
  8. package/dist/cache/route-cache-warmer.d.ts +0 -161
  9. package/dist/cache/sqlite-cache.d.ts +0 -209
  10. package/dist/cache/streaming-cache.d.ts +0 -132
  11. package/dist/chunk-1mvtv6jw.js +0 -13012
  12. package/dist/cli/colors.d.ts +0 -15
  13. package/dist/cli/index.d.ts +0 -10
  14. package/dist/cli/middleware.d.ts +0 -31
  15. package/dist/cli/openapi.d.ts +0 -17
  16. package/dist/cli/router.d.ts +0 -15
  17. package/dist/cli/routes.d.ts +0 -29
  18. package/dist/cli/utils.d.ts +0 -74
  19. package/dist/cli.d.ts +0 -1
  20. package/dist/cli.js +0 -3195
  21. package/dist/config.d.ts +0 -7
  22. package/dist/container/container.d.ts +0 -273
  23. package/dist/container/contextual-binding.d.ts +0 -240
  24. package/dist/container/decorators.d.ts +0 -141
  25. package/dist/container/service-provider.d.ts +0 -285
  26. package/dist/development/hot-reload.d.ts +0 -187
  27. package/dist/development/index.d.ts +0 -167
  28. package/dist/development/performance-profiler.d.ts +0 -217
  29. package/dist/development/route-debugger.d.ts +0 -154
  30. package/dist/development/route-inspector.d.ts +0 -211
  31. package/dist/development/typescript-utilities.d.ts +0 -209
  32. package/dist/docs.d.ts +0 -11
  33. package/dist/errors/circuit-breaker.d.ts +0 -195
  34. package/dist/errors/error-handler.d.ts +0 -88
  35. package/dist/errors/error-reporting.d.ts +0 -144
  36. package/dist/errors/exceptions.d.ts +0 -184
  37. package/dist/errors/graceful-degradation.d.ts +0 -154
  38. package/dist/errors/index.d.ts +0 -9
  39. package/dist/errors/router-errors.d.ts +0 -110
  40. package/dist/file-serving/static-files.d.ts +0 -143
  41. package/dist/index.d.ts +0 -14
  42. package/dist/index.js +0 -13933
  43. package/dist/middleware/auth.d.ts +0 -63
  44. package/dist/middleware/content_security_policy.d.ts +0 -53
  45. package/dist/middleware/cors.d.ts +0 -5
  46. package/dist/middleware/csrf.d.ts +0 -7
  47. package/dist/middleware/ddos_protection.d.ts +0 -39
  48. package/dist/middleware/file_security.d.ts +0 -26
  49. package/dist/middleware/file_upload.d.ts +0 -38
  50. package/dist/middleware/helmet.d.ts +0 -54
  51. package/dist/middleware/index.d.ts +0 -44
  52. package/dist/middleware/input_validation.d.ts +0 -45
  53. package/dist/middleware/json_body.d.ts +0 -4
  54. package/dist/middleware/performance_alerting.d.ts +0 -87
  55. package/dist/middleware/performance_dashboard.d.ts +0 -87
  56. package/dist/middleware/performance_monitor.d.ts +0 -209
  57. package/dist/middleware/pipeline.d.ts +0 -131
  58. package/dist/middleware/rate_limit.d.ts +0 -36
  59. package/dist/middleware/request_id.d.ts +0 -4
  60. package/dist/middleware/request_signing.d.ts +0 -153
  61. package/dist/middleware/request_tracer.d.ts +0 -72
  62. package/dist/middleware/response_cache.d.ts +0 -97
  63. package/dist/middleware/security.d.ts +0 -69
  64. package/dist/middleware/security_suite.d.ts +0 -46
  65. package/dist/middleware/session.d.ts +0 -23
  66. package/dist/model-binding/index.d.ts +0 -2
  67. package/dist/model-binding/model-middleware.d.ts +0 -118
  68. package/dist/model-binding/model-registry.d.ts +0 -164
  69. package/dist/model-binding.d.ts +0 -185
  70. package/dist/model-resolver-factory.d.ts +0 -31
  71. package/dist/observability/correlation.d.ts +0 -187
  72. package/dist/observability/health-checks.d.ts +0 -186
  73. package/dist/observability/index.d.ts +0 -60
  74. package/dist/observability/integration.d.ts +0 -147
  75. package/dist/observability/metrics.d.ts +0 -184
  76. package/dist/observability/tracing.d.ts +0 -187
  77. package/dist/optimization/bun-utilities.d.ts +0 -224
  78. package/dist/query-builder-integration.d.ts +0 -36
  79. package/dist/request/context.d.ts +0 -34
  80. package/dist/request/enhanced-request.d.ts +0 -213
  81. package/dist/request/macros.d.ts +0 -300
  82. package/dist/response/macros.d.ts +0 -245
  83. package/dist/response/response-factory.d.ts +0 -133
  84. package/dist/router/api-routes.d.ts +0 -5
  85. package/dist/router/file-based-routing.d.ts +0 -118
  86. package/dist/router/file-streaming.d.ts +0 -5
  87. package/dist/router/fluent-router.d.ts +0 -315
  88. package/dist/router/fluent-routing.d.ts +0 -271
  89. package/dist/router/group-organization.d.ts +0 -5
  90. package/dist/router/handler-resolver.d.ts +0 -24
  91. package/dist/router/http-methods.d.ts +0 -10
  92. package/dist/router/index.d.ts +0 -114
  93. package/dist/router/middleware-groups.d.ts +0 -94
  94. package/dist/router/middleware-integration.d.ts +0 -112
  95. package/dist/router/middleware.d.ts +0 -5
  96. package/dist/router/model-binding.d.ts +0 -5
  97. package/dist/router/optimized-route-matching.d.ts +0 -6
  98. package/dist/router/route-building.d.ts +0 -5
  99. package/dist/router/route-compiler.d.ts +0 -153
  100. package/dist/router/route-matching.d.ts +0 -5
  101. package/dist/router/route-trie.d.ts +0 -114
  102. package/dist/router/router.d.ts +0 -294
  103. package/dist/router/server.d.ts +0 -5
  104. package/dist/router/validation-integration.d.ts +0 -170
  105. package/dist/router/view-rendering.d.ts +0 -5
  106. package/dist/router/websocket.d.ts +0 -5
  107. package/dist/routing/route-caching.d.ts +0 -129
  108. package/dist/routing/route-throttling.d.ts +0 -150
  109. package/dist/routing/subdomain-routing.d.ts +0 -206
  110. package/dist/session/database-store.d.ts +0 -51
  111. package/dist/session/file-store.d.ts +0 -22
  112. package/dist/session/index.d.ts +0 -106
  113. package/dist/session/memory-store.d.ts +0 -21
  114. package/dist/session/redis-store.d.ts +0 -31
  115. package/dist/streaming/index.d.ts +0 -3
  116. package/dist/streaming/sse-handler.d.ts +0 -138
  117. package/dist/streaming/stream-handler.d.ts +0 -114
  118. package/dist/testing/auth-testing.d.ts +0 -156
  119. package/dist/testing/file-upload-testing.d.ts +0 -190
  120. package/dist/testing/index.d.ts +0 -10
  121. package/dist/testing/middleware-testing.d.ts +0 -138
  122. package/dist/testing/model-binding-testing.d.ts +0 -186
  123. package/dist/testing/performance-testing.d.ts +0 -235
  124. package/dist/testing/test-client.d.ts +0 -117
  125. package/dist/testing/test-request.d.ts +0 -85
  126. package/dist/testing/test-response.d.ts +0 -90
  127. package/dist/testing/types.d.ts +0 -207
  128. package/dist/testing/websocket-testing.d.ts +0 -227
  129. package/dist/types/controller-types.d.ts +0 -208
  130. package/dist/types/core.d.ts +0 -543
  131. package/dist/types/middleware-types.d.ts +0 -227
  132. package/dist/types/request-response-augmentation.d.ts +0 -261
  133. package/dist/types/route-inference.d.ts +0 -168
  134. package/dist/types.d.ts +0 -1782
  135. package/dist/url.d.ts +0 -56
  136. package/dist/utils/index.d.ts +0 -1
  137. package/dist/utils/query-preservation.d.ts +0 -48
  138. package/dist/utils.d.ts +0 -69
  139. package/dist/validation/validator.d.ts +0 -140
  140. package/dist/websocket/clustering.d.ts +0 -185
  141. package/src/auth.ts +0 -469
  142. package/src/cache/lru-cache.ts +0 -457
  143. package/src/cache/middleware-memoization.ts +0 -531
  144. package/src/cache/route-cache-warmer.ts +0 -486
  145. package/src/cache/sqlite-cache.ts +0 -783
  146. package/src/cache/streaming-cache.ts +0 -572
  147. package/src/cli/colors.ts +0 -29
  148. package/src/cli/index.ts +0 -287
  149. package/src/cli/middleware.ts +0 -291
  150. package/src/cli/openapi.ts +0 -407
  151. package/src/cli/router.ts +0 -188
  152. package/src/cli/routes.ts +0 -265
  153. package/src/cli/utils.ts +0 -531
  154. package/src/cli.ts +0 -5
  155. package/src/config.ts +0 -322
  156. package/src/container/container.ts +0 -740
  157. package/src/container/contextual-binding.ts +0 -603
  158. package/src/container/decorators.ts +0 -359
  159. package/src/container/service-provider.ts +0 -596
  160. package/src/development/hot-reload.ts +0 -673
  161. package/src/development/index.ts +0 -499
  162. package/src/development/performance-profiler.ts +0 -717
  163. package/src/development/route-debugger.ts +0 -527
  164. package/src/development/route-inspector.ts +0 -749
  165. package/src/development/typescript-utilities.ts +0 -682
  166. package/src/docs.ts +0 -397
  167. package/src/errors/circuit-breaker.ts +0 -732
  168. package/src/errors/error-handler.ts +0 -569
  169. package/src/errors/error-reporting.ts +0 -672
  170. package/src/errors/exceptions.ts +0 -536
  171. package/src/errors/graceful-degradation.ts +0 -621
  172. package/src/errors/index.ts +0 -21
  173. package/src/errors/router-errors.ts +0 -632
  174. package/src/file-serving/static-files.ts +0 -581
  175. package/src/index.ts +0 -14
  176. package/src/middleware/auth.ts +0 -219
  177. package/src/middleware/content_security_policy.ts +0 -215
  178. package/src/middleware/cors.ts +0 -74
  179. package/src/middleware/csrf.ts +0 -108
  180. package/src/middleware/ddos_protection.ts +0 -255
  181. package/src/middleware/file_security.ts +0 -191
  182. package/src/middleware/file_upload.ts +0 -264
  183. package/src/middleware/helmet.ts +0 -268
  184. package/src/middleware/index.ts +0 -117
  185. package/src/middleware/input_validation.ts +0 -449
  186. package/src/middleware/json_body.ts +0 -37
  187. package/src/middleware/performance_alerting.ts +0 -538
  188. package/src/middleware/performance_dashboard.ts +0 -661
  189. package/src/middleware/performance_monitor.ts +0 -943
  190. package/src/middleware/pipeline.ts +0 -489
  191. package/src/middleware/rate_limit.ts +0 -245
  192. package/src/middleware/request_id.ts +0 -36
  193. package/src/middleware/request_signing.ts +0 -636
  194. package/src/middleware/request_tracer.ts +0 -636
  195. package/src/middleware/response_cache.ts +0 -743
  196. package/src/middleware/security.ts +0 -482
  197. package/src/middleware/security_suite.ts +0 -257
  198. package/src/middleware/session.ts +0 -91
  199. package/src/model-binding/index.ts +0 -18
  200. package/src/model-binding/model-middleware.ts +0 -425
  201. package/src/model-binding/model-registry.ts +0 -550
  202. package/src/model-binding.ts +0 -370
  203. package/src/model-resolver-factory.ts +0 -106
  204. package/src/observability/correlation.ts +0 -691
  205. package/src/observability/health-checks.ts +0 -729
  206. package/src/observability/index.ts +0 -184
  207. package/src/observability/integration.ts +0 -548
  208. package/src/observability/metrics.ts +0 -753
  209. package/src/observability/tracing.ts +0 -638
  210. package/src/optimization/bun-utilities.ts +0 -778
  211. package/src/query-builder-integration.ts +0 -137
  212. package/src/request/context.ts +0 -62
  213. package/src/request/enhanced-request.ts +0 -857
  214. package/src/request/macros.ts +0 -688
  215. package/src/response/macros.ts +0 -612
  216. package/src/response/response-factory.ts +0 -596
  217. package/src/router/api-routes.ts +0 -243
  218. package/src/router/file-based-routing.ts +0 -670
  219. package/src/router/file-streaming.ts +0 -372
  220. package/src/router/fluent-router.ts +0 -927
  221. package/src/router/fluent-routing.ts +0 -797
  222. package/src/router/group-organization.ts +0 -213
  223. package/src/router/handler-resolver.ts +0 -291
  224. package/src/router/http-methods.ts +0 -377
  225. package/src/router/index.ts +0 -187
  226. package/src/router/middleware-groups.ts +0 -222
  227. package/src/router/middleware-integration.ts +0 -399
  228. package/src/router/middleware.ts +0 -231
  229. package/src/router/model-binding.ts +0 -215
  230. package/src/router/optimized-route-matching.ts +0 -253
  231. package/src/router/route-building.ts +0 -212
  232. package/src/router/route-compiler.ts +0 -702
  233. package/src/router/route-matching.ts +0 -349
  234. package/src/router/route-trie.ts +0 -464
  235. package/src/router/router.ts +0 -1581
  236. package/src/router/server.ts +0 -462
  237. package/src/router/validation-integration.ts +0 -443
  238. package/src/router/view-rendering.ts +0 -233
  239. package/src/router/websocket.ts +0 -100
  240. package/src/routing/route-caching.ts +0 -402
  241. package/src/routing/route-throttling.ts +0 -469
  242. package/src/routing/subdomain-routing.ts +0 -492
  243. package/src/session/database-store.ts +0 -109
  244. package/src/session/file-store.ts +0 -148
  245. package/src/session/index.ts +0 -244
  246. package/src/session/memory-store.ts +0 -88
  247. package/src/session/redis-store.ts +0 -93
  248. package/src/streaming/index.ts +0 -17
  249. package/src/streaming/sse-handler.ts +0 -482
  250. package/src/streaming/stream-handler.ts +0 -552
  251. package/src/testing/auth-testing.ts +0 -446
  252. package/src/testing/file-upload-testing.ts +0 -543
  253. package/src/testing/index.ts +0 -10
  254. package/src/testing/middleware-testing.ts +0 -322
  255. package/src/testing/model-binding-testing.ts +0 -645
  256. package/src/testing/performance-testing.ts +0 -738
  257. package/src/testing/test-client.ts +0 -310
  258. package/src/testing/test-request.ts +0 -315
  259. package/src/testing/test-response.ts +0 -332
  260. package/src/testing/types.ts +0 -224
  261. package/src/testing/websocket-testing.ts +0 -590
  262. package/src/types/controller-types.ts +0 -385
  263. package/src/types/core.ts +0 -683
  264. package/src/types/middleware-types.ts +0 -419
  265. package/src/types/request-response-augmentation.ts +0 -489
  266. package/src/types/route-inference.ts +0 -357
  267. package/src/types.ts +0 -2055
  268. package/src/url.ts +0 -126
  269. package/src/utils/index.ts +0 -1
  270. package/src/utils/query-preservation.ts +0 -201
  271. package/src/utils.ts +0 -327
  272. package/src/validation/validator.ts +0 -685
  273. package/src/websocket/clustering.ts +0 -762
@@ -1,100 +0,0 @@
1
- import type { WebSocketConfig } from '../types'
2
- import type { Router } from './router'
3
-
4
- /**
5
- * WebSocket extension for Router class
6
- */
7
- export function registerWebSocketHandling(RouterClass: typeof Router): void {
8
- Object.defineProperties(RouterClass.prototype, {
9
- /**
10
- * Configure WebSocket handling
11
- */
12
- websocket: {
13
- value(config: WebSocketConfig): Router {
14
- this.wsConfig = config
15
- return this
16
- },
17
- writable: true,
18
- configurable: true,
19
- },
20
-
21
- /**
22
- * Publish a message to a WebSocket topic
23
- */
24
- publish: {
25
- value(topic: string, data: string | ArrayBuffer | Uint8Array, compress = false): number {
26
- if (!this.serverInstance) {
27
- throw new Error('Server not started, cannot publish to WebSocket topics')
28
- }
29
-
30
- return this.serverInstance.publish(topic, data, compress)
31
- },
32
- writable: true,
33
- configurable: true,
34
- },
35
-
36
- /**
37
- * Get the number of subscribers for a WebSocket topic
38
- */
39
- subscriberCount: {
40
- value(topic: string): number {
41
- if (!this.serverInstance) {
42
- throw new Error('Server not started, cannot get subscriber count')
43
- }
44
-
45
- return this.serverInstance.subscriberCount(topic)
46
- },
47
- writable: true,
48
- configurable: true,
49
- },
50
-
51
- /**
52
- * Upgrade an HTTP request to a WebSocket connection
53
- */
54
- upgrade: {
55
- value(request: Request, options?: { headers?: Record<string, string>, data?: any }): boolean {
56
- if (!this.serverInstance) {
57
- throw new Error('Server not started, cannot upgrade to WebSocket')
58
- }
59
-
60
- if (!this.wsConfig) {
61
- throw new Error('WebSocket configuration not set, use router.websocket() to configure')
62
- }
63
-
64
- return this.serverInstance.upgrade(request, options)
65
- },
66
- writable: true,
67
- configurable: true,
68
- },
69
-
70
- /**
71
- * Set a timeout for a request
72
- */
73
- timeout: {
74
- value(request: Request, seconds: number): void {
75
- if (!this.serverInstance) {
76
- throw new Error('Server not started, cannot set timeout')
77
- }
78
-
79
- this.serverInstance.timeout(request, seconds)
80
- },
81
- writable: true,
82
- configurable: true,
83
- },
84
-
85
- /**
86
- * Get the IP address of a request
87
- */
88
- requestIP: {
89
- value(request: Request): { address: string, port: number } | null {
90
- if (!this.serverInstance) {
91
- throw new Error('Server not started, cannot get request IP')
92
- }
93
-
94
- return this.serverInstance.requestIP(request)
95
- },
96
- writable: true,
97
- configurable: true,
98
- },
99
- })
100
- }
@@ -1,402 +0,0 @@
1
- import type { EnhancedRequest } from '../types'
2
- import { LRUCache } from '../cache/lru-cache'
3
-
4
- /**
5
- * Route caching configuration
6
- */
7
- export interface RouteCacheConfig {
8
- ttl?: number // Time to live in milliseconds
9
- maxSize?: number // Maximum number of cached responses
10
- tags?: string[] // Cache tags for invalidation
11
- varyBy?: string[] // Headers to vary cache by
12
- excludeQuery?: string[] // Query parameters to exclude from cache key
13
- condition?: (req: EnhancedRequest) => boolean // Condition to determine if response should be cached
14
- }
15
-
16
- /**
17
- * Cached response metadata
18
- */
19
- export interface CachedResponse {
20
- response: Response
21
- headers: Record<string, string>
22
- status: number
23
- body: string | Uint8Array
24
- timestamp: number
25
- ttl?: number
26
- tags: string[]
27
- etag?: string
28
- }
29
-
30
- /**
31
- * Cache key generator for route responses
32
- */
33
- export class RouteCacheKeyGenerator {
34
- /**
35
- * Generate cache key from request
36
- */
37
- static generateKey(req: EnhancedRequest, config: RouteCacheConfig): string {
38
- const url = new URL(req.url)
39
- const method = req.method
40
- const path = url.pathname
41
-
42
- // Base key components
43
- const keyParts = [method, path]
44
-
45
- // Add query parameters (excluding specified ones)
46
- const queryParams = new URLSearchParams(url.search)
47
- const excludeQuery = config.excludeQuery || []
48
-
49
- const relevantQuery: string[] = []
50
- for (const [key, value] of queryParams.entries()) {
51
- if (!excludeQuery.includes(key)) {
52
- relevantQuery.push(`${key}=${value}`)
53
- }
54
- }
55
-
56
- if (relevantQuery.length > 0) {
57
- keyParts.push(relevantQuery.sort().join('&'))
58
- }
59
-
60
- // Add vary headers
61
- if (config.varyBy) {
62
- const varyValues: string[] = []
63
- for (const header of config.varyBy) {
64
- const value = req.headers.get(header)
65
- if (value) {
66
- varyValues.push(`${header}:${value}`)
67
- }
68
- }
69
- if (varyValues.length > 0) {
70
- keyParts.push(varyValues.join('|'))
71
- }
72
- }
73
-
74
- return keyParts.join('::')
75
- }
76
- }
77
-
78
- /**
79
- * Route cache manager with tag-based invalidation
80
- */
81
- export class RouteCacheManager {
82
- private cache: LRUCache<CachedResponse>
83
- private tagIndex: Map<string, Set<string>> = new Map() // tag -> cache keys
84
- private keyTags: Map<string, Set<string>> = new Map() // cache key -> tags
85
-
86
- constructor(maxSize: number = 1000) {
87
- this.cache = new LRUCache<CachedResponse>({ maxSize })
88
- }
89
-
90
- /**
91
- * Get cached response
92
- */
93
- async get(key: string): Promise<CachedResponse | null> {
94
- const cached = this.cache.get(key)
95
- if (!cached) {
96
- return null
97
- }
98
-
99
- // Check TTL
100
- if (cached.ttl && Date.now() - cached.timestamp > cached.ttl) {
101
- this.delete(key)
102
- return null
103
- }
104
-
105
- return cached
106
- }
107
-
108
- /**
109
- * Set cached response
110
- */
111
- async set(key: string, response: CachedResponse): Promise<void> {
112
- // Store in cache
113
- this.cache.set(key, response)
114
-
115
- // Update tag indexes
116
- this.keyTags.set(key, new Set(response.tags))
117
-
118
- for (const tag of response.tags) {
119
- if (!this.tagIndex.has(tag)) {
120
- this.tagIndex.set(tag, new Set())
121
- }
122
- this.tagIndex.get(tag)!.add(key)
123
- }
124
- }
125
-
126
- /**
127
- * Delete cached response
128
- */
129
- delete(key: string): boolean {
130
- const tags = this.keyTags.get(key)
131
- if (tags) {
132
- // Remove from tag indexes
133
- for (const tag of tags) {
134
- const tagKeys = this.tagIndex.get(tag)
135
- if (tagKeys) {
136
- tagKeys.delete(key)
137
- if (tagKeys.size === 0) {
138
- this.tagIndex.delete(tag)
139
- }
140
- }
141
- }
142
- this.keyTags.delete(key)
143
- }
144
-
145
- return this.cache.delete(key)
146
- }
147
-
148
- /**
149
- * Invalidate cache by tags
150
- */
151
- invalidateByTags(tags: string[]): number {
152
- const keysToDelete = new Set<string>()
153
-
154
- for (const tag of tags) {
155
- const tagKeys = this.tagIndex.get(tag)
156
- if (tagKeys) {
157
- for (const key of tagKeys) {
158
- keysToDelete.add(key)
159
- }
160
- }
161
- }
162
-
163
- for (const key of keysToDelete) {
164
- this.delete(key)
165
- }
166
-
167
- return keysToDelete.size
168
- }
169
-
170
- /**
171
- * Clear all cache
172
- */
173
- clear(): void {
174
- this.cache.clear()
175
- this.tagIndex.clear()
176
- this.keyTags.clear()
177
- }
178
-
179
- /**
180
- * Get cache statistics
181
- */
182
- getStats(): ReturnType<LRUCache<CachedResponse>['getStats']> & { totalTags: number, totalKeyTagMappings: number } {
183
- return {
184
- ...this.cache.getStats(),
185
- totalTags: this.tagIndex.size,
186
- totalKeyTagMappings: this.keyTags.size,
187
- }
188
- }
189
- }
190
-
191
- /**
192
- * Global route cache manager instance
193
- */
194
- export const routeCacheManager: RouteCacheManager = new RouteCacheManager()
195
-
196
- /**
197
- * Create route caching middleware
198
- */
199
- export function createRouteCacheMiddleware(config: RouteCacheConfig) {
200
- return async (req: EnhancedRequest, next: () => Promise<Response>): Promise<Response> => {
201
- // Check if caching condition is met
202
- if (config.condition && !config.condition(req)) {
203
- return await next()
204
- }
205
-
206
- // Only cache GET and HEAD requests by default
207
- if (req.method !== 'GET' && req.method !== 'HEAD') {
208
- return await next()
209
- }
210
-
211
- // Generate cache key
212
- const cacheKey = RouteCacheKeyGenerator.generateKey(req, config)
213
-
214
- // Try to get from cache
215
- const cached = await routeCacheManager.get(cacheKey)
216
- if (cached) {
217
- // Return cached response
218
- const headers = new Headers(cached.headers)
219
-
220
- // Add cache headers
221
- headers.set('X-Cache', 'HIT')
222
- headers.set('X-Cache-Key', cacheKey)
223
-
224
- if (cached.etag) {
225
- headers.set('ETag', cached.etag)
226
-
227
- // Check if client has matching ETag
228
- const clientETag = req.headers.get('If-None-Match')
229
- if (clientETag === cached.etag) {
230
- return new Response(null, { status: 304, headers })
231
- }
232
- }
233
-
234
- return new Response(cached.body as any, {
235
- status: cached.status,
236
- headers,
237
- })
238
- }
239
-
240
- // Execute route handler
241
- const response = await next()
242
-
243
- // Only cache successful responses
244
- if (response.status >= 200 && response.status < 300) {
245
- try {
246
- // Clone response to cache it
247
- const responseClone = response.clone()
248
- const body = await responseClone.arrayBuffer()
249
-
250
- // Generate ETag
251
- const etag = await generateETag(body)
252
-
253
- // Prepare headers for caching
254
- const headers: Record<string, string> = {}
255
- responseClone.headers.forEach((value, key) => {
256
- headers[key] = value
257
- })
258
-
259
- // Create cached response
260
- const cachedResponse: CachedResponse = {
261
- response: responseClone as Response,
262
- headers,
263
- status: response.status,
264
- body: new Uint8Array(body),
265
- timestamp: Date.now(),
266
- ttl: config.ttl,
267
- tags: config.tags || [],
268
- etag,
269
- }
270
-
271
- // Store in cache
272
- await routeCacheManager.set(cacheKey, cachedResponse)
273
-
274
- // Add cache headers to original response
275
- const originalHeaders = new Headers(response.headers)
276
- originalHeaders.set('X-Cache', 'MISS')
277
- originalHeaders.set('X-Cache-Key', cacheKey)
278
- originalHeaders.set('ETag', etag)
279
-
280
- return new Response(response.body, {
281
- status: response.status,
282
- headers: originalHeaders,
283
- })
284
- }
285
- catch (error) {
286
- console.error('Error caching response:', error)
287
- // Return original response if caching fails
288
- return response
289
- }
290
- }
291
-
292
- return response
293
- }
294
- }
295
-
296
- /**
297
- * Generate ETag from response body
298
- */
299
- async function generateETag(body: ArrayBuffer): Promise<string> {
300
- const hash = await crypto.subtle.digest('SHA-256', body)
301
- const hashArray = Array.from(new Uint8Array(hash))
302
- const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
303
- return `"${hashHex.substring(0, 16)}"` // Use first 16 chars for ETag
304
- }
305
-
306
- /**
307
- * Factory functions for common cache configurations
308
- */
309
- export const RouteCacheFactory = {
310
- /**
311
- * Short-term cache (5 minutes)
312
- */
313
- short: (tags: string[] = []): RouteCacheConfig => ({
314
- ttl: 5 * 60 * 1000, // 5 minutes
315
- maxSize: 500,
316
- tags,
317
- }),
318
-
319
- /**
320
- * Medium-term cache (1 hour)
321
- */
322
- medium: (tags: string[] = []): RouteCacheConfig => ({
323
- ttl: 60 * 60 * 1000, // 1 hour
324
- maxSize: 1000,
325
- tags,
326
- }),
327
-
328
- /**
329
- * Long-term cache (24 hours)
330
- */
331
- long: (tags: string[] = []): RouteCacheConfig => ({
332
- ttl: 24 * 60 * 60 * 1000, // 24 hours
333
- maxSize: 2000,
334
- tags,
335
- }),
336
-
337
- /**
338
- * API response cache with common settings
339
- */
340
- api: (tags: string[] = []): RouteCacheConfig => ({
341
- ttl: 15 * 60 * 1000, // 15 minutes
342
- maxSize: 1000,
343
- tags,
344
- varyBy: ['Authorization', 'Accept', 'Accept-Language'],
345
- excludeQuery: ['_t', 'timestamp', 'cache_bust'],
346
- }),
347
-
348
- /**
349
- * Static content cache
350
- */
351
- static: (tags: string[] = []): RouteCacheConfig => ({
352
- ttl: 7 * 24 * 60 * 60 * 1000, // 7 days
353
- maxSize: 5000,
354
- tags,
355
- varyBy: ['Accept-Encoding'],
356
- }),
357
-
358
- /**
359
- * User-specific cache
360
- */
361
- user: (tags: string[] = []): RouteCacheConfig => ({
362
- ttl: 30 * 60 * 1000, // 30 minutes
363
- maxSize: 2000,
364
- tags,
365
- varyBy: ['Authorization'],
366
- condition: req => !!req.headers.get('Authorization'),
367
- }),
368
- }
369
-
370
- /**
371
- * Cache invalidation utilities
372
- */
373
- export const CacheInvalidation = {
374
- /**
375
- * Invalidate by tags
376
- */
377
- byTags: (tags: string[]): number => {
378
- return routeCacheManager.invalidateByTags(tags)
379
- },
380
-
381
- /**
382
- * Invalidate all user-related cache
383
- */
384
- forUser: (userId: string): number => {
385
- return routeCacheManager.invalidateByTags([`user:${userId}`])
386
- },
387
-
388
- /**
389
- * Invalidate model-related cache
390
- */
391
- forModel: (modelName: string, id?: string): number => {
392
- const tags = id ? [`${modelName}:${id}`, modelName] : [modelName]
393
- return routeCacheManager.invalidateByTags(tags)
394
- },
395
-
396
- /**
397
- * Clear all cache
398
- */
399
- all: (): void => {
400
- routeCacheManager.clear()
401
- },
402
- }