@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,623 +0,0 @@
1
- /**
2
- * Advanced Error Handling - Graceful Degradation
3
- *
4
- * Handles partial failures with fallback mechanisms and service degradation
5
- */
6
-
7
- import type { EnhancedRequest } from '../types'
8
- import type { ErrorContext, RouterException } from './exceptions'
9
-
10
- export interface DegradationConfig {
11
- enabled: boolean
12
- fallbackStrategies: {
13
- [serviceName: string]: FallbackStrategy
14
- }
15
- healthChecks: {
16
- [serviceName: string]: HealthCheckConfig
17
- }
18
- monitoring: {
19
- enabled: boolean
20
- alertThresholds: {
21
- errorRate: number
22
- responseTime: number
23
- availability: number
24
- }
25
- }
26
- }
27
-
28
- export interface FallbackStrategy {
29
- type: 'cache' | 'static' | 'simplified' | 'redirect' | 'custom'
30
- priority: number
31
- timeout: number
32
- retries: number
33
- backoff: {
34
- type: 'fixed' | 'exponential'
35
- delay: number
36
- maxDelay?: number
37
- }
38
- fallbackHandler?: (error: RouterException, context: ErrorContext) => Promise<Response>
39
- cacheConfig?: {
40
- key: string
41
- ttl: number
42
- staleWhileRevalidate: boolean
43
- }
44
- staticResponse?: {
45
- status: number
46
- body: any
47
- headers?: Record<string, string>
48
- }
49
- redirectConfig?: {
50
- url: string
51
- permanent: boolean
52
- }
53
- }
54
-
55
- export interface HealthCheckConfig {
56
- enabled: boolean
57
- endpoint: string
58
- interval: number
59
- timeout: number
60
- retries: number
61
- expectedStatus: number[]
62
- expectedBody?: string | RegExp
63
- headers?: Record<string, string>
64
- onHealthy?: () => void
65
- onUnhealthy?: (error: Error) => void
66
- }
67
-
68
- export interface ServiceHealth {
69
- name: string
70
- status: 'healthy' | 'degraded' | 'unhealthy'
71
- lastCheck: Date
72
- responseTime: number
73
- errorRate: number
74
- availability: number
75
- consecutiveFailures: number
76
- metadata?: Record<string, any>
77
- }
78
-
79
- export interface DegradationContext {
80
- request: EnhancedRequest
81
- serviceName: string
82
- error: RouterException
83
- attemptCount: number
84
- startTime: Date
85
- metadata?: Record<string, any>
86
- }
87
-
88
- /**
89
- * Service health monitor
90
- */
91
- export class ServiceHealthMonitor {
92
- private healthStatus = new Map<string, ServiceHealth>()
93
- private healthCheckIntervals = new Map<string, ReturnType<typeof setInterval>>()
94
- private config: DegradationConfig
95
-
96
- constructor(config: DegradationConfig) {
97
- this.config = config
98
- this.initializeHealthChecks()
99
- }
100
-
101
- private initializeHealthChecks(): void {
102
- for (const [serviceName, healthConfig] of Object.entries(this.config.healthChecks)) {
103
- if (!healthConfig.enabled)
104
- continue
105
-
106
- // Initialize health status
107
- this.healthStatus.set(serviceName, {
108
- name: serviceName,
109
- status: 'healthy',
110
- lastCheck: new Date(),
111
- responseTime: 0,
112
- errorRate: 0,
113
- availability: 100,
114
- consecutiveFailures: 0,
115
- })
116
-
117
- // Start health check interval
118
- const interval = setInterval(
119
- () => this.performHealthCheck(serviceName, healthConfig),
120
- healthConfig.interval,
121
- )
122
- // Health checks must not keep the process alive on shutdown
123
- interval.unref?.()
124
- this.healthCheckIntervals.set(serviceName, interval)
125
- }
126
- }
127
-
128
- private async performHealthCheck(serviceName: string, config: HealthCheckConfig): Promise<void> {
129
- const startTime = Date.now()
130
- let isHealthy = false
131
-
132
- try {
133
- const controller = new AbortController()
134
- const timeoutId = setTimeout(() => controller.abort(), config.timeout)
135
-
136
- const response = await fetch(config.endpoint, {
137
- signal: controller.signal,
138
- headers: config.headers,
139
- method: 'GET',
140
- })
141
-
142
- clearTimeout(timeoutId)
143
-
144
- // Check status code
145
- isHealthy = config.expectedStatus.includes(response.status)
146
-
147
- // Check response body if configured
148
- if (isHealthy && config.expectedBody) {
149
- const body = await response.text()
150
- if (typeof config.expectedBody === 'string') {
151
- isHealthy = body.includes(config.expectedBody)
152
- }
153
- else {
154
- isHealthy = config.expectedBody.test(body)
155
- }
156
- }
157
- }
158
- catch (error) {
159
- console.error(error)
160
- isHealthy = false
161
- }
162
-
163
- const responseTime = Date.now() - startTime
164
- this.updateHealthStatus(serviceName, isHealthy, responseTime)
165
-
166
- // Call health callbacks
167
- if (isHealthy && config.onHealthy) {
168
- config.onHealthy()
169
- }
170
- else if (!isHealthy && config.onUnhealthy) {
171
- config.onUnhealthy(new Error(`Health check failed for ${serviceName}`))
172
- }
173
- }
174
-
175
- private updateHealthStatus(serviceName: string, isHealthy: boolean, responseTime: number): void {
176
- const current = this.healthStatus.get(serviceName)
177
- if (!current)
178
- return
179
-
180
- const updated: ServiceHealth = {
181
- ...current,
182
- lastCheck: new Date(),
183
- responseTime,
184
- consecutiveFailures: isHealthy ? 0 : current.consecutiveFailures + 1,
185
- }
186
-
187
- // Update status based on consecutive failures
188
- if (updated.consecutiveFailures === 0) {
189
- updated.status = 'healthy'
190
- }
191
- else if (updated.consecutiveFailures < 3) {
192
- updated.status = 'degraded'
193
- }
194
- else {
195
- updated.status = 'unhealthy'
196
- }
197
-
198
- // Calculate availability (simple moving average)
199
- const healthyCount = isHealthy ? 1 : 0
200
- updated.availability = (current.availability * 0.9) + (healthyCount * 10)
201
-
202
- this.healthStatus.set(serviceName, updated)
203
- }
204
-
205
- getServiceHealth(serviceName: string): ServiceHealth | undefined {
206
- return this.healthStatus.get(serviceName)
207
- }
208
-
209
- getAllServiceHealth(): ServiceHealth[] {
210
- return Array.from(this.healthStatus.values())
211
- }
212
-
213
- isServiceHealthy(serviceName: string): boolean {
214
- const health = this.healthStatus.get(serviceName)
215
- return health?.status === 'healthy'
216
- }
217
-
218
- isServiceDegraded(serviceName: string): boolean {
219
- const health = this.healthStatus.get(serviceName)
220
- return health?.status === 'degraded'
221
- }
222
-
223
- stop(): void {
224
- for (const interval of this.healthCheckIntervals.values()) {
225
- clearInterval(interval)
226
- }
227
- this.healthCheckIntervals.clear()
228
- }
229
- }
230
-
231
- /**
232
- * Graceful degradation manager
233
- */
234
- export class GracefulDegradationManager {
235
- private config: DegradationConfig
236
- private healthMonitor: ServiceHealthMonitor
237
- private cache = new Map<string, { data: any, expires: Date }>()
238
- private metrics = new Map<string, { requests: number, errors: number, totalTime: number }>()
239
-
240
- constructor(config: DegradationConfig) {
241
- this.config = config
242
- this.healthMonitor = new ServiceHealthMonitor(config)
243
- }
244
-
245
- /**
246
- * Handle service failure with graceful degradation
247
- */
248
- async handleFailure(
249
- serviceName: string,
250
- error: RouterException,
251
- request: EnhancedRequest,
252
- originalHandler: () => Promise<Response>,
253
- ): Promise<Response> {
254
- if (!this.config.enabled) {
255
- throw error
256
- }
257
-
258
- const strategy = this.config.fallbackStrategies[serviceName]
259
- if (!strategy) {
260
- throw error
261
- }
262
-
263
- const context: DegradationContext = {
264
- request,
265
- serviceName,
266
- error,
267
- attemptCount: 1,
268
- startTime: new Date(),
269
- }
270
-
271
- return this.executeFallbackStrategy(strategy, context, originalHandler)
272
- }
273
-
274
- private async executeFallbackStrategy(
275
- strategy: FallbackStrategy,
276
- context: DegradationContext,
277
- originalHandler: () => Promise<Response>,
278
- ): Promise<Response> {
279
- // Try with retries and backoff
280
- if (context.attemptCount <= strategy.retries) {
281
- try {
282
- // Apply backoff delay
283
- if (context.attemptCount > 1) {
284
- const delay = this.calculateBackoffDelay(strategy.backoff, context.attemptCount)
285
- await this.sleep(delay)
286
- }
287
-
288
- // Retry original handler with timeout
289
- const timeoutPromise = new Promise<never>((_, reject) => {
290
- setTimeout(() => reject(new Error('Timeout')), strategy.timeout)
291
- })
292
-
293
- const result = await Promise.race([originalHandler(), timeoutPromise])
294
-
295
- // Success - update metrics and return
296
- this.updateMetrics(context.serviceName, true, Date.now() - context.startTime.getTime())
297
- return result
298
- }
299
- catch (retryError) {
300
- console.error(retryError)
301
- context.attemptCount++
302
- if (context.attemptCount <= strategy.retries) {
303
- return this.executeFallbackStrategy(strategy, context, originalHandler)
304
- }
305
- // Fall through to fallback strategies
306
- }
307
- }
308
-
309
- // Update metrics for failure
310
- this.updateMetrics(context.serviceName, false, Date.now() - context.startTime.getTime())
311
-
312
- // Execute fallback based on strategy type
313
- switch (strategy.type) {
314
- case 'cache':
315
- return this.handleCacheFallback(strategy, context)
316
- case 'static':
317
- return this.handleStaticFallback(strategy, context)
318
- case 'simplified':
319
- return this.handleSimplifiedFallback(strategy, context)
320
- case 'redirect':
321
- return this.handleRedirectFallback(strategy, context)
322
- case 'custom':
323
- return this.handleCustomFallback(strategy, context)
324
- default:
325
- throw context.error
326
- }
327
- }
328
-
329
- private async handleCacheFallback(strategy: FallbackStrategy, context: DegradationContext): Promise<Response> {
330
- if (!strategy.cacheConfig) {
331
- throw context.error
332
- }
333
-
334
- const cacheKey = this.generateCacheKey(strategy.cacheConfig.key, context)
335
- const cached = this.cache.get(cacheKey)
336
-
337
- if (cached && (cached.expires > new Date() || strategy.cacheConfig.staleWhileRevalidate)) {
338
- // Return cached response
339
- const headers = new Headers({
340
- 'Content-Type': 'application/json',
341
- 'X-Cache': 'HIT',
342
- 'X-Degraded': 'true',
343
- 'X-Service-Status': this.healthMonitor.getServiceHealth(context.serviceName)?.status || 'unknown',
344
- })
345
-
346
- if (strategy.cacheConfig.staleWhileRevalidate && cached.expires <= new Date()) {
347
- headers.set('X-Cache', 'STALE')
348
- }
349
-
350
- return new Response(JSON.stringify(cached.data), {
351
- status: 200,
352
- headers,
353
- })
354
- }
355
-
356
- throw context.error
357
- }
358
-
359
- private async handleStaticFallback(strategy: FallbackStrategy, context: DegradationContext): Promise<Response> {
360
- if (!strategy.staticResponse) {
361
- throw context.error
362
- }
363
-
364
- const headers = new Headers(strategy.staticResponse.headers || {})
365
- headers.set('X-Degraded', 'true')
366
- headers.set('X-Fallback-Type', 'static')
367
- headers.set('X-Service-Status', this.healthMonitor.getServiceHealth(context.serviceName)?.status || 'unknown')
368
-
369
- return new Response(
370
- typeof strategy.staticResponse.body === 'string'
371
- ? strategy.staticResponse.body
372
- : JSON.stringify(strategy.staticResponse.body),
373
- {
374
- status: strategy.staticResponse.status,
375
- headers,
376
- },
377
- )
378
- }
379
-
380
- private async handleSimplifiedFallback(strategy: FallbackStrategy, context: DegradationContext): Promise<Response> {
381
- // Return a simplified version of the response
382
- const simplifiedData = {
383
- message: 'Service temporarily unavailable. Showing simplified view.',
384
- status: 'degraded',
385
- timestamp: new Date().toISOString(),
386
- requestId: context.request.requestId,
387
- }
388
-
389
- return new Response(JSON.stringify(simplifiedData), {
390
- status: 200,
391
- headers: {
392
- 'Content-Type': 'application/json',
393
- 'X-Degraded': 'true',
394
- 'X-Fallback-Type': 'simplified',
395
- 'X-Service-Status': this.healthMonitor.getServiceHealth(context.serviceName)?.status || 'unknown',
396
- },
397
- })
398
- }
399
-
400
- private async handleRedirectFallback(strategy: FallbackStrategy, context: DegradationContext): Promise<Response> {
401
- if (!strategy.redirectConfig) {
402
- throw context.error
403
- }
404
-
405
- return new Response(null, {
406
- status: strategy.redirectConfig.permanent ? 301 : 302,
407
- headers: {
408
- 'Location': strategy.redirectConfig.url,
409
- 'X-Degraded': 'true',
410
- 'X-Fallback-Type': 'redirect',
411
- },
412
- })
413
- }
414
-
415
- private async handleCustomFallback(strategy: FallbackStrategy, context: DegradationContext): Promise<Response> {
416
- if (!strategy.fallbackHandler) {
417
- throw context.error
418
- }
419
-
420
- try {
421
- const response = await strategy.fallbackHandler(context.error, context.error.context)
422
-
423
- // Add degradation headers
424
- response.headers.set('X-Degraded', 'true')
425
- response.headers.set('X-Fallback-Type', 'custom')
426
- response.headers.set('X-Service-Status', this.healthMonitor.getServiceHealth(context.serviceName)?.status || 'unknown')
427
-
428
- return response
429
- }
430
- catch (fallbackError) {
431
- console.error(fallbackError)
432
- throw context.error
433
- }
434
- }
435
-
436
- /**
437
- * Cache successful responses for fallback use
438
- */
439
- cacheResponse(serviceName: string, key: string, data: any, ttl: number): void {
440
- const strategy = this.config.fallbackStrategies[serviceName]
441
- if (strategy?.type === 'cache' && strategy.cacheConfig) {
442
- const cacheKey = this.generateCacheKey(key, { serviceName } as DegradationContext)
443
- this.cache.set(cacheKey, {
444
- data,
445
- expires: new Date(Date.now() + ttl * 1000),
446
- })
447
- }
448
- }
449
-
450
- /**
451
- * Get service metrics
452
- */
453
- getServiceMetrics(serviceName: string): { errorRate: number, avgResponseTime: number, totalRequests: number } {
454
- const metrics = this.metrics.get(serviceName)
455
- if (!metrics || metrics.requests === 0) {
456
- return { errorRate: 0, avgResponseTime: 0, totalRequests: 0 }
457
- }
458
-
459
- return {
460
- errorRate: (metrics.errors / metrics.requests) * 100,
461
- avgResponseTime: metrics.totalTime / metrics.requests,
462
- totalRequests: metrics.requests,
463
- }
464
- }
465
-
466
- /**
467
- * Get overall system health
468
- */
469
- getSystemHealth(): { status: 'healthy' | 'degraded' | 'unhealthy', services: ServiceHealth[] } {
470
- const services = this.healthMonitor.getAllServiceHealth()
471
- const unhealthyCount = services.filter(s => s.status === 'unhealthy').length
472
- const degradedCount = services.filter(s => s.status === 'degraded').length
473
-
474
- let status: 'healthy' | 'degraded' | 'unhealthy' = 'healthy'
475
-
476
- if (unhealthyCount > 0) {
477
- status = unhealthyCount > services.length / 2 ? 'unhealthy' : 'degraded'
478
- }
479
- else if (degradedCount > 0) {
480
- status = 'degraded'
481
- }
482
-
483
- return { status, services }
484
- }
485
-
486
- private calculateBackoffDelay(backoff: FallbackStrategy['backoff'], attempt: number): number {
487
- if (backoff.type === 'fixed') {
488
- return backoff.delay
489
- }
490
-
491
- // Exponential backoff
492
- const delay = backoff.delay * 2 ** (attempt - 1)
493
- return Math.min(delay, backoff.maxDelay || 30000)
494
- }
495
-
496
- private generateCacheKey(template: string, context: DegradationContext): string {
497
- return template
498
- .replace('{service}', context.serviceName)
499
- .replace('{url}', context.request.url)
500
- .replace('{method}', context.request.method)
501
- .replace('{userId}', String(context.request.user?.id || 'anonymous'))
502
- }
503
-
504
- private updateMetrics(serviceName: string, success: boolean, responseTime: number): void {
505
- const current = this.metrics.get(serviceName) || { requests: 0, errors: 0, totalTime: 0 }
506
-
507
- current.requests++
508
- current.totalTime += responseTime
509
- if (!success) {
510
- current.errors++
511
- }
512
-
513
- this.metrics.set(serviceName, current)
514
- }
515
-
516
- private sleep(ms: number): Promise<void> {
517
- return new Promise(resolve => setTimeout(resolve, ms))
518
- }
519
-
520
- stop(): void {
521
- this.healthMonitor.stop()
522
- }
523
- }
524
-
525
- /**
526
- * Middleware for graceful degradation
527
- */
528
- export function createGracefulDegradationMiddleware(config: DegradationConfig) {
529
- const manager = new GracefulDegradationManager(config)
530
-
531
- return async (req: EnhancedRequest, next: () => Promise<Response>): Promise<Response> => {
532
- try {
533
- const response = await next()
534
-
535
- // Cache successful responses if configured
536
- const serviceName = req.context?.serviceName as string
537
- if (serviceName && response.ok) {
538
- const strategy = config.fallbackStrategies[serviceName]
539
- if (strategy?.type === 'cache' && strategy.cacheConfig) {
540
- try {
541
- const data = await response.clone().json()
542
- manager.cacheResponse(serviceName, strategy.cacheConfig.key, data, strategy.cacheConfig.ttl)
543
- }
544
- catch {
545
- // Ignore cache errors
546
- }
547
- }
548
- }
549
-
550
- return response
551
- }
552
- catch (error) {
553
- const serviceName = req.context?.serviceName as string
554
-
555
- if (serviceName && error instanceof Error) {
556
- // Convert to RouterException if needed
557
- const routerError = error as RouterException
558
-
559
- try {
560
- return await manager.handleFailure(serviceName, routerError, req, next)
561
- }
562
- catch (fallbackError) {
563
- console.error(fallbackError)
564
- // If all fallbacks fail, throw original error
565
- throw error
566
- }
567
- }
568
-
569
- throw error
570
- }
571
- }
572
- }
573
-
574
- /**
575
- * Factory functions for common degradation strategies
576
- */
577
- export const DegradationStrategies = {
578
- cacheFirst: (ttl: number = 3600, staleWhileRevalidate = true): FallbackStrategy => ({
579
- type: 'cache',
580
- priority: 1,
581
- timeout: 5000,
582
- retries: 2,
583
- backoff: { type: 'exponential', delay: 1000, maxDelay: 5000 },
584
- cacheConfig: {
585
- key: '{service}:{url}:{method}',
586
- ttl,
587
- staleWhileRevalidate,
588
- },
589
- }),
590
-
591
- staticFallback: (body: any, status = 200): FallbackStrategy => ({
592
- type: 'static',
593
- priority: 2,
594
- timeout: 1000,
595
- retries: 0,
596
- backoff: { type: 'fixed', delay: 0 },
597
- staticResponse: {
598
- status,
599
- body,
600
- headers: { 'Content-Type': 'application/json' },
601
- },
602
- }),
603
-
604
- simplifiedView: (): FallbackStrategy => ({
605
- type: 'simplified',
606
- priority: 3,
607
- timeout: 1000,
608
- retries: 0,
609
- backoff: { type: 'fixed', delay: 0 },
610
- }),
611
-
612
- redirectToMaintenance: (url: string): FallbackStrategy => ({
613
- type: 'redirect',
614
- priority: 4,
615
- timeout: 1000,
616
- retries: 0,
617
- backoff: { type: 'fixed', delay: 0 },
618
- redirectConfig: {
619
- url,
620
- permanent: false,
621
- },
622
- }),
623
- }
@@ -1,21 +0,0 @@
1
- /**
2
- * Advanced Error Handling - Main Export File
3
- */
4
-
5
- // Circuit breaker
6
- export * from './circuit-breaker'
7
-
8
- // Main error handler middleware
9
- export { createAdvancedErrorHandler } from './error-handler'
10
-
11
- // Error reporting
12
- export * from './error-reporting'
13
-
14
- // Exception hierarchy
15
- export * from './exceptions'
16
-
17
- // Graceful degradation
18
- export * from './graceful-degradation'
19
-
20
- // Enhanced router errors
21
- export * from './router-errors'