fastify 5.2.0 → 5.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/README.md +42 -43
- package/build/build-validation.js +1 -1
- package/docs/Reference/Errors.md +2 -0
- package/docs/Reference/Request.md +9 -10
- package/docs/Reference/Server.md +1 -1
- package/fastify.js +1 -1
- package/lib/errors.js +4 -0
- package/lib/reply.js +4 -0
- package/lib/request.js +13 -9
- package/package.json +19 -8
- package/test/custom-parser.2.test.js +19 -20
- package/test/custom-parser.3.test.js +56 -45
- package/test/delete.test.js +79 -67
- package/test/internals/errors.test.js +19 -7
- package/test/nullable-validation.test.js +30 -27
- package/test/web-api.test.js +44 -0
- package/.vscode/settings.json +0 -22
- package/test/test-reporter.mjs +0 -68
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const test = t.test
|
|
3
|
+
const { test } = require('node:test')
|
|
5
4
|
const sget = require('simple-get').concat
|
|
6
5
|
const Fastify = require('..')
|
|
7
6
|
|
|
8
|
-
test('nullable string', t => {
|
|
7
|
+
test('nullable string', (t, done) => {
|
|
9
8
|
t.plan(3)
|
|
10
9
|
const fastify = Fastify()
|
|
11
10
|
fastify.route({
|
|
12
11
|
method: 'POST',
|
|
13
12
|
url: '/',
|
|
14
13
|
handler: (req, reply) => {
|
|
15
|
-
t.
|
|
14
|
+
t.assert.strictEqual(req.body.hello, null)
|
|
16
15
|
reply.code(200).send(req.body)
|
|
17
16
|
},
|
|
18
17
|
schema: {
|
|
@@ -47,12 +46,13 @@ test('nullable string', t => {
|
|
|
47
46
|
hello: null
|
|
48
47
|
}
|
|
49
48
|
}, (err, res) => {
|
|
50
|
-
t.
|
|
51
|
-
t.
|
|
49
|
+
t.assert.ifError(err)
|
|
50
|
+
t.assert.strictEqual(res.json().hello, null)
|
|
51
|
+
done()
|
|
52
52
|
})
|
|
53
53
|
})
|
|
54
54
|
|
|
55
|
-
test('object or null body', t => {
|
|
55
|
+
test('object or null body', (t, done) => {
|
|
56
56
|
t.plan(5)
|
|
57
57
|
|
|
58
58
|
const fastify = Fastify()
|
|
@@ -61,7 +61,7 @@ test('object or null body', t => {
|
|
|
61
61
|
method: 'POST',
|
|
62
62
|
url: '/',
|
|
63
63
|
handler: (req, reply) => {
|
|
64
|
-
t.
|
|
64
|
+
t.assert.strictEqual(req.body, undefined)
|
|
65
65
|
reply.code(200).send({ isUndefinedBody: req.body === undefined })
|
|
66
66
|
},
|
|
67
67
|
schema: {
|
|
@@ -89,21 +89,22 @@ test('object or null body', t => {
|
|
|
89
89
|
})
|
|
90
90
|
|
|
91
91
|
fastify.listen({ port: 0 }, (err) => {
|
|
92
|
-
t.
|
|
93
|
-
t.
|
|
92
|
+
t.assert.ifError(err)
|
|
93
|
+
t.after(() => { fastify.close() })
|
|
94
94
|
|
|
95
95
|
sget({
|
|
96
96
|
method: 'POST',
|
|
97
97
|
url: 'http://localhost:' + fastify.server.address().port
|
|
98
98
|
}, (err, response, body) => {
|
|
99
|
-
t.
|
|
100
|
-
t.
|
|
101
|
-
t.
|
|
99
|
+
t.assert.ifError(err)
|
|
100
|
+
t.assert.strictEqual(response.statusCode, 200)
|
|
101
|
+
t.assert.deepStrictEqual(JSON.parse(body), { isUndefinedBody: true })
|
|
102
|
+
done()
|
|
102
103
|
})
|
|
103
104
|
})
|
|
104
105
|
})
|
|
105
106
|
|
|
106
|
-
test('nullable body', t => {
|
|
107
|
+
test('nullable body', (t, done) => {
|
|
107
108
|
t.plan(5)
|
|
108
109
|
|
|
109
110
|
const fastify = Fastify()
|
|
@@ -112,7 +113,7 @@ test('nullable body', t => {
|
|
|
112
113
|
method: 'POST',
|
|
113
114
|
url: '/',
|
|
114
115
|
handler: (req, reply) => {
|
|
115
|
-
t.
|
|
116
|
+
t.assert.strictEqual(req.body, undefined)
|
|
116
117
|
reply.code(200).send({ isUndefinedBody: req.body === undefined })
|
|
117
118
|
},
|
|
118
119
|
schema: {
|
|
@@ -141,21 +142,22 @@ test('nullable body', t => {
|
|
|
141
142
|
})
|
|
142
143
|
|
|
143
144
|
fastify.listen({ port: 0 }, (err) => {
|
|
144
|
-
t.
|
|
145
|
-
t.
|
|
145
|
+
t.assert.ifError(err)
|
|
146
|
+
t.after(() => fastify.close())
|
|
146
147
|
|
|
147
148
|
sget({
|
|
148
149
|
method: 'POST',
|
|
149
150
|
url: 'http://localhost:' + fastify.server.address().port
|
|
150
151
|
}, (err, response, body) => {
|
|
151
|
-
t.
|
|
152
|
-
t.
|
|
153
|
-
t.
|
|
152
|
+
t.assert.ifError(err)
|
|
153
|
+
t.assert.strictEqual(response.statusCode, 200)
|
|
154
|
+
t.assert.deepStrictEqual(JSON.parse(body), { isUndefinedBody: true })
|
|
155
|
+
done()
|
|
154
156
|
})
|
|
155
157
|
})
|
|
156
158
|
})
|
|
157
159
|
|
|
158
|
-
test('Nullable body with 204', t => {
|
|
160
|
+
test('Nullable body with 204', (t, done) => {
|
|
159
161
|
t.plan(5)
|
|
160
162
|
|
|
161
163
|
const fastify = Fastify()
|
|
@@ -164,7 +166,7 @@ test('Nullable body with 204', t => {
|
|
|
164
166
|
method: 'POST',
|
|
165
167
|
url: '/',
|
|
166
168
|
handler: (req, reply) => {
|
|
167
|
-
t.
|
|
169
|
+
t.assert.strictEqual(req.body, undefined)
|
|
168
170
|
reply.code(204).send()
|
|
169
171
|
},
|
|
170
172
|
schema: {
|
|
@@ -182,16 +184,17 @@ test('Nullable body with 204', t => {
|
|
|
182
184
|
})
|
|
183
185
|
|
|
184
186
|
fastify.listen({ port: 0 }, (err) => {
|
|
185
|
-
t.
|
|
186
|
-
t.
|
|
187
|
+
t.assert.ifError(err)
|
|
188
|
+
t.after(() => fastify.close())
|
|
187
189
|
|
|
188
190
|
sget({
|
|
189
191
|
method: 'POST',
|
|
190
192
|
url: 'http://localhost:' + fastify.server.address().port
|
|
191
193
|
}, (err, response, body) => {
|
|
192
|
-
t.
|
|
193
|
-
t.
|
|
194
|
-
t.
|
|
194
|
+
t.assert.ifError(err)
|
|
195
|
+
t.assert.strictEqual(response.statusCode, 204)
|
|
196
|
+
t.assert.strictEqual(body.length, 0)
|
|
197
|
+
done()
|
|
195
198
|
})
|
|
196
199
|
})
|
|
197
200
|
})
|
package/test/web-api.test.js
CHANGED
|
@@ -227,6 +227,50 @@ test('Error when Response.bodyUsed', async (t) => {
|
|
|
227
227
|
t.assert.strictEqual(body.code, 'FST_ERR_REP_RESPONSE_BODY_CONSUMED')
|
|
228
228
|
})
|
|
229
229
|
|
|
230
|
+
test('Error when Response.body.locked', async (t) => {
|
|
231
|
+
t.plan(3)
|
|
232
|
+
|
|
233
|
+
const fastify = Fastify()
|
|
234
|
+
|
|
235
|
+
fastify.get('/', async function (request, reply) {
|
|
236
|
+
const stream = Readable.toWeb(fs.createReadStream(__filename))
|
|
237
|
+
const response = new Response(stream, {
|
|
238
|
+
status: 200,
|
|
239
|
+
headers: {
|
|
240
|
+
hello: 'world'
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
stream.getReader()
|
|
244
|
+
t.assert.strictEqual(stream.locked, true)
|
|
245
|
+
return reply.send(response)
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
const response = await fastify.inject({ method: 'GET', path: '/' })
|
|
249
|
+
|
|
250
|
+
t.assert.strictEqual(response.statusCode, 500)
|
|
251
|
+
const body = response.json()
|
|
252
|
+
t.assert.strictEqual(body.code, 'FST_ERR_REP_READABLE_STREAM_LOCKED')
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
test('Error when ReadableStream.locked', async (t) => {
|
|
256
|
+
t.plan(3)
|
|
257
|
+
|
|
258
|
+
const fastify = Fastify()
|
|
259
|
+
|
|
260
|
+
fastify.get('/', async function (request, reply) {
|
|
261
|
+
const stream = Readable.toWeb(fs.createReadStream(__filename))
|
|
262
|
+
stream.getReader()
|
|
263
|
+
t.assert.strictEqual(stream.locked, true)
|
|
264
|
+
return reply.send(stream)
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
const response = await fastify.inject({ method: 'GET', path: '/' })
|
|
268
|
+
|
|
269
|
+
t.assert.strictEqual(response.statusCode, 500)
|
|
270
|
+
const body = response.json()
|
|
271
|
+
t.assert.strictEqual(body.code, 'FST_ERR_REP_READABLE_STREAM_LOCKED')
|
|
272
|
+
})
|
|
273
|
+
|
|
230
274
|
test('allow to pipe with fetch', async (t) => {
|
|
231
275
|
t.plan(2)
|
|
232
276
|
const abortController = new AbortController()
|
package/.vscode/settings.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"workbench.colorCustomizations": {
|
|
3
|
-
"[GitHub Dark]": {
|
|
4
|
-
"tab.activeBackground": "#0d0d0d",
|
|
5
|
-
"tab.activeBorder": "#ffff00"
|
|
6
|
-
},
|
|
7
|
-
"activityBar.background": "#FBE7B2",
|
|
8
|
-
"activityBar.foreground": "#52358C",
|
|
9
|
-
"activityBar.inactiveForeground": "#616161",
|
|
10
|
-
"activityBar.activeBorder": "#04184d",
|
|
11
|
-
"activityBar.activeBackground": "#C3B48B",
|
|
12
|
-
"activityBar.border": "#C3B48B",
|
|
13
|
-
"titleBar.activeBackground": "#D2BE88",
|
|
14
|
-
"titleBar.activeForeground": "#52358C",
|
|
15
|
-
"titleBar.inactiveBackground": "#bdb59c",
|
|
16
|
-
"titleBar.inactiveForeground": "#616161",
|
|
17
|
-
"titleBar.border": "#C3B48B",
|
|
18
|
-
"statusBar.background": "#E9DBB7",
|
|
19
|
-
"statusBar.foreground": "#52358C",
|
|
20
|
-
"statusBar.border": "#C3B48B"
|
|
21
|
-
}
|
|
22
|
-
}
|
package/test/test-reporter.mjs
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
function colorize (type, text) {
|
|
2
|
-
if (type === 'pass') {
|
|
3
|
-
const blackText = `\x1b[30m${text}`
|
|
4
|
-
const boldblackText = `\x1b[1m${blackText}`
|
|
5
|
-
// Green background with black text
|
|
6
|
-
return `\x1b[42m${boldblackText}\x1b[0m`
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
if (type === 'fail') {
|
|
10
|
-
const whiteText = `\x1b[37m${text}`
|
|
11
|
-
const boldWhiteText = `\x1b[1m${whiteText}`
|
|
12
|
-
// Red background with white text
|
|
13
|
-
return `\x1b[41m${boldWhiteText}\x1b[0m`
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return text
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function formatDiagnosticStr (str) {
|
|
20
|
-
return str.replace(/^(\w+)(\s*\d*)/i, (_, firstWord, rest) => {
|
|
21
|
-
return firstWord.charAt(0).toUpperCase() + firstWord.slice(1).toLowerCase() + ':' + rest
|
|
22
|
-
})
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async function * reporter (source) {
|
|
26
|
-
const failed = new Set()
|
|
27
|
-
const diagnostics = new Set()
|
|
28
|
-
|
|
29
|
-
for await (const event of source) {
|
|
30
|
-
switch (event.type) {
|
|
31
|
-
case 'test:pass': {
|
|
32
|
-
yield `${colorize('pass', 'PASSED')}: ${event.data.file || event.data.name}\n`
|
|
33
|
-
break
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
case 'test:fail': {
|
|
37
|
-
failed.add(event.data.name || event.data.file)
|
|
38
|
-
yield `${colorize('fail', 'FAILED')}: ${event.data.file || event.data.name}\n`
|
|
39
|
-
break
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
case 'test:diagnostic': {
|
|
43
|
-
diagnostics.add(`${formatDiagnosticStr(event.data.message)}\n`)
|
|
44
|
-
break
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
default: {
|
|
48
|
-
yield ''
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (failed.size > 0) {
|
|
54
|
-
yield `\n\n${colorize('fail', 'Failed tests:')}\n`
|
|
55
|
-
for (const file of failed) {
|
|
56
|
-
yield `${file}\n`
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
yield '\n'
|
|
61
|
-
|
|
62
|
-
for (const diagnostic of diagnostics) {
|
|
63
|
-
yield `${diagnostic}`
|
|
64
|
-
}
|
|
65
|
-
yield '\n'
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export default reporter
|