@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
|
@@ -1,797 +0,0 @@
|
|
|
1
|
-
import type { BunQueryBuilderModel } from '../model-binding'
|
|
2
|
-
import type { RouteCacheConfig } from '../routing/route-caching'
|
|
3
|
-
import type { ThrottleConfig } from '../routing/route-throttling'
|
|
4
|
-
import type { EnhancedRequest, MiddlewareHandler, NextFunction, RouteHandler, ThrottlePattern } from '../types'
|
|
5
|
-
import { createModelBindingMiddleware } from '../model-binding'
|
|
6
|
-
import { createRouteCacheMiddleware, RouteCacheFactory } from '../routing/route-caching'
|
|
7
|
-
import { createRateLimitMiddleware, parseThrottleString, ThrottleFactory } from '../routing/route-throttling'
|
|
8
|
-
import { DomainGroup, DomainMatcher, SubdomainRouter } from '../routing/subdomain-routing'
|
|
9
|
-
import { registerNamedRoute } from '../url'
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Fluent route builder with chainable API
|
|
13
|
-
*/
|
|
14
|
-
export class FluentRouteBuilder {
|
|
15
|
-
private middleware: MiddlewareHandler[] = []
|
|
16
|
-
private cacheConfig?: RouteCacheConfig
|
|
17
|
-
private throttleConfig?: ThrottleConfig
|
|
18
|
-
private routeName?: string
|
|
19
|
-
private modelBindings: Record<string, BunQueryBuilderModel> = {}
|
|
20
|
-
|
|
21
|
-
constructor(
|
|
22
|
-
private method: string,
|
|
23
|
-
private path: string,
|
|
24
|
-
private handler: RouteHandler,
|
|
25
|
-
) {}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Add middleware to route
|
|
29
|
-
*/
|
|
30
|
-
addMiddleware(middleware: MiddlewareHandler | MiddlewareHandler[]): this {
|
|
31
|
-
if (Array.isArray(middleware)) {
|
|
32
|
-
this.middleware.push(...middleware)
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
this.middleware.push(middleware)
|
|
36
|
-
}
|
|
37
|
-
return this
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Add route caching with tags
|
|
42
|
-
*/
|
|
43
|
-
cached(tags: string[] = [], config?: Partial<RouteCacheConfig>): this {
|
|
44
|
-
this.cacheConfig = {
|
|
45
|
-
...RouteCacheFactory.api(tags),
|
|
46
|
-
...config,
|
|
47
|
-
}
|
|
48
|
-
return this
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Add route throttling with narrow type checking
|
|
53
|
-
*/
|
|
54
|
-
throttle(limit: ThrottlePattern | ThrottleConfig, _name?: string): this {
|
|
55
|
-
if (typeof limit === 'string') {
|
|
56
|
-
const parsed = parseThrottleString(limit)
|
|
57
|
-
this.throttleConfig = {
|
|
58
|
-
maxAttempts: parsed.maxAttempts ?? 60,
|
|
59
|
-
windowMs: parsed.windowMs,
|
|
60
|
-
keyGenerator: (req: EnhancedRequest) => req.headers.get('x-forwarded-for') || 'anonymous',
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
this.throttleConfig = limit
|
|
65
|
-
}
|
|
66
|
-
return this
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Set route name
|
|
71
|
-
*/
|
|
72
|
-
name(name: string): this {
|
|
73
|
-
this.routeName = name
|
|
74
|
-
return this
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Bind models to route parameters
|
|
79
|
-
*/
|
|
80
|
-
model(parameter: string, model: BunQueryBuilderModel): this {
|
|
81
|
-
this.modelBindings[parameter] = model
|
|
82
|
-
return this
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Build the final route configuration
|
|
87
|
-
*/
|
|
88
|
-
build(): {
|
|
89
|
-
method: string
|
|
90
|
-
path: string
|
|
91
|
-
handler: RouteHandler
|
|
92
|
-
middleware: MiddlewareHandler[]
|
|
93
|
-
name?: string
|
|
94
|
-
} {
|
|
95
|
-
const finalMiddleware: MiddlewareHandler[] = []
|
|
96
|
-
|
|
97
|
-
// Add model binding middleware
|
|
98
|
-
if (Object.keys(this.modelBindings).length > 0) {
|
|
99
|
-
const parameters = Object.keys(this.modelBindings).map(name => ({ name }))
|
|
100
|
-
const modelBindingMiddleware = createModelBindingMiddleware(parameters as any, this.modelBindings as any)
|
|
101
|
-
finalMiddleware.push(modelBindingMiddleware as unknown as MiddlewareHandler)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Add throttling middleware
|
|
105
|
-
if (this.throttleConfig) {
|
|
106
|
-
const throttleMiddleware = createRateLimitMiddleware(this.throttleConfig)
|
|
107
|
-
finalMiddleware.push(throttleMiddleware as MiddlewareHandler)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Add caching middleware
|
|
111
|
-
if (this.cacheConfig) {
|
|
112
|
-
const cacheMiddleware = createRouteCacheMiddleware(this.cacheConfig)
|
|
113
|
-
finalMiddleware.push(cacheMiddleware as MiddlewareHandler)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Add custom middleware
|
|
117
|
-
finalMiddleware.push(...this.middleware)
|
|
118
|
-
|
|
119
|
-
return {
|
|
120
|
-
method: this.method,
|
|
121
|
-
path: this.path,
|
|
122
|
-
handler: this.handler,
|
|
123
|
-
middleware: finalMiddleware,
|
|
124
|
-
name: this.routeName,
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Middleware condition function type
|
|
131
|
-
*/
|
|
132
|
-
export type MiddlewareCondition = (_request: EnhancedRequest) => boolean | Promise<boolean>
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Conditional middleware wrapper
|
|
136
|
-
*/
|
|
137
|
-
export interface ConditionalMiddleware {
|
|
138
|
-
condition: MiddlewareCondition
|
|
139
|
-
middleware: MiddlewareHandler[]
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Builder for conditional middleware
|
|
144
|
-
*/
|
|
145
|
-
export class FluentConditionalBuilder {
|
|
146
|
-
constructor(
|
|
147
|
-
private router: FluentRouter,
|
|
148
|
-
private condition: MiddlewareCondition,
|
|
149
|
-
) {}
|
|
150
|
-
|
|
151
|
-
middleware(middlewareName: string): this {
|
|
152
|
-
const [name, params] = middlewareName.split(':')
|
|
153
|
-
const middlewareFactory = (this.router as any).namedMiddleware.get(name)
|
|
154
|
-
|
|
155
|
-
if (!middlewareFactory) {
|
|
156
|
-
throw new Error(`Unknown middleware: ${name}`)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const middlewareHandler = middlewareFactory(params)
|
|
160
|
-
;(this.router as any).conditionalMiddleware.push({
|
|
161
|
-
condition: this.condition,
|
|
162
|
-
middleware: [middlewareHandler],
|
|
163
|
-
})
|
|
164
|
-
|
|
165
|
-
return this
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Builder for middleware with parameters
|
|
171
|
-
*/
|
|
172
|
-
export class FluentMiddlewareBuilder {
|
|
173
|
-
constructor(
|
|
174
|
-
private router: FluentRouter,
|
|
175
|
-
private middleware: MiddlewareHandler[],
|
|
176
|
-
) {}
|
|
177
|
-
|
|
178
|
-
get(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
179
|
-
return new FluentRouteBuilder('GET', path, handler).addMiddleware(this.middleware)
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
post(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
183
|
-
return new FluentRouteBuilder('POST', path, handler).addMiddleware(this.middleware)
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
put(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
187
|
-
return new FluentRouteBuilder('PUT', path, handler).addMiddleware(this.middleware)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
delete(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
191
|
-
return new FluentRouteBuilder('DELETE', path, handler).addMiddleware(this.middleware)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
patch(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
195
|
-
return new FluentRouteBuilder('PATCH', path, handler).addMiddleware(this.middleware)
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Builder for route groups with middleware
|
|
201
|
-
*/
|
|
202
|
-
export class FluentRouteGroupBuilder {
|
|
203
|
-
constructor(
|
|
204
|
-
private router: FluentRouter,
|
|
205
|
-
private groupMiddleware: MiddlewareHandler[],
|
|
206
|
-
) {}
|
|
207
|
-
|
|
208
|
-
get(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
209
|
-
return new FluentRouteBuilder('GET', path, handler).addMiddleware(this.groupMiddleware)
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
post(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
213
|
-
return new FluentRouteBuilder('POST', path, handler).addMiddleware(this.groupMiddleware)
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
put(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
217
|
-
return new FluentRouteBuilder('PUT', path, handler).addMiddleware(this.groupMiddleware)
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
delete(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
221
|
-
return new FluentRouteBuilder('DELETE', path, handler).addMiddleware(this.groupMiddleware)
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
patch(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
225
|
-
return new FluentRouteBuilder('PATCH', path, handler).addMiddleware(this.groupMiddleware)
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Fluent router with chainable API and advanced features
|
|
231
|
-
*/
|
|
232
|
-
export class FluentRouter {
|
|
233
|
-
private routes: Array<{
|
|
234
|
-
method: string
|
|
235
|
-
path: string
|
|
236
|
-
handler: RouteHandler
|
|
237
|
-
middleware: MiddlewareHandler[]
|
|
238
|
-
name?: string
|
|
239
|
-
}> = []
|
|
240
|
-
|
|
241
|
-
private globalMiddleware: MiddlewareHandler[] = []
|
|
242
|
-
private subdomainRouter = new SubdomainRouter()
|
|
243
|
-
private routeGroups: Array<{
|
|
244
|
-
prefix?: string
|
|
245
|
-
middleware?: MiddlewareHandler[]
|
|
246
|
-
name?: string
|
|
247
|
-
domain?: string
|
|
248
|
-
}> = []
|
|
249
|
-
|
|
250
|
-
// Middleware groups registry
|
|
251
|
-
private middlewareGroups = new Map<string, MiddlewareHandler[]>()
|
|
252
|
-
|
|
253
|
-
// Named middleware registry with parameter support
|
|
254
|
-
private namedMiddleware = new Map<string, (params?: string) => MiddlewareHandler>()
|
|
255
|
-
|
|
256
|
-
// Conditional middleware
|
|
257
|
-
private conditionalMiddleware: ConditionalMiddleware[] = []
|
|
258
|
-
|
|
259
|
-
constructor() {
|
|
260
|
-
this.setupDefaultMiddleware()
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Setup default named middleware with parameter support
|
|
265
|
-
*/
|
|
266
|
-
private setupDefaultMiddleware(): void {
|
|
267
|
-
// Throttle middleware with parameters
|
|
268
|
-
this.namedMiddleware.set('throttle', (params?: string) => {
|
|
269
|
-
const parsed = params ? parseThrottleString(params as ThrottlePattern) : { maxAttempts: 60, windowMs: 60000 }
|
|
270
|
-
const handler = createRateLimitMiddleware({
|
|
271
|
-
maxAttempts: parsed.maxAttempts,
|
|
272
|
-
windowMs: parsed.windowMs,
|
|
273
|
-
keyGenerator: (req: EnhancedRequest) => req.headers.get('x-forwarded-for') || 'anonymous',
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
const adapted: MiddlewareHandler = async (req: EnhancedRequest, next: NextFunction) => {
|
|
277
|
-
const adaptedNext = async () => {
|
|
278
|
-
const res = await next()
|
|
279
|
-
return res ?? new Response(null)
|
|
280
|
-
}
|
|
281
|
-
return await handler(req, adaptedNext)
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
return adapted
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
// Auth middleware
|
|
288
|
-
this.namedMiddleware.set('auth', () => {
|
|
289
|
-
return async (req: EnhancedRequest, next: any) => {
|
|
290
|
-
const token = req.headers.get('Authorization')?.replace('Bearer ', '')
|
|
291
|
-
if (!token) {
|
|
292
|
-
return new Response('Unauthorized', { status: 401 })
|
|
293
|
-
}
|
|
294
|
-
// Mock JWT verification
|
|
295
|
-
;(req as any).user = { id: '123', roles: ['user'] }
|
|
296
|
-
return await next()
|
|
297
|
-
}
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
// CORS middleware
|
|
301
|
-
this.namedMiddleware.set('cors', () => {
|
|
302
|
-
return async (_req: EnhancedRequest, next: any) => {
|
|
303
|
-
const response = await next()
|
|
304
|
-
if (response) {
|
|
305
|
-
const headers = new Headers(response.headers)
|
|
306
|
-
headers.set('Access-Control-Allow-Origin', '*')
|
|
307
|
-
headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
|
|
308
|
-
headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization')
|
|
309
|
-
return new Response(response.body, {
|
|
310
|
-
status: response.status,
|
|
311
|
-
statusText: response.statusText,
|
|
312
|
-
headers,
|
|
313
|
-
})
|
|
314
|
-
}
|
|
315
|
-
return response
|
|
316
|
-
}
|
|
317
|
-
})
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Register a middleware group
|
|
322
|
-
*/
|
|
323
|
-
middlewareGroup(name: string, middlewareNames: string[]): this {
|
|
324
|
-
const middlewareHandlers: MiddlewareHandler[] = []
|
|
325
|
-
|
|
326
|
-
for (const middlewareName of middlewareNames) {
|
|
327
|
-
const [name, params] = middlewareName.split(':')
|
|
328
|
-
const middlewareFactory = this.namedMiddleware.get(name)
|
|
329
|
-
if (middlewareFactory) {
|
|
330
|
-
middlewareHandlers.push(middlewareFactory(params))
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
this.middlewareGroups.set(name, middlewareHandlers)
|
|
335
|
-
return this
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Apply middleware group to routes
|
|
340
|
-
*/
|
|
341
|
-
middlewareGroupRoutes(name: string): FluentRouteGroupBuilder {
|
|
342
|
-
const middlewareHandlers = this.middlewareGroups.get(name) || []
|
|
343
|
-
return new FluentRouteGroupBuilder(this, middlewareHandlers)
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Conditional middleware execution
|
|
348
|
-
*/
|
|
349
|
-
when(condition: MiddlewareCondition): FluentConditionalBuilder {
|
|
350
|
-
return new FluentConditionalBuilder(this, condition)
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Apply middleware with parameters
|
|
355
|
-
*/
|
|
356
|
-
middleware(middlewareName: string): FluentMiddlewareBuilder {
|
|
357
|
-
const [name, params] = middlewareName.split(':')
|
|
358
|
-
const middlewareFactory = this.namedMiddleware.get(name)
|
|
359
|
-
|
|
360
|
-
if (!middlewareFactory) {
|
|
361
|
-
throw new Error(`Unknown middleware: ${name}`)
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const middlewareHandler = middlewareFactory(params)
|
|
365
|
-
return new FluentMiddlewareBuilder(this, [middlewareHandler])
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Add global middleware
|
|
370
|
-
*/
|
|
371
|
-
use(middleware: MiddlewareHandler): this {
|
|
372
|
-
this.globalMiddleware.push(middleware)
|
|
373
|
-
return this
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
/**
|
|
377
|
-
* Create a GET route
|
|
378
|
-
*/
|
|
379
|
-
get(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
380
|
-
return new FluentRouteBuilder('GET', path, handler)
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* Create a POST route
|
|
385
|
-
*/
|
|
386
|
-
post(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
387
|
-
return new FluentRouteBuilder('POST', path, handler)
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* Create a PUT route
|
|
392
|
-
*/
|
|
393
|
-
put(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
394
|
-
return new FluentRouteBuilder('PUT', path, handler)
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* Create a DELETE route
|
|
399
|
-
*/
|
|
400
|
-
delete(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
401
|
-
return new FluentRouteBuilder('DELETE', path, handler)
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* Create a PATCH route
|
|
406
|
-
*/
|
|
407
|
-
patch(path: string, handler: RouteHandler): FluentRouteBuilder {
|
|
408
|
-
return new FluentRouteBuilder('PATCH', path, handler)
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
/**
|
|
412
|
-
* Register a built route
|
|
413
|
-
*/
|
|
414
|
-
register(builder: FluentRouteBuilder): this {
|
|
415
|
-
const route = builder.build()
|
|
416
|
-
this.routes.push(route)
|
|
417
|
-
if (route.name)
|
|
418
|
-
registerNamedRoute(route.name, route.path)
|
|
419
|
-
return this
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Create a cached route
|
|
424
|
-
*/
|
|
425
|
-
cached(tags: string[] = [], config?: Partial<RouteCacheConfig>): {
|
|
426
|
-
get: (path: string, handler: RouteHandler) => FluentRouteBuilder
|
|
427
|
-
post: (path: string, handler: RouteHandler) => FluentRouteBuilder
|
|
428
|
-
put: (path: string, handler: RouteHandler) => FluentRouteBuilder
|
|
429
|
-
delete: (path: string, handler: RouteHandler) => FluentRouteBuilder
|
|
430
|
-
patch: (path: string, handler: RouteHandler) => FluentRouteBuilder
|
|
431
|
-
} {
|
|
432
|
-
return {
|
|
433
|
-
get: (path: string, handler: RouteHandler) =>
|
|
434
|
-
this.get(path, handler).cached(tags, config),
|
|
435
|
-
post: (path: string, handler: RouteHandler) =>
|
|
436
|
-
this.post(path, handler).cached(tags, config),
|
|
437
|
-
put: (path: string, handler: RouteHandler) =>
|
|
438
|
-
this.put(path, handler).cached(tags, config),
|
|
439
|
-
delete: (path: string, handler: RouteHandler) =>
|
|
440
|
-
this.delete(path, handler).cached(tags, config),
|
|
441
|
-
patch: (path: string, handler: RouteHandler) =>
|
|
442
|
-
this.patch(path, handler).cached(tags, config),
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* Create a throttled route
|
|
448
|
-
*/
|
|
449
|
-
throttled(limit: ThrottlePattern | ThrottleConfig): {
|
|
450
|
-
get: (path: string, handler: RouteHandler) => FluentRouteBuilder
|
|
451
|
-
post: (path: string, handler: RouteHandler) => FluentRouteBuilder
|
|
452
|
-
put: (path: string, handler: RouteHandler) => FluentRouteBuilder
|
|
453
|
-
delete: (path: string, handler: RouteHandler) => FluentRouteBuilder
|
|
454
|
-
patch: (path: string, handler: RouteHandler) => FluentRouteBuilder
|
|
455
|
-
} {
|
|
456
|
-
return {
|
|
457
|
-
get: (path: string, handler: RouteHandler) =>
|
|
458
|
-
this.get(path, handler).throttle(limit),
|
|
459
|
-
post: (path: string, handler: RouteHandler) =>
|
|
460
|
-
this.post(path, handler).throttle(limit),
|
|
461
|
-
put: (path: string, handler: RouteHandler) =>
|
|
462
|
-
this.put(path, handler).throttle(limit),
|
|
463
|
-
delete: (path: string, handler: RouteHandler) =>
|
|
464
|
-
this.delete(path, handler).throttle(limit),
|
|
465
|
-
patch: (path: string, handler: RouteHandler) =>
|
|
466
|
-
this.patch(path, handler).throttle(limit),
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
/**
|
|
471
|
-
* Create route group with shared attributes
|
|
472
|
-
*/
|
|
473
|
-
group(
|
|
474
|
-
config: {
|
|
475
|
-
prefix?: string
|
|
476
|
-
middleware?: MiddlewareHandler[]
|
|
477
|
-
name?: string
|
|
478
|
-
domain?: string
|
|
479
|
-
},
|
|
480
|
-
callback: (router: FluentRouter) => void,
|
|
481
|
-
): this {
|
|
482
|
-
const groupRouter = new FluentRouter()
|
|
483
|
-
callback(groupRouter)
|
|
484
|
-
|
|
485
|
-
for (const route of groupRouter.routes) {
|
|
486
|
-
const groupedRoute = {
|
|
487
|
-
...route,
|
|
488
|
-
path: config.prefix ? `${config.prefix}${route.path}` : route.path,
|
|
489
|
-
middleware: [
|
|
490
|
-
...(config.middleware || []),
|
|
491
|
-
...route.middleware,
|
|
492
|
-
],
|
|
493
|
-
name: config.name && route.name ? `${config.name}.${route.name}` : route.name,
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
if (config.domain) {
|
|
497
|
-
const domainPattern = DomainMatcher.parseDomainPattern(config.domain)
|
|
498
|
-
const domainGroup = new DomainGroup(domainPattern, { domain: config.domain })
|
|
499
|
-
domainGroup.addRoute(
|
|
500
|
-
groupedRoute.method,
|
|
501
|
-
groupedRoute.path,
|
|
502
|
-
groupedRoute.handler,
|
|
503
|
-
groupedRoute.middleware,
|
|
504
|
-
groupedRoute.name,
|
|
505
|
-
)
|
|
506
|
-
this.subdomainRouter.addDomainGroup(domainGroup)
|
|
507
|
-
}
|
|
508
|
-
else {
|
|
509
|
-
this.routes.push(groupedRoute)
|
|
510
|
-
if (groupedRoute.name)
|
|
511
|
-
registerNamedRoute(groupedRoute.name, groupedRoute.path)
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
return this
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/**
|
|
519
|
-
* Create subdomain routing group
|
|
520
|
-
*/
|
|
521
|
-
domain(pattern: string): {
|
|
522
|
-
routes: (callback: (router: FluentRouter) => void) => FluentRouter
|
|
523
|
-
} {
|
|
524
|
-
return {
|
|
525
|
-
routes: (callback: (router: FluentRouter) => void): FluentRouter => {
|
|
526
|
-
const domainRouter = new FluentRouter()
|
|
527
|
-
callback(domainRouter)
|
|
528
|
-
|
|
529
|
-
const domainPattern = DomainMatcher.parseDomainPattern(pattern)
|
|
530
|
-
const domainGroup = new DomainGroup(domainPattern, { domain: pattern })
|
|
531
|
-
for (const route of domainRouter.routes) {
|
|
532
|
-
domainGroup.addRoute(
|
|
533
|
-
route.method,
|
|
534
|
-
route.path,
|
|
535
|
-
route.handler,
|
|
536
|
-
route.middleware,
|
|
537
|
-
route.name,
|
|
538
|
-
)
|
|
539
|
-
}
|
|
540
|
-
this.subdomainRouter.addDomainGroup(domainGroup)
|
|
541
|
-
|
|
542
|
-
return this
|
|
543
|
-
},
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
/**
|
|
548
|
-
* Create resource routes (Laravel-style)
|
|
549
|
-
*/
|
|
550
|
-
resource(name: string, controller: any, options: {
|
|
551
|
-
only?: string[]
|
|
552
|
-
except?: string[]
|
|
553
|
-
model?: BunQueryBuilderModel
|
|
554
|
-
} = {}): this {
|
|
555
|
-
const actions = ['index', 'create', 'store', 'show', 'edit', 'update', 'destroy']
|
|
556
|
-
const allowedActions = options.only || actions.filter(action => !options.except?.includes(action))
|
|
557
|
-
|
|
558
|
-
const routes = [
|
|
559
|
-
{ action: 'index', method: 'GET', path: `/${name}`, handler: controller.index },
|
|
560
|
-
{ action: 'create', method: 'GET', path: `/${name}/create`, handler: controller.create },
|
|
561
|
-
{ action: 'store', method: 'POST', path: `/${name}`, handler: controller.store },
|
|
562
|
-
{ action: 'show', method: 'GET', path: `/${name}/{${name.slice(0, -1)}}`, handler: controller.show },
|
|
563
|
-
{ action: 'edit', method: 'GET', path: `/${name}/{${name.slice(0, -1)}}/edit`, handler: controller.edit },
|
|
564
|
-
{ action: 'update', method: 'PUT', path: `/${name}/{${name.slice(0, -1)}}`, handler: controller.update },
|
|
565
|
-
{ action: 'destroy', method: 'DELETE', path: `/${name}/{${name.slice(0, -1)}}`, handler: controller.destroy },
|
|
566
|
-
]
|
|
567
|
-
|
|
568
|
-
for (const route of routes) {
|
|
569
|
-
if (allowedActions.includes(route.action) && route.handler) {
|
|
570
|
-
const builder = new FluentRouteBuilder(route.method, route.path, route.handler)
|
|
571
|
-
.name(`${name}.${route.action}`)
|
|
572
|
-
|
|
573
|
-
if (options.model && ['show', 'edit', 'update', 'destroy'].includes(route.action)) {
|
|
574
|
-
builder.model(name.slice(0, -1), options.model)
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
this.register(builder)
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
return this
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
/**
|
|
585
|
-
* Get all registered routes
|
|
586
|
-
*/
|
|
587
|
-
getRoutes(): Array<{
|
|
588
|
-
method: string
|
|
589
|
-
path: string
|
|
590
|
-
handler: RouteHandler
|
|
591
|
-
middleware: MiddlewareHandler[]
|
|
592
|
-
name?: string
|
|
593
|
-
}> {
|
|
594
|
-
return [...this.routes, ...this.subdomainRouter.getAllRoutes()]
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
/**
|
|
598
|
-
* Handle incoming request
|
|
599
|
-
*/
|
|
600
|
-
async handle(request: EnhancedRequest): Promise<Response | null> {
|
|
601
|
-
const _url = new URL(request.url)
|
|
602
|
-
|
|
603
|
-
// Try subdomain routing first
|
|
604
|
-
const url = new URL(request.url)
|
|
605
|
-
const domain = url.hostname
|
|
606
|
-
const match = this.subdomainRouter.findDomainGroup(domain)
|
|
607
|
-
if (match) {
|
|
608
|
-
// Add domain parameters to request
|
|
609
|
-
const enhancedReq = request as EnhancedRequest & { domainParams?: Record<string, string> }
|
|
610
|
-
enhancedReq.domainParams = match.parameters
|
|
611
|
-
|
|
612
|
-
// Find matching route in domain group
|
|
613
|
-
for (const route of match.group.getRoutes()) {
|
|
614
|
-
if (this.matchesRoute(route, request)) {
|
|
615
|
-
return await this.executeRoute(route, enhancedReq)
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
// Find matching route
|
|
621
|
-
for (const route of this.routes) {
|
|
622
|
-
if (this.matchesRoute(route, request)) {
|
|
623
|
-
return await this.executeRoute(route, request)
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
return null
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
/**
|
|
631
|
-
* Check if route matches request
|
|
632
|
-
*/
|
|
633
|
-
private matchesRoute(route: any, request: EnhancedRequest): boolean {
|
|
634
|
-
if (route.method !== request.method) {
|
|
635
|
-
return false
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
const url = new URL(request.url)
|
|
639
|
-
// eslint-disable-next-line regexp/no-super-linear-backtracking
|
|
640
|
-
const routePattern = route.path.replace(/\{([^:}]+):?([^}]*)\}/g, '([^/]+)')
|
|
641
|
-
const regex = new RegExp(`^${routePattern}$`)
|
|
642
|
-
|
|
643
|
-
return regex.test(url.pathname)
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
/**
|
|
647
|
-
* Execute route with middleware
|
|
648
|
-
*/
|
|
649
|
-
private async executeRoute(route: any, request: EnhancedRequest): Promise<Response> {
|
|
650
|
-
const allMiddleware = [...this.globalMiddleware, ...route.middleware]
|
|
651
|
-
|
|
652
|
-
let index = 0
|
|
653
|
-
const next = async (): Promise<Response> => {
|
|
654
|
-
if (index < allMiddleware.length) {
|
|
655
|
-
const middleware = allMiddleware[index++]
|
|
656
|
-
return await middleware(request, next)
|
|
657
|
-
}
|
|
658
|
-
return await route.handler(request)
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
return await next()
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
/** API route options */
|
|
666
|
-
export interface ApiRouteOptions {
|
|
667
|
-
method?: string
|
|
668
|
-
cache?: string[]
|
|
669
|
-
throttle?: string
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
/** Protected route options */
|
|
673
|
-
export interface ProtectedRouteOptions {
|
|
674
|
-
method?: string
|
|
675
|
-
roles?: string[]
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
/** Upload route options */
|
|
679
|
-
export interface UploadRouteOptions {
|
|
680
|
-
maxSize?: number
|
|
681
|
-
allowedTypes?: string[]
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
/**
|
|
685
|
-
* Factory functions for common route patterns
|
|
686
|
-
*/
|
|
687
|
-
export const RouteFactory: {
|
|
688
|
-
api: (path: string, handler: RouteHandler, options?: ApiRouteOptions) => FluentRouteBuilder
|
|
689
|
-
protected: (path: string, handler: RouteHandler, options?: ProtectedRouteOptions) => FluentRouteBuilder
|
|
690
|
-
upload: (path: string, handler: RouteHandler, options?: UploadRouteOptions) => FluentRouteBuilder
|
|
691
|
-
} = {
|
|
692
|
-
/**
|
|
693
|
-
* API route with caching and throttling
|
|
694
|
-
*/
|
|
695
|
-
api: (path: string, handler: RouteHandler, options: ApiRouteOptions = {}): FluentRouteBuilder => {
|
|
696
|
-
const method = options.method || 'GET'
|
|
697
|
-
const builder = new FluentRouteBuilder(method, path, handler)
|
|
698
|
-
|
|
699
|
-
if (options.cache) {
|
|
700
|
-
builder.cached(options.cache)
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
if (options.throttle) {
|
|
704
|
-
builder.throttle(options.throttle as ThrottlePattern)
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
return builder
|
|
708
|
-
},
|
|
709
|
-
|
|
710
|
-
/**
|
|
711
|
-
* Protected route with authentication
|
|
712
|
-
*/
|
|
713
|
-
protected: (path: string, handler: RouteHandler, options: ProtectedRouteOptions = {}): FluentRouteBuilder => {
|
|
714
|
-
const method = options.method || 'GET'
|
|
715
|
-
const builder = new FluentRouteBuilder(method, path, handler)
|
|
716
|
-
|
|
717
|
-
// Add auth middleware (would need to be implemented)
|
|
718
|
-
builder.addMiddleware(async (req: EnhancedRequest, next: NextFunction) => {
|
|
719
|
-
// Mock auth check
|
|
720
|
-
if (!req.headers.get('Authorization')) {
|
|
721
|
-
return new Response('Unauthorized', { status: 401 })
|
|
722
|
-
}
|
|
723
|
-
return await next()
|
|
724
|
-
})
|
|
725
|
-
|
|
726
|
-
return builder
|
|
727
|
-
},
|
|
728
|
-
|
|
729
|
-
/**
|
|
730
|
-
* File upload route
|
|
731
|
-
*/
|
|
732
|
-
upload: (path: string, handler: RouteHandler, _options: UploadRouteOptions = {}): FluentRouteBuilder => {
|
|
733
|
-
const builder = new FluentRouteBuilder('POST', path, handler)
|
|
734
|
-
|
|
735
|
-
// Add file upload middleware (would need to be implemented)
|
|
736
|
-
builder.addMiddleware(async (_req: EnhancedRequest, next: NextFunction) => {
|
|
737
|
-
// Mock file upload handling
|
|
738
|
-
return await next()
|
|
739
|
-
})
|
|
740
|
-
|
|
741
|
-
return builder
|
|
742
|
-
},
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
/**
|
|
746
|
-
* Utility functions
|
|
747
|
-
*/
|
|
748
|
-
export const RouterUtils = {
|
|
749
|
-
/**
|
|
750
|
-
* Generate route URL with parameters
|
|
751
|
-
*/
|
|
752
|
-
route: (name: string, params: Record<string, string> = {}, query: Record<string, string> = {}): string => {
|
|
753
|
-
// Mock route URL generation
|
|
754
|
-
let url = `/${name}`
|
|
755
|
-
|
|
756
|
-
for (const [key, value] of Object.entries(params)) {
|
|
757
|
-
url = url.replace(`{${key}}`, value)
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
const queryString = new URLSearchParams(query).toString()
|
|
761
|
-
if (queryString) {
|
|
762
|
-
url += `?${queryString}`
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
return url
|
|
766
|
-
},
|
|
767
|
-
|
|
768
|
-
/**
|
|
769
|
-
* Redirect response
|
|
770
|
-
*/
|
|
771
|
-
redirect: (url: string, status: number = 302): Response => {
|
|
772
|
-
return new Response(null, {
|
|
773
|
-
status,
|
|
774
|
-
headers: { Location: url },
|
|
775
|
-
})
|
|
776
|
-
},
|
|
777
|
-
|
|
778
|
-
/**
|
|
779
|
-
* JSON response
|
|
780
|
-
*/
|
|
781
|
-
json: (data: any, status: number = 200): Response => {
|
|
782
|
-
return new Response(JSON.stringify(data), {
|
|
783
|
-
status,
|
|
784
|
-
headers: { 'Content-Type': 'application/json' },
|
|
785
|
-
})
|
|
786
|
-
},
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
/**
|
|
790
|
-
* Global router instance
|
|
791
|
-
*/
|
|
792
|
-
export const router: FluentRouter = new FluentRouter()
|
|
793
|
-
|
|
794
|
-
/**
|
|
795
|
-
* Export commonly used factory functions
|
|
796
|
-
*/
|
|
797
|
-
export { RouteCacheFactory, ThrottleFactory }
|