fastify 5.0.0-alpha.2 → 5.0.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. package/README.md +2 -2
  2. package/SPONSORS.md +2 -0
  3. package/build/build-validation.js +3 -15
  4. package/docs/Guides/Ecosystem.md +4 -0
  5. package/docs/Guides/Getting-Started.md +0 -2
  6. package/docs/Guides/Migration-Guide-V4.md +48 -0
  7. package/docs/Guides/Recommendations.md +8 -6
  8. package/docs/Reference/Errors.md +0 -2
  9. package/docs/Reference/Hooks.md +5 -9
  10. package/docs/Reference/Logging.md +1 -1
  11. package/docs/Reference/Reply.md +9 -11
  12. package/docs/Reference/Request.md +0 -11
  13. package/docs/Reference/Routes.md +4 -23
  14. package/docs/Reference/Server.md +30 -40
  15. package/docs/Reference/Type-Providers.md +2 -2
  16. package/docs/Reference/TypeScript.md +16 -18
  17. package/docs/Reference/Validation-and-Serialization.md +62 -27
  18. package/docs/Reference/Warnings.md +0 -26
  19. package/eslint.config.js +9 -25
  20. package/fastify.d.ts +10 -23
  21. package/fastify.js +60 -61
  22. package/lib/configValidator.js +130 -182
  23. package/lib/context.js +1 -22
  24. package/lib/decorate.js +2 -2
  25. package/lib/errors.js +0 -6
  26. package/lib/handleRequest.js +5 -5
  27. package/lib/reply.js +34 -74
  28. package/lib/request.js +0 -45
  29. package/lib/route.js +12 -27
  30. package/lib/schemas.js +27 -22
  31. package/lib/server.js +6 -11
  32. package/lib/symbols.js +1 -1
  33. package/lib/validation.js +27 -6
  34. package/lib/warnings.js +1 -92
  35. package/lib/wrapThenable.js +1 -1
  36. package/package.json +14 -15
  37. package/test/decorator.test.js +1 -1
  38. package/test/diagnostics-channel/404.test.js +1 -1
  39. package/test/diagnostics-channel/async-delay-request.test.js +1 -1
  40. package/test/diagnostics-channel/async-request.test.js +1 -1
  41. package/test/diagnostics-channel/error-before-handler.test.js +1 -1
  42. package/test/diagnostics-channel/error-request.test.js +1 -1
  43. package/test/diagnostics-channel/error-status.test.js +1 -1
  44. package/test/diagnostics-channel/init.test.js +2 -2
  45. package/test/diagnostics-channel/sync-delay-request.test.js +1 -1
  46. package/test/diagnostics-channel/sync-request-reply.test.js +1 -1
  47. package/test/diagnostics-channel/sync-request.test.js +1 -1
  48. package/test/{copy.test.js → http-methods/copy.test.js} +2 -1
  49. package/test/http-methods/custom-http-methods.test.js +111 -0
  50. package/test/{get.test.js → http-methods/get.test.js} +1 -1
  51. package/test/{head.test.js → http-methods/head.test.js} +7 -87
  52. package/test/{lock.test.js → http-methods/lock.test.js} +2 -1
  53. package/test/{mkcalendar.test.js → http-methods/mkcalendar.test.js} +2 -1
  54. package/test/{mkcol.test.js → http-methods/mkcol.test.js} +2 -1
  55. package/test/{move.test.js → http-methods/move.test.js} +2 -1
  56. package/test/{propfind.test.js → http-methods/propfind.test.js} +2 -1
  57. package/test/{proppatch.test.js → http-methods/proppatch.test.js} +2 -1
  58. package/test/{report.test.js → http-methods/report.test.js} +2 -1
  59. package/test/{search.test.js → http-methods/search.test.js} +2 -1
  60. package/test/{trace.test.js → http-methods/trace.test.js} +2 -1
  61. package/test/{unlock.test.js → http-methods/unlock.test.js} +2 -1
  62. package/test/internals/all.test.js +3 -3
  63. package/test/internals/decorator.test.js +2 -2
  64. package/test/internals/errors.test.js +7 -17
  65. package/test/internals/initialConfig.test.js +0 -31
  66. package/test/internals/reply-serialize.test.js +25 -10
  67. package/test/internals/reply.test.js +31 -153
  68. package/test/internals/request-validate.test.js +21 -12
  69. package/test/internals/request.test.js +1 -18
  70. package/test/internals/validation.test.js +49 -56
  71. package/test/listen.1.test.js +66 -14
  72. package/test/listen.5.test.js +11 -0
  73. package/test/reply-trailers.test.js +1 -32
  74. package/test/route-shorthand.test.js +3 -1
  75. package/test/route.3.test.js +4 -1
  76. package/test/route.7.test.js +2 -12
  77. package/test/route.8.test.js +34 -5
  78. package/test/router-options.test.js +6 -3
  79. package/test/schema-examples.test.js +15 -6
  80. package/test/schema-feature.test.js +178 -35
  81. package/test/schema-serialization.test.js +125 -21
  82. package/test/schema-validation.test.js +154 -3
  83. package/test/skip-reply-send.test.js +6 -6
  84. package/test/stream-serializers.test.js +37 -0
  85. package/test/throw.test.js +2 -14
  86. package/test/types/errors.test-d.ts +1 -2
  87. package/test/types/fastify.test-d.ts +23 -34
  88. package/test/types/hooks.test-d.ts +56 -56
  89. package/test/types/instance.test-d.ts +3 -3
  90. package/test/types/reply.test-d.ts +7 -8
  91. package/test/types/request.test-d.ts +2 -12
  92. package/test/types/route.test-d.ts +158 -158
  93. package/test/types/schema.test-d.ts +22 -5
  94. package/test/versioned-routes.test.js +0 -90
  95. package/test/web-api.test.js +75 -0
  96. package/types/errors.d.ts +78 -79
  97. package/types/hooks.d.ts +18 -18
  98. package/types/instance.d.ts +1 -1
  99. package/types/logger.d.ts +7 -7
  100. package/types/reply.d.ts +18 -22
  101. package/types/request.d.ts +8 -14
  102. package/types/route.d.ts +5 -6
  103. package/types/type-provider.d.ts +1 -1
  104. package/.tap/processinfo/09002e93-10ad-430c-bc86-c0576928b0ed.json +0 -241
  105. package/.tap/processinfo/ee66c5ab-635d-48b5-8be6-3dc3ceea5bfc.json +0 -268
  106. package/.tap/test-results/test/404s.test.js.tap +0 -623
  107. package/.tap/test-results/test/500s.test.js.tap +0 -64
  108. package/.tap/test-results/test/allowUnsafeRegex.test.js.tap +0 -36
  109. package/.tap/test-results/test/als.test.js.tap +0 -15
  110. package/.tap/test-results/test/async-await.test.js.tap +0 -184
  111. package/.tap/test-results/test/async-dispose.test.js.tap +0 -8
  112. package/.tap/test-results/test/async_hooks.test.js.tap +0 -10
  113. package/.tap/test-results/test/bodyLimit.test.js.tap +0 -48
  114. package/.tap/test-results/test/buffer.test.js.tap +0 -20
  115. package/.tap/test-results/test/build/error-serializer.test.js.tap +0 -12
  116. package/.tap/test-results/test/build/version.test.js.tap +0 -7
  117. package/.tap/test-results/test/case-insensitive.test.js.tap +0 -36
  118. package/.tap/test-results/test/chainable.test.js.tap +0 -17
  119. package/.tap/test-results/test/check.test.js.tap +0 -10
  120. package/.tap/test-results/test/childLoggerFactory.test.js.tap +0 -23
  121. package/.tap/test-results/test/client-timeout.test.js.tap +0 -7
  122. package/.tap/test-results/test/close-pipelining.test.js.tap +0 -15
  123. package/.tap/test-results/test/close.test.js.tap +0 -172
  124. package/.tap/test-results/test/connectionTimeout.test.js.tap +0 -12
  125. package/.tap/test-results/test/constrained-routes.test.js.tap +0 -173
  126. package/.tap/test-results/test/content-length.test.js.tap +0 -46
  127. package/.tap/test-results/test/content-parser.test.js.tap +0 -266
  128. package/.tap/test-results/test/content-type.test.js.tap +0 -14
  129. package/.tap/test-results/test/context-config.test.js.tap +0 -41
  130. package/.tap/test-results/test/copy.test.js.tap +0 -14
  131. package/.tap/test-results/test/custom-http-server.test.js.tap +0 -30
  132. package/.tap/test-results/test/custom-parser-async.test.js.tap +0 -21
  133. package/.tap/test-results/test/custom-parser.0.test.js.tap +0 -199
  134. package/.tap/test-results/test/custom-parser.1.test.js.tap +0 -90
  135. package/.tap/test-results/test/custom-parser.2.test.js.tap +0 -22
  136. package/.tap/test-results/test/custom-parser.3.test.js.tap +0 -53
  137. package/.tap/test-results/test/custom-parser.4.test.js.tap +0 -45
  138. package/.tap/test-results/test/custom-parser.5.test.js.tap +0 -41
  139. package/.tap/test-results/test/custom-querystring-parser.test.js.tap +0 -46
  140. package/.tap/test-results/test/decorator.test.js.tap +0 -465
  141. package/.tap/test-results/test/delete.test.js.tap +0 -110
  142. package/.tap/test-results/test/diagnostics-channel/404.test.js.tap +0 -15
  143. package/.tap/test-results/test/diagnostics-channel/async-delay-request.test.js.tap +0 -25
  144. package/.tap/test-results/test/diagnostics-channel/async-request.test.js.tap +0 -24
  145. package/.tap/test-results/test/diagnostics-channel/error-before-handler.test.js.tap +0 -9
  146. package/.tap/test-results/test/diagnostics-channel/error-request.test.js.tap +0 -20
  147. package/.tap/test-results/test/diagnostics-channel/error-status.test.js.tap +0 -10
  148. package/.tap/test-results/test/diagnostics-channel/init.test.js.tap +0 -14
  149. package/.tap/test-results/test/diagnostics-channel/sync-delay-request.test.js.tap +0 -16
  150. package/.tap/test-results/test/diagnostics-channel/sync-request-reply.test.js.tap +0 -16
  151. package/.tap/test-results/test/diagnostics-channel/sync-request.test.js.tap +0 -19
  152. package/.tap/test-results/test/encapsulated-child-logger-factory.test.js.tap +0 -18
  153. package/.tap/test-results/test/encapsulated-error-handler.test.js.tap +0 -243
  154. package/.tap/test-results/test/esm/errorCodes.test.mjs.tap +0 -9
  155. package/.tap/test-results/test/esm/esm.test.mjs.tap +0 -8
  156. package/.tap/test-results/test/esm/index.test.js.tap +0 -8
  157. package/.tap/test-results/test/fastify-instance.test.js.tap +0 -114
  158. package/.tap/test-results/test/findRoute.test.js.tap +0 -37
  159. package/.tap/test-results/test/fluent-schema.test.js.tap +0 -36
  160. package/.tap/test-results/test/genReqId.test.js.tap +0 -106
  161. package/.tap/test-results/test/get.test.js.tap +0 -151
  162. package/.tap/test-results/test/handler-context.test.js.tap +0 -19
  163. package/.tap/test-results/test/has-route.test.js.tap +0 -30
  164. package/.tap/test-results/test/head.test.js.tap +0 -130
  165. package/.tap/test-results/test/header-overflow.test.js.tap +0 -16
  166. package/.tap/test-results/test/hooks-async.test.js.tap +0 -286
  167. package/.tap/test-results/test/hooks.on-listen.test.js.tap +0 -311
  168. package/.tap/test-results/test/hooks.on-ready.test.js.tap +0 -151
  169. package/.tap/test-results/test/hooks.test.js.tap +0 -966
  170. package/.tap/test-results/test/http2/closing.test.js.tap +0 -35
  171. package/.tap/test-results/test/http2/constraint.test.js.tap +0 -32
  172. package/.tap/test-results/test/http2/head.test.js.tap +0 -9
  173. package/.tap/test-results/test/http2/missing-http2-module.test.js.tap +0 -8
  174. package/.tap/test-results/test/http2/plain.test.js.tap +0 -22
  175. package/.tap/test-results/test/http2/secure-with-fallback.test.js.tap +0 -40
  176. package/.tap/test-results/test/http2/secure.test.js.tap +0 -27
  177. package/.tap/test-results/test/http2/unknown-http-method.test.js.tap +0 -9
  178. package/.tap/test-results/test/https/custom-https-server.test.js.tap +0 -10
  179. package/.tap/test-results/test/https/https.test.js.tap +0 -45
  180. package/.tap/test-results/test/imports.test.js.tap +0 -14
  181. package/.tap/test-results/test/inject.test.js.tap +0 -165
  182. package/.tap/test-results/test/internals/all.test.js.tap +0 -42
  183. package/.tap/test-results/test/internals/contentTypeParser.test.js.tap +0 -14
  184. package/.tap/test-results/test/internals/context.test.js.tap +0 -14
  185. package/.tap/test-results/test/internals/decorator.test.js.tap +0 -51
  186. package/.tap/test-results/test/internals/errors.test.js.tap +0 -1212
  187. package/.tap/test-results/test/internals/handleRequest.test.js.tap +0 -69
  188. package/.tap/test-results/test/internals/hookRunner.test.js.tap +0 -143
  189. package/.tap/test-results/test/internals/hooks.test.js.tap +0 -45
  190. package/.tap/test-results/test/internals/initialConfig.test.js.tap +0 -125
  191. package/.tap/test-results/test/internals/logger.test.js.tap +0 -71
  192. package/.tap/test-results/test/internals/plugin.test.js.tap +0 -48
  193. package/.tap/test-results/test/internals/reply-serialize.test.js.tap +0 -166
  194. package/.tap/test-results/test/internals/reply.test.js.tap +0 -688
  195. package/.tap/test-results/test/internals/reqIdGenFactory.test.js.tap +0 -74
  196. package/.tap/test-results/test/internals/request-validate.test.js.tap +0 -384
  197. package/.tap/test-results/test/internals/request.test.js.tap +0 -163
  198. package/.tap/test-results/test/internals/server.test.js.tap +0 -30
  199. package/.tap/test-results/test/internals/validation.test.js.tap +0 -121
  200. package/.tap/test-results/test/keepAliveTimeout.test.js.tap +0 -12
  201. package/.tap/test-results/test/listen.1.test.js.tap +0 -31
  202. package/.tap/test-results/test/listen.2.test.js.tap +0 -46
  203. package/.tap/test-results/test/listen.3.test.js.tap +0 -25
  204. package/.tap/test-results/test/listen.4.test.js.tap +0 -51
  205. package/.tap/test-results/test/lock.test.js.tap +0 -29
  206. package/.tap/test-results/test/logger/instantiation.test.js.tap +0 -92
  207. package/.tap/test-results/test/logger/logging.test.js.tap +0 -117
  208. package/.tap/test-results/test/logger/options.test.js.tap +0 -165
  209. package/.tap/test-results/test/logger/request.test.js.tap +0 -82
  210. package/.tap/test-results/test/logger/response.test.js.tap +0 -38
  211. package/.tap/test-results/test/maxRequestsPerSocket.test.js.tap +0 -44
  212. package/.tap/test-results/test/method-missing.test.js.tap +0 -8
  213. package/.tap/test-results/test/middleware.test.js.tap +0 -17
  214. package/.tap/test-results/test/mkcalendar.test.js.tap +0 -43
  215. package/.tap/test-results/test/mkcol.test.js.tap +0 -14
  216. package/.tap/test-results/test/move.test.js.tap +0 -15
  217. package/.tap/test-results/test/noop-set.test.js.tap +0 -8
  218. package/.tap/test-results/test/nullable-validation.test.js.tap +0 -36
  219. package/.tap/test-results/test/options.error-handler.test.js.tap +0 -186
  220. package/.tap/test-results/test/options.test.js.tap +0 -174
  221. package/.tap/test-results/test/output-validation.test.js.tap +0 -66
  222. package/.tap/test-results/test/patch.error-handler.test.js.tap +0 -206
  223. package/.tap/test-results/test/patch.test.js.tap +0 -182
  224. package/.tap/test-results/test/plugin.1.test.js.tap +0 -78
  225. package/.tap/test-results/test/plugin.2.test.js.tap +0 -102
  226. package/.tap/test-results/test/plugin.3.test.js.tap +0 -58
  227. package/.tap/test-results/test/plugin.4.test.js.tap +0 -164
  228. package/.tap/test-results/test/post-empty-body.test.js.tap +0 -8
  229. package/.tap/test-results/test/pretty-print.test.js.tap +0 -82
  230. package/.tap/test-results/test/promises.test.js.tap +0 -46
  231. package/.tap/test-results/test/propfind.test.js.tap +0 -43
  232. package/.tap/test-results/test/proppatch.test.js.tap +0 -29
  233. package/.tap/test-results/test/proto-poisoning.test.js.tap +0 -47
  234. package/.tap/test-results/test/put.error-handler.test.js.tap +0 -206
  235. package/.tap/test-results/test/put.test.js.tap +0 -182
  236. package/.tap/test-results/test/register.test.js.tap +0 -61
  237. package/.tap/test-results/test/reply-code.test.js.tap +0 -40
  238. package/.tap/test-results/test/reply-earlyHints.test.js.tap +0 -22
  239. package/.tap/test-results/test/reply-error.test.js.tap +0 -643
  240. package/.tap/test-results/test/reply-trailers.test.js.tap +0 -176
  241. package/.tap/test-results/test/report.test.js.tap +0 -43
  242. package/.tap/test-results/test/request-error.test.js.tap +0 -98
  243. package/.tap/test-results/test/request-id.test.js.tap +0 -38
  244. package/.tap/test-results/test/request.deprecated.test.js.tap +0 -13
  245. package/.tap/test-results/test/requestTimeout.test.js.tap +0 -21
  246. package/.tap/test-results/test/route-hooks.test.js.tap +0 -498
  247. package/.tap/test-results/test/route-prefix.test.js.tap +0 -195
  248. package/.tap/test-results/test/route-shorthand.test.js.tap +0 -190
  249. package/.tap/test-results/test/route.1.test.js.tap +0 -93
  250. package/.tap/test-results/test/route.2.test.js.tap +0 -28
  251. package/.tap/test-results/test/route.3.test.js.tap +0 -39
  252. package/.tap/test-results/test/route.4.test.js.tap +0 -32
  253. package/.tap/test-results/test/route.5.test.js.tap +0 -54
  254. package/.tap/test-results/test/route.6.test.js.tap +0 -81
  255. package/.tap/test-results/test/route.7.test.js.tap +0 -93
  256. package/.tap/test-results/test/route.8.test.js.tap +0 -38
  257. package/.tap/test-results/test/router-options.test.js.tap +0 -104
  258. package/.tap/test-results/test/same-shape.test.js.tap +0 -22
  259. package/.tap/test-results/test/schema-examples.test.js.tap +0 -85
  260. package/.tap/test-results/test/schema-feature.test.js.tap +0 -445
  261. package/.tap/test-results/test/schema-serialization.test.js.tap +0 -194
  262. package/.tap/test-results/test/schema-special-usage.test.js.tap +0 -186
  263. package/.tap/test-results/test/schema-validation.test.js.tap +0 -199
  264. package/.tap/test-results/test/search.test.js.tap +0 -77
  265. package/.tap/test-results/test/serialize-response.test.js.tap +0 -26
  266. package/.tap/test-results/test/server.test.js.tap +0 -65
  267. package/.tap/test-results/test/set-error-handler.test.js.tap +0 -7
  268. package/.tap/test-results/test/skip-reply-send.test.js.tap +0 -272
  269. package/.tap/test-results/test/stream.1.test.js.tap +0 -36
  270. package/.tap/test-results/test/stream.2.test.js.tap +0 -20
  271. package/.tap/test-results/test/stream.3.test.js.tap +0 -34
  272. package/.tap/test-results/test/stream.4.test.js.tap +0 -40
  273. package/.tap/test-results/test/stream.5.test.js.tap +0 -37
  274. package/.tap/test-results/test/sync-routes.test.js.tap +0 -19
  275. package/.tap/test-results/test/throw.test.js.tap +0 -116
  276. package/.tap/test-results/test/trace.test.js.tap +0 -7
  277. package/.tap/test-results/test/trust-proxy.test.js.tap +0 -109
  278. package/.tap/test-results/test/type-provider.test.js.tap +0 -12
  279. package/.tap/test-results/test/unlock.test.js.tap +0 -14
  280. package/.tap/test-results/test/upgrade.test.js.tap +0 -8
  281. package/.tap/test-results/test/url-rewriting.test.js.tap +0 -39
  282. package/.tap/test-results/test/useSemicolonDelimiter.test.js.tap +0 -33
  283. package/.tap/test-results/test/validation-error-handling.test.js.tap +0 -180
  284. package/.tap/test-results/test/versioned-routes.test.js.tap +0 -151
  285. package/.tap/test-results/test/web-api.test.js.tap +0 -51
  286. package/.tap/test-results/test/wrapThenable.test.js.tap +0 -11
  287. package/EXPENSE_POLICY.md +0 -105
  288. package/lib/httpMethods.js +0 -40
  289. package/test/method-missing.test.js +0 -24
  290. package/test/request.deprecated.test.js +0 -38
@@ -110,7 +110,14 @@ test('Get compilers is empty when settle on routes', t => {
110
110
  fastify.post('/', {
111
111
  schema: {
112
112
  body: { type: 'object', properties: { hello: { type: 'string' } } },
113
- response: { '2xx': { foo: { type: 'array', items: { type: 'string' } } } }
113
+ response: {
114
+ '2xx': {
115
+ type: 'object',
116
+ properties: {
117
+ foo: { type: 'array', items: { type: 'string' } }
118
+ }
119
+ }
120
+ }
114
121
  },
115
122
  validatorCompiler: ({ schema, method, url, httpPart }) => {},
116
123
  serializerCompiler: ({ schema, method, url, httpPart }) => {}
@@ -160,8 +167,18 @@ test('Cannot add schema for query and querystring', t => {
160
167
  fastify.get('/', {
161
168
  handler: () => {},
162
169
  schema: {
163
- query: { foo: { type: 'string' } },
164
- querystring: { foo: { type: 'string' } }
170
+ query: {
171
+ type: 'object',
172
+ properties: {
173
+ foo: { type: 'string' }
174
+ }
175
+ },
176
+ querystring: {
177
+ type: 'object',
178
+ properties: {
179
+ foo: { type: 'string' }
180
+ }
181
+ }
165
182
  }
166
183
  })
167
184
 
@@ -179,7 +196,10 @@ test('Should throw of the schema does not exists in input', t => {
179
196
  handler: echoParams,
180
197
  schema: {
181
198
  params: {
182
- name: { $ref: '#notExist' }
199
+ type: 'object',
200
+ properties: {
201
+ name: { $ref: '#notExist' }
202
+ }
183
203
  }
184
204
  }
185
205
  })
@@ -190,6 +210,27 @@ test('Should throw of the schema does not exists in input', t => {
190
210
  })
191
211
  })
192
212
 
213
+ test('Should throw if schema is missing for content type', t => {
214
+ t.plan(2)
215
+
216
+ const fastify = Fastify()
217
+ fastify.post('/', {
218
+ handler: echoBody,
219
+ schema: {
220
+ body: {
221
+ content: {
222
+ 'application/json': {}
223
+ }
224
+ }
225
+ }
226
+ })
227
+
228
+ fastify.ready(err => {
229
+ t.equal(err.code, 'FST_ERR_SCH_CONTENT_MISSING_SCHEMA')
230
+ t.equal(err.message, "Schema is missing for the content type 'application/json'")
231
+ })
232
+ })
233
+
193
234
  test('Should throw of the schema does not exists in output', t => {
194
235
  t.plan(2)
195
236
  const fastify = Fastify()
@@ -199,7 +240,10 @@ test('Should throw of the schema does not exists in output', t => {
199
240
  schema: {
200
241
  response: {
201
242
  '2xx': {
202
- name: { $ref: '#notExist' }
243
+ type: 'object',
244
+ properties: {
245
+ name: { $ref: '#notExist' }
246
+ }
203
247
  }
204
248
  }
205
249
  }
@@ -235,7 +279,10 @@ test('Should not change the input schemas', t => {
235
279
  },
236
280
  response: {
237
281
  '2xx': {
238
- name: { $ref: 'helloSchema#/definitions/hello' }
282
+ type: 'object',
283
+ properties: {
284
+ name: { $ref: 'helloSchema#/definitions/hello' }
285
+ }
239
286
  }
240
287
  }
241
288
  }
@@ -507,12 +554,37 @@ test('Customize validator compiler in instance and route', t => {
507
554
  fastify.post('/:id', {
508
555
  handler: echoBody,
509
556
  schema: {
510
- query: { lang: { type: 'string', enum: ['it', 'en'] } },
511
- headers: { x: { type: 'string' } },
512
- params: { id: { type: 'number' } },
513
- body: { foo: { type: 'array' } },
557
+ query: {
558
+ type: 'object',
559
+ properties: {
560
+ lang: { type: 'string', enum: ['it', 'en'] }
561
+ }
562
+ },
563
+ headers: {
564
+ type: 'object',
565
+ properties: {
566
+ x: { type: 'string' }
567
+ }
568
+ },
569
+ params: {
570
+ type: 'object',
571
+ properties: {
572
+ id: { type: 'number' }
573
+ }
574
+ },
575
+ body: {
576
+ type: 'object',
577
+ properties: {
578
+ foo: { type: 'array' }
579
+ }
580
+ },
514
581
  response: {
515
- '2xx': { foo: { type: 'array', items: { type: 'string' } } }
582
+ '2xx': {
583
+ type: 'object',
584
+ properties: {
585
+ foo: { type: 'array', items: { type: 'string' } }
586
+ }
587
+ }
516
588
  }
517
589
  }
518
590
  })
@@ -525,10 +597,32 @@ test('Customize validator compiler in instance and route', t => {
525
597
  return () => { return true } // ignore the validation
526
598
  },
527
599
  schema: {
528
- query: { lang: { type: 'string', enum: ['it', 'en'] } },
529
- headers: { x: { type: 'string' } },
530
- params: { id: { type: 'number' } },
531
- response: { '2xx': { foo: { type: 'array', items: { type: 'string' } } } }
600
+ query: {
601
+ type: 'object',
602
+ properties: {
603
+ lang: { type: 'string', enum: ['it', 'en'] }
604
+ }
605
+ },
606
+ headers: {
607
+ type: 'object',
608
+ properties: {
609
+ x: { type: 'string' }
610
+ }
611
+ },
612
+ params: {
613
+ type: 'object',
614
+ properties: {
615
+ id: { type: 'number' }
616
+ }
617
+ },
618
+ response: {
619
+ '2xx': {
620
+ type: 'object',
621
+ properties: {
622
+ foo: { type: 'array', items: { type: 'string' } }
623
+ }
624
+ }
625
+ }
532
626
  }
533
627
  })
534
628
 
@@ -570,7 +664,12 @@ test('Use the same schema across multiple routes', t => {
570
664
 
571
665
  fastify.get('/first/:id', {
572
666
  schema: {
573
- params: { id: { $ref: 'test#/properties/id' } }
667
+ params: {
668
+ type: 'object',
669
+ properties: {
670
+ id: { $ref: 'test#/properties/id' }
671
+ }
672
+ }
574
673
  },
575
674
  handler: (req, reply) => {
576
675
  reply.send(typeof req.params.id)
@@ -579,7 +678,12 @@ test('Use the same schema across multiple routes', t => {
579
678
 
580
679
  fastify.get('/second/:id', {
581
680
  schema: {
582
- params: { id: { $ref: 'test#/properties/id' } }
681
+ params: {
682
+ type: 'object',
683
+ properties: {
684
+ id: { $ref: 'test#/properties/id' }
685
+ }
686
+ }
583
687
  },
584
688
  handler: (req, reply) => {
585
689
  reply.send(typeof req.params.id)
@@ -622,7 +726,12 @@ test('Encapsulation should intervene', t => {
622
726
  instance.get('/:id', {
623
727
  handler: echoParams,
624
728
  schema: {
625
- params: { id: { $ref: 'encapsulation#/properties/id' } }
729
+ params: {
730
+ type: 'object',
731
+ properties: {
732
+ id: { $ref: 'encapsulation#/properties/id' }
733
+ }
734
+ }
626
735
  }
627
736
  })
628
737
  done()
@@ -761,9 +870,19 @@ test('Use the same schema id in different places', t => {
761
870
  fastify.post('/:id', {
762
871
  handler: echoBody,
763
872
  schema: {
764
- body: { id: { $ref: 'test#/properties/id' } },
873
+ body: {
874
+ type: 'object',
875
+ properties: {
876
+ id: { $ref: 'test#/properties/id' }
877
+ }
878
+ },
765
879
  response: {
766
- 200: { id: { $ref: 'test#/properties/id' } }
880
+ 200: {
881
+ type: 'object',
882
+ properties: {
883
+ id: { $ref: 'test#/properties/id' }
884
+ }
885
+ }
767
886
  }
768
887
  }
769
888
  })
@@ -1333,7 +1452,10 @@ test('The schema compiler recreate itself if needed', t => {
1333
1452
  fastify.get('/:foobarId', {
1334
1453
  schema: {
1335
1454
  params: {
1336
- foobarId: { $ref: 'identifier#' }
1455
+ type: 'object',
1456
+ properties: {
1457
+ foobarId: { $ref: 'identifier#' }
1458
+ }
1337
1459
  }
1338
1460
  }
1339
1461
  }, echoBody)
@@ -1525,8 +1647,11 @@ test('setSchemaController: Inherits correctly parent schemas with a customized v
1525
1647
  {
1526
1648
  schema: {
1527
1649
  querystring: {
1528
- msg: {
1529
- $ref: 'some#'
1650
+ type: 'object',
1651
+ properties: {
1652
+ msg: {
1653
+ $ref: 'some#'
1654
+ }
1530
1655
  }
1531
1656
  },
1532
1657
  response: {
@@ -1635,8 +1760,11 @@ test('setSchemaController: Inherits buildSerializer from parent if not present w
1635
1760
  {
1636
1761
  schema: {
1637
1762
  querystring: {
1638
- msg: {
1639
- $ref: 'some#'
1763
+ type: 'object',
1764
+ properties: {
1765
+ msg: {
1766
+ $ref: 'some#'
1767
+ }
1640
1768
  }
1641
1769
  },
1642
1770
  response: {
@@ -1746,8 +1874,11 @@ test('setSchemaController: Inherits buildValidator from parent if not present wi
1746
1874
  {
1747
1875
  schema: {
1748
1876
  querystring: {
1749
- msg: {
1750
- $ref: 'some#'
1877
+ type: 'object',
1878
+ properties: {
1879
+ msg: {
1880
+ $ref: 'some#'
1881
+ }
1751
1882
  }
1752
1883
  },
1753
1884
  response: {
@@ -1838,13 +1969,19 @@ test('Should throw if not default validator passed', async t => {
1838
1969
  {
1839
1970
  schema: {
1840
1971
  query: {
1841
- msg: {
1842
- $ref: 'some#'
1972
+ type: 'object',
1973
+ properties: {
1974
+ msg: {
1975
+ $ref: 'some#'
1976
+ }
1843
1977
  }
1844
1978
  },
1845
1979
  headers: {
1846
- 'x-another': {
1847
- $ref: 'another#'
1980
+ type: 'object',
1981
+ properties: {
1982
+ 'x-another': {
1983
+ $ref: 'another#'
1984
+ }
1848
1985
  }
1849
1986
  }
1850
1987
  }
@@ -1899,13 +2036,19 @@ test('Should coerce the array if the default validator is used', async t => {
1899
2036
  {
1900
2037
  schema: {
1901
2038
  query: {
1902
- msg: {
1903
- $ref: 'some#'
2039
+ type: 'object',
2040
+ properties: {
2041
+ msg: {
2042
+ $ref: 'some#'
2043
+ }
1904
2044
  }
1905
2045
  },
1906
2046
  headers: {
1907
- 'x-another': {
1908
- $ref: 'another#'
2047
+ type: 'object',
2048
+ properties: {
2049
+ 'x-another': {
2050
+ $ref: 'another#'
2051
+ }
1909
2052
  }
1910
2053
  }
1911
2054
  }
@@ -61,7 +61,7 @@ test('custom serializer options', t => {
61
61
  })
62
62
 
63
63
  test('Different content types', t => {
64
- t.plan(32)
64
+ t.plan(46)
65
65
 
66
66
  const fastify = Fastify()
67
67
  fastify.addSchema({
@@ -81,9 +81,12 @@ test('Different content types', t => {
81
81
  content: {
82
82
  'application/json': {
83
83
  schema: {
84
- name: { type: 'string' },
85
- image: { type: 'string' },
86
- address: { type: 'string' }
84
+ type: 'object',
85
+ properties: {
86
+ name: { type: 'string' },
87
+ image: { type: 'string' },
88
+ address: { type: 'string' }
89
+ }
87
90
  }
88
91
  },
89
92
  'application/vnd.v1+json': {
@@ -95,17 +98,40 @@ test('Different content types', t => {
95
98
  }
96
99
  },
97
100
  201: {
98
- content: { type: 'string' }
101
+ content: {
102
+ '*/*': {
103
+ schema: { type: 'string' }
104
+ }
105
+ }
99
106
  },
100
107
  202: {
101
- content: { const: 'Processing exclusive content' }
108
+ content: {
109
+ '*/*': {
110
+ schema: { const: 'Processing exclusive content' }
111
+ }
112
+ }
102
113
  },
103
114
  '3xx': {
104
115
  content: {
105
116
  'application/vnd.v2+json': {
106
117
  schema: {
107
- fullName: { type: 'string' },
108
- phone: { type: 'string' }
118
+ type: 'object',
119
+ properties: {
120
+ fullName: { type: 'string' },
121
+ phone: { type: 'string' }
122
+ }
123
+ }
124
+ }
125
+ }
126
+ },
127
+ '4xx': {
128
+ content: {
129
+ '*/*': {
130
+ schema: {
131
+ type: 'object',
132
+ properties: {
133
+ details: { type: 'string' }
134
+ }
109
135
  }
110
136
  }
111
137
  }
@@ -114,7 +140,19 @@ test('Different content types', t => {
114
140
  content: {
115
141
  'application/json': {
116
142
  schema: {
117
- details: { type: 'string' }
143
+ type: 'object',
144
+ properties: {
145
+ details: { type: 'string' }
146
+ }
147
+ }
148
+ },
149
+ '*/*': {
150
+ schema: {
151
+ type: 'object',
152
+ properties: {
153
+ desc: { type: 'string' },
154
+ details: { type: 'string' }
155
+ }
118
156
  }
119
157
  }
120
158
  }
@@ -160,6 +198,15 @@ test('Different content types', t => {
160
198
  reply.code(400)
161
199
  reply.send({ details: 'validation error' })
162
200
  break
201
+ case 'application/vnd.v8+json':
202
+ reply.header('Content-Type', 'application/vnd.v8+json')
203
+ reply.code(500)
204
+ reply.send({ desc: 'age is missing', details: 'validation error' })
205
+ break
206
+ case 'application/vnd.v9+json':
207
+ reply.code(500)
208
+ reply.send({ details: 'validation error' })
209
+ break
163
210
  default:
164
211
  // to test if schema not found
165
212
  reply.header('Content-Type', 'application/vnd.v3+json')
@@ -179,9 +226,24 @@ test('Different content types', t => {
179
226
  content: {
180
227
  'application/json': {
181
228
  schema: {
182
- name: { type: 'string' },
183
- image: { type: 'string' },
184
- address: { type: 'string' }
229
+ type: 'object',
230
+ properties: {
231
+ name: { type: 'string' },
232
+ image: { type: 'string' },
233
+ address: { type: 'string' }
234
+ }
235
+ }
236
+ }
237
+ }
238
+ },
239
+ default: {
240
+ content: {
241
+ 'application/json': {
242
+ schema: {
243
+ type: 'object',
244
+ properties: {
245
+ details: { type: 'string' }
246
+ }
185
247
  }
186
248
  }
187
249
  }
@@ -189,8 +251,23 @@ test('Different content types', t => {
189
251
  }
190
252
  }
191
253
  }, function (req, reply) {
192
- reply.header('Content-Type', 'application/json')
193
- reply.send({ age: 18, city: 'AU' })
254
+ switch (req.headers['code']) {
255
+ case '200': {
256
+ reply.header('Content-Type', 'application/json')
257
+ reply.code(200).send({ age: 18, city: 'AU' })
258
+ break
259
+ }
260
+ case '201': {
261
+ reply.header('Content-Type', 'application/json')
262
+ reply.code(201).send({ details: 'validation error' })
263
+ break
264
+ }
265
+ default: {
266
+ reply.header('Content-Type', 'application/vnd.v1+json')
267
+ reply.code(201).send({ created: true })
268
+ break
269
+ }
270
+ }
194
271
  })
195
272
 
196
273
  fastify.inject({ method: 'GET', url: '/', headers: { Accept: 'application/json' } }, (err, res) => {
@@ -225,19 +302,19 @@ test('Different content types', t => {
225
302
 
226
303
  fastify.inject({ method: 'GET', url: '/', headers: { Accept: 'application/vnd.v4+json' } }, (err, res) => {
227
304
  t.error(err)
228
- t.equal(res.payload, JSON.stringify({ content: 'Games' }))
305
+ t.equal(res.payload, '"[object Object]"')
229
306
  t.equal(res.statusCode, 201)
230
307
  })
231
308
 
232
309
  fastify.inject({ method: 'GET', url: '/', headers: { Accept: 'application/vnd.v5+json' } }, (err, res) => {
233
310
  t.error(err)
234
- t.equal(res.payload, JSON.stringify({ content: 'Processing exclusive content' }))
311
+ t.equal(res.payload, '"Processing exclusive content"')
235
312
  t.equal(res.statusCode, 202)
236
313
  })
237
314
 
238
315
  fastify.inject({ method: 'GET', url: '/', headers: { Accept: 'application/vnd.v6+json' } }, (err, res) => {
239
316
  t.error(err)
240
- t.equal(res.payload, JSON.stringify({ desc: 'age is missing', details: 'validation error' }))
317
+ t.equal(res.payload, JSON.stringify({ details: 'validation error' }))
241
318
  t.equal(res.statusCode, 400)
242
319
  })
243
320
 
@@ -247,11 +324,35 @@ test('Different content types', t => {
247
324
  t.equal(res.statusCode, 400)
248
325
  })
249
326
 
250
- fastify.inject({ method: 'GET', url: '/test' }, (err, res) => {
327
+ fastify.inject({ method: 'GET', url: '/', headers: { Accept: 'application/vnd.v8+json' } }, (err, res) => {
328
+ t.error(err)
329
+ t.equal(res.payload, JSON.stringify({ desc: 'age is missing', details: 'validation error' }))
330
+ t.equal(res.statusCode, 500)
331
+ })
332
+
333
+ fastify.inject({ method: 'GET', url: '/', headers: { Accept: 'application/vnd.v9+json' } }, (err, res) => {
334
+ t.error(err)
335
+ t.equal(res.payload, JSON.stringify({ details: 'validation error' }))
336
+ t.equal(res.statusCode, 500)
337
+ })
338
+
339
+ fastify.inject({ method: 'GET', url: '/test', headers: { Code: '200' } }, (err, res) => {
251
340
  t.error(err)
252
341
  t.equal(res.payload, JSON.stringify({ age: 18, city: 'AU' }))
253
342
  t.equal(res.statusCode, 200)
254
343
  })
344
+
345
+ fastify.inject({ method: 'GET', url: '/test', headers: { Code: '201' } }, (err, res) => {
346
+ t.error(err)
347
+ t.equal(res.payload, JSON.stringify({ details: 'validation error' }))
348
+ t.equal(res.statusCode, 201)
349
+ })
350
+
351
+ fastify.inject({ method: 'GET', url: '/test', headers: { Accept: 'application/vnd.v1+json' } }, (err, res) => {
352
+ t.error(err)
353
+ t.equal(res.payload, JSON.stringify({ created: true }))
354
+ t.equal(res.statusCode, 201)
355
+ })
255
356
  })
256
357
 
257
358
  test('Invalid multiple content schema, throw FST_ERR_SCH_CONTENT_MISSING_SCHEMA error', t => {
@@ -265,8 +366,11 @@ test('Invalid multiple content schema, throw FST_ERR_SCH_CONTENT_MISSING_SCHEMA
265
366
  content: {
266
367
  'application/json': {
267
368
  schema: {
268
- fullName: { type: 'string' },
269
- phone: { type: 'string' }
369
+ type: 'object',
370
+ properties: {
371
+ fullName: { type: 'string' },
372
+ phone: { type: 'string' }
373
+ }
270
374
  },
271
375
  example: {
272
376
  fullName: 'John Doe',
@@ -321,7 +425,7 @@ test('Use the same schema id in different places', t => {
321
425
  url: '/123'
322
426
  }, (err, res) => {
323
427
  t.error(err)
324
- t.same(res.json(), [{ id: 1 }, { id: 2 }, { }])
428
+ t.same(res.json(), [{ id: 1 }, { id: 2 }, {}])
325
429
  })
326
430
  })
327
431