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.
@@ -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 a async error handler function,
14
- the upper-level error handler is executed if set.
15
- If there is not a upper-level error handler, the default will
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
- ### Deprecation of `app.use()` ([#3506](https://github.com/fastify/fastify/pull/3506))
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
- Starting this version of Fastify, we have deprecated the use of `app.use()`. We
46
- have decided not to support the use of middlewares. Both
47
- [`@fastify/middie`](https://github.com/fastify/middie) and
48
- [`@fastify/express`](https://github.com/fastify/fastify-express) will still be
49
- there and maintained. Use Fastify's [hooks](../Reference/Hooks.md) instead.
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'll instead need to depend on `reply.raw`.
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're
59
- just not explicitly returning a response, you'll need to return the `reply`
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 from v4, all the `GET` routes will create a sibling `HEAD` route.
65
- You can revert this behaviour by setting the server's option `exposeHeadRoutes`
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
- The route registration has been made synchronous from v4.
71
- This change was done to provide better error reporting for route definition.
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
- instance.addHook('onRoute', (routeOptions) => {
80
- const { path, method } = routeOptions;
81
- console.log({ path, method });
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
- done();
84
- });
85
- ```
86
- Into this:
87
- ```
88
- await fastify.register((instance, opts, done) => {
89
- instance.addHook('onRoute', (routeOptions) => {
90
- const { path, method } = routeOptions;
91
- console.log({ path, method });
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
- done();
94
- });
95
- ```
126
+ ```
96
127
 
97
- ## Non Breaking Changes
128
+ ## Non-Breaking Changes
98
129
 
99
- ### Change of schema for multiple types
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
- Since Fastify v4 has upgraded to Ajv v8. The "type" keywords with multiple types
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
- You may encounter a console warning such as
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
- So schemas like below will need to be changed from
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://dependabot.com/),
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
@@ -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. Use
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
- fastify().register(plugin, {}) // Error - options object is missing required properties
1241
- fastify().register(plugin, { option1: '', option2: true }) // OK - options object contains required properties
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
@@ -56,7 +56,7 @@ const opts: RouteShorthandOptions = {
56
56
  };
57
57
 
58
58
  // Add our route handler with correct types
59
- server.get<{
59
+ server.post<{
60
60
  Querystring: PingQuerystring;
61
61
  Params: PingParams;
62
62
  Headers: PingHeaders;
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.5.3'
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
@@ -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.bind(serializer)(obj["statusCode"])
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.bind(serializer)(obj["code"])
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.bind(serializer)(obj["error"])
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.bind(serializer)(obj["message"])
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
  }