@stacksjs/bun-router 0.0.15 → 0.0.17
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/dist/auth.d.ts +22 -8
- package/dist/chunk-1ahs68ys.js +18 -0
- package/dist/{chunk-j0e7z7hd.js → chunk-cgptvjdf.js} +153 -75
- package/dist/chunk-g3ybefhg.js +1923 -0
- package/dist/cli.js +13 -11
- package/dist/container/container.d.ts +1 -0
- package/dist/container/contextual-binding.d.ts +0 -1
- package/dist/container/decorators.d.ts +2 -5
- package/dist/container/index.d.ts +16 -0
- package/dist/container/index.js +322 -0
- package/dist/file-serving/static-files.d.ts +16 -0
- package/dist/index.d.ts +17 -1
- package/dist/index.js +1086 -1270
- package/dist/middleware/cors.d.ts +9 -0
- package/dist/middleware/csrf.d.ts +7 -0
- package/dist/middleware/ddos_protection.d.ts +16 -1
- package/dist/middleware/rate_limit.d.ts +7 -1
- package/dist/middleware/request_tracer.d.ts +15 -9
- package/dist/middleware/response_cache.d.ts +2 -1
- package/dist/request/context.d.ts +12 -1
- package/dist/request/macros.d.ts +40 -2
- package/dist/response/macros.d.ts +3 -3
- package/dist/router/fluent-routing.d.ts +50 -13
- package/dist/router/handler-resolver.d.ts +8 -0
- package/dist/router/index.d.ts +2 -0
- package/dist/router/route-compiler.d.ts +8 -10
- package/dist/router/route-trie.d.ts +7 -1
- package/dist/router/router.d.ts +13 -2
- package/dist/router/validation-integration.d.ts +10 -4
- package/dist/types/middleware-types.d.ts +1 -1
- package/dist/types/route-inference.d.ts +9 -2
- package/dist/types.d.ts +62 -9
- package/dist/utils.d.ts +1 -1
- package/package.json +11 -1
- package/src/auth.ts +32 -12
- package/src/container/container.ts +58 -12
- package/src/container/contextual-binding.ts +4 -1
- package/src/container/decorators.ts +16 -7
- package/src/container/index.ts +49 -0
- package/src/errors/circuit-breaker.ts +3 -2
- package/src/errors/graceful-degradation.ts +2 -0
- package/src/file-serving/static-files.ts +144 -7
- package/src/index.ts +53 -1
- package/src/middleware/cors.ts +76 -8
- package/src/middleware/csrf.ts +80 -22
- package/src/middleware/ddos_protection.ts +27 -3
- package/src/middleware/input_validation.ts +10 -6
- package/src/middleware/performance_alerting.ts +2 -0
- package/src/middleware/performance_monitor.ts +2 -0
- package/src/middleware/rate_limit.ts +7 -1
- package/src/middleware/request_signing.ts +2 -0
- package/src/middleware/request_tracer.ts +34 -17
- package/src/middleware/response_cache.ts +48 -13
- package/src/middleware/session.ts +3 -3
- package/src/observability/metrics.ts +1 -1
- package/src/request/context.ts +50 -3
- package/src/request/enhanced-request.ts +20 -1
- package/src/request/macros.ts +183 -49
- package/src/response/macros.ts +3 -3
- package/src/router/file-based-routing.ts +17 -10
- package/src/router/fluent-routing.ts +117 -48
- package/src/router/group-organization.ts +17 -1
- package/src/router/handler-resolver.ts +36 -0
- package/src/router/http-methods.ts +33 -3
- package/src/router/index.ts +6 -0
- package/src/router/middleware.ts +3 -0
- package/src/router/optimized-route-matching.ts +58 -9
- package/src/router/route-compiler.ts +62 -73
- package/src/router/route-matching.ts +19 -0
- package/src/router/route-trie.ts +34 -48
- package/src/router/router.ts +72 -60
- package/src/router/server.ts +361 -139
- package/src/router/validation-integration.ts +11 -5
- package/src/testing/auth-testing.ts +6 -4
- package/src/types/middleware-types.ts +7 -4
- package/src/types/route-inference.ts +29 -14
- package/src/types.ts +63 -7
- package/src/url.ts +7 -2
- package/src/utils.ts +107 -39
- package/src/validation/validator.ts +7 -4
- package/src/websocket/clustering.ts +8 -1
- package/dist/router/fluent-router.d.ts +0 -315
- package/src/router/fluent-router.ts +0 -927
package/src/router/router.ts
CHANGED
|
@@ -81,6 +81,14 @@ export class Router {
|
|
|
81
81
|
// Middleware pipeline for advanced features
|
|
82
82
|
_middlewarePipeline?: MiddlewarePipeline
|
|
83
83
|
|
|
84
|
+
// Bumped whenever global middleware changes; per-route compiled chains
|
|
85
|
+
// cache against this epoch and rebuild when it moves
|
|
86
|
+
_mwEpoch = 0
|
|
87
|
+
|
|
88
|
+
// Memoized getAllowedMethods results (the 405-vs-404 scan), keyed by
|
|
89
|
+
// domain:pathname. Cleared whenever routes change.
|
|
90
|
+
_allowedMethodsCache: Map<string, string[]> = new Map()
|
|
91
|
+
|
|
84
92
|
config: RouterConfig = {
|
|
85
93
|
verbose: false,
|
|
86
94
|
routesPath: 'routes',
|
|
@@ -233,6 +241,7 @@ export class Router {
|
|
|
233
241
|
*/
|
|
234
242
|
invalidateCache(): void {
|
|
235
243
|
this.routeCache.clear()
|
|
244
|
+
this._allowedMethodsCache.clear()
|
|
236
245
|
}
|
|
237
246
|
|
|
238
247
|
/**
|
|
@@ -758,61 +767,46 @@ export class Router {
|
|
|
758
767
|
*/
|
|
759
768
|
getAllowedMethods(path: string, domain?: string): string[] {
|
|
760
769
|
const url = new URL(path, 'http://localhost')
|
|
761
|
-
const methods: Set<string> = new Set()
|
|
762
|
-
const allMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD']
|
|
763
|
-
|
|
764
|
-
for (const method of allMethods) {
|
|
765
|
-
// Check static routes
|
|
766
|
-
if (this.staticRoutes.has(method)) {
|
|
767
|
-
const staticRoute = this.staticRoutes.get(method)!.get(url.pathname)
|
|
768
|
-
if (staticRoute && (!domain || !staticRoute.domain || staticRoute.domain === domain)) {
|
|
769
|
-
methods.add(method)
|
|
770
|
-
continue
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
770
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
771
|
+
// Memoized per path: every unmatched request pays this scan for its
|
|
772
|
+
// 405-vs-404 decision, and 404 floods tend to hammer the same paths
|
|
773
|
+
const cacheKey = `${domain || ''}:${url.pathname}`
|
|
774
|
+
const cached = this._allowedMethodsCache.get(cacheKey)
|
|
775
|
+
if (cached) {
|
|
776
|
+
return cached
|
|
777
|
+
}
|
|
778
778
|
|
|
779
|
-
|
|
780
|
-
const methodRoutes = potentialRoutes.filter((route: Route) => route.method === method)
|
|
779
|
+
const methods: Set<string> = new Set()
|
|
781
780
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
}
|
|
781
|
+
// Static routes: one map lookup per registered method
|
|
782
|
+
for (const [method, routesByPath] of this.staticRoutes) {
|
|
783
|
+
const staticRoute = routesByPath.get(url.pathname)
|
|
784
|
+
if (staticRoute && (!domain || !staticRoute.domain || staticRoute.domain === domain)) {
|
|
785
|
+
methods.add(method)
|
|
788
786
|
}
|
|
787
|
+
}
|
|
789
788
|
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
methods.add(method)
|
|
797
|
-
break
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
}
|
|
789
|
+
// Dynamic routes: a single pass over the candidate pool covers exact,
|
|
790
|
+
// pattern, and wildcard matches for every method at once (the old
|
|
791
|
+
// implementation re-scanned the table once per HTTP method)
|
|
792
|
+
const potentialRoutes: Route[] = domain && this.domains[domain]
|
|
793
|
+
? this.domains[domain]
|
|
794
|
+
: this.routes
|
|
802
795
|
|
|
803
|
-
|
|
804
|
-
if (
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
796
|
+
for (const route of potentialRoutes) {
|
|
797
|
+
if (methods.has(route.method)) {
|
|
798
|
+
continue
|
|
799
|
+
}
|
|
800
|
+
if (route.path === url.pathname) {
|
|
801
|
+
methods.add(route.method)
|
|
802
|
+
continue
|
|
803
|
+
}
|
|
804
|
+
if (route.pattern && route.pattern.exec(url)) {
|
|
805
|
+
methods.add(route.method)
|
|
806
|
+
continue
|
|
807
|
+
}
|
|
808
|
+
if (route.path.endsWith('*') && url.pathname.startsWith(route.path.slice(0, -1))) {
|
|
809
|
+
methods.add(route.method)
|
|
816
810
|
}
|
|
817
811
|
}
|
|
818
812
|
|
|
@@ -821,7 +815,12 @@ export class Router {
|
|
|
821
815
|
methods.add('HEAD')
|
|
822
816
|
}
|
|
823
817
|
|
|
824
|
-
|
|
818
|
+
const result = Array.from(methods)
|
|
819
|
+
if (this._allowedMethodsCache.size >= 10_000) {
|
|
820
|
+
this._allowedMethodsCache.clear()
|
|
821
|
+
}
|
|
822
|
+
this._allowedMethodsCache.set(cacheKey, result)
|
|
823
|
+
return result
|
|
825
824
|
}
|
|
826
825
|
|
|
827
826
|
/**
|
|
@@ -1350,9 +1349,16 @@ export class Router {
|
|
|
1350
1349
|
}
|
|
1351
1350
|
|
|
1352
1351
|
/**
|
|
1353
|
-
* Create a route group with prefix and middleware
|
|
1352
|
+
* Create a route group with prefix and middleware.
|
|
1353
|
+
*
|
|
1354
|
+
* Synchronous callbacks return the router for chaining. Asynchronous
|
|
1355
|
+
* callbacks return a promise that resolves once the callback (and any
|
|
1356
|
+
* routes it registers) has finished — await it, or routes registered
|
|
1357
|
+
* after an `await` inside the callback would lose the group prefix.
|
|
1354
1358
|
*/
|
|
1355
|
-
group(options: { prefix?: string, middleware?: (string | MiddlewareHandler)[] }, callback: () =>
|
|
1359
|
+
group(options: { prefix?: string, middleware?: (string | MiddlewareHandler)[] }, callback: () => Promise<void>): Promise<Router>
|
|
1360
|
+
group(options: { prefix?: string, middleware?: (string | MiddlewareHandler)[] }, callback: () => void): Router
|
|
1361
|
+
group(options: { prefix?: string, middleware?: (string | MiddlewareHandler)[] }, callback: () => void | Promise<void>): Router | Promise<Router> {
|
|
1356
1362
|
// Save current group state
|
|
1357
1363
|
const previousGroup = this.currentGroup
|
|
1358
1364
|
|
|
@@ -1374,17 +1380,23 @@ export class Router {
|
|
|
1374
1380
|
// Execute callback
|
|
1375
1381
|
const result = callback()
|
|
1376
1382
|
|
|
1377
|
-
//
|
|
1383
|
+
// Async callbacks keep the group active until they settle
|
|
1378
1384
|
if (result instanceof Promise) {
|
|
1379
|
-
result.then(
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1385
|
+
return result.then(
|
|
1386
|
+
() => {
|
|
1387
|
+
this.currentGroup = previousGroup
|
|
1388
|
+
return this
|
|
1389
|
+
},
|
|
1390
|
+
(error: unknown) => {
|
|
1391
|
+
this.currentGroup = previousGroup
|
|
1392
|
+
throw error
|
|
1393
|
+
},
|
|
1394
|
+
)
|
|
1386
1395
|
}
|
|
1387
1396
|
|
|
1397
|
+
// Restore previous group state
|
|
1398
|
+
this.currentGroup = previousGroup
|
|
1399
|
+
|
|
1388
1400
|
return this
|
|
1389
1401
|
}
|
|
1390
1402
|
|