@stacksjs/bun-router 0.0.17 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/container/service-provider.d.ts +3 -3
  3. package/dist/development/performance-profiler.d.ts +3 -3
  4. package/dist/development/route-debugger.d.ts +1 -1
  5. package/dist/development/route-inspector.d.ts +2 -2
  6. package/dist/observability/integration.d.ts +1 -1
  7. package/dist/response/macros.d.ts +1 -1
  8. package/dist/router/index.d.ts +7 -7
  9. package/dist/router/router.d.ts +0 -32
  10. package/dist/testing/performance-testing.d.ts +2 -2
  11. package/dist/testing/test-client.d.ts +1 -1
  12. package/dist/testing/websocket-testing.d.ts +1 -1
  13. package/package.json +2 -3
  14. package/src/auth.ts +0 -489
  15. package/src/cache/lru-cache.ts +0 -457
  16. package/src/cache/middleware-memoization.ts +0 -531
  17. package/src/cache/route-cache-warmer.ts +0 -486
  18. package/src/cache/sqlite-cache.ts +0 -783
  19. package/src/cache/streaming-cache.ts +0 -572
  20. package/src/cli/colors.ts +0 -29
  21. package/src/cli/index.ts +0 -287
  22. package/src/cli/middleware.ts +0 -291
  23. package/src/cli/openapi.ts +0 -407
  24. package/src/cli/router.ts +0 -188
  25. package/src/cli/routes.ts +0 -265
  26. package/src/cli/utils.ts +0 -531
  27. package/src/cli.ts +0 -5
  28. package/src/config.ts +0 -322
  29. package/src/container/container.ts +0 -786
  30. package/src/container/contextual-binding.ts +0 -606
  31. package/src/container/decorators.ts +0 -368
  32. package/src/container/index.ts +0 -49
  33. package/src/container/service-provider.ts +0 -596
  34. package/src/development/hot-reload.ts +0 -673
  35. package/src/development/index.ts +0 -499
  36. package/src/development/performance-profiler.ts +0 -717
  37. package/src/development/route-debugger.ts +0 -527
  38. package/src/development/route-inspector.ts +0 -749
  39. package/src/development/typescript-utilities.ts +0 -682
  40. package/src/docs.ts +0 -397
  41. package/src/errors/circuit-breaker.ts +0 -733
  42. package/src/errors/error-handler.ts +0 -569
  43. package/src/errors/error-reporting.ts +0 -672
  44. package/src/errors/exceptions.ts +0 -536
  45. package/src/errors/graceful-degradation.ts +0 -623
  46. package/src/errors/index.ts +0 -21
  47. package/src/errors/router-errors.ts +0 -632
  48. package/src/file-serving/static-files.ts +0 -718
  49. package/src/index.ts +0 -66
  50. package/src/middleware/auth.ts +0 -220
  51. package/src/middleware/content_security_policy.ts +0 -215
  52. package/src/middleware/cors.ts +0 -142
  53. package/src/middleware/csrf.ts +0 -166
  54. package/src/middleware/ddos_protection.ts +0 -279
  55. package/src/middleware/file_security.ts +0 -191
  56. package/src/middleware/file_upload.ts +0 -275
  57. package/src/middleware/helmet.ts +0 -268
  58. package/src/middleware/index.ts +0 -117
  59. package/src/middleware/input_validation.ts +0 -453
  60. package/src/middleware/json_body.ts +0 -37
  61. package/src/middleware/performance_alerting.ts +0 -540
  62. package/src/middleware/performance_dashboard.ts +0 -661
  63. package/src/middleware/performance_monitor.ts +0 -945
  64. package/src/middleware/pipeline.ts +0 -489
  65. package/src/middleware/rate_limit.ts +0 -251
  66. package/src/middleware/request_id.ts +0 -36
  67. package/src/middleware/request_signing.ts +0 -638
  68. package/src/middleware/request_tracer.ts +0 -653
  69. package/src/middleware/response_cache.ts +0 -778
  70. package/src/middleware/security.ts +0 -482
  71. package/src/middleware/security_suite.ts +0 -257
  72. package/src/middleware/session.ts +0 -91
  73. package/src/model-binding/index.ts +0 -18
  74. package/src/model-binding/model-middleware.ts +0 -425
  75. package/src/model-binding/model-registry.ts +0 -550
  76. package/src/model-binding.ts +0 -370
  77. package/src/model-resolver-factory.ts +0 -106
  78. package/src/observability/correlation.ts +0 -691
  79. package/src/observability/health-checks.ts +0 -729
  80. package/src/observability/index.ts +0 -184
  81. package/src/observability/integration.ts +0 -548
  82. package/src/observability/metrics.ts +0 -753
  83. package/src/observability/tracing.ts +0 -638
  84. package/src/optimization/bun-utilities.ts +0 -778
  85. package/src/query-builder-integration.ts +0 -137
  86. package/src/request/context.ts +0 -109
  87. package/src/request/enhanced-request.ts +0 -876
  88. package/src/request/macros.ts +0 -822
  89. package/src/response/macros.ts +0 -665
  90. package/src/response/response-factory.ts +0 -596
  91. package/src/router/api-routes.ts +0 -243
  92. package/src/router/file-based-routing.ts +0 -697
  93. package/src/router/file-streaming.ts +0 -383
  94. package/src/router/fluent-routing.ts +0 -866
  95. package/src/router/group-organization.ts +0 -229
  96. package/src/router/handler-resolver.ts +0 -327
  97. package/src/router/http-methods.ts +0 -407
  98. package/src/router/index.ts +0 -193
  99. package/src/router/middleware-groups.ts +0 -222
  100. package/src/router/middleware-integration.ts +0 -399
  101. package/src/router/middleware.ts +0 -234
  102. package/src/router/model-binding.ts +0 -215
  103. package/src/router/optimized-route-matching.ts +0 -302
  104. package/src/router/route-building.ts +0 -221
  105. package/src/router/route-compiler.ts +0 -691
  106. package/src/router/route-matching.ts +0 -368
  107. package/src/router/route-trie.ts +0 -450
  108. package/src/router/router.ts +0 -1616
  109. package/src/router/server.ts +0 -684
  110. package/src/router/validation-integration.ts +0 -449
  111. package/src/router/view-rendering.ts +0 -233
  112. package/src/router/websocket.ts +0 -100
  113. package/src/routing/route-caching.ts +0 -402
  114. package/src/routing/route-throttling.ts +0 -469
  115. package/src/routing/subdomain-routing.ts +0 -492
  116. package/src/session/database-store.ts +0 -109
  117. package/src/session/file-store.ts +0 -148
  118. package/src/session/index.ts +0 -244
  119. package/src/session/memory-store.ts +0 -88
  120. package/src/session/redis-store.ts +0 -93
  121. package/src/streaming/index.ts +0 -17
  122. package/src/streaming/sse-handler.ts +0 -482
  123. package/src/streaming/stream-handler.ts +0 -552
  124. package/src/testing/auth-testing.ts +0 -448
  125. package/src/testing/file-upload-testing.ts +0 -543
  126. package/src/testing/index.ts +0 -10
  127. package/src/testing/middleware-testing.ts +0 -322
  128. package/src/testing/model-binding-testing.ts +0 -645
  129. package/src/testing/performance-testing.ts +0 -738
  130. package/src/testing/test-client.ts +0 -310
  131. package/src/testing/test-request.ts +0 -315
  132. package/src/testing/test-response.ts +0 -332
  133. package/src/testing/types.ts +0 -224
  134. package/src/testing/websocket-testing.ts +0 -590
  135. package/src/types/controller-types.ts +0 -385
  136. package/src/types/core.ts +0 -683
  137. package/src/types/middleware-types.ts +0 -422
  138. package/src/types/request-response-augmentation.ts +0 -489
  139. package/src/types/route-inference.ts +0 -372
  140. package/src/types.ts +0 -2123
  141. package/src/url.ts +0 -131
  142. package/src/utils/index.ts +0 -1
  143. package/src/utils/query-preservation.ts +0 -201
  144. package/src/utils.ts +0 -395
  145. package/src/validation/validator.ts +0 -688
  146. package/src/websocket/clustering.ts +0 -769
@@ -1,450 +0,0 @@
1
- import type { HTTPMethod, Route } from '../types'
2
-
3
- /**
4
- * Route segment types for the trie
5
- */
6
- export type RouteSegmentType = 'static' | 'parameter' | 'wildcard' | 'optional'
7
-
8
- export interface RouteSegment {
9
- type: RouteSegmentType
10
- value: string
11
- paramName?: string
12
- pattern?: RegExp
13
- optional?: boolean
14
- }
15
-
16
- export interface CompiledRoute {
17
- route: Route
18
- segments: RouteSegment[]
19
- paramNames: string[]
20
- priority: number
21
- staticScore: number
22
- dynamicScore: number
23
- }
24
-
25
- /**
26
- * Trie node for efficient route matching
27
- */
28
- export class TrieNode {
29
- children: Map<string, TrieNode> = new Map()
30
- paramChild: TrieNode | null = null
31
- wildcardChild: TrieNode | null = null
32
- routes: Map<HTTPMethod, CompiledRoute> = new Map()
33
- paramName: string | null = null
34
- pattern: RegExp | null = null
35
- isEndpoint: boolean = false
36
-
37
- /**
38
- * Add a route to this node
39
- */
40
- addRoute(method: HTTPMethod, compiledRoute: CompiledRoute): void {
41
- this.routes.set(method, compiledRoute)
42
- this.isEndpoint = true
43
- }
44
-
45
- /**
46
- * Get route for a specific HTTP method
47
- */
48
- getRoute(method: HTTPMethod): CompiledRoute | undefined {
49
- return this.routes.get(method)
50
- }
51
-
52
- /**
53
- * Get all routes at this node
54
- */
55
- getAllRoutes(): CompiledRoute[] {
56
- return Array.from(this.routes.values())
57
- }
58
- }
59
-
60
- /**
61
- * Route matching result with extracted parameters
62
- */
63
- export interface RouteMatch {
64
- route: Route
65
- params: Record<string, string>
66
- score: number
67
- }
68
-
69
- /**
70
- * High-performance route trie for O(log n) route matching
71
- */
72
- export class RouteTrie {
73
- private root: TrieNode = new TrieNode()
74
- private compiledRoutes: Map<string, CompiledRoute> = new Map()
75
- private methodTries: Map<HTTPMethod, TrieNode> = new Map()
76
-
77
- constructor() {
78
- // Initialize method-specific tries for faster filtering
79
- const methods: HTTPMethod[] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT']
80
- for (const method of methods) {
81
- this.methodTries.set(method, new TrieNode())
82
- }
83
- }
84
-
85
- /**
86
- * Compile a route pattern into segments
87
- */
88
- compileRoute(route: Route): CompiledRoute {
89
- // Include constraints in the cache key if present
90
- let cacheKey = `${route.method}:${route.path}`
91
- if (route.constraints && !Array.isArray(route.constraints)) {
92
- const constraintsRecord = route.constraints as Record<string, string>
93
- const constraintKeys = Object.keys(constraintsRecord).sort()
94
- const constraintString = constraintKeys
95
- .map(key => `${key}:${constraintsRecord[key]}`)
96
- .join('|')
97
- cacheKey = `${route.method}:${route.path}#${constraintString}`
98
- }
99
-
100
- if (this.compiledRoutes.has(cacheKey)) {
101
- return this.compiledRoutes.get(cacheKey)!
102
- }
103
-
104
- const segments = this.parsePathSegments(route.path)
105
- const paramNames = segments
106
- .filter(seg => seg.type === 'parameter')
107
- .map(seg => seg.paramName!)
108
-
109
- // Apply constraints to segments if they exist
110
- if (route.constraints && !Array.isArray(route.constraints)) {
111
- const constraintsRecord = route.constraints as Record<string, string>
112
- for (const segment of segments) {
113
- if (segment.type === 'parameter' && segment.paramName
114
- && constraintsRecord[segment.paramName]) {
115
- segment.pattern = new RegExp(`^${constraintsRecord[segment.paramName]}$`)
116
- }
117
- }
118
- }
119
-
120
- const priority = this.calculateRoutePriority(segments)
121
- const staticScore = segments.filter(seg => seg.type === 'static').length
122
- const dynamicScore = segments.filter(seg => seg.type !== 'static').length
123
-
124
- const compiled: CompiledRoute = {
125
- route,
126
- segments,
127
- paramNames,
128
- priority,
129
- staticScore,
130
- dynamicScore,
131
- }
132
-
133
- this.compiledRoutes.set(cacheKey, compiled)
134
- return compiled
135
- }
136
-
137
- /**
138
- * Parse path into segments
139
- */
140
- private parsePathSegments(path: string): RouteSegment[] {
141
- const segments: RouteSegment[] = []
142
- const parts = path.split('/').filter(part => part.length > 0)
143
-
144
- for (const part of parts) {
145
- if (part === '*') {
146
- segments.push({
147
- type: 'wildcard',
148
- value: '*',
149
- })
150
- }
151
- else if (part.startsWith('{') && part.endsWith('}')) {
152
- const paramPart = part.slice(1, -1)
153
- const [paramName, pattern] = paramPart.split(':')
154
-
155
- segments.push({
156
- type: 'parameter',
157
- value: part,
158
- paramName: paramName.replace('?', ''),
159
- pattern: pattern ? new RegExp(`^${pattern}$`) : undefined,
160
- optional: paramPart.endsWith('?'),
161
- })
162
- }
163
- else if (part.includes('{')) {
164
- // Mixed static/dynamic segment like "user-{id}"
165
- const regex = part.replace(/\{([^}:]+)(?::([^}]+))?\}/g, (_match, _name, pattern) => {
166
- return pattern ? `(${pattern})` : '([^/]+)'
167
- })
168
-
169
- const paramNames = Array.from(part.matchAll(/\{([^}:]+)(?::([^}]+))?\}/g))
170
- .map(match => match[1].replace('?', ''))
171
-
172
- segments.push({
173
- type: 'parameter',
174
- value: part,
175
- paramName: paramNames[0], // For simplicity, use first param name
176
- pattern: new RegExp(`^${regex}$`),
177
- })
178
- }
179
- else {
180
- segments.push({
181
- type: 'static',
182
- value: part,
183
- })
184
- }
185
- }
186
-
187
- return segments
188
- }
189
-
190
- /**
191
- * Calculate route priority (higher = more specific)
192
- */
193
- private calculateRoutePriority(segments: RouteSegment[]): number {
194
- let priority = 0
195
-
196
- for (let i = 0; i < segments.length; i++) {
197
- const segment = segments[i]
198
- const positionWeight = segments.length - i // Earlier segments have higher weight
199
-
200
- switch (segment.type) {
201
- case 'static':
202
- priority += positionWeight * 1000
203
- break
204
- case 'parameter':
205
- if (segment.pattern) {
206
- priority += positionWeight * 100 // Constrained params have higher priority
207
- }
208
- else {
209
- priority += positionWeight * 10
210
- }
211
- break
212
- case 'wildcard':
213
- priority += positionWeight * 1 // Wildcards have lowest priority
214
- break
215
- }
216
- }
217
-
218
- return priority
219
- }
220
-
221
- /**
222
- * Add a route to the trie
223
- */
224
- addRoute(route: Route): void {
225
- const compiled = this.compileRoute(route)
226
-
227
- // Add to main trie
228
- this.insertRoute(this.root, compiled, 0)
229
-
230
- // Add to method-specific trie for faster filtering
231
- const methodTrie = this.methodTries.get(route.method as HTTPMethod)
232
- if (methodTrie) {
233
- this.insertRoute(methodTrie, compiled, 0)
234
- }
235
- }
236
-
237
- /**
238
- * Insert compiled route into trie
239
- */
240
- private insertRoute(node: TrieNode, compiled: CompiledRoute, segmentIndex: number): void {
241
- if (segmentIndex >= compiled.segments.length) {
242
- node.addRoute(compiled.route.method as HTTPMethod, compiled)
243
- return
244
- }
245
-
246
- const segment = compiled.segments[segmentIndex]
247
-
248
- switch (segment.type) {
249
- case 'static':
250
- if (!node.children.has(segment.value)) {
251
- node.children.set(segment.value, new TrieNode())
252
- }
253
- this.insertRoute(node.children.get(segment.value)!, compiled, segmentIndex + 1)
254
- break
255
-
256
- case 'parameter':
257
- if (!node.paramChild) {
258
- node.paramChild = new TrieNode()
259
- node.paramChild.paramName = segment.paramName!
260
- node.paramChild.pattern = segment.pattern || null
261
- }
262
- this.insertRoute(node.paramChild, compiled, segmentIndex + 1)
263
- break
264
-
265
- case 'wildcard':
266
- if (!node.wildcardChild) {
267
- node.wildcardChild = new TrieNode()
268
- }
269
- this.insertRoute(node.wildcardChild, compiled, segmentIndex + 1)
270
- break
271
- }
272
- }
273
-
274
- /**
275
- * Match a path against the trie
276
- */
277
- match(path: string, method: HTTPMethod): RouteMatch | null {
278
- const segments = path.split('/').filter(seg => seg.length > 0)
279
-
280
- // Try method-specific trie first for better performance
281
- const methodTrie = this.methodTries.get(method)
282
- if (methodTrie) {
283
- const result = this.matchSegments(methodTrie, segments, 0, {}, method)
284
- if (result)
285
- return result
286
- }
287
-
288
- // Fallback to main trie
289
- return this.matchSegments(this.root, segments, 0, {}, method)
290
- }
291
-
292
- /**
293
- * Recursively match path segments.
294
- *
295
- * Candidates are tried in specificity order — static, then parameter,
296
- * then wildcard — and the first full match wins. This both fixes the
297
- * old behavior (where a wildcard sibling could shadow a static route)
298
- * and avoids allocating candidate arrays and params copies per segment:
299
- * `params` is mutated in place and rolled back on backtrack.
300
- */
301
- private matchSegments(
302
- node: TrieNode,
303
- segments: string[],
304
- segmentIndex: number,
305
- params: Record<string, string>,
306
- method: HTTPMethod,
307
- ): RouteMatch | null {
308
- // If we've matched all segments, check for route
309
- if (segmentIndex >= segments.length) {
310
- const compiled = node.getRoute(method)
311
- if (compiled) {
312
- return {
313
- route: compiled.route,
314
- params,
315
- score: compiled.priority,
316
- }
317
- }
318
- return null
319
- }
320
-
321
- const segment = segments[segmentIndex]
322
-
323
- // Try static match first (highest priority)
324
- const staticChild = node.children.get(segment)
325
- if (staticChild) {
326
- const match = this.matchSegments(staticChild, segments, segmentIndex + 1, params, method)
327
- if (match)
328
- return match
329
- }
330
-
331
- // Try parameter match
332
- const paramNode = node.paramChild
333
- if (paramNode && paramNode.paramName
334
- && (!paramNode.pattern || paramNode.pattern.test(segment))) {
335
- const previous = params[paramNode.paramName]
336
- params[paramNode.paramName] = segment
337
- const match = this.matchSegments(paramNode, segments, segmentIndex + 1, params, method)
338
- if (match)
339
- return match
340
- // Backtrack: restore params before trying lower-priority branches
341
- if (previous === undefined)
342
- delete params[paramNode.paramName]
343
- else
344
- params[paramNode.paramName] = previous
345
- }
346
-
347
- // Try wildcard match (lowest priority) — consumes all remaining segments
348
- if (node.wildcardChild) {
349
- const compiled = node.wildcardChild.getRoute(method)
350
- if (compiled) {
351
- params.wildcard = segments.slice(segmentIndex).join('/')
352
- return {
353
- route: compiled.route,
354
- params,
355
- score: compiled.priority,
356
- }
357
- }
358
- }
359
-
360
- return null
361
- }
362
-
363
- /**
364
- * Get all routes for debugging
365
- */
366
- getAllRoutes(): CompiledRoute[] {
367
- return Array.from(this.compiledRoutes.values())
368
- }
369
-
370
- /**
371
- * Remove a route from the trie
372
- */
373
- removeRoute(route: Route): void {
374
- // Generate the cache key for this route
375
- let cacheKey = `${route.method}:${route.path}`
376
- if (route.constraints && !Array.isArray(route.constraints)) {
377
- const constraintsRecord = route.constraints as Record<string, string>
378
- const constraintKeys = Object.keys(constraintsRecord).sort()
379
- const constraintString = constraintKeys
380
- .map(key => `${key}:${constraintsRecord[key]}`)
381
- .join('|')
382
- cacheKey = `${route.method}:${route.path}#${constraintString}`
383
- }
384
-
385
- // Remove from compiled routes cache
386
- this.compiledRoutes.delete(cacheKey)
387
-
388
- // We don't actually need to remove nodes from the trie structure
389
- // since we'll be adding the updated route back immediately
390
- // This is a performance optimization to avoid complex trie node removal
391
- }
392
-
393
- /**
394
- * Clear the trie
395
- */
396
- clear(): void {
397
- this.root = new TrieNode()
398
- this.compiledRoutes.clear()
399
-
400
- for (const [method] of this.methodTries) {
401
- this.methodTries.set(method, new TrieNode())
402
- }
403
- }
404
-
405
- /**
406
- * Get trie statistics for debugging
407
- */
408
- getStats(): {
409
- totalRoutes: number
410
- totalNodes: number
411
- averageDepth: number
412
- methodDistribution: Record<string, number>
413
- } {
414
- const stats = {
415
- totalRoutes: this.compiledRoutes.size,
416
- totalNodes: this.countNodes(this.root),
417
- averageDepth: 0,
418
- methodDistribution: {} as Record<string, number>,
419
- }
420
-
421
- // Calculate method distribution
422
- for (const compiled of this.compiledRoutes.values()) {
423
- const method = compiled.route.method
424
- stats.methodDistribution[method] = (stats.methodDistribution[method] || 0) + 1
425
- }
426
-
427
- return stats
428
- }
429
-
430
- /**
431
- * Count total nodes in trie
432
- */
433
- private countNodes(node: TrieNode): number {
434
- let count = 1
435
-
436
- for (const child of node.children.values()) {
437
- count += this.countNodes(child)
438
- }
439
-
440
- if (node.paramChild) {
441
- count += this.countNodes(node.paramChild)
442
- }
443
-
444
- if (node.wildcardChild) {
445
- count += this.countNodes(node.wildcardChild)
446
- }
447
-
448
- return count
449
- }
450
- }