make-fetch 3.1.3 → 3.2.0

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 CHANGED
@@ -1,30 +1,71 @@
1
- export const WILDCARD = '*'
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 async function fetch (...requestOptions) {
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(async (request) => {
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
- return await onError(e, request)
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,14 @@
1
1
  {
2
2
  "name": "make-fetch",
3
- "version": "3.1.3",
3
+ "version": "3.2.0",
4
4
  "description": "Implement your own `fetch()` with node.js streams",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "scripts": {
8
8
  "test": "node test",
9
- "lint": "standard --fix"
9
+ "lint": "standard --fix && tsc --noEmit",
10
+ "build": "tsc",
11
+ "preversion": "npm run lint && npm run build && npm run test"
10
12
  },
11
13
  "repository": {
12
14
  "type": "git",
@@ -25,7 +27,11 @@
25
27
  },
26
28
  "homepage": "https://github.com/RangerMauve/make-fetch#readme",
27
29
  "devDependencies": {
30
+ "@tsconfig/node20": "^20.1.8",
31
+ "@types/node": "^25.0.3",
32
+ "@types/tape": "^5.8.1",
28
33
  "standard": "^17.0.0",
29
- "tape": "^5.6.1"
34
+ "tape": "^5.6.1",
35
+ "typescript": "^5.9.3"
30
36
  }
31
37
  }
package/test.js CHANGED
@@ -31,7 +31,7 @@ test('Basic makeFetch test', async (t) => {
31
31
  t.end()
32
32
  })
33
33
 
34
- test.only('Basic makeFetch test with Request object', async (t) => {
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
+ }