0http-bun 1.1.0 → 1.1.2
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/common.d.ts +2 -2
- package/index.d.ts +2 -2
- package/index.js +1 -1
- package/lib/next.js +13 -4
- package/lib/router/sequential.d.ts +1 -1
- package/lib/router/sequential.js +85 -31
- package/package.json +10 -8
package/common.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {Pattern, Methods} from 'trouter'
|
|
2
2
|
|
|
3
3
|
export interface IRouterConfig {
|
|
4
4
|
defaultRoute?: RequestHandler
|
|
@@ -16,7 +16,7 @@ type ZeroRequest = Request & {
|
|
|
16
16
|
|
|
17
17
|
export type RequestHandler = (
|
|
18
18
|
req: ZeroRequest,
|
|
19
|
-
next: StepFunction
|
|
19
|
+
next: StepFunction,
|
|
20
20
|
) => Response | Promise<Response>
|
|
21
21
|
|
|
22
22
|
export interface IRouter {
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
package/lib/next.js
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
|
-
module.exports = function next
|
|
2
|
-
|
|
1
|
+
module.exports = function next(
|
|
2
|
+
middlewares,
|
|
3
|
+
req,
|
|
4
|
+
index,
|
|
5
|
+
defaultRoute,
|
|
6
|
+
errorHandler,
|
|
7
|
+
) {
|
|
8
|
+
// Optimized loop unrolling for common cases
|
|
9
|
+
const length = middlewares.length
|
|
10
|
+
if (index >= length) {
|
|
3
11
|
return defaultRoute(req)
|
|
4
12
|
}
|
|
5
13
|
|
|
6
|
-
const middleware = middlewares[index
|
|
14
|
+
const middleware = middlewares[index]
|
|
15
|
+
const nextIndex = index + 1
|
|
7
16
|
|
|
8
17
|
try {
|
|
9
18
|
return middleware(req, (err) => {
|
|
10
19
|
if (err) {
|
|
11
20
|
return errorHandler(err, req)
|
|
12
21
|
}
|
|
13
|
-
return next(middlewares, req,
|
|
22
|
+
return next(middlewares, req, nextIndex, defaultRoute, errorHandler)
|
|
14
23
|
})
|
|
15
24
|
} catch (err) {
|
|
16
25
|
return errorHandler(err, req)
|
package/lib/router/sequential.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
const Trouter = require('trouter')
|
|
1
|
+
const {Trouter} = require('trouter')
|
|
2
2
|
const qs = require('fast-querystring')
|
|
3
3
|
const next = require('./../next')
|
|
4
4
|
|
|
5
5
|
const STATUS_404 = {
|
|
6
|
-
status: 404
|
|
6
|
+
status: 404,
|
|
7
7
|
}
|
|
8
8
|
const STATUS_500 = {
|
|
9
|
-
status: 500
|
|
9
|
+
status: 500,
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
module.exports = (config = {}) => {
|
|
13
13
|
const cache = new Map()
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
config.errorHandler
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
15
|
+
// Pre-create default responses to avoid object creation overhead
|
|
16
|
+
const default404Response = new Response(null, STATUS_404)
|
|
17
|
+
|
|
18
|
+
// Cache default functions to avoid closure creation
|
|
19
|
+
const defaultRouteHandler = config.defaultRoute || (() => default404Response)
|
|
20
|
+
const errorHandlerFn =
|
|
21
|
+
config.errorHandler || ((err) => new Response(err.message, STATUS_500))
|
|
22
|
+
|
|
23
|
+
// Optimize empty params object reuse
|
|
24
|
+
const emptyParams = {}
|
|
25
25
|
|
|
26
26
|
const router = new Trouter()
|
|
27
27
|
router.port = config.port || 3000
|
|
@@ -40,35 +40,89 @@ module.exports = (config = {}) => {
|
|
|
40
40
|
|
|
41
41
|
router.fetch = (req) => {
|
|
42
42
|
const url = req.url
|
|
43
|
-
const startIndex = url.indexOf('/', 11)
|
|
44
|
-
const queryIndex = url.indexOf('?', startIndex + 1)
|
|
45
|
-
const path = queryIndex === -1 ? url.substring(startIndex) : url.substring(startIndex, queryIndex)
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
// Highly optimized URL parsing - single pass through the string
|
|
45
|
+
let pathStart = 0
|
|
46
|
+
let pathEnd = url.length
|
|
47
|
+
let queryString = null
|
|
48
|
+
|
|
49
|
+
// Find protocol end
|
|
50
|
+
const protocolEnd = url.indexOf('://')
|
|
51
|
+
if (protocolEnd !== -1) {
|
|
52
|
+
// Find host end (start of path)
|
|
53
|
+
pathStart = url.indexOf('/', protocolEnd + 3)
|
|
54
|
+
if (pathStart === -1) {
|
|
55
|
+
pathStart = url.length
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Find query start
|
|
60
|
+
const queryStart = url.indexOf('?', pathStart)
|
|
61
|
+
if (queryStart !== -1) {
|
|
62
|
+
pathEnd = queryStart
|
|
63
|
+
queryString = url.substring(queryStart + 1)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const path = pathStart < pathEnd ? url.substring(pathStart, pathEnd) : '/'
|
|
49
67
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
68
|
+
req.path = path
|
|
69
|
+
req.query = queryString ? qs.parse(queryString) : {}
|
|
70
|
+
|
|
71
|
+
// Optimized cache lookup with method-based Map structure
|
|
72
|
+
const method = req.method
|
|
73
|
+
let methodCache = cache.get(method)
|
|
74
|
+
let match_result
|
|
75
|
+
|
|
76
|
+
if (methodCache) {
|
|
77
|
+
match_result = methodCache.get(path)
|
|
78
|
+
if (match_result === undefined) {
|
|
79
|
+
match_result = router.find(method, path)
|
|
80
|
+
methodCache.set(path, match_result)
|
|
81
|
+
}
|
|
54
82
|
} else {
|
|
55
|
-
|
|
56
|
-
|
|
83
|
+
match_result = router.find(method, path)
|
|
84
|
+
methodCache = new Map([[path, match_result]])
|
|
85
|
+
cache.set(method, methodCache)
|
|
57
86
|
}
|
|
58
87
|
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
88
|
+
if (match_result?.handlers?.length > 0) {
|
|
89
|
+
// Fast path for params assignment
|
|
90
|
+
const params = match_result.params
|
|
91
|
+
if (params) {
|
|
92
|
+
// Check if params object has properties without Object.keys()
|
|
93
|
+
let hasParams = false
|
|
94
|
+
for (const key in params) {
|
|
95
|
+
hasParams = true
|
|
96
|
+
break
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (hasParams) {
|
|
100
|
+
req.params = req.params || {}
|
|
101
|
+
// Direct property copy - faster than Object.keys() + loop
|
|
102
|
+
for (const key in params) {
|
|
103
|
+
req.params[key] = params[key]
|
|
104
|
+
}
|
|
105
|
+
} else if (!req.params) {
|
|
106
|
+
req.params = emptyParams
|
|
107
|
+
}
|
|
108
|
+
} else if (!req.params) {
|
|
109
|
+
req.params = emptyParams
|
|
62
110
|
}
|
|
63
|
-
Object.assign(req.params, match.params)
|
|
64
111
|
|
|
65
|
-
return next(
|
|
112
|
+
return next(
|
|
113
|
+
match_result.handlers,
|
|
114
|
+
req,
|
|
115
|
+
0,
|
|
116
|
+
defaultRouteHandler,
|
|
117
|
+
errorHandlerFn,
|
|
118
|
+
)
|
|
66
119
|
} else {
|
|
67
|
-
return
|
|
120
|
+
return defaultRouteHandler(req)
|
|
68
121
|
}
|
|
69
122
|
}
|
|
70
123
|
|
|
71
|
-
router.on = (method, pattern, ...handlers) =>
|
|
124
|
+
router.on = (method, pattern, ...handlers) =>
|
|
125
|
+
router.add(method, pattern, handlers)
|
|
72
126
|
|
|
73
127
|
return router
|
|
74
128
|
}
|
package/package.json
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "0http-bun",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "0http for Bun",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"lint": "
|
|
8
|
-
"
|
|
9
|
-
"
|
|
7
|
+
"lint": "prettier --check **/*.js",
|
|
8
|
+
"test": "bun --coverage test",
|
|
9
|
+
"bench": "bun run bench.js",
|
|
10
|
+
"format": "prettier --write **/*.js"
|
|
10
11
|
},
|
|
11
12
|
"dependencies": {
|
|
12
13
|
"fast-querystring": "^1.1.2",
|
|
13
|
-
"trouter": "^
|
|
14
|
+
"trouter": "^4.0.0"
|
|
14
15
|
},
|
|
15
16
|
"repository": {
|
|
16
17
|
"type": "git",
|
|
@@ -25,9 +26,10 @@
|
|
|
25
26
|
"lib/"
|
|
26
27
|
],
|
|
27
28
|
"devDependencies": {
|
|
28
|
-
"0http-bun": "^1.0
|
|
29
|
-
"bun-types": "^1.
|
|
30
|
-
"mitata": "^1.0.
|
|
29
|
+
"0http-bun": "^1.1.0",
|
|
30
|
+
"bun-types": "^1.2.5",
|
|
31
|
+
"mitata": "^1.0.34",
|
|
32
|
+
"prettier": "^3.5.3"
|
|
31
33
|
},
|
|
32
34
|
"keywords": [
|
|
33
35
|
"http",
|