@stacksjs/bun-router 0.0.12 → 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 -48
- 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/response/macros.ts
DELETED
|
@@ -1,612 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Request/Response Enhancements - Response Macros
|
|
3
|
-
*
|
|
4
|
-
* Laravel-style response macros for common response patterns
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import process from 'node:process'
|
|
8
|
-
|
|
9
|
-
export interface ResponseMacro {
|
|
10
|
-
name: string
|
|
11
|
-
handler: (...args: any[]) => Response
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface ApiResponse<T = any> {
|
|
15
|
-
data?: T
|
|
16
|
-
message?: string
|
|
17
|
-
error?: string
|
|
18
|
-
errors?: Record<string, string[]>
|
|
19
|
-
meta?: Record<string, any>
|
|
20
|
-
links?: Record<string, string>
|
|
21
|
-
timestamp?: string
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface PaginatedResponse<T = any> extends ApiResponse<T[]> {
|
|
25
|
-
meta: {
|
|
26
|
-
current_page: number
|
|
27
|
-
per_page: number
|
|
28
|
-
total: number
|
|
29
|
-
last_page: number
|
|
30
|
-
from: number
|
|
31
|
-
to: number
|
|
32
|
-
path: string
|
|
33
|
-
first_page_url: string
|
|
34
|
-
last_page_url: string
|
|
35
|
-
next_page_url?: string
|
|
36
|
-
prev_page_url?: string
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Response macro registry
|
|
42
|
-
*/
|
|
43
|
-
class ResponseMacroRegistry {
|
|
44
|
-
private macros: Map<string, ResponseMacro> = new Map()
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Register a response macro
|
|
48
|
-
*/
|
|
49
|
-
register(name: string, handler: (...args: any[]) => Response): void {
|
|
50
|
-
this.macros.set(name, { name, handler })
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Get a registered macro
|
|
55
|
-
*/
|
|
56
|
-
get(name: string): ResponseMacro | undefined {
|
|
57
|
-
return this.macros.get(name)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Check if macro exists
|
|
62
|
-
*/
|
|
63
|
-
has(name: string): boolean {
|
|
64
|
-
return this.macros.has(name)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Get all registered macros
|
|
69
|
-
*/
|
|
70
|
-
all(): ResponseMacro[] {
|
|
71
|
-
return Array.from(this.macros.values())
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Remove a macro
|
|
76
|
-
*/
|
|
77
|
-
remove(name: string): boolean {
|
|
78
|
-
return this.macros.delete(name)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Clear all macros
|
|
83
|
-
*/
|
|
84
|
-
clear(): void {
|
|
85
|
-
this.macros.clear()
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Global response macro registry
|
|
91
|
-
*/
|
|
92
|
-
export const responseMacroRegistry: ResponseMacroRegistry = new ResponseMacroRegistry()
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Response class with macro support
|
|
96
|
-
*/
|
|
97
|
-
export class ResponseWithMacros extends Response {
|
|
98
|
-
/**
|
|
99
|
-
* Register a response macro
|
|
100
|
-
*/
|
|
101
|
-
static macro(name: string, handler: (...args: any[]) => Response): void {
|
|
102
|
-
responseMacroRegistry.register(name, handler)
|
|
103
|
-
|
|
104
|
-
// Add method to Response prototype
|
|
105
|
-
;(Response as any)[name] = handler
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Call a registered macro
|
|
110
|
-
*/
|
|
111
|
-
static callMacro(name: string, ...args: any[]): Response {
|
|
112
|
-
const macro = responseMacroRegistry.get(name)
|
|
113
|
-
if (!macro) {
|
|
114
|
-
throw new Error(`Response macro "${name}" not found`)
|
|
115
|
-
}
|
|
116
|
-
return macro.handler(...args)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Check if macro exists
|
|
121
|
-
*/
|
|
122
|
-
static hasMacro(name: string): boolean {
|
|
123
|
-
return responseMacroRegistry.has(name)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Built-in response macros
|
|
129
|
-
*/
|
|
130
|
-
export const BuiltInResponseMacros = {
|
|
131
|
-
/**
|
|
132
|
-
* Success response with data
|
|
133
|
-
*/
|
|
134
|
-
success: (data?: any, message?: string, status = 200): Response => {
|
|
135
|
-
const body: Record<string, unknown> = {}
|
|
136
|
-
if (data !== undefined)
|
|
137
|
-
body.data = data
|
|
138
|
-
if (message !== undefined)
|
|
139
|
-
body.message = message
|
|
140
|
-
|
|
141
|
-
return new Response(JSON.stringify(body), {
|
|
142
|
-
status,
|
|
143
|
-
headers: { 'Content-Type': 'application/json' },
|
|
144
|
-
})
|
|
145
|
-
},
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Error response with message and errors
|
|
149
|
-
*/
|
|
150
|
-
error: (message: string, errors?: Record<string, string[]>, status = 400): Response => {
|
|
151
|
-
const body: Record<string, unknown> = { error: message }
|
|
152
|
-
if (errors !== undefined)
|
|
153
|
-
body.errors = errors
|
|
154
|
-
|
|
155
|
-
return new Response(JSON.stringify(body), {
|
|
156
|
-
status,
|
|
157
|
-
headers: { 'Content-Type': 'application/json' },
|
|
158
|
-
})
|
|
159
|
-
},
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Validation error response
|
|
163
|
-
*/
|
|
164
|
-
validationError: (errors: Record<string, string[]>, message = 'Validation failed'): Response => {
|
|
165
|
-
return BuiltInResponseMacros.error(message, errors, 422)
|
|
166
|
-
},
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Not found response
|
|
170
|
-
*/
|
|
171
|
-
notFound: (message = 'Resource not found'): Response => {
|
|
172
|
-
return BuiltInResponseMacros.error(message, undefined, 404)
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Unauthorized response
|
|
177
|
-
*/
|
|
178
|
-
unauthorized: (message = 'Unauthorized'): Response => {
|
|
179
|
-
return BuiltInResponseMacros.error(message, undefined, 401)
|
|
180
|
-
},
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Forbidden response
|
|
184
|
-
*/
|
|
185
|
-
forbidden: (message = 'Forbidden'): Response => {
|
|
186
|
-
return BuiltInResponseMacros.error(message, undefined, 403)
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Internal server error response
|
|
191
|
-
*/
|
|
192
|
-
serverError: (message = 'Internal server error'): Response => {
|
|
193
|
-
return BuiltInResponseMacros.error(message, undefined, 500)
|
|
194
|
-
},
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Created response
|
|
198
|
-
*/
|
|
199
|
-
created: (data?: any, message = 'Resource created successfully'): Response => {
|
|
200
|
-
return BuiltInResponseMacros.success(data, message, 201)
|
|
201
|
-
},
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Updated response
|
|
205
|
-
*/
|
|
206
|
-
updated: (data?: any, message = 'Resource updated successfully'): Response => {
|
|
207
|
-
return BuiltInResponseMacros.success(data, message, 200)
|
|
208
|
-
},
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Deleted response
|
|
212
|
-
*/
|
|
213
|
-
deleted: (message = 'Resource deleted successfully'): Response => {
|
|
214
|
-
return BuiltInResponseMacros.success(null, message, 200)
|
|
215
|
-
},
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* No content response
|
|
219
|
-
*/
|
|
220
|
-
noContent: (): Response => {
|
|
221
|
-
return new Response(null, { status: 204 })
|
|
222
|
-
},
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Accepted response
|
|
226
|
-
*/
|
|
227
|
-
accepted: (data?: any, message = 'Request accepted'): Response => {
|
|
228
|
-
return BuiltInResponseMacros.success(data, message, 202)
|
|
229
|
-
},
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Paginated response
|
|
233
|
-
*/
|
|
234
|
-
paginated: <T>(
|
|
235
|
-
data: T[],
|
|
236
|
-
pagination: {
|
|
237
|
-
current_page: number
|
|
238
|
-
per_page: number
|
|
239
|
-
total: number
|
|
240
|
-
path: string
|
|
241
|
-
},
|
|
242
|
-
message?: string,
|
|
243
|
-
): Response => {
|
|
244
|
-
const lastPage = Math.ceil(pagination.total / pagination.per_page)
|
|
245
|
-
const from = (pagination.current_page - 1) * pagination.per_page + 1
|
|
246
|
-
const to = Math.min(from + pagination.per_page - 1, pagination.total)
|
|
247
|
-
|
|
248
|
-
const response: PaginatedResponse<T> = {
|
|
249
|
-
data,
|
|
250
|
-
message,
|
|
251
|
-
meta: {
|
|
252
|
-
current_page: pagination.current_page,
|
|
253
|
-
per_page: pagination.per_page,
|
|
254
|
-
total: pagination.total,
|
|
255
|
-
last_page: lastPage,
|
|
256
|
-
from,
|
|
257
|
-
to,
|
|
258
|
-
path: pagination.path,
|
|
259
|
-
first_page_url: `${pagination.path}?page=1`,
|
|
260
|
-
last_page_url: `${pagination.path}?page=${lastPage}`,
|
|
261
|
-
next_page_url: pagination.current_page < lastPage
|
|
262
|
-
? `${pagination.path}?page=${pagination.current_page + 1}`
|
|
263
|
-
: undefined,
|
|
264
|
-
prev_page_url: pagination.current_page > 1
|
|
265
|
-
? `${pagination.path}?page=${pagination.current_page - 1}`
|
|
266
|
-
: undefined,
|
|
267
|
-
},
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
return new Response(JSON.stringify(response), {
|
|
271
|
-
status: 200,
|
|
272
|
-
headers: { 'Content-Type': 'application/json' },
|
|
273
|
-
})
|
|
274
|
-
},
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* JSON response with custom headers
|
|
278
|
-
*/
|
|
279
|
-
json: (data: any, status = 200, headers: Record<string, string> = {}): Response => {
|
|
280
|
-
return new Response(JSON.stringify(data), {
|
|
281
|
-
status,
|
|
282
|
-
headers: {
|
|
283
|
-
'Content-Type': 'application/json',
|
|
284
|
-
...headers,
|
|
285
|
-
},
|
|
286
|
-
})
|
|
287
|
-
},
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* HTML response
|
|
291
|
-
*/
|
|
292
|
-
html: (content: string, status = 200, headers: Record<string, string> = {}): Response => {
|
|
293
|
-
return new Response(content, {
|
|
294
|
-
status,
|
|
295
|
-
headers: {
|
|
296
|
-
'Content-Type': 'text/html',
|
|
297
|
-
...headers,
|
|
298
|
-
},
|
|
299
|
-
})
|
|
300
|
-
},
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* Plain text response
|
|
304
|
-
*/
|
|
305
|
-
text: (content: string, status = 200, headers: Record<string, string> = {}): Response => {
|
|
306
|
-
return new Response(content, {
|
|
307
|
-
status,
|
|
308
|
-
headers: {
|
|
309
|
-
'Content-Type': 'text/plain',
|
|
310
|
-
...headers,
|
|
311
|
-
},
|
|
312
|
-
})
|
|
313
|
-
},
|
|
314
|
-
|
|
315
|
-
/**
|
|
316
|
-
* XML response
|
|
317
|
-
*/
|
|
318
|
-
xml: (content: string, status = 200, headers: Record<string, string> = {}): Response => {
|
|
319
|
-
return new Response(content, {
|
|
320
|
-
status,
|
|
321
|
-
headers: {
|
|
322
|
-
'Content-Type': 'application/xml',
|
|
323
|
-
...headers,
|
|
324
|
-
},
|
|
325
|
-
})
|
|
326
|
-
},
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Redirect response
|
|
330
|
-
*/
|
|
331
|
-
redirect: (url: string, status = 302): Response => {
|
|
332
|
-
return new Response(null, {
|
|
333
|
-
status,
|
|
334
|
-
headers: {
|
|
335
|
-
Location: url,
|
|
336
|
-
},
|
|
337
|
-
})
|
|
338
|
-
},
|
|
339
|
-
|
|
340
|
-
/**
|
|
341
|
-
* Permanent redirect response
|
|
342
|
-
*/
|
|
343
|
-
permanentRedirect: (url: string): Response => {
|
|
344
|
-
return BuiltInResponseMacros.redirect(url, 301)
|
|
345
|
-
},
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Download response
|
|
349
|
-
*/
|
|
350
|
-
download: (
|
|
351
|
-
data: ArrayBuffer | Uint8Array | string,
|
|
352
|
-
filename: string,
|
|
353
|
-
contentType = 'application/octet-stream',
|
|
354
|
-
): Response => {
|
|
355
|
-
return new Response(data as any, {
|
|
356
|
-
status: 200,
|
|
357
|
-
headers: {
|
|
358
|
-
'Content-Type': contentType,
|
|
359
|
-
'Content-Disposition': `attachment; filename="${filename}"`,
|
|
360
|
-
},
|
|
361
|
-
})
|
|
362
|
-
},
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* Stream response
|
|
366
|
-
*/
|
|
367
|
-
stream: (
|
|
368
|
-
stream: ReadableStream,
|
|
369
|
-
contentType = 'application/octet-stream',
|
|
370
|
-
headers: Record<string, string> = {},
|
|
371
|
-
): Response => {
|
|
372
|
-
return new Response(stream, {
|
|
373
|
-
status: 200,
|
|
374
|
-
headers: {
|
|
375
|
-
'Content-Type': contentType,
|
|
376
|
-
...headers,
|
|
377
|
-
},
|
|
378
|
-
})
|
|
379
|
-
},
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Cache response with headers
|
|
383
|
-
*/
|
|
384
|
-
cache: (
|
|
385
|
-
data: any,
|
|
386
|
-
maxAge = 3600,
|
|
387
|
-
isPublic = true,
|
|
388
|
-
etag?: string,
|
|
389
|
-
): Response => {
|
|
390
|
-
const cacheControl = isPublic ? `public, max-age=${maxAge}` : `private, max-age=${maxAge}`
|
|
391
|
-
const headers: Record<string, string> = {
|
|
392
|
-
'Content-Type': 'application/json',
|
|
393
|
-
'Cache-Control': cacheControl,
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
if (etag) {
|
|
397
|
-
headers.ETag = etag
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
return new Response(JSON.stringify(data), {
|
|
401
|
-
status: 200,
|
|
402
|
-
headers,
|
|
403
|
-
})
|
|
404
|
-
},
|
|
405
|
-
|
|
406
|
-
/**
|
|
407
|
-
* CORS response
|
|
408
|
-
*/
|
|
409
|
-
cors: (
|
|
410
|
-
data: any,
|
|
411
|
-
origin = '*',
|
|
412
|
-
methods = 'GET,POST,PUT,DELETE,OPTIONS',
|
|
413
|
-
headers = 'Content-Type,Authorization',
|
|
414
|
-
): Response => {
|
|
415
|
-
return new Response(JSON.stringify(data), {
|
|
416
|
-
status: 200,
|
|
417
|
-
headers: {
|
|
418
|
-
'Content-Type': 'application/json',
|
|
419
|
-
'Access-Control-Allow-Origin': origin,
|
|
420
|
-
'Access-Control-Allow-Methods': methods,
|
|
421
|
-
'Access-Control-Allow-Headers': headers,
|
|
422
|
-
},
|
|
423
|
-
})
|
|
424
|
-
},
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* Server-Sent Events response
|
|
428
|
-
*/
|
|
429
|
-
sse: (data: string, event?: string, id?: string): Response => {
|
|
430
|
-
let sseData = ''
|
|
431
|
-
|
|
432
|
-
if (id)
|
|
433
|
-
sseData += `id: ${id}\n`
|
|
434
|
-
if (event)
|
|
435
|
-
sseData += `event: ${event}\n`
|
|
436
|
-
sseData += `data: ${data}\n\n`
|
|
437
|
-
|
|
438
|
-
return new Response(sseData, {
|
|
439
|
-
status: 200,
|
|
440
|
-
headers: {
|
|
441
|
-
'Content-Type': 'text/event-stream',
|
|
442
|
-
'Cache-Control': 'no-cache',
|
|
443
|
-
'Connection': 'keep-alive',
|
|
444
|
-
},
|
|
445
|
-
})
|
|
446
|
-
},
|
|
447
|
-
|
|
448
|
-
/**
|
|
449
|
-
* Health check response
|
|
450
|
-
*/
|
|
451
|
-
health: (status: 'healthy' | 'unhealthy' | 'degraded' = 'healthy', checks: Record<string, any> = {}): Response => {
|
|
452
|
-
const statusCode: number = status === 'healthy' ? 200 : status === 'degraded' ? 200 : 503
|
|
453
|
-
|
|
454
|
-
const response: { status: string, timestamp: string, checks: Record<string, any>, uptime: number } = {
|
|
455
|
-
status,
|
|
456
|
-
timestamp: new Date().toISOString(),
|
|
457
|
-
checks,
|
|
458
|
-
uptime: process.uptime?.() || 0,
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
return new Response(JSON.stringify(response), {
|
|
462
|
-
status: statusCode,
|
|
463
|
-
headers: {
|
|
464
|
-
'Content-Type': 'application/json',
|
|
465
|
-
},
|
|
466
|
-
})
|
|
467
|
-
},
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
/**
|
|
471
|
-
* Register all built-in macros
|
|
472
|
-
*/
|
|
473
|
-
export function registerBuiltInResponseMacros(): void {
|
|
474
|
-
Object.entries(BuiltInResponseMacros).forEach(([name, handler]) => {
|
|
475
|
-
ResponseWithMacros.macro(name, handler)
|
|
476
|
-
})
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* Response macro factory functions
|
|
481
|
-
*/
|
|
482
|
-
export const ResponseMacroFactory = {
|
|
483
|
-
/**
|
|
484
|
-
* Create API response macro
|
|
485
|
-
*/
|
|
486
|
-
api: (defaultMeta?: Record<string, any>) => {
|
|
487
|
-
return (data?: any, message?: string, status = 200): Response => {
|
|
488
|
-
const body: Record<string, unknown> = {}
|
|
489
|
-
if (data !== undefined)
|
|
490
|
-
body.data = data
|
|
491
|
-
if (message !== undefined)
|
|
492
|
-
body.message = message
|
|
493
|
-
if (defaultMeta !== undefined)
|
|
494
|
-
body.meta = defaultMeta
|
|
495
|
-
|
|
496
|
-
return new Response(JSON.stringify(body), {
|
|
497
|
-
status,
|
|
498
|
-
headers: { 'Content-Type': 'application/json' },
|
|
499
|
-
})
|
|
500
|
-
}
|
|
501
|
-
},
|
|
502
|
-
|
|
503
|
-
/**
|
|
504
|
-
* Create versioned API response macro
|
|
505
|
-
*/
|
|
506
|
-
versionedApi: (version: string) => {
|
|
507
|
-
return (data?: any, message?: string, status = 200): Response => {
|
|
508
|
-
const body: Record<string, unknown> = { meta: { version } }
|
|
509
|
-
if (data !== undefined)
|
|
510
|
-
body.data = data
|
|
511
|
-
if (message !== undefined)
|
|
512
|
-
body.message = message
|
|
513
|
-
|
|
514
|
-
return new Response(JSON.stringify(body), {
|
|
515
|
-
status,
|
|
516
|
-
headers: {
|
|
517
|
-
'Content-Type': 'application/json',
|
|
518
|
-
'X-API-Version': version,
|
|
519
|
-
},
|
|
520
|
-
})
|
|
521
|
-
}
|
|
522
|
-
},
|
|
523
|
-
|
|
524
|
-
/**
|
|
525
|
-
* Create custom error response macro
|
|
526
|
-
*/
|
|
527
|
-
customError: (defaultStatus: number = 400, defaultMessage: string = 'An error occurred'): (message?: string, errors?: Record<string, string[]>, status?: number) => Response => {
|
|
528
|
-
return (message: string = defaultMessage, errors?: Record<string, string[]>, status: number = defaultStatus): Response => {
|
|
529
|
-
const body: Record<string, unknown> = { error: message }
|
|
530
|
-
if (errors !== undefined)
|
|
531
|
-
body.errors = errors
|
|
532
|
-
|
|
533
|
-
return new Response(JSON.stringify(body), {
|
|
534
|
-
status,
|
|
535
|
-
headers: { 'Content-Type': 'application/json' },
|
|
536
|
-
})
|
|
537
|
-
}
|
|
538
|
-
},
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
/**
|
|
542
|
-
* Response helper utilities
|
|
543
|
-
*/
|
|
544
|
-
export const ResponseHelpers = {
|
|
545
|
-
/**
|
|
546
|
-
* Check if response is successful
|
|
547
|
-
*/
|
|
548
|
-
isSuccess: (response: Response): boolean => {
|
|
549
|
-
return response.status >= 200 && response.status < 300
|
|
550
|
-
},
|
|
551
|
-
|
|
552
|
-
/**
|
|
553
|
-
* Check if response is error
|
|
554
|
-
*/
|
|
555
|
-
isError: (response: Response): boolean => {
|
|
556
|
-
return response.status >= 400
|
|
557
|
-
},
|
|
558
|
-
|
|
559
|
-
/**
|
|
560
|
-
* Get response body as JSON
|
|
561
|
-
*/
|
|
562
|
-
getJson: async (response: Response): Promise<any> => {
|
|
563
|
-
try {
|
|
564
|
-
return await response.json()
|
|
565
|
-
}
|
|
566
|
-
catch {
|
|
567
|
-
return null
|
|
568
|
-
}
|
|
569
|
-
},
|
|
570
|
-
|
|
571
|
-
/**
|
|
572
|
-
* Get response body as text
|
|
573
|
-
*/
|
|
574
|
-
getText: async (response: Response): Promise<string> => {
|
|
575
|
-
try {
|
|
576
|
-
return await response.text()
|
|
577
|
-
}
|
|
578
|
-
catch {
|
|
579
|
-
return ''
|
|
580
|
-
}
|
|
581
|
-
},
|
|
582
|
-
|
|
583
|
-
/**
|
|
584
|
-
* Clone response with new headers
|
|
585
|
-
*/
|
|
586
|
-
withHeaders: (response: Response, headers: Record<string, string>): Response => {
|
|
587
|
-
const newHeaders = new Headers(response.headers)
|
|
588
|
-
Object.entries(headers).forEach(([key, value]) => {
|
|
589
|
-
newHeaders.set(key, value)
|
|
590
|
-
})
|
|
591
|
-
|
|
592
|
-
return new Response(response.body, {
|
|
593
|
-
status: response.status,
|
|
594
|
-
statusText: response.statusText,
|
|
595
|
-
headers: newHeaders,
|
|
596
|
-
})
|
|
597
|
-
},
|
|
598
|
-
|
|
599
|
-
/**
|
|
600
|
-
* Clone response with new status
|
|
601
|
-
*/
|
|
602
|
-
withStatus: (response: Response, status: number, statusText?: string): Response => {
|
|
603
|
-
return new Response(response.body, {
|
|
604
|
-
status,
|
|
605
|
-
statusText: statusText || response.statusText,
|
|
606
|
-
headers: response.headers,
|
|
607
|
-
})
|
|
608
|
-
},
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// Auto-register built-in macros
|
|
612
|
-
registerBuiltInResponseMacros()
|