fastify 3.7.0 → 3.8.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.
Files changed (66) hide show
  1. package/docs/Ecosystem.md +6 -1
  2. package/docs/Hooks.md +0 -5
  3. package/docs/Recommendations.md +17 -0
  4. package/docs/Reply.md +2 -2
  5. package/docs/Request.md +1 -1
  6. package/docs/Routes.md +19 -1
  7. package/docs/Server.md +2 -0
  8. package/docs/Style-Guide.md +180 -0
  9. package/docs/TypeScript.md +359 -359
  10. package/examples/parser.js +1 -1
  11. package/fastify.js +8 -8
  12. package/lib/contentTypeParser.js +12 -11
  13. package/lib/context.js +4 -3
  14. package/lib/decorate.js +1 -1
  15. package/lib/fourOhFour.js +4 -4
  16. package/lib/handleRequest.js +5 -5
  17. package/lib/hooks.js +4 -4
  18. package/lib/logger.js +6 -6
  19. package/lib/pluginUtils.js +1 -1
  20. package/lib/reply.js +24 -21
  21. package/lib/reqIdGenFactory.js +2 -2
  22. package/lib/request.js +8 -5
  23. package/lib/route.js +9 -8
  24. package/lib/schemas.js +1 -1
  25. package/lib/server.js +5 -5
  26. package/lib/validation.js +8 -8
  27. package/package.json +8 -8
  28. package/test/404s.test.js +15 -15
  29. package/test/async-await.test.js +7 -7
  30. package/test/custom-parser-async.test.js +2 -2
  31. package/test/custom-parser.test.js +8 -8
  32. package/test/helper.js +1 -1
  33. package/test/hooks.test.js +6 -6
  34. package/test/http2/head.test.js +1 -1
  35. package/test/http2/plain.test.js +1 -1
  36. package/test/http2/secure-with-fallback.test.js +1 -1
  37. package/test/http2/secure.test.js +1 -1
  38. package/test/http2/unknown-http-method.test.js +1 -1
  39. package/test/https/https.test.js +2 -1
  40. package/test/inject.test.js +2 -2
  41. package/test/internals/all.test.js +1 -1
  42. package/test/internals/hookRunner.test.js +1 -1
  43. package/test/internals/logger.test.js +1 -1
  44. package/test/internals/reply.test.js +62 -7
  45. package/test/internals/request.test.js +23 -0
  46. package/test/listen.test.js +12 -0
  47. package/test/logger.test.js +10 -10
  48. package/test/nullable-validation.test.js +108 -0
  49. package/test/pretty-print.test.js +9 -14
  50. package/test/reply-error.test.js +2 -2
  51. package/test/route-hooks.test.js +10 -10
  52. package/test/stream.test.js +11 -11
  53. package/test/types/fastify.test-d.ts +1 -2
  54. package/test/types/logger.test-d.ts +1 -1
  55. package/test/types/route.test-d.ts +5 -0
  56. package/test/versioned-routes.test.js +55 -0
  57. package/types/.eslintrc.json +4 -1
  58. package/types/content-type-parser.d.ts +0 -15
  59. package/types/hooks.d.ts +138 -16
  60. package/types/instance.d.ts +81 -2
  61. package/types/logger.d.ts +1 -1
  62. package/types/plugin.d.ts +5 -7
  63. package/types/register.d.ts +8 -8
  64. package/types/route.d.ts +38 -58
  65. package/types/schema.d.ts +4 -4
  66. package/types/serverFactory.d.ts +9 -9
@@ -4,7 +4,7 @@
4
4
 
5
5
  The Fastify framework is written in vanilla JavaScript, and as such type definitions are not as easy to maintain; however, since version 2 and beyond, maintainers and contributors have put in a great effort to improve the types.
6
6
 
7
- The type system was changed in Fastify version 3. The new type system introduces generic constraining and defaulting, plus a new way to define schema types such as a request body, querystring, and more! As the team works on improving framework and type definition synergy, sometimes parts of the API will not be typed or may be typed incorrectly. We encourage you to **contribute** to help us fill in the gaps. Just make sure to read our [`CONTRIBUTING.md`](../CONTRIBUTING.md) file before getting started to make sure things go smoothly!
7
+ The type system was changed in Fastify version 3. The new type system introduces generic constraining and defaulting, plus a new way to define schema types such as a request body, querystring, and more! As the team works on improving framework and type definition synergy, sometimes parts of the API will not be typed or may be typed incorrectly. We encourage you to **contribute** to help us fill in the gaps. Just make sure to read our [`CONTRIBUTING.md`](../CONTRIBUTING.md) file before getting started to make sure things go smoothly!
8
8
 
9
9
  > The documentation in this section covers Fastify version 3.x typings
10
10
 
@@ -14,11 +14,11 @@ The type system was changed in Fastify version 3. The new type system introduces
14
14
 
15
15
  ## Learn By Example
16
16
 
17
- The best way to learn the Fastify type system is by example! The following four examples should cover the most common Fastify development cases. After the examples there is further, more detailed documentation for the type system.
17
+ The best way to learn the Fastify type system is by example! The following four examples should cover the most common Fastify development cases. After the examples there is further, more detailed documentation for the type system.
18
18
 
19
19
  ### Getting Started
20
20
 
21
- This example will get you up and running with Fastify and TypeScript. It results in a blank http Fastify server.
21
+ This example will get you up and running with Fastify and TypeScript. It results in a blank http Fastify server.
22
22
 
23
23
  1. Create a new npm project, install Fastify, and install typescript & node.js types as peer dependencies:
24
24
  ```bash
@@ -39,27 +39,27 @@ This example will get you up and running with Fastify and TypeScript. It results
39
39
  ```bash
40
40
  npx typescript --init
41
41
  ```
42
- or use one of the [recommended ones](https://github.com/tsconfig/bases#node-10-tsconfigjson).
42
+ or use one of the [recommended ones](https://github.com/tsconfig/bases#node-10-tsconfigjson).
43
43
 
44
44
  4. Create an `index.ts` file - this will contain the server code
45
45
  5. Add the following code block to your file:
46
- ```typescript
47
- import fastify from 'fastify'
48
-
49
- const server = fastify()
50
-
51
- server.get('/ping', async (request, reply) => {
52
- return 'pong\n'
53
- })
54
-
55
- server.listen(8080, (err, address) => {
56
- if(err) {
57
- console.error(err)
58
- process.exit(1)
59
- }
60
- console.log(`Server listening at ${address}`)
61
- })
62
- ```
46
+ ```typescript
47
+ import fastify from 'fastify'
48
+
49
+ const server = fastify()
50
+
51
+ server.get('/ping', async (request, reply) => {
52
+ return 'pong\n'
53
+ })
54
+
55
+ server.listen(8080, (err, address) => {
56
+ if (err) {
57
+ console.error(err)
58
+ process.exit(1)
59
+ }
60
+ console.log(`Server listening at ${address}`)
61
+ })
62
+ ```
63
63
  6. Run `npm run build` - this will compile `index.ts` into `index.js` which can be executed using Node.js. If you run into any errors please open an issue in [fastify/help](https://github.com/fastify/help/)
64
64
  7. Run `npm run start` to run the Fastify server
65
65
  8. You should see `Server listening at http://127.0.0.1:8080` in your console
@@ -75,51 +75,51 @@ The type system heavily relies on generic properties to provide the most accurat
75
75
 
76
76
  1. If you did not complete the previous example, follow steps 1-4 to get set up.
77
77
  2. Inside `index.ts`, define two interfaces `IQuerystring` and `IHeaders`:
78
- ```typescript
79
- interface IQuerystring {
80
- username: string;
81
- password: string;
82
- }
83
-
84
- interface IHeaders {
85
- 'H-Custom': string;
86
- }
87
- ```
88
- 3. Using the two interfaces, define a new API route and pass them as generics. The shorthand route methods (i.e. `.get`) accept a generic object `RequestGenericInterface` containing four named properties: `Body`, `Querystring`, `Params`, and `Headers`. The interfaces will be passed down through the route method into the route method handler `request` instance.
89
- ```typescript
90
- server.get<{
91
- Querystring: IQuerystring,
92
- Headers: IHeaders
93
- }>('/auth', async (request, reply) => {
94
- const { username, password } = request.query
95
- const customerHeader = request.headers['H-Custom']
96
- // do something with request data
97
-
98
- return `logged in!`
99
- })
100
- ```
78
+ ```typescript
79
+ interface IQuerystring {
80
+ username: string;
81
+ password: string;
82
+ }
83
+
84
+ interface IHeaders {
85
+ 'H-Custom': string;
86
+ }
87
+ ```
88
+ 3. Using the two interfaces, define a new API route and pass them as generics. The shorthand route methods (i.e. `.get`) accept a generic object `RequestGenericInterface` containing four named properties: `Body`, `Querystring`, `Params`, and `Headers`. The interfaces will be passed down through the route method into the route method handler `request` instance.
89
+ ```typescript
90
+ server.get<{
91
+ Querystring: IQuerystring,
92
+ Headers: IHeaders
93
+ }>('/auth', async (request, reply) => {
94
+ const { username, password } = request.query
95
+ const customerHeader = request.headers['H-Custom']
96
+ // do something with request data
97
+
98
+ return `logged in!`
99
+ })
100
+ ```
101
101
  4. Build and run the server code with `npm run build` and `npm run start`
102
102
  5. Query the api
103
- ```bash
104
- curl localhost:8080/auth?username=admin&password=Password123!
105
- ```
106
- And it should return back `logged in!`
103
+ ```bash
104
+ curl localhost:8080/auth?username=admin&password=Password123!
105
+ ```
106
+ And it should return back `logged in!`
107
107
  6. But wait theres more! The generic interfaces are also available inside route level hook methods. Modify the previous route by adding a `preValidation` hook:
108
- ```typescript
109
- server.get<{
110
- Querystring: IQuerystring,
111
- Headers: IHeaders
112
- }>('/auth', {
113
- preValidation: (request, reply, done) => {
114
- const { username, password } = request.query
115
- done(username !== 'admin' ? new Error('Must be admin') : undefined) // only validate `admin` account
116
- }
117
- }, async (request, reply) => {
118
- const customerHeader = request.headers['H-Custom']
119
- // do something with request data
120
- return `logged in!`
121
- })
122
- ```
108
+ ```typescript
109
+ server.get<{
110
+ Querystring: IQuerystring,
111
+ Headers: IHeaders
112
+ }>('/auth', {
113
+ preValidation: (request, reply, done) => {
114
+ const { username, password } = request.query
115
+ done(username !== 'admin' ? new Error('Must be admin') : undefined) // only validate `admin` account
116
+ }
117
+ }, async (request, reply) => {
118
+ const customerHeader = request.headers['H-Custom']
119
+ // do something with request data
120
+ return `logged in!`
121
+ })
122
+ ```
123
123
  7. Build and run and query with the `username` query string option set to anything other than `admin`. The API should now return a HTTP 500 error `{"statusCode":500,"error":"Internal Server Error","message":"Must be admin"}`
124
124
 
125
125
  🎉 Good work, now you can define interfaces for each route and have strictly typed request and reply instances. Other parts of the Fastify type system rely on generic properties. Make sure to reference the detailed type system documentation below to learn more about what is available.
@@ -130,262 +130,262 @@ In the last example we used interfaces to define the types for the request query
130
130
 
131
131
  1. If you did not complete the 'Getting Started' example, go back and follow steps 1-4 first.
132
132
  2. Install the `json-schema-to-typescript` module:
133
- ```
134
- npm i -D json-schema-to-typescript
135
- ```
133
+ ```
134
+ npm i -D json-schema-to-typescript
135
+ ```
136
136
  3. Create a new folder called `schemas` and add two files `headers.json` and `querystring.json`. Copy and paste the following schema definitions into the respective files:
137
- ```json
138
- {
139
- "title": "Headers Schema",
140
- "type": "object",
141
- "properties": {
142
- "H-Custom": { "type": "string" }
143
- },
144
- "additionalProperties": false,
145
- "required": ["H-Custom"]
146
- }
147
- ```
148
- ```json
149
- {
150
- "title": "Querystring Schema",
151
- "type": "object",
152
- "properties": {
153
- "username": { "type": "string" },
154
- "password": { "type": "string" }
155
- },
156
- "additionalProperties": false,
157
- "required": ["username", "password"]
158
- }
159
- ```
137
+ ```json
138
+ {
139
+ "title": "Headers Schema",
140
+ "type": "object",
141
+ "properties": {
142
+ "H-Custom": { "type": "string" }
143
+ },
144
+ "additionalProperties": false,
145
+ "required": ["H-Custom"]
146
+ }
147
+ ```
148
+ ```json
149
+ {
150
+ "title": "Querystring Schema",
151
+ "type": "object",
152
+ "properties": {
153
+ "username": { "type": "string" },
154
+ "password": { "type": "string" }
155
+ },
156
+ "additionalProperties": false,
157
+ "required": ["username", "password"]
158
+ }
159
+ ```
160
160
  4. Add a `compile-schemas` script to the package.json:
161
- ```json
162
- {
163
- "scripts": {
164
- "compile-schemas": "json2ts -i schemas -o types"
165
- }
166
- }
167
- ```
168
- `json2ts` is a CLI utility included in `json-schema-to-typescript`. `schemas` is the input path, and `types` is the output path.
161
+ ```json
162
+ {
163
+ "scripts": {
164
+ "compile-schemas": "json2ts -i schemas -o types"
165
+ }
166
+ }
167
+ ```
168
+ `json2ts` is a CLI utility included in `json-schema-to-typescript`. `schemas` is the input path, and `types` is the output path.
169
169
  5. Run `npm run compile-schemas`. Two new files should have been created in the `types` directory.
170
170
  6. Update `index.ts` to have the following code:
171
- ```typescript
172
- import fastify from 'fastify'
173
-
174
- // import json schemas as normal
175
- import QuerystringSchema from './schemas/querystring.json'
176
- import HeadersSchema from './schemas/headers.json'
177
-
178
- // import the generated interfaces
179
- import { QuerystringSchema as QuerystringSchemaInterface } from './types/querystring'
180
- import { HeadersSchema as HeadersSchemaInterface } from './types/headers'
181
-
182
- const server = fastify()
183
-
184
- server.get<{
185
- Querystring: QuerystringSchemaInterface,
186
- Headers: HeadersSchemaInterface
187
- }>('/auth', {
188
- schema: {
189
- querystring: QuerystringSchema,
190
- headers: HeadersSchema
191
- },
192
- preValidation: (request, reply, done) => {
193
- const { username, password } = request.query
194
- done(username !== 'admin' ? new Error('Must be admin') : undefined)
195
- }
196
- }, async (request, reply) => {
197
- const customerHeader = request.headers['H-Custom']
198
- // do something with request data
199
- return `logged in!`
200
- })
201
-
202
- server.route<{
203
- Querystring: QuerystringSchemaInterface,
204
- Headers: HeadersSchemaInterface
205
- }>({
206
- method: 'GET',
207
- url: '/auth2',
208
- schema: {
209
- querystring: QuerystringSchema,
210
- headers: HeadersSchema
211
- },
212
- preHandler: (request, reply) => {
213
- const { username, password } = request.query
214
- const customerHeader = request.headers['H-Custom']
215
- },
216
- handler: (request, reply) => {
217
- const { username, password } = request.query
218
- const customerHeader = request.headers['H-Custom']
219
- }
220
- })
221
-
222
- server.listen(8080, (err, address) => {
223
- if(err) {
224
- console.error(err)
225
- process.exit(0)
226
- }
227
- console.log(`Server listening at ${address}`)
228
- })
229
- ```
230
- Pay special attention to the imports at the top of this file. It might seem redundant, but you need to import both the schema files and the generated interfaces.
171
+ ```typescript
172
+ import fastify from 'fastify'
173
+
174
+ // import json schemas as normal
175
+ import QuerystringSchema from './schemas/querystring.json'
176
+ import HeadersSchema from './schemas/headers.json'
177
+
178
+ // import the generated interfaces
179
+ import { QuerystringSchema as QuerystringSchemaInterface } from './types/querystring'
180
+ import { HeadersSchema as HeadersSchemaInterface } from './types/headers'
181
+
182
+ const server = fastify()
183
+
184
+ server.get<{
185
+ Querystring: QuerystringSchemaInterface,
186
+ Headers: HeadersSchemaInterface
187
+ }>('/auth', {
188
+ schema: {
189
+ querystring: QuerystringSchema,
190
+ headers: HeadersSchema
191
+ },
192
+ preValidation: (request, reply, done) => {
193
+ const { username, password } = request.query
194
+ done(username !== 'admin' ? new Error('Must be admin') : undefined)
195
+ }
196
+ }, async (request, reply) => {
197
+ const customerHeader = request.headers['H-Custom']
198
+ // do something with request data
199
+ return `logged in!`
200
+ })
201
+
202
+ server.route<{
203
+ Querystring: QuerystringSchemaInterface,
204
+ Headers: HeadersSchemaInterface
205
+ }>({
206
+ method: 'GET',
207
+ url: '/auth2',
208
+ schema: {
209
+ querystring: QuerystringSchema,
210
+ headers: HeadersSchema
211
+ },
212
+ preHandler: (request, reply) => {
213
+ const { username, password } = request.query
214
+ const customerHeader = request.headers['H-Custom']
215
+ },
216
+ handler: (request, reply) => {
217
+ const { username, password } = request.query
218
+ const customerHeader = request.headers['H-Custom']
219
+ }
220
+ })
221
+
222
+ server.listen(8080, (err, address) => {
223
+ if (err) {
224
+ console.error(err)
225
+ process.exit(0)
226
+ }
227
+ console.log(`Server listening at ${address}`)
228
+ })
229
+ ```
230
+ Pay special attention to the imports at the top of this file. It might seem redundant, but you need to import both the schema files and the generated interfaces.
231
231
 
232
232
  Great work! Now you can make use of both JSON Schemas and TypeScript definitions. If you didn't know already, defining schemas for your Fastify routes can increase their throughput! Check out the [Validation and Serialization](Validation-and-Serialization.md) documenation for more info.
233
233
 
234
234
  Some additional notes:
235
- - Currently, there is no type definition support for inline JSON schemas. If you can come up with a solution please open a PR!
235
+ - Currently, there is no type definition support for inline JSON schemas. If you can come up with a solution please open a PR!
236
236
 
237
237
  ### Plugins
238
238
 
239
- One of Fastify's most distinguishable features is its extensive plugin ecosystem. Plugin types are fully supported, and take advantage of the [declaration merging]() pattern. This example is broken up into three parts: Creating a TypeScript Fastify Plugin, Creating Type Definitions for a Fastify Plugin, and Using a Fastify Plugin in a TypeScript Project.
239
+ One of Fastify's most distinguishable features is its extensive plugin ecosystem. Plugin types are fully supported, and take advantage of the [declaration merging]() pattern. This example is broken up into three parts: Creating a TypeScript Fastify Plugin, Creating Type Definitions for a Fastify Plugin, and Using a Fastify Plugin in a TypeScript Project.
240
240
 
241
241
  #### Creating a TypeScript Fastify Plugin
242
242
 
243
243
  1. Initialize a new npm project and install required dependencies
244
- ```bash
245
- npm init -y
246
- npm i fastify fastify-plugin
247
- npm i -D typescript @types/node
248
- ```
244
+ ```bash
245
+ npm init -y
246
+ npm i fastify fastify-plugin
247
+ npm i -D typescript @types/node
248
+ ```
249
249
  2. Add a `build` script to the `"scripts"` section and `'index.d.ts'` to the `"types"` section of the `package.json` file:
250
- ```json
251
- {
252
- "types": "index.d.ts",
253
- "scripts": {
254
- "build": "tsc -p tsconfig.json"
255
- }
256
- }
257
- ```
250
+ ```json
251
+ {
252
+ "types": "index.d.ts",
253
+ "scripts": {
254
+ "build": "tsc -p tsconfig.json"
255
+ }
256
+ }
257
+ ```
258
258
  3. Initialize a TypeScript configuration file:
259
- ```bash
260
- npx typescript --init
261
- ```
262
- Once the file is generated, enable the `"declaration"` option in the `"compilerOptions"` object.
263
- ```json
264
- {
265
- "compileOptions": {
266
- "declaration": true
267
- }
268
- }
269
- ```
259
+ ```bash
260
+ npx typescript --init
261
+ ```
262
+ Once the file is generated, enable the `"declaration"` option in the `"compilerOptions"` object.
263
+ ```json
264
+ {
265
+ "compileOptions": {
266
+ "declaration": true
267
+ }
268
+ }
269
+ ```
270
270
  4. Create an `index.ts` file - this will contain the plugin code
271
271
  5. Add the following code to `index.ts`
272
- ```typescript
273
- import { FastifyPluginCallback, FastifyPluginAsync } from 'fastify'
274
- import fp from 'fastify-plugin'
275
-
276
- // using declaration merging, add your plugin props to the appropriate fastify interfaces
277
- declare module 'fastify' {
278
- interface FastifyRequest {
279
- myPluginProp: string
280
- }
281
- interface FastifyReply {
282
- myPluginProp: number
283
- }
284
- }
285
-
286
- // define options
287
- export interface MyPluginOptions {
288
- myPluginOption: string
289
- }
290
-
291
- // define plugin using callbacks
292
- const myPluginCallback: FastifyPluginCallback<MyPluginOptions> = (fastify, options, done) => {
293
- fastify.decorateRequest('myPluginProp', 'super_secret_value')
294
- fastify.decorateReply('myPluginProp', options.myPluginOption)
295
-
296
- done()
297
- }
298
-
299
- // define plugin using promises
300
- const myPluginAsync: FastifyPluginAsync<MyPluginOptions> = async (fastify, options) => {
301
- fastify.decorateRequest('myPluginProp', 'super_secret_value')
302
- fastify.decorateReply('myPluginProp', options.myPluginOption)
303
- }
304
-
305
- // export plugin using fastify-plugin
306
- export default fp(myPluginCallback, '3.x')
307
- // or
308
- // export default fp(myPluginAsync, '3.x')
309
- ```
272
+ ```typescript
273
+ import { FastifyPluginCallback, FastifyPluginAsync } from 'fastify'
274
+ import fp from 'fastify-plugin'
275
+
276
+ // using declaration merging, add your plugin props to the appropriate fastify interfaces
277
+ declare module 'fastify' {
278
+ interface FastifyRequest {
279
+ myPluginProp: string
280
+ }
281
+ interface FastifyReply {
282
+ myPluginProp: number
283
+ }
284
+ }
285
+
286
+ // define options
287
+ export interface MyPluginOptions {
288
+ myPluginOption: string
289
+ }
290
+
291
+ // define plugin using callbacks
292
+ const myPluginCallback: FastifyPluginCallback<MyPluginOptions> = (fastify, options, done) => {
293
+ fastify.decorateRequest('myPluginProp', 'super_secret_value')
294
+ fastify.decorateReply('myPluginProp', options.myPluginOption)
295
+
296
+ done()
297
+ }
298
+
299
+ // define plugin using promises
300
+ const myPluginAsync: FastifyPluginAsync<MyPluginOptions> = async (fastify, options) => {
301
+ fastify.decorateRequest('myPluginProp', 'super_secret_value')
302
+ fastify.decorateReply('myPluginProp', options.myPluginOption)
303
+ }
304
+
305
+ // export plugin using fastify-plugin
306
+ export default fp(myPluginCallback, '3.x')
307
+ // or
308
+ // export default fp(myPluginAsync, '3.x')
309
+ ```
310
310
  6. Run `npm run build` to compile the plugin code and produce both a JavaScript source file and a type definition file.
311
311
  7. With the plugin now complete you can [publish to npm] or use it locally.
312
- > You do not _need_ to publish your plugin to npm to use it. You can include it in a Fastify project and reference it as you would any piece of code! As a TypeScript user, make sure the declaration override exists somewhere that will be included in your project compilation so the TypeScript interpreter can process it.
312
+ > You do not _need_ to publish your plugin to npm to use it. You can include it in a Fastify project and reference it as you would any piece of code! As a TypeScript user, make sure the declaration override exists somewhere that will be included in your project compilation so the TypeScript interpreter can process it.
313
313
 
314
314
  #### Creating Type Definitions for a Fastify Plugin
315
315
 
316
316
  This plugin guide is for Fastify plugins written in JavaScript. The steps outlined in this example are for adding TypeScript support for users consuming your plugin.
317
317
 
318
318
  1. Initialize a new npm project and install required dependencies
319
- ```bash
320
- npm init -y
321
- npm i fastify-plugin
322
- ```
319
+ ```bash
320
+ npm init -y
321
+ npm i fastify-plugin
322
+ ```
323
323
  2. Create two files `index.js` and `index.d.ts`
324
324
  3. Modify the package json to include these files under the `main` and `types` properties (the name does not have to be `index` explicitly, but it is recommended the files have the same name):
325
- ```json
326
- {
327
- "main": "index.js",
328
- "types": "index.d.ts"
329
- }
330
- ```
325
+ ```json
326
+ {
327
+ "main": "index.js",
328
+ "types": "index.d.ts"
329
+ }
330
+ ```
331
331
  4. Open `index.js` and add the following code:
332
- ```javascript
333
- // fastify-plugin is highly recommended for any plugin you write
334
- const fp = require('fastify-plugin')
335
-
336
- function myPlugin (instance, options, next) {
337
-
338
- // decorate the fastify instance with a custom function called myPluginFunc
339
- instance.decorate('myPluginFunc', (input) => {
340
- return input.toUpperCase()
341
- })
342
-
343
- next()
344
- }
345
-
346
- module.exports = fp(myPlugin, {
347
- fastify: '3.x',
348
- name: 'my-plugin' // this is used by fastify-plugin to derive the property name
349
- })
350
- ```
351
- 5. Open `index.d.ts` and add the following code:
352
- ```typescript
353
- import { FastifyPlugin } from 'fastify'
332
+ ```javascript
333
+ // fastify-plugin is highly recommended for any plugin you write
334
+ const fp = require('fastify-plugin')
354
335
 
355
- interface PluginOptions {
356
- //...
357
- }
358
-
359
- // Optionally, you can add any additional exports.
360
- // Here we are exporting the decorator we added.
361
- export interface myPluginFunc {
362
- (input: string): string
363
- }
336
+ function myPlugin (instance, options, next) {
364
337
 
365
- // Most importantly, use declaration merging to add the custom property to the Fastify type system
366
- declare module 'fastify' {
367
- interface FastifyInstance {
368
- myPluginFunc: myPluginFunc
369
- }
370
- }
338
+ // decorate the fastify instance with a custom function called myPluginFunc
339
+ instance.decorate('myPluginFunc', (input) => {
340
+ return input.toUpperCase()
341
+ })
371
342
 
372
- // fastify-plugin automatically adds named export, so be sure to add also this type
373
- // the variable name is derived from `options.name` property if `module.exports.myPlugin` is missing
374
- export const myPlugin: FastifyPlugin<PluginOptions>
343
+ next()
344
+ }
375
345
 
376
- // fastify-plugin automatically adds `.default` property to the exported plugin. See the note below
377
- export default myPlugin
378
- ```
346
+ module.exports = fp(myPlugin, {
347
+ fastify: '3.x',
348
+ name: 'my-plugin' // this is used by fastify-plugin to derive the property name
349
+ })
350
+ ```
351
+ 5. Open `index.d.ts` and add the following code:
352
+ ```typescript
353
+ import { FastifyPlugin } from 'fastify'
354
+
355
+ interface PluginOptions {
356
+ //...
357
+ }
358
+
359
+ // Optionally, you can add any additional exports.
360
+ // Here we are exporting the decorator we added.
361
+ export interface myPluginFunc {
362
+ (input: string): string
363
+ }
364
+
365
+ // Most importantly, use declaration merging to add the custom property to the Fastify type system
366
+ declare module 'fastify' {
367
+ interface FastifyInstance {
368
+ myPluginFunc: myPluginFunc
369
+ }
370
+ }
371
+
372
+ // fastify-plugin automatically adds named export, so be sure to add also this type
373
+ // the variable name is derived from `options.name` property if `module.exports.myPlugin` is missing
374
+ export const myPlugin: FastifyPlugin<PluginOptions>
375
+
376
+ // fastify-plugin automatically adds `.default` property to the exported plugin. See the note below
377
+ export default myPlugin
378
+ ```
379
379
 
380
380
  __Note__: [fastify-plugin](https://github.com/fastify/fastify-plugin) v2.3.0 and newer, automatically adds `.default` property and a named export to the exported plugin. Be sure to `export default` and `export const myPlugin` in your typings to provide the best developer experience. For a complete example you can check out [fastify-swagger](https://github.com/fastify/fastify-swagger/blob/master/index.d.ts).
381
381
 
382
- With those files completed, the plugin is now ready to be consumed by any TypeScript project!
382
+ With those files completed, the plugin is now ready to be consumed by any TypeScript project!
383
383
 
384
384
  The Fastify plugin system enables developers to decorate the Fastify instance, and the request/reply instances. For more information check out this blog post on [Declaration Merging and Generic Inheritance](https://dev.to/ethanarrowood/is-declaration-merging-and-generic-inheritance-at-the-same-time-impossible-53cp).
385
385
 
386
386
  #### Using a Plugin
387
387
 
388
- Using a Fastify plugin in TypeScript is just as easy as using one in JavaScript. Import the plugin with `import/from` and you're all set -- except there is one exception users should be aware of.
388
+ Using a Fastify plugin in TypeScript is just as easy as using one in JavaScript. Import the plugin with `import/from` and you're all set -- except there is one exception users should be aware of.
389
389
 
390
390
  Fastify plugins use declaration merging to modify existing Fastify type interfaces (check out the previous two examples for more details). Declaration merging is not very _smart_, meaning if the plugin type definition for a plugin is within the scope of the TypeScript interpreter, then the plugin types will be included **regardless** of if the plugin is being used or not. This is an unfortunate limitation of using TypeScript and is unavoidable as of right now.
391
391
 
@@ -408,54 +408,54 @@ All `http`, `https`, and `http2` types are inferred from `@types/node`
408
408
  The Fastify API is powered by the `fastify()` method. In JavaScript you would import it using `const fastify = require('fastify')`. In TypeScript it is recommended to use the `import/from` syntax instead so types can be resolved. There are a couple supported import methods with the Fastify type system.
409
409
 
410
410
  1. `import fastify from 'fastify'`
411
- - Types are resolved but not accessible using dot notation
412
- - Example:
413
- ```typescript
414
- import fastify from 'fastify'
415
-
416
- const f = fastify()
417
- f.listen(8080, () => { console.log('running') })
418
- ```
419
- - Gain access to types with destructuring:
420
- ```typescript
421
- import fastify, { FastifyInstance } from 'fastify'
422
-
423
- const f: FastifyInstance = fastify()
424
- f.listen(8080, () => { console.log('running') })
425
- ```
426
- - Destructuring also works for the main API method:
427
- ```typescript
428
- import { fastify, FastifyInstance } from 'fastify'
429
-
430
- const f: FastifyInstance = fastify()
431
- f.listen(8080, () => { console.log('running') })
432
- ```
411
+ - Types are resolved but not accessible using dot notation
412
+ - Example:
413
+ ```typescript
414
+ import fastify from 'fastify'
415
+
416
+ const f = fastify()
417
+ f.listen(8080, () => { console.log('running') })
418
+ ```
419
+ - Gain access to types with destructuring:
420
+ ```typescript
421
+ import fastify, { FastifyInstance } from 'fastify'
422
+
423
+ const f: FastifyInstance = fastify()
424
+ f.listen(8080, () => { console.log('running') })
425
+ ```
426
+ - Destructuring also works for the main API method:
427
+ ```typescript
428
+ import { fastify, FastifyInstance } from 'fastify'
429
+
430
+ const f: FastifyInstance = fastify()
431
+ f.listen(8080, () => { console.log('running') })
432
+ ```
433
433
  2. `import * as Fastify from 'fastify'`
434
- - Types are resolved and accessible using dot notation
435
- - Calling the main Fastify API method requires a slightly different syntax (see example)
436
- - Example:
437
- ```typescript
438
- import * as Fastify from 'fastify'
439
-
440
- const f: Fastify.FastifyInstance = Fastify.fastify()
441
- f.listen(8080, () => { console.log('running') })
442
- ```
434
+ - Types are resolved and accessible using dot notation
435
+ - Calling the main Fastify API method requires a slightly different syntax (see example)
436
+ - Example:
437
+ ```typescript
438
+ import * as Fastify from 'fastify'
439
+
440
+ const f: Fastify.FastifyInstance = Fastify.fastify()
441
+ f.listen(8080, () => { console.log('running') })
442
+ ```
443
443
  3. `const fastify = require('fastify')`
444
- - This syntax is valid and will import fastify as expected; however, types will **not** be resolved
445
- - Example:
446
- ```typescript
447
- const fastify = require('fastify')
448
-
449
- const f = fastify()
450
- f.listen(8080, () => { console.log('running') })
451
- ```
452
- - Destructuring is still supported, but will also not resolve types
453
- ```typescript
454
- const { fastify } = require('fastify')
455
-
456
- const f = fastify()
457
- f.listen(8080, () => { console.log('running') })
458
- ```
444
+ - This syntax is valid and will import fastify as expected; however, types will **not** be resolved
445
+ - Example:
446
+ ```typescript
447
+ const fastify = require('fastify')
448
+
449
+ const f = fastify()
450
+ f.listen(8080, () => { console.log('running') })
451
+ ```
452
+ - Destructuring is still supported, but will also not resolve types
453
+ ```typescript
454
+ const { fastify } = require('fastify')
455
+
456
+ const f = fastify()
457
+ f.listen(8080, () => { console.log('running') })
458
+ ```
459
459
 
460
460
  #### Generics
461
461
 
@@ -463,7 +463,7 @@ Many type definitions share the same generic parameters; they are all documented
463
463
 
464
464
  Most definitions depend on `@node/types` modules `http`, `https`, and `http2`
465
465
 
466
- ##### RawServer
466
+ ##### RawServer
467
467
  Underlying Node.js server type
468
468
 
469
469
  Default: `http.Server`
@@ -482,7 +482,7 @@ Constraints: `http.IncomingMessage`, `http2.Http2ServerRequest`
482
482
  Enforced by: [`RawServer`][RawServerGeneric]
483
483
 
484
484
  ##### RawReply
485
- Underlying Node.js response type
485
+ Underlying Node.js response type
486
486
 
487
487
  Default: [`RawReplyDefaultExpression`][RawReplyDefaultExpression]
488
488
 
@@ -524,33 +524,33 @@ Check out the Learn By Example - [Getting Started](#getting-started) example for
524
524
  ###### Example 2: HTTPS sever
525
525
 
526
526
  1. Create the following imports from `@types/node` and `fastify`
527
- ```typescript
528
- import fs from 'fs'
529
- import path from 'path'
530
- import fastify from 'fastify'
531
- ```
527
+ ```typescript
528
+ import fs from 'fs'
529
+ import path from 'path'
530
+ import fastify from 'fastify'
531
+ ```
532
532
  2. Follow the steps in this official [Node.js https server guide](https://nodejs.org/en/knowledge/HTTP/servers/how-to-create-a-HTTPS-server/) to create the `key.pem` and `cert.pem` files
533
533
  3. Instantiate a Fastify https server and add a route:
534
- ```typescript
535
- const server = fastify({
536
- https: {
537
- key: fs.readFileSync(path.join(__dirname, 'key.pem')),
538
- cert: fs.readFileSync(path.join(__dirname, 'cert.pem'))
539
- }
540
- })
541
-
542
- server.get('/', async function (request, reply) {
543
- return { hello: 'world' }
544
- })
545
-
546
- server.listen(8080, (err, address) => {
547
- if(err) {
548
- console.error(err)
549
- process.exit(0)
550
- }
551
- console.log(`Server listening at ${address}`)
552
- })
553
- ```
534
+ ```typescript
535
+ const server = fastify({
536
+ https: {
537
+ key: fs.readFileSync(path.join(__dirname, 'key.pem')),
538
+ cert: fs.readFileSync(path.join(__dirname, 'cert.pem'))
539
+ }
540
+ })
541
+
542
+ server.get('/', async function (request, reply) {
543
+ return { hello: 'world' }
544
+ })
545
+
546
+ server.listen(8080, (err, address) => {
547
+ if (err) {
548
+ console.error(err)
549
+ process.exit(0)
550
+ }
551
+ console.log(`Server listening at ${address}`)
552
+ })
553
+ ```
554
554
  4. Build and run! Test your server out by querying with: `curl -k https://localhost:8080`
555
555
 
556
556
  ###### Example 3: HTTP2 server
@@ -612,19 +612,19 @@ server.get('/', async (request, reply) => {
612
612
 
613
613
  ---
614
614
 
615
- ##### fastify.HTTPMethods
615
+ ##### fastify.HTTPMethods
616
616
  [src](./../types/utils.d.ts#L8)
617
617
 
618
618
  Union type of: `'DELETE' | 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT' | 'OPTIONS'`
619
619
 
620
- ##### fastify.RawServerBase
620
+ ##### fastify.RawServerBase
621
621
  [src](./../types/utils.d.ts#L13)
622
622
 
623
623
  Dependant on `@types/node` modules `http`, `https`, `http2`
624
624
 
625
625
  Union type of: `http.Server | https.Server | http2.Http2Server | http2.Http2SecureServer`
626
626
 
627
- ##### fastify.RawServerDefault
627
+ ##### fastify.RawServerDefault
628
628
  [src](./../types/utils.d.ts#L18)
629
629
 
630
630
  Dependant on `@types/node` modules `http`
@@ -645,7 +645,7 @@ See the main [fastify][Fastify] method type definition section for examples on i
645
645
 
646
646
  [src](../types/instance.d.ts#L16)
647
647
 
648
- Interface that represents the Fastify server object. This is the returned server instance from the [`fastify()`][Fastify] method. This type is an interface so it can be extended via [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) if your code makes use of the `decorate` method.
648
+ Interface that represents the Fastify server object. This is the returned server instance from the [`fastify()`][Fastify] method. This type is an interface so it can be extended via [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) if your code makes use of the `decorate` method.
649
649
 
650
650
  Through the use of generic cascading, all methods attached to the instance inherit the generic properties from instantiation. This means that by specifying the server, request, or reply types, all methods will know how to type those objects.
651
651
 
@@ -655,7 +655,7 @@ Check out the main [Learn by Example](#learn-by-example) section for detailed gu
655
655
 
656
656
  #### Request
657
657
 
658
- ##### fastify.FastifyRequest<[RequestGeneric][FastifyRequestGenericInterface], [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric]>
658
+ ##### fastify.FastifyRequest<[RequestGeneric][FastifyRequestGenericInterface], [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric]>
659
659
  [src](./../types/request.d.ts#L15)
660
660
 
661
661
  This interface contains properties of Fastify request object. The properties added here disregard what kind of request object (http vs http2) and disregard what route level it is serving; thus calling `request.body` inside a GET request will not throw an error (but good luck sending a GET request with a body 😉).
@@ -770,7 +770,7 @@ declare module 'fastify' {
770
770
  }
771
771
  ```
772
772
 
773
- ##### fastify.RawReplyDefaultExpression<[RawServer][RawServerGeneric]>
773
+ ##### fastify.RawReplyDefaultExpression<[RawServer][RawServerGeneric]>
774
774
  [src](./../types/utils.d.ts#L27)
775
775
 
776
776
  Dependant on `@types/node` modules `http`, `https`, `http2`
@@ -971,7 +971,7 @@ A method for checking the existence of a type parser of a certain content type
971
971
 
972
972
  FastifyError is a custom error object that includes status code and validation results.
973
973
 
974
- It extends the Node.js `Error` type, and adds two additional, optional properties: `statusCode: number` and `validation: ValiationResult[]`.
974
+ It extends the Node.js `Error` type, and adds two additional, optional properties: `statusCode: number` and `validation: ValiationResult[]`.
975
975
 
976
976
  ##### fastify.ValidationResult
977
977
 
@@ -1000,8 +1000,8 @@ Notice: in the `onRequest` hook, request.body will always be null, because the b
1000
1000
  preParsing` is the second hook to be executed in the request lifecycle. The previous hook was `onRequest`, the next hook will be `preValidation`.
1001
1001
 
1002
1002
  Notice: in the `preParsing` hook, request.body will always be null, because the body parsing happens before the `preValidation` hook.
1003
-
1004
- Notice: you should also add `receivedEncodedLength` property to the returned stream. This property is used to correctly match the request payload with the `Content-Length` header value. Ideally, this property should be updated on each received chunk.
1003
+
1004
+ Notice: you should also add `receivedEncodedLength` property to the returned stream. This property is used to correctly match the request payload with the `Content-Length` header value. Ideally, this property should be updated on each received chunk.
1005
1005
 
1006
1006
  ##### fastify.preValidationHookHandler<[RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>(request: [FastifyRequest][FastifyRequest], reply: [FastifyReply][FastifyReply], done: (err?: [FastifyError][FastifyError]) => void): Promise\<unknown\> | void
1007
1007