@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.
- package/CHANGELOG.md +770 -0
- package/README.md +584 -261
- package/package.json +43 -47
- package/bin/cli.ts +0 -9
- package/dist/auth.d.ts +0 -134
- package/dist/cache/lru-cache.d.ts +0 -139
- package/dist/cache/middleware-memoization.d.ts +0 -151
- package/dist/cache/route-cache-warmer.d.ts +0 -161
- package/dist/cache/sqlite-cache.d.ts +0 -209
- package/dist/cache/streaming-cache.d.ts +0 -132
- package/dist/chunk-1mvtv6jw.js +0 -13012
- package/dist/cli/colors.d.ts +0 -15
- package/dist/cli/index.d.ts +0 -10
- package/dist/cli/middleware.d.ts +0 -31
- package/dist/cli/openapi.d.ts +0 -17
- package/dist/cli/router.d.ts +0 -15
- package/dist/cli/routes.d.ts +0 -29
- package/dist/cli/utils.d.ts +0 -74
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +0 -3195
- package/dist/config.d.ts +0 -7
- package/dist/container/container.d.ts +0 -273
- package/dist/container/contextual-binding.d.ts +0 -240
- package/dist/container/decorators.d.ts +0 -141
- package/dist/container/service-provider.d.ts +0 -285
- package/dist/development/hot-reload.d.ts +0 -187
- package/dist/development/index.d.ts +0 -167
- package/dist/development/performance-profiler.d.ts +0 -217
- package/dist/development/route-debugger.d.ts +0 -154
- package/dist/development/route-inspector.d.ts +0 -211
- package/dist/development/typescript-utilities.d.ts +0 -209
- package/dist/docs.d.ts +0 -11
- package/dist/errors/circuit-breaker.d.ts +0 -195
- package/dist/errors/error-handler.d.ts +0 -88
- package/dist/errors/error-reporting.d.ts +0 -144
- package/dist/errors/exceptions.d.ts +0 -184
- package/dist/errors/graceful-degradation.d.ts +0 -154
- package/dist/errors/index.d.ts +0 -9
- package/dist/errors/router-errors.d.ts +0 -110
- package/dist/file-serving/static-files.d.ts +0 -143
- package/dist/index.d.ts +0 -14
- package/dist/index.js +0 -13933
- package/dist/middleware/auth.d.ts +0 -63
- package/dist/middleware/content_security_policy.d.ts +0 -53
- package/dist/middleware/cors.d.ts +0 -5
- package/dist/middleware/csrf.d.ts +0 -7
- package/dist/middleware/ddos_protection.d.ts +0 -39
- package/dist/middleware/file_security.d.ts +0 -26
- package/dist/middleware/file_upload.d.ts +0 -38
- package/dist/middleware/helmet.d.ts +0 -54
- package/dist/middleware/index.d.ts +0 -44
- package/dist/middleware/input_validation.d.ts +0 -45
- package/dist/middleware/json_body.d.ts +0 -4
- package/dist/middleware/performance_alerting.d.ts +0 -87
- package/dist/middleware/performance_dashboard.d.ts +0 -87
- package/dist/middleware/performance_monitor.d.ts +0 -209
- package/dist/middleware/pipeline.d.ts +0 -131
- package/dist/middleware/rate_limit.d.ts +0 -36
- package/dist/middleware/request_id.d.ts +0 -4
- package/dist/middleware/request_signing.d.ts +0 -153
- package/dist/middleware/request_tracer.d.ts +0 -72
- package/dist/middleware/response_cache.d.ts +0 -97
- package/dist/middleware/security.d.ts +0 -69
- package/dist/middleware/security_suite.d.ts +0 -46
- package/dist/middleware/session.d.ts +0 -23
- package/dist/model-binding/index.d.ts +0 -2
- package/dist/model-binding/model-middleware.d.ts +0 -118
- package/dist/model-binding/model-registry.d.ts +0 -164
- package/dist/model-binding.d.ts +0 -185
- package/dist/model-resolver-factory.d.ts +0 -31
- package/dist/observability/correlation.d.ts +0 -187
- package/dist/observability/health-checks.d.ts +0 -186
- package/dist/observability/index.d.ts +0 -60
- package/dist/observability/integration.d.ts +0 -147
- package/dist/observability/metrics.d.ts +0 -184
- package/dist/observability/tracing.d.ts +0 -187
- package/dist/optimization/bun-utilities.d.ts +0 -224
- package/dist/query-builder-integration.d.ts +0 -36
- package/dist/request/context.d.ts +0 -34
- package/dist/request/enhanced-request.d.ts +0 -213
- package/dist/request/macros.d.ts +0 -300
- package/dist/response/macros.d.ts +0 -245
- package/dist/response/response-factory.d.ts +0 -133
- package/dist/router/api-routes.d.ts +0 -5
- package/dist/router/file-based-routing.d.ts +0 -118
- package/dist/router/file-streaming.d.ts +0 -5
- package/dist/router/fluent-router.d.ts +0 -315
- package/dist/router/fluent-routing.d.ts +0 -271
- package/dist/router/group-organization.d.ts +0 -5
- package/dist/router/handler-resolver.d.ts +0 -24
- package/dist/router/http-methods.d.ts +0 -10
- package/dist/router/index.d.ts +0 -114
- package/dist/router/middleware-groups.d.ts +0 -94
- package/dist/router/middleware-integration.d.ts +0 -112
- package/dist/router/middleware.d.ts +0 -5
- package/dist/router/model-binding.d.ts +0 -5
- package/dist/router/optimized-route-matching.d.ts +0 -6
- package/dist/router/route-building.d.ts +0 -5
- package/dist/router/route-compiler.d.ts +0 -153
- package/dist/router/route-matching.d.ts +0 -5
- package/dist/router/route-trie.d.ts +0 -114
- package/dist/router/router.d.ts +0 -294
- package/dist/router/server.d.ts +0 -5
- package/dist/router/validation-integration.d.ts +0 -170
- package/dist/router/view-rendering.d.ts +0 -5
- package/dist/router/websocket.d.ts +0 -5
- package/dist/routing/route-caching.d.ts +0 -129
- package/dist/routing/route-throttling.d.ts +0 -150
- package/dist/routing/subdomain-routing.d.ts +0 -206
- package/dist/session/database-store.d.ts +0 -51
- package/dist/session/file-store.d.ts +0 -22
- package/dist/session/index.d.ts +0 -106
- package/dist/session/memory-store.d.ts +0 -21
- package/dist/session/redis-store.d.ts +0 -31
- package/dist/streaming/index.d.ts +0 -3
- package/dist/streaming/sse-handler.d.ts +0 -138
- package/dist/streaming/stream-handler.d.ts +0 -114
- package/dist/testing/auth-testing.d.ts +0 -156
- package/dist/testing/file-upload-testing.d.ts +0 -190
- package/dist/testing/index.d.ts +0 -10
- package/dist/testing/middleware-testing.d.ts +0 -138
- package/dist/testing/model-binding-testing.d.ts +0 -186
- package/dist/testing/performance-testing.d.ts +0 -235
- package/dist/testing/test-client.d.ts +0 -117
- package/dist/testing/test-request.d.ts +0 -85
- package/dist/testing/test-response.d.ts +0 -90
- package/dist/testing/types.d.ts +0 -207
- package/dist/testing/websocket-testing.d.ts +0 -227
- package/dist/types/controller-types.d.ts +0 -208
- package/dist/types/core.d.ts +0 -543
- package/dist/types/middleware-types.d.ts +0 -227
- package/dist/types/request-response-augmentation.d.ts +0 -261
- package/dist/types/route-inference.d.ts +0 -168
- package/dist/types.d.ts +0 -1782
- package/dist/url.d.ts +0 -56
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/query-preservation.d.ts +0 -48
- package/dist/utils.d.ts +0 -69
- package/dist/validation/validator.d.ts +0 -140
- package/dist/websocket/clustering.d.ts +0 -185
- package/src/auth.ts +0 -469
- package/src/cache/lru-cache.ts +0 -457
- package/src/cache/middleware-memoization.ts +0 -531
- package/src/cache/route-cache-warmer.ts +0 -486
- package/src/cache/sqlite-cache.ts +0 -783
- package/src/cache/streaming-cache.ts +0 -572
- package/src/cli/colors.ts +0 -29
- package/src/cli/index.ts +0 -287
- package/src/cli/middleware.ts +0 -291
- package/src/cli/openapi.ts +0 -407
- package/src/cli/router.ts +0 -188
- package/src/cli/routes.ts +0 -265
- package/src/cli/utils.ts +0 -531
- package/src/cli.ts +0 -5
- package/src/config.ts +0 -322
- package/src/container/container.ts +0 -740
- package/src/container/contextual-binding.ts +0 -603
- package/src/container/decorators.ts +0 -359
- package/src/container/service-provider.ts +0 -596
- package/src/development/hot-reload.ts +0 -673
- package/src/development/index.ts +0 -499
- package/src/development/performance-profiler.ts +0 -717
- package/src/development/route-debugger.ts +0 -527
- package/src/development/route-inspector.ts +0 -749
- package/src/development/typescript-utilities.ts +0 -682
- package/src/docs.ts +0 -397
- package/src/errors/circuit-breaker.ts +0 -732
- package/src/errors/error-handler.ts +0 -569
- package/src/errors/error-reporting.ts +0 -672
- package/src/errors/exceptions.ts +0 -536
- package/src/errors/graceful-degradation.ts +0 -621
- package/src/errors/index.ts +0 -21
- package/src/errors/router-errors.ts +0 -632
- package/src/file-serving/static-files.ts +0 -581
- package/src/index.ts +0 -14
- package/src/middleware/auth.ts +0 -219
- package/src/middleware/content_security_policy.ts +0 -215
- package/src/middleware/cors.ts +0 -74
- package/src/middleware/csrf.ts +0 -108
- package/src/middleware/ddos_protection.ts +0 -255
- package/src/middleware/file_security.ts +0 -191
- package/src/middleware/file_upload.ts +0 -264
- package/src/middleware/helmet.ts +0 -268
- package/src/middleware/index.ts +0 -117
- package/src/middleware/input_validation.ts +0 -449
- package/src/middleware/json_body.ts +0 -37
- package/src/middleware/performance_alerting.ts +0 -538
- package/src/middleware/performance_dashboard.ts +0 -661
- package/src/middleware/performance_monitor.ts +0 -943
- package/src/middleware/pipeline.ts +0 -489
- package/src/middleware/rate_limit.ts +0 -245
- package/src/middleware/request_id.ts +0 -36
- package/src/middleware/request_signing.ts +0 -636
- package/src/middleware/request_tracer.ts +0 -636
- package/src/middleware/response_cache.ts +0 -743
- package/src/middleware/security.ts +0 -482
- package/src/middleware/security_suite.ts +0 -257
- package/src/middleware/session.ts +0 -91
- package/src/model-binding/index.ts +0 -18
- package/src/model-binding/model-middleware.ts +0 -425
- package/src/model-binding/model-registry.ts +0 -550
- package/src/model-binding.ts +0 -370
- package/src/model-resolver-factory.ts +0 -106
- package/src/observability/correlation.ts +0 -691
- package/src/observability/health-checks.ts +0 -729
- package/src/observability/index.ts +0 -184
- package/src/observability/integration.ts +0 -548
- package/src/observability/metrics.ts +0 -753
- package/src/observability/tracing.ts +0 -638
- package/src/optimization/bun-utilities.ts +0 -778
- package/src/query-builder-integration.ts +0 -137
- package/src/request/context.ts +0 -62
- package/src/request/enhanced-request.ts +0 -857
- package/src/request/macros.ts +0 -688
- package/src/response/macros.ts +0 -612
- package/src/response/response-factory.ts +0 -596
- package/src/router/api-routes.ts +0 -243
- package/src/router/file-based-routing.ts +0 -670
- package/src/router/file-streaming.ts +0 -372
- package/src/router/fluent-router.ts +0 -927
- package/src/router/fluent-routing.ts +0 -797
- package/src/router/group-organization.ts +0 -213
- package/src/router/handler-resolver.ts +0 -291
- package/src/router/http-methods.ts +0 -377
- package/src/router/index.ts +0 -187
- package/src/router/middleware-groups.ts +0 -222
- package/src/router/middleware-integration.ts +0 -399
- package/src/router/middleware.ts +0 -231
- package/src/router/model-binding.ts +0 -215
- package/src/router/optimized-route-matching.ts +0 -253
- package/src/router/route-building.ts +0 -212
- package/src/router/route-compiler.ts +0 -702
- package/src/router/route-matching.ts +0 -349
- package/src/router/route-trie.ts +0 -464
- package/src/router/router.ts +0 -1581
- package/src/router/server.ts +0 -462
- package/src/router/validation-integration.ts +0 -443
- package/src/router/view-rendering.ts +0 -233
- package/src/router/websocket.ts +0 -100
- package/src/routing/route-caching.ts +0 -402
- package/src/routing/route-throttling.ts +0 -469
- package/src/routing/subdomain-routing.ts +0 -492
- package/src/session/database-store.ts +0 -109
- package/src/session/file-store.ts +0 -148
- package/src/session/index.ts +0 -244
- package/src/session/memory-store.ts +0 -88
- package/src/session/redis-store.ts +0 -93
- package/src/streaming/index.ts +0 -17
- package/src/streaming/sse-handler.ts +0 -482
- package/src/streaming/stream-handler.ts +0 -552
- package/src/testing/auth-testing.ts +0 -446
- package/src/testing/file-upload-testing.ts +0 -543
- package/src/testing/index.ts +0 -10
- package/src/testing/middleware-testing.ts +0 -322
- package/src/testing/model-binding-testing.ts +0 -645
- package/src/testing/performance-testing.ts +0 -738
- package/src/testing/test-client.ts +0 -310
- package/src/testing/test-request.ts +0 -315
- package/src/testing/test-response.ts +0 -332
- package/src/testing/types.ts +0 -224
- package/src/testing/websocket-testing.ts +0 -590
- package/src/types/controller-types.ts +0 -385
- package/src/types/core.ts +0 -683
- package/src/types/middleware-types.ts +0 -419
- package/src/types/request-response-augmentation.ts +0 -489
- package/src/types/route-inference.ts +0 -357
- package/src/types.ts +0 -2055
- package/src/url.ts +0 -126
- package/src/utils/index.ts +0 -1
- package/src/utils/query-preservation.ts +0 -201
- package/src/utils.ts +0 -327
- package/src/validation/validator.ts +0 -685
- package/src/websocket/clustering.ts +0 -762
package/src/cli/utils.ts
DELETED
|
@@ -1,531 +0,0 @@
|
|
|
1
|
-
import process from 'node:process'
|
|
2
|
-
import { chalk } from './colors'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Formats console output with consistent styling
|
|
6
|
-
*/
|
|
7
|
-
export const format = {
|
|
8
|
-
success: (message: string): string => chalk.green(`✨ ${message}`),
|
|
9
|
-
info: (message: string): string => chalk.blue(message),
|
|
10
|
-
warning: (message: string): string => chalk.yellow(message),
|
|
11
|
-
error: (message: string): string => chalk.red(message),
|
|
12
|
-
dim: (message: string): string => chalk.dim(message),
|
|
13
|
-
bold: (message: string): string => chalk.bold(message),
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Logger for CLI commands with consistent styling
|
|
18
|
-
*/
|
|
19
|
-
export const logger = {
|
|
20
|
-
success: (message: string): void => console.log(format.success(message)),
|
|
21
|
-
info: (message: string): void => console.log(format.info(message)),
|
|
22
|
-
warning: (message: string): void => console.log(format.warning(message)),
|
|
23
|
-
error: (message: string): void => console.error(format.error(message)),
|
|
24
|
-
debug: (message: string): void => console.debug(format.dim(message)),
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Load router instance from the application
|
|
29
|
-
*/
|
|
30
|
-
export async function loadRouter(): Promise<any> {
|
|
31
|
-
try {
|
|
32
|
-
const routesFile = `${process.cwd()}/routes/index.ts`
|
|
33
|
-
const { router } = await import(routesFile)
|
|
34
|
-
|
|
35
|
-
if (!router) {
|
|
36
|
-
logger.error(`Could not find router instance in ${routesFile}.`)
|
|
37
|
-
process.exit(1)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return router
|
|
41
|
-
}
|
|
42
|
-
catch (error: any) {
|
|
43
|
-
if (error.code === 'ERR_MODULE_NOT_FOUND') {
|
|
44
|
-
logger.error(`Routes file not found at ${process.cwd()}/routes/index.ts`)
|
|
45
|
-
logger.warning('Make sure your routes are defined and exported as "router" in routes/index.ts')
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
logger.error(`Error loading router: ${error.message}`)
|
|
49
|
-
}
|
|
50
|
-
throw error
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Setup a debounced file watcher
|
|
56
|
-
*/
|
|
57
|
-
export function setupDebouncedWatcher(
|
|
58
|
-
_callback: () => Promise<void>,
|
|
59
|
-
_debounceTime = 500,
|
|
60
|
-
): { timeoutId: NodeJS.Timeout | null } {
|
|
61
|
-
const state = { timeoutId: null as NodeJS.Timeout | null }
|
|
62
|
-
|
|
63
|
-
return state
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Utility to get method color for console output
|
|
68
|
-
*/
|
|
69
|
-
export function getMethodColor(method: string): string {
|
|
70
|
-
switch (method.toUpperCase()) {
|
|
71
|
-
case 'GET':
|
|
72
|
-
return chalk.cyan.toString()
|
|
73
|
-
case 'POST':
|
|
74
|
-
return chalk.green.toString()
|
|
75
|
-
case 'PUT':
|
|
76
|
-
return chalk.yellow.toString()
|
|
77
|
-
case 'PATCH':
|
|
78
|
-
return chalk.yellow.toString()
|
|
79
|
-
case 'DELETE':
|
|
80
|
-
return chalk.red.toString()
|
|
81
|
-
case 'OPTIONS':
|
|
82
|
-
return chalk.gray.toString()
|
|
83
|
-
default:
|
|
84
|
-
return chalk.white.toString()
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Pad a string to a specified length
|
|
90
|
-
*/
|
|
91
|
-
export function padString(str: string, length: number): string {
|
|
92
|
-
return (str + ' '.repeat(length)).substring(0, length)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Check router health and configuration
|
|
97
|
-
*/
|
|
98
|
-
export async function checkRouterHealth(options: { verbose?: boolean }): Promise<void> {
|
|
99
|
-
logger.info('🔍 Checking router health...')
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
const router = await loadRouter()
|
|
103
|
-
const routes = router.routes || []
|
|
104
|
-
const globalMiddleware = router.globalMiddleware || []
|
|
105
|
-
const namedRoutes = router.namedRoutes || new Map()
|
|
106
|
-
|
|
107
|
-
// Basic health metrics
|
|
108
|
-
const health = {
|
|
109
|
-
totalRoutes: routes.length,
|
|
110
|
-
namedRoutes: namedRoutes.size,
|
|
111
|
-
globalMiddleware: globalMiddleware.length,
|
|
112
|
-
routesByMethod: {} as Record<string, number>,
|
|
113
|
-
duplicateRoutes: [] as Array<{ path: string, method: string }>,
|
|
114
|
-
routesWithMiddleware: 0,
|
|
115
|
-
staticRoutes: 0,
|
|
116
|
-
dynamicRoutes: 0,
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Analyze routes
|
|
120
|
-
const routeMap = new Map<string, string[]>()
|
|
121
|
-
for (const route of routes) {
|
|
122
|
-
const key = `${route.method}:${route.path}`
|
|
123
|
-
|
|
124
|
-
// Count by method
|
|
125
|
-
health.routesByMethod[route.method] = (health.routesByMethod[route.method] || 0) + 1
|
|
126
|
-
|
|
127
|
-
// Check for duplicates
|
|
128
|
-
if (!routeMap.has(key)) {
|
|
129
|
-
routeMap.set(key, [])
|
|
130
|
-
}
|
|
131
|
-
routeMap.get(key)!.push(route.path)
|
|
132
|
-
|
|
133
|
-
if (routeMap.get(key)!.length > 1) {
|
|
134
|
-
health.duplicateRoutes.push({ path: route.path, method: route.method })
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Count middleware usage
|
|
138
|
-
if (route.middleware && route.middleware.length > 0) {
|
|
139
|
-
health.routesWithMiddleware++
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Count static vs dynamic routes
|
|
143
|
-
if (route.path.includes('{') || route.path.includes('*')) {
|
|
144
|
-
health.dynamicRoutes++
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
health.staticRoutes++
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Display results
|
|
152
|
-
logger.success(`Router health check completed`)
|
|
153
|
-
console.log(`📊 Routes: ${health.totalRoutes} total (${health.staticRoutes} static, ${health.dynamicRoutes} dynamic)`)
|
|
154
|
-
console.log(`📛 Named routes: ${health.namedRoutes}`)
|
|
155
|
-
console.log(`🛡️ Global middleware: ${health.globalMiddleware}`)
|
|
156
|
-
console.log(`🔧 Routes with middleware: ${health.routesWithMiddleware}`)
|
|
157
|
-
|
|
158
|
-
if (options.verbose) {
|
|
159
|
-
console.log('\n📈 Routes by method:')
|
|
160
|
-
for (const [method, count] of Object.entries(health.routesByMethod)) {
|
|
161
|
-
const color = getMethodColor(method)
|
|
162
|
-
console.log(` ${chalk.hex(color)(method.padEnd(8))}: ${count}`)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (health.duplicateRoutes.length > 0) {
|
|
166
|
-
logger.warning(`\n⚠️ Found ${health.duplicateRoutes.length} duplicate route(s):`)
|
|
167
|
-
for (const duplicate of health.duplicateRoutes) {
|
|
168
|
-
console.log(` ${duplicate.method} ${duplicate.path}`)
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Check for potential issues
|
|
173
|
-
const issues = []
|
|
174
|
-
if (health.totalRoutes === 0) {
|
|
175
|
-
issues.push('No routes defined')
|
|
176
|
-
}
|
|
177
|
-
if (health.duplicateRoutes.length > 0) {
|
|
178
|
-
issues.push(`${health.duplicateRoutes.length} duplicate routes`)
|
|
179
|
-
}
|
|
180
|
-
if (health.routesWithMiddleware === 0 && health.globalMiddleware === 0) {
|
|
181
|
-
issues.push('No middleware configured')
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (issues.length > 0) {
|
|
185
|
-
logger.warning('\n⚠️ Potential issues:')
|
|
186
|
-
for (const issue of issues) {
|
|
187
|
-
console.log(` • ${issue}`)
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
logger.success('\n✅ No issues detected')
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
catch (error: any) {
|
|
196
|
-
logger.error(`Health check failed: ${error.message}`)
|
|
197
|
-
throw error
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Test routes by making HTTP requests
|
|
203
|
-
*/
|
|
204
|
-
export async function testRoutes(options: {
|
|
205
|
-
baseUrl?: string
|
|
206
|
-
filter?: string
|
|
207
|
-
method?: string
|
|
208
|
-
timeout?: number
|
|
209
|
-
}): Promise<void> {
|
|
210
|
-
const baseUrl = options.baseUrl || 'http://localhost:3000'
|
|
211
|
-
const timeout = options.timeout || 5000
|
|
212
|
-
const allowedMethods = options.method ? options.method.split(',').map(m => m.trim().toUpperCase()) : null
|
|
213
|
-
|
|
214
|
-
logger.info(`🧪 Testing routes at ${baseUrl}...`)
|
|
215
|
-
|
|
216
|
-
try {
|
|
217
|
-
const router = await loadRouter()
|
|
218
|
-
const routes = router.routes || []
|
|
219
|
-
|
|
220
|
-
let filteredRoutes = routes
|
|
221
|
-
|
|
222
|
-
// Filter by path pattern
|
|
223
|
-
if (options.filter) {
|
|
224
|
-
const pattern = new RegExp(options.filter.replace(/\*/g, '.*'))
|
|
225
|
-
filteredRoutes = routes.filter((route: any) => pattern.test(route.path))
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Filter by method
|
|
229
|
-
if (allowedMethods) {
|
|
230
|
-
filteredRoutes = filteredRoutes.filter((route: any) => allowedMethods.includes(route.method))
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
if (filteredRoutes.length === 0) {
|
|
234
|
-
logger.warning('No routes match the specified filters')
|
|
235
|
-
return
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
logger.info(`Testing ${filteredRoutes.length} routes...`)
|
|
239
|
-
|
|
240
|
-
const results = {
|
|
241
|
-
total: 0,
|
|
242
|
-
passed: 0,
|
|
243
|
-
failed: 0,
|
|
244
|
-
errors: [] as Array<{ route: string, error: string }>,
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
for (const route of filteredRoutes) {
|
|
248
|
-
results.total++
|
|
249
|
-
|
|
250
|
-
// Skip routes with parameters for now (would need parameter generation)
|
|
251
|
-
if (route.path.includes('{')) {
|
|
252
|
-
logger.debug(`Skipping parameterized route: ${route.method} ${route.path}`)
|
|
253
|
-
continue
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
try {
|
|
257
|
-
const url = `${baseUrl}${route.path}`
|
|
258
|
-
const response = await fetch(url, {
|
|
259
|
-
method: route.method,
|
|
260
|
-
signal: AbortSignal.timeout(timeout),
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
if (response.status < 500) {
|
|
264
|
-
results.passed++
|
|
265
|
-
logger.debug(`✅ ${route.method} ${route.path} → ${response.status}`)
|
|
266
|
-
}
|
|
267
|
-
else {
|
|
268
|
-
results.failed++
|
|
269
|
-
results.errors.push({
|
|
270
|
-
route: `${route.method} ${route.path}`,
|
|
271
|
-
error: `HTTP ${response.status}`,
|
|
272
|
-
})
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
catch (error: any) {
|
|
276
|
-
results.failed++
|
|
277
|
-
results.errors.push({
|
|
278
|
-
route: `${route.method} ${route.path}`,
|
|
279
|
-
error: error.message,
|
|
280
|
-
})
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Display results
|
|
285
|
-
console.log(`\n📊 Test Results:`)
|
|
286
|
-
console.log(` Total: ${results.total}`)
|
|
287
|
-
console.log(` Passed: ${chalk.green(String(results.passed))}`)
|
|
288
|
-
console.log(` Failed: ${chalk.red(String(results.failed))}`)
|
|
289
|
-
|
|
290
|
-
if (results.errors.length > 0) {
|
|
291
|
-
console.log(`\n❌ Failures:`)
|
|
292
|
-
for (const error of results.errors) {
|
|
293
|
-
console.log(` ${error.route}: ${error.error}`)
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (results.failed > 0) {
|
|
298
|
-
process.exit(1)
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
301
|
-
logger.success('All tests passed!')
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
catch (error: any) {
|
|
305
|
-
logger.error(`Route testing failed: ${error.message}`)
|
|
306
|
-
throw error
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/**
|
|
311
|
-
* Debug route matching for a specific path
|
|
312
|
-
*/
|
|
313
|
-
export async function debugRoute(path: string, options: {
|
|
314
|
-
method?: string
|
|
315
|
-
verbose?: boolean
|
|
316
|
-
}): Promise<void> {
|
|
317
|
-
const method = options.method?.toUpperCase() || 'GET'
|
|
318
|
-
|
|
319
|
-
logger.info(`🔍 Debugging route matching for: ${method} ${path}`)
|
|
320
|
-
|
|
321
|
-
try {
|
|
322
|
-
const router = await loadRouter()
|
|
323
|
-
|
|
324
|
-
// Try to match the route
|
|
325
|
-
const match = router.matchRoute ? router.matchRoute(path, method) : null
|
|
326
|
-
|
|
327
|
-
if (match) {
|
|
328
|
-
logger.success(`✅ Route matched!`)
|
|
329
|
-
console.log(` Route: ${match.route.method} ${match.route.path}`)
|
|
330
|
-
console.log(` Handler: ${typeof match.route.handler}`)
|
|
331
|
-
|
|
332
|
-
if (Object.keys(match.params || {}).length > 0) {
|
|
333
|
-
console.log(` Parameters:`)
|
|
334
|
-
for (const [key, value] of Object.entries(match.params)) {
|
|
335
|
-
console.log(` ${key}: ${value}`)
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
if (match.route.middleware && match.route.middleware.length > 0) {
|
|
340
|
-
console.log(` Middleware: ${match.route.middleware.length} handler(s)`)
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
if (match.route.name) {
|
|
344
|
-
console.log(` Named route: ${match.route.name}`)
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
else {
|
|
348
|
-
logger.error(`❌ No route matched for ${method} ${path}`)
|
|
349
|
-
|
|
350
|
-
if (options.verbose) {
|
|
351
|
-
console.log('\n📋 Available routes:')
|
|
352
|
-
const routes = router.routes || []
|
|
353
|
-
const methodRoutes = routes.filter((r: any) => r.method === method)
|
|
354
|
-
|
|
355
|
-
if (methodRoutes.length === 0) {
|
|
356
|
-
console.log(` No routes defined for ${method} method`)
|
|
357
|
-
}
|
|
358
|
-
else {
|
|
359
|
-
for (const route of methodRoutes) {
|
|
360
|
-
console.log(` ${route.method} ${route.path}`)
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
catch (error: any) {
|
|
367
|
-
logger.error(`Route debugging failed: ${error.message}`)
|
|
368
|
-
throw error
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Clear route caches
|
|
374
|
-
*/
|
|
375
|
-
export async function clearCaches(options: { stats?: boolean }): Promise<void> {
|
|
376
|
-
logger.info('🗑️ Clearing route caches...')
|
|
377
|
-
|
|
378
|
-
try {
|
|
379
|
-
const router = await loadRouter()
|
|
380
|
-
|
|
381
|
-
if (options.stats) {
|
|
382
|
-
// Show cache statistics before clearing
|
|
383
|
-
if (router.getCacheStats) {
|
|
384
|
-
const stats = router.getCacheStats()
|
|
385
|
-
console.log('📊 Cache statistics before clearing:')
|
|
386
|
-
console.log(` Hit rate: ${stats.hitRate}%`)
|
|
387
|
-
console.log(` Total hits: ${stats.hits}`)
|
|
388
|
-
console.log(` Total misses: ${stats.misses}`)
|
|
389
|
-
console.log(` Cache size: ${stats.size}`)
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
if (router.routeCache) {
|
|
393
|
-
console.log(` Route cache entries: ${router.routeCache.size}`)
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
if (router.templateCache) {
|
|
397
|
-
console.log(` Template cache entries: ${router.templateCache.size}`)
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// Clear various caches
|
|
402
|
-
if (router.clearRouteCache) {
|
|
403
|
-
router.clearRouteCache()
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
if (router.routeCache && router.routeCache.clear) {
|
|
407
|
-
router.routeCache.clear()
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
if (router.templateCache && router.templateCache.clear) {
|
|
411
|
-
router.templateCache.clear()
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
if (router.clearModelCache) {
|
|
415
|
-
router.clearModelCache()
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
logger.success('✅ Caches cleared successfully')
|
|
419
|
-
}
|
|
420
|
-
catch (error: any) {
|
|
421
|
-
logger.error(`Cache clearing failed: ${error.message}`)
|
|
422
|
-
throw error
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* Validate route definitions and configuration
|
|
428
|
-
*/
|
|
429
|
-
export async function validateRoutes(options: {
|
|
430
|
-
strict?: boolean
|
|
431
|
-
fix?: boolean
|
|
432
|
-
}): Promise<void> {
|
|
433
|
-
logger.info('🔍 Validating route definitions...')
|
|
434
|
-
|
|
435
|
-
try {
|
|
436
|
-
const router = await loadRouter()
|
|
437
|
-
const routes = router.routes || []
|
|
438
|
-
|
|
439
|
-
const issues = []
|
|
440
|
-
const warnings = []
|
|
441
|
-
|
|
442
|
-
// Check each route
|
|
443
|
-
for (const route of routes) {
|
|
444
|
-
// Check for required properties
|
|
445
|
-
if (!route.method) {
|
|
446
|
-
issues.push(`Route missing method: ${route.path}`)
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
if (!route.path) {
|
|
450
|
-
issues.push(`Route missing path: ${route.method || 'UNKNOWN'}`)
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
if (!route.handler) {
|
|
454
|
-
issues.push(`Route missing handler: ${route.method} ${route.path}`)
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
// Validate path format
|
|
458
|
-
if (route.path && !route.path.startsWith('/')) {
|
|
459
|
-
issues.push(`Route path should start with '/': ${route.method} ${route.path}`)
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
// Check for parameter syntax issues
|
|
463
|
-
if (route.path && route.path.includes('{')) {
|
|
464
|
-
const params = route.path.match(/\{[^}]+\}/g) || []
|
|
465
|
-
for (const param of params) {
|
|
466
|
-
if (!param.match(/^\{[a-z_]\w*(\?|:[^}]+)?\}$/i)) {
|
|
467
|
-
issues.push(`Invalid parameter syntax in ${route.method} ${route.path}: ${param}`)
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
// Strict mode validations
|
|
473
|
-
if (options.strict) {
|
|
474
|
-
// Check for missing route names on important routes
|
|
475
|
-
if (!route.name && !route.path.includes('{') && route.path !== '/') {
|
|
476
|
-
warnings.push(`Consider adding a name to route: ${route.method} ${route.path}`)
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// Check for missing middleware on sensitive routes
|
|
480
|
-
if (route.path.includes('/admin') && (!route.middleware || route.middleware.length === 0)) {
|
|
481
|
-
warnings.push(`Admin route missing middleware: ${route.method} ${route.path}`)
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
// Check for duplicate routes
|
|
487
|
-
const routeMap = new Map<string, number>()
|
|
488
|
-
for (const route of routes) {
|
|
489
|
-
const key = `${route.method}:${route.path}`
|
|
490
|
-
routeMap.set(key, (routeMap.get(key) || 0) + 1)
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
for (const [key, count] of routeMap.entries()) {
|
|
494
|
-
if (count > 1) {
|
|
495
|
-
issues.push(`Duplicate route detected: ${key} (${count} times)`)
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
// Display results
|
|
500
|
-
if (issues.length === 0 && warnings.length === 0) {
|
|
501
|
-
logger.success('✅ All route definitions are valid')
|
|
502
|
-
return
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
if (issues.length > 0) {
|
|
506
|
-
logger.error(`❌ Found ${issues.length} validation error(s):`)
|
|
507
|
-
for (const issue of issues) {
|
|
508
|
-
console.log(` • ${issue}`)
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
if (warnings.length > 0) {
|
|
513
|
-
logger.warning(`⚠️ Found ${warnings.length} warning(s):`)
|
|
514
|
-
for (const warning of warnings) {
|
|
515
|
-
console.log(` • ${warning}`)
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
if (options.fix) {
|
|
520
|
-
logger.info('🔧 Auto-fixing is not yet implemented')
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
if (issues.length > 0) {
|
|
524
|
-
process.exit(1)
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
catch (error: any) {
|
|
528
|
-
logger.error(`Route validation failed: ${error.message}`)
|
|
529
|
-
throw error
|
|
530
|
-
}
|
|
531
|
-
}
|