fastify 3.27.4 → 4.0.0-alpha.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/.taprc +3 -0
- package/README.md +7 -7
- package/build/build-error-serializer.js +27 -0
- package/build/build-validation.js +47 -35
- package/docs/Guides/Database.md +320 -0
- package/docs/Guides/Ecosystem.md +9 -0
- package/docs/Guides/Getting-Started.md +7 -7
- package/docs/Guides/Plugins-Guide.md +1 -1
- package/docs/Guides/Serverless.md +3 -3
- package/docs/Guides/Testing.md +2 -2
- package/docs/Migration-Guide-V4.md +12 -0
- package/docs/Reference/ContentTypeParser.md +4 -0
- package/docs/Reference/Decorators.md +2 -2
- package/docs/Reference/Encapsulation.md +2 -2
- package/docs/Reference/Errors.md +51 -6
- package/docs/Reference/HTTP2.md +3 -3
- package/docs/Reference/Hooks.md +4 -7
- package/docs/Reference/LTS.md +5 -4
- package/docs/Reference/Plugins.md +3 -3
- package/docs/Reference/Reply.md +73 -22
- package/docs/Reference/Request.md +1 -3
- package/docs/Reference/Routes.md +22 -15
- package/docs/Reference/Server.md +69 -119
- package/docs/Reference/TypeScript.md +20 -22
- package/docs/Reference/Validation-and-Serialization.md +30 -55
- package/docs/Type-Providers.md +257 -0
- package/examples/asyncawait.js +1 -1
- package/examples/benchmark/hooks-benchmark-async-await.js +1 -1
- package/examples/benchmark/hooks-benchmark.js +1 -1
- package/examples/benchmark/simple.js +1 -1
- package/examples/hooks.js +2 -2
- package/examples/http2.js +1 -1
- package/examples/https.js +1 -1
- package/examples/parser.js +13 -3
- package/examples/route-prefix.js +1 -1
- package/examples/shared-schema.js +1 -1
- package/examples/simple-stream.js +18 -0
- package/examples/simple.js +1 -1
- package/examples/simple.mjs +1 -1
- package/examples/typescript-server.ts +1 -1
- package/examples/use-plugin.js +1 -1
- package/fastify.d.ts +34 -22
- package/fastify.js +40 -36
- package/lib/configValidator.js +902 -1023
- package/lib/contentTypeParser.js +6 -16
- package/lib/context.js +36 -10
- package/lib/decorate.js +3 -1
- package/lib/error-handler.js +158 -0
- package/lib/error-serializer.js +257 -0
- package/lib/errors.js +51 -9
- package/lib/fourOhFour.js +31 -20
- package/lib/handleRequest.js +10 -13
- package/lib/hooks.js +14 -9
- package/lib/pluginOverride.js +0 -3
- package/lib/pluginUtils.js +3 -2
- package/lib/reply.js +121 -175
- package/lib/request.js +13 -10
- package/lib/route.js +131 -138
- package/lib/schema-controller.js +2 -2
- package/lib/schemas.js +27 -1
- package/lib/server.js +242 -116
- package/lib/symbols.js +5 -3
- package/lib/validation.js +11 -9
- package/lib/warnings.js +4 -12
- package/lib/wrapThenable.js +4 -11
- package/package.json +37 -39
- package/test/404s.test.js +258 -125
- package/test/500s.test.js +3 -3
- package/test/als.test.js +1 -1
- package/test/async-await.test.js +20 -76
- package/test/bodyLimit.test.js +1 -1
- package/test/build-certificate.js +6 -7
- package/test/case-insensitive.test.js +4 -4
- package/test/close-pipelining.test.js +2 -2
- package/test/close.test.js +11 -11
- package/test/content-parser.test.js +32 -0
- package/test/context-config.test.js +52 -0
- package/test/custom-http-server.test.js +14 -7
- package/test/custom-parser-async.test.js +1 -66
- package/test/custom-parser.test.js +92 -159
- package/test/custom-querystring-parser.test.js +3 -3
- package/test/decorator.test.js +11 -13
- package/test/delete.test.js +6 -6
- package/test/encapsulated-error-handler.test.js +50 -0
- package/test/esm/index.test.js +0 -14
- package/test/fastify-instance.test.js +4 -4
- package/test/fluent-schema.test.js +4 -4
- package/test/genReqId.test.js +1 -1
- package/test/get.test.js +4 -4
- package/test/handler-context.test.js +2 -2
- package/test/head.test.js +1 -1
- package/test/helper.js +19 -4
- package/test/hooks-async.test.js +15 -48
- package/test/hooks.on-ready.test.js +10 -5
- package/test/hooks.test.js +78 -119
- package/test/http2/closing.test.js +10 -16
- package/test/http2/constraint.test.js +1 -1
- package/test/http2/head.test.js +1 -1
- package/test/http2/plain.test.js +1 -1
- package/test/http2/secure-with-fallback.test.js +1 -1
- package/test/http2/secure.test.js +1 -1
- package/test/http2/unknown-http-method.test.js +4 -10
- package/test/https/custom-https-server.test.js +12 -6
- package/test/https/https.test.js +1 -1
- package/test/input-validation.js +3 -3
- package/test/internals/handleRequest.test.js +6 -43
- package/test/internals/initialConfig.test.js +41 -12
- package/test/internals/logger.test.js +2 -2
- package/test/internals/reply.test.js +317 -48
- package/test/internals/request.test.js +13 -7
- package/test/internals/server.test.js +88 -0
- package/test/listen.deprecated.test.js +202 -0
- package/test/listen.test.js +140 -145
- package/test/logger.test.js +82 -42
- package/test/maxRequestsPerSocket.test.js +8 -6
- package/test/middleware.test.js +2 -25
- package/test/nullable-validation.test.js +53 -16
- package/test/output-validation.test.js +1 -1
- package/test/plugin.test.js +47 -21
- package/test/pretty-print.test.js +22 -10
- package/test/promises.test.js +1 -1
- package/test/proto-poisoning.test.js +6 -6
- package/test/register.test.js +3 -3
- package/test/reply-error.test.js +126 -15
- package/test/reply-trailers.test.js +270 -0
- package/test/request-error.test.js +3 -6
- package/test/route-hooks.test.js +18 -18
- package/test/route-prefix.test.js +2 -1
- package/test/route.test.js +206 -22
- package/test/router-options.test.js +2 -2
- package/test/schema-examples.test.js +11 -5
- package/test/schema-feature.test.js +25 -20
- package/test/schema-serialization.test.js +9 -9
- package/test/schema-special-usage.test.js +5 -153
- package/test/schema-validation.test.js +9 -9
- package/test/skip-reply-send.test.js +2 -2
- package/test/stream.test.js +82 -23
- package/test/throw.test.js +8 -5
- package/test/trust-proxy.test.js +6 -6
- package/test/type-provider.test.js +20 -0
- package/test/types/fastify.test-d.ts +10 -18
- package/test/types/hooks.test-d.ts +61 -5
- package/test/types/import.js +2 -0
- package/test/types/import.ts +1 -0
- package/test/types/instance.test-d.ts +68 -17
- package/test/types/logger.test-d.ts +44 -15
- package/test/types/reply.test-d.ts +2 -1
- package/test/types/request.test-d.ts +71 -1
- package/test/types/route.test-d.ts +8 -2
- package/test/types/schema.test-d.ts +2 -39
- package/test/types/type-provider.test-d.ts +424 -0
- package/test/url-rewriting.test.js +3 -3
- package/test/validation-error-handling.test.js +8 -8
- package/test/versioned-routes.test.js +30 -18
- package/test/wrapThenable.test.js +7 -6
- package/types/content-type-parser.d.ts +17 -8
- package/types/hooks.d.ts +182 -85
- package/types/instance.d.ts +286 -118
- package/types/logger.d.ts +18 -104
- package/types/plugin.d.ts +10 -4
- package/types/reply.d.ts +18 -12
- package/types/request.d.ts +13 -8
- package/types/route.d.ts +62 -34
- package/types/schema.d.ts +1 -1
- package/types/type-provider.d.ts +99 -0
- package/types/utils.d.ts +1 -1
- package/lib/schema-compilers.js +0 -12
- package/test/emit-warning.test.js +0 -166
package/lib/contentTypeParser.js
CHANGED
|
@@ -14,7 +14,8 @@ const {
|
|
|
14
14
|
kBodyLimit,
|
|
15
15
|
kRequestPayloadStream,
|
|
16
16
|
kState,
|
|
17
|
-
kTestInternals
|
|
17
|
+
kTestInternals,
|
|
18
|
+
kReplyIsError
|
|
18
19
|
} = require('./symbols')
|
|
19
20
|
|
|
20
21
|
const {
|
|
@@ -28,7 +29,6 @@ const {
|
|
|
28
29
|
FST_ERR_CTP_INVALID_CONTENT_LENGTH,
|
|
29
30
|
FST_ERR_CTP_EMPTY_JSON_BODY
|
|
30
31
|
} = require('./errors')
|
|
31
|
-
const warning = require('./warnings')
|
|
32
32
|
|
|
33
33
|
function ContentTypeParser (bodyLimit, onProtoPoisoning, onConstructorPoisoning) {
|
|
34
34
|
this[kDefaultJsonParse] = getDefaultJsonParser(onProtoPoisoning, onConstructorPoisoning)
|
|
@@ -151,13 +151,7 @@ ContentTypeParser.prototype.run = function (contentType, handler, request, reply
|
|
|
151
151
|
done
|
|
152
152
|
)
|
|
153
153
|
} else {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if (parser.isDeprecatedSignature) {
|
|
157
|
-
result = parser.fn(request[kRequestPayloadStream], done)
|
|
158
|
-
} else {
|
|
159
|
-
result = parser.fn(request, request[kRequestPayloadStream], done)
|
|
160
|
-
}
|
|
154
|
+
const result = parser.fn(request, request[kRequestPayloadStream], done)
|
|
161
155
|
|
|
162
156
|
if (result && typeof result.then === 'function') {
|
|
163
157
|
result.then(body => done(null, body), done)
|
|
@@ -165,9 +159,10 @@ ContentTypeParser.prototype.run = function (contentType, handler, request, reply
|
|
|
165
159
|
}
|
|
166
160
|
|
|
167
161
|
function done (error, body) {
|
|
168
|
-
// We cannot use resource.bind() because it is broken in node v12
|
|
162
|
+
// We cannot use resource.bind() because it is broken in node v12 and v14
|
|
169
163
|
resource.runInAsyncScope(() => {
|
|
170
164
|
if (error) {
|
|
165
|
+
reply[kReplyIsError] = true
|
|
171
166
|
reply.send(error)
|
|
172
167
|
} else {
|
|
173
168
|
request.body = body
|
|
@@ -228,6 +223,7 @@ function rawBody (request, reply, options, parser, done) {
|
|
|
228
223
|
|
|
229
224
|
if (err !== undefined) {
|
|
230
225
|
err.statusCode = 400
|
|
226
|
+
reply[kReplyIsError] = true
|
|
231
227
|
reply.code(err.statusCode).send(err)
|
|
232
228
|
return
|
|
233
229
|
}
|
|
@@ -279,12 +275,6 @@ function Parser (asString, asBuffer, bodyLimit, fn) {
|
|
|
279
275
|
this.asBuffer = asBuffer
|
|
280
276
|
this.bodyLimit = bodyLimit
|
|
281
277
|
this.fn = fn
|
|
282
|
-
|
|
283
|
-
// Check for deprecation syntax
|
|
284
|
-
if (fn.length === (fn.constructor.name === 'AsyncFunction' ? 1 : 2)) {
|
|
285
|
-
warning.emit('FSTDEP003')
|
|
286
|
-
this.isDeprecatedSignature = true
|
|
287
|
-
}
|
|
288
278
|
}
|
|
289
279
|
|
|
290
280
|
function buildContentTypeParser (c) {
|
package/lib/context.js
CHANGED
|
@@ -1,15 +1,37 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const {
|
|
4
|
+
kFourOhFourContext,
|
|
5
|
+
kReplySerializerDefault,
|
|
6
|
+
kSchemaErrorFormatter,
|
|
7
|
+
kErrorHandler,
|
|
8
|
+
kReply,
|
|
9
|
+
kRequest,
|
|
10
|
+
kBodyLimit,
|
|
11
|
+
kLogLevel,
|
|
12
|
+
kContentTypeParser
|
|
13
|
+
} = require('./symbols.js')
|
|
4
14
|
|
|
5
15
|
// Objects that holds the context of every request
|
|
6
16
|
// Every route holds an instance of this object.
|
|
7
|
-
function Context (
|
|
17
|
+
function Context ({
|
|
18
|
+
schema,
|
|
19
|
+
handler,
|
|
20
|
+
config,
|
|
21
|
+
errorHandler,
|
|
22
|
+
bodyLimit,
|
|
23
|
+
logLevel,
|
|
24
|
+
logSerializers,
|
|
25
|
+
attachValidation,
|
|
26
|
+
replySerializer,
|
|
27
|
+
schemaErrorFormatter,
|
|
28
|
+
server
|
|
29
|
+
}) {
|
|
8
30
|
this.schema = schema
|
|
9
31
|
this.handler = handler
|
|
10
|
-
this.Reply =
|
|
11
|
-
this.Request =
|
|
12
|
-
this.contentTypeParser =
|
|
32
|
+
this.Reply = server[kReply]
|
|
33
|
+
this.Request = server[kRequest]
|
|
34
|
+
this.contentTypeParser = server[kContentTypeParser]
|
|
13
35
|
this.onRequest = null
|
|
14
36
|
this.onSend = null
|
|
15
37
|
this.onError = null
|
|
@@ -17,15 +39,19 @@ function Context (schema, handler, Reply, Request, contentTypeParser, config, er
|
|
|
17
39
|
this.preHandler = null
|
|
18
40
|
this.onResponse = null
|
|
19
41
|
this.config = config
|
|
20
|
-
this.errorHandler = errorHandler
|
|
42
|
+
this.errorHandler = errorHandler || server[kErrorHandler]
|
|
21
43
|
this._middie = null
|
|
22
|
-
this._parserOptions = {
|
|
23
|
-
|
|
44
|
+
this._parserOptions = {
|
|
45
|
+
limit: bodyLimit || server[kBodyLimit]
|
|
46
|
+
}
|
|
47
|
+
this.logLevel = logLevel || server[kLogLevel]
|
|
24
48
|
this.logSerializers = logSerializers
|
|
25
49
|
this[kFourOhFourContext] = null
|
|
26
50
|
this.attachValidation = attachValidation
|
|
27
51
|
this[kReplySerializerDefault] = replySerializer
|
|
28
|
-
this.schemaErrorFormatter = schemaErrorFormatter || defaultSchemaErrorFormatter
|
|
52
|
+
this.schemaErrorFormatter = schemaErrorFormatter || server[kSchemaErrorFormatter] || defaultSchemaErrorFormatter
|
|
53
|
+
|
|
54
|
+
this.server = server
|
|
29
55
|
}
|
|
30
56
|
|
|
31
57
|
function defaultSchemaErrorFormatter (errors, dataVar) {
|
|
@@ -35,7 +61,7 @@ function defaultSchemaErrorFormatter (errors, dataVar) {
|
|
|
35
61
|
// eslint-disable-next-line no-var
|
|
36
62
|
for (var i = 0; i !== errors.length; ++i) {
|
|
37
63
|
const e = errors[i]
|
|
38
|
-
text += dataVar + (e.
|
|
64
|
+
text += dataVar + (e.instancePath || '') + ' ' + e.message + separator
|
|
39
65
|
}
|
|
40
66
|
return new Error(text.slice(0, -separator.length))
|
|
41
67
|
}
|
package/lib/decorate.js
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
const {
|
|
6
6
|
kReply,
|
|
7
7
|
kRequest,
|
|
8
|
-
kState
|
|
8
|
+
kState,
|
|
9
|
+
kHasBeenDecorated
|
|
9
10
|
} = require('./symbols.js')
|
|
10
11
|
|
|
11
12
|
const {
|
|
@@ -40,6 +41,7 @@ function decorateConstructor (konstructor, name, fn, dependencies) {
|
|
|
40
41
|
throw new FST_ERR_DEC_ALREADY_PRESENT(name)
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
konstructor[kHasBeenDecorated] = true
|
|
43
45
|
checkDependencies(konstructor, name, dependencies)
|
|
44
46
|
|
|
45
47
|
if (fn && (typeof fn.getter === 'function' || typeof fn.setter === 'function')) {
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const statusCodes = require('http').STATUS_CODES
|
|
4
|
+
const wrapThenable = require('./wrapThenable')
|
|
5
|
+
const {
|
|
6
|
+
kReplyHeaders, kReplyNextErrorHandler, kReplyIsRunningOnErrorHook, kReplyHasStatusCode
|
|
7
|
+
} = require('./symbols.js')
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
FST_ERR_REP_INVALID_PAYLOAD_TYPE
|
|
11
|
+
} = require('./errors')
|
|
12
|
+
|
|
13
|
+
const { getSchemaSerializer } = require('./schemas')
|
|
14
|
+
|
|
15
|
+
const serializeError = require('./error-serializer')
|
|
16
|
+
|
|
17
|
+
const rootErrorHandler = {
|
|
18
|
+
func: defaultErrorHandler,
|
|
19
|
+
toJSON () {
|
|
20
|
+
return this.func.name.toString() + '()'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function handleError (reply, error, cb) {
|
|
25
|
+
reply[kReplyIsRunningOnErrorHook] = false
|
|
26
|
+
|
|
27
|
+
const context = reply.context
|
|
28
|
+
if (reply[kReplyNextErrorHandler] === false) {
|
|
29
|
+
fallbackErrorHandler(error, reply, function (reply, payload) {
|
|
30
|
+
try {
|
|
31
|
+
reply.raw.writeHead(reply.raw.statusCode, reply[kReplyHeaders])
|
|
32
|
+
} catch (error) {
|
|
33
|
+
reply.log.warn(
|
|
34
|
+
{ req: reply.request, res: reply, err: error },
|
|
35
|
+
error && error.message
|
|
36
|
+
)
|
|
37
|
+
reply.raw.writeHead(reply.raw.statusCode)
|
|
38
|
+
}
|
|
39
|
+
reply.raw.end(payload)
|
|
40
|
+
})
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
const errorHandler = reply[kReplyNextErrorHandler] || context.errorHandler
|
|
44
|
+
|
|
45
|
+
// In case the error handler throws, we set the next errorHandler so we can error again
|
|
46
|
+
reply[kReplyNextErrorHandler] = Object.getPrototypeOf(errorHandler)
|
|
47
|
+
|
|
48
|
+
delete reply[kReplyHeaders]['content-length']
|
|
49
|
+
|
|
50
|
+
const func = errorHandler.func
|
|
51
|
+
|
|
52
|
+
if (!func) {
|
|
53
|
+
reply[kReplyNextErrorHandler] = false
|
|
54
|
+
fallbackErrorHandler(error, reply, cb)
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const result = func(error, reply.request, reply)
|
|
59
|
+
if (result !== undefined) {
|
|
60
|
+
if (result !== null && typeof result.then === 'function') {
|
|
61
|
+
wrapThenable(result, reply)
|
|
62
|
+
} else {
|
|
63
|
+
reply.send(result)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function defaultErrorHandler (error, request, reply) {
|
|
69
|
+
setErrorHeaders(error, reply)
|
|
70
|
+
if (!reply[kReplyHasStatusCode] || reply.statusCode === 200) {
|
|
71
|
+
const statusCode = error.statusCode || error.status
|
|
72
|
+
reply.code(statusCode >= 400 ? statusCode : 500)
|
|
73
|
+
}
|
|
74
|
+
if (reply.statusCode < 500) {
|
|
75
|
+
reply.log.info(
|
|
76
|
+
{ res: reply, err: error },
|
|
77
|
+
error && error.message
|
|
78
|
+
)
|
|
79
|
+
} else {
|
|
80
|
+
reply.log.error(
|
|
81
|
+
{ req: request, res: reply, err: error },
|
|
82
|
+
error && error.message
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
reply.send(error)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function fallbackErrorHandler (error, reply, cb) {
|
|
89
|
+
const res = reply.raw
|
|
90
|
+
const statusCode = reply.statusCode
|
|
91
|
+
let payload
|
|
92
|
+
try {
|
|
93
|
+
const serializerFn = getSchemaSerializer(reply.context, statusCode)
|
|
94
|
+
payload = (serializerFn === false)
|
|
95
|
+
? serializeError({
|
|
96
|
+
error: statusCodes[statusCode + ''],
|
|
97
|
+
code: error.code,
|
|
98
|
+
message: error.message,
|
|
99
|
+
statusCode
|
|
100
|
+
})
|
|
101
|
+
: serializerFn(Object.create(error, {
|
|
102
|
+
error: { value: statusCodes[statusCode + ''] },
|
|
103
|
+
message: { value: error.message },
|
|
104
|
+
statusCode: { value: statusCode }
|
|
105
|
+
}))
|
|
106
|
+
} catch (err) {
|
|
107
|
+
// error is always FST_ERR_SCH_SERIALIZATION_BUILD because this is called from route/compileSchemasForSerialization
|
|
108
|
+
reply.log.error({ err, statusCode: res.statusCode }, 'The serializer for the given status code failed')
|
|
109
|
+
reply.code(500)
|
|
110
|
+
payload = serializeError({
|
|
111
|
+
error: statusCodes['500'],
|
|
112
|
+
message: err.message,
|
|
113
|
+
statusCode: 500
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (typeof payload !== 'string' && !Buffer.isBuffer(payload)) {
|
|
118
|
+
payload = serializeError(new FST_ERR_REP_INVALID_PAYLOAD_TYPE(typeof payload))
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
reply[kReplyHeaders]['content-type'] = 'application/json; charset=utf-8'
|
|
122
|
+
reply[kReplyHeaders]['content-length'] = '' + Buffer.byteLength(payload)
|
|
123
|
+
|
|
124
|
+
cb(reply, payload)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function buildErrorHandler (parent = rootErrorHandler, func) {
|
|
128
|
+
if (!func) {
|
|
129
|
+
return parent
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const errorHandler = Object.create(parent)
|
|
133
|
+
errorHandler.func = func
|
|
134
|
+
return errorHandler
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function setErrorHeaders (error, reply) {
|
|
138
|
+
const res = reply.raw
|
|
139
|
+
let statusCode = res.statusCode
|
|
140
|
+
statusCode = (statusCode >= 400) ? statusCode : 500
|
|
141
|
+
// treat undefined and null as same
|
|
142
|
+
if (error != null) {
|
|
143
|
+
if (error.headers !== undefined) {
|
|
144
|
+
reply.headers(error.headers)
|
|
145
|
+
}
|
|
146
|
+
if (error.status >= 400) {
|
|
147
|
+
statusCode = error.status
|
|
148
|
+
} else if (error.statusCode >= 400) {
|
|
149
|
+
statusCode = error.statusCode
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
res.statusCode = statusCode
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
module.exports = {
|
|
156
|
+
buildErrorHandler,
|
|
157
|
+
handleError
|
|
158
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
// This file is autogenerated by build/build-error-serializer.js, do not edit
|
|
2
|
+
/* istanbul ignore file */
|
|
3
|
+
module.exports = $main
|
|
4
|
+
'use strict'
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
function $pad2Zeros (num) {
|
|
8
|
+
const s = '00' + num
|
|
9
|
+
return s[s.length - 2] + s[s.length - 1]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function $asAny (i) {
|
|
13
|
+
return JSON.stringify(i)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function $asNull () {
|
|
17
|
+
return 'null'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function $asInteger (i) {
|
|
21
|
+
if (typeof i === 'bigint') {
|
|
22
|
+
return i.toString()
|
|
23
|
+
} else if (Number.isInteger(i)) {
|
|
24
|
+
return $asNumber(i)
|
|
25
|
+
} else {
|
|
26
|
+
/* eslint no-undef: "off" */
|
|
27
|
+
return $asNumber(parseInteger(i))
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function $asIntegerNullable (i) {
|
|
32
|
+
return i === null ? null : $asInteger(i)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function $asNumber (i) {
|
|
36
|
+
const num = Number(i)
|
|
37
|
+
if (isNaN(num)) {
|
|
38
|
+
return 'null'
|
|
39
|
+
} else {
|
|
40
|
+
return '' + num
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function $asNumberNullable (i) {
|
|
45
|
+
return i === null ? null : $asNumber(i)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function $asBoolean (bool) {
|
|
49
|
+
return bool && 'true' || 'false' // eslint-disable-line
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function $asBooleanNullable (bool) {
|
|
53
|
+
return bool === null ? null : $asBoolean(bool)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function $asDatetime (date, skipQuotes) {
|
|
57
|
+
const quotes = skipQuotes === true ? '' : '"'
|
|
58
|
+
if (date instanceof Date) {
|
|
59
|
+
return quotes + date.toISOString() + quotes
|
|
60
|
+
} else if (date && typeof date.toISOString === 'function') {
|
|
61
|
+
return quotes + date.toISOString() + quotes
|
|
62
|
+
} else {
|
|
63
|
+
return $asString(date, skipQuotes)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function $asDate (date, skipQuotes) {
|
|
68
|
+
const quotes = skipQuotes === true ? '' : '"'
|
|
69
|
+
if (date instanceof Date) {
|
|
70
|
+
return quotes + new Date(date.getTime() - (date.getTimezoneOffset() * 60000 )).toISOString().slice(0, 10) + quotes
|
|
71
|
+
} else if (date && typeof date.format === 'function') {
|
|
72
|
+
return quotes + date.format('YYYY-MM-DD') + quotes
|
|
73
|
+
} else {
|
|
74
|
+
return $asString(date, skipQuotes)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function $asTime (date, skipQuotes) {
|
|
79
|
+
const quotes = skipQuotes === true ? '' : '"'
|
|
80
|
+
if (date instanceof Date) {
|
|
81
|
+
const hour = new Intl.DateTimeFormat('en', { hour: 'numeric', hour12: false }).format(date)
|
|
82
|
+
const minute = new Intl.DateTimeFormat('en', { minute: 'numeric' }).format(date)
|
|
83
|
+
const second = new Intl.DateTimeFormat('en', { second: 'numeric' }).format(date)
|
|
84
|
+
return quotes + $pad2Zeros(hour) + ':' + $pad2Zeros(minute) + ':' + $pad2Zeros(second) + quotes
|
|
85
|
+
} else if (date && typeof date.format === 'function') {
|
|
86
|
+
return quotes + date.format('HH:mm:ss') + quotes
|
|
87
|
+
} else {
|
|
88
|
+
return $asString(date, skipQuotes)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function $asString (str, skipQuotes) {
|
|
93
|
+
const quotes = skipQuotes === true ? '' : '"'
|
|
94
|
+
if (str instanceof Date) {
|
|
95
|
+
return quotes + str.toISOString() + quotes
|
|
96
|
+
} else if (str === null) {
|
|
97
|
+
return quotes + quotes
|
|
98
|
+
} else if (str instanceof RegExp) {
|
|
99
|
+
str = str.source
|
|
100
|
+
} else if (typeof str !== 'string') {
|
|
101
|
+
str = str.toString()
|
|
102
|
+
}
|
|
103
|
+
// If we skipQuotes it means that we are using it as test
|
|
104
|
+
// no need to test the string length for the render
|
|
105
|
+
if (skipQuotes) {
|
|
106
|
+
return str
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (str.length < 42) {
|
|
110
|
+
return $asStringSmall(str)
|
|
111
|
+
} else {
|
|
112
|
+
return JSON.stringify(str)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function $asStringNullable (str) {
|
|
117
|
+
return str === null ? null : $asString(str)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// magically escape strings for json
|
|
121
|
+
// relying on their charCodeAt
|
|
122
|
+
// everything below 32 needs JSON.stringify()
|
|
123
|
+
// every string that contain surrogate needs JSON.stringify()
|
|
124
|
+
// 34 and 92 happens all the time, so we
|
|
125
|
+
// have a fast case for them
|
|
126
|
+
function $asStringSmall (str) {
|
|
127
|
+
const l = str.length
|
|
128
|
+
let result = ''
|
|
129
|
+
let last = 0
|
|
130
|
+
let found = false
|
|
131
|
+
let surrogateFound = false
|
|
132
|
+
let point = 255
|
|
133
|
+
// eslint-disable-next-line
|
|
134
|
+
for (var i = 0; i < l && point >= 32; i++) {
|
|
135
|
+
point = str.charCodeAt(i)
|
|
136
|
+
if (point >= 0xD800 && point <= 0xDFFF) {
|
|
137
|
+
// The current character is a surrogate.
|
|
138
|
+
surrogateFound = true
|
|
139
|
+
}
|
|
140
|
+
if (point === 34 || point === 92) {
|
|
141
|
+
result += str.slice(last, i) + '\\'
|
|
142
|
+
last = i
|
|
143
|
+
found = true
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (!found) {
|
|
148
|
+
result = str
|
|
149
|
+
} else {
|
|
150
|
+
result += str.slice(last)
|
|
151
|
+
}
|
|
152
|
+
return ((point < 32) || (surrogateFound === true)) ? JSON.stringify(str) : '"' + result + '"'
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Used by schemas that are dependant on calling 'ajv.validate' during runtime,
|
|
159
|
+
* it stores the value of the '$id' property of the schema (if it has it) inside
|
|
160
|
+
* a cache which is used to figure out if the schema was compiled into a validator
|
|
161
|
+
* by ajv on a previous call, if it was then the '$id' string will be used to
|
|
162
|
+
* invoke 'ajv.validate', this allows:
|
|
163
|
+
*
|
|
164
|
+
* 1. Schemas that depend on ajv.validate calls to leverage ajv caching system.
|
|
165
|
+
* 2. To avoid errors, since directly invoking 'ajv.validate' with the same
|
|
166
|
+
* schema (that contains an '$id' property) twice will throw an error.
|
|
167
|
+
*/
|
|
168
|
+
const $validateWithAjv = (function() {
|
|
169
|
+
const cache = new Set()
|
|
170
|
+
|
|
171
|
+
return function (schema, target) {
|
|
172
|
+
const id = schema.$id
|
|
173
|
+
|
|
174
|
+
if (!id) {
|
|
175
|
+
return ajv.validate(schema, target)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const cached = cache.has(id)
|
|
179
|
+
|
|
180
|
+
if (cached) {
|
|
181
|
+
return ajv.validate(id, target)
|
|
182
|
+
} else {
|
|
183
|
+
cache.add(id)
|
|
184
|
+
return ajv.validate(schema, target)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
})()
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
function parseInteger(int) { return Math.trunc(int) }
|
|
191
|
+
|
|
192
|
+
function $main (input) {
|
|
193
|
+
|
|
194
|
+
var obj = (input && typeof input.toJSON === 'function')
|
|
195
|
+
? input.toJSON()
|
|
196
|
+
: input
|
|
197
|
+
|
|
198
|
+
var json = '{'
|
|
199
|
+
var addComma = false
|
|
200
|
+
|
|
201
|
+
var t = Number(obj["statusCode"])
|
|
202
|
+
if (!isNaN(t)) {
|
|
203
|
+
|
|
204
|
+
if (addComma) {
|
|
205
|
+
json += ','
|
|
206
|
+
} else {
|
|
207
|
+
addComma = true
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
json += "\"statusCode\"" + ':' + t
|
|
211
|
+
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (obj["code"] !== undefined) {
|
|
215
|
+
|
|
216
|
+
if (addComma) {
|
|
217
|
+
json += ','
|
|
218
|
+
} else {
|
|
219
|
+
addComma = true
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
json += "\"code\"" + ':'
|
|
223
|
+
json += $asString(obj["code"])
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (obj["error"] !== undefined) {
|
|
227
|
+
|
|
228
|
+
if (addComma) {
|
|
229
|
+
json += ','
|
|
230
|
+
} else {
|
|
231
|
+
addComma = true
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
json += "\"error\"" + ':'
|
|
235
|
+
json += $asString(obj["error"])
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (obj["message"] !== undefined) {
|
|
239
|
+
|
|
240
|
+
if (addComma) {
|
|
241
|
+
json += ','
|
|
242
|
+
} else {
|
|
243
|
+
addComma = true
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
json += "\"message\"" + ':'
|
|
247
|
+
json += $asString(obj["message"])
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
json += '}'
|
|
251
|
+
return json
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
;
|
|
256
|
+
return $main
|
|
257
|
+
|
package/lib/errors.js
CHANGED
|
@@ -110,6 +110,11 @@ const codes = {
|
|
|
110
110
|
500
|
|
111
111
|
),
|
|
112
112
|
|
|
113
|
+
FST_ERR_HOOK_TIMEOUT: createError(
|
|
114
|
+
'FST_ERR_HOOK_TIMEOUT',
|
|
115
|
+
"A callback for '%s' hook timed out. You may have forgotten to call 'done' function or to resolve a Promise"
|
|
116
|
+
),
|
|
117
|
+
|
|
113
118
|
/**
|
|
114
119
|
* logger
|
|
115
120
|
*/
|
|
@@ -147,6 +152,14 @@ const codes = {
|
|
|
147
152
|
'FST_ERR_BAD_STATUS_CODE',
|
|
148
153
|
'Called reply with an invalid status code: %s'
|
|
149
154
|
),
|
|
155
|
+
FST_ERR_BAD_TRAILER_NAME: createError(
|
|
156
|
+
'FST_ERR_BAD_TRAILER_NAME',
|
|
157
|
+
'Called reply.trailer with an invalid header name: %s'
|
|
158
|
+
),
|
|
159
|
+
FST_ERR_BAD_TRAILER_VALUE: createError(
|
|
160
|
+
'FST_ERR_BAD_TRAILER_VALUE',
|
|
161
|
+
"Called reply.trailer('%s', fn) with an invalid type: %s. Expected a function."
|
|
162
|
+
),
|
|
150
163
|
|
|
151
164
|
/**
|
|
152
165
|
* schemas
|
|
@@ -172,14 +185,6 @@ const codes = {
|
|
|
172
185
|
'Failed building the serialization schema for %s: %s, due to error %s'
|
|
173
186
|
),
|
|
174
187
|
|
|
175
|
-
/**
|
|
176
|
-
* wrapThenable
|
|
177
|
-
*/
|
|
178
|
-
FST_ERR_PROMISE_NOT_FULFILLED: createError(
|
|
179
|
-
'FST_ERR_PROMISE_NOT_FULFILLED',
|
|
180
|
-
"Promise may not be fulfilled with 'undefined' when statusCode is not 204"
|
|
181
|
-
),
|
|
182
|
-
|
|
183
188
|
/**
|
|
184
189
|
* http2
|
|
185
190
|
*/
|
|
@@ -199,6 +204,10 @@ const codes = {
|
|
|
199
204
|
/**
|
|
200
205
|
* router
|
|
201
206
|
*/
|
|
207
|
+
FST_ERR_DUPLICATED_ROUTE: createError(
|
|
208
|
+
'FST_ERR_DUPLICATED_ROUTE',
|
|
209
|
+
"Method '%s' already declared for route '%s'"
|
|
210
|
+
),
|
|
202
211
|
FST_ERR_BAD_URL: createError(
|
|
203
212
|
'FST_ERR_BAD_URL',
|
|
204
213
|
"'%s' is not a valid url component",
|
|
@@ -234,7 +243,40 @@ const codes = {
|
|
|
234
243
|
FST_ERR_PLUGIN_VERSION_MISMATCH: createError(
|
|
235
244
|
'FST_ERR_PLUGIN_VERSION_MISMATCH',
|
|
236
245
|
"fastify-plugin: %s - expected '%s' fastify version, '%s' is installed"
|
|
237
|
-
)
|
|
246
|
+
),
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Avvio Errors map
|
|
250
|
+
*/
|
|
251
|
+
AVVIO_ERRORS_MAP: {
|
|
252
|
+
AVV_ERR_CALLBACK_NOT_FN: createError(
|
|
253
|
+
'FST_ERR_PLUGIN_CALLBACK_NOT_FN',
|
|
254
|
+
'fastify-plugin: %s'
|
|
255
|
+
),
|
|
256
|
+
AVV_ERR_PLUGIN_NOT_VALID: createError(
|
|
257
|
+
'FST_ERR_PLUGIN_NOT_VALID',
|
|
258
|
+
'fastify-plugin: %s'
|
|
259
|
+
),
|
|
260
|
+
AVV_ERR_ROOT_PLG_BOOTED: createError(
|
|
261
|
+
'FST_ERR_ROOT_PLG_BOOTED',
|
|
262
|
+
'fastify-plugin: %s'
|
|
263
|
+
),
|
|
264
|
+
AVV_ERR_PARENT_PLG_LOADED: createError(
|
|
265
|
+
'FST_ERR_PARENT_PLUGIN_BOOTED',
|
|
266
|
+
'fastify-plugin: %s'
|
|
267
|
+
),
|
|
268
|
+
AVV_ERR_READY_TIMEOUT: createError(
|
|
269
|
+
'FST_ERR_PLUGIN_TIMEOUT',
|
|
270
|
+
'fastify-plugin: %s'
|
|
271
|
+
)
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
// Util function
|
|
275
|
+
appendStackTrace (oldErr, newErr) {
|
|
276
|
+
newErr.cause = oldErr
|
|
277
|
+
|
|
278
|
+
return newErr
|
|
279
|
+
}
|
|
238
280
|
}
|
|
239
281
|
|
|
240
282
|
module.exports = codes
|