@stacksjs/bun-router 0.0.17 → 0.0.18

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 (146) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/container/service-provider.d.ts +3 -3
  3. package/dist/development/performance-profiler.d.ts +3 -3
  4. package/dist/development/route-debugger.d.ts +1 -1
  5. package/dist/development/route-inspector.d.ts +2 -2
  6. package/dist/observability/integration.d.ts +1 -1
  7. package/dist/response/macros.d.ts +1 -1
  8. package/dist/router/index.d.ts +7 -7
  9. package/dist/router/router.d.ts +0 -32
  10. package/dist/testing/performance-testing.d.ts +2 -2
  11. package/dist/testing/test-client.d.ts +1 -1
  12. package/dist/testing/websocket-testing.d.ts +1 -1
  13. package/package.json +2 -3
  14. package/src/auth.ts +0 -489
  15. package/src/cache/lru-cache.ts +0 -457
  16. package/src/cache/middleware-memoization.ts +0 -531
  17. package/src/cache/route-cache-warmer.ts +0 -486
  18. package/src/cache/sqlite-cache.ts +0 -783
  19. package/src/cache/streaming-cache.ts +0 -572
  20. package/src/cli/colors.ts +0 -29
  21. package/src/cli/index.ts +0 -287
  22. package/src/cli/middleware.ts +0 -291
  23. package/src/cli/openapi.ts +0 -407
  24. package/src/cli/router.ts +0 -188
  25. package/src/cli/routes.ts +0 -265
  26. package/src/cli/utils.ts +0 -531
  27. package/src/cli.ts +0 -5
  28. package/src/config.ts +0 -322
  29. package/src/container/container.ts +0 -786
  30. package/src/container/contextual-binding.ts +0 -606
  31. package/src/container/decorators.ts +0 -368
  32. package/src/container/index.ts +0 -49
  33. package/src/container/service-provider.ts +0 -596
  34. package/src/development/hot-reload.ts +0 -673
  35. package/src/development/index.ts +0 -499
  36. package/src/development/performance-profiler.ts +0 -717
  37. package/src/development/route-debugger.ts +0 -527
  38. package/src/development/route-inspector.ts +0 -749
  39. package/src/development/typescript-utilities.ts +0 -682
  40. package/src/docs.ts +0 -397
  41. package/src/errors/circuit-breaker.ts +0 -733
  42. package/src/errors/error-handler.ts +0 -569
  43. package/src/errors/error-reporting.ts +0 -672
  44. package/src/errors/exceptions.ts +0 -536
  45. package/src/errors/graceful-degradation.ts +0 -623
  46. package/src/errors/index.ts +0 -21
  47. package/src/errors/router-errors.ts +0 -632
  48. package/src/file-serving/static-files.ts +0 -718
  49. package/src/index.ts +0 -66
  50. package/src/middleware/auth.ts +0 -220
  51. package/src/middleware/content_security_policy.ts +0 -215
  52. package/src/middleware/cors.ts +0 -142
  53. package/src/middleware/csrf.ts +0 -166
  54. package/src/middleware/ddos_protection.ts +0 -279
  55. package/src/middleware/file_security.ts +0 -191
  56. package/src/middleware/file_upload.ts +0 -275
  57. package/src/middleware/helmet.ts +0 -268
  58. package/src/middleware/index.ts +0 -117
  59. package/src/middleware/input_validation.ts +0 -453
  60. package/src/middleware/json_body.ts +0 -37
  61. package/src/middleware/performance_alerting.ts +0 -540
  62. package/src/middleware/performance_dashboard.ts +0 -661
  63. package/src/middleware/performance_monitor.ts +0 -945
  64. package/src/middleware/pipeline.ts +0 -489
  65. package/src/middleware/rate_limit.ts +0 -251
  66. package/src/middleware/request_id.ts +0 -36
  67. package/src/middleware/request_signing.ts +0 -638
  68. package/src/middleware/request_tracer.ts +0 -653
  69. package/src/middleware/response_cache.ts +0 -778
  70. package/src/middleware/security.ts +0 -482
  71. package/src/middleware/security_suite.ts +0 -257
  72. package/src/middleware/session.ts +0 -91
  73. package/src/model-binding/index.ts +0 -18
  74. package/src/model-binding/model-middleware.ts +0 -425
  75. package/src/model-binding/model-registry.ts +0 -550
  76. package/src/model-binding.ts +0 -370
  77. package/src/model-resolver-factory.ts +0 -106
  78. package/src/observability/correlation.ts +0 -691
  79. package/src/observability/health-checks.ts +0 -729
  80. package/src/observability/index.ts +0 -184
  81. package/src/observability/integration.ts +0 -548
  82. package/src/observability/metrics.ts +0 -753
  83. package/src/observability/tracing.ts +0 -638
  84. package/src/optimization/bun-utilities.ts +0 -778
  85. package/src/query-builder-integration.ts +0 -137
  86. package/src/request/context.ts +0 -109
  87. package/src/request/enhanced-request.ts +0 -876
  88. package/src/request/macros.ts +0 -822
  89. package/src/response/macros.ts +0 -665
  90. package/src/response/response-factory.ts +0 -596
  91. package/src/router/api-routes.ts +0 -243
  92. package/src/router/file-based-routing.ts +0 -697
  93. package/src/router/file-streaming.ts +0 -383
  94. package/src/router/fluent-routing.ts +0 -866
  95. package/src/router/group-organization.ts +0 -229
  96. package/src/router/handler-resolver.ts +0 -327
  97. package/src/router/http-methods.ts +0 -407
  98. package/src/router/index.ts +0 -193
  99. package/src/router/middleware-groups.ts +0 -222
  100. package/src/router/middleware-integration.ts +0 -399
  101. package/src/router/middleware.ts +0 -234
  102. package/src/router/model-binding.ts +0 -215
  103. package/src/router/optimized-route-matching.ts +0 -302
  104. package/src/router/route-building.ts +0 -221
  105. package/src/router/route-compiler.ts +0 -691
  106. package/src/router/route-matching.ts +0 -368
  107. package/src/router/route-trie.ts +0 -450
  108. package/src/router/router.ts +0 -1616
  109. package/src/router/server.ts +0 -684
  110. package/src/router/validation-integration.ts +0 -449
  111. package/src/router/view-rendering.ts +0 -233
  112. package/src/router/websocket.ts +0 -100
  113. package/src/routing/route-caching.ts +0 -402
  114. package/src/routing/route-throttling.ts +0 -469
  115. package/src/routing/subdomain-routing.ts +0 -492
  116. package/src/session/database-store.ts +0 -109
  117. package/src/session/file-store.ts +0 -148
  118. package/src/session/index.ts +0 -244
  119. package/src/session/memory-store.ts +0 -88
  120. package/src/session/redis-store.ts +0 -93
  121. package/src/streaming/index.ts +0 -17
  122. package/src/streaming/sse-handler.ts +0 -482
  123. package/src/streaming/stream-handler.ts +0 -552
  124. package/src/testing/auth-testing.ts +0 -448
  125. package/src/testing/file-upload-testing.ts +0 -543
  126. package/src/testing/index.ts +0 -10
  127. package/src/testing/middleware-testing.ts +0 -322
  128. package/src/testing/model-binding-testing.ts +0 -645
  129. package/src/testing/performance-testing.ts +0 -738
  130. package/src/testing/test-client.ts +0 -310
  131. package/src/testing/test-request.ts +0 -315
  132. package/src/testing/test-response.ts +0 -332
  133. package/src/testing/types.ts +0 -224
  134. package/src/testing/websocket-testing.ts +0 -590
  135. package/src/types/controller-types.ts +0 -385
  136. package/src/types/core.ts +0 -683
  137. package/src/types/middleware-types.ts +0 -422
  138. package/src/types/request-response-augmentation.ts +0 -489
  139. package/src/types/route-inference.ts +0 -372
  140. package/src/types.ts +0 -2123
  141. package/src/url.ts +0 -131
  142. package/src/utils/index.ts +0 -1
  143. package/src/utils/query-preservation.ts +0 -201
  144. package/src/utils.ts +0 -395
  145. package/src/validation/validator.ts +0 -688
  146. package/src/websocket/clustering.ts +0 -769
@@ -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
- }