fastify 4.5.3 → 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/Guides/Ecosystem.md +23 -8
- package/docs/Guides/Migration-Guide-V4.md +97 -48
- package/docs/Guides/Write-Plugin.md +1 -1
- package/docs/Reference/Logging.md +16 -13
- package/docs/Reference/Server.md +24 -2
- package/docs/Reference/Type-Providers.md +2 -16
- package/docs/Reference/TypeScript.md +7 -14
- package/examples/typescript-server.ts +1 -1
- package/fastify.d.ts +2 -2
- package/fastify.js +4 -1
- package/lib/error-serializer.js +13 -40
- package/lib/route.js +9 -0
- package/lib/schemas.js +1 -0
- package/lib/server.js +6 -1
- package/package.json +2 -2
- package/test/has-route.test.js +77 -0
- package/test/listen.deprecated.test.js +33 -0
- package/test/schema-special-usage.test.js +29 -0
- package/test/types/fastify.test-d.ts +9 -0
- package/test/types/route.test-d.ts +11 -0
- package/test/unsupported-httpversion.test.js +0 -26
- package/types/hooks.d.ts +25 -25
- package/types/instance.d.ts +27 -21
- package/types/logger.d.ts +1 -1
- package/types/plugin.d.ts +3 -3
- package/types/reply.d.ts +2 -2
- package/types/request.d.ts +2 -2
- package/types/route.d.ts +9 -9
package/docs/Guides/Ecosystem.md
CHANGED
|
@@ -75,6 +75,9 @@ section.
|
|
|
75
75
|
connection pool across every part of your server.
|
|
76
76
|
- [`@fastify/multipart`](https://github.com/fastify/fastify-multipart) Multipart
|
|
77
77
|
support for Fastify.
|
|
78
|
+
- [`@fastify/nextjs`](https://github.com/fastify/fastify-nextjs) React
|
|
79
|
+
server-side rendering support for Fastify with
|
|
80
|
+
[Next](https://github.com/zeit/next.js/).
|
|
78
81
|
- [`@fastify/oauth2`](https://github.com/fastify/fastify-oauth2) Wrap around
|
|
79
82
|
[`simple-oauth2`](https://github.com/lelylan/simple-oauth2).
|
|
80
83
|
- [`@fastify/postgres`](https://github.com/fastify/fastify-postgres) Fastify
|
|
@@ -82,6 +85,11 @@ section.
|
|
|
82
85
|
connection pool in every part of your server.
|
|
83
86
|
- [`@fastify/rate-limit`](https://github.com/fastify/fastify-rate-limit) A low
|
|
84
87
|
overhead rate limiter for your routes.
|
|
88
|
+
- [`@fastify/redis`](https://github.com/fastify/fastify-redis) Fastify Redis
|
|
89
|
+
connection plugin, with which you can share the same Redis connection across
|
|
90
|
+
every part of your server.
|
|
91
|
+
- [`@fastify/reply-from`](https://github.com/fastify/fastify-reply-from) Plugin
|
|
92
|
+
to forward the current HTTP request to another server.
|
|
85
93
|
- [`@fastify/request-context`](https://github.com/fastify/fastify-request-context)
|
|
86
94
|
Request-scoped storage, based on
|
|
87
95
|
[AsyncLocalStorage](https://nodejs.org/api/async_hooks.html#async_hooks_class_asynclocalstorage)
|
|
@@ -89,14 +97,6 @@ section.
|
|
|
89
97
|
providing functionality similar to thread-local storages.
|
|
90
98
|
- [`@fastify/response-validation`](https://github.com/fastify/fastify-response-validation)
|
|
91
99
|
A simple plugin that enables response validation for Fastify.
|
|
92
|
-
- [`@fastify/nextjs`](https://github.com/fastify/fastify-nextjs) React
|
|
93
|
-
server-side rendering support for Fastify with
|
|
94
|
-
[Next](https://github.com/zeit/next.js/).
|
|
95
|
-
- [`@fastify/redis`](https://github.com/fastify/fastify-redis) Fastify Redis
|
|
96
|
-
connection plugin, with which you can share the same Redis connection across
|
|
97
|
-
every part of your server.
|
|
98
|
-
- [`@fastify/reply-from`](https://github.com/fastify/fastify-reply-from) Plugin
|
|
99
|
-
to forward the current HTTP request to another server.
|
|
100
100
|
- [`@fastify/routes`](https://github.com/fastify/fastify-routes) Plugin that
|
|
101
101
|
provides a `Map` of routes.
|
|
102
102
|
- [`@fastify/schedule`](https://github.com/fastify/fastify-schedule) Plugin for
|
|
@@ -146,6 +146,13 @@ section.
|
|
|
146
146
|
close the server gracefully on `SIGINT` and `SIGTERM` signals.
|
|
147
147
|
- [`@eropple/fastify-openapi3`](https://github.com/eropple/fastify-openapi3) Provides
|
|
148
148
|
easy, developer-friendly OpenAPI 3.1 specs + doc explorer based on your routes.
|
|
149
|
+
- [`@ethicdevs/fastify-custom-session`](https://github.com/EthicDevs/fastify-custom-session)
|
|
150
|
+
A plugin that let you use session and decide only where to load/save from/to. Has
|
|
151
|
+
great TypeScript support + built-in adapters for common ORMs/databases (Firebase,
|
|
152
|
+
Prisma Client, Postgres (wip), InMemory) and you can easily make your own adapter!
|
|
153
|
+
- [`@ethicdevs/fastify-git-server`](https://github.com/EthicDevs/fastify-git-server)
|
|
154
|
+
A plugin to easily create git server and make one/many Git repositories available
|
|
155
|
+
for clone/fetch/push through the standard `git` (over http) commands.
|
|
149
156
|
- [`@gquittet/graceful-server`](https://github.com/gquittet/graceful-server)
|
|
150
157
|
Tiny (~5k), Fast, KISS, and dependency-free Node.JS library to make your
|
|
151
158
|
Fastify API graceful.
|
|
@@ -216,6 +223,12 @@ section.
|
|
|
216
223
|
- [`fastify-autoroutes`](https://github.com/GiovanniCardamone/fastify-autoroutes)
|
|
217
224
|
Plugin to scan and load routes based on filesystem path from a custom
|
|
218
225
|
directory.
|
|
226
|
+
- [`fastify-aws-sns`](https://github.com/gzileni/fastify-aws-sns) Fastify plugin
|
|
227
|
+
for AWS Simple Notification Service (AWS SNS) that coordinates and manages
|
|
228
|
+
the delivery or sending of messages to subscribing endpoints or clients.
|
|
229
|
+
- [`fastify-aws-timestream`](https://github.com/gzileni/fastify-aws-timestream)
|
|
230
|
+
Fastify plugin for managing databases, tables, and querying and creating
|
|
231
|
+
scheduled queries with AWS Timestream.
|
|
219
232
|
- [`fastify-axios`](https://github.com/davidedantonio/fastify-axios) Plugin to
|
|
220
233
|
send HTTP requests via [axios](https://github.com/axios/axios).
|
|
221
234
|
- [`fastify-babel`](https://github.com/cfware/fastify-babel) Fastify plugin for
|
|
@@ -574,6 +587,8 @@ section.
|
|
|
574
587
|
- [`openapi-validator-middleware`](https://github.com/PayU/openapi-validator-middleware#fastify)
|
|
575
588
|
Swagger and OpenAPI 3.0 spec-based request validation middleware that supports
|
|
576
589
|
Fastify.
|
|
590
|
+
- [`pubsub-http-handler`](https://github.com/cobraz/pubsub-http-handler) A Fastify
|
|
591
|
+
plugin to easily create Google Cloud PubSub endpoints.
|
|
577
592
|
- [`sequelize-fastify`](https://github.com/hsynlms/sequelize-fastify) A simple
|
|
578
593
|
and lightweight Sequelize plugin for Fastify.
|
|
579
594
|
- [`typeorm-fastify-plugin`](https://github.com/jclemens24/fastify-typeorm) A simple
|
|
@@ -10,12 +10,11 @@ work after upgrading.
|
|
|
10
10
|
|
|
11
11
|
### Error handling composition ([#3261](https://github.com/fastify/fastify/pull/3261))
|
|
12
12
|
|
|
13
|
-
When an error is thrown in
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
be executed as it was previously.
|
|
13
|
+
When an error is thrown in an async error handler function, the upper-level
|
|
14
|
+
error handler is executed if set. If there is no upper-level error handler,
|
|
15
|
+
the default will be executed as it was previously:
|
|
17
16
|
|
|
18
|
-
```
|
|
17
|
+
```js
|
|
19
18
|
import Fastify from 'fastify'
|
|
20
19
|
|
|
21
20
|
const fastify = Fastify()
|
|
@@ -40,75 +39,125 @@ const res = await fastify.inject('/encapsulated')
|
|
|
40
39
|
console.log(res.json().message) // 'wrapped'
|
|
41
40
|
```
|
|
42
41
|
|
|
43
|
-
###
|
|
42
|
+
### Removed `app.use()` ([#3506](https://github.com/fastify/fastify/pull/3506))
|
|
43
|
+
|
|
44
|
+
With v4 of Fastify, `app.use()` has been removed and the use of middleware is
|
|
45
|
+
no longer supported.
|
|
44
46
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
[`@fastify/
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
If you need to use middleware, use
|
|
48
|
+
[`@fastify/middie`](https://github.com/fastify/middie) or
|
|
49
|
+
[`@fastify/express`](https://github.com/fastify/fastify-express), which will
|
|
50
|
+
continue to be maintained.
|
|
51
|
+
However, it is strongly recommended that you migrate to Fastify's [hooks](../Reference/Hooks.md).
|
|
50
52
|
|
|
51
53
|
### `reply.res` moved to `reply.raw`
|
|
52
54
|
|
|
53
55
|
If you previously used the `reply.res` attribute to access the underlying Request
|
|
54
|
-
object you
|
|
56
|
+
object you will now need to use `reply.raw`.
|
|
55
57
|
|
|
56
58
|
### Need to `return reply` to signal a "fork" of the promise chain
|
|
57
59
|
|
|
58
|
-
In some situations, like when a response is sent asynchronously or when you
|
|
59
|
-
|
|
60
|
+
In some situations, like when a response is sent asynchronously or when you are
|
|
61
|
+
not explicitly returning a response, you will now need to return the `reply`
|
|
60
62
|
argument from your router handler.
|
|
61
63
|
|
|
62
64
|
### `exposeHeadRoutes` true by default
|
|
63
65
|
|
|
64
|
-
Starting
|
|
65
|
-
You can revert this
|
|
66
|
-
to `false`.
|
|
66
|
+
Starting with v4, every `GET` route will create a sibling `HEAD` route.
|
|
67
|
+
You can revert this behavior by setting `exposeHeadRoutes: false` in the server options.
|
|
67
68
|
|
|
68
|
-
### Synchronous route definitions
|
|
69
|
+
### Synchronous route definitions ([#2954](https://github.com/fastify/fastify/pull/2954))
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
As a result if you specify an `onRoute` hook in a plugin you should either:
|
|
71
|
+
To improve error reporting in route definitions, route registration is now synchronous.
|
|
72
|
+
As a result, if you specify an `onRoute` hook in a plugin you should now either:
|
|
73
73
|
* wrap your routes in a plugin (recommended)
|
|
74
|
+
|
|
75
|
+
For example, refactor this:
|
|
76
|
+
```js
|
|
77
|
+
fastify.register((instance, opts, done) => {
|
|
78
|
+
instance.addHook('onRoute', (routeOptions) => {
|
|
79
|
+
const { path, method } = routeOptions;
|
|
80
|
+
console.log({ path, method });
|
|
81
|
+
done();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
fastify.get('/', (request, reply) => { reply.send('hello') });
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Into this:
|
|
89
|
+
```js
|
|
90
|
+
fastify.register((instance, opts, done) => {
|
|
91
|
+
instance.addHook('onRoute', (routeOptions) => {
|
|
92
|
+
const { path, method } = routeOptions;
|
|
93
|
+
console.log({ path, method });
|
|
94
|
+
done();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
fastify.register((instance, opts, done) => {
|
|
99
|
+
instance.get('/', (request, reply) => { reply.send('hello') });
|
|
100
|
+
done();
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
74
104
|
* use `await register(...)`
|
|
75
105
|
|
|
76
|
-
For example refactor this:
|
|
77
|
-
```
|
|
78
|
-
fastify.register((instance, opts, done) => {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
106
|
+
For example, refactor this:
|
|
107
|
+
```js
|
|
108
|
+
fastify.register((instance, opts, done) => {
|
|
109
|
+
instance.addHook('onRoute', (routeOptions) => {
|
|
110
|
+
const { path, method } = routeOptions;
|
|
111
|
+
console.log({ path, method });
|
|
112
|
+
});
|
|
113
|
+
done();
|
|
82
114
|
});
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Into this:
|
|
118
|
+
```js
|
|
119
|
+
await fastify.register((instance, opts) => {
|
|
120
|
+
instance.addHook('onRoute', (routeOptions) => {
|
|
121
|
+
const { path, method } = routeOptions;
|
|
122
|
+
console.log({ path, method });
|
|
123
|
+
});
|
|
124
|
+
done();
|
|
92
125
|
});
|
|
93
|
-
|
|
94
|
-
});
|
|
95
|
-
```
|
|
126
|
+
```
|
|
96
127
|
|
|
97
|
-
## Non
|
|
128
|
+
## Non-Breaking Changes
|
|
98
129
|
|
|
99
|
-
###
|
|
130
|
+
### Deprecation of variadic `.listen()` signature
|
|
100
131
|
|
|
132
|
+
The [variadic signature](https://en.wikipedia.org/wiki/Variadic_function) of the
|
|
133
|
+
`fastify.listen()` method is now deprecated.
|
|
101
134
|
|
|
102
|
-
|
|
103
|
-
(other than with "null") are prohibited. Read more
|
|
104
|
-
['here'](https://ajv.js.org/strict-mode.html#strict-types)
|
|
135
|
+
Prior to this release, the following invocations of this method were valid:
|
|
105
136
|
|
|
106
|
-
|
|
137
|
+
- `fastify.listen(8000)`
|
|
138
|
+
- `fastify.listen(8000, ‘127.0.0.1’)`
|
|
139
|
+
- `fastify.listen(8000, ‘127.0.0.1’, 511)`
|
|
140
|
+
- `fastify.listen(8000, (err) => { if (err) throw err })`
|
|
141
|
+
- `fastify.listen({ port: 8000 }, (err) => { if (err) throw err })`
|
|
107
142
|
|
|
108
|
-
|
|
143
|
+
With Fastify v4, only the following invocations are valid:
|
|
144
|
+
|
|
145
|
+
- `fastify.listen()`
|
|
146
|
+
- `fastify.listen({ port: 8000 })`
|
|
147
|
+
- `fastify.listen({ port: 8000 }, (err) => { if (err) throw err })`
|
|
148
|
+
|
|
149
|
+
### Change of schema for multiple types
|
|
150
|
+
|
|
151
|
+
Ajv has been upgraded to v8 in Fastify v4, meaning "type" keywords with multiple
|
|
152
|
+
types other than "null"
|
|
153
|
+
[are now prohibited](https://ajv.js.org/strict-mode.html#strict-types).
|
|
154
|
+
|
|
155
|
+
You may encounter a console warning such as:
|
|
156
|
+
```sh
|
|
109
157
|
strict mode: use allowUnionTypes to allow union type keyword at "#/properties/image" (strictTypes)
|
|
110
158
|
```
|
|
111
|
-
|
|
159
|
+
|
|
160
|
+
As such, schemas like below will need to be changed from:
|
|
112
161
|
```
|
|
113
162
|
type: 'object',
|
|
114
163
|
properties: {
|
|
@@ -117,8 +166,8 @@ properties: {
|
|
|
117
166
|
}
|
|
118
167
|
}
|
|
119
168
|
```
|
|
120
|
-
to
|
|
121
169
|
|
|
170
|
+
Into:
|
|
122
171
|
```
|
|
123
172
|
type: 'object',
|
|
124
173
|
properties: {
|
|
@@ -80,7 +80,7 @@ to show that the plugin works as intended. Both
|
|
|
80
80
|
Actions](https://github.com/features/actions) are free for open source projects
|
|
81
81
|
and easy to set up.
|
|
82
82
|
|
|
83
|
-
In addition, you can enable services like [Dependabot](https://
|
|
83
|
+
In addition, you can enable services like [Dependabot](https://github.com/dependabot),
|
|
84
84
|
which will help you keep your dependencies up to date and discover if a new
|
|
85
85
|
release of Fastify has some issues with your plugin.
|
|
86
86
|
|
|
@@ -22,21 +22,24 @@ const fastify = require('fastify')({
|
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
Enabling the logger with appropriate configuration for both local development
|
|
25
|
-
and production environment requires bit more configuration:
|
|
25
|
+
and production and test environment requires bit more configuration:
|
|
26
|
+
|
|
26
27
|
```js
|
|
28
|
+
const envToLogger = {
|
|
29
|
+
development: {
|
|
30
|
+
transport: {
|
|
31
|
+
target: 'pino-pretty',
|
|
32
|
+
options: {
|
|
33
|
+
translateTime: 'HH:MM:ss Z',
|
|
34
|
+
ignore: 'pid,hostname',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
production: true,
|
|
39
|
+
test: false,
|
|
40
|
+
}
|
|
27
41
|
const fastify = require('fastify')({
|
|
28
|
-
logger:
|
|
29
|
-
transport:
|
|
30
|
-
environment === 'development'
|
|
31
|
-
? {
|
|
32
|
-
target: 'pino-pretty',
|
|
33
|
-
options: {
|
|
34
|
-
translateTime: 'HH:MM:ss Z',
|
|
35
|
-
ignore: 'pid,hostname'
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
: undefined
|
|
39
|
-
}
|
|
42
|
+
logger: envToLogger[environment] ?? true // defaults to true if no entry matches in the map
|
|
40
43
|
})
|
|
41
44
|
```
|
|
42
45
|
⚠️ `pino-pretty` needs to be installed as a dev dependency, it is not included
|
package/docs/Reference/Server.md
CHANGED
|
@@ -54,6 +54,7 @@ describes the properties available in that options object.
|
|
|
54
54
|
- [setDefaultRoute](#setdefaultroute)
|
|
55
55
|
- [routing](#routing)
|
|
56
56
|
- [route](#route)
|
|
57
|
+
- [hasRoute](#hasRoute)
|
|
57
58
|
- [close](#close)
|
|
58
59
|
- [decorate*](#decorate)
|
|
59
60
|
- [register](#register)
|
|
@@ -667,7 +668,7 @@ the incoming request as usual.
|
|
|
667
668
|
|
|
668
669
|
Configure the Ajv v8 instance used by Fastify without providing a custom one.
|
|
669
670
|
The default configuration is explained in the
|
|
670
|
-
[#schema-validator](Validation-and-Serialization.md#schema-validator) section.
|
|
671
|
+
[#schema-validator](./Validation-and-Serialization.md#schema-validator) section.
|
|
671
672
|
|
|
672
673
|
```js
|
|
673
674
|
const fastify = require('fastify')({
|
|
@@ -1020,7 +1021,8 @@ const defaultRoute = fastify.getDefaultRoute()
|
|
|
1020
1021
|
<a id="setDefaultRoute"></a>
|
|
1021
1022
|
|
|
1022
1023
|
**Note**: The default 404 handler, or one set using `setNotFoundHandler`, will
|
|
1023
|
-
never trigger if the default route is overridden.
|
|
1024
|
+
never trigger if the default route is overridden. This sets the handler for the
|
|
1025
|
+
Fastify application, not just the current instance context. Use
|
|
1024
1026
|
[setNotFoundHandler](#setnotfoundhandler) if you want to customize 404 handling
|
|
1025
1027
|
instead. Method to set the `defaultRoute` for the server:
|
|
1026
1028
|
|
|
@@ -1048,6 +1050,26 @@ fastify.routing(req, res)
|
|
|
1048
1050
|
Method to add routes to the server, it also has shorthand functions, check
|
|
1049
1051
|
[here](./Routes.md).
|
|
1050
1052
|
|
|
1053
|
+
#### hasRoute
|
|
1054
|
+
<a id="hasRoute"></a>
|
|
1055
|
+
|
|
1056
|
+
Method to check if a route is already registered to the internal router. It
|
|
1057
|
+
expects an object as payload. `url` and `method` are mandatory fields. It is
|
|
1058
|
+
possible to also specify `constraints`. The method returns true if the route is
|
|
1059
|
+
registered, and false if it is not registered.
|
|
1060
|
+
|
|
1061
|
+
```js
|
|
1062
|
+
const routeExists = fastify.hasRoute({
|
|
1063
|
+
url: '/',
|
|
1064
|
+
method: 'GET',
|
|
1065
|
+
constraints: { version: '1.0.0' } // optional
|
|
1066
|
+
})
|
|
1067
|
+
|
|
1068
|
+
if (routeExists === false) {
|
|
1069
|
+
// add route
|
|
1070
|
+
}
|
|
1071
|
+
```
|
|
1072
|
+
|
|
1051
1073
|
#### close
|
|
1052
1074
|
<a id="close"></a>
|
|
1053
1075
|
|
|
@@ -155,14 +155,7 @@ import Fastify from 'fastify'
|
|
|
155
155
|
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
|
|
156
156
|
import { Type } from '@sinclair/typebox'
|
|
157
157
|
|
|
158
|
-
const server = Fastify(
|
|
159
|
-
ajv: {
|
|
160
|
-
customOptions: {
|
|
161
|
-
strict: 'log',
|
|
162
|
-
keywords: ['kind', 'modifier'],
|
|
163
|
-
},
|
|
164
|
-
},
|
|
165
|
-
}).withTypeProvider<TypeBoxTypeProvider>()
|
|
158
|
+
const server = Fastify().withTypeProvider<TypeBoxTypeProvider>()
|
|
166
159
|
|
|
167
160
|
server.register(plugin1) // wrong
|
|
168
161
|
server.register(plugin2) // correct
|
|
@@ -213,14 +206,7 @@ import Fastify from 'fastify'
|
|
|
213
206
|
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
|
|
214
207
|
import { registerRoutes } from './routes'
|
|
215
208
|
|
|
216
|
-
const server = Fastify(
|
|
217
|
-
ajv: {
|
|
218
|
-
customOptions: {
|
|
219
|
-
strict: 'log',
|
|
220
|
-
keywords: ['kind', 'modifier'],
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
|
-
}).withTypeProvider<TypeBoxTypeProvider>()
|
|
209
|
+
const server = Fastify().withTypeProvider<TypeBoxTypeProvider>()
|
|
224
210
|
|
|
225
211
|
registerRoutes(server)
|
|
226
212
|
|
|
@@ -61,6 +61,11 @@ in a blank http Fastify server.
|
|
|
61
61
|
*Note: Set `target` property in `tsconfig.json` to `es2017` or greater to avoid
|
|
62
62
|
[FastifyDeprecation](https://github.com/fastify/fastify/issues/3284) warning.*
|
|
63
63
|
|
|
64
|
+
*Note 2: Avoid using ```"moduleResolution": "NodeNext"``` in tsconfig.json with
|
|
65
|
+
```"type": "module"``` in package.json. This combination is currently not
|
|
66
|
+
supported by fastify typing system.
|
|
67
|
+
[ts(2349)](https://github.com/fastify/fastify/issues/4241) warning.*
|
|
68
|
+
|
|
64
69
|
4. Create an `index.ts` file - this will contain the server code
|
|
65
70
|
5. Add the following code block to your file:
|
|
66
71
|
```typescript
|
|
@@ -254,18 +259,6 @@ can do it as follows:
|
|
|
254
259
|
)
|
|
255
260
|
```
|
|
256
261
|
|
|
257
|
-
**Note** For Ajv version 7 and above is required to use the `ajvTypeBoxPlugin`:
|
|
258
|
-
|
|
259
|
-
```typescript
|
|
260
|
-
import Fastify from 'fastify'
|
|
261
|
-
import { ajvTypeBoxPlugin, TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
|
|
262
|
-
|
|
263
|
-
const fastify = Fastify({
|
|
264
|
-
ajv: {
|
|
265
|
-
plugins: [ajvTypeBoxPlugin]
|
|
266
|
-
}
|
|
267
|
-
}).withTypeProvider<TypeBoxTypeProvider>()
|
|
268
|
-
```
|
|
269
262
|
|
|
270
263
|
#### Schemas in JSON Files
|
|
271
264
|
|
|
@@ -1237,8 +1230,8 @@ const plugin: FastifyPlugin<{
|
|
|
1237
1230
|
option2: boolean;
|
|
1238
1231
|
}> = function (instance, opts, done) { }
|
|
1239
1232
|
|
|
1240
|
-
|
|
1241
|
-
|
|
1233
|
+
server().register(plugin, {}) // Error - options object is missing required properties
|
|
1234
|
+
server().register(plugin, { option1: '', option2: true }) // OK - options object contains required properties
|
|
1242
1235
|
```
|
|
1243
1236
|
|
|
1244
1237
|
See the Learn By Example, [Plugins](#plugins) section for more detailed examples
|
package/fastify.d.ts
CHANGED
|
@@ -84,7 +84,7 @@ export type FastifyHttpsOptions<
|
|
|
84
84
|
Server extends https.Server,
|
|
85
85
|
Logger extends FastifyBaseLogger = FastifyLoggerInstance
|
|
86
86
|
> = FastifyServerOptions<Server, Logger> & {
|
|
87
|
-
https: https.ServerOptions
|
|
87
|
+
https: https.ServerOptions | null
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
type FindMyWayVersion<RawServer extends RawServerBase> = RawServer extends http.Server ? HTTPVersion.V1 : HTTPVersion.V2
|
|
@@ -197,7 +197,7 @@ export { FastifyPluginCallback, FastifyPluginAsync, FastifyPluginOptions, Fastif
|
|
|
197
197
|
export { FastifyListenOptions, FastifyInstance, PrintRoutesOptions } from './types/instance'
|
|
198
198
|
export { FastifyLoggerOptions, FastifyBaseLogger, FastifyLoggerInstance, FastifyLogFn, LogLevel } from './types/logger'
|
|
199
199
|
export { FastifyContext, FastifyContextConfig } from './types/context'
|
|
200
|
-
export { RouteHandler, RouteHandlerMethod, RouteOptions, RouteShorthandMethod, RouteShorthandOptions, RouteShorthandOptionsWithHandler } from './types/route'
|
|
200
|
+
export { RouteHandler, RouteHandlerMethod, RouteOptions, RouteShorthandMethod, RouteShorthandOptions, RouteShorthandOptionsWithHandler, RouteGenericInterface } from './types/route'
|
|
201
201
|
export * from './types/register'
|
|
202
202
|
export { FastifyBodyParser, FastifyContentTypeParser, AddContentTypeParser, hasContentTypeParser, getDefaultJsonParser, ProtoAction, ConstructorAction } from './types/content-type-parser'
|
|
203
203
|
export { FastifyError } from '@fastify/error'
|
package/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const VERSION = '4.
|
|
3
|
+
const VERSION = '4.6.0'
|
|
4
4
|
|
|
5
5
|
const Avvio = require('avvio')
|
|
6
6
|
const http = require('http')
|
|
@@ -267,6 +267,9 @@ function fastify (options) {
|
|
|
267
267
|
// otherwise we should bind it after the declaration
|
|
268
268
|
return router.route.call(this, { options })
|
|
269
269
|
},
|
|
270
|
+
hasRoute: function _route (options) {
|
|
271
|
+
return router.hasRoute.call(this, { options })
|
|
272
|
+
},
|
|
270
273
|
// expose logger instance
|
|
271
274
|
log: logger,
|
|
272
275
|
// type provider
|
package/lib/error-serializer.js
CHANGED
|
@@ -23,14 +23,6 @@ class Serializer {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
asAny (i) {
|
|
27
|
-
return JSON.stringify(i)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
asNull () {
|
|
31
|
-
return 'null'
|
|
32
|
-
}
|
|
33
|
-
|
|
34
26
|
asInteger (i) {
|
|
35
27
|
if (typeof i === 'bigint') {
|
|
36
28
|
return i.toString()
|
|
@@ -47,10 +39,6 @@ class Serializer {
|
|
|
47
39
|
}
|
|
48
40
|
}
|
|
49
41
|
|
|
50
|
-
asIntegerNullable (i) {
|
|
51
|
-
return i === null ? 'null' : this.asInteger(i)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
42
|
asNumber (i) {
|
|
55
43
|
const num = Number(i)
|
|
56
44
|
if (Number.isNaN(num)) {
|
|
@@ -62,54 +50,43 @@ class Serializer {
|
|
|
62
50
|
}
|
|
63
51
|
}
|
|
64
52
|
|
|
65
|
-
asNumberNullable (i) {
|
|
66
|
-
return i === null ? 'null' : this.asNumber(i)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
53
|
asBoolean (bool) {
|
|
70
54
|
return bool && 'true' || 'false' // eslint-disable-line
|
|
71
55
|
}
|
|
72
56
|
|
|
73
|
-
asBooleanNullable (bool) {
|
|
74
|
-
return bool === null ? 'null' : this.asBoolean(bool)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
57
|
asDateTime (date) {
|
|
78
58
|
if (date === null) return '""'
|
|
79
59
|
if (date instanceof Date) {
|
|
80
60
|
return '"' + date.toISOString() + '"'
|
|
81
61
|
}
|
|
62
|
+
if (typeof date === 'string') {
|
|
63
|
+
return '"' + date + '"'
|
|
64
|
+
}
|
|
82
65
|
throw new Error(`The value "${date}" cannot be converted to a date-time.`)
|
|
83
66
|
}
|
|
84
67
|
|
|
85
|
-
asDateTimeNullable (date) {
|
|
86
|
-
return date === null ? 'null' : this.asDateTime(date)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
68
|
asDate (date) {
|
|
90
69
|
if (date === null) return '""'
|
|
91
70
|
if (date instanceof Date) {
|
|
92
71
|
return '"' + new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(0, 10) + '"'
|
|
93
72
|
}
|
|
73
|
+
if (typeof date === 'string') {
|
|
74
|
+
return '"' + date + '"'
|
|
75
|
+
}
|
|
94
76
|
throw new Error(`The value "${date}" cannot be converted to a date.`)
|
|
95
77
|
}
|
|
96
78
|
|
|
97
|
-
asDateNullable (date) {
|
|
98
|
-
return date === null ? 'null' : this.asDate(date)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
79
|
asTime (date) {
|
|
102
80
|
if (date === null) return '""'
|
|
103
81
|
if (date instanceof Date) {
|
|
104
82
|
return '"' + new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString().slice(11, 19) + '"'
|
|
105
83
|
}
|
|
84
|
+
if (typeof date === 'string') {
|
|
85
|
+
return '"' + date + '"'
|
|
86
|
+
}
|
|
106
87
|
throw new Error(`The value "${date}" cannot be converted to a time.`)
|
|
107
88
|
}
|
|
108
89
|
|
|
109
|
-
asTimeNullable (date) {
|
|
110
|
-
return date === null ? 'null' : this.asTime(date)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
90
|
asString (str) {
|
|
114
91
|
const quotes = '"'
|
|
115
92
|
if (str instanceof Date) {
|
|
@@ -129,10 +106,6 @@ class Serializer {
|
|
|
129
106
|
}
|
|
130
107
|
}
|
|
131
108
|
|
|
132
|
-
asStringNullable (str) {
|
|
133
|
-
return str === null ? 'null' : this.asString(str)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
109
|
// magically escape strings for json
|
|
137
110
|
// relying on their charCodeAt
|
|
138
111
|
// everything below 32 needs JSON.stringify()
|
|
@@ -200,7 +173,7 @@ class Serializer {
|
|
|
200
173
|
}
|
|
201
174
|
|
|
202
175
|
json += "\"statusCode\"" + ':'
|
|
203
|
-
json += serializer.asNumber
|
|
176
|
+
json += serializer.asNumber(obj["statusCode"])
|
|
204
177
|
}
|
|
205
178
|
|
|
206
179
|
if (obj["code"] !== undefined) {
|
|
@@ -212,7 +185,7 @@ class Serializer {
|
|
|
212
185
|
}
|
|
213
186
|
|
|
214
187
|
json += "\"code\"" + ':'
|
|
215
|
-
json += serializer.asString
|
|
188
|
+
json += serializer.asString(obj["code"])
|
|
216
189
|
}
|
|
217
190
|
|
|
218
191
|
if (obj["error"] !== undefined) {
|
|
@@ -224,7 +197,7 @@ class Serializer {
|
|
|
224
197
|
}
|
|
225
198
|
|
|
226
199
|
json += "\"error\"" + ':'
|
|
227
|
-
json += serializer.asString
|
|
200
|
+
json += serializer.asString(obj["error"])
|
|
228
201
|
}
|
|
229
202
|
|
|
230
203
|
if (obj["message"] !== undefined) {
|
|
@@ -236,7 +209,7 @@ class Serializer {
|
|
|
236
209
|
}
|
|
237
210
|
|
|
238
211
|
json += "\"message\"" + ':'
|
|
239
|
-
json += serializer.asString
|
|
212
|
+
json += serializer.asString(obj["message"])
|
|
240
213
|
}
|
|
241
214
|
|
|
242
215
|
json += '}'
|
package/lib/route.js
CHANGED
|
@@ -83,6 +83,7 @@ function buildRouting (options) {
|
|
|
83
83
|
},
|
|
84
84
|
routing: router.lookup.bind(router), // router func to find the right handler to call
|
|
85
85
|
route, // configure a route in the fastify instance
|
|
86
|
+
hasRoute,
|
|
86
87
|
prepareRoute,
|
|
87
88
|
getDefaultRoute: function () {
|
|
88
89
|
return router.defaultRoute
|
|
@@ -141,6 +142,14 @@ function buildRouting (options) {
|
|
|
141
142
|
return route.call(this, { options, isFastify })
|
|
142
143
|
}
|
|
143
144
|
|
|
145
|
+
function hasRoute ({ options }) {
|
|
146
|
+
return router.find(
|
|
147
|
+
options.method,
|
|
148
|
+
options.url || '',
|
|
149
|
+
options.constraints
|
|
150
|
+
) !== null
|
|
151
|
+
}
|
|
152
|
+
|
|
144
153
|
// Route management
|
|
145
154
|
function route ({ options, isFastify }) {
|
|
146
155
|
// Since we are mutating/assigning only top level props, it is fine to have a shallow copy using the spread operator
|
package/lib/schemas.js
CHANGED
|
@@ -62,6 +62,7 @@ function normalizeSchema (routeSchemas, serverOptions) {
|
|
|
62
62
|
// let's check if our schemas have a custom prototype
|
|
63
63
|
for (const key of ['headers', 'querystring', 'params', 'body']) {
|
|
64
64
|
if (typeof routeSchemas[key] === 'object' && Object.getPrototypeOf(routeSchemas[key]) !== Object.prototype) {
|
|
65
|
+
routeSchemas[kSchemaVisited] = true
|
|
65
66
|
return routeSchemas
|
|
66
67
|
}
|
|
67
68
|
}
|