strong-tie/inbound-calls
0
1<h1 align="center">Fastify</h1>2 3## TypeScript4 5The Fastify framework is written in vanilla JavaScript, and as such type6definitions are not as easy to maintain; however, since version 2 and beyond,7maintainers and contributors have put in a great effort to improve the types.8 9The type system was changed in Fastify version 3. The new type system introduces10generic constraining and defaulting, plus a new way to define schema types such11as a request body, querystring, and more! As the team works on improving12framework and type definition synergy, sometimes parts of the API will not be13typed or may be typed incorrectly. We encourage you to **contribute** to help us14fill in the gaps. Just make sure to read our15[`CONTRIBUTING.md`](https://github.com/fastify/fastify/blob/main/CONTRIBUTING.md)16file before getting started to make sure things go smoothly!17 18> The documentation in this section covers Fastify version 3.x typings19 20> Plugins may or may not include typings. See [Plugins](#plugins) for more21> information. We encourage users to send pull requests to improve typings22> support.23 24๐จ Don't forget to install `@types/node`25 26## Learn By Example27 28The best way to learn the Fastify type system is by example! The following four29examples should cover the most common Fastify development cases. After the30examples there is further, more detailed documentation for the type system.31 32### Getting Started33 34This example will get you up and running with Fastify and TypeScript. It results35in a blank http Fastify server.36 371. Create a new npm project, install Fastify, and install typescript & Node.js38 types as peer dependencies:39 ```bash40 npm init -y41 npm i fastify42 npm i -D typescript @types/node43 ```442. Add the following lines to the `"scripts"` section of the `package.json`:45 ```json46 {47 "scripts": {48 "build": "tsc -p tsconfig.json",49 "start": "node index.js"50 }51 }52 ```53 543. Initialize a TypeScript configuration file:55 ```bash56 npx tsc --init57 ```58 or use one of the [recommended59 ones](https://github.com/tsconfig/bases#node-14-tsconfigjson).60 61*Note: Set `target` property in `tsconfig.json` to `es2017` or greater to avoid62[FastifyDeprecation](https://github.com/fastify/fastify/issues/3284) warning.*63 644. Create an `index.ts` file - this will contain the server code655. Add the following code block to your file:66 ```typescript67 import fastify from 'fastify'68 69 const server = fastify()70 71 server.get('/ping', async (request, reply) => {72 return 'pong\n'73 })74 75 server.listen({ port: 8080 }, (err, address) => {76 if (err) {77 console.error(err)78 process.exit(1)79 }80 console.log(`Server listening at ${address}`)81 })82 ```836. Run `npm run build` - this will compile `index.ts` into `index.js` which can84 be executed using Node.js. If you run into any errors please open an issue in85 [fastify/help](https://github.com/fastify/help/)867. Run `npm run start` to run the Fastify server878. You should see `Server listening at http://127.0.0.1:8080` in your console889. Try out your server using `curl localhost:8080/ping`, it should return `pong`89 ๐90 91๐ You now have a working Typescript Fastify server! This example demonstrates92the simplicity of the version 3.x type system. By default, the type system93assumes you are using an `http` server. The later examples will demonstrate how94to create more complex servers such as `https` and `http2`, how to specify route95schemas, and more!96 97> For more examples on initializing Fastify with TypeScript (such as enabling98> HTTP2) check out the detailed API section [here][Fastify]99 100### Using Generics101 102The type system heavily relies on generic properties to provide the most103accurate development experience. While some may find the overhead a bit104cumbersome, the tradeoff is worth it! This example will dive into implementing105generic types for route schemas and the dynamic properties located on the106route-level `request` object.107 1081. If you did not complete the previous example, follow steps 1-4 to get set up.1092. Inside `index.ts`, define three interfaces `IQuerystring`,`IHeaders` and `IReply`:110 ```typescript111 interface IQuerystring {112 username: string;113 password: string;114 }115 116 interface IHeaders {117 'h-Custom': string;118 }119 120 interface IReply {121 200: { success: boolean };122 302: { url: string };123 '4xx': { error: string };124 }125 ```1263. Using the three interfaces, define a new API route and pass them as generics.127 The shorthand route methods (i.e. `.get`) accept a generic object128 `RouteGenericInterface` containing five named properties: `Body`,129 `Querystring`, `Params`, `Headers` and `Reply`. The interfaces `Body`,130 `Querystring`, `Params` and `Headers` will be passed down through the route131 method into the route method handler `request` instance and the `Reply`132 interface to the `reply` instance.133 ```typescript134 server.get<{135 Querystring: IQuerystring,136 Headers: IHeaders,137 Reply: IReply138 }>('/auth', async (request, reply) => {139 const { username, password } = request.query140 const customerHeader = request.headers['h-Custom']141 // do something with request data142 143 // chaining .statusCode/.code calls with .send allows type narrowing. For example:144 // this works145 reply.code(200).send({ success: true });146 // but this gives a type error147 reply.code(200).send('uh-oh');148 // it even works for wildcards149 reply.code(404).send({ error: 'Not found' });150 return `logged in!`151 })152 ```153 1544. Build and run the server code with `npm run build` and `npm run start`1555. Query the API156 ```bash157 curl localhost:8080/auth?username=admin&password=Password123!158 ```159 And it should return back `logged in!`1606. But wait there's more! The generic interfaces are also available inside route161 level hook methods. Modify the previous route by adding a `preValidation`162 hook:163 ```typescript164 server.get<{165 Querystring: IQuerystring,166 Headers: IHeaders,167 Reply: IReply168 }>('/auth', {169 preValidation: (request, reply, done) => {170 const { username, password } = request.query171 done(username !== 'admin' ? new Error('Must be admin') : undefined) // only validate `admin` account172 }173 }, async (request, reply) => {174 const customerHeader = request.headers['h-Custom']175 // do something with request data176 return `logged in!`177 })178 ```1797. Build and run and query with the `username` query string option set to180 anything other than `admin`. The API should now return a HTTP 500 error181 `{"statusCode":500,"error":"Internal Server Error","message":"Must be182 admin"}`183 184๐ Good work, now you can define interfaces for each route and have strictly185typed request and reply instances. Other parts of the Fastify type system rely186on generic properties. Make sure to reference the detailed type system187documentation below to learn more about what is available.188 189### JSON Schema190 191To validate your requests and responses you can use JSON Schema files. If you192didn't know already, defining schemas for your Fastify routes can increase their193throughput! Check out the [Validation and194Serialization](./Validation-and-Serialization.md) documentation for more info.195 196Also it has the advantage to use the defined type within your handlers197(including pre-validation, etc.).198 199Here are some options on how to achieve this.200 201#### Fastify Type Providers202 203Fastify offers two packages wrapping `json-schema-to-ts` and `typebox`:204 205- [`@fastify/type-provider-json-schema-to-ts`](https://github.com/fastify/fastify-type-provider-json-schema-to-ts)206- [`@fastify/type-provider-typebox`](https://github.com/fastify/fastify-type-provider-typebox)207 208And a `zod` wrapper by a third party called [`fastify-type-provider-zod`](https://github.com/turkerdev/fastify-type-provider-zod)209 210They simplify schema validation setup and you can read more about them in [Type211Providers](./Type-Providers.md) page.212 213Below is how to setup schema validation using the `typebox`,214`json-schema-to-typescript`, and `json-schema-to-ts` packages without type215providers.216 217#### TypeBox218 219A useful library for building types and a schema at once is [TypeBox](https://www.npmjs.com/package/@sinclair/typebox).220With TypeBox you define your schema within your code and use them directly as221types or schemas as you need them.222 223When you want to use it for validation of some payload in a fastify route you224can do it as follows:225 2261. Install `typebox` in your project.227 228 ```bash229 npm i @sinclair/typebox230 ```231 2322. Define the schema you need with `Type` and create the respective type with233 `Static`.234 235 ```typescript236 import { Static, Type } from '@sinclair/typebox'237 238 export const User = Type.Object({239 name: Type.String(),240 mail: Type.Optional(Type.String({ format: 'email' })),241 })242 243 export type UserType = Static<typeof User>244 ```245 2463. Use the defined type and schema during the definition of your route247 248 ```typescript249 import Fastify from 'fastify'250 // ...251 252 const fastify = Fastify()253 254 fastify.post<{ Body: UserType, Reply: UserType }>(255 '/',256 {257 schema: {258 body: User,259 response: {260 200: User261 },262 },263 },264 (request, reply) => {265 // The `name` and `mail` types are automatically inferred266 const { name, mail } = request.body;267 reply.status(200).send({ name, mail });268 }269 )270 ```271 272#### json-schema-to-typescript273 274In the last example we used Typebox to define the types and schemas for our275route. Many users will already be using JSON Schemas to define these properties,276and luckily there is a way to transform existing JSON Schemas into TypeScript277interfaces!278 2791. If you did not complete the 'Getting Started' example, go back and follow280 steps 1-4 first.2812. Install the `json-schema-to-typescript` module:282 283 ```bash284 npm i -D json-schema-to-typescript285 ```286 2873. Create a new folder called `schemas` and add two files `headers.json` and288 `querystring.json`. Copy and paste the following schema definitions into the289 respective files:290 291 ```json292 {293 "title": "Headers Schema",294 "type": "object",295 "properties": {296 "h-Custom": { "type": "string" }297 },298 "additionalProperties": false,299 "required": ["h-Custom"]300 }301 ```302 303 ```json304 {305 "title": "Querystring Schema",306 "type": "object",307 "properties": {308 "username": { "type": "string" },309 "password": { "type": "string" }310 },311 "additionalProperties": false,312 "required": ["username", "password"]313 }314 ```315 3164. Add a `compile-schemas` script to the package.json:317 318```json319 {320 "scripts": {321 "compile-schemas": "json2ts -i schemas -o types"322 }323 }324```325 326 `json2ts` is a CLI utility included in `json-schema-to-typescript`. `schemas`327 is the input path, and `types` is the output path.3285. Run `npm run compile-schemas`. Two new files should have been created in the329 `types` directory.3306. Update `index.ts` to have the following code:331 332```typescript333 import fastify from 'fastify'334 335 // import json schemas as normal336 import QuerystringSchema from './schemas/querystring.json'337 import HeadersSchema from './schemas/headers.json'338 339 // import the generated interfaces340 import { QuerystringSchema as QuerystringSchemaInterface } from './types/querystring'341 import { HeadersSchema as HeadersSchemaInterface } from './types/headers'342 343 const server = fastify()344 345 server.get<{346 Querystring: QuerystringSchemaInterface,347 Headers: HeadersSchemaInterface348 }>('/auth', {349 schema: {350 querystring: QuerystringSchema,351 headers: HeadersSchema352 },353 preValidation: (request, reply, done) => {354 const { username, password } = request.query355 done(username !== 'admin' ? new Error('Must be admin') : undefined)356 }357 // or if using async358 // preValidation: async (request, reply) => {359 // const { username, password } = request.query360 // if (username !== "admin") throw new Error("Must be admin");361 // }362 }, async (request, reply) => {363 const customerHeader = request.headers['h-Custom']364 // do something with request data365 return `logged in!`366 })367 368 server.route<{369 Querystring: QuerystringSchemaInterface,370 Headers: HeadersSchemaInterface371 }>({372 method: 'GET',373 url: '/auth2',374 schema: {375 querystring: QuerystringSchema,376 headers: HeadersSchema377 },378 preHandler: (request, reply, done) => {379 const { username, password } = request.query380 const customerHeader = request.headers['h-Custom']381 done()382 },383 handler: (request, reply) => {384 const { username, password } = request.query385 const customerHeader = request.headers['h-Custom']386 reply.status(200).send({username});387 }388 })389 390 server.listen({ port: 8080 }, (err, address) => {391 if (err) {392 console.error(err)393 process.exit(0)394 }395 console.log(`Server listening at ${address}`)396 })397 ```398 Pay special attention to the imports at the top of this file. It might seem399 redundant, but you need to import both the schema files and the generated400 interfaces.401 402Great work! Now you can make use of both JSON Schemas and TypeScript403definitions.404 405#### json-schema-to-ts406 407If you do not want to generate types from your schemas, but want to use them408directly from your code, you can use the package409[json-schema-to-ts](https://www.npmjs.com/package/json-schema-to-ts).410 411You can install it as dev-dependency.412 413```bash414npm i -D json-schema-to-ts415```416 417In your code you can define your schema like a normal object. But be aware of418making it *const* like explained in the docs of the module.419 420```typescript421const todo = {422 type: 'object',423 properties: {424 name: { type: 'string' },425 description: { type: 'string' },426 done: { type: 'boolean' },427 },428 required: ['name'],429} as const; // don't forget to use const !430```431 432With the provided type `FromSchema` you can build a type from your schema and433use it in your handler.434 435```typescript436import { FromSchema } from "json-schema-to-ts";437fastify.post<{ Body: FromSchema<typeof todo> }>(438 '/todo',439 {440 schema: {441 body: todo,442 response: {443 201: {444 type: 'string',445 },446 },447 }448 },449 async (request, reply): Promise<void> => {450 451 /*452 request.body has type453 {454 [x: string]: unknown;455 description?: string;456 done?: boolean;457 name: string;458 }459 */460 461 request.body.name // will not throw type error462 request.body.notthere // will throw type error463 464 reply.status(201).send();465 },466);467```468 469### Plugins470 471One of Fastify's most distinguishable features is its extensive plugin472ecosystem. Plugin types are fully supported, and take advantage of the473[declaration474merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html)475pattern. This example is broken up into three parts: Creating a TypeScript476Fastify Plugin, Creating Type Definitions for a Fastify Plugin, and Using a477Fastify Plugin in a TypeScript Project.478 479#### Creating a TypeScript Fastify Plugin480 4811. Initialize a new npm project and install required dependencies482 ```bash483 npm init -y484 npm i fastify fastify-plugin485 npm i -D typescript @types/node486 ```4872. Add a `build` script to the `"scripts"` section and `'index.d.ts'` to the488 `"types"` section of the `package.json` file:489 ```json490 {491 "types": "index.d.ts",492 "scripts": {493 "build": "tsc -p tsconfig.json"494 }495 }496 ```4973. Initialize a TypeScript configuration file:498 ```bash499 npx typescript --init500 ```501 Once the file is generated, enable the `"declaration"` option in the502 `"compilerOptions"` object.503 ```json504 {505 "compilerOptions": {506 "declaration": true507 }508 }509 ```5104. Create an `index.ts` file - this will contain the plugin code5115. Add the following code to `index.ts`512 ```typescript513 import { FastifyPluginCallback, FastifyPluginAsync } from 'fastify'514 import fp from 'fastify-plugin'515 516 // using declaration merging, add your plugin props to the appropriate fastify interfaces517 // if prop type is defined here, the value will be typechecked when you call decorate{,Request,Reply}518 declare module 'fastify' {519 interface FastifyRequest {520 myPluginProp: string521 }522 interface FastifyReply {523 myPluginProp: number524 }525 }526 527 // define options528 export interface MyPluginOptions {529 myPluginOption: string530 }531 532 // define plugin using callbacks533 const myPluginCallback: FastifyPluginCallback<MyPluginOptions> = (fastify, options, done) => {534 fastify.decorateRequest('myPluginProp', 'super_secret_value')535 fastify.decorateReply('myPluginProp', options.myPluginOption)536 537 done()538 }539 540 // define plugin using promises541 const myPluginAsync: FastifyPluginAsync<MyPluginOptions> = async (fastify, options) => {542 fastify.decorateRequest('myPluginProp', 'super_secret_value')543 fastify.decorateReply('myPluginProp', options.myPluginOption)544 }545 546 // export plugin using fastify-plugin547 export default fp(myPluginCallback, '3.x')548 // or549 // export default fp(myPluginAsync, '3.x')550 ```5516. Run `npm run build` to compile the plugin code and produce both a JavaScript552 source file and a type definition file.5537. With the plugin now complete you can [publish to npm] or use it locally.554 > You do not _need_ to publish your plugin to npm to use it. You can include555 > it in a Fastify project and reference it as you would any piece of code! As556 > a TypeScript user, make sure the declaration override exists somewhere that557 > will be included in your project compilation so the TypeScript interpreter558 > can process it.559 560#### Creating Type Definitions for a Fastify Plugin561 562This plugin guide is for Fastify plugins written in JavaScript. The steps563outlined in this example are for adding TypeScript support for users consuming564your plugin.565 5661. Initialize a new npm project and install required dependencies567 ```bash568 npm init -y569 npm i fastify-plugin570 ```5712. Create two files `index.js` and `index.d.ts`5723. Modify the package json to include these files under the `main` and `types`573 properties (the name does not have to be `index` explicitly, but it is574 recommended the files have the same name):575 ```json576 {577 "main": "index.js",578 "types": "index.d.ts"579 }580 ```5814. Open `index.js` and add the following code:582 ```javascript583 // fastify-plugin is highly recommended for any plugin you write584 const fp = require('fastify-plugin')585 586 function myPlugin (instance, options, done) {587 588 // decorate the fastify instance with a custom function called myPluginFunc589 instance.decorate('myPluginFunc', (input) => {590 return input.toUpperCase()591 })592 593 done()594 }595 596 module.exports = fp(myPlugin, {597 fastify: '5.x',598 name: 'my-plugin' // this is used by fastify-plugin to derive the property name599 })600 ```6015. Open `index.d.ts` and add the following code:602 ```typescript603 import { FastifyPluginCallback } from 'fastify'604 605 interface PluginOptions {606 //...607 }608 609 // Optionally, you can add any additional exports.610 // Here we are exporting the decorator we added.611 export interface myPluginFunc {612 (input: string): string613 }614 615 // Most importantly, use declaration merging to add the custom property to the Fastify type system616 declare module 'fastify' {617 interface FastifyInstance {618 myPluginFunc: myPluginFunc619 }620 }621 622 // fastify-plugin automatically adds named export, so be sure to add also this type623 // the variable name is derived from `options.name` property if `module.exports.myPlugin` is missing624 export const myPlugin: FastifyPluginCallback<PluginOptions>625 626 // fastify-plugin automatically adds `.default` property to the exported plugin. See the note below627 export default myPlugin628 ```629 630__Note__: [fastify-plugin](https://github.com/fastify/fastify-plugin) v2.3.0 and631newer, automatically adds `.default` property and a named export to the exported632plugin. Be sure to `export default` and `export const myPlugin` in your typings633to provide the best developer experience. For a complete example you can check634out635[@fastify/swagger](https://github.com/fastify/fastify-swagger/blob/master/index.d.ts).636 637With those files completed, the plugin is now ready to be consumed by any638TypeScript project!639 640The Fastify plugin system enables developers to decorate the Fastify instance,641and the request/reply instances. For more information check out this blog post642on [Declaration Merging and Generic643Inheritance](https://dev.to/ethanarrowood/is-declaration-merging-and-generic-inheritance-at-the-same-time-impossible-53cp).644 645#### Using a Plugin646 647Using a Fastify plugin in TypeScript is just as easy as using one in JavaScript.648Import the plugin with `import/from` and you're all set -- except there is one649exception users should be aware of.650 651Fastify plugins use declaration merging to modify existing Fastify type652interfaces (check out the previous two examples for more details). Declaration653merging is not very _smart_, meaning if the plugin type definition for a plugin654is within the scope of the TypeScript interpreter, then the plugin types will be655included **regardless** of if the plugin is being used or not. This is an656unfortunate limitation of using TypeScript and is unavoidable as of right now.657 658However, there are a couple of suggestions to help improve this experience:659- Make sure the `no-unused-vars` rule is enabled in660 [ESLint](https://eslint.org/docs/rules/no-unused-vars) and any imported plugin661 are actually being loaded.662- In case you've the `@typescript-eslint/no-floating-promises` enabled,663please double-check that your ESLint configuration includes a `allowForKnownSafePromises`664property as described on the [`typescript-eslint no-floating-promises allowForKnownSafePromises665documentation`](https://typescript-eslint.io/rules/no-floating-promises/#allowforknownsafepromises):666```667{668 "rules": {669 "@typescript-eslint/no-floating-promises": ["error", {670 "allowForKnownSafePromises": [671 { "from": "package", "name": "FastifyInstance", "package": "fastify" },672 { "from": "package", "name": "FastifyReply", "package": "fastify" },673 { "from": "package", "name": "SafePromiseLike", "package": "fastify" },674 ]675 }]676 }677}678```679- Use a module such as [depcheck](https://www.npmjs.com/package/depcheck) or680 [npm-check](https://www.npmjs.com/package/npm-check) to verify plugin681 dependencies are being used somewhere in your project.682 683Note that using `require` will not load the type definitions properly and may684cause type errors.685TypeScript can only identify the types that are directly imported into code,686which means that you can use require inline with import on top. For example:687 688```typescript689import 'plugin' // here will trigger the type augmentation.690 691fastify.register(require('plugin'))692```693 694```typescript695import plugin from 'plugin' // here will trigger the type augmentation.696 697fastify.register(plugin)698```699 700Or even explicit config on tsconfig701```jsonc702{703 "types": ["plugin"] // we force TypeScript to import the types704}705```706 707## Code Completion In Vanilla JavaScript708 709Vanilla JavaScript can use the published types to provide code completion (e.g.710[Intellisense](https://code.visualstudio.com/docs/editor/intellisense)) by711following the [TypeScript JSDoc712Reference](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html).713 714For example:715 716```js717/** @type {import('fastify').FastifyPluginAsync<{ optionA: boolean, optionB: string }>} */718module.exports = async function (fastify, { optionA, optionB }) {719 fastify.get('/look', () => 'at me');720}721```722 723## API Type System Documentation724 725This section is a detailed account of all the types available to you in Fastify726version 3.x727 728All `http`, `https`, and `http2` types are inferred from `@types/node`729 730[Generics](#generics) are documented by their default value as well as their731constraint value(s). Read these articles for more information on TypeScript732generics.733- [Generic Parameter734 Default](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html#generic-parameter-defaults)735- [Generic Constraints](https://www.typescriptlang.org/docs/handbook/2/generics.html#generic-constraints)736 737 738#### How to import739 740The Fastify API is powered by the `fastify()` method. In JavaScript you would741import it using `const fastify = require('fastify')`. In TypeScript it is742recommended to use the `import/from` syntax instead so types can be resolved.743There are a couple supported import methods with the Fastify type system.744 7451. `import fastify from 'fastify'`746 - Types are resolved but not accessible using dot notation747 - Example:748 ```typescript749 import fastify from 'fastify'750 751 const f = fastify()752 f.listen({ port: 8080 }, () => { console.log('running') })753 ```754 - Gain access to types with destructuring:755 ```typescript756 import fastify, { FastifyInstance } from 'fastify'757 758 const f: FastifyInstance = fastify()759 f.listen({ port: 8080 }, () => { console.log('running') })760 ```761 - Destructuring also works for the main API method:762 ```typescript763 import { fastify, FastifyInstance } from 'fastify'764 765 const f: FastifyInstance = fastify()766 f.listen({ port: 8080 }, () => { console.log('running') })767 ```7682. `import * as Fastify from 'fastify'`769 - Types are resolved and accessible using dot notation770 - Calling the main Fastify API method requires a slightly different syntax771 (see example)772 - Example:773 ```typescript774 import * as Fastify from 'fastify'775 776 const f: Fastify.FastifyInstance = Fastify.fastify()777 f.listen({ port: 8080 }, () => { console.log('running') })778 ```7793. `const fastify = require('fastify')`780 - This syntax is valid and will import fastify as expected; however, types781 will **not** be resolved782 - Example:783 ```typescript784 const fastify = require('fastify')785 786 const f = fastify()787 f.listen({ port: 8080 }, () => { console.log('running') })788 ```789 - Destructuring is supported and will resolve types properly790 ```typescript791 const { fastify } = require('fastify')792 793 const f = fastify()794 f.listen({ port: 8080 }, () => { console.log('running') })795 ```796 797#### Generics798 799Many type definitions share the same generic parameters; they are all800documented, in detail, within this section.801 802Most definitions depend on `@types/node` modules `http`, `https`, and `http2`803 804##### RawServer805Underlying Node.js server type806 807Default: `http.Server`808 809Constraints: `http.Server`, `https.Server`, `http2.Http2Server`,810`http2.Http2SecureServer`811 812Enforces generic parameters: [`RawRequest`][RawRequestGeneric],813[`RawReply`][RawReplyGeneric]814 815##### RawRequest816Underlying Node.js request type817 818Default: [`RawRequestDefaultExpression`][RawRequestDefaultExpression]819 820Constraints: `http.IncomingMessage`, `http2.Http2ServerRequest`821 822Enforced by: [`RawServer`][RawServerGeneric]823 824##### RawReply825Underlying Node.js response type826 827Default: [`RawReplyDefaultExpression`][RawReplyDefaultExpression]828 829Constraints: `http.ServerResponse`, `http2.Http2ServerResponse`830 831Enforced by: [`RawServer`][RawServerGeneric]832 833##### Logger834Fastify logging utility835 836Default: [`FastifyLoggerOptions`][FastifyLoggerOptions]837 838Enforced by: [`RawServer`][RawServerGeneric]839 840##### RawBody841A generic parameter for the content-type-parser methods.842 843Constraints: `string | Buffer`844 845---846 847#### Fastify848 849##### fastify< [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [Logger][LoggerGeneric]>(opts?: [FastifyServerOptions][FastifyServerOptions]): [FastifyInstance][FastifyInstance]850[src](https://github.com/fastify/fastify/blob/main/fastify.d.ts#L19)851 852The main Fastify API method. By default creates an HTTP server. Utilizing853discriminant unions and overload methods, the type system will automatically854infer which type of server (http, https, or http2) is being created purely based855on the options based to the method (see the examples below for more856information). It also supports an extensive generic type system to allow the857user to extend the underlying Node.js Server, Request, and Reply objects.858Additionally, the `Logger` generic exists for custom log types. See the examples859and generic breakdown below for more information.860 861###### Example 1: Standard HTTP server862 863No need to specify the `Server` generic as the type system defaults to HTTP.864```typescript865import fastify from 'fastify'866 867const server = fastify()868```869Check out the Learn By Example - [Getting Started](#getting-started) example for870a more detailed http server walkthrough.871 872###### Example 2: HTTPS server873 8741. Create the following imports from `@types/node` and `fastify`875 ```typescript876 import fs from 'node:fs'877 import path from 'node:path'878 import fastify from 'fastify'879 ```8802. Perform the following steps before setting up a Fastify HTTPS server881to create the `key.pem` and `cert.pem` files:882```sh883openssl genrsa -out key.pem884openssl req -new -key key.pem -out csr.pem885openssl x509 -req -days 9999 -in csr.pem -signkey key.pem -out cert.pem886rm csr.pem887```8883. Instantiate a Fastify https server and add a route:889 ```typescript890 const server = fastify({891 https: {892 key: fs.readFileSync(path.join(__dirname, 'key.pem')),893 cert: fs.readFileSync(path.join(__dirname, 'cert.pem'))894 }895 })896 897 server.get('/', async function (request, reply) {898 return { hello: 'world' }899 })900 901 server.listen({ port: 8080 }, (err, address) => {902 if (err) {903 console.error(err)904 process.exit(0)905 }906 console.log(`Server listening at ${address}`)907 })908 ```9094. Build and run! Test your server out by querying with: `curl -k910 https://localhost:8080`911 912###### Example 3: HTTP2 server913 914There are two types of HTTP2 server types, insecure and secure. Both require915specifying the `http2` property as `true` in the `options` object. The `https`916property is used for creating a secure http2 server; omitting the `https`917property will create an insecure http2 server.918 919```typescript920const insecureServer = fastify({ http2: true })921const secureServer = fastify({922 http2: true,923 https: {} // use the `key.pem` and `cert.pem` files from the https section924})925```926 927For more details on using HTTP2 check out the Fastify [HTTP2](./HTTP2.md)928documentation page.929 930###### Example 4: Extended HTTP server931 932Not only can you specify the server type, but also the request and reply types.933Thus, allowing you to specify special properties, methods, and more! When934specified at server instantiation, the custom type becomes available on all935further instances of the custom type.936```typescript937import fastify from 'fastify'938import http from 'node:http'939 940interface customRequest extends http.IncomingMessage {941 mySpecialProp: string942}943 944const server = fastify<http.Server, customRequest>()945 946server.get('/', async (request, reply) => {947 const someValue = request.raw.mySpecialProp // TS knows this is a string, because of the `customRequest` interface948 return someValue.toUpperCase()949})950```951 952###### Example 5: Specifying logger types953 954Fastify uses [Pino](https://getpino.io/#/) logging library under the hood. Since955`pino@7`, all of it's properties can be configured via `logger` field when956constructing Fastify's instance. If properties you need aren't exposed, please957open an Issue to [`Pino`](https://github.com/pinojs/pino/issues) or pass a958preconfigured external instance of Pino (or any other compatible logger) as959temporary fix to Fastify via the same field. This allows creating custom960serializers as well, see the [Logging](Logging.md) documentation for more info.961 962```typescript963import fastify from 'fastify'964 965const server = fastify({966 logger: {967 level: 'info',968 redact: ['x-userinfo'],969 messageKey: 'message'970 }971})972 973server.get('/', async (request, reply) => {974 server.log.info('log message')975 return 'another message'976})977```978 979---980 981##### fastify.HTTPMethods982[src](https://github.com/fastify/fastify/blob/main/types/utils.d.ts#L8)983 984Union type of: `'DELETE' | 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT' |985'OPTIONS'`986 987##### fastify.RawServerBase988[src](https://github.com/fastify/fastify/blob/main/types/utils.d.ts#L13)989 990Dependent on `@types/node` modules `http`, `https`, `http2`991 992Union type of: `http.Server | https.Server | http2.Http2Server |993http2.Http2SecureServer`994 995##### fastify.RawServerDefault996[src](https://github.com/fastify/fastify/blob/main/types/utils.d.ts#L18)997 998Dependent on `@types/node` modules `http`999 1000Type alias for `http.Server`1001 1002---1003 1004##### fastify.FastifyServerOptions< [RawServer][RawServerGeneric], [Logger][LoggerGeneric]>1005 1006[src](https://github.com/fastify/fastify/blob/main/fastify.d.ts#L29)1007 1008An interface of properties used in the instantiation of the Fastify server. Is1009used in the main [`fastify()`][Fastify] method. The `RawServer` and `Logger`1010generic parameters are passed down through that method.1011 1012See the main [fastify][Fastify] method type definition section for examples on1013instantiating a Fastify server with TypeScript.1014 1015##### fastify.FastifyInstance< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RequestGeneric][FastifyRequestGenericInterface], [Logger][LoggerGeneric]>1016 1017[src](https://github.com/fastify/fastify/blob/main/types/instance.d.ts#L16)1018 1019Interface that represents the Fastify server object. This is the returned server1020instance from the [`fastify()`][Fastify] method. This type is an interface so it1021can be extended via [declaration1022merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html)1023if your code makes use of the `decorate` method.1024 1025Through the use of generic cascading, all methods attached to the instance1026inherit the generic properties from instantiation. This means that by specifying1027the server, request, or reply types, all methods will know how to type those1028objects.1029 1030Check out the main [Learn by Example](#learn-by-example) section for detailed1031guides, or the more simplified [fastify][Fastify] method examples for additional1032details on this interface.1033 1034---1035 1036#### Request1037 1038##### fastify.FastifyRequest< [RequestGeneric][FastifyRequestGenericInterface], [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric]>1039[src](https://github.com/fastify/fastify/blob/main/types/request.d.ts#L15)1040 1041This interface contains properties of Fastify request object. The properties1042added here disregard what kind of request object (http vs http2) and disregard1043what route level it is serving; thus calling `request.body` inside a GET request1044will not throw an error (but good luck sending a GET request with a body ๐).1045 1046If you need to add custom properties to the `FastifyRequest` object (such as1047when using the [`decorateRequest`][DecorateRequest] method) you need to use1048declaration merging on this interface.1049 1050A basic example is provided in the [`FastifyRequest`][FastifyRequest] section.1051For a more detailed example check out the Learn By Example section:1052[Plugins](#plugins)1053 1054###### Example1055```typescript1056import fastify from 'fastify'1057 1058const server = fastify()1059 1060server.decorateRequest('someProp', 'hello!')1061 1062server.get('/', async (request, reply) => {1063 const { someProp } = request // need to use declaration merging to add this prop to the request interface1064 return someProp1065})1066 1067// this declaration must be in scope of the typescript interpreter to work1068declare module 'fastify' {1069 interface FastifyRequest { // you must reference the interface and not the type1070 someProp: string1071 }1072}1073 1074// Or you can type your request using1075type CustomRequest = FastifyRequest<{1076 Body: { test: boolean };1077}>1078 1079server.get('/typedRequest', async (request: CustomRequest, reply: FastifyReply) => {1080 return request.body.test1081})1082```1083 1084##### fastify.RequestGenericInterface1085[src](https://github.com/fastify/fastify/blob/main/types/request.d.ts#L4)1086 1087Fastify request objects have four dynamic properties: `body`, `params`, `query`,1088and `headers`. Their respective types are assignable through this interface. It1089is a named property interface enabling the developer to ignore the properties1090they do not want to specify. All omitted properties are defaulted to `unknown`.1091The corresponding property names are: `Body`, `Querystring`, `Params`,1092`Headers`.1093 1094```typescript1095import fastify, { RequestGenericInterface } from 'fastify'1096 1097const server = fastify()1098 1099interface requestGeneric extends RequestGenericInterface {1100 Querystring: {1101 name: string1102 }1103}1104 1105server.get<requestGeneric>('/', async (request, reply) => {1106 const { name } = request.query // the name prop now exists on the query prop1107 return name.toUpperCase()1108})1109```1110 1111If you want to see a detailed example of using this interface check out the1112Learn by Example section: [JSON Schema](#json-schema).1113 1114##### fastify.RawRequestDefaultExpression\<[RawServer][RawServerGeneric]\>1115[src](https://github.com/fastify/fastify/blob/main/types/utils.d.ts#L23)1116 1117Dependent on `@types/node` modules `http`, `https`, `http2`1118 1119Generic parameter `RawServer` defaults to [`RawServerDefault`][RawServerDefault]1120 1121If `RawServer` is of type `http.Server` or `https.Server`, then this expression1122returns `http.IncomingMessage`, otherwise, it returns1123`http2.Http2ServerRequest`.1124 1125```typescript1126import http from 'node:http'1127import http2 from 'node:http2'1128import { RawRequestDefaultExpression } from 'fastify'1129 1130RawRequestDefaultExpression<http.Server> // -> http.IncomingMessage1131RawRequestDefaultExpression<http2.Http2Server> // -> http2.Http2ServerRequest1132```1133 1134---1135 1136#### Reply1137 1138##### fastify.FastifyReply<[RequestGeneric][FastifyRequestGenericInterface], [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [ContextConfig][ContextConfigGeneric]>1139[src](https://github.com/fastify/fastify/blob/main/types/reply.d.ts#L32)1140 1141This interface contains the custom properties that Fastify adds to the standard1142Node.js reply object. The properties added here disregard what kind of reply1143object (http vs http2).1144 1145If you need to add custom properties to the FastifyReply object (such as when1146using the `decorateReply` method) you need to use declaration merging on this1147interface.1148 1149A basic example is provided in the [`FastifyReply`][FastifyReply] section. For a1150more detailed example check out the Learn By Example section:1151[Plugins](#plugins)1152 1153###### Example1154```typescript1155import fastify from 'fastify'1156 1157const server = fastify()1158 1159server.decorateReply('someProp', 'world')1160 1161server.get('/', async (request, reply) => {1162 const { someProp } = reply // need to use declaration merging to add this prop to the reply interface1163 return someProp1164})1165 1166// this declaration must be in scope of the typescript interpreter to work1167declare module 'fastify' {1168 interface FastifyReply { // you must reference the interface and not the type1169 someProp: string1170 }1171}1172```1173 1174##### fastify.RawReplyDefaultExpression< [RawServer][RawServerGeneric]>1175[src](https://github.com/fastify/fastify/blob/main/types/utils.d.ts#L27)1176 1177Dependent on `@types/node` modules `http`, `https`, `http2`1178 1179Generic parameter `RawServer` defaults to [`RawServerDefault`][RawServerDefault]1180 1181If `RawServer` is of type `http.Server` or `https.Server`, then this expression1182returns `http.ServerResponse`, otherwise, it returns1183`http2.Http2ServerResponse`.1184 1185```typescript1186import http from 'node:http'1187import http2 from 'node:http2'1188import { RawReplyDefaultExpression } from 'fastify'1189 1190RawReplyDefaultExpression<http.Server> // -> http.ServerResponse1191RawReplyDefaultExpression<http2.Http2Server> // -> http2.Http2ServerResponse1192```1193 1194---1195 1196#### Plugin1197 1198Fastify allows the user to extend its functionalities with plugins. A plugin can1199be a set of routes, a server decorator or whatever. To activate plugins, use the1200[`fastify.register()`][FastifyRegister] method.