### Install @fastify/response-validation Source: https://github.com/fastify/fastify-response-validation/blob/main/README.md Install the plugin using npm. ```bash npm i @fastify/response-validation ``` -------------------------------- ### Extend AJV with Plugins via Options Source: https://context7.com/fastify/fastify-response-validation/llms.txt Register AJV plugins without building a custom instance by providing the `ajv.plugins` array. This example registers `ajv-formats` and `ajv-errors` with options. ```javascript import ajvFormats from 'ajv-formats' import ajvErrors from 'ajv-errors' import responseValidation from '@fastify/response-validation' await app.register(responseValidation, { ajv: { allErrors: true, plugins: [ ajvFormats, // plugin without options [ajvErrors, { singleError: false }] // plugin with options ] } }) app.get('/product', { schema: { response: { '2xx': { type: 'object', required: ['price'], properties: { price: { type: 'number', format: 'float' }, sku: { type: 'string' } }, additionalProperties: false, errorMessage: 'Invalid product shape' } } }, handler: async () => ({ sku: 'ABC-1' }) // missing required "price" }) const res = await app.inject({ method: 'GET', url: '/product' }) console.log(res.statusCode) // 500 console.log(res.json().message) // 'response Invalid product shape' ``` -------------------------------- ### Register and Use Response Validation Source: https://github.com/fastify/fastify-response-validation/blob/main/README.md Register the plugin and define a response schema for a route. The example demonstrates basic usage with a GET route and injects a request to test the validation. ```javascript import fastify from 'fastify' const app = fastify() await app.register(require('@fastify/response-validation')) app.route({ method: 'GET', path: '/', schema: { response: { '2xx': { type: 'object', properties: { answer: { type: 'number' } } } } }, handler: async (req, reply) => { return { answer: '42' } } }) app.inject({ method: 'GET', path: '/' }, (err, res) => { if (err) throw err console.log(res.payload) }) ``` -------------------------------- ### Register Plugin and Validate Basic Response Source: https://context7.com/fastify/fastify-response-validation/llms.txt Register the plugin globally to validate all routes with a `schema.response`. This example shows a validation failure due to a type mismatch. ```javascript import fastify from 'fastify' import responseValidation from '@fastify/response-validation' const app = fastify() // Register with all defaults: // coerceTypes: false, useDefaults: true, removeAdditional: true, allErrors: true await app.register(responseValidation) app.get('/user', { schema: { response: { '2xx': { type: 'object', properties: { id: { type: 'number' }, name: { type: 'string' } } } } }, handler: async () => { return { id: '99', name: 'Alice' } // id is a string → validation fails } }) const res = await app.inject({ method: 'GET', url: '/user' }) console.log(res.statusCode) // 500 console.log(res.json()) // { // code: 'FST_RESPONSE_VALIDATION_FAILED_VALIDATION', // statusCode: 500, // error: 'Internal Server Error', // message: 'response/id must be number' // } ``` -------------------------------- ### Pass Pre-Built AJV Instance with Formats and Errors Source: https://context7.com/fastify/fastify-response-validation/llms.txt Provide a fully configured Ajv instance directly when full control over the validator lifecycle is needed. This example includes `ajv-formats` and `ajv-errors` plugins. ```javascript import Ajv from 'ajv' import Ajv2020 from 'ajv/dist/2020' import ajvFormats from 'ajv-formats' import ajvErrors from 'ajv-errors' import responseValidation from '@fastify/response-validation' const ajv = new Ajv2020({ allErrors: true }) ajvFormats(ajv) ajvErrors(ajv, { singleError: true }) await app.register(responseValidation, { ajv }) app.get('/email', { schema: { response: { '2xx': { type: 'object', properties: { email: { type: 'string', format: 'email' } } } } }, handler: async () => ({ email: 'user@example.com' }) }) const res = await app.inject({ method: 'GET', url: '/email' }) console.log(res.statusCode) // 200 console.log(res.json()) // { email: 'user@example.com' } ``` -------------------------------- ### Use Shorthand Schema Syntax for Response Validation Source: https://context7.com/fastify/fastify-response-validation/llms.txt The plugin automatically wraps top-level properties in a schema with `type: 'object'`. This example demonstrates a validation failure with the shorthand syntax. ```javascript await app.register(responseValidation) app.get('/ping', { schema: { response: { '2xx': { // shorthand — no explicit "type: 'object'" required answer: { type: 'number' } } } }, handler: async () => ({ answer: '42' }) // string, not number → fails }) const res = await app.inject({ method: 'GET', url: '/ping' }) console.log(res.statusCode) // 500 console.log(res.json().message) // 'response/answer must be number' ``` -------------------------------- ### Handle Status Code Wildcards and Default Fallback Source: https://context7.com/fastify/fastify-response-validation/llms.txt Supports wildcard status codes (e.g., '2XX') and a 'default' schema for any status code not explicitly matched. This example validates a 503 response against the 'default' schema. ```javascript await app.register(responseValidation) app.get('/order', { schema: { response: { '2XX': { type: 'object', properties: { orderId: { type: 'number' } } }, default: { type: 'object', properties: { errorMessage: { type: 'string' } }, required: ['errorMessage'] } } }, handler: async (_req, reply) => { reply.status(503).send({ errorMessage: 'Service unavailable' }) } }) const res = await app.inject({ method: 'GET', url: '/order' }) console.log(res.statusCode) // 503 — validated against "default" schema console.log(res.json()) // { errorMessage: 'Service unavailable' } ``` -------------------------------- ### Override Default AJV Configuration Source: https://github.com/fastify/fastify-response-validation/blob/main/README.md Customize the AJV instance used by the plugin by passing an options object to the 'ajv' property during registration. This example enables 'coerceTypes'. ```javascript // Default configuration: // coerceTypes: false // useDefaults: true // removeAdditional: true // allErrors: true import responseValidator from '@fastify/response-validation' // ... App setup await fastify.register(responseValidator, { ajv: { coerceTypes: true } }) ``` -------------------------------- ### Enable Strict Status Code Validation Per Route Source: https://context7.com/fastify/fastify-response-validation/llms.txt Override the global setting by enabling `responseStatusCodeValidation` on a specific route. The example shows a route that only defines a schema for status code 204, but the handler returns 200, triggering an error. ```javascript app.route({ method: 'GET', url: '/strict', responseStatusCodeValidation: true, // per-route flag schema: { response: { 204: { type: 'object', properties: { id: { type: 'number' } } } } }, handler: async () => ({ id: 1 }) // handler returns 200, but schema only covers 204 }) const res = await app.inject({ method: 'GET', url: '/strict' }) console.log(res.statusCode) // 500 console.log(res.json()) // { // code: 'FST_RESPONSE_VALIDATION_SCHEMA_NOT_DEFINED', // statusCode: 500, // error: 'Internal Server Error', // message: 'No schema defined for status code 200' // } ``` -------------------------------- ### Override AJV Options with Coerce Types Source: https://context7.com/fastify/fastify-response-validation/llms.txt Pass an ajv options object to override built-in defaults. Enabling `coerceTypes: true` allows the validator to cast values instead of failing. This example demonstrates coercing a string '42' to a number. ```javascript import fastify from 'fastify' import responseValidation from '@fastify/response-validation' const app = fastify() await app.register(responseValidation, { ajv: { coerceTypes: true, // '42' → 42 (string coerced to number) allErrors: true // collect all errors, not just the first } }) app.get('/coerce', { schema: { response: { '2xx': { type: 'object', properties: { answer: { type: 'number' } } } } }, handler: async () => ({ answer: '42' }) // string '42' will be coerced }) const res = await app.inject({ method: 'GET', url: '/coerce' }) console.log(res.statusCode) // 200 console.log(res.json()) // { answer: 42 } — coerced to number ``` -------------------------------- ### Define Response Schema with Content Types Source: https://github.com/fastify/fastify-response-validation/blob/main/README.md Specify response schemas for different content types using the 'content' property. This ensures Fastify correctly compiles the schema for each type. ```json { response: { 200: { description: 'Description and all status-code based properties are working', content: { 'application/json': { schema: { name: { type: 'string' }, image: { type: 'string' }, address: { type: 'string' } } }, 'application/vnd.v1+json': { schema: { fullName: { type: 'string' }, phone: { type: 'string' } } } } } } } ``` -------------------------------- ### Per-Media-Type Response Validation with OpenAPI `content` Source: https://context7.com/fastify/fastify-response-validation/llms.txt Use the OpenAPI `content` key to define different schemas for different media types. The plugin selects the schema based on the response `Content-Type` header. If no schema matches the `Content-Type`, an error is thrown. ```javascript await app.register(responseValidation) app.get('/data', { schema: { response: { '2xx': { content: { 'application/json': { schema: { type: 'object', properties: { value: { type: 'number' } } } }, 'application/vnd.v2+json': { schema: { type: 'object', properties: { value: { type: 'string' } } } } } } } }, handler: async (_req, reply) => { reply.header('Content-Type', 'application/vnd.v2+json') return { value: 'hello' } // valid for application/vnd.v2+json } }) const res = await app.inject({ method: 'GET', url: '/data' }) console.log(res.statusCode) // 200 console.log(res.json()) // { value: 'hello' } // If the Content-Type has no matching schema: // → FST_RESPONSE_VALIDATION_SCHEMA_NOT_DEFINED (500) // → message: 'No schema defined for media type ' ``` -------------------------------- ### Pass Custom AJV Instance Source: https://github.com/fastify/fastify-response-validation/blob/main/README.md Provide a pre-configured AJV instance to the plugin by passing it via the 'ajv' option. This allows for advanced customization of the validator. ```javascript // Default configuration: // coerceTypes: false // useDefaults: true // removeAdditional: true // allErrors: true import responseValidator from '@fastify/response-validation' import Ajv from 'ajv' // ... App setup const ajv = new Ajv() await fastify.register(responseValidator, { ajv }) ``` -------------------------------- ### Add AJV Plugins to Validator Source: https://github.com/fastify/fastify-response-validation/blob/main/README.md Extend the AJV instance with additional plugins, such as 'ajv-formats' or 'ajv-errors', by listing them in the 'plugins' array within the 'ajv' configuration. ```javascript fastify.register(require('fastify-response-validation'), { ajv: { plugins: [ require('ajv-formats'), [require('ajv-errors'), { singleError: false }] // Usage: [plugin, pluginOptions] - Plugin with options // Usage: plugin - Plugin without options ] } }) ``` -------------------------------- ### Enable Strict Status Code Validation Globally Source: https://context7.com/fastify/fastify-response-validation/llms.txt Register the response validation plugin globally with `responseStatusCodeValidation` set to `true`. This ensures every route must cover all status codes it can emit. ```javascript await app.register(responseValidation, { responseStatusCodeValidation: true }) ``` -------------------------------- ### Disable Response Validation Globally Source: https://github.com/fastify/fastify-response-validation/blob/main/README.md Turn off response validation for all routes by setting 'responseValidation' to false when registering the plugin. ```javascript import responseValidator from '@fastify/response-validation' // ... App setup await fastify.register(responseValidator, { responseValidation: false }) ``` -------------------------------- ### Disable Response Validation Globally Source: https://context7.com/fastify/fastify-response-validation/llms.txt Set `responseValidation: false` at plugin registration to turn off response validation for the entire Fastify instance. This allows routes to bypass schema checks. ```javascript await app.register(responseValidation, { responseValidation: false }) app.get('/free', { schema: { response: { '2xx': { type: 'object', properties: { answer: { type: 'number' } } } } }, handler: async () => ({ answer: '42' }) // would fail if validation were on }) const res = await app.inject({ method: 'GET', url: '/free' }) console.log(res.statusCode) // 200 — schema is ignored, no validation console.log(res.json()) // { answer: '42' } ``` -------------------------------- ### Disable Response Validation for a Specific Route Source: https://github.com/fastify/fastify-response-validation/blob/main/README.md Opt out of response validation for an individual route by setting 'responseValidation: false' within the route's options. ```javascript fastify.route({ method: 'GET', path: '/', responseValidation: false, schema: { response: { '2xx': { type: 'object', properties: { answer: { type: 'number' } } } } }, handler: async (req, reply) => { return { answer: '42' } } }) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.