make-fetch 3.1.3 → 3.2.1
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/index.js +116 -7
- package/package.json +10 -3
- package/test.js +5 -2
- package/tsconfig.json +15 -0
package/index.js
CHANGED
|
@@ -1,30 +1,71 @@
|
|
|
1
|
-
|
|
1
|
+
/** @typedef {ConstructorParameters<typeof globalThis.Response>[0] | AsyncIterable<string>} Body */
|
|
2
|
+
/** @typedef {Response|ResponseInit & {body?: Body}} ResponseLike */
|
|
3
|
+
/** @typedef {(request: Request) => ResponseLike|Promise<ResponseLike> } Handler */
|
|
4
|
+
/** @typedef {(error: Error, request: Request) => ResponseLike } ErrorHandler */
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {object} Route
|
|
8
|
+
* @property {string} protocol
|
|
9
|
+
* @property {string} method
|
|
10
|
+
* @property {string} hostname
|
|
11
|
+
* @property {string[]} segments
|
|
12
|
+
* @property {Handler} handler
|
|
13
|
+
*/
|
|
2
14
|
|
|
15
|
+
/** @typedef {'pathname' | 'hostname' | 'protocol' | 'method'} MatchProperty */
|
|
16
|
+
|
|
17
|
+
/** @type {MatchProperty[]} */
|
|
3
18
|
const MATCH_ORDER = ['method', 'protocol', 'hostname', 'pathname']
|
|
4
19
|
|
|
20
|
+
export const WILDCARD = '*'
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {Handler} handler
|
|
24
|
+
* @param {object} [options]
|
|
25
|
+
* @param {typeof globalThis.Request} [options.Request]
|
|
26
|
+
* @param {typeof globalThis.Response} [options.Response]
|
|
27
|
+
* @returns {typeof fetch}
|
|
28
|
+
*/
|
|
5
29
|
export function makeFetch (handler, {
|
|
6
30
|
Request = globalThis.Request,
|
|
7
31
|
Response = globalThis.Response
|
|
8
32
|
} = {}) {
|
|
9
|
-
return
|
|
33
|
+
return fetch
|
|
34
|
+
|
|
35
|
+
/** @type {typeof globalThis.fetch} */
|
|
36
|
+
async function fetch (...requestOptions) {
|
|
10
37
|
const isAlreadyRequest = requestOptions[0] instanceof Request
|
|
11
|
-
const request = isAlreadyRequest ? requestOptions[0] : new Request(...requestOptions)
|
|
38
|
+
const request = isAlreadyRequest ? /** @type {Request} */(requestOptions[0]) : new Request(...requestOptions)
|
|
12
39
|
|
|
13
40
|
const { body = null, ...responseOptions } = await handler(request)
|
|
14
41
|
|
|
42
|
+
// @ts-ignore You can use an AsyncIterable of strings for body
|
|
15
43
|
const response = new Response(body, responseOptions)
|
|
16
44
|
|
|
17
45
|
return response
|
|
18
46
|
}
|
|
19
47
|
}
|
|
20
48
|
|
|
49
|
+
/**
|
|
50
|
+
*
|
|
51
|
+
* @param {object} [options]
|
|
52
|
+
* @param {Handler} [options.onNotFound]
|
|
53
|
+
* @param {ErrorHandler} [options.onError]
|
|
54
|
+
* @returns
|
|
55
|
+
*/
|
|
21
56
|
export function makeRoutedFetch ({
|
|
22
57
|
onNotFound = DEFAULT_NOT_FOUND,
|
|
23
58
|
onError = DEFAULT_ON_ERROR
|
|
24
59
|
} = {}) {
|
|
25
60
|
const router = new Router()
|
|
26
61
|
|
|
27
|
-
const fetch = makeFetch(
|
|
62
|
+
const fetch = makeFetch(handler)
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {Request} request
|
|
66
|
+
* @returns {Promise<ResponseLike>}
|
|
67
|
+
*/
|
|
68
|
+
async function handler (request) {
|
|
28
69
|
const route = router.route(request)
|
|
29
70
|
if (!route) {
|
|
30
71
|
return onNotFound(request)
|
|
@@ -33,9 +74,10 @@ export function makeRoutedFetch ({
|
|
|
33
74
|
const response = await route.handler(request)
|
|
34
75
|
return response
|
|
35
76
|
} catch (e) {
|
|
36
|
-
|
|
77
|
+
// Typescript is annoying
|
|
78
|
+
return await onError(/** @type {Error} */ (e), request)
|
|
37
79
|
}
|
|
38
|
-
}
|
|
80
|
+
}
|
|
39
81
|
|
|
40
82
|
return { fetch, router }
|
|
41
83
|
}
|
|
@@ -44,6 +86,7 @@ export function DEFAULT_NOT_FOUND () {
|
|
|
44
86
|
return { status: 404, statusText: 'Invalid URL' }
|
|
45
87
|
}
|
|
46
88
|
|
|
89
|
+
/** @type {ErrorHandler} */
|
|
47
90
|
export function DEFAULT_ON_ERROR (e) {
|
|
48
91
|
return {
|
|
49
92
|
status: 500,
|
|
@@ -56,37 +99,86 @@ export function DEFAULT_ON_ERROR (e) {
|
|
|
56
99
|
|
|
57
100
|
export class Router {
|
|
58
101
|
constructor () {
|
|
59
|
-
this.routes = []
|
|
102
|
+
this.routes = /** @type {Route[]} */ ([])
|
|
60
103
|
}
|
|
61
104
|
|
|
105
|
+
/**
|
|
106
|
+
*
|
|
107
|
+
* @param {string} url
|
|
108
|
+
* @param {Handler} handler
|
|
109
|
+
* @returns {Router}
|
|
110
|
+
*/
|
|
62
111
|
get (url, handler) {
|
|
63
112
|
return this.add('GET', url, handler)
|
|
64
113
|
}
|
|
65
114
|
|
|
115
|
+
/**
|
|
116
|
+
*
|
|
117
|
+
* @param {string} url
|
|
118
|
+
* @param {Handler} handler
|
|
119
|
+
* @returns {Router}
|
|
120
|
+
*/
|
|
66
121
|
head (url, handler) {
|
|
67
122
|
return this.add('HEAD', url, handler)
|
|
68
123
|
}
|
|
69
124
|
|
|
125
|
+
/**
|
|
126
|
+
*
|
|
127
|
+
* @param {string} url
|
|
128
|
+
* @param {Handler} handler
|
|
129
|
+
* @returns {Router}
|
|
130
|
+
*/
|
|
70
131
|
post (url, handler) {
|
|
71
132
|
return this.add('POST', url, handler)
|
|
72
133
|
}
|
|
73
134
|
|
|
135
|
+
/**
|
|
136
|
+
*
|
|
137
|
+
* @param {string} url
|
|
138
|
+
* @param {Handler} handler
|
|
139
|
+
* @returns {Router}
|
|
140
|
+
*/
|
|
74
141
|
put (url, handler) {
|
|
75
142
|
return this.add('PUT', url, handler)
|
|
76
143
|
}
|
|
77
144
|
|
|
145
|
+
/**
|
|
146
|
+
*
|
|
147
|
+
* @param {string} url
|
|
148
|
+
* @param {Handler} handler
|
|
149
|
+
* @returns {Router}
|
|
150
|
+
*/
|
|
78
151
|
delete (url, handler) {
|
|
79
152
|
return this.add('DELETE', url, handler)
|
|
80
153
|
}
|
|
81
154
|
|
|
155
|
+
/**
|
|
156
|
+
*
|
|
157
|
+
* @param {string} url
|
|
158
|
+
* @param {Handler} handler
|
|
159
|
+
* @returns {Router}
|
|
160
|
+
*/
|
|
82
161
|
patch (url, handler) {
|
|
83
162
|
return this.add('PATCH', url, handler)
|
|
84
163
|
}
|
|
85
164
|
|
|
165
|
+
/**
|
|
166
|
+
*
|
|
167
|
+
* @param {string} url
|
|
168
|
+
* @param {Handler} handler
|
|
169
|
+
* @returns {Router}
|
|
170
|
+
*/
|
|
86
171
|
any (url, handler) {
|
|
87
172
|
return this.add(WILDCARD, url, handler)
|
|
88
173
|
}
|
|
89
174
|
|
|
175
|
+
/**
|
|
176
|
+
*
|
|
177
|
+
* @param {string} method
|
|
178
|
+
* @param {string} url
|
|
179
|
+
* @param {Handler} handler
|
|
180
|
+
* @returns {Router}
|
|
181
|
+
*/
|
|
90
182
|
add (method, url, handler) {
|
|
91
183
|
const parsed = new URL(url)
|
|
92
184
|
const { hostname, protocol, pathname } = parsed
|
|
@@ -104,6 +196,11 @@ export class Router {
|
|
|
104
196
|
return this
|
|
105
197
|
}
|
|
106
198
|
|
|
199
|
+
/**
|
|
200
|
+
*
|
|
201
|
+
* @param {Request} request
|
|
202
|
+
* @returns {Route?}
|
|
203
|
+
*/
|
|
107
204
|
route (request) {
|
|
108
205
|
for (const route of this.routes) {
|
|
109
206
|
let hasFail = false
|
|
@@ -120,6 +217,13 @@ export class Router {
|
|
|
120
217
|
}
|
|
121
218
|
}
|
|
122
219
|
|
|
220
|
+
/**
|
|
221
|
+
*
|
|
222
|
+
* @param {Request} request
|
|
223
|
+
* @param {Route} route
|
|
224
|
+
* @param {MatchProperty} property
|
|
225
|
+
* @returns
|
|
226
|
+
*/
|
|
123
227
|
function matches (request, route, property) {
|
|
124
228
|
if (property === 'pathname') {
|
|
125
229
|
const routeSegments = route.segments
|
|
@@ -160,6 +264,11 @@ function matches (request, route, property) {
|
|
|
160
264
|
}
|
|
161
265
|
}
|
|
162
266
|
|
|
267
|
+
/**
|
|
268
|
+
* @param {string} routeProperty
|
|
269
|
+
* @param {string} requestProperty
|
|
270
|
+
* @returns
|
|
271
|
+
*/
|
|
163
272
|
function areEqual (routeProperty, requestProperty) {
|
|
164
273
|
if (routeProperty === '*') return true
|
|
165
274
|
return routeProperty === requestProperty
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "make-fetch",
|
|
3
|
-
"version": "3.1
|
|
3
|
+
"version": "3.2.1",
|
|
4
4
|
"description": "Implement your own `fetch()` with node.js streams",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
7
8
|
"scripts": {
|
|
8
9
|
"test": "node test",
|
|
9
|
-
"lint": "standard --fix"
|
|
10
|
+
"lint": "standard --fix && tsc --noEmit",
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"preversion": "npm run lint && npm run build && npm run test"
|
|
10
13
|
},
|
|
11
14
|
"repository": {
|
|
12
15
|
"type": "git",
|
|
@@ -25,7 +28,11 @@
|
|
|
25
28
|
},
|
|
26
29
|
"homepage": "https://github.com/RangerMauve/make-fetch#readme",
|
|
27
30
|
"devDependencies": {
|
|
31
|
+
"@tsconfig/node20": "^20.1.8",
|
|
32
|
+
"@types/node": "^25.0.3",
|
|
33
|
+
"@types/tape": "^5.8.1",
|
|
28
34
|
"standard": "^17.0.0",
|
|
29
|
-
"tape": "^5.6.1"
|
|
35
|
+
"tape": "^5.6.1",
|
|
36
|
+
"typescript": "^5.9.3"
|
|
30
37
|
}
|
|
31
38
|
}
|
package/test.js
CHANGED
|
@@ -31,7 +31,7 @@ test('Basic makeFetch test', async (t) => {
|
|
|
31
31
|
t.end()
|
|
32
32
|
})
|
|
33
33
|
|
|
34
|
-
test
|
|
34
|
+
test('Basic makeFetch test with Request object', async (t) => {
|
|
35
35
|
const fetch = makeFetch(({ url }) => {
|
|
36
36
|
return {
|
|
37
37
|
status: 200,
|
|
@@ -60,7 +60,6 @@ test.only('Basic makeFetch test with Request object', async (t) => {
|
|
|
60
60
|
t.end()
|
|
61
61
|
})
|
|
62
62
|
|
|
63
|
-
|
|
64
63
|
test('Basic router tests', async (t) => {
|
|
65
64
|
const { fetch, router } = makeRoutedFetch()
|
|
66
65
|
|
|
@@ -78,6 +77,10 @@ test('Basic router tests', async (t) => {
|
|
|
78
77
|
t.equal(body, toFetch, 'got expected body')
|
|
79
78
|
})
|
|
80
79
|
|
|
80
|
+
/**
|
|
81
|
+
* @param {string} data
|
|
82
|
+
* @returns {AsyncIterable<string>}
|
|
83
|
+
*/
|
|
81
84
|
async function * intoAsyncIterable (data) {
|
|
82
85
|
yield data
|
|
83
86
|
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2022",
|
|
4
|
+
"module": "nodenext",
|
|
5
|
+
"checkJs": true,
|
|
6
|
+
"allowJs": true,
|
|
7
|
+
"declaration": true,
|
|
8
|
+
"emitDeclarationOnly": true,
|
|
9
|
+
"moduleResolution": "nodenext",
|
|
10
|
+
"outDir": "dist",
|
|
11
|
+
},
|
|
12
|
+
"extends": "@tsconfig/node20/tsconfig.json",
|
|
13
|
+
"files": ["./index.js","./test.js"],
|
|
14
|
+
"include": ["./index.js","./test.js"]
|
|
15
|
+
}
|