New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

fastify

Package Overview
Dependencies
Maintainers
4
Versions
292
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fastify - npm Package Compare versions

Comparing version 4.28.1 to 4.29.0

test/json-shorthand.test.js

52

docs/Guides/Migration-Guide-V4.md

@@ -9,2 +9,30 @@ # V4 Migration Guide

## Codemods
### Fastify v4 Codemods
To help with the upgrade, we’ve worked with the team at
[Codemod](https://github.com/codemod-com/codemod) to
publish codemods that will automatically update your code to many of
the new APIs and patterns in Fastify v4.
Run the following
[migration recipe](https://go.codemod.com/fastify-4-migration-recipe) to
automatically update your code to Fastify v4:
```
npx codemod@latest fastify/4/migration-recipe
```
This will run the following codemods:
- [`fastify/4/remove-app-use`](https://go.codemod.com/fastify-4-remove-app-use)
- [`fastify/4/reply-raw-access`](https://go.codemod.com/fastify-4-reply-raw-access)
- [`fastify/4/wrap-routes-plugin`](https://go.codemod.com/fastify-4-wrap-routes-plugin)
- [`fastify/4/await-register-calls`](https://go.codemod.com/fastify-4-await-register-calls)
Each of these codemods automates the changes listed in the v4 migration guide.
For a complete list of available Fastify codemods and further details,
see [Codemod Registry](https://go.codemod.com/fastify).
## Breaking Changes

@@ -59,2 +87,8 @@

> **Note**: Codemod remove `app.use()` with:
>
> ```bash
> npx codemod@latest fastify/4/remove-app-use
> ```
### `reply.res` moved to `reply.raw`

@@ -65,2 +99,8 @@

> **Note**: Codemod `reply.res` to `reply.raw` with:
>
> ```bash
> npx codemod@latest fastify/4/reply-raw-access
> ```
### Need to `return reply` to signal a "fork" of the promise chain

@@ -111,2 +151,7 @@

```
> **Note**: Codemod synchronous route definitions with:
>
> ```bash
> npx codemod@latest fastify/4/wrap-routes-plugin
> ```

@@ -137,2 +182,9 @@ * use `await register(...)`

> **Note**: Codemod 'await register(...)' with:
>
> ```bash
> npx codemod@latest fastify/4/await-register-calls
> ```
### Optional URL parameters

@@ -139,0 +191,0 @@

3

docs/Reference/Routes.md

@@ -46,3 +46,4 @@ <h1 align="center">Fastify</h1>

* `body`: validates the body of the request if it is a POST, PUT, PATCH,
TRACE, SEARCH, PROPFIND, PROPPATCH or LOCK method.
TRACE, SEARCH, PROPFIND, PROPPATCH, COPY, MOVE, MKCOL, REPORT, MKCALENDAR
or LOCK method.
* `querystring` or `query`: validates the querystring. This can be a complete

@@ -49,0 +50,0 @@ JSON Schema object, with the property `type` of `object` and `properties`

@@ -238,2 +238,24 @@ <h1 align="center">Fastify</h1>

For `body` schema, it is further possible to differentiate the schema per content
type by nesting the schemas inside `content` property. The schema validation
will be applied based on the `Content-Type` header in the request.
```js
fastify.post('/the/url', {
schema: {
body: {
content: {
'application/json': {
schema: { type: 'object' }
},
'text/plain': {
schema: { type: 'string' }
}
// Other content types will not be validated
}
}
}
}, handler)
```
*Note that Ajv will try to [coerce](https://ajv.js.org/coercion.html) the values

@@ -240,0 +262,0 @@ to the types specified in your schema `type` keywords, both to pass the

@@ -28,2 +28,3 @@

- [FSTDEP021](#FSTDEP021)
- [FSTDEP022](#FSTDEP022)

@@ -96,1 +97,2 @@

| <a id="FSTDEP021">FSTDEP021</a> | The `reply.redirect()` method has a new signature: `reply.redirect(url: string, code?: number)`. It will be enforced in `fastify@v5`'. | [#5483](https://github.com/fastify/fastify/pull/5483) |
| <a id="FSTDEP022">FSTDEP022</a> | You are using the deprecated json shorthand schema on route %s. Specify full object schema instead. It will be removed in `fastify@v5` | [#5483](https://github.com/fastify/fastify/pull/0000) |
'use strict'
const VERSION = '4.28.1'
const VERSION = '4.29.0'

@@ -674,3 +674,3 @@ const Avvio = require('avvio')

if (name === 'onClose') {
this.onClose(fn)
this.onClose(fn.bind(this))
} else if (name === 'onReady' || name === 'onListen' || name === 'onRoute') {

@@ -677,0 +677,0 @@ this[kHooks].add(name, fn)

@@ -31,3 +31,4 @@ 'use strict'

if (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'TRACE' || method === 'SEARCH' ||
method === 'PROPFIND' || method === 'PROPPATCH' || method === 'LOCK' || method === 'REPORT' || method === 'MKCALENDAR') {
method === 'PROPFIND' || method === 'PROPPATCH' || method === 'LOCK' || method === 'COPY' || method === 'MOVE' ||
method === 'MKCOL' || method === 'REPORT' || method === 'MKCALENDAR') {
if (contentType === undefined) {

@@ -34,0 +35,0 @@ if (

@@ -605,6 +605,6 @@ 'use strict'

// since Response contain status code, we need to update before
// any action that used statusCode
const isResponse = toString.call(payload) === '[object Response]'
if (isResponse) {
// since Response contain status code, headers and body,
// we need to update the status, add the headers and use it's body as payload
// before continuing
if (toString.call(payload) === '[object Response]') {
// https://developer.mozilla.org/en-US/docs/Web/API/Response/status

@@ -614,2 +614,18 @@ if (typeof payload.status === 'number') {

}
// https://developer.mozilla.org/en-US/docs/Web/API/Response/headers
if (typeof payload.headers === 'object' && typeof payload.headers.forEach === 'function') {
for (const [headerName, headerValue] of payload.headers) {
reply.header(headerName, headerValue)
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Response/body
if (payload.body !== null) {
if (payload.bodyUsed) {
throw new FST_ERR_REP_RESPONSE_BODY_CONSUMED()
}
}
// Keep going, body is either null or ReadableStream
payload = payload.body
}

@@ -661,22 +677,2 @@ const statusCode = res.statusCode

// Response
if (isResponse) {
// https://developer.mozilla.org/en-US/docs/Web/API/Response/headers
if (typeof payload.headers === 'object' && typeof payload.headers.forEach === 'function') {
for (const [headerName, headerValue] of payload.headers) {
reply.header(headerName, headerValue)
}
}
// https://developer.mozilla.org/en-US/docs/Web/API/Response/body
if (payload.body != null) {
if (payload.bodyUsed) {
throw new FST_ERR_REP_RESPONSE_BODY_CONSUMED()
}
// Response.body always a ReadableStream
sendWebStream(payload.body, res, reply)
}
return
}
if (typeof payload !== 'string' && !Buffer.isBuffer(payload)) {

@@ -732,3 +728,3 @@ throw new FST_ERR_REP_INVALID_PAYLOAD_TYPE(typeof payload)

errorLogged = true
logStreamError(reply.log, err, res)
logStreamError(reply.log, err, reply)
}

@@ -735,0 +731,0 @@ res.destroy()

@@ -369,3 +369,3 @@ 'use strict'

if (!context[kRouteByFastify]) {
const isDuplicatedRoute = error.message.includes(`Method '${opts.method}' already declared for route '${opts.url}'`)
const isDuplicatedRoute = error.message.includes(`Method '${opts.method}' already declared for route`)
if (isDuplicatedRoute) {

@@ -411,3 +411,3 @@ throw new FST_ERR_DUPLICATED_ROUTE(opts.method, opts.url)

if (opts.schema) {
context.schema = normalizeSchema(context.schema, this.initialConfig)
context.schema = normalizeSchema(opts, context.schema, this.initialConfig)

@@ -414,0 +414,0 @@ const schemaController = this[kSchemaController]

@@ -8,2 +8,5 @@ 'use strict'

const {
FSTDEP022
} = require('./warnings')
const {
FST_ERR_SCH_MISSING_ID,

@@ -58,3 +61,3 @@ FST_ERR_SCH_ALREADY_PRESENT,

function normalizeSchema (routeSchemas, serverOptions) {
function normalizeSchema (opts, routeSchemas, serverOptions) {
if (routeSchemas[kSchemaVisited]) {

@@ -78,3 +81,16 @@ return routeSchemas

if (schema && !isCustomSchemaPrototype(schema)) {
routeSchemas[key] = getSchemaAnyway(schema, serverOptions.jsonShorthand)
if (key === 'body' && schema.content) {
const contentProperty = schema.content
const keys = Object.keys(contentProperty)
for (let i = 0; i < keys.length; i++) {
const contentType = keys[i]
const contentSchema = contentProperty[contentType].schema
if (!contentSchema) {
throw new FST_ERR_SCH_CONTENT_MISSING_SCHEMA(contentType)
}
routeSchemas.body.content[contentType].schema = getSchemaAnyway(opts.url, contentSchema, serverOptions.jsonShorthand)
}
continue
}
routeSchemas[key] = getSchemaAnyway(opts.url, schema, serverOptions.jsonShorthand)
}

@@ -101,3 +117,3 @@ }

}
routeSchemas.response[code].content[mediaName].schema = getSchemaAnyway(contentProperty[mediaName].schema, serverOptions.jsonShorthand)
routeSchemas.response[code].content[mediaName].schema = getSchemaAnyway(opts.url, contentProperty[mediaName].schema, serverOptions.jsonShorthand)
if (i === keys.length - 1) {

@@ -110,3 +126,3 @@ hasContentMultipleContentTypes = true

if (!hasContentMultipleContentTypes) {
routeSchemas.response[code] = getSchemaAnyway(routeSchemas.response[code], serverOptions.jsonShorthand)
routeSchemas.response[code] = getSchemaAnyway(opts.url, routeSchemas.response[code], serverOptions.jsonShorthand)
}

@@ -137,5 +153,6 @@ }

function getSchemaAnyway (schema, jsonShorthand) {
function getSchemaAnyway (url, schema, jsonShorthand) {
if (!jsonShorthand || schema.$ref || schema.oneOf || schema.allOf || schema.anyOf || schema.$merge || schema.$patch) return schema
if (!schema.type && !schema.properties) {
FSTDEP022(url)
return {

@@ -142,0 +159,0 @@ type: 'object',

@@ -75,3 +75,4 @@ 'use strict'

}
if (Object.prototype.hasOwnProperty.call(listenOptions, 'host') === false) {
if (Object.prototype.hasOwnProperty.call(listenOptions, 'host') === false ||
listenOptions.host == null) {
listenOptions.host = host

@@ -78,0 +79,0 @@ }

@@ -90,3 +90,13 @@ 'use strict'

if (schema.body) {
context[bodySchema] = compile({ schema: schema.body, method, url, httpPart: 'body' })
const contentProperty = schema.body.content
if (contentProperty) {
const contentTypeSchemas = {}
for (const contentType of Object.keys(contentProperty)) {
const contentSchema = contentProperty[contentType].schema
contentTypeSchemas[contentType] = compile({ schema: contentSchema, method, url, httpPart: 'body', contentType })
}
context[bodySchema] = contentTypeSchemas
} else {
context[bodySchema] = compile({ schema: schema.body, method, url, httpPart: 'body' })
}
} else if (Object.prototype.hasOwnProperty.call(schema, 'body')) {

@@ -144,3 +154,14 @@ FSTWRN001('body', method, url)

if (runExecution || !execution.skipBody) {
const body = validateParam(context[bodySchema], request, 'body')
let validatorFunction = null
if (typeof context[bodySchema] === 'function') {
validatorFunction = context[bodySchema]
} else if (context[bodySchema]) {
// TODO: add request.contentType and reuse it here
const contentType = request.headers['content-type']?.split(';', 1)[0]
const contentSchema = context[bodySchema][contentType]
if (contentSchema) {
validatorFunction = contentSchema
}
}
const body = validateParam(validatorFunction, request, 'body')
if (body) {

@@ -147,0 +168,0 @@ if (typeof body.then !== 'function') {

@@ -90,2 +90,7 @@ 'use strict'

const FSTDEP022 = createDeprecation({
code: 'FSTDEP021',
message: 'You are using the deprecated json shorthand schema on route %s. Specify full object schema instead. It will be removed in `fastify@v5`'
})
const FSTWRN001 = createWarning({

@@ -123,4 +128,5 @@ name: 'FastifyWarning',

FSTDEP021,
FSTDEP022,
FSTWRN001,
FSTWRN002
}
{
"name": "fastify",
"version": "4.28.1",
"version": "4.29.0",
"description": "Fast and low overhead web framework, for Node.js",

@@ -5,0 +5,0 @@ "main": "fastify.js",

@@ -17,2 +17,4 @@ # Sponsors

- [Mercedes-Benz Group](https://github.com/mercedes-benz)
- [Val Town, Inc.](https://opencollective.com/valtown)
- [Handsontable - JavaScript Data Grid](https://handsontable.com/docs/react-data-grid/?utm_source=Fastify_GH&utm_medium=sponsorship&utm_campaign=library_sponsorship_2024)

@@ -19,0 +21,0 @@ ## Tier 2

@@ -13,7 +13,10 @@ 'use strict'

test('close callback', t => {
t.plan(4)
t.plan(7)
const fastify = Fastify()
fastify.addHook('onClose', onClose)
function onClose (instance, done) {
t.type(fastify, this)
t.type(fastify, instance)
t.equal(fastify, this)
t.equal(fastify, instance)
done()

@@ -20,0 +23,0 @@ }

@@ -15,3 +15,6 @@ 'use strict'

handler: function (req, reply) {
reply.code(204).send()
reply.code(204)
.header('location', req.headers.destination)
.header('body', req.body.toString())
.send()
}

@@ -30,3 +33,3 @@ })

test('request - copy', t => {
t.plan(2)
t.plan(4)
sget({

@@ -36,6 +39,10 @@ url: `http://localhost:${fastify.server.address().port}/test.txt`,

headers: {
Destination: '/test2.txt'
}
}, (err, response, body) => {
destination: '/test2.txt',
'Content-Type': 'text/plain'
},
body: '/test3.txt'
}, (err, response) => {
t.error(err)
t.equal(response.headers.location, '/test2.txt')
t.equal(response.headers.body, '/test3.txt')
t.equal(response.statusCode, 204)

@@ -42,0 +49,0 @@ })

@@ -66,3 +66,3 @@ 'use strict'

test('build schema - payload schema', t => {
test('build schema - body schema', t => {
t.plan(1)

@@ -83,2 +83,28 @@ const opts = {

test('build schema - body with multiple content type schemas', t => {
t.plan(2)
const opts = {
schema: {
body: {
content: {
'application/json': {
schema: {
type: 'object',
properties: {
hello: { type: 'string' }
}
}
},
'text/plain': {
schema: { type: 'string' }
}
}
}
}
}
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))
t.type(opts[symbols.bodySchema]['application/json'], 'function')
t.type(opts[symbols.bodySchema]['text/plain'], 'function')
})
test('build schema - avoid repeated normalize schema', t => {

@@ -99,6 +125,6 @@ t.plan(3)

}
opts.schema = normalizeSchema(opts.schema, serverConfig)
opts.schema = normalizeSchema({}, opts.schema, serverConfig)
t.not(kSchemaVisited, undefined)
t.equal(opts.schema[kSchemaVisited], true)
t.equal(opts.schema, normalizeSchema(opts.schema, serverConfig))
t.equal(opts.schema, normalizeSchema({}, opts.schema, serverConfig))
})

@@ -121,3 +147,3 @@

}
opts.schema = normalizeSchema(opts.schema, serverConfig)
opts.schema = normalizeSchema({}, opts.schema, serverConfig)
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))

@@ -140,3 +166,3 @@ t.type(opts[symbols.querystringSchema].schema.type, 'string')

}
opts.schema = normalizeSchema(opts.schema, serverConfig)
opts.schema = normalizeSchema({}, opts.schema, serverConfig)
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))

@@ -176,3 +202,3 @@ t.type(opts[symbols.querystringSchema].schema.type, 'string')

}
opts.schema = normalizeSchema(opts.schema, serverConfig)
opts.schema = normalizeSchema({}, opts.schema, serverConfig)
validation.compileSchemasForValidation(opts, ({ schema, method, url, httpPart }) => ajv.compile(schema))

@@ -205,3 +231,3 @@ t.type(opts[symbols.querystringSchema].schema.type, 'string')

}
opts.schema = normalizeSchema(opts.schema, serverConfig)
opts.schema = normalizeSchema({}, opts.schema, serverConfig)
} catch (err) {

@@ -364,5 +390,5 @@ t.equal(err.code, 'FST_ERR_SCH_DUPLICATE')

testCases.forEach((testCase) => {
const result = normalizeSchema(testCase.schema, { jsonShorthand: true })
const result = normalizeSchema({}, testCase.schema, { jsonShorthand: true })
testCase.assertions(result)
})
})

@@ -102,1 +102,37 @@ 'use strict'

})
test('listen works with undefined host', async t => {
const doNotWarn = () => {
t.fail('should not be deprecated')
}
process.on('warning', doNotWarn)
const fastify = Fastify()
t.teardown(fastify.close.bind(fastify))
t.teardown(() => {
fastify.close()
process.removeListener('warning', doNotWarn)
})
await fastify.listen({ host: undefined, port: 0 })
const address = fastify.server.address()
t.equal(address.address, localhost)
t.ok(address.port > 0)
})
test('listen works with null host', async t => {
const doNotWarn = () => {
t.fail('should not be deprecated')
}
process.on('warning', doNotWarn)
const fastify = Fastify()
t.teardown(fastify.close.bind(fastify))
t.teardown(() => {
fastify.close()
process.removeListener('warning', doNotWarn)
})
await fastify.listen({ host: null, port: 0 })
const address = fastify.server.address()
t.equal(address.address, localhost)
t.ok(address.port > 0)
})

@@ -15,3 +15,3 @@ 'use strict'

handler: function (req, reply) {
reply.code(201).send()
reply.code(201).header('body', req.body.toString()).send()
}

@@ -30,8 +30,11 @@ })

test('request - mkcol', t => {
t.plan(2)
t.plan(3)
sget({
url: `http://localhost:${fastify.server.address().port}/test/`,
method: 'MKCOL'
}, (err, response, body) => {
method: 'MKCOL',
headers: { 'Content-Type': 'text/plain' },
body: '/test.txt'
}, (err, response) => {
t.error(err)
t.equal(response.headers.body, '/test.txt')
t.equal(response.statusCode, 201)

@@ -38,0 +41,0 @@ })

@@ -15,5 +15,5 @@ 'use strict'

handler: function (req, reply) {
const destination = req.headers.destination
reply.code(201)
.header('location', destination)
.header('location', req.headers.destination)
.header('body', req.body.toString())
.send()

@@ -33,3 +33,3 @@ }

test('request - move', t => {
t.plan(3)
t.plan(4)
sget({

@@ -39,10 +39,13 @@ url: `http://localhost:${fastify.server.address().port}/test.txt`,

headers: {
Destination: '/test2.txt'
}
}, (err, response, body) => {
destination: '/test2.txt',
'Content-Type': 'text/plain'
},
body: '/test3.txt'
}, (err, response) => {
t.error(err)
t.equal(response.statusCode, 201)
t.equal(response.headers.location, '/test2.txt')
t.equal(response.headers.body, '/test3.txt')
})
})
})

@@ -143,1 +143,28 @@ 'use strict'

})
test('Adding manually HEAD route after GET with the same path throws Fastify duplicated route instance error', t => {
t.plan(1)
const fastify = Fastify()
fastify.route({
method: 'GET',
path: '/:param1',
handler: (req, reply) => {
reply.send({ hello: 'world' })
}
})
try {
fastify.route({
method: 'HEAD',
path: '/:param2',
handler: (req, reply) => {
reply.send({ hello: 'world' })
}
})
t.fail('Should throw fastify duplicated route declaration')
} catch (error) {
t.equal(error.code, 'FST_ERR_DUPLICATED_ROUTE')
}
})

@@ -193,2 +193,23 @@ 'use strict'

test('Should throw if schema is missing for content type', t => {
t.plan(2)
const fastify = Fastify()
fastify.post('/', {
handler: echoBody,
schema: {
body: {
content: {
'application/json': {}
}
}
}
})
fastify.ready(err => {
t.equal(err.code, 'FST_ERR_SCH_CONTENT_MISSING_SCHEMA')
t.equal(err.message, "Schema is missing for the content type 'application/json'")
})
})
test('Should throw of the schema does not exists in output', t => {

@@ -195,0 +216,0 @@ t.plan(2)

@@ -108,2 +108,138 @@ 'use strict'

test('Different schema per content type', t => {
t.plan(12)
const fastify = Fastify()
fastify.addContentTypeParser('application/octet-stream', {
parseAs: 'buffer'
}, async function (_, payload) {
return payload
})
fastify.post('/', {
schema: {
body: {
content: {
'application/json': {
schema: schemaArtist
},
'application/octet-stream': {
schema: {} // Skip validation
},
'text/plain': {
schema: { type: 'string' }
}
}
}
}
}, async function (req, reply) {
return reply.send(req.body)
})
fastify.inject({
url: '/',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: {
name: 'michelangelo',
work: 'sculptor, painter, architect and poet'
}
}, (err, res) => {
t.error(err)
t.same(JSON.parse(res.payload).name, 'michelangelo')
t.equal(res.statusCode, 200)
})
fastify.inject({
url: '/',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: { name: 'michelangelo' }
}, (err, res) => {
t.error(err)
t.same(res.json(), { statusCode: 400, code: 'FST_ERR_VALIDATION', error: 'Bad Request', message: "body must have required property 'work'" })
t.equal(res.statusCode, 400)
})
fastify.inject({
url: '/',
method: 'POST',
headers: { 'Content-Type': 'application/octet-stream' },
body: Buffer.from('AAAAAAAA')
}, (err, res) => {
t.error(err)
t.same(res.payload, 'AAAAAAAA')
t.equal(res.statusCode, 200)
})
fastify.inject({
url: '/',
method: 'POST',
headers: { 'Content-Type': 'text/plain' },
body: 'AAAAAAAA'
}, (err, res) => {
t.error(err)
t.same(res.payload, 'AAAAAAAA')
t.equal(res.statusCode, 200)
})
})
test('Skip validation if no schema for content type', t => {
t.plan(3)
const fastify = Fastify()
fastify.post('/', {
schema: {
body: {
content: {
'application/json': {
schema: schemaArtist
}
// No schema for 'text/plain'
}
}
}
}, async function (req, reply) {
return reply.send(req.body)
})
fastify.inject({
url: '/',
method: 'POST',
headers: { 'Content-Type': 'text/plain' },
body: 'AAAAAAAA'
}, (err, res) => {
t.error(err)
t.same(res.payload, 'AAAAAAAA')
t.equal(res.statusCode, 200)
})
})
test('Skip validation if no content type schemas', t => {
t.plan(3)
const fastify = Fastify()
fastify.post('/', {
schema: {
body: {
content: {
// No schemas
}
}
}
}, async function (req, reply) {
return reply.send(req.body)
})
fastify.inject({
url: '/',
method: 'POST',
headers: { 'Content-Type': 'text/plain' },
body: 'AAAAAAAA'
}, (err, res) => {
t.error(err)
t.same(res.payload, 'AAAAAAAA')
t.equal(res.statusCode, 200)
})
})
test('External AJV instance', t => {

@@ -110,0 +246,0 @@ t.plan(5)

@@ -25,5 +25,5 @@ 'use strict'

fastify.get('/', () => {})
t.fail('Should throw on duplicated route declaration')
t.fail('Should throw fastify duplicated route declaration')
} catch (error) {
t.equal(error.message, "Method 'GET' already declared for route '/'")
t.equal(error.code, 'FST_ERR_DUPLICATED_ROUTE')
}

@@ -30,0 +30,0 @@ })

@@ -154,3 +154,4 @@ import { FastifyError } from '@fastify/error'

server.addHook('onClose', (instance, done) => {
server.addHook('onClose', function (instance, done) {
expectType<FastifyInstance>(this)
expectType<FastifyInstance>(instance)

@@ -240,3 +241,4 @@ expectAssignable<(err?: FastifyError) => void>(done)

server.addHook('onClose', async (instance) => {
server.addHook('onClose', async function (instance) {
expectType<FastifyInstance>(this)
expectType<FastifyInstance>(instance)

@@ -243,0 +245,0 @@ })

@@ -22,3 +22,10 @@ import { FastifyError } from '@fastify/error'

bar: number;
includeMessage?: boolean;
}
interface FastifyRequest<RouteGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider, ContextConfig, Logger, RequestType> {
message: ContextConfig extends { includeMessage: true }
? string
: null;
}
}

@@ -40,2 +47,18 @@

fastify().get(
'/',
{ config: { foo: 'bar', bar: 100, includeMessage: true } },
(req) => {
expectType<string>(req.message)
}
)
fastify().get(
'/',
{ config: { foo: 'bar', bar: 100, includeMessage: false } },
(req) => {
expectType<null>(req.message)
}
)
type LowerCaseHTTPMethods = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete' | 'options';

@@ -42,0 +65,0 @@

@@ -23,2 +23,21 @@ import { expectAssignable } from 'tsd'

expectAssignable<FastifyInstance>(server.post(
'/multiple-content-schema',
{
schema: {
body: {
content: {
'application/json': {
schema: { type: 'object' }
},
'text/plain': {
schema: { type: 'string' }
}
}
}
}
},
() => { }
))
expectAssignable<FastifyInstance>(server.get(

@@ -25,0 +44,0 @@ '/empty-schema',

@@ -65,2 +65,77 @@ 'use strict'

test('should response with a Response 204', async (t) => {
t.plan(3)
const fastify = Fastify()
fastify.get('/', function (request, reply) {
reply.send(new Response(null, {
status: 204,
headers: {
hello: 'world'
}
}))
})
const {
statusCode,
headers,
body
} = await fastify.inject({ method: 'GET', path: '/' })
t.equal(statusCode, 204)
t.equal(body, '')
t.equal(headers.hello, 'world')
})
test('should response with a Response 304', async (t) => {
t.plan(3)
const fastify = Fastify()
fastify.get('/', function (request, reply) {
reply.send(new Response(null, {
status: 304,
headers: {
hello: 'world'
}
}))
})
const {
statusCode,
headers,
body
} = await fastify.inject({ method: 'GET', path: '/' })
t.equal(statusCode, 304)
t.equal(body, '')
t.equal(headers.hello, 'world')
})
test('should response with a Response without body', async (t) => {
t.plan(3)
const fastify = Fastify()
fastify.get('/', function (request, reply) {
reply.send(new Response(null, {
status: 200,
headers: {
hello: 'world'
}
}))
})
const {
statusCode,
headers,
body
} = await fastify.inject({ method: 'GET', path: '/' })
t.equal(statusCode, 200)
t.equal(body, '')
t.equal(headers.hello, 'world')
})
test('able to use in onSend hook - ReadableStream', async (t) => {

@@ -67,0 +142,0 @@ t.plan(4)

@@ -785,2 +785,3 @@ import { Readable } from 'stream'

(
this: FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>,
instance: FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>,

@@ -799,2 +800,3 @@ done: HookHandlerDoneFunction

(
this: FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>,
instance: FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>

@@ -801,0 +803,0 @@ ): Promise<unknown>;

import { FastifyError } from '@fastify/error'
import { ConstraintStrategy } from 'find-my-way'
import { FastifyRequestContext } from './context'
import { FastifyContextConfig } from './context'
import { onErrorMetaHookHandler, onRequestAbortMetaHookHandler, onRequestMetaHookHandler, onResponseMetaHookHandler, onSendMetaHookHandler, onTimeoutMetaHookHandler, preHandlerMetaHookHandler, preParsingMetaHookHandler, preSerializationMetaHookHandler, preValidationMetaHookHandler } from './hooks'

@@ -55,3 +55,3 @@ import { FastifyInstance } from './instance'

logLevel?: LogLevel;
config?: Omit<FastifyRequestContext<ContextConfig>['config'], 'url' | 'method'>;
config?: FastifyContextConfig & ContextConfig;
version?: string;

@@ -58,0 +58,0 @@ constraints?: RouteConstraint,

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc