node-fastify 5.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.borp.yaml +3 -0
- package/.markdownlint-cli2.yaml +22 -0
- package/.prettierignore +1 -0
- package/GOVERNANCE.md +4 -0
- package/LICENSE +21 -0
- package/PROJECT_CHARTER.md +126 -0
- package/README.md +423 -0
- package/SECURITY.md +220 -0
- package/SPONSORS.md +24 -0
- package/build/build-error-serializer.js +35 -0
- package/build/build-validation.js +169 -0
- package/build/sync-version.js +11 -0
- package/docs/Guides/Benchmarking.md +60 -0
- package/docs/Guides/Database.md +321 -0
- package/docs/Guides/Delay-Accepting-Requests.md +608 -0
- package/docs/Guides/Detecting-When-Clients-Abort.md +172 -0
- package/docs/Guides/Ecosystem.md +726 -0
- package/docs/Guides/Fluent-Schema.md +127 -0
- package/docs/Guides/Getting-Started.md +620 -0
- package/docs/Guides/Index.md +43 -0
- package/docs/Guides/Migration-Guide-V3.md +287 -0
- package/docs/Guides/Migration-Guide-V4.md +267 -0
- package/docs/Guides/Migration-Guide-V5.md +727 -0
- package/docs/Guides/Plugins-Guide.md +520 -0
- package/docs/Guides/Prototype-Poisoning.md +383 -0
- package/docs/Guides/Recommendations.md +378 -0
- package/docs/Guides/Serverless.md +604 -0
- package/docs/Guides/Style-Guide.md +246 -0
- package/docs/Guides/Testing.md +481 -0
- package/docs/Guides/Write-Plugin.md +103 -0
- package/docs/Guides/Write-Type-Provider.md +34 -0
- package/docs/Reference/ContentTypeParser.md +271 -0
- package/docs/Reference/Decorators.md +436 -0
- package/docs/Reference/Encapsulation.md +194 -0
- package/docs/Reference/Errors.md +377 -0
- package/docs/Reference/HTTP2.md +94 -0
- package/docs/Reference/Hooks.md +958 -0
- package/docs/Reference/Index.md +73 -0
- package/docs/Reference/LTS.md +86 -0
- package/docs/Reference/Lifecycle.md +99 -0
- package/docs/Reference/Logging.md +268 -0
- package/docs/Reference/Middleware.md +79 -0
- package/docs/Reference/Plugins.md +245 -0
- package/docs/Reference/Principles.md +73 -0
- package/docs/Reference/Reply.md +1001 -0
- package/docs/Reference/Request.md +295 -0
- package/docs/Reference/Routes.md +802 -0
- package/docs/Reference/Server.md +2389 -0
- package/docs/Reference/Type-Providers.md +256 -0
- package/docs/Reference/TypeScript.md +1729 -0
- package/docs/Reference/Validation-and-Serialization.md +1130 -0
- package/docs/Reference/Warnings.md +58 -0
- package/docs/index.md +24 -0
- package/docs/resources/encapsulation_context.drawio +1 -0
- package/docs/resources/encapsulation_context.svg +3 -0
- package/eslint.config.js +35 -0
- package/examples/asyncawait.js +38 -0
- package/examples/benchmark/body.json +3 -0
- package/examples/benchmark/hooks-benchmark-async-await.js +44 -0
- package/examples/benchmark/hooks-benchmark.js +52 -0
- package/examples/benchmark/parser.js +47 -0
- package/examples/benchmark/simple.js +30 -0
- package/examples/benchmark/webstream.js +27 -0
- package/examples/hooks.js +91 -0
- package/examples/http2.js +39 -0
- package/examples/https.js +38 -0
- package/examples/parser.js +53 -0
- package/examples/plugin.js +12 -0
- package/examples/route-prefix.js +38 -0
- package/examples/shared-schema.js +38 -0
- package/examples/simple-stream.js +20 -0
- package/examples/simple.js +32 -0
- package/examples/simple.mjs +27 -0
- package/examples/typescript-server.ts +79 -0
- package/examples/use-plugin.js +29 -0
- package/fastify.d.ts +253 -0
- package/fastify.js +985 -0
- package/integration/server.js +29 -0
- package/integration/test.sh +23 -0
- package/lib/config-validator.js +1266 -0
- package/lib/content-type-parser.js +413 -0
- package/lib/content-type.js +160 -0
- package/lib/context.js +98 -0
- package/lib/decorate.js +152 -0
- package/lib/error-handler.js +173 -0
- package/lib/error-serializer.js +134 -0
- package/lib/error-status.js +14 -0
- package/lib/errors.js +516 -0
- package/lib/four-oh-four.js +190 -0
- package/lib/handle-request.js +195 -0
- package/lib/head-route.js +45 -0
- package/lib/hooks.js +429 -0
- package/lib/initial-config-validation.js +37 -0
- package/lib/logger-factory.js +136 -0
- package/lib/logger-pino.js +68 -0
- package/lib/noop-set.js +10 -0
- package/lib/plugin-override.js +90 -0
- package/lib/plugin-utils.js +169 -0
- package/lib/promise.js +23 -0
- package/lib/reply.js +1030 -0
- package/lib/req-id-gen-factory.js +52 -0
- package/lib/request.js +391 -0
- package/lib/route.js +686 -0
- package/lib/schema-controller.js +164 -0
- package/lib/schemas.js +207 -0
- package/lib/server.js +441 -0
- package/lib/symbols.js +71 -0
- package/lib/validation.js +280 -0
- package/lib/warnings.js +57 -0
- package/lib/wrap-thenable.js +84 -0
- package/package.json +225 -0
- package/scripts/validate-ecosystem-links.js +179 -0
- package/test/404s.test.js +2035 -0
- package/test/500s.test.js +422 -0
- package/test/allow-unsafe-regex.test.js +92 -0
- package/test/als.test.js +65 -0
- package/test/async-await.test.js +705 -0
- package/test/async-dispose.test.js +20 -0
- package/test/async_hooks.test.js +52 -0
- package/test/body-limit.test.js +224 -0
- package/test/buffer.test.js +74 -0
- package/test/build/error-serializer.test.js +36 -0
- package/test/build/version.test.js +14 -0
- package/test/build-certificate.js +109 -0
- package/test/bundler/README.md +29 -0
- package/test/bundler/esbuild/bundler-test.js +32 -0
- package/test/bundler/esbuild/package.json +10 -0
- package/test/bundler/esbuild/src/fail-plugin-version.js +14 -0
- package/test/bundler/esbuild/src/index.js +9 -0
- package/test/bundler/webpack/bundler-test.js +32 -0
- package/test/bundler/webpack/package.json +11 -0
- package/test/bundler/webpack/src/fail-plugin-version.js +14 -0
- package/test/bundler/webpack/src/index.js +9 -0
- package/test/bundler/webpack/webpack.config.js +15 -0
- package/test/case-insensitive.test.js +102 -0
- package/test/chainable.test.js +40 -0
- package/test/child-logger-factory.test.js +128 -0
- package/test/client-timeout.test.js +38 -0
- package/test/close-pipelining.test.js +78 -0
- package/test/close.test.js +706 -0
- package/test/conditional-pino.test.js +47 -0
- package/test/connection-timeout.test.js +42 -0
- package/test/constrained-routes.test.js +1138 -0
- package/test/content-length.test.js +174 -0
- package/test/content-parser.test.js +739 -0
- package/test/content-type.test.js +181 -0
- package/test/context-config.test.js +164 -0
- package/test/custom-http-server.test.js +118 -0
- package/test/custom-parser-async.test.js +59 -0
- package/test/custom-parser.0.test.js +701 -0
- package/test/custom-parser.1.test.js +266 -0
- package/test/custom-parser.2.test.js +91 -0
- package/test/custom-parser.3.test.js +208 -0
- package/test/custom-parser.4.test.js +218 -0
- package/test/custom-parser.5.test.js +130 -0
- package/test/custom-querystring-parser.test.js +129 -0
- package/test/decorator.test.js +1330 -0
- package/test/delete.test.js +344 -0
- package/test/diagnostics-channel/404.test.js +49 -0
- package/test/diagnostics-channel/async-delay-request.test.js +65 -0
- package/test/diagnostics-channel/async-request.test.js +64 -0
- package/test/diagnostics-channel/error-before-handler.test.js +35 -0
- package/test/diagnostics-channel/error-request.test.js +53 -0
- package/test/diagnostics-channel/error-status.test.js +123 -0
- package/test/diagnostics-channel/init.test.js +50 -0
- package/test/diagnostics-channel/sync-delay-request.test.js +49 -0
- package/test/diagnostics-channel/sync-request-reply.test.js +51 -0
- package/test/diagnostics-channel/sync-request.test.js +54 -0
- package/test/encapsulated-child-logger-factory.test.js +69 -0
- package/test/encapsulated-error-handler.test.js +237 -0
- package/test/esm/errorCodes.test.mjs +10 -0
- package/test/esm/esm.test.mjs +13 -0
- package/test/esm/index.test.js +8 -0
- package/test/esm/named-exports.mjs +14 -0
- package/test/esm/other.mjs +8 -0
- package/test/esm/plugin.mjs +8 -0
- package/test/fastify-instance.test.js +300 -0
- package/test/find-route.test.js +152 -0
- package/test/fluent-schema.test.js +209 -0
- package/test/genReqId.test.js +426 -0
- package/test/handler-context.test.js +45 -0
- package/test/handler-timeout.test.js +367 -0
- package/test/has-route.test.js +88 -0
- package/test/header-overflow.test.js +55 -0
- package/test/helper.js +496 -0
- package/test/hooks-async.test.js +1099 -0
- package/test/hooks.on-listen.test.js +1162 -0
- package/test/hooks.on-ready.test.js +421 -0
- package/test/hooks.test.js +3578 -0
- package/test/http-methods/copy.test.js +35 -0
- package/test/http-methods/custom-http-methods.test.js +114 -0
- package/test/http-methods/get.test.js +412 -0
- package/test/http-methods/head.test.js +263 -0
- package/test/http-methods/lock.test.js +108 -0
- package/test/http-methods/mkcalendar.test.js +143 -0
- package/test/http-methods/mkcol.test.js +35 -0
- package/test/http-methods/move.test.js +42 -0
- package/test/http-methods/propfind.test.js +136 -0
- package/test/http-methods/proppatch.test.js +105 -0
- package/test/http-methods/report.test.js +142 -0
- package/test/http-methods/search.test.js +233 -0
- package/test/http-methods/trace.test.js +21 -0
- package/test/http-methods/unlock.test.js +38 -0
- package/test/http2/closing.test.js +270 -0
- package/test/http2/constraint.test.js +109 -0
- package/test/http2/head.test.js +34 -0
- package/test/http2/plain.test.js +68 -0
- package/test/http2/secure-with-fallback.test.js +113 -0
- package/test/http2/secure.test.js +67 -0
- package/test/http2/unknown-http-method.test.js +34 -0
- package/test/https/custom-https-server.test.js +58 -0
- package/test/https/https.test.js +136 -0
- package/test/imports.test.js +17 -0
- package/test/inject.test.js +502 -0
- package/test/input-validation.js +335 -0
- package/test/internals/all.test.js +38 -0
- package/test/internals/content-type-parser.test.js +111 -0
- package/test/internals/context.test.js +31 -0
- package/test/internals/decorator.test.js +156 -0
- package/test/internals/errors.test.js +982 -0
- package/test/internals/handle-request.test.js +270 -0
- package/test/internals/hook-runner.test.js +449 -0
- package/test/internals/hooks.test.js +96 -0
- package/test/internals/initial-config.test.js +383 -0
- package/test/internals/logger.test.js +163 -0
- package/test/internals/plugin.test.js +170 -0
- package/test/internals/promise.test.js +63 -0
- package/test/internals/reply-serialize.test.js +714 -0
- package/test/internals/reply.test.js +1920 -0
- package/test/internals/req-id-gen-factory.test.js +133 -0
- package/test/internals/request-validate.test.js +1402 -0
- package/test/internals/request.test.js +506 -0
- package/test/internals/schema-controller-perf.test.js +40 -0
- package/test/internals/server.test.js +91 -0
- package/test/internals/validation.test.js +352 -0
- package/test/issue-4959.test.js +118 -0
- package/test/keep-alive-timeout.test.js +42 -0
- package/test/listen.1.test.js +154 -0
- package/test/listen.2.test.js +113 -0
- package/test/listen.3.test.js +83 -0
- package/test/listen.4.test.js +168 -0
- package/test/listen.5.test.js +122 -0
- package/test/logger/instantiation.test.js +341 -0
- package/test/logger/logger-test-utils.js +47 -0
- package/test/logger/logging.test.js +460 -0
- package/test/logger/options.test.js +579 -0
- package/test/logger/request.test.js +292 -0
- package/test/logger/response.test.js +183 -0
- package/test/logger/tap-parallel-not-ok +0 -0
- package/test/max-requests-per-socket.test.js +113 -0
- package/test/middleware.test.js +37 -0
- package/test/noop-set.test.js +19 -0
- package/test/nullable-validation.test.js +187 -0
- package/test/options.error-handler.test.js +5 -0
- package/test/options.test.js +5 -0
- package/test/output-validation.test.js +140 -0
- package/test/patch.error-handler.test.js +5 -0
- package/test/patch.test.js +5 -0
- package/test/plugin.1.test.js +230 -0
- package/test/plugin.2.test.js +314 -0
- package/test/plugin.3.test.js +287 -0
- package/test/plugin.4.test.js +504 -0
- package/test/plugin.helper.js +8 -0
- package/test/plugin.name.display.js +10 -0
- package/test/post-empty-body.test.js +38 -0
- package/test/pretty-print.test.js +366 -0
- package/test/promises.test.js +125 -0
- package/test/proto-poisoning.test.js +145 -0
- package/test/put.error-handler.test.js +5 -0
- package/test/put.test.js +5 -0
- package/test/register.test.js +184 -0
- package/test/reply-code.test.js +148 -0
- package/test/reply-early-hints.test.js +100 -0
- package/test/reply-error.test.js +815 -0
- package/test/reply-trailers.test.js +445 -0
- package/test/reply-web-stream-locked.test.js +37 -0
- package/test/request-error.test.js +624 -0
- package/test/request-header-host.test.js +339 -0
- package/test/request-id.test.js +118 -0
- package/test/request-timeout.test.js +53 -0
- package/test/route-hooks.test.js +635 -0
- package/test/route-prefix.test.js +904 -0
- package/test/route-shorthand.test.js +48 -0
- package/test/route.1.test.js +259 -0
- package/test/route.2.test.js +100 -0
- package/test/route.3.test.js +213 -0
- package/test/route.4.test.js +127 -0
- package/test/route.5.test.js +211 -0
- package/test/route.6.test.js +306 -0
- package/test/route.7.test.js +406 -0
- package/test/route.8.test.js +225 -0
- package/test/router-options.test.js +1108 -0
- package/test/same-shape.test.js +124 -0
- package/test/schema-examples.test.js +661 -0
- package/test/schema-feature.test.js +2198 -0
- package/test/schema-serialization.test.js +1171 -0
- package/test/schema-special-usage.test.js +1348 -0
- package/test/schema-validation.test.js +1572 -0
- package/test/scripts/validate-ecosystem-links.test.js +339 -0
- package/test/serialize-response.test.js +186 -0
- package/test/server.test.js +347 -0
- package/test/set-error-handler.test.js +69 -0
- package/test/skip-reply-send.test.js +317 -0
- package/test/stream-serializers.test.js +40 -0
- package/test/stream.1.test.js +94 -0
- package/test/stream.2.test.js +129 -0
- package/test/stream.3.test.js +198 -0
- package/test/stream.4.test.js +176 -0
- package/test/stream.5.test.js +188 -0
- package/test/sync-routes.test.js +32 -0
- package/test/throw.test.js +359 -0
- package/test/toolkit.js +63 -0
- package/test/trust-proxy.test.js +162 -0
- package/test/type-provider.test.js +22 -0
- package/test/types/content-type-parser.test-d.ts +72 -0
- package/test/types/decorate-request-reply.test-d.ts +18 -0
- package/test/types/dummy-plugin.ts +9 -0
- package/test/types/errors.test-d.ts +90 -0
- package/test/types/fastify.test-d.ts +352 -0
- package/test/types/hooks.test-d.ts +550 -0
- package/test/types/import.ts +2 -0
- package/test/types/instance.test-d.ts +588 -0
- package/test/types/logger.test-d.ts +277 -0
- package/test/types/plugin.test-d.ts +97 -0
- package/test/types/register.test-d.ts +237 -0
- package/test/types/reply.test-d.ts +254 -0
- package/test/types/request.test-d.ts +188 -0
- package/test/types/route.test-d.ts +553 -0
- package/test/types/schema.test-d.ts +135 -0
- package/test/types/serverFactory.test-d.ts +37 -0
- package/test/types/type-provider.test-d.ts +1213 -0
- package/test/types/using.test-d.ts +17 -0
- package/test/upgrade.test.js +52 -0
- package/test/url-rewriting.test.js +122 -0
- package/test/use-semicolon-delimiter.test.js +168 -0
- package/test/validation-error-handling.test.js +900 -0
- package/test/versioned-routes.test.js +603 -0
- package/test/web-api.test.js +616 -0
- package/test/wrap-thenable.test.js +30 -0
- package/types/content-type-parser.d.ts +75 -0
- package/types/context.d.ts +22 -0
- package/types/errors.d.ts +92 -0
- package/types/hooks.d.ts +875 -0
- package/types/instance.d.ts +609 -0
- package/types/logger.d.ts +107 -0
- package/types/plugin.d.ts +44 -0
- package/types/register.d.ts +42 -0
- package/types/reply.d.ts +81 -0
- package/types/request.d.ts +95 -0
- package/types/route.d.ts +199 -0
- package/types/schema.d.ts +61 -0
- package/types/server-factory.d.ts +19 -0
- package/types/type-provider.d.ts +130 -0
- package/types/utils.d.ts +98 -0
|
@@ -0,0 +1,1729 @@
|
|
|
1
|
+
<h1 align="center">Fastify</h1>
|
|
2
|
+
|
|
3
|
+
## TypeScript
|
|
4
|
+
|
|
5
|
+
The Fastify framework is written in vanilla JavaScript, and as such type
|
|
6
|
+
definitions are not as easy to maintain; however, since version 2 and beyond,
|
|
7
|
+
maintainers and contributors have put in a great effort to improve the types.
|
|
8
|
+
|
|
9
|
+
The type system was changed in Fastify version 3. The new type system introduces
|
|
10
|
+
generic constraining and defaulting, plus a new way to define schema types such
|
|
11
|
+
as a request body, querystring, and more! As the team works on improving
|
|
12
|
+
framework and type definition synergy, sometimes parts of the API will not be
|
|
13
|
+
typed or may be typed incorrectly. We encourage you to **contribute** to help us
|
|
14
|
+
fill in the gaps. Just make sure to read our
|
|
15
|
+
[`CONTRIBUTING.md`](https://github.com/fastify/fastify/blob/main/CONTRIBUTING.md)
|
|
16
|
+
file before getting started to make sure things go smoothly!
|
|
17
|
+
|
|
18
|
+
> The documentation in this section covers Fastify version 3.x typings
|
|
19
|
+
|
|
20
|
+
> Plugins may or may not include typings. See [Plugins](#plugins) for more
|
|
21
|
+
> information. We encourage users to send pull requests to improve typings
|
|
22
|
+
> support.
|
|
23
|
+
|
|
24
|
+
🚨 Don't forget to install `@types/node`
|
|
25
|
+
|
|
26
|
+
## Learn By Example
|
|
27
|
+
|
|
28
|
+
The best way to learn the Fastify type system is by example! The following four
|
|
29
|
+
examples should cover the most common Fastify development cases. After the
|
|
30
|
+
examples there is further, more detailed documentation for the type system.
|
|
31
|
+
|
|
32
|
+
### Getting Started
|
|
33
|
+
|
|
34
|
+
This example will get you up and running with Fastify and TypeScript. It results
|
|
35
|
+
in a blank http Fastify server.
|
|
36
|
+
|
|
37
|
+
1. Create a new npm project, install Fastify, and install typescript & Node.js
|
|
38
|
+
types as peer dependencies:
|
|
39
|
+
```bash
|
|
40
|
+
npm init -y
|
|
41
|
+
npm i fastify
|
|
42
|
+
npm i -D typescript @types/node
|
|
43
|
+
```
|
|
44
|
+
2. Add the following lines to the `"scripts"` section of the `package.json`:
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsc -p tsconfig.json",
|
|
49
|
+
"start": "node index.js"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
3. Initialize a TypeScript configuration file:
|
|
55
|
+
```bash
|
|
56
|
+
npx tsc --init
|
|
57
|
+
```
|
|
58
|
+
or use one of the [recommended
|
|
59
|
+
ones](https://github.com/tsconfig/bases#node-14-tsconfigjson).
|
|
60
|
+
|
|
61
|
+
> ℹ️ Note:
|
|
62
|
+
> Set `target` property in `tsconfig.json` to `es2017` or greater to avoid
|
|
63
|
+
> [FastifyDeprecation](https://github.com/fastify/fastify/issues/3284) warning.
|
|
64
|
+
|
|
65
|
+
4. Create an `index.ts` file - this will contain the server code
|
|
66
|
+
5. Add the following code block to your file:
|
|
67
|
+
```typescript
|
|
68
|
+
import fastify from 'fastify'
|
|
69
|
+
|
|
70
|
+
const server = fastify()
|
|
71
|
+
|
|
72
|
+
server.get('/ping', async (request, reply) => {
|
|
73
|
+
return 'pong\n'
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
server.listen({ port: 8080 }, (err, address) => {
|
|
77
|
+
if (err) {
|
|
78
|
+
console.error(err)
|
|
79
|
+
process.exit(1)
|
|
80
|
+
}
|
|
81
|
+
console.log(`Server listening at ${address}`)
|
|
82
|
+
})
|
|
83
|
+
```
|
|
84
|
+
6. Run `npm run build` - this will compile `index.ts` into `index.js` which can
|
|
85
|
+
be executed using Node.js. If you run into any errors please open an issue in
|
|
86
|
+
[fastify/help](https://github.com/fastify/help/)
|
|
87
|
+
7. Run `npm run start` to run the Fastify server
|
|
88
|
+
8. You should see `Server listening at http://127.0.0.1:8080` in your console
|
|
89
|
+
9. Try out your server using `curl localhost:8080/ping`, it should return `pong`
|
|
90
|
+
🏓
|
|
91
|
+
|
|
92
|
+
🎉 You now have a working Typescript Fastify server! This example demonstrates
|
|
93
|
+
the simplicity of the version 3.x type system. By default, the type system
|
|
94
|
+
assumes you are using an `http` server. The later examples will demonstrate how
|
|
95
|
+
to create more complex servers such as `https` and `http2`, how to specify route
|
|
96
|
+
schemas, and more!
|
|
97
|
+
|
|
98
|
+
> For more examples on initializing Fastify with TypeScript (such as enabling
|
|
99
|
+
> HTTP2) check out the detailed API section [here][Fastify]
|
|
100
|
+
|
|
101
|
+
### Using Generics
|
|
102
|
+
|
|
103
|
+
The type system heavily relies on generic properties to provide the most
|
|
104
|
+
accurate development experience. While some may find the overhead a bit
|
|
105
|
+
cumbersome, the tradeoff is worth it! This example will dive into implementing
|
|
106
|
+
generic types for route schemas and the dynamic properties located on the
|
|
107
|
+
route-level `request` object.
|
|
108
|
+
|
|
109
|
+
1. If you did not complete the previous example, follow steps 1-4 to get set up.
|
|
110
|
+
2. Inside `index.ts`, define three interfaces `IQuerystring`,`IHeaders` and `IReply`:
|
|
111
|
+
```typescript
|
|
112
|
+
interface IQuerystring {
|
|
113
|
+
username: string;
|
|
114
|
+
password: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface IHeaders {
|
|
118
|
+
'h-Custom': string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
interface IReply {
|
|
122
|
+
200: { success: boolean };
|
|
123
|
+
302: { url: string };
|
|
124
|
+
'4xx': { error: string };
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
3. Using the three interfaces, define a new API route and pass them as generics.
|
|
128
|
+
The shorthand route methods (i.e. `.get`) accept a generic object
|
|
129
|
+
`RouteGenericInterface` containing five named properties: `Body`,
|
|
130
|
+
`Querystring`, `Params`, `Headers` and `Reply`. The interfaces `Body`,
|
|
131
|
+
`Querystring`, `Params` and `Headers` will be passed down through the route
|
|
132
|
+
method into the route method handler `request` instance and the `Reply`
|
|
133
|
+
interface to the `reply` instance.
|
|
134
|
+
```typescript
|
|
135
|
+
server.get<{
|
|
136
|
+
Querystring: IQuerystring,
|
|
137
|
+
Headers: IHeaders,
|
|
138
|
+
Reply: IReply
|
|
139
|
+
}>('/auth', async (request, reply) => {
|
|
140
|
+
const { username, password } = request.query
|
|
141
|
+
const customerHeader = request.headers['h-Custom']
|
|
142
|
+
// do something with request data
|
|
143
|
+
|
|
144
|
+
// chaining .statusCode/.code calls with .send allows type narrowing. For example:
|
|
145
|
+
// this works
|
|
146
|
+
reply.code(200).send({ success: true });
|
|
147
|
+
// but this gives a type error
|
|
148
|
+
reply.code(200).send('uh-oh');
|
|
149
|
+
// it even works for wildcards
|
|
150
|
+
reply.code(404).send({ error: 'Not found' });
|
|
151
|
+
return { success: true }
|
|
152
|
+
})
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
4. Build and run the server code with `npm run build` and `npm run start`
|
|
156
|
+
5. Query the API
|
|
157
|
+
```bash
|
|
158
|
+
curl localhost:8080/auth?username=admin&password=Password123!
|
|
159
|
+
```
|
|
160
|
+
And it should return back `logged in!`
|
|
161
|
+
6. But wait there's more! The generic interfaces are also available inside route
|
|
162
|
+
level hook methods. Modify the previous route by adding a `preValidation`
|
|
163
|
+
hook:
|
|
164
|
+
```typescript
|
|
165
|
+
server.get<{
|
|
166
|
+
Querystring: IQuerystring,
|
|
167
|
+
Headers: IHeaders,
|
|
168
|
+
Reply: IReply
|
|
169
|
+
}>('/auth', {
|
|
170
|
+
preValidation: (request, reply, done) => {
|
|
171
|
+
const { username, password } = request.query
|
|
172
|
+
done(username !== 'admin' ? new Error('Must be admin') : undefined) // only validate `admin` account
|
|
173
|
+
}
|
|
174
|
+
}, async (request, reply) => {
|
|
175
|
+
const customerHeader = request.headers['h-Custom']
|
|
176
|
+
// do something with request data
|
|
177
|
+
return { success: true }
|
|
178
|
+
})
|
|
179
|
+
```
|
|
180
|
+
7. Build and run and query with the `username` query string option set to
|
|
181
|
+
anything other than `admin`. The API should now return a HTTP 500 error
|
|
182
|
+
`{"statusCode":500,"error":"Internal Server Error","message":"Must be
|
|
183
|
+
admin"}`
|
|
184
|
+
|
|
185
|
+
🎉 Good work, now you can define interfaces for each route and have strictly
|
|
186
|
+
typed request and reply instances. Other parts of the Fastify type system rely
|
|
187
|
+
on generic properties. Make sure to reference the detailed type system
|
|
188
|
+
documentation below to learn more about what is available.
|
|
189
|
+
|
|
190
|
+
### JSON Schema
|
|
191
|
+
|
|
192
|
+
To validate your requests and responses you can use JSON Schema files. If you
|
|
193
|
+
didn't know already, defining schemas for your Fastify routes can increase their
|
|
194
|
+
throughput! Check out the [Validation and
|
|
195
|
+
Serialization](./Validation-and-Serialization.md) documentation for more info.
|
|
196
|
+
|
|
197
|
+
Also it has the advantage to use the defined type within your handlers
|
|
198
|
+
(including pre-validation, etc.).
|
|
199
|
+
|
|
200
|
+
Here are some options on how to achieve this.
|
|
201
|
+
|
|
202
|
+
#### Fastify Type Providers
|
|
203
|
+
|
|
204
|
+
Fastify offers two packages wrapping `json-schema-to-ts` and `typebox`:
|
|
205
|
+
|
|
206
|
+
- [`@fastify/type-provider-json-schema-to-ts`](https://github.com/fastify/fastify-type-provider-json-schema-to-ts)
|
|
207
|
+
- [`@fastify/type-provider-typebox`](https://github.com/fastify/fastify-type-provider-typebox)
|
|
208
|
+
|
|
209
|
+
And a `zod` wrapper by a third party called [`fastify-type-provider-zod`](https://github.com/turkerdev/fastify-type-provider-zod)
|
|
210
|
+
|
|
211
|
+
They simplify schema validation setup and you can read more about them in [Type
|
|
212
|
+
Providers](./Type-Providers.md) page.
|
|
213
|
+
|
|
214
|
+
Below is how to setup schema validation using the `typebox`,
|
|
215
|
+
`json-schema-to-typescript`, and `json-schema-to-ts` packages without type
|
|
216
|
+
providers.
|
|
217
|
+
|
|
218
|
+
#### TypeBox
|
|
219
|
+
|
|
220
|
+
A useful library for building types and a schema at once is [TypeBox](https://www.npmjs.com/package/typebox).
|
|
221
|
+
With TypeBox you define your schema within your code and use them directly as
|
|
222
|
+
types or schemas as you need them.
|
|
223
|
+
|
|
224
|
+
When you want to use it for validation of some payload in a fastify route you
|
|
225
|
+
can do it as follows:
|
|
226
|
+
|
|
227
|
+
1. Install `typebox` in your project.
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
npm i typebox
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
2. Define the schema you need with `Type` and create the respective type with
|
|
234
|
+
`Static`.
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import { Static, Type } from 'typebox'
|
|
238
|
+
|
|
239
|
+
export const User = Type.Object({
|
|
240
|
+
name: Type.String(),
|
|
241
|
+
mail: Type.Optional(Type.String({ format: 'email' })),
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
export type UserType = Static<typeof User>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
3. Use the defined type and schema during the definition of your route
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import Fastify from 'fastify'
|
|
251
|
+
// ...
|
|
252
|
+
|
|
253
|
+
const fastify = Fastify()
|
|
254
|
+
|
|
255
|
+
fastify.post<{ Body: UserType, Reply: UserType }>(
|
|
256
|
+
'/',
|
|
257
|
+
{
|
|
258
|
+
schema: {
|
|
259
|
+
body: User,
|
|
260
|
+
response: {
|
|
261
|
+
200: User
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
(request, reply) => {
|
|
266
|
+
// The `name` and `mail` types are automatically inferred
|
|
267
|
+
const { name, mail } = request.body;
|
|
268
|
+
reply.status(200).send({ name, mail });
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
#### json-schema-to-typescript
|
|
274
|
+
|
|
275
|
+
In the last example we used Typebox to define the types and schemas for our
|
|
276
|
+
route. Many users will already be using JSON Schemas to define these properties,
|
|
277
|
+
and luckily there is a way to transform existing JSON Schemas into TypeScript
|
|
278
|
+
interfaces!
|
|
279
|
+
|
|
280
|
+
1. If you did not complete the 'Getting Started' example, go back and follow
|
|
281
|
+
steps 1-4 first.
|
|
282
|
+
2. Install the `json-schema-to-typescript` module:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
npm i -D json-schema-to-typescript
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
3. Create a new folder called `schemas` and add two files `headers.json` and
|
|
289
|
+
`querystring.json`. Copy and paste the following schema definitions into the
|
|
290
|
+
respective files:
|
|
291
|
+
|
|
292
|
+
```json
|
|
293
|
+
{
|
|
294
|
+
"title": "Headers Schema",
|
|
295
|
+
"type": "object",
|
|
296
|
+
"properties": {
|
|
297
|
+
"h-Custom": { "type": "string" }
|
|
298
|
+
},
|
|
299
|
+
"additionalProperties": false,
|
|
300
|
+
"required": ["h-Custom"]
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
```json
|
|
305
|
+
{
|
|
306
|
+
"title": "Querystring Schema",
|
|
307
|
+
"type": "object",
|
|
308
|
+
"properties": {
|
|
309
|
+
"username": { "type": "string" },
|
|
310
|
+
"password": { "type": "string" }
|
|
311
|
+
},
|
|
312
|
+
"additionalProperties": false,
|
|
313
|
+
"required": ["username", "password"]
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
4. Add a `compile-schemas` script to the package.json:
|
|
318
|
+
|
|
319
|
+
```json
|
|
320
|
+
{
|
|
321
|
+
"scripts": {
|
|
322
|
+
"compile-schemas": "json2ts -i schemas -o types"
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
`json2ts` is a CLI utility included in `json-schema-to-typescript`. `schemas`
|
|
328
|
+
is the input path, and `types` is the output path.
|
|
329
|
+
5. Run `npm run compile-schemas`. Two new files should have been created in the
|
|
330
|
+
`types` directory.
|
|
331
|
+
6. Update `index.ts` to have the following code:
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
import fastify from 'fastify'
|
|
335
|
+
|
|
336
|
+
// import json schemas as normal
|
|
337
|
+
import QuerystringSchema from './schemas/querystring.json'
|
|
338
|
+
import HeadersSchema from './schemas/headers.json'
|
|
339
|
+
|
|
340
|
+
// import the generated interfaces
|
|
341
|
+
import { QuerystringSchema as QuerystringSchemaInterface } from './types/querystring'
|
|
342
|
+
import { HeadersSchema as HeadersSchemaInterface } from './types/headers'
|
|
343
|
+
|
|
344
|
+
const server = fastify()
|
|
345
|
+
|
|
346
|
+
server.get<{
|
|
347
|
+
Querystring: QuerystringSchemaInterface,
|
|
348
|
+
Headers: HeadersSchemaInterface
|
|
349
|
+
}>('/auth', {
|
|
350
|
+
schema: {
|
|
351
|
+
querystring: QuerystringSchema,
|
|
352
|
+
headers: HeadersSchema
|
|
353
|
+
},
|
|
354
|
+
preValidation: (request, reply, done) => {
|
|
355
|
+
const { username, password } = request.query
|
|
356
|
+
done(username !== 'admin' ? new Error('Must be admin') : undefined)
|
|
357
|
+
}
|
|
358
|
+
// or if using async
|
|
359
|
+
// preValidation: async (request, reply) => {
|
|
360
|
+
// const { username, password } = request.query
|
|
361
|
+
// if (username !== "admin") throw new Error("Must be admin");
|
|
362
|
+
// }
|
|
363
|
+
}, async (request, reply) => {
|
|
364
|
+
const customerHeader = request.headers['h-Custom']
|
|
365
|
+
// do something with request data
|
|
366
|
+
return `logged in!`
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
server.route<{
|
|
370
|
+
Querystring: QuerystringSchemaInterface,
|
|
371
|
+
Headers: HeadersSchemaInterface
|
|
372
|
+
}>({
|
|
373
|
+
method: 'GET',
|
|
374
|
+
url: '/auth2',
|
|
375
|
+
schema: {
|
|
376
|
+
querystring: QuerystringSchema,
|
|
377
|
+
headers: HeadersSchema
|
|
378
|
+
},
|
|
379
|
+
preHandler: (request, reply, done) => {
|
|
380
|
+
const { username, password } = request.query
|
|
381
|
+
const customerHeader = request.headers['h-Custom']
|
|
382
|
+
done()
|
|
383
|
+
},
|
|
384
|
+
handler: (request, reply) => {
|
|
385
|
+
const { username, password } = request.query
|
|
386
|
+
const customerHeader = request.headers['h-Custom']
|
|
387
|
+
reply.status(200).send({username});
|
|
388
|
+
}
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
server.listen({ port: 8080 }, (err, address) => {
|
|
392
|
+
if (err) {
|
|
393
|
+
console.error(err)
|
|
394
|
+
process.exit(0)
|
|
395
|
+
}
|
|
396
|
+
console.log(`Server listening at ${address}`)
|
|
397
|
+
})
|
|
398
|
+
```
|
|
399
|
+
Pay special attention to the imports at the top of this file. It might seem
|
|
400
|
+
redundant, but you need to import both the schema files and the generated
|
|
401
|
+
interfaces.
|
|
402
|
+
|
|
403
|
+
Great work! Now you can make use of both JSON Schemas and TypeScript
|
|
404
|
+
definitions.
|
|
405
|
+
|
|
406
|
+
#### json-schema-to-ts
|
|
407
|
+
|
|
408
|
+
If you do not want to generate types from your schemas, but want to use them
|
|
409
|
+
directly from your code, you can use the package
|
|
410
|
+
[json-schema-to-ts](https://www.npmjs.com/package/json-schema-to-ts).
|
|
411
|
+
|
|
412
|
+
You can install it as dev-dependency.
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
npm i -D json-schema-to-ts
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
In your code you can define your schema like a normal object. But be aware of
|
|
419
|
+
making it *const* like explained in the docs of the module.
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
const todo = {
|
|
423
|
+
type: 'object',
|
|
424
|
+
properties: {
|
|
425
|
+
name: { type: 'string' },
|
|
426
|
+
description: { type: 'string' },
|
|
427
|
+
done: { type: 'boolean' },
|
|
428
|
+
},
|
|
429
|
+
required: ['name'],
|
|
430
|
+
} as const; // don't forget to use const !
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
With the provided type `FromSchema` you can build a type from your schema and
|
|
434
|
+
use it in your handler.
|
|
435
|
+
|
|
436
|
+
```typescript
|
|
437
|
+
import { FromSchema } from "json-schema-to-ts";
|
|
438
|
+
fastify.post<{ Body: FromSchema<typeof todo> }>(
|
|
439
|
+
'/todo',
|
|
440
|
+
{
|
|
441
|
+
schema: {
|
|
442
|
+
body: todo,
|
|
443
|
+
response: {
|
|
444
|
+
201: {
|
|
445
|
+
type: 'string',
|
|
446
|
+
},
|
|
447
|
+
},
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
async (request, reply): Promise<void> => {
|
|
451
|
+
|
|
452
|
+
/*
|
|
453
|
+
request.body has type
|
|
454
|
+
{
|
|
455
|
+
[x: string]: unknown;
|
|
456
|
+
description?: string;
|
|
457
|
+
done?: boolean;
|
|
458
|
+
name: string;
|
|
459
|
+
}
|
|
460
|
+
*/
|
|
461
|
+
|
|
462
|
+
request.body.name // will not throw type error
|
|
463
|
+
request.body.notthere // will throw type error
|
|
464
|
+
|
|
465
|
+
reply.status(201).send();
|
|
466
|
+
},
|
|
467
|
+
);
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### Plugins
|
|
471
|
+
|
|
472
|
+
One of Fastify's most distinguishable features is its extensive plugin
|
|
473
|
+
ecosystem. Plugin types are fully supported, and take advantage of the
|
|
474
|
+
[declaration
|
|
475
|
+
merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html)
|
|
476
|
+
pattern. This example is broken up into three parts: Creating a TypeScript
|
|
477
|
+
Fastify Plugin, Creating Type Definitions for a Fastify Plugin, and Using a
|
|
478
|
+
Fastify Plugin in a TypeScript Project.
|
|
479
|
+
|
|
480
|
+
#### Creating a TypeScript Fastify Plugin
|
|
481
|
+
|
|
482
|
+
1. Initialize a new npm project and install required dependencies
|
|
483
|
+
```bash
|
|
484
|
+
npm init -y
|
|
485
|
+
npm i fastify fastify-plugin
|
|
486
|
+
npm i -D typescript @types/node
|
|
487
|
+
```
|
|
488
|
+
2. Add a `build` script to the `"scripts"` section and `'index.d.ts'` to the
|
|
489
|
+
`"types"` section of the `package.json` file:
|
|
490
|
+
```json
|
|
491
|
+
{
|
|
492
|
+
"types": "index.d.ts",
|
|
493
|
+
"scripts": {
|
|
494
|
+
"build": "tsc -p tsconfig.json"
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
3. Initialize a TypeScript configuration file:
|
|
499
|
+
```bash
|
|
500
|
+
npx typescript --init
|
|
501
|
+
```
|
|
502
|
+
Once the file is generated, enable the `"declaration"` option in the
|
|
503
|
+
`"compilerOptions"` object.
|
|
504
|
+
```json
|
|
505
|
+
{
|
|
506
|
+
"compilerOptions": {
|
|
507
|
+
"declaration": true
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
```
|
|
511
|
+
4. Create an `index.ts` file - this will contain the plugin code
|
|
512
|
+
5. Add the following code to `index.ts`
|
|
513
|
+
```typescript
|
|
514
|
+
import { FastifyPluginCallback, FastifyPluginAsync } from 'fastify'
|
|
515
|
+
import fp from 'fastify-plugin'
|
|
516
|
+
|
|
517
|
+
// using declaration merging, add your plugin props to the appropriate fastify interfaces
|
|
518
|
+
// if prop type is defined here, the value will be typechecked when you call decorate{,Request,Reply}
|
|
519
|
+
declare module 'fastify' {
|
|
520
|
+
interface FastifyRequest {
|
|
521
|
+
myPluginProp: string
|
|
522
|
+
}
|
|
523
|
+
interface FastifyReply {
|
|
524
|
+
myPluginProp: number
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// define options
|
|
529
|
+
export interface MyPluginOptions {
|
|
530
|
+
myPluginOption: string
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// define plugin using callbacks
|
|
534
|
+
const myPluginCallback: FastifyPluginCallback<MyPluginOptions> = (fastify, options, done) => {
|
|
535
|
+
fastify.decorateRequest('myPluginProp', 'super_secret_value')
|
|
536
|
+
fastify.decorateReply('myPluginProp', options.myPluginOption)
|
|
537
|
+
|
|
538
|
+
done()
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// define plugin using promises
|
|
542
|
+
const myPluginAsync: FastifyPluginAsync<MyPluginOptions> = async (fastify, options) => {
|
|
543
|
+
fastify.decorateRequest('myPluginProp', 'super_secret_value')
|
|
544
|
+
fastify.decorateReply('myPluginProp', options.myPluginOption)
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// export plugin using fastify-plugin
|
|
548
|
+
export default fp(myPluginCallback, '3.x')
|
|
549
|
+
// or
|
|
550
|
+
// export default fp(myPluginAsync, '3.x')
|
|
551
|
+
```
|
|
552
|
+
6. Run `npm run build` to compile the plugin code and produce both a JavaScript
|
|
553
|
+
source file and a type definition file.
|
|
554
|
+
7. With the plugin now complete you can [publish to npm] or use it locally.
|
|
555
|
+
> You do not _need_ to publish your plugin to npm to use it. You can include
|
|
556
|
+
> it in a Fastify project and reference it as you would any piece of code! As
|
|
557
|
+
> a TypeScript user, make sure the declaration override exists somewhere that
|
|
558
|
+
> will be included in your project compilation so the TypeScript interpreter
|
|
559
|
+
> can process it.
|
|
560
|
+
|
|
561
|
+
#### Creating Type Definitions for a Fastify Plugin
|
|
562
|
+
|
|
563
|
+
This plugin guide is for Fastify plugins written in JavaScript. The steps
|
|
564
|
+
outlined in this example are for adding TypeScript support for users consuming
|
|
565
|
+
your plugin.
|
|
566
|
+
|
|
567
|
+
1. Initialize a new npm project and install required dependencies
|
|
568
|
+
```bash
|
|
569
|
+
npm init -y
|
|
570
|
+
npm i fastify-plugin
|
|
571
|
+
```
|
|
572
|
+
2. Create two files `index.js` and `index.d.ts`
|
|
573
|
+
3. Modify the package json to include these files under the `main` and `types`
|
|
574
|
+
properties (the name does not have to be `index` explicitly, but it is
|
|
575
|
+
recommended the files have the same name):
|
|
576
|
+
```json
|
|
577
|
+
{
|
|
578
|
+
"main": "index.js",
|
|
579
|
+
"types": "index.d.ts"
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
4. Open `index.js` and add the following code:
|
|
583
|
+
```javascript
|
|
584
|
+
// fastify-plugin is highly recommended for any plugin you write
|
|
585
|
+
const fp = require('fastify-plugin')
|
|
586
|
+
|
|
587
|
+
function myPlugin (instance, options, done) {
|
|
588
|
+
|
|
589
|
+
// decorate the fastify instance with a custom function called myPluginFunc
|
|
590
|
+
instance.decorate('myPluginFunc', (input) => {
|
|
591
|
+
return input.toUpperCase()
|
|
592
|
+
})
|
|
593
|
+
|
|
594
|
+
done()
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
module.exports = fp(myPlugin, {
|
|
598
|
+
fastify: '5.x',
|
|
599
|
+
name: 'my-plugin' // this is used by fastify-plugin to derive the property name
|
|
600
|
+
})
|
|
601
|
+
```
|
|
602
|
+
5. Open `index.d.ts` and add the following code:
|
|
603
|
+
```typescript
|
|
604
|
+
import { FastifyPluginCallback } from 'fastify'
|
|
605
|
+
|
|
606
|
+
interface PluginOptions {
|
|
607
|
+
//...
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// Optionally, you can add any additional exports.
|
|
611
|
+
// Here we are exporting the decorator we added.
|
|
612
|
+
export interface myPluginFunc {
|
|
613
|
+
(input: string): string
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Most importantly, use declaration merging to add the custom property to the Fastify type system
|
|
617
|
+
declare module 'fastify' {
|
|
618
|
+
interface FastifyInstance {
|
|
619
|
+
myPluginFunc: myPluginFunc
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// fastify-plugin automatically adds named export, so be sure to add also this type
|
|
624
|
+
// the variable name is derived from `options.name` property if `module.exports.myPlugin` is missing
|
|
625
|
+
export const myPlugin: FastifyPluginCallback<PluginOptions>
|
|
626
|
+
|
|
627
|
+
// fastify-plugin automatically adds `.default` property to the exported plugin. See the note below
|
|
628
|
+
export default myPlugin
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
__Note__: [fastify-plugin](https://github.com/fastify/fastify-plugin) v2.3.0 and
|
|
632
|
+
newer, automatically adds `.default` property and a named export to the exported
|
|
633
|
+
plugin. Be sure to `export default` and `export const myPlugin` in your typings
|
|
634
|
+
to provide the best developer experience. For a complete example you can check
|
|
635
|
+
out
|
|
636
|
+
[@fastify/swagger](https://github.com/fastify/fastify-swagger/blob/main/index.d.ts).
|
|
637
|
+
|
|
638
|
+
With those files completed, the plugin is now ready to be consumed by any
|
|
639
|
+
TypeScript project!
|
|
640
|
+
|
|
641
|
+
The Fastify plugin system enables developers to decorate the Fastify instance,
|
|
642
|
+
and the request/reply instances. For more information check out this blog post
|
|
643
|
+
on [Declaration Merging and Generic
|
|
644
|
+
Inheritance](https://dev.to/ethanarrowood/is-declaration-merging-and-generic-inheritance-at-the-same-time-impossible-53cp).
|
|
645
|
+
|
|
646
|
+
#### Using a Plugin
|
|
647
|
+
|
|
648
|
+
Using a Fastify plugin in TypeScript is just as easy as using one in JavaScript.
|
|
649
|
+
Import the plugin with `import/from` and you're all set -- except there is one
|
|
650
|
+
exception users should be aware of.
|
|
651
|
+
|
|
652
|
+
Fastify plugins use declaration merging to modify existing Fastify type
|
|
653
|
+
interfaces (check out the previous two examples for more details). Declaration
|
|
654
|
+
merging is not very _smart_, meaning if the plugin type definition for a plugin
|
|
655
|
+
is within the scope of the TypeScript interpreter, then the plugin types will be
|
|
656
|
+
included **regardless** of if the plugin is being used or not. This is an
|
|
657
|
+
unfortunate limitation of using TypeScript and is unavoidable as of right now.
|
|
658
|
+
|
|
659
|
+
However, there are a couple of suggestions to help improve this experience:
|
|
660
|
+
- Make sure the `no-unused-vars` rule is enabled in
|
|
661
|
+
[ESLint](https://eslint.org/docs/rules/no-unused-vars) and any imported plugin
|
|
662
|
+
are actually being loaded.
|
|
663
|
+
- Use a module such as [depcheck](https://www.npmjs.com/package/depcheck) or
|
|
664
|
+
[npm-check](https://www.npmjs.com/package/npm-check) to verify plugin
|
|
665
|
+
dependencies are being used somewhere in your project.
|
|
666
|
+
|
|
667
|
+
Note that using `require` will not load the type definitions properly and may
|
|
668
|
+
cause type errors.
|
|
669
|
+
TypeScript can only identify the types that are directly imported into code,
|
|
670
|
+
which means that you can use require inline with import on top. For example:
|
|
671
|
+
|
|
672
|
+
```typescript
|
|
673
|
+
import 'plugin' // here will trigger the type augmentation.
|
|
674
|
+
|
|
675
|
+
fastify.register(require('plugin'))
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
```typescript
|
|
679
|
+
import plugin from 'plugin' // here will trigger the type augmentation.
|
|
680
|
+
|
|
681
|
+
fastify.register(plugin)
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
Or even explicit config on tsconfig
|
|
685
|
+
```jsonc
|
|
686
|
+
{
|
|
687
|
+
"types": ["plugin"] // we force TypeScript to import the types
|
|
688
|
+
}
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
#### `getDecorator<T>`
|
|
692
|
+
|
|
693
|
+
Fastify's `getDecorator<T>` method retrieves decorators with enhanced type safety.
|
|
694
|
+
|
|
695
|
+
The `getDecorator<T>` method supports generic type parameters for enhanced type
|
|
696
|
+
safety:
|
|
697
|
+
|
|
698
|
+
```typescript
|
|
699
|
+
// Type-safe decorator retrieval
|
|
700
|
+
const usersRepository = fastify.getDecorator<IUsersRepository>('usersRepository')
|
|
701
|
+
const session = request.getDecorator<ISession>('session')
|
|
702
|
+
const sendSuccess = reply.getDecorator<SendSuccessFn>('sendSuccess')
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
**Alternative to Module Augmentation**
|
|
706
|
+
|
|
707
|
+
Decorators are typically typed via module augmentation:
|
|
708
|
+
|
|
709
|
+
```typescript
|
|
710
|
+
declare module 'fastify' {
|
|
711
|
+
interface FastifyInstance {
|
|
712
|
+
usersRepository: IUsersRepository
|
|
713
|
+
}
|
|
714
|
+
interface FastifyRequest {
|
|
715
|
+
session: ISession
|
|
716
|
+
}
|
|
717
|
+
interface FastifyReply {
|
|
718
|
+
sendSuccess: SendSuccessFn
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
This approach modifies the Fastify instance globally, which may lead to conflicts
|
|
724
|
+
and inconsistent behavior in multi-server setups or with plugin encapsulation.
|
|
725
|
+
|
|
726
|
+
Using `getDecorator<T>` allows limiting types scope:
|
|
727
|
+
|
|
728
|
+
```typescript
|
|
729
|
+
serverOne.register(async function (fastify) {
|
|
730
|
+
const usersRepository = fastify.getDecorator<PostgreUsersRepository>(
|
|
731
|
+
'usersRepository'
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
fastify.decorateRequest('session', null)
|
|
735
|
+
fastify.addHook('onRequest', async (req, reply) => {
|
|
736
|
+
req.setDecorator('session', { user: 'Jean' })
|
|
737
|
+
})
|
|
738
|
+
|
|
739
|
+
fastify.get('/me', (request, reply) => {
|
|
740
|
+
const session = request.getDecorator<ISession>('session')
|
|
741
|
+
reply.send(session)
|
|
742
|
+
})
|
|
743
|
+
})
|
|
744
|
+
|
|
745
|
+
serverTwo.register(async function (fastify) {
|
|
746
|
+
const usersRepository = fastify.getDecorator<SqlLiteUsersRepository>(
|
|
747
|
+
'usersRepository'
|
|
748
|
+
)
|
|
749
|
+
|
|
750
|
+
fastify.decorateReply('sendSuccess', function (data) {
|
|
751
|
+
return this.send({ success: true })
|
|
752
|
+
})
|
|
753
|
+
|
|
754
|
+
fastify.get('/success', async (request, reply) => {
|
|
755
|
+
const sendSuccess = reply.getDecorator<SendSuccessFn>('sendSuccess')
|
|
756
|
+
await sendSuccess()
|
|
757
|
+
})
|
|
758
|
+
})
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
**Bound Functions Inference**
|
|
762
|
+
|
|
763
|
+
To save time, it is common to infer function types instead of writing them manually:
|
|
764
|
+
|
|
765
|
+
```typescript
|
|
766
|
+
function sendSuccess (this: FastifyReply) {
|
|
767
|
+
return this.send({ success: true })
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
export type SendSuccess = typeof sendSuccess
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
However, `getDecorator` returns functions with the `this` context already **bound**,
|
|
774
|
+
meaning the `this` parameter disappears from the function signature.
|
|
775
|
+
|
|
776
|
+
To correctly type it, use the `OmitThisParameter` utility:
|
|
777
|
+
|
|
778
|
+
```typescript
|
|
779
|
+
function sendSuccess (this: FastifyReply) {
|
|
780
|
+
return this.send({ success: true })
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
type BoundSendSuccess = OmitThisParameter<typeof sendSuccess>
|
|
784
|
+
|
|
785
|
+
fastify.decorateReply('sendSuccess', sendSuccess)
|
|
786
|
+
fastify.get('/success', async (request, reply) => {
|
|
787
|
+
const sendSuccess = reply.getDecorator<BoundSendSuccess>('sendSuccess')
|
|
788
|
+
await sendSuccess()
|
|
789
|
+
})
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
#### `setDecorator<T>`
|
|
793
|
+
|
|
794
|
+
Fastify's `setDecorator<T>` method provides enhanced type safety for updating request
|
|
795
|
+
decorators.
|
|
796
|
+
|
|
797
|
+
The `setDecorator<T>` method provides enhanced type safety for updating request
|
|
798
|
+
decorators:
|
|
799
|
+
|
|
800
|
+
```typescript
|
|
801
|
+
fastify.decorateRequest('user', '')
|
|
802
|
+
fastify.addHook('preHandler', async (req, reply) => {
|
|
803
|
+
// Type-safe decorator setting
|
|
804
|
+
req.setDecorator<string>('user', 'Bob Dylan')
|
|
805
|
+
})
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
**Type Safety Benefits**
|
|
809
|
+
|
|
810
|
+
If the `FastifyRequest` interface does not declare the decorator, type assertions
|
|
811
|
+
are typically needed:
|
|
812
|
+
|
|
813
|
+
```typescript
|
|
814
|
+
fastify.addHook('preHandler', async (req, reply) => {
|
|
815
|
+
(req as typeof req & { user: string }).user = 'Bob Dylan'
|
|
816
|
+
})
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
The `setDecorator<T>` method eliminates the need for explicit type assertions
|
|
820
|
+
while providing type safety:
|
|
821
|
+
|
|
822
|
+
```typescript
|
|
823
|
+
fastify.addHook('preHandler', async (req, reply) => {
|
|
824
|
+
req.setDecorator<string>('user', 'Bob Dylan')
|
|
825
|
+
})
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
## Code Completion In Vanilla JavaScript
|
|
829
|
+
|
|
830
|
+
Vanilla JavaScript can use the published types to provide code completion (e.g.
|
|
831
|
+
[Intellisense](https://code.visualstudio.com/docs/editor/intellisense)) by
|
|
832
|
+
following the [TypeScript JSDoc
|
|
833
|
+
Reference](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html).
|
|
834
|
+
|
|
835
|
+
For example:
|
|
836
|
+
|
|
837
|
+
```js
|
|
838
|
+
/** @type {import('fastify').FastifyPluginAsync<{ optionA: boolean, optionB: string }>} */
|
|
839
|
+
module.exports = async function (fastify, { optionA, optionB }) {
|
|
840
|
+
fastify.get('/look', () => 'at me');
|
|
841
|
+
}
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
## API Type System Documentation
|
|
845
|
+
|
|
846
|
+
This section is a detailed account of all the types available to you in Fastify
|
|
847
|
+
version 3.x
|
|
848
|
+
|
|
849
|
+
All `http`, `https`, and `http2` types are inferred from `@types/node`
|
|
850
|
+
|
|
851
|
+
[Generics](#generics) are documented by their default value as well as their
|
|
852
|
+
constraint value(s). Read these articles for more information on TypeScript
|
|
853
|
+
generics.
|
|
854
|
+
- [Generic Parameter
|
|
855
|
+
Default](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html#generic-parameter-defaults)
|
|
856
|
+
- [Generic Constraints](https://www.typescriptlang.org/docs/handbook/2/generics.html#generic-constraints)
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
#### How to import
|
|
860
|
+
|
|
861
|
+
The Fastify API is powered by the `fastify()` method. In JavaScript you would
|
|
862
|
+
import it using `const fastify = require('fastify')`. In TypeScript it is
|
|
863
|
+
recommended to use the `import/from` syntax instead so types can be resolved.
|
|
864
|
+
There are a couple supported import methods with the Fastify type system.
|
|
865
|
+
|
|
866
|
+
1. `import fastify from 'fastify'`
|
|
867
|
+
- Types are resolved but not accessible using dot notation
|
|
868
|
+
- Example:
|
|
869
|
+
```typescript
|
|
870
|
+
import fastify from 'fastify'
|
|
871
|
+
|
|
872
|
+
const f = fastify()
|
|
873
|
+
f.listen({ port: 8080 }, () => { console.log('running') })
|
|
874
|
+
```
|
|
875
|
+
- Gain access to types with destructuring:
|
|
876
|
+
```typescript
|
|
877
|
+
import fastify, { FastifyInstance } from 'fastify'
|
|
878
|
+
|
|
879
|
+
const f: FastifyInstance = fastify()
|
|
880
|
+
f.listen({ port: 8080 }, () => { console.log('running') })
|
|
881
|
+
```
|
|
882
|
+
- Destructuring also works for the main API method:
|
|
883
|
+
```typescript
|
|
884
|
+
import { fastify, FastifyInstance } from 'fastify'
|
|
885
|
+
|
|
886
|
+
const f: FastifyInstance = fastify()
|
|
887
|
+
f.listen({ port: 8080 }, () => { console.log('running') })
|
|
888
|
+
```
|
|
889
|
+
2. `import * as Fastify from 'fastify'`
|
|
890
|
+
- Types are resolved and accessible using dot notation
|
|
891
|
+
- Calling the main Fastify API method requires a slightly different syntax
|
|
892
|
+
(see example)
|
|
893
|
+
- Example:
|
|
894
|
+
```typescript
|
|
895
|
+
import * as Fastify from 'fastify'
|
|
896
|
+
|
|
897
|
+
const f: Fastify.FastifyInstance = Fastify.fastify()
|
|
898
|
+
f.listen({ port: 8080 }, () => { console.log('running') })
|
|
899
|
+
```
|
|
900
|
+
3. `const fastify = require('fastify')`
|
|
901
|
+
- This syntax is valid and will import fastify as expected; however, types
|
|
902
|
+
will **not** be resolved
|
|
903
|
+
- Example:
|
|
904
|
+
```typescript
|
|
905
|
+
const fastify = require('fastify')
|
|
906
|
+
|
|
907
|
+
const f = fastify()
|
|
908
|
+
f.listen({ port: 8080 }, () => { console.log('running') })
|
|
909
|
+
```
|
|
910
|
+
- Destructuring is supported and will resolve types properly
|
|
911
|
+
```typescript
|
|
912
|
+
const { fastify } = require('fastify')
|
|
913
|
+
|
|
914
|
+
const f = fastify()
|
|
915
|
+
f.listen({ port: 8080 }, () => { console.log('running') })
|
|
916
|
+
```
|
|
917
|
+
|
|
918
|
+
#### Generics
|
|
919
|
+
|
|
920
|
+
Many type definitions share the same generic parameters; they are all
|
|
921
|
+
documented, in detail, within this section.
|
|
922
|
+
|
|
923
|
+
Most definitions depend on `@types/node` modules `http`, `https`, and `http2`
|
|
924
|
+
|
|
925
|
+
##### RawServer
|
|
926
|
+
Underlying Node.js server type
|
|
927
|
+
|
|
928
|
+
Default: `http.Server`
|
|
929
|
+
|
|
930
|
+
Constraints: `http.Server`, `https.Server`, `http2.Http2Server`,
|
|
931
|
+
`http2.Http2SecureServer`
|
|
932
|
+
|
|
933
|
+
Enforces generic parameters: [`RawRequest`][RawRequestGeneric],
|
|
934
|
+
[`RawReply`][RawReplyGeneric]
|
|
935
|
+
|
|
936
|
+
##### RawRequest
|
|
937
|
+
Underlying Node.js request type
|
|
938
|
+
|
|
939
|
+
Default: [`RawRequestDefaultExpression`][RawRequestDefaultExpression]
|
|
940
|
+
|
|
941
|
+
Constraints: `http.IncomingMessage`, `http2.Http2ServerRequest`
|
|
942
|
+
|
|
943
|
+
Enforced by: [`RawServer`][RawServerGeneric]
|
|
944
|
+
|
|
945
|
+
##### RawReply
|
|
946
|
+
Underlying Node.js response type
|
|
947
|
+
|
|
948
|
+
Default: [`RawReplyDefaultExpression`][RawReplyDefaultExpression]
|
|
949
|
+
|
|
950
|
+
Constraints: `http.ServerResponse`, `http2.Http2ServerResponse`
|
|
951
|
+
|
|
952
|
+
Enforced by: [`RawServer`][RawServerGeneric]
|
|
953
|
+
|
|
954
|
+
##### Logger
|
|
955
|
+
Fastify logging utility
|
|
956
|
+
|
|
957
|
+
Default: [`FastifyLoggerOptions`][FastifyLoggerOptions]
|
|
958
|
+
|
|
959
|
+
Enforced by: [`RawServer`][RawServerGeneric]
|
|
960
|
+
|
|
961
|
+
##### RawBody
|
|
962
|
+
A generic parameter for the content-type-parser methods.
|
|
963
|
+
|
|
964
|
+
Constraints: `string | Buffer`
|
|
965
|
+
|
|
966
|
+
---
|
|
967
|
+
|
|
968
|
+
#### Fastify
|
|
969
|
+
|
|
970
|
+
##### fastify< [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [Logger][LoggerGeneric]>(opts?: [FastifyServerOptions][FastifyServerOptions]): [FastifyInstance][FastifyInstance]
|
|
971
|
+
[src](https://github.com/fastify/fastify/blob/main/fastify.d.ts#L19)
|
|
972
|
+
|
|
973
|
+
The main Fastify API method. By default creates an HTTP server. Utilizing
|
|
974
|
+
discriminant unions and overload methods, the type system will automatically
|
|
975
|
+
infer which type of server (http, https, or http2) is being created purely based
|
|
976
|
+
on the options based to the method (see the examples below for more
|
|
977
|
+
information). It also supports an extensive generic type system to allow the
|
|
978
|
+
user to extend the underlying Node.js Server, Request, and Reply objects.
|
|
979
|
+
Additionally, the `Logger` generic exists for custom log types. See the examples
|
|
980
|
+
and generic breakdown below for more information.
|
|
981
|
+
|
|
982
|
+
###### Example 1: Standard HTTP server
|
|
983
|
+
|
|
984
|
+
No need to specify the `Server` generic as the type system defaults to HTTP.
|
|
985
|
+
```typescript
|
|
986
|
+
import fastify from 'fastify'
|
|
987
|
+
|
|
988
|
+
const server = fastify()
|
|
989
|
+
```
|
|
990
|
+
Check out the Learn By Example - [Getting Started](#getting-started) example for
|
|
991
|
+
a more detailed http server walkthrough.
|
|
992
|
+
|
|
993
|
+
###### Example 2: HTTPS server
|
|
994
|
+
|
|
995
|
+
1. Create the following imports from `@types/node` and `fastify`
|
|
996
|
+
```typescript
|
|
997
|
+
import fs from 'node:fs'
|
|
998
|
+
import path from 'node:path'
|
|
999
|
+
import fastify from 'fastify'
|
|
1000
|
+
```
|
|
1001
|
+
2. Perform the following steps before setting up a Fastify HTTPS server
|
|
1002
|
+
to create the `key.pem` and `cert.pem` files:
|
|
1003
|
+
```sh
|
|
1004
|
+
openssl genrsa -out key.pem
|
|
1005
|
+
openssl req -new -key key.pem -out csr.pem
|
|
1006
|
+
openssl x509 -req -days 9999 -in csr.pem -signkey key.pem -out cert.pem
|
|
1007
|
+
rm csr.pem
|
|
1008
|
+
```
|
|
1009
|
+
3. Instantiate a Fastify https server and add a route:
|
|
1010
|
+
```typescript
|
|
1011
|
+
const server = fastify({
|
|
1012
|
+
https: {
|
|
1013
|
+
key: fs.readFileSync(path.join(__dirname, 'key.pem')),
|
|
1014
|
+
cert: fs.readFileSync(path.join(__dirname, 'cert.pem'))
|
|
1015
|
+
}
|
|
1016
|
+
})
|
|
1017
|
+
|
|
1018
|
+
server.get('/', async function (request, reply) {
|
|
1019
|
+
return { hello: 'world' }
|
|
1020
|
+
})
|
|
1021
|
+
|
|
1022
|
+
server.listen({ port: 8080 }, (err, address) => {
|
|
1023
|
+
if (err) {
|
|
1024
|
+
console.error(err)
|
|
1025
|
+
process.exit(0)
|
|
1026
|
+
}
|
|
1027
|
+
console.log(`Server listening at ${address}`)
|
|
1028
|
+
})
|
|
1029
|
+
```
|
|
1030
|
+
4. Build and run! Test your server out by querying with: `curl -k
|
|
1031
|
+
https://localhost:8080`
|
|
1032
|
+
|
|
1033
|
+
###### Example 3: HTTP2 server
|
|
1034
|
+
|
|
1035
|
+
There are two types of HTTP2 server types, insecure and secure. Both require
|
|
1036
|
+
specifying the `http2` property as `true` in the `options` object. The `https`
|
|
1037
|
+
property is used for creating a secure http2 server; omitting the `https`
|
|
1038
|
+
property will create an insecure http2 server.
|
|
1039
|
+
|
|
1040
|
+
```typescript
|
|
1041
|
+
const insecureServer = fastify({ http2: true })
|
|
1042
|
+
const secureServer = fastify({
|
|
1043
|
+
http2: true,
|
|
1044
|
+
https: {} // use the `key.pem` and `cert.pem` files from the https section
|
|
1045
|
+
})
|
|
1046
|
+
```
|
|
1047
|
+
|
|
1048
|
+
For more details on using HTTP2 check out the Fastify [HTTP2](./HTTP2.md)
|
|
1049
|
+
documentation page.
|
|
1050
|
+
|
|
1051
|
+
###### Example 4: Extended HTTP server
|
|
1052
|
+
|
|
1053
|
+
Not only can you specify the server type, but also the request and reply types.
|
|
1054
|
+
Thus, allowing you to specify special properties, methods, and more! When
|
|
1055
|
+
specified at server instantiation, the custom type becomes available on all
|
|
1056
|
+
further instances of the custom type.
|
|
1057
|
+
```typescript
|
|
1058
|
+
import fastify from 'fastify'
|
|
1059
|
+
import http from 'node:http'
|
|
1060
|
+
|
|
1061
|
+
interface customRequest extends http.IncomingMessage {
|
|
1062
|
+
mySpecialProp: string
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
const server = fastify<http.Server, customRequest>()
|
|
1066
|
+
|
|
1067
|
+
server.get('/', async (request, reply) => {
|
|
1068
|
+
const someValue = request.raw.mySpecialProp // TS knows this is a string, because of the `customRequest` interface
|
|
1069
|
+
return someValue.toUpperCase()
|
|
1070
|
+
})
|
|
1071
|
+
```
|
|
1072
|
+
|
|
1073
|
+
###### Example 5: Specifying logger types
|
|
1074
|
+
|
|
1075
|
+
Fastify uses [Pino](https://getpino.io/#/) logging library under the hood. Since
|
|
1076
|
+
`pino@7`, all of it's properties can be configured via `logger` field when
|
|
1077
|
+
constructing Fastify's instance. If properties you need aren't exposed, please
|
|
1078
|
+
open an Issue to [`Pino`](https://github.com/pinojs/pino/issues) or pass a
|
|
1079
|
+
preconfigured external instance of Pino (or any other compatible logger) as
|
|
1080
|
+
temporary fix to Fastify via the same field. This allows creating custom
|
|
1081
|
+
serializers as well, see the [Logging](Logging.md) documentation for more info.
|
|
1082
|
+
|
|
1083
|
+
```typescript
|
|
1084
|
+
import fastify from 'fastify'
|
|
1085
|
+
|
|
1086
|
+
const server = fastify({
|
|
1087
|
+
logger: {
|
|
1088
|
+
level: 'info',
|
|
1089
|
+
redact: ['x-userinfo'],
|
|
1090
|
+
messageKey: 'message'
|
|
1091
|
+
}
|
|
1092
|
+
})
|
|
1093
|
+
|
|
1094
|
+
server.get('/', async (request, reply) => {
|
|
1095
|
+
server.log.info('log message')
|
|
1096
|
+
return 'another message'
|
|
1097
|
+
})
|
|
1098
|
+
```
|
|
1099
|
+
|
|
1100
|
+
---
|
|
1101
|
+
|
|
1102
|
+
##### fastify.HTTPMethods
|
|
1103
|
+
[src](https://github.com/fastify/fastify/blob/main/types/utils.d.ts#L8)
|
|
1104
|
+
|
|
1105
|
+
Union type of: `'DELETE' | 'GET' | 'HEAD' | 'PATCH' | 'POST' | 'PUT' |
|
|
1106
|
+
'OPTIONS'`
|
|
1107
|
+
|
|
1108
|
+
##### fastify.RawServerBase
|
|
1109
|
+
[src](https://github.com/fastify/fastify/blob/main/types/utils.d.ts#L13)
|
|
1110
|
+
|
|
1111
|
+
Dependent on `@types/node` modules `http`, `https`, `http2`
|
|
1112
|
+
|
|
1113
|
+
Union type of: `http.Server | https.Server | http2.Http2Server |
|
|
1114
|
+
http2.Http2SecureServer`
|
|
1115
|
+
|
|
1116
|
+
##### fastify.RawServerDefault
|
|
1117
|
+
[src](https://github.com/fastify/fastify/blob/main/types/utils.d.ts#L18)
|
|
1118
|
+
|
|
1119
|
+
Dependent on `@types/node` modules `http`
|
|
1120
|
+
|
|
1121
|
+
Type alias for `http.Server`
|
|
1122
|
+
|
|
1123
|
+
---
|
|
1124
|
+
|
|
1125
|
+
##### fastify.FastifyServerOptions< [RawServer][RawServerGeneric], [Logger][LoggerGeneric]>
|
|
1126
|
+
|
|
1127
|
+
[src](https://github.com/fastify/fastify/blob/main/fastify.d.ts#L29)
|
|
1128
|
+
|
|
1129
|
+
An interface of properties used in the instantiation of the Fastify server. Is
|
|
1130
|
+
used in the main [`fastify()`][Fastify] method. The `RawServer` and `Logger`
|
|
1131
|
+
generic parameters are passed down through that method.
|
|
1132
|
+
|
|
1133
|
+
See the main [fastify][Fastify] method type definition section for examples on
|
|
1134
|
+
instantiating a Fastify server with TypeScript.
|
|
1135
|
+
|
|
1136
|
+
##### fastify.FastifyInstance< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RequestGeneric][FastifyRequestGenericInterface], [Logger][LoggerGeneric]>
|
|
1137
|
+
|
|
1138
|
+
[src](https://github.com/fastify/fastify/blob/main/types/instance.d.ts#L16)
|
|
1139
|
+
|
|
1140
|
+
Interface that represents the Fastify server object. This is the returned server
|
|
1141
|
+
instance from the [`fastify()`][Fastify] method. This type is an interface so it
|
|
1142
|
+
can be extended via [declaration
|
|
1143
|
+
merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html)
|
|
1144
|
+
if your code makes use of the `decorate` method.
|
|
1145
|
+
|
|
1146
|
+
Through the use of generic cascading, all methods attached to the instance
|
|
1147
|
+
inherit the generic properties from instantiation. This means that by specifying
|
|
1148
|
+
the server, request, or reply types, all methods will know how to type those
|
|
1149
|
+
objects.
|
|
1150
|
+
|
|
1151
|
+
Check out the main [Learn by Example](#learn-by-example) section for detailed
|
|
1152
|
+
guides, or the more simplified [fastify][Fastify] method examples for additional
|
|
1153
|
+
details on this interface.
|
|
1154
|
+
|
|
1155
|
+
---
|
|
1156
|
+
|
|
1157
|
+
#### Request
|
|
1158
|
+
|
|
1159
|
+
##### fastify.FastifyRequest< [RequestGeneric][FastifyRequestGenericInterface], [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric]>
|
|
1160
|
+
[src](https://github.com/fastify/fastify/blob/main/types/request.d.ts#L15)
|
|
1161
|
+
|
|
1162
|
+
This interface contains properties of Fastify request object. The properties
|
|
1163
|
+
added here disregard what kind of request object (http vs http2) and disregard
|
|
1164
|
+
what route level it is serving; thus calling `request.body` inside a GET request
|
|
1165
|
+
will not throw an error (but good luck sending a GET request with a body 😉).
|
|
1166
|
+
|
|
1167
|
+
If you need to add custom properties to the `FastifyRequest` object (such as
|
|
1168
|
+
when using the [`decorateRequest`][DecorateRequest] method) you need to use
|
|
1169
|
+
declaration merging on this interface.
|
|
1170
|
+
|
|
1171
|
+
A basic example is provided in the [`FastifyRequest`][FastifyRequest] section.
|
|
1172
|
+
For a more detailed example check out the Learn By Example section:
|
|
1173
|
+
[Plugins](#plugins)
|
|
1174
|
+
|
|
1175
|
+
###### Example
|
|
1176
|
+
```typescript
|
|
1177
|
+
import fastify from 'fastify'
|
|
1178
|
+
|
|
1179
|
+
const server = fastify()
|
|
1180
|
+
|
|
1181
|
+
server.decorateRequest('someProp', 'hello!')
|
|
1182
|
+
|
|
1183
|
+
server.get('/', async (request, reply) => {
|
|
1184
|
+
const { someProp } = request // need to use declaration merging to add this prop to the request interface
|
|
1185
|
+
return someProp
|
|
1186
|
+
})
|
|
1187
|
+
|
|
1188
|
+
// this declaration must be in scope of the typescript interpreter to work
|
|
1189
|
+
declare module 'fastify' {
|
|
1190
|
+
interface FastifyRequest { // you must reference the interface and not the type
|
|
1191
|
+
someProp: string
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
// Or you can type your request using
|
|
1196
|
+
type CustomRequest = FastifyRequest<{
|
|
1197
|
+
Body: { test: boolean };
|
|
1198
|
+
}>
|
|
1199
|
+
|
|
1200
|
+
server.get('/typedRequest', async (request: CustomRequest, reply: FastifyReply) => {
|
|
1201
|
+
return request.body.test
|
|
1202
|
+
})
|
|
1203
|
+
```
|
|
1204
|
+
|
|
1205
|
+
##### fastify.RequestGenericInterface
|
|
1206
|
+
[src](https://github.com/fastify/fastify/blob/main/types/request.d.ts#L4)
|
|
1207
|
+
|
|
1208
|
+
Fastify request objects have four dynamic properties: `body`, `params`, `query`,
|
|
1209
|
+
and `headers`. Their respective types are assignable through this interface. It
|
|
1210
|
+
is a named property interface enabling the developer to ignore the properties
|
|
1211
|
+
they do not want to specify. All omitted properties are defaulted to `unknown`.
|
|
1212
|
+
The corresponding property names are: `Body`, `Querystring`, `Params`,
|
|
1213
|
+
`Headers`.
|
|
1214
|
+
|
|
1215
|
+
```typescript
|
|
1216
|
+
import fastify, { RequestGenericInterface } from 'fastify'
|
|
1217
|
+
|
|
1218
|
+
const server = fastify()
|
|
1219
|
+
|
|
1220
|
+
interface requestGeneric extends RequestGenericInterface {
|
|
1221
|
+
Querystring: {
|
|
1222
|
+
name: string
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
server.get<requestGeneric>('/', async (request, reply) => {
|
|
1227
|
+
const { name } = request.query // the name prop now exists on the query prop
|
|
1228
|
+
return name.toUpperCase()
|
|
1229
|
+
})
|
|
1230
|
+
```
|
|
1231
|
+
|
|
1232
|
+
If you want to see a detailed example of using this interface check out the
|
|
1233
|
+
Learn by Example section: [JSON Schema](#json-schema).
|
|
1234
|
+
|
|
1235
|
+
##### fastify.RawRequestDefaultExpression\<[RawServer][RawServerGeneric]\>
|
|
1236
|
+
[src](https://github.com/fastify/fastify/blob/main/types/utils.d.ts#L23)
|
|
1237
|
+
|
|
1238
|
+
Dependent on `@types/node` modules `http`, `https`, `http2`
|
|
1239
|
+
|
|
1240
|
+
Generic parameter `RawServer` defaults to [`RawServerDefault`][RawServerDefault]
|
|
1241
|
+
|
|
1242
|
+
If `RawServer` is of type `http.Server` or `https.Server`, then this expression
|
|
1243
|
+
returns `http.IncomingMessage`, otherwise, it returns
|
|
1244
|
+
`http2.Http2ServerRequest`.
|
|
1245
|
+
|
|
1246
|
+
```typescript
|
|
1247
|
+
import http from 'node:http'
|
|
1248
|
+
import http2 from 'node:http2'
|
|
1249
|
+
import { RawRequestDefaultExpression } from 'fastify'
|
|
1250
|
+
|
|
1251
|
+
RawRequestDefaultExpression<http.Server> // -> http.IncomingMessage
|
|
1252
|
+
RawRequestDefaultExpression<http2.Http2Server> // -> http2.Http2ServerRequest
|
|
1253
|
+
```
|
|
1254
|
+
|
|
1255
|
+
---
|
|
1256
|
+
|
|
1257
|
+
#### Reply
|
|
1258
|
+
|
|
1259
|
+
##### fastify.FastifyReply<[RequestGeneric][FastifyRequestGenericInterface], [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [ContextConfig][ContextConfigGeneric]>
|
|
1260
|
+
[src](https://github.com/fastify/fastify/blob/main/types/reply.d.ts#L32)
|
|
1261
|
+
|
|
1262
|
+
This interface contains the custom properties that Fastify adds to the standard
|
|
1263
|
+
Node.js reply object. The properties added here disregard what kind of reply
|
|
1264
|
+
object (http vs http2).
|
|
1265
|
+
|
|
1266
|
+
If you need to add custom properties to the FastifyReply object (such as when
|
|
1267
|
+
using the `decorateReply` method) you need to use declaration merging on this
|
|
1268
|
+
interface.
|
|
1269
|
+
|
|
1270
|
+
A basic example is provided in the [`FastifyReply`][FastifyReply] section. For a
|
|
1271
|
+
more detailed example check out the Learn By Example section:
|
|
1272
|
+
[Plugins](#plugins)
|
|
1273
|
+
|
|
1274
|
+
###### Example
|
|
1275
|
+
```typescript
|
|
1276
|
+
import fastify from 'fastify'
|
|
1277
|
+
|
|
1278
|
+
const server = fastify()
|
|
1279
|
+
|
|
1280
|
+
server.decorateReply('someProp', 'world')
|
|
1281
|
+
|
|
1282
|
+
server.get('/', async (request, reply) => {
|
|
1283
|
+
const { someProp } = reply // need to use declaration merging to add this prop to the reply interface
|
|
1284
|
+
return someProp
|
|
1285
|
+
})
|
|
1286
|
+
|
|
1287
|
+
// this declaration must be in scope of the typescript interpreter to work
|
|
1288
|
+
declare module 'fastify' {
|
|
1289
|
+
interface FastifyReply { // you must reference the interface and not the type
|
|
1290
|
+
someProp: string
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
```
|
|
1294
|
+
|
|
1295
|
+
##### fastify.RawReplyDefaultExpression< [RawServer][RawServerGeneric]>
|
|
1296
|
+
[src](https://github.com/fastify/fastify/blob/main/types/utils.d.ts#L27)
|
|
1297
|
+
|
|
1298
|
+
Dependent on `@types/node` modules `http`, `https`, `http2`
|
|
1299
|
+
|
|
1300
|
+
Generic parameter `RawServer` defaults to [`RawServerDefault`][RawServerDefault]
|
|
1301
|
+
|
|
1302
|
+
If `RawServer` is of type `http.Server` or `https.Server`, then this expression
|
|
1303
|
+
returns `http.ServerResponse`, otherwise, it returns
|
|
1304
|
+
`http2.Http2ServerResponse`.
|
|
1305
|
+
|
|
1306
|
+
```typescript
|
|
1307
|
+
import http from 'node:http'
|
|
1308
|
+
import http2 from 'node:http2'
|
|
1309
|
+
import { RawReplyDefaultExpression } from 'fastify'
|
|
1310
|
+
|
|
1311
|
+
RawReplyDefaultExpression<http.Server> // -> http.ServerResponse
|
|
1312
|
+
RawReplyDefaultExpression<http2.Http2Server> // -> http2.Http2ServerResponse
|
|
1313
|
+
```
|
|
1314
|
+
|
|
1315
|
+
---
|
|
1316
|
+
|
|
1317
|
+
#### Plugin
|
|
1318
|
+
|
|
1319
|
+
Fastify allows the user to extend its functionalities with plugins. A plugin can
|
|
1320
|
+
be a set of routes, a server decorator or whatever. To activate plugins, use the
|
|
1321
|
+
[`fastify.register()`][FastifyRegister] method.
|
|
1322
|
+
|
|
1323
|
+
When creating plugins for Fastify, it is recommended to use the `fastify-plugin`
|
|
1324
|
+
module. Additionally, there is a guide to creating plugins with TypeScript and
|
|
1325
|
+
Fastify available in the Learn by Example, [Plugins](#plugins) section.
|
|
1326
|
+
|
|
1327
|
+
##### fastify.FastifyPluginCallback< [Options][FastifyPluginOptions]>
|
|
1328
|
+
[src](https://github.com/fastify/fastify/blob/main/types/plugin.d.ts#L9)
|
|
1329
|
+
|
|
1330
|
+
Interface method definition used within the
|
|
1331
|
+
[`fastify.register()`][FastifyRegister] method.
|
|
1332
|
+
|
|
1333
|
+
##### fastify.FastifyPluginAsync< [Options][FastifyPluginOptions]>
|
|
1334
|
+
[src](https://github.com/fastify/fastify/blob/main/types/plugin.d.ts#L20)
|
|
1335
|
+
|
|
1336
|
+
Interface method definition used within the
|
|
1337
|
+
[`fastify.register()`][FastifyRegister] method.
|
|
1338
|
+
|
|
1339
|
+
##### fastify.FastifyPlugin< [Options][FastifyPluginOptions]>
|
|
1340
|
+
[src](https://github.com/fastify/fastify/blob/main/types/plugin.d.ts#L29)
|
|
1341
|
+
|
|
1342
|
+
Interface method definition used within the
|
|
1343
|
+
[`fastify.register()`][FastifyRegister] method. Document deprecated in favor of
|
|
1344
|
+
`FastifyPluginCallback` and `FastifyPluginAsync` since general `FastifyPlugin`
|
|
1345
|
+
doesn't properly infer types for async functions.
|
|
1346
|
+
|
|
1347
|
+
##### fastify.FastifyPluginOptions
|
|
1348
|
+
[src](https://github.com/fastify/fastify/blob/main/types/plugin.d.ts#L31)
|
|
1349
|
+
|
|
1350
|
+
A loosely typed object used to constrain the `options` parameter of
|
|
1351
|
+
[`fastify.register()`][FastifyRegister] to an object. When creating a plugin,
|
|
1352
|
+
define its options as an extension of this interface (`interface MyPluginOptions
|
|
1353
|
+
extends FastifyPluginOptions`) so they can be passed to the register method.
|
|
1354
|
+
|
|
1355
|
+
---
|
|
1356
|
+
|
|
1357
|
+
#### Register
|
|
1358
|
+
|
|
1359
|
+
##### fastify.FastifyRegister(plugin: [FastifyPluginCallback][FastifyPluginCallback], opts: [FastifyRegisterOptions][FastifyRegisterOptions])
|
|
1360
|
+
[src](https://github.com/fastify/fastify/blob/main/types/register.d.ts#L9)
|
|
1361
|
+
##### fastify.FastifyRegister(plugin: [FastifyPluginAsync][FastifyPluginAsync], opts: [FastifyRegisterOptions][FastifyRegisterOptions])
|
|
1362
|
+
[src](https://github.com/fastify/fastify/blob/main/types/register.d.ts#L9)
|
|
1363
|
+
##### fastify.FastifyRegister(plugin: [FastifyPlugin][FastifyPlugin], opts: [FastifyRegisterOptions][FastifyRegisterOptions])
|
|
1364
|
+
[src](https://github.com/fastify/fastify/blob/main/types/register.d.ts#L9)
|
|
1365
|
+
|
|
1366
|
+
This type interface specifies the type for the
|
|
1367
|
+
[`fastify.register()`](./Server.md#register) method. The type interface returns
|
|
1368
|
+
a function signature with an underlying generic `Options` which is defaulted to
|
|
1369
|
+
[FastifyPluginOptions][FastifyPluginOptions]. It infers this generic from the
|
|
1370
|
+
FastifyPlugin parameter when calling this function so there is no need to
|
|
1371
|
+
specify the underlying generic. The options parameter is the intersection of the
|
|
1372
|
+
plugin's options and two additional optional properties: `prefix: string` and
|
|
1373
|
+
`logLevel`: [LogLevel][LogLevel]. `FastifyPlugin` is deprecated use
|
|
1374
|
+
`FastifyPluginCallback` and `FastifyPluginAsync` instead.
|
|
1375
|
+
|
|
1376
|
+
Below is an example of the options inference in action:
|
|
1377
|
+
|
|
1378
|
+
```typescript
|
|
1379
|
+
const server = fastify()
|
|
1380
|
+
|
|
1381
|
+
const plugin: FastifyPluginCallback<{
|
|
1382
|
+
option1: string;
|
|
1383
|
+
option2: boolean;
|
|
1384
|
+
}> = function (instance, opts, done) { }
|
|
1385
|
+
|
|
1386
|
+
server().register(plugin, {}) // Error - options object is missing required properties
|
|
1387
|
+
server().register(plugin, { option1: '', option2: true }) // OK - options object contains required properties
|
|
1388
|
+
```
|
|
1389
|
+
|
|
1390
|
+
See the Learn By Example, [Plugins](#plugins) section for more detailed examples
|
|
1391
|
+
of creating TypeScript plugins in Fastify.
|
|
1392
|
+
|
|
1393
|
+
##### fastify.FastifyRegisterOptions
|
|
1394
|
+
[src](https://github.com/fastify/fastify/blob/main/types/register.d.ts#L16)
|
|
1395
|
+
|
|
1396
|
+
This type is the intersection of the `Options` generic and a non-exported
|
|
1397
|
+
interface `RegisterOptions` that specifies two optional properties: `prefix:
|
|
1398
|
+
string` and `logLevel`: [LogLevel][LogLevel]. This type can also be specified as
|
|
1399
|
+
a function that returns the previously described intersection.
|
|
1400
|
+
|
|
1401
|
+
---
|
|
1402
|
+
|
|
1403
|
+
#### Logger
|
|
1404
|
+
|
|
1405
|
+
Check out the [Specifying Logger Types](#example-5-specifying-logger-types)
|
|
1406
|
+
example for more details on specifying a custom logger.
|
|
1407
|
+
|
|
1408
|
+
##### fastify.FastifyLoggerOptions< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric]>
|
|
1409
|
+
|
|
1410
|
+
[src](https://github.com/fastify/fastify/blob/main/types/logger.d.ts#L17)
|
|
1411
|
+
|
|
1412
|
+
An interface definition for the internal Fastify logger. It is emulative of the
|
|
1413
|
+
[Pino.js](https://getpino.io/#/) logger. When enabled through server options,
|
|
1414
|
+
use it following the general [logger](./Logging.md) documentation.
|
|
1415
|
+
|
|
1416
|
+
##### fastify.FastifyLogFn
|
|
1417
|
+
|
|
1418
|
+
[src](https://github.com/fastify/fastify/blob/main/types/logger.d.ts#L7)
|
|
1419
|
+
|
|
1420
|
+
An overload function interface that implements the two ways Fastify calls log
|
|
1421
|
+
methods. This interface is passed to all associated log level properties on the
|
|
1422
|
+
FastifyLoggerOptions object.
|
|
1423
|
+
|
|
1424
|
+
##### fastify.LogLevel
|
|
1425
|
+
|
|
1426
|
+
[src](https://github.com/fastify/fastify/blob/main/types/logger.d.ts#L12)
|
|
1427
|
+
|
|
1428
|
+
Union type of: `'info' | 'error' | 'debug' | 'fatal' | 'warn' | 'trace'`
|
|
1429
|
+
|
|
1430
|
+
---
|
|
1431
|
+
|
|
1432
|
+
#### Context
|
|
1433
|
+
|
|
1434
|
+
The context type definition is similar to the other highly dynamic pieces of the
|
|
1435
|
+
type system. Route context is available in the route handler method.
|
|
1436
|
+
|
|
1437
|
+
##### fastify.FastifyRequestContext
|
|
1438
|
+
|
|
1439
|
+
[src](https://github.com/fastify/fastify/blob/main/types/context.d.ts#L11)
|
|
1440
|
+
|
|
1441
|
+
An interface with a single required property `config` that is set by default to
|
|
1442
|
+
`unknown`. Can be specified either using a generic or an overload.
|
|
1443
|
+
|
|
1444
|
+
This type definition is potentially incomplete. If you are using it and can
|
|
1445
|
+
provide more details on how to improve the definition, we strongly encourage you
|
|
1446
|
+
to open an issue in the main
|
|
1447
|
+
[fastify/fastify](https://github.com/fastify/fastify) repository. Thank you in
|
|
1448
|
+
advanced!
|
|
1449
|
+
|
|
1450
|
+
##### fastify.FastifyReplyContext
|
|
1451
|
+
|
|
1452
|
+
[src](https://github.com/fastify/fastify/blob/main/types/context.d.ts#L11)
|
|
1453
|
+
|
|
1454
|
+
An interface with a single required property `config` that is set by default to
|
|
1455
|
+
`unknown`. Can be specified either using a generic or an overload.
|
|
1456
|
+
|
|
1457
|
+
This type definition is potentially incomplete. If you are using it and can
|
|
1458
|
+
provide more details on how to improve the definition, we strongly encourage you
|
|
1459
|
+
to open an issue in the main
|
|
1460
|
+
[fastify/fastify](https://github.com/fastify/fastify) repository. Thank you in
|
|
1461
|
+
advanced!
|
|
1462
|
+
|
|
1463
|
+
---
|
|
1464
|
+
|
|
1465
|
+
#### Routing
|
|
1466
|
+
|
|
1467
|
+
One of the core principles in Fastify is its routing capabilities. Most of the
|
|
1468
|
+
types defined in this section are used under-the-hood by the Fastify instance
|
|
1469
|
+
`.route` and `.get/.post/.etc` methods.
|
|
1470
|
+
|
|
1471
|
+
##### fastify.RouteHandlerMethod< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>
|
|
1472
|
+
|
|
1473
|
+
[src](https://github.com/fastify/fastify/blob/main/types/route.d.ts#L105)
|
|
1474
|
+
|
|
1475
|
+
A type declaration for the route handler methods. Has two arguments, `request`
|
|
1476
|
+
and `reply` which are typed by `FastifyRequest` and `FastifyReply` respectively.
|
|
1477
|
+
The generics parameters are passed through to these arguments. The method
|
|
1478
|
+
returns either `void` or `Promise<any>` for synchronous and asynchronous
|
|
1479
|
+
handlers respectively.
|
|
1480
|
+
|
|
1481
|
+
##### fastify.RouteOptions< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>
|
|
1482
|
+
|
|
1483
|
+
[src](https://github.com/fastify/fastify/blob/main/types/route.d.ts#L78)
|
|
1484
|
+
|
|
1485
|
+
An interface that extends RouteShorthandOptions and adds the following three
|
|
1486
|
+
required properties:
|
|
1487
|
+
1. `method` which corresponds to a singular [HTTPMethod][HTTPMethods] or a list
|
|
1488
|
+
of [HTTPMethods][HTTPMethods]
|
|
1489
|
+
2. `url` a string for the route
|
|
1490
|
+
3. `handler` the route handler method, see [RouteHandlerMethod][] for more
|
|
1491
|
+
details
|
|
1492
|
+
|
|
1493
|
+
##### fastify.RouteShorthandMethod< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric]>
|
|
1494
|
+
|
|
1495
|
+
[src](https://github.com/fastify/fastify/blob/main/types/route.d.ts#12)
|
|
1496
|
+
|
|
1497
|
+
An overloaded function interface for three kinds of shorthand route methods to
|
|
1498
|
+
be used in conjunction with the `.get/.post/.etc` methods.
|
|
1499
|
+
|
|
1500
|
+
##### fastify.RouteShorthandOptions< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>
|
|
1501
|
+
|
|
1502
|
+
[src](https://github.com/fastify/fastify/blob/main/types/route.d.ts#55)
|
|
1503
|
+
|
|
1504
|
+
An interface that covers all of the base options for a route. Each property on
|
|
1505
|
+
this interface is optional, and it serves as the base for the RouteOptions and
|
|
1506
|
+
RouteShorthandOptionsWithHandler interfaces.
|
|
1507
|
+
|
|
1508
|
+
##### fastify.RouteShorthandOptionsWithHandler< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>
|
|
1509
|
+
|
|
1510
|
+
[src](https://github.com/fastify/fastify/blob/main/types/route.d.ts#93)
|
|
1511
|
+
|
|
1512
|
+
This interface adds a single, required property to the RouteShorthandOptions
|
|
1513
|
+
interface `handler` which is of type RouteHandlerMethod
|
|
1514
|
+
|
|
1515
|
+
---
|
|
1516
|
+
|
|
1517
|
+
#### Parsers
|
|
1518
|
+
|
|
1519
|
+
##### RawBody
|
|
1520
|
+
|
|
1521
|
+
A generic type that is either a `string` or `Buffer`
|
|
1522
|
+
|
|
1523
|
+
##### fastify.FastifyBodyParser< [RawBody][RawBodyGeneric], [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric]>
|
|
1524
|
+
|
|
1525
|
+
[src](https://github.com/fastify/fastify/blob/main/types/content-type-parser.d.ts#L7)
|
|
1526
|
+
|
|
1527
|
+
A function type definition for specifying a body parser method. Use the
|
|
1528
|
+
`RawBody` generic to specify the type of the body being parsed.
|
|
1529
|
+
|
|
1530
|
+
##### fastify.FastifyContentTypeParser< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric]>
|
|
1531
|
+
|
|
1532
|
+
[src](https://github.com/fastify/fastify/blob/main/types/content-type-parser.d.ts#L17)
|
|
1533
|
+
|
|
1534
|
+
A function type definition for specifying a body parser method. Content is typed
|
|
1535
|
+
via the `RawRequest` generic.
|
|
1536
|
+
|
|
1537
|
+
##### fastify.AddContentTypeParser< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric]>
|
|
1538
|
+
|
|
1539
|
+
[src](https://github.com/fastify/fastify/blob/main/types/content-type-parser.d.ts#L46)
|
|
1540
|
+
|
|
1541
|
+
An overloaded interface function definition for the `addContentTypeParser`
|
|
1542
|
+
method. If `parseAs` is passed to the `opts` parameter, the definition uses
|
|
1543
|
+
[FastifyBodyParser][] for the `parser` parameter; otherwise, it uses
|
|
1544
|
+
[FastifyContentTypeParser][].
|
|
1545
|
+
|
|
1546
|
+
##### fastify.hasContentTypeParser
|
|
1547
|
+
|
|
1548
|
+
[src](https://github.com/fastify/fastify/blob/main/types/content-type-parser.d.ts#L63)
|
|
1549
|
+
|
|
1550
|
+
A method for checking the existence of a type parser of a certain content type
|
|
1551
|
+
|
|
1552
|
+
---
|
|
1553
|
+
|
|
1554
|
+
#### Errors
|
|
1555
|
+
|
|
1556
|
+
##### fastify.FastifyError
|
|
1557
|
+
|
|
1558
|
+
[src](https://github.com/fastify/fastify/blob/main/fastify.d.ts#L179)
|
|
1559
|
+
|
|
1560
|
+
FastifyError is a custom error object that includes status code and validation
|
|
1561
|
+
results.
|
|
1562
|
+
|
|
1563
|
+
It extends the Node.js `Error` type, and adds two additional, optional
|
|
1564
|
+
properties: `statusCode: number` and `validation: ValidationResult[]`.
|
|
1565
|
+
|
|
1566
|
+
##### fastify.ValidationResult
|
|
1567
|
+
|
|
1568
|
+
[src](https://github.com/fastify/fastify/blob/main/fastify.d.ts#L184)
|
|
1569
|
+
|
|
1570
|
+
The route validation internally relies upon Ajv, which is a high-performance
|
|
1571
|
+
JSON schema validator.
|
|
1572
|
+
|
|
1573
|
+
This interface is passed to instance of FastifyError.
|
|
1574
|
+
|
|
1575
|
+
---
|
|
1576
|
+
|
|
1577
|
+
#### Hooks
|
|
1578
|
+
|
|
1579
|
+
##### fastify.onRequestHookHandler< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>(request: [FastifyRequest][FastifyRequest], reply: [FastifyReply][FastifyReply], done: (err?: [FastifyError][FastifyError]) => void): Promise\<unknown\> | void
|
|
1580
|
+
|
|
1581
|
+
[src](https://github.com/fastify/fastify/blob/main/types/hooks.d.ts#L17)
|
|
1582
|
+
|
|
1583
|
+
`onRequest` is the first hook to be executed in the request lifecycle. There was
|
|
1584
|
+
no previous hook, the next hook will be `preParsing`.
|
|
1585
|
+
|
|
1586
|
+
Notice: in the `onRequest` hook, request.body will always be null, because the
|
|
1587
|
+
body parsing happens before the `preHandler` hook.
|
|
1588
|
+
|
|
1589
|
+
##### fastify.preParsingHookHandler< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>(request: [FastifyRequest][FastifyRequest], reply: [FastifyReply][FastifyReply], done: (err?: [FastifyError][FastifyError]) => void): Promise\<unknown\> | void
|
|
1590
|
+
|
|
1591
|
+
[src](https://github.com/fastify/fastify/blob/main/types/hooks.d.ts#L35)
|
|
1592
|
+
|
|
1593
|
+
`preParsing` is the second hook to be executed in the request lifecycle. The
|
|
1594
|
+
previous hook was `onRequest`, the next hook will be `preValidation`.
|
|
1595
|
+
|
|
1596
|
+
Notice: in the `preParsing` hook, request.body will always be null, because the
|
|
1597
|
+
body parsing happens before the `preValidation` hook.
|
|
1598
|
+
|
|
1599
|
+
Notice: you should also add `receivedEncodedLength` property to the returned
|
|
1600
|
+
stream. This property is used to correctly match the request payload with the
|
|
1601
|
+
`Content-Length` header value. Ideally, this property should be updated on each
|
|
1602
|
+
received chunk.
|
|
1603
|
+
|
|
1604
|
+
##### 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
|
|
1605
|
+
|
|
1606
|
+
[src](https://github.com/fastify/fastify/blob/main/types/hooks.d.ts#L53)
|
|
1607
|
+
|
|
1608
|
+
`preValidation` is the third hook to be executed in the request lifecycle. The
|
|
1609
|
+
previous hook was `preParsing`, the next hook will be `preHandler`.
|
|
1610
|
+
|
|
1611
|
+
##### fastify.preHandlerHookHandler< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>(request: [FastifyRequest][FastifyRequest], reply: [FastifyReply][FastifyReply], done: (err?: [FastifyError][FastifyError]) => void): Promise\<unknown\> | void
|
|
1612
|
+
|
|
1613
|
+
[src](https://github.com/fastify/fastify/blob/main/types/hooks.d.ts#L70)
|
|
1614
|
+
|
|
1615
|
+
`preHandler` is the fourth hook to be executed in the request lifecycle. The
|
|
1616
|
+
previous hook was `preValidation`, the next hook will be `preSerialization`.
|
|
1617
|
+
|
|
1618
|
+
##### fastify.preSerializationHookHandler< PreSerializationPayload, [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>(request: [FastifyRequest][FastifyRequest], reply: [FastifyReply][FastifyReply], payload: PreSerializationPayload, done: (err: [FastifyError][FastifyError] | null, res?: unknown) => void): Promise\<unknown\> | void
|
|
1619
|
+
|
|
1620
|
+
[src](https://github.com/fastify/fastify/blob/main/types/hooks.d.ts#L94)
|
|
1621
|
+
|
|
1622
|
+
`preSerialization` is the fifth hook to be executed in the request lifecycle.
|
|
1623
|
+
The previous hook was `preHandler`, the next hook will be `onSend`.
|
|
1624
|
+
|
|
1625
|
+
> ℹ️ Note:
|
|
1626
|
+
> The hook is NOT called if the payload is a string, a Buffer,
|
|
1627
|
+
> a stream, or null.
|
|
1628
|
+
|
|
1629
|
+
##### fastify.onSendHookHandler< OnSendPayload, [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>(request: [FastifyRequest][FastifyRequest], reply: [FastifyReply][FastifyReply], payload: OnSendPayload, done: (err: [FastifyError][FastifyError] | null, res?: unknown) => void): Promise\<unknown\> | void
|
|
1630
|
+
|
|
1631
|
+
[src](https://github.com/fastify/fastify/blob/main/types/hooks.d.ts#L114)
|
|
1632
|
+
|
|
1633
|
+
You can change the payload with the `onSend` hook. It is the sixth hook to be
|
|
1634
|
+
executed in the request lifecycle. The previous hook was `preSerialization`, the
|
|
1635
|
+
next hook will be `onResponse`.
|
|
1636
|
+
|
|
1637
|
+
> ℹ️ Note:
|
|
1638
|
+
> If you change the payload, you may only change it to a string,
|
|
1639
|
+
> a Buffer, a stream, or null.
|
|
1640
|
+
|
|
1641
|
+
##### fastify.onResponseHookHandler< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>(request: [FastifyRequest][FastifyRequest], reply: [FastifyReply][FastifyReply], done: (err?: [FastifyError][FastifyError]) => void): Promise\<unknown\> | void
|
|
1642
|
+
|
|
1643
|
+
[src](https://github.com/fastify/fastify/blob/main/types/hooks.d.ts#L134)
|
|
1644
|
+
|
|
1645
|
+
`onResponse` is the seventh and last hook in the request hook lifecycle. The
|
|
1646
|
+
previous hook was `onSend`, there is no next hook.
|
|
1647
|
+
|
|
1648
|
+
The onResponse hook is executed when a response has been sent, so you will not
|
|
1649
|
+
be able to send more data to the client. It can however be useful for sending
|
|
1650
|
+
data to external services, for example to gather statistics.
|
|
1651
|
+
|
|
1652
|
+
##### fastify.onErrorHookHandler< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>(request: [FastifyRequest][FastifyRequest], reply: [FastifyReply][FastifyReply], error: [FastifyError][FastifyError], done: () => void): Promise\<unknown\> | void
|
|
1653
|
+
|
|
1654
|
+
[src](https://github.com/fastify/fastify/blob/main/types/hooks.d.ts#L154)
|
|
1655
|
+
|
|
1656
|
+
This hook is useful if you need to do some custom error logging or add some
|
|
1657
|
+
specific header in case of error.
|
|
1658
|
+
|
|
1659
|
+
It is not intended for changing the error, and calling reply.send will throw an
|
|
1660
|
+
exception.
|
|
1661
|
+
|
|
1662
|
+
This hook will be executed before the customErrorHandler.
|
|
1663
|
+
|
|
1664
|
+
Notice: unlike the other hooks, pass an error to the done function is not
|
|
1665
|
+
supported.
|
|
1666
|
+
|
|
1667
|
+
##### fastify.onRouteHookHandler< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [RequestGeneric][FastifyRequestGenericInterface], [ContextConfig][ContextConfigGeneric]>(opts: [RouteOptions][RouteOptions] & \{ path: string; prefix: string }): Promise\<unknown\> | void
|
|
1668
|
+
|
|
1669
|
+
[src](https://github.com/fastify/fastify/blob/main/types/hooks.d.ts#L174)
|
|
1670
|
+
|
|
1671
|
+
Triggered when a new route is registered. Listeners are passed a routeOptions
|
|
1672
|
+
object as the sole parameter. The interface is synchronous, and, as such, the
|
|
1673
|
+
listener does not get passed a callback
|
|
1674
|
+
|
|
1675
|
+
##### fastify.onRegisterHookHandler< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [Logger][LoggerGeneric]>(instance: [FastifyInstance][FastifyInstance], done: (err?: [FastifyError][FastifyError]) => void): Promise\<unknown\> | void
|
|
1676
|
+
|
|
1677
|
+
[src](https://github.com/fastify/fastify/blob/main/types/hooks.d.ts#L191)
|
|
1678
|
+
|
|
1679
|
+
Triggered when a new plugin is registered and a new encapsulation context is
|
|
1680
|
+
created. The hook will be executed before the registered code.
|
|
1681
|
+
|
|
1682
|
+
This hook can be useful if you are developing a plugin that needs to know when a
|
|
1683
|
+
plugin context is formed, and you want to operate in that specific context.
|
|
1684
|
+
|
|
1685
|
+
> ℹ️ Note:
|
|
1686
|
+
> This hook will not be called if a plugin is wrapped inside fastify-plugin.
|
|
1687
|
+
|
|
1688
|
+
##### fastify.onCloseHookHandler< [RawServer][RawServerGeneric], [RawRequest][RawRequestGeneric], [RawReply][RawReplyGeneric], [Logger][LoggerGeneric]>(instance: [FastifyInstance][FastifyInstance], done: (err?: [FastifyError][FastifyError]) => void): Promise\<unknown\> | void
|
|
1689
|
+
|
|
1690
|
+
[src](https://github.com/fastify/fastify/blob/main/types/hooks.d.ts#L206)
|
|
1691
|
+
|
|
1692
|
+
Triggered when fastify.close() is invoked to stop the server. It is useful when
|
|
1693
|
+
plugins need a "shutdown" event, for example to close an open connection to a
|
|
1694
|
+
database.
|
|
1695
|
+
|
|
1696
|
+
|
|
1697
|
+
<!-- Links -->
|
|
1698
|
+
|
|
1699
|
+
[Fastify]:
|
|
1700
|
+
#fastifyrawserver-rawrequest-rawreply-loggeropts-fastifyserveroptions-fastifyinstance
|
|
1701
|
+
[RawServerGeneric]: #rawserver
|
|
1702
|
+
[RawRequestGeneric]: #rawrequest
|
|
1703
|
+
[RawReplyGeneric]: #rawreply
|
|
1704
|
+
[LoggerGeneric]: #logger
|
|
1705
|
+
[RawBodyGeneric]: #rawbody
|
|
1706
|
+
[HTTPMethods]: #fastifyhttpmethods
|
|
1707
|
+
[RawServerBase]: #fastifyrawserverbase
|
|
1708
|
+
[RawServerDefault]: #fastifyrawserverdefault
|
|
1709
|
+
[FastifyRequest]: #fastifyfastifyrequestrawserver-rawrequest-requestgeneric
|
|
1710
|
+
[FastifyRequestGenericInterface]: #fastifyrequestgenericinterface
|
|
1711
|
+
[RawRequestDefaultExpression]: #fastifyrawrequestdefaultexpressionrawserver
|
|
1712
|
+
[FastifyReply]: #fastifyfastifyreplyrawserver-rawreply-contextconfig
|
|
1713
|
+
[RawReplyDefaultExpression]: #fastifyrawreplydefaultexpression
|
|
1714
|
+
[FastifyServerOptions]: #fastifyfastifyserveroptions-rawserver-logger
|
|
1715
|
+
[FastifyInstance]: #fastifyfastifyinstance
|
|
1716
|
+
[FastifyLoggerOptions]: #fastifyfastifyloggeroptions
|
|
1717
|
+
[ContextConfigGeneric]: #ContextConfigGeneric
|
|
1718
|
+
[FastifyPlugin]:
|
|
1719
|
+
#fastifyfastifypluginoptions-rawserver-rawrequest-requestgeneric
|
|
1720
|
+
[FastifyPluginCallback]: #fastifyfastifyplugincallbackoptions
|
|
1721
|
+
[FastifyPluginAsync]: #fastifyfastifypluginasyncoptions
|
|
1722
|
+
[FastifyPluginOptions]: #fastifyfastifypluginoptions
|
|
1723
|
+
[FastifyRegister]:
|
|
1724
|
+
#fastifyfastifyregisterrawserver-rawrequest-requestgenericplugin-fastifyplugin-opts-fastifyregisteroptions
|
|
1725
|
+
[FastifyRegisterOptions]: #fastifyfastifytregisteroptions
|
|
1726
|
+
[LogLevel]: #fastifyloglevel
|
|
1727
|
+
[FastifyError]: #fastifyfastifyerror
|
|
1728
|
+
[RouteOptions]:
|
|
1729
|
+
#fastifyrouteoptionsrawserver-rawrequest-rawreply-requestgeneric-contextconfig
|