@stacksjs/bun-router 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (269) hide show
  1. package/dist/auth.d.ts +134 -0
  2. package/dist/cache/lru-cache.d.ts +139 -0
  3. package/dist/cache/middleware-memoization.d.ts +151 -0
  4. package/dist/cache/route-cache-warmer.d.ts +161 -0
  5. package/dist/cache/sqlite-cache.d.ts +209 -0
  6. package/dist/cache/streaming-cache.d.ts +132 -0
  7. package/dist/cli/colors.d.ts +15 -0
  8. package/dist/cli/index.d.ts +10 -0
  9. package/dist/cli/middleware.d.ts +31 -0
  10. package/dist/cli/openapi.d.ts +17 -0
  11. package/dist/cli/router.d.ts +15 -0
  12. package/dist/cli/routes.d.ts +29 -0
  13. package/dist/cli/utils.d.ts +74 -0
  14. package/dist/cli.d.ts +1 -1
  15. package/dist/cli.js +1 -1
  16. package/dist/config.d.ts +7 -0
  17. package/dist/container/container.d.ts +273 -0
  18. package/dist/container/contextual-binding.d.ts +240 -0
  19. package/dist/container/decorators.d.ts +141 -0
  20. package/dist/container/service-provider.d.ts +285 -0
  21. package/dist/development/hot-reload.d.ts +187 -0
  22. package/dist/development/index.d.ts +167 -0
  23. package/dist/development/performance-profiler.d.ts +217 -0
  24. package/dist/development/route-debugger.d.ts +154 -0
  25. package/dist/development/route-inspector.d.ts +211 -0
  26. package/dist/development/typescript-utilities.d.ts +209 -0
  27. package/dist/docs.d.ts +11 -0
  28. package/dist/errors/circuit-breaker.d.ts +195 -0
  29. package/dist/errors/error-handler.d.ts +88 -0
  30. package/dist/errors/error-reporting.d.ts +144 -0
  31. package/dist/errors/exceptions.d.ts +184 -0
  32. package/dist/errors/graceful-degradation.d.ts +154 -0
  33. package/dist/errors/index.d.ts +9 -0
  34. package/dist/errors/router-errors.d.ts +110 -0
  35. package/dist/file-serving/static-files.d.ts +143 -0
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.js +319 -205
  38. package/dist/middleware/auth.d.ts +63 -0
  39. package/dist/middleware/content_security_policy.d.ts +53 -0
  40. package/dist/middleware/cors.d.ts +5 -0
  41. package/dist/middleware/csrf.d.ts +7 -0
  42. package/dist/middleware/ddos_protection.d.ts +39 -0
  43. package/dist/middleware/file_security.d.ts +26 -0
  44. package/dist/middleware/file_upload.d.ts +38 -0
  45. package/dist/middleware/helmet.d.ts +54 -0
  46. package/dist/middleware/index.d.ts +44 -0
  47. package/dist/middleware/input_validation.d.ts +45 -0
  48. package/dist/middleware/json_body.d.ts +4 -0
  49. package/dist/middleware/performance_alerting.d.ts +87 -0
  50. package/dist/middleware/performance_dashboard.d.ts +87 -0
  51. package/dist/middleware/performance_monitor.d.ts +209 -0
  52. package/dist/middleware/pipeline.d.ts +131 -0
  53. package/dist/middleware/rate_limit.d.ts +36 -0
  54. package/dist/middleware/request_id.d.ts +4 -0
  55. package/dist/middleware/request_signing.d.ts +153 -0
  56. package/dist/middleware/request_tracer.d.ts +72 -0
  57. package/dist/middleware/response_cache.d.ts +97 -0
  58. package/dist/middleware/security.d.ts +69 -0
  59. package/dist/middleware/security_suite.d.ts +46 -0
  60. package/dist/middleware/session.d.ts +23 -0
  61. package/dist/model-binding/index.d.ts +2 -0
  62. package/dist/model-binding/model-middleware.d.ts +118 -0
  63. package/dist/model-binding/model-registry.d.ts +164 -0
  64. package/dist/model-binding.d.ts +185 -0
  65. package/dist/model-resolver-factory.d.ts +31 -0
  66. package/dist/observability/correlation.d.ts +187 -0
  67. package/dist/observability/health-checks.d.ts +186 -0
  68. package/dist/observability/index.d.ts +60 -0
  69. package/dist/observability/integration.d.ts +147 -0
  70. package/dist/observability/metrics.d.ts +184 -0
  71. package/dist/observability/tracing.d.ts +187 -0
  72. package/dist/optimization/bun-utilities.d.ts +224 -0
  73. package/dist/query-builder-integration.d.ts +36 -0
  74. package/dist/request/context.d.ts +34 -0
  75. package/dist/request/enhanced-request.d.ts +213 -0
  76. package/dist/request/macros.d.ts +300 -0
  77. package/dist/response/macros.d.ts +245 -0
  78. package/dist/response/response-factory.d.ts +133 -0
  79. package/dist/router/api-routes.d.ts +5 -0
  80. package/dist/router/file-based-routing.d.ts +118 -0
  81. package/dist/router/file-streaming.d.ts +5 -0
  82. package/dist/router/fluent-router.d.ts +315 -0
  83. package/dist/router/fluent-routing.d.ts +271 -0
  84. package/dist/router/group-organization.d.ts +5 -0
  85. package/dist/router/handler-resolver.d.ts +24 -0
  86. package/dist/router/http-methods.d.ts +10 -0
  87. package/dist/router/index.d.ts +113 -0
  88. package/dist/router/middleware-groups.d.ts +94 -0
  89. package/dist/router/middleware-integration.d.ts +112 -0
  90. package/dist/router/middleware.d.ts +5 -0
  91. package/dist/router/model-binding.d.ts +5 -0
  92. package/dist/router/optimized-route-matching.d.ts +6 -0
  93. package/dist/router/route-building.d.ts +5 -0
  94. package/dist/router/route-compiler.d.ts +153 -0
  95. package/dist/router/route-matching.d.ts +5 -0
  96. package/dist/router/route-trie.d.ts +114 -0
  97. package/dist/router/router.d.ts +276 -0
  98. package/dist/router/server.d.ts +5 -0
  99. package/dist/router/validation-integration.d.ts +170 -0
  100. package/dist/router/view-rendering.d.ts +5 -0
  101. package/dist/router/websocket.d.ts +5 -0
  102. package/dist/routing/route-caching.d.ts +129 -0
  103. package/dist/routing/route-throttling.d.ts +150 -0
  104. package/dist/routing/subdomain-routing.d.ts +206 -0
  105. package/dist/session/database-store.d.ts +51 -0
  106. package/dist/session/file-store.d.ts +22 -0
  107. package/dist/session/index.d.ts +106 -0
  108. package/dist/session/memory-store.d.ts +21 -0
  109. package/dist/session/redis-store.d.ts +31 -0
  110. package/dist/streaming/index.d.ts +3 -0
  111. package/dist/streaming/sse-handler.d.ts +138 -0
  112. package/dist/streaming/stream-handler.d.ts +114 -0
  113. package/dist/testing/auth-testing.d.ts +156 -0
  114. package/dist/testing/file-upload-testing.d.ts +190 -0
  115. package/dist/testing/index.d.ts +10 -0
  116. package/dist/testing/middleware-testing.d.ts +138 -0
  117. package/dist/testing/model-binding-testing.d.ts +186 -0
  118. package/dist/testing/performance-testing.d.ts +235 -0
  119. package/dist/testing/test-client.d.ts +117 -0
  120. package/dist/testing/test-request.d.ts +85 -0
  121. package/dist/testing/test-response.d.ts +90 -0
  122. package/dist/testing/types.d.ts +207 -0
  123. package/dist/testing/websocket-testing.d.ts +227 -0
  124. package/dist/types/controller-types.d.ts +208 -0
  125. package/dist/types/core.d.ts +543 -0
  126. package/dist/types/middleware-types.d.ts +227 -0
  127. package/dist/types/request-response-augmentation.d.ts +261 -0
  128. package/dist/types/route-inference.d.ts +168 -0
  129. package/dist/types.d.ts +1776 -0
  130. package/dist/url.d.ts +56 -0
  131. package/dist/utils/index.d.ts +1 -0
  132. package/dist/utils/query-preservation.d.ts +48 -0
  133. package/dist/utils.d.ts +69 -0
  134. package/dist/validation/validator.d.ts +140 -0
  135. package/dist/websocket/clustering.d.ts +185 -0
  136. package/package.json +3 -2
  137. package/src/auth.ts +469 -0
  138. package/src/cache/lru-cache.ts +457 -0
  139. package/src/cache/middleware-memoization.ts +531 -0
  140. package/src/cache/route-cache-warmer.ts +486 -0
  141. package/src/cache/sqlite-cache.ts +783 -0
  142. package/src/cache/streaming-cache.ts +572 -0
  143. package/src/cli/colors.ts +29 -0
  144. package/src/cli/index.ts +287 -0
  145. package/src/cli/middleware.ts +291 -0
  146. package/src/cli/openapi.ts +407 -0
  147. package/src/cli/router.ts +188 -0
  148. package/src/cli/routes.ts +265 -0
  149. package/src/cli/utils.ts +531 -0
  150. package/src/cli.ts +5 -0
  151. package/src/config.ts +322 -0
  152. package/src/container/container.ts +740 -0
  153. package/src/container/contextual-binding.ts +603 -0
  154. package/src/container/decorators.ts +359 -0
  155. package/src/container/service-provider.ts +596 -0
  156. package/src/development/hot-reload.ts +673 -0
  157. package/src/development/index.ts +499 -0
  158. package/src/development/performance-profiler.ts +717 -0
  159. package/src/development/route-debugger.ts +527 -0
  160. package/src/development/route-inspector.ts +749 -0
  161. package/src/development/typescript-utilities.ts +678 -0
  162. package/src/docs.ts +397 -0
  163. package/src/errors/circuit-breaker.ts +732 -0
  164. package/src/errors/error-handler.ts +569 -0
  165. package/src/errors/error-reporting.ts +672 -0
  166. package/src/errors/exceptions.ts +536 -0
  167. package/src/errors/graceful-degradation.ts +621 -0
  168. package/src/errors/index.ts +21 -0
  169. package/src/errors/router-errors.ts +632 -0
  170. package/src/file-serving/static-files.ts +581 -0
  171. package/src/index.ts +14 -0
  172. package/src/middleware/auth.ts +219 -0
  173. package/src/middleware/content_security_policy.ts +215 -0
  174. package/src/middleware/cors.ts +74 -0
  175. package/src/middleware/csrf.ts +108 -0
  176. package/src/middleware/ddos_protection.ts +255 -0
  177. package/src/middleware/file_security.ts +191 -0
  178. package/src/middleware/file_upload.ts +264 -0
  179. package/src/middleware/helmet.ts +268 -0
  180. package/src/middleware/index.ts +117 -0
  181. package/src/middleware/input_validation.ts +449 -0
  182. package/src/middleware/json_body.ts +37 -0
  183. package/src/middleware/performance_alerting.ts +538 -0
  184. package/src/middleware/performance_dashboard.ts +661 -0
  185. package/src/middleware/performance_monitor.ts +943 -0
  186. package/src/middleware/pipeline.ts +489 -0
  187. package/src/middleware/rate_limit.ts +245 -0
  188. package/src/middleware/request_id.ts +36 -0
  189. package/src/middleware/request_signing.ts +636 -0
  190. package/src/middleware/request_tracer.ts +636 -0
  191. package/src/middleware/response_cache.ts +743 -0
  192. package/src/middleware/security.ts +482 -0
  193. package/src/middleware/security_suite.ts +257 -0
  194. package/src/middleware/session.ts +91 -0
  195. package/src/model-binding/index.ts +18 -0
  196. package/src/model-binding/model-middleware.ts +425 -0
  197. package/src/model-binding/model-registry.ts +550 -0
  198. package/src/model-binding.ts +370 -0
  199. package/src/model-resolver-factory.ts +106 -0
  200. package/src/observability/correlation.ts +691 -0
  201. package/src/observability/health-checks.ts +729 -0
  202. package/src/observability/index.ts +184 -0
  203. package/src/observability/integration.ts +548 -0
  204. package/src/observability/metrics.ts +753 -0
  205. package/src/observability/tracing.ts +638 -0
  206. package/src/optimization/bun-utilities.ts +778 -0
  207. package/src/query-builder-integration.ts +137 -0
  208. package/src/request/context.ts +62 -0
  209. package/src/request/enhanced-request.ts +857 -0
  210. package/src/request/macros.ts +688 -0
  211. package/src/response/macros.ts +612 -0
  212. package/src/response/response-factory.ts +588 -0
  213. package/src/router/api-routes.ts +243 -0
  214. package/src/router/file-based-routing.ts +670 -0
  215. package/src/router/file-streaming.ts +372 -0
  216. package/src/router/fluent-router.ts +927 -0
  217. package/src/router/fluent-routing.ts +797 -0
  218. package/src/router/group-organization.ts +213 -0
  219. package/src/router/handler-resolver.ts +291 -0
  220. package/src/router/http-methods.ts +377 -0
  221. package/src/router/index.ts +185 -0
  222. package/src/router/middleware-groups.ts +222 -0
  223. package/src/router/middleware-integration.ts +399 -0
  224. package/src/router/middleware.ts +231 -0
  225. package/src/router/model-binding.ts +215 -0
  226. package/src/router/optimized-route-matching.ts +253 -0
  227. package/src/router/route-building.ts +212 -0
  228. package/src/router/route-compiler.ts +702 -0
  229. package/src/router/route-matching.ts +349 -0
  230. package/src/router/route-trie.ts +464 -0
  231. package/src/router/router.ts +1508 -0
  232. package/src/router/server.ts +406 -0
  233. package/src/router/validation-integration.ts +443 -0
  234. package/src/router/view-rendering.ts +233 -0
  235. package/src/router/websocket.ts +100 -0
  236. package/src/routing/route-caching.ts +402 -0
  237. package/src/routing/route-throttling.ts +469 -0
  238. package/src/routing/subdomain-routing.ts +492 -0
  239. package/src/session/database-store.ts +109 -0
  240. package/src/session/file-store.ts +148 -0
  241. package/src/session/index.ts +244 -0
  242. package/src/session/memory-store.ts +88 -0
  243. package/src/session/redis-store.ts +93 -0
  244. package/src/streaming/index.ts +17 -0
  245. package/src/streaming/sse-handler.ts +482 -0
  246. package/src/streaming/stream-handler.ts +552 -0
  247. package/src/testing/auth-testing.ts +446 -0
  248. package/src/testing/file-upload-testing.ts +543 -0
  249. package/src/testing/index.ts +10 -0
  250. package/src/testing/middleware-testing.ts +322 -0
  251. package/src/testing/model-binding-testing.ts +645 -0
  252. package/src/testing/performance-testing.ts +738 -0
  253. package/src/testing/test-client.ts +310 -0
  254. package/src/testing/test-request.ts +315 -0
  255. package/src/testing/test-response.ts +332 -0
  256. package/src/testing/types.ts +224 -0
  257. package/src/testing/websocket-testing.ts +590 -0
  258. package/src/types/controller-types.ts +385 -0
  259. package/src/types/core.ts +683 -0
  260. package/src/types/middleware-types.ts +419 -0
  261. package/src/types/request-response-augmentation.ts +489 -0
  262. package/src/types/route-inference.ts +357 -0
  263. package/src/types.ts +2049 -0
  264. package/src/url.ts +126 -0
  265. package/src/utils/index.ts +1 -0
  266. package/src/utils/query-preservation.ts +201 -0
  267. package/src/utils.ts +327 -0
  268. package/src/validation/validator.ts +685 -0
  269. package/src/websocket/clustering.ts +762 -0
@@ -0,0 +1,443 @@
1
+ /**
2
+ * Router Validation Integration
3
+ *
4
+ * Integration layer for validation and macros with the router.
5
+ * Provides RouteBuilder and FluentRouter for building routes with validation support.
6
+ */
7
+
8
+ import type { EnhancedRequest, MiddlewareHandler, NextFunction, RouteHandler } from '../types'
9
+ import type { ValidationRules, ValidatorConfig } from '../validation/validator'
10
+ import { RequestWithMacros } from '../request/macros'
11
+ import { ResponseWithMacros } from '../response/macros'
12
+ import { createValidationMiddleware } from '../validation/validator'
13
+
14
+ /**
15
+ * Route builder with validation support
16
+ */
17
+ export class RouteBuilder {
18
+ private validationRules?: ValidationRules
19
+ private validatorConfig?: ValidatorConfig
20
+
21
+ constructor(
22
+ private method: string,
23
+ private path: string,
24
+ private handler: RouteHandler,
25
+ ) {}
26
+
27
+ /**
28
+ * Add validation to the route
29
+ */
30
+ validate(rules: ValidationRules, config?: ValidatorConfig): this {
31
+ this.validationRules = rules
32
+ this.validatorConfig = config
33
+ return this
34
+ }
35
+
36
+ /**
37
+ * Build the route with middleware
38
+ */
39
+ build(): { method: string, path: string, handler: RouteHandler, middleware?: MiddlewareHandler[] } {
40
+ const middleware: MiddlewareHandler[] = []
41
+
42
+ // Add validation middleware if rules are provided
43
+ if (this.validationRules) {
44
+ middleware.push(createValidationMiddleware(this.validationRules, this.validatorConfig))
45
+ }
46
+
47
+ // Add request macro middleware
48
+ middleware.push(async (req: EnhancedRequest, next: NextFunction) => {
49
+ // Apply request macros
50
+ RequestWithMacros.applyMacros(req)
51
+ const result = await next()
52
+ return result || new Response('Not Found', { status: 404 })
53
+ })
54
+
55
+ return {
56
+ method: this.method,
57
+ path: this.path,
58
+ handler: this.handler,
59
+ middleware: middleware.length > 0 ? middleware : undefined,
60
+ }
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Fluent router for enhanced routing functionality
66
+ */
67
+ export class FluentRouter {
68
+ private routes: Array<{
69
+ method: string
70
+ path: string
71
+ handler: RouteHandler
72
+ middleware?: MiddlewareHandler[]
73
+ }> = []
74
+
75
+ /**
76
+ * Create GET route
77
+ */
78
+ get(path: string, handler: RouteHandler): RouteBuilder {
79
+ return new RouteBuilder('GET', path, handler)
80
+ }
81
+
82
+ /**
83
+ * Create POST route
84
+ */
85
+ post(path: string, handler: RouteHandler): RouteBuilder {
86
+ return new RouteBuilder('POST', path, handler)
87
+ }
88
+
89
+ /**
90
+ * Create PUT route
91
+ */
92
+ put(path: string, handler: RouteHandler): RouteBuilder {
93
+ return new RouteBuilder('PUT', path, handler)
94
+ }
95
+
96
+ /**
97
+ * Create PATCH route
98
+ */
99
+ patch(path: string, handler: RouteHandler): RouteBuilder {
100
+ return new RouteBuilder('PATCH', path, handler)
101
+ }
102
+
103
+ /**
104
+ * Create DELETE route
105
+ */
106
+ delete(path: string, handler: RouteHandler): RouteBuilder {
107
+ return new RouteBuilder('DELETE', path, handler)
108
+ }
109
+
110
+ /**
111
+ * Register a built route
112
+ */
113
+ register(routeBuilder: RouteBuilder): void {
114
+ const route = routeBuilder.build()
115
+ this.routes.push(route)
116
+ }
117
+
118
+ /**
119
+ * Get all registered routes
120
+ */
121
+ getRoutes(): Array<{
122
+ method: string
123
+ path: string
124
+ handler: RouteHandler
125
+ middleware?: MiddlewareHandler[]
126
+ }> {
127
+ return this.routes
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Router middleware factory for request/response enhancements
133
+ */
134
+ export function createEnhancementMiddleware() {
135
+ return async (req: EnhancedRequest, next: () => Promise<Response>): Promise<Response> => {
136
+ // Apply request macros
137
+ RequestWithMacros.applyMacros(req)
138
+
139
+ // Add start time for age calculation
140
+ ;(req as any).startTime = Date.now()
141
+
142
+ return await next()
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Validation middleware factory with fluent API
148
+ */
149
+ export class ValidationMiddlewareBuilder {
150
+ private rules: ValidationRules = {}
151
+ private config: ValidatorConfig = {}
152
+
153
+ /**
154
+ * Add validation rule for field
155
+ */
156
+ field(name: string, rules: string): this {
157
+ this.rules[name] = rules
158
+ return this
159
+ }
160
+
161
+ /**
162
+ * Add multiple validation rules
163
+ */
164
+ fields(rules: ValidationRules): this {
165
+ Object.assign(this.rules, rules)
166
+ return this
167
+ }
168
+
169
+ /**
170
+ * Set validator configuration
171
+ */
172
+ configure(config: ValidatorConfig): this {
173
+ Object.assign(this.config, config)
174
+ return this
175
+ }
176
+
177
+ /**
178
+ * Stop on first validation failure
179
+ */
180
+ stopOnFirstFailure(): this {
181
+ this.config.stopOnFirstFailure = true
182
+ return this
183
+ }
184
+
185
+ /**
186
+ * Set custom error messages
187
+ */
188
+ messages(messages: Record<string, string>): this {
189
+ this.config.customMessages = messages
190
+ return this
191
+ }
192
+
193
+ /**
194
+ * Set custom field attributes
195
+ */
196
+ attributes(attributes: Record<string, string>): this {
197
+ this.config.customAttributes = attributes
198
+ return this
199
+ }
200
+
201
+ /**
202
+ * Build the validation middleware
203
+ */
204
+ build(): MiddlewareHandler {
205
+ return createValidationMiddleware(this.rules, this.config)
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Factory function to create validation middleware builder
211
+ */
212
+ export function validate(): ValidationMiddlewareBuilder {
213
+ return new ValidationMiddlewareBuilder()
214
+ }
215
+
216
+ /** Resource handlers configuration */
217
+ export interface ResourceHandlers {
218
+ index?: RouteHandler
219
+ show?: RouteHandler
220
+ store?: RouteHandler
221
+ update?: RouteHandler
222
+ destroy?: RouteHandler
223
+ }
224
+
225
+ /** Resource validation configuration */
226
+ export interface ResourceValidation {
227
+ store?: ValidationRules
228
+ update?: ValidationRules
229
+ }
230
+
231
+ /**
232
+ * Route helper functions
233
+ */
234
+ export const RouteHelpers: {
235
+ validated: (method: string, path: string, handler: RouteHandler, rules: ValidationRules, config?: ValidatorConfig) => RouteBuilder
236
+ apiRoute: (method: string, path: string, handler: RouteHandler, rules?: ValidationRules) => RouteBuilder
237
+ resourceRoute: (basePath: string, handlers: ResourceHandlers, validation?: ResourceValidation) => RouteBuilder[]
238
+ } = {
239
+ /**
240
+ * Create validated route
241
+ */
242
+ validated: (
243
+ method: string,
244
+ path: string,
245
+ handler: RouteHandler,
246
+ rules: ValidationRules,
247
+ config?: ValidatorConfig,
248
+ ): RouteBuilder => {
249
+ const builder = new RouteBuilder(method, path, handler)
250
+ return builder.validate(rules, config)
251
+ },
252
+
253
+ /**
254
+ * Create API route with JSON validation
255
+ */
256
+ apiRoute: (
257
+ method: string,
258
+ path: string,
259
+ handler: RouteHandler,
260
+ rules?: ValidationRules,
261
+ ): RouteBuilder => {
262
+ const builder = new RouteBuilder(method, path, async (req): Promise<Response> => {
263
+ // Ensure request expects JSON
264
+ if (!req.expectsJson()) {
265
+ return ResponseWithMacros.callMacro('error', 'API endpoint requires JSON Accept header', undefined, 406)
266
+ }
267
+
268
+ return await handler(req)
269
+ })
270
+
271
+ if (rules) {
272
+ builder.validate(rules)
273
+ }
274
+
275
+ return builder
276
+ },
277
+
278
+ /**
279
+ * Create resource route with validation
280
+ */
281
+ resourceRoute: (
282
+ basePath: string,
283
+ handlers: ResourceHandlers,
284
+ validation?: ResourceValidation,
285
+ ): RouteBuilder[] => {
286
+ const routes: RouteBuilder[] = []
287
+
288
+ if (handlers.index) {
289
+ routes.push(new RouteBuilder('GET', basePath, handlers.index))
290
+ }
291
+
292
+ if (handlers.show) {
293
+ routes.push(new RouteBuilder('GET', `${basePath}/{id}`, handlers.show))
294
+ }
295
+
296
+ if (handlers.store) {
297
+ const builder = new RouteBuilder('POST', basePath, handlers.store)
298
+ if (validation?.store) {
299
+ builder.validate(validation.store)
300
+ }
301
+ routes.push(builder)
302
+ }
303
+
304
+ if (handlers.update) {
305
+ const builder = new RouteBuilder('PUT', `${basePath}/{id}`, handlers.update)
306
+ if (validation?.update) {
307
+ builder.validate(validation.update)
308
+ }
309
+ routes.push(builder)
310
+ }
311
+
312
+ if (handlers.destroy) {
313
+ routes.push(new RouteBuilder('DELETE', `${basePath}/{id}`, handlers.destroy))
314
+ }
315
+
316
+ return routes
317
+ },
318
+ }
319
+
320
+ /**
321
+ * Fluent router factory
322
+ */
323
+ export function createFluentRouter(): FluentRouter {
324
+ return new FluentRouter()
325
+ }
326
+
327
+ /**
328
+ * Middleware composition helpers
329
+ */
330
+ export const MiddlewareHelpers = {
331
+ /**
332
+ * Compose multiple middleware into one
333
+ */
334
+ compose: (...middleware: MiddlewareHandler[]): MiddlewareHandler => {
335
+ return async (req: EnhancedRequest, next: NextFunction): Promise<Response | null> => {
336
+ let index = 0
337
+
338
+ const dispatch = async (): Promise<Response | null> => {
339
+ if (index >= middleware.length) {
340
+ return await next()
341
+ }
342
+
343
+ const currentMiddleware = middleware[index++]
344
+ return await currentMiddleware(req, dispatch)
345
+ }
346
+
347
+ return await dispatch()
348
+ }
349
+ },
350
+
351
+ /**
352
+ * Create conditional middleware
353
+ */
354
+ when: (
355
+ condition: (req: EnhancedRequest) => boolean,
356
+ middleware: MiddlewareHandler,
357
+ ): MiddlewareHandler => {
358
+ return async (req: EnhancedRequest, next: NextFunction): Promise<Response | null> => {
359
+ if (condition(req)) {
360
+ return await middleware(req, next)
361
+ }
362
+ return await next()
363
+ }
364
+ },
365
+
366
+ /**
367
+ * Create middleware that runs unless condition is met
368
+ */
369
+ unless: (
370
+ condition: (req: EnhancedRequest) => boolean,
371
+ middleware: MiddlewareHandler,
372
+ ): MiddlewareHandler => {
373
+ return MiddlewareHelpers.when(req => !condition(req), middleware)
374
+ },
375
+
376
+ /**
377
+ * Create middleware group
378
+ */
379
+ group: (middleware: MiddlewareHandler[]): MiddlewareHandler => {
380
+ return MiddlewareHelpers.compose(...middleware)
381
+ },
382
+ }
383
+
384
+ /** Enhancement middleware type */
385
+ export type EnhancementMiddleware = (req: EnhancedRequest, next: () => Promise<Response>) => Promise<Response>
386
+
387
+ /**
388
+ * Request/Response enhancement presets
389
+ */
390
+ export const EnhancementPresets: {
391
+ api: () => EnhancementMiddleware[]
392
+ web: () => EnhancementMiddleware[]
393
+ validation: (rules: ValidationRules, config?: ValidatorConfig) => EnhancementMiddleware[]
394
+ } = {
395
+ /**
396
+ * API preset with JSON validation and response macros
397
+ */
398
+ api: (): EnhancementMiddleware[] => [
399
+ createEnhancementMiddleware(),
400
+ async (req: EnhancedRequest, next: () => Promise<Response>): Promise<Response> => {
401
+ try {
402
+ const response = await next()
403
+
404
+ // Add API headers
405
+ const headers = new Headers(response.headers)
406
+ headers.set('X-API-Version', '1.0')
407
+ headers.set('X-Response-Time', new Date().toISOString())
408
+
409
+ return new Response(response.body, {
410
+ status: response.status,
411
+ statusText: response.statusText,
412
+ headers,
413
+ })
414
+ }
415
+ catch (error) {
416
+ console.error(error)
417
+ // Return JSON error response
418
+ return ResponseWithMacros.callMacro('error', 'Internal server error', undefined, 500)
419
+ }
420
+ },
421
+ ],
422
+
423
+ /**
424
+ * Web preset with request enhancements and CSRF protection
425
+ */
426
+ web: (): EnhancementMiddleware[] => [
427
+ createEnhancementMiddleware(),
428
+ async (req: EnhancedRequest, next: () => Promise<Response>): Promise<Response> => {
429
+ // Add web-specific enhancements
430
+ ;(req as any).session = {} // Placeholder for session
431
+
432
+ return await next()
433
+ },
434
+ ],
435
+
436
+ /**
437
+ * Validation preset with comprehensive validation
438
+ */
439
+ validation: (rules: ValidationRules, config?: ValidatorConfig): EnhancementMiddleware[] => [
440
+ createEnhancementMiddleware(),
441
+ createValidationMiddleware(rules, config) as EnhancementMiddleware,
442
+ ],
443
+ }
@@ -0,0 +1,233 @@
1
+ import type { ActionHandler, EnhancedRequest, RouterConfig } from '../types'
2
+ import type { Router } from './router'
3
+ import { join } from 'node:path'
4
+ import { processHtmlTemplate, resolveViewPath, injectQueryPreservationScript } from '../utils'
5
+
6
+ /**
7
+ * View rendering extension for Router class
8
+ */
9
+ export function registerViewRendering(RouterClass: typeof Router): void {
10
+ Object.defineProperties(RouterClass.prototype, {
11
+ /**
12
+ * Render a view with data
13
+ */
14
+ renderView: {
15
+ async value(
16
+ view: string,
17
+ data: Record<string, any> = {},
18
+ options: { layout?: string } = {},
19
+ ): Promise<string> {
20
+ const viewsConfig = this.config.views || {
21
+ viewsPath: 'resources/views',
22
+ extensions: ['.html', '.stx'],
23
+ cache: Bun.env.NODE_ENV === 'production',
24
+ engine: 'auto',
25
+ }
26
+
27
+ // Check cache first if enabled
28
+ const cacheKey = `${view}:${options.layout || ''}`
29
+ if (viewsConfig.cache && this.templateCache.has(cacheKey)) {
30
+ return this.processTemplate(this.templateCache.get(cacheKey)!, data, viewsConfig)
31
+ }
32
+
33
+ // Resolve the view path
34
+ const viewPath = await resolveViewPath(view, viewsConfig.viewsPath, viewsConfig.extensions)
35
+ if (!viewPath) {
36
+ throw new Error(`View '${view}' not found`)
37
+ }
38
+
39
+ // Read the view file
40
+ let viewContent = await Bun.file(viewPath).text()
41
+
42
+ // Apply layout if specified or if a default layout is configured
43
+ const layoutName = options.layout || viewsConfig.defaultLayout
44
+ if (layoutName) {
45
+ const layoutPath = await resolveViewPath(
46
+ join('layouts', layoutName),
47
+ viewsConfig.viewsPath,
48
+ viewsConfig.extensions,
49
+ )
50
+
51
+ if (!layoutPath) {
52
+ throw new Error(`Layout '${layoutName}' not found`)
53
+ }
54
+
55
+ const layoutContent = await Bun.file(layoutPath).text()
56
+ // Replace {{content}} placeholder with the view content
57
+ viewContent = layoutContent.replace(/\{\{\s*content\s*\}\}/g, viewContent)
58
+ }
59
+
60
+ // Cache the template if caching is enabled
61
+ if (viewsConfig.cache) {
62
+ this.templateCache.set(cacheKey, viewContent)
63
+ }
64
+
65
+ // Process the template with data
66
+ return this.processTemplate(viewContent, data, viewsConfig)
67
+ },
68
+ writable: true,
69
+ configurable: true,
70
+ },
71
+
72
+ /**
73
+ * Process a template with data
74
+ */
75
+ processTemplate: {
76
+ async value(
77
+ template: string,
78
+ data: Record<string, any>,
79
+ viewConfig: RouterConfig['views'],
80
+ ): Promise<string> {
81
+ // Choose template engine based on configuration
82
+ const engine = viewConfig?.engine || 'auto'
83
+
84
+ if (engine === 'custom' && viewConfig?.customRenderer) {
85
+ return viewConfig.customRenderer(template, data, {})
86
+ }
87
+
88
+ // Default to simple template processing
89
+ let processedTemplate = processHtmlTemplate(template, data)
90
+
91
+ // Apply minification if configured
92
+ if (viewConfig?.minify?.enabled) {
93
+ try {
94
+ const _minifyOptions = viewConfig.minify.options || {
95
+ removeComments: true,
96
+ collapseWhitespace: true,
97
+ minifyJS: true,
98
+ minifyCSS: true,
99
+ }
100
+
101
+ // In a real implementation, you would use a library like html-minifier
102
+ // This is just a placeholder
103
+ processedTemplate = processedTemplate
104
+ .replace(/\s+/g, ' ')
105
+ .replace(/<!--[\s\S]*?-->/g, '')
106
+ }
107
+ catch (err) {
108
+ console.error('Error minifying HTML:', err)
109
+ }
110
+ }
111
+
112
+ return processedTemplate
113
+ },
114
+ writable: true,
115
+ configurable: true,
116
+ },
117
+
118
+ /**
119
+ * Register a view route
120
+ */
121
+ view: {
122
+ value(
123
+ path: string,
124
+ viewOrData: string | Record<string, any>,
125
+ dataOrOptions: Record<string, any> | { layout?: string, status?: number, headers?: Record<string, string> } = {},
126
+ optionsOrType: { layout?: string, status?: number, headers?: Record<string, string> } | 'web' | 'api' = {},
127
+ typeOrName: 'web' | 'api' | string = 'web',
128
+ name?: string,
129
+ ): Router {
130
+ let view: string
131
+ let data: Record<string, any> = {}
132
+ let options: { layout?: string, status?: number, headers?: Record<string, string> } = {}
133
+ let type: 'web' | 'api' = 'web'
134
+ let routeName: string | undefined
135
+
136
+ // Parse the flexible parameters
137
+ if (typeof viewOrData === 'string') {
138
+ view = viewOrData
139
+
140
+ if (typeof dataOrOptions === 'object' && !Array.isArray(dataOrOptions)) {
141
+ // If dataOrOptions has layout, status, or headers, it's options
142
+ if ('layout' in dataOrOptions || 'status' in dataOrOptions || 'headers' in dataOrOptions) {
143
+ options = dataOrOptions as { layout?: string, status?: number, headers?: Record<string, string> }
144
+ }
145
+ else {
146
+ // Otherwise it's data
147
+ data = dataOrOptions
148
+ }
149
+ }
150
+
151
+ if (typeof optionsOrType === 'object') {
152
+ options = { ...options, ...optionsOrType }
153
+ }
154
+ else if (typeof optionsOrType === 'string') {
155
+ type = optionsOrType as 'web' | 'api'
156
+ }
157
+
158
+ if (typeof typeOrName === 'string') {
159
+ if (typeOrName === 'web' || typeOrName === 'api') {
160
+ type = typeOrName
161
+ }
162
+ else {
163
+ routeName = typeOrName
164
+ }
165
+ }
166
+
167
+ if (name) {
168
+ routeName = name
169
+ }
170
+ }
171
+ else {
172
+ // viewOrData is actually data
173
+ data = viewOrData
174
+
175
+ if (typeof dataOrOptions === 'string') {
176
+ view = dataOrOptions
177
+ }
178
+ else {
179
+ throw new TypeError('View name must be a string')
180
+ }
181
+
182
+ if (typeof optionsOrType === 'object') {
183
+ options = optionsOrType
184
+ }
185
+ else if (typeof optionsOrType === 'string') {
186
+ if (optionsOrType === 'web' || optionsOrType === 'api') {
187
+ type = optionsOrType
188
+ }
189
+ else {
190
+ view = optionsOrType
191
+ type = 'web'
192
+ }
193
+ }
194
+ }
195
+
196
+ // Create the route handler
197
+ const handler: ActionHandler = async (_req: EnhancedRequest) => {
198
+ let renderedView = await this.renderView(view, data, {
199
+ layout: options.layout,
200
+ })
201
+
202
+ // Inject query preservation script if configured
203
+ const queryPreservationConfig = this.config?.queryPreservation
204
+ if (queryPreservationConfig?.enabled !== false && queryPreservationConfig?.preserve?.length) {
205
+ renderedView = injectQueryPreservationScript(renderedView, queryPreservationConfig)
206
+ }
207
+
208
+ const headers = new Headers()
209
+ headers.set('Content-Type', 'text/html; charset=utf-8')
210
+
211
+ // Add custom headers if provided
212
+ if (options.headers) {
213
+ for (const [key, value] of Object.entries(options.headers)) {
214
+ headers.set(key, value)
215
+ }
216
+ }
217
+
218
+ return new Response(renderedView, {
219
+ status: options.status || 200,
220
+ headers,
221
+ })
222
+ }
223
+
224
+ // Register the route
225
+ this.get(path, handler, type, routeName)
226
+
227
+ return this
228
+ },
229
+ writable: true,
230
+ configurable: true,
231
+ },
232
+ })
233
+ }