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,280 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
kSchemaHeaders: headersSchema,
|
|
5
|
+
kSchemaParams: paramsSchema,
|
|
6
|
+
kSchemaQuerystring: querystringSchema,
|
|
7
|
+
kSchemaBody: bodySchema,
|
|
8
|
+
kSchemaResponse: responseSchema
|
|
9
|
+
} = require('./symbols')
|
|
10
|
+
const scChecker = /^[1-5](?:\d{2}|xx)$|^default$/
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
FST_ERR_SCH_RESPONSE_SCHEMA_NOT_NESTED_2XX
|
|
14
|
+
} = require('./errors')
|
|
15
|
+
|
|
16
|
+
const { FSTWRN001 } = require('./warnings')
|
|
17
|
+
|
|
18
|
+
function compileSchemasForSerialization (context, compile) {
|
|
19
|
+
if (!context.schema || !context.schema.response) {
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
const { method, url } = context.config || {}
|
|
23
|
+
context[responseSchema] = Object.keys(context.schema.response)
|
|
24
|
+
.reduce(function (acc, statusCode) {
|
|
25
|
+
const schema = context.schema.response[statusCode]
|
|
26
|
+
statusCode = statusCode.toLowerCase()
|
|
27
|
+
if (!scChecker.test(statusCode)) {
|
|
28
|
+
throw new FST_ERR_SCH_RESPONSE_SCHEMA_NOT_NESTED_2XX()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (schema.content) {
|
|
32
|
+
const contentTypesSchemas = {}
|
|
33
|
+
for (const mediaName of Object.keys(schema.content)) {
|
|
34
|
+
const contentSchema = schema.content[mediaName].schema
|
|
35
|
+
contentTypesSchemas[mediaName] = compile({
|
|
36
|
+
schema: contentSchema,
|
|
37
|
+
url,
|
|
38
|
+
method,
|
|
39
|
+
httpStatus: statusCode,
|
|
40
|
+
contentType: mediaName
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
acc[statusCode] = contentTypesSchemas
|
|
44
|
+
} else {
|
|
45
|
+
acc[statusCode] = compile({
|
|
46
|
+
schema,
|
|
47
|
+
url,
|
|
48
|
+
method,
|
|
49
|
+
httpStatus: statusCode
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return acc
|
|
54
|
+
}, {})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function compileSchemasForValidation (context, compile, isCustom) {
|
|
58
|
+
const { schema } = context
|
|
59
|
+
if (!schema) {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const { method, url } = context.config || {}
|
|
64
|
+
|
|
65
|
+
const headers = schema.headers
|
|
66
|
+
// the or part is used for backward compatibility
|
|
67
|
+
if (headers && (isCustom || Object.getPrototypeOf(headers) !== Object.prototype)) {
|
|
68
|
+
// do not mess with schema when custom validator applied, e.g. Joi, Typebox
|
|
69
|
+
context[headersSchema] = compile({ schema: headers, method, url, httpPart: 'headers' })
|
|
70
|
+
} else if (headers) {
|
|
71
|
+
// The header keys are case insensitive
|
|
72
|
+
// https://datatracker.ietf.org/doc/html/rfc2616#section-4.2
|
|
73
|
+
const headersSchemaLowerCase = {}
|
|
74
|
+
Object.keys(headers).forEach(k => { headersSchemaLowerCase[k] = headers[k] })
|
|
75
|
+
if (headersSchemaLowerCase.required instanceof Array) {
|
|
76
|
+
headersSchemaLowerCase.required = headersSchemaLowerCase.required.map(h => h.toLowerCase())
|
|
77
|
+
}
|
|
78
|
+
if (headers.properties) {
|
|
79
|
+
headersSchemaLowerCase.properties = {}
|
|
80
|
+
Object.keys(headers.properties).forEach(k => {
|
|
81
|
+
headersSchemaLowerCase.properties[k.toLowerCase()] = headers.properties[k]
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
context[headersSchema] = compile({ schema: headersSchemaLowerCase, method, url, httpPart: 'headers' })
|
|
85
|
+
} else if (Object.hasOwn(schema, 'headers')) {
|
|
86
|
+
FSTWRN001('headers', method, url)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (schema.body) {
|
|
90
|
+
const contentProperty = schema.body.content
|
|
91
|
+
if (contentProperty) {
|
|
92
|
+
const contentTypeSchemas = {}
|
|
93
|
+
for (const contentType of Object.keys(contentProperty)) {
|
|
94
|
+
const contentSchema = contentProperty[contentType].schema
|
|
95
|
+
contentTypeSchemas[contentType] = compile({ schema: contentSchema, method, url, httpPart: 'body', contentType })
|
|
96
|
+
}
|
|
97
|
+
context[bodySchema] = contentTypeSchemas
|
|
98
|
+
} else {
|
|
99
|
+
context[bodySchema] = compile({ schema: schema.body, method, url, httpPart: 'body' })
|
|
100
|
+
}
|
|
101
|
+
} else if (Object.hasOwn(schema, 'body')) {
|
|
102
|
+
FSTWRN001('body', method, url)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (schema.querystring) {
|
|
106
|
+
context[querystringSchema] = compile({ schema: schema.querystring, method, url, httpPart: 'querystring' })
|
|
107
|
+
} else if (Object.hasOwn(schema, 'querystring')) {
|
|
108
|
+
FSTWRN001('querystring', method, url)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (schema.params) {
|
|
112
|
+
context[paramsSchema] = compile({ schema: schema.params, method, url, httpPart: 'params' })
|
|
113
|
+
} else if (Object.hasOwn(schema, 'params')) {
|
|
114
|
+
FSTWRN001('params', method, url)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function validateParam (validatorFunction, request, paramName) {
|
|
119
|
+
const isUndefined = request[paramName] === undefined
|
|
120
|
+
let ret
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
ret = validatorFunction?.(isUndefined ? null : request[paramName])
|
|
124
|
+
} catch (err) {
|
|
125
|
+
// If validator throws synchronously, ensure it propagates as an internal error
|
|
126
|
+
err.statusCode = 500
|
|
127
|
+
return err
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (ret && typeof ret.then === 'function') {
|
|
131
|
+
return ret
|
|
132
|
+
.then((res) => { return answer(res) })
|
|
133
|
+
.catch(err => { return err }) // return as simple error (not throw)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return answer(ret)
|
|
137
|
+
|
|
138
|
+
function answer (ret) {
|
|
139
|
+
if (ret === false) return validatorFunction.errors
|
|
140
|
+
if (ret && ret.error) return ret.error
|
|
141
|
+
if (ret && ret.value) request[paramName] = ret.value
|
|
142
|
+
return false
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function validate (context, request, execution) {
|
|
147
|
+
const runExecution = execution === undefined
|
|
148
|
+
|
|
149
|
+
if (runExecution || !execution.skipParams) {
|
|
150
|
+
const params = validateParam(context[paramsSchema], request, 'params')
|
|
151
|
+
if (params) {
|
|
152
|
+
if (typeof params.then !== 'function') {
|
|
153
|
+
return wrapValidationError(params, 'params', context.schemaErrorFormatter)
|
|
154
|
+
} else {
|
|
155
|
+
return validateAsyncParams(params, context, request)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (runExecution || !execution.skipBody) {
|
|
161
|
+
let validatorFunction = null
|
|
162
|
+
if (typeof context[bodySchema] === 'function') {
|
|
163
|
+
validatorFunction = context[bodySchema]
|
|
164
|
+
} else if (context[bodySchema]) {
|
|
165
|
+
// TODO: add request.contentType and reuse it here
|
|
166
|
+
const contentType = getEssenceMediaType(request.headers['content-type'])
|
|
167
|
+
const contentSchema = context[bodySchema][contentType]
|
|
168
|
+
if (contentSchema) {
|
|
169
|
+
validatorFunction = contentSchema
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const body = validateParam(validatorFunction, request, 'body')
|
|
173
|
+
if (body) {
|
|
174
|
+
if (typeof body.then !== 'function') {
|
|
175
|
+
return wrapValidationError(body, 'body', context.schemaErrorFormatter)
|
|
176
|
+
} else {
|
|
177
|
+
return validateAsyncBody(body, context, request)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (runExecution || !execution.skipQuery) {
|
|
183
|
+
const query = validateParam(context[querystringSchema], request, 'query')
|
|
184
|
+
if (query) {
|
|
185
|
+
if (typeof query.then !== 'function') {
|
|
186
|
+
return wrapValidationError(query, 'querystring', context.schemaErrorFormatter)
|
|
187
|
+
} else {
|
|
188
|
+
return validateAsyncQuery(query, context, request)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const headers = validateParam(context[headersSchema], request, 'headers')
|
|
194
|
+
if (headers) {
|
|
195
|
+
if (typeof headers.then !== 'function') {
|
|
196
|
+
return wrapValidationError(headers, 'headers', context.schemaErrorFormatter)
|
|
197
|
+
} else {
|
|
198
|
+
return validateAsyncHeaders(headers, context, request)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return false
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function validateAsyncParams (validatePromise, context, request) {
|
|
206
|
+
return validatePromise
|
|
207
|
+
.then((paramsResult) => {
|
|
208
|
+
if (paramsResult) {
|
|
209
|
+
return wrapValidationError(paramsResult, 'params', context.schemaErrorFormatter)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return validate(context, request, { skipParams: true })
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function validateAsyncBody (validatePromise, context, request) {
|
|
217
|
+
return validatePromise
|
|
218
|
+
.then((bodyResult) => {
|
|
219
|
+
if (bodyResult) {
|
|
220
|
+
return wrapValidationError(bodyResult, 'body', context.schemaErrorFormatter)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return validate(context, request, { skipParams: true, skipBody: true })
|
|
224
|
+
})
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function validateAsyncQuery (validatePromise, context, request) {
|
|
228
|
+
return validatePromise
|
|
229
|
+
.then((queryResult) => {
|
|
230
|
+
if (queryResult) {
|
|
231
|
+
return wrapValidationError(queryResult, 'querystring', context.schemaErrorFormatter)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return validate(context, request, { skipParams: true, skipBody: true, skipQuery: true })
|
|
235
|
+
})
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function validateAsyncHeaders (validatePromise, context, request) {
|
|
239
|
+
return validatePromise
|
|
240
|
+
.then((headersResult) => {
|
|
241
|
+
if (headersResult) {
|
|
242
|
+
return wrapValidationError(headersResult, 'headers', context.schemaErrorFormatter)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return false
|
|
246
|
+
})
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function wrapValidationError (result, dataVar, schemaErrorFormatter) {
|
|
250
|
+
if (result instanceof Error) {
|
|
251
|
+
result.statusCode = result.statusCode || 400
|
|
252
|
+
result.code = result.code || 'FST_ERR_VALIDATION'
|
|
253
|
+
result.validationContext = result.validationContext || dataVar
|
|
254
|
+
return result
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const error = schemaErrorFormatter(result, dataVar)
|
|
258
|
+
error.statusCode = error.statusCode || 400
|
|
259
|
+
error.code = error.code || 'FST_ERR_VALIDATION'
|
|
260
|
+
error.validation = result
|
|
261
|
+
error.validationContext = dataVar
|
|
262
|
+
return error
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* simple function to retrieve the essence media type
|
|
267
|
+
* @param {string} header
|
|
268
|
+
* @returns {string} Mimetype string.
|
|
269
|
+
*/
|
|
270
|
+
function getEssenceMediaType (header) {
|
|
271
|
+
if (!header) return ''
|
|
272
|
+
return header.split(/[ ;]/, 1)[0].trim().toLowerCase()
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
module.exports = {
|
|
276
|
+
symbols: { bodySchema, querystringSchema, responseSchema, paramsSchema, headersSchema },
|
|
277
|
+
compileSchemasForValidation,
|
|
278
|
+
compileSchemasForSerialization,
|
|
279
|
+
validate
|
|
280
|
+
}
|
package/lib/warnings.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { createWarning } = require('process-warning')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Deprecation codes:
|
|
7
|
+
* - FSTWRN001
|
|
8
|
+
* - FSTSEC001
|
|
9
|
+
* - FSTDEP022
|
|
10
|
+
*
|
|
11
|
+
* Deprecation Codes FSTDEP001 - FSTDEP021 were used by v4 and MUST NOT not be reused.
|
|
12
|
+
* - FSTDEP022 is used by v5 and MUST NOT be reused.
|
|
13
|
+
* Warning Codes FSTWRN001 - FSTWRN002 were used by v4 and MUST NOT not be reused.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const FSTWRN001 = createWarning({
|
|
17
|
+
name: 'FastifyWarning',
|
|
18
|
+
code: 'FSTWRN001',
|
|
19
|
+
message: 'The %s schema for %s: %s is missing. This may indicate the schema is not well specified.',
|
|
20
|
+
unlimited: true
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const FSTWRN003 = createWarning({
|
|
24
|
+
name: 'FastifyWarning',
|
|
25
|
+
code: 'FSTWRN003',
|
|
26
|
+
message: 'The %s mixes async and callback styles that may lead to unhandled rejections. Please use only one of them.',
|
|
27
|
+
unlimited: true
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const FSTWRN004 = createWarning({
|
|
31
|
+
name: 'FastifyWarning',
|
|
32
|
+
code: 'FSTWRN004',
|
|
33
|
+
message: 'It seems that you are overriding an errorHandler in the same scope, which can lead to subtle bugs.',
|
|
34
|
+
unlimited: true
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const FSTSEC001 = createWarning({
|
|
38
|
+
name: 'FastifySecurity',
|
|
39
|
+
code: 'FSTSEC001',
|
|
40
|
+
message: 'You are using /%s/ Content-Type which may be vulnerable to CORS attack. Please make sure your RegExp start with "^" or include ";?" to proper detection of the essence MIME type.',
|
|
41
|
+
unlimited: true
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const FSTDEP022 = createWarning({
|
|
45
|
+
name: 'FastifyWarning',
|
|
46
|
+
code: 'FSTDEP022',
|
|
47
|
+
message: 'The router options for %s property access is deprecated. Please use "options.routerOptions" instead for accessing router options. The router options will be removed in `fastify@6`.',
|
|
48
|
+
unlimited: true
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
module.exports = {
|
|
52
|
+
FSTWRN001,
|
|
53
|
+
FSTWRN003,
|
|
54
|
+
FSTWRN004,
|
|
55
|
+
FSTSEC001,
|
|
56
|
+
FSTDEP022
|
|
57
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
kReplyIsError,
|
|
5
|
+
kReplyHijacked
|
|
6
|
+
} = require('./symbols')
|
|
7
|
+
const { setErrorStatusCode } = require('./error-status')
|
|
8
|
+
|
|
9
|
+
const diagnostics = require('node:diagnostics_channel')
|
|
10
|
+
const channels = diagnostics.tracingChannel('fastify.request.handler')
|
|
11
|
+
|
|
12
|
+
function wrapThenable (thenable, reply, store) {
|
|
13
|
+
if (store) store.async = true
|
|
14
|
+
thenable.then(function (payload) {
|
|
15
|
+
if (reply[kReplyHijacked] === true) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (store) {
|
|
20
|
+
channels.asyncStart.publish(store)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
// this is for async functions that are using reply.send directly
|
|
25
|
+
//
|
|
26
|
+
// since wrap-thenable will be called when using reply.send directly
|
|
27
|
+
// without actual return. the response can be sent already or
|
|
28
|
+
// the request may be terminated during the reply. in this situation,
|
|
29
|
+
// it require an extra checking of request.aborted to see whether
|
|
30
|
+
// the request is killed by client.
|
|
31
|
+
if (payload !== undefined || //
|
|
32
|
+
(reply.sent === false && //
|
|
33
|
+
reply.raw.headersSent === false &&
|
|
34
|
+
reply.request.raw.aborted === false &&
|
|
35
|
+
reply.request.socket &&
|
|
36
|
+
!reply.request.socket.destroyed
|
|
37
|
+
)
|
|
38
|
+
) {
|
|
39
|
+
// we use a try-catch internally to avoid adding a catch to another
|
|
40
|
+
// promise, increase promise perf by 10%
|
|
41
|
+
try {
|
|
42
|
+
reply.send(payload)
|
|
43
|
+
} catch (err) {
|
|
44
|
+
reply[kReplyIsError] = true
|
|
45
|
+
reply.send(err)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} finally {
|
|
49
|
+
if (store) {
|
|
50
|
+
channels.asyncEnd.publish(store)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}, function (err) {
|
|
54
|
+
if (store) {
|
|
55
|
+
store.error = err
|
|
56
|
+
// Set status code before publishing so subscribers see the correct value
|
|
57
|
+
setErrorStatusCode(reply, err)
|
|
58
|
+
channels.error.publish(store) // note that error happens before asyncStart
|
|
59
|
+
channels.asyncStart.publish(store)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
if (reply.sent === true) {
|
|
64
|
+
reply.log.error({ err }, 'Promise errored, but reply.sent = true was set')
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
reply[kReplyIsError] = true
|
|
69
|
+
|
|
70
|
+
reply.send(err)
|
|
71
|
+
// The following should not happen
|
|
72
|
+
/* c8 ignore next 3 */
|
|
73
|
+
} catch (err) {
|
|
74
|
+
// try-catch allow to re-throw error in error handler for async handler
|
|
75
|
+
reply.send(err)
|
|
76
|
+
} finally {
|
|
77
|
+
if (store) {
|
|
78
|
+
channels.asyncEnd.publish(store)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = wrapThenable
|
package/package.json
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "node-fastify",
|
|
3
|
+
"version": "5.8.3",
|
|
4
|
+
"description": "Fast and low overhead web framework, for Node.js",
|
|
5
|
+
"main": "fastify.js",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"types": "fastify.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"bench": "branchcmp -r 2 -g -s \"npm run benchmark\"",
|
|
10
|
+
"benchmark": "concurrently -k -s first \"node ./examples/benchmark/simple.js\" \"autocannon -c 100 -d 30 -p 10 localhost:3000/\"",
|
|
11
|
+
"benchmark:parser": "concurrently -k -s first \"node ./examples/benchmark/parser.js\" \"autocannon -c 100 -d 30 -p 10 -i ./examples/benchmark/body.json -H \"content-type:application/jsoff\" -m POST localhost:3000/\"",
|
|
12
|
+
"benchmark:parser:error": "concurrently -k -s first \"node ./examples/benchmark/parser.js\" \"autocannon -c 100 -d 30 -p 10 -i ./examples/benchmark/body.json -H \"content-type:application/jsoff\" -H \"content-length:123\" -m POST localhost:3000/\"",
|
|
13
|
+
"build:validation": "node build/build-error-serializer.js && node build/build-validation.js",
|
|
14
|
+
"build:sync-version": "node build/sync-version.js",
|
|
15
|
+
"coverage": "c8 --reporter html borp --reporter=@jsumners/line-reporter",
|
|
16
|
+
"coverage:ci-check-coverage": "borp --reporter=@jsumners/line-reporter --coverage --check-coverage --lines 100",
|
|
17
|
+
"lint": "npm run lint:eslint",
|
|
18
|
+
"lint:fix": "eslint --fix",
|
|
19
|
+
"lint:markdown": "markdownlint-cli2",
|
|
20
|
+
"lint:eslint": "eslint",
|
|
21
|
+
"prepublishOnly": "cross-env PREPUBLISH=true borp --reporter=@jsumners/line-reporter && npm run test:validator:integrity && npm run build:sync-version",
|
|
22
|
+
"test": "npm run lint && npm run unit && npm run test:typescript",
|
|
23
|
+
"test:ci": "npm run unit && npm run test:typescript",
|
|
24
|
+
"test:report": "npm run lint && npm run unit:report && npm run test:typescript",
|
|
25
|
+
"test:validator:integrity": "npm run build:validation && git diff --quiet --ignore-all-space --ignore-blank-lines --ignore-cr-at-eol lib/error-serializer.js && git diff --quiet --ignore-all-space --ignore-blank-lines --ignore-cr-at-eol lib/config-validator.js",
|
|
26
|
+
"test:typescript": "tsc test/types/import.ts --target es2022 --moduleResolution node16 --module node16 --noEmit && tsd",
|
|
27
|
+
"test:watch": "npm run unit -- --watch --coverage-report=none --reporter=terse",
|
|
28
|
+
"unit": "borp",
|
|
29
|
+
"unit:report": "c8 --reporter html borp --reporter=@jsumners/line-reporter",
|
|
30
|
+
"citgm": "borp --reporter=@jsumners/line-reporter --coverage --check-coverage --concurrency=1"
|
|
31
|
+
},
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/fastify/fastify.git"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"web",
|
|
38
|
+
"framework",
|
|
39
|
+
"json",
|
|
40
|
+
"schema",
|
|
41
|
+
"open",
|
|
42
|
+
"api"
|
|
43
|
+
],
|
|
44
|
+
"author": "Matteo Collina <hello@matteocollina.com>",
|
|
45
|
+
"contributors": [
|
|
46
|
+
{
|
|
47
|
+
"name": "Tomas Della Vedova",
|
|
48
|
+
"url": "http://delved.org",
|
|
49
|
+
"author": true
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "Tommaso Allevi",
|
|
53
|
+
"email": "tomallevi@gmail.com"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "Ethan Arrowood",
|
|
57
|
+
"url": "https://github.com/Ethan-Arrowood",
|
|
58
|
+
"email": "ethan.arrowood@gmail.com"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"name": "Dustin Deus",
|
|
62
|
+
"url": "http://starptech.de",
|
|
63
|
+
"email": "deusdustin@gmail.com"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"name": "Ayoub El Khattabi",
|
|
67
|
+
"url": "https://github.com/AyoubElk",
|
|
68
|
+
"email": "elkhattabi.ayoub@gmail.com"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "Rafael Gonzaga",
|
|
72
|
+
"email": "rafael.nunu@hotmail.com",
|
|
73
|
+
"url": "https://github.com/rafaelgss"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "Trivikram Kamat",
|
|
77
|
+
"url": "http://trivikr.github.io",
|
|
78
|
+
"email": "trivikr.dev@gmail.com"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"name": "Luciano Mammino",
|
|
82
|
+
"url": "https://loige.co"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "Cemre Mengu",
|
|
86
|
+
"email": "cemremengu@gmail.com"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "Evan Shortiss",
|
|
90
|
+
"email": "evanshortiss@gmail.com"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"name": "Maksim Sinik",
|
|
94
|
+
"url": "https://maksim.dev"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"name": "Manuel Spigolon",
|
|
98
|
+
"email": "behemoth89@gmail.com"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"name": "James Sumners",
|
|
102
|
+
"url": "https://james.sumners.info"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "Denis Fäcke",
|
|
106
|
+
"url": "https://github.com/SerayaEryn"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"name": "Igor Savin",
|
|
110
|
+
"email": "kibertoad@gmail.com",
|
|
111
|
+
"url": "https://github.com/kibertoad"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"name": "Vincent Le Goff",
|
|
115
|
+
"email": "vince.legoff@gmail.com",
|
|
116
|
+
"url": "https://github.com/zekth"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"name": "Luis Orbaiceta",
|
|
120
|
+
"email": "luisorbaiceta@gmail.com",
|
|
121
|
+
"url": "https://luisorbaiceta.com"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "Carlos Fuentes",
|
|
125
|
+
"email": "me@metcoder.dev",
|
|
126
|
+
"url": "https://metcoder.dev"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "Gürgün Dayıoğlu",
|
|
130
|
+
"email": "hey@gurgun.day",
|
|
131
|
+
"url": "https://heyhey.to/G"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"name": "Aras Abbasi",
|
|
135
|
+
"email": "aras.abbasi@gmail.com"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"name": "Frazer Smith",
|
|
139
|
+
"email": "frazer.dev@icloud.com",
|
|
140
|
+
"url": "https://github.com/fdawgs"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"name": "KaKa Ng",
|
|
144
|
+
"email": "kaka@kakang.dev",
|
|
145
|
+
"url": "https://github.com/climba03003"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"name": "Jean Michelet",
|
|
149
|
+
"email": "jean.antoine.michelet@gmail.com",
|
|
150
|
+
"url": "https://github.com/jean-michelet"
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
"license": "MIT",
|
|
154
|
+
"bugs": {
|
|
155
|
+
"url": "https://github.com/fastify/fastify/issues"
|
|
156
|
+
},
|
|
157
|
+
"homepage": "https://fastify.dev/",
|
|
158
|
+
"funding": [
|
|
159
|
+
{
|
|
160
|
+
"type": "github",
|
|
161
|
+
"url": "https://github.com/sponsors/fastify"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"type": "opencollective",
|
|
165
|
+
"url": "https://opencollective.com/fastify"
|
|
166
|
+
}
|
|
167
|
+
],
|
|
168
|
+
"devDependencies": {
|
|
169
|
+
"@jsumners/line-reporter": "^1.0.1",
|
|
170
|
+
"@sinonjs/fake-timers": "^11.2.2",
|
|
171
|
+
"@stylistic/eslint-plugin": "^5.1.0",
|
|
172
|
+
"@stylistic/eslint-plugin-js": "^4.1.0",
|
|
173
|
+
"@types/node": "^25.0.3",
|
|
174
|
+
"ajv": "^8.12.0",
|
|
175
|
+
"ajv-errors": "^3.0.0",
|
|
176
|
+
"ajv-formats": "^3.0.1",
|
|
177
|
+
"ajv-i18n": "^4.2.0",
|
|
178
|
+
"ajv-merge-patch": "^5.0.1",
|
|
179
|
+
"autocannon": "^8.0.0",
|
|
180
|
+
"borp": "^0.21.0",
|
|
181
|
+
"branch-comparer": "^1.1.0",
|
|
182
|
+
"concurrently": "^9.1.2",
|
|
183
|
+
"cross-env": "^10.0.0",
|
|
184
|
+
"eslint": "^9.0.0",
|
|
185
|
+
"fast-json-body": "^1.1.0",
|
|
186
|
+
"fastify-plugin": "^5.0.0",
|
|
187
|
+
"fluent-json-schema": "^6.0.0",
|
|
188
|
+
"h2url": "^0.2.0",
|
|
189
|
+
"http-errors": "^2.0.0",
|
|
190
|
+
"joi": "^18.0.1",
|
|
191
|
+
"json-schema-to-ts": "^3.0.1",
|
|
192
|
+
"JSONStream": "^1.3.5",
|
|
193
|
+
"markdownlint-cli2": "^0.21.0",
|
|
194
|
+
"neostandard": "^0.12.0",
|
|
195
|
+
"node-forge": "^1.3.1",
|
|
196
|
+
"proxyquire": "^2.1.3",
|
|
197
|
+
"split2": "^4.2.0",
|
|
198
|
+
"tsd": "^0.33.0",
|
|
199
|
+
"typebox": "^1.0.81",
|
|
200
|
+
"typescript": "~5.9.2",
|
|
201
|
+
"undici": "^7.11.0",
|
|
202
|
+
"vary": "^1.1.2",
|
|
203
|
+
"yup": "^1.4.0"
|
|
204
|
+
},
|
|
205
|
+
"dependencies": {
|
|
206
|
+
"@fastify/ajv-compiler": "^4.0.5",
|
|
207
|
+
"@fastify/error": "^4.0.0",
|
|
208
|
+
"@fastify/fast-json-stringify-compiler": "^5.0.0",
|
|
209
|
+
"@fastify/proxy-addr": "^5.0.0",
|
|
210
|
+
"abstract-logging": "^2.0.1",
|
|
211
|
+
"avvio": "^9.0.0",
|
|
212
|
+
"fast-json-stringify": "^6.0.0",
|
|
213
|
+
"find-my-way": "^9.0.0",
|
|
214
|
+
"light-my-request": "^6.0.0",
|
|
215
|
+
"pino": "^9.14.0 || ^10.1.0",
|
|
216
|
+
"process-warning": "^5.0.0",
|
|
217
|
+
"rfdc": "^1.3.1",
|
|
218
|
+
"secure-json-parse": "^4.0.0",
|
|
219
|
+
"semver": "^7.6.0",
|
|
220
|
+
"toad-cache": "^3.7.0"
|
|
221
|
+
},
|
|
222
|
+
"tsd": {
|
|
223
|
+
"directory": "test/types"
|
|
224
|
+
}
|
|
225
|
+
}
|