UNPKG

20.5 kBPlain TextView Raw
1import { expectAssignable, expectDeprecated, expectError, expectNotDeprecated, expectType } from 'tsd'
2import fastify, {
3 FastifyBaseLogger,
4 FastifyBodyParser,
5 FastifyError,
6 FastifyInstance,
7 RawReplyDefaultExpression,
8 RawRequestDefaultExpression,
9 RawServerDefault,
10 RouteGenericInterface
11} from '../../fastify'
12import { HookHandlerDoneFunction } from '../../types/hooks'
13import { FastifyReply } from '../../types/reply'
14import { FastifyRequest } from '../../types/request'
15import { DefaultRoute } from '../../types/route'
16import { FastifySchemaControllerOptions, FastifySchemaCompiler, FastifySerializerCompiler } from '../../types/schema'
17import { AddressInfo } from 'net'
18import { Bindings, ChildLoggerOptions } from '../../types/logger'
19
20const server = fastify()
21
22expectAssignable<FastifyInstance>(server.addSchema({
23 type: 'null'
24}))
25expectAssignable<FastifyInstance>(server.addSchema({
26 schemaId: 'id'
27}))
28expectAssignable<FastifyInstance>(server.addSchema({
29 schemas: []
30}))
31
32expectType<string>(server.pluginName)
33
34expectType<Record<string, unknown>>(server.getSchemas())
35expectType<AddressInfo[]>(server.addresses())
36expectType<unknown>(server.getSchema('SchemaId'))
37expectType<string>(server.printRoutes())
38expectType<string>(server.printPlugins())
39expectType<string>(server.listeningOrigin)
40
41expectAssignable<FastifyInstance>(
42 server.setErrorHandler(function (error, request, reply) {
43 expectType<FastifyError>(error)
44 expectAssignable<FastifyInstance>(this)
45 })
46)
47
48expectAssignable<FastifyInstance>(
49 server.setErrorHandler<FastifyError>(function (error, request, reply) {
50 expectType<FastifyError>(error)
51 })
52)
53
54expectAssignable<FastifyInstance>(
55 server.setGenReqId(function (req) {
56 expectType<RawRequestDefaultExpression>(req)
57 return 'foo'
58 })
59)
60
61function fastifySetGenReqId (req: RawRequestDefaultExpression) {
62 return 'foo'
63}
64server.setGenReqId(fastifySetGenReqId)
65
66function fastifyErrorHandler (this: FastifyInstance, error: FastifyError) {}
67server.setErrorHandler(fastifyErrorHandler)
68
69async function asyncFastifyErrorHandler (this: FastifyInstance, error: FastifyError) {}
70server.setErrorHandler(asyncFastifyErrorHandler)
71
72function nodeJSErrorHandler (error: NodeJS.ErrnoException) {
73 if (error) { throw error }
74}
75server.setErrorHandler(nodeJSErrorHandler)
76
77function asyncNodeJSErrorHandler (error: NodeJS.ErrnoException) {
78 if (error) { throw error }
79}
80server.setErrorHandler(asyncNodeJSErrorHandler)
81
82class CustomError extends Error {
83 private __brand: any
84}
85interface ReplyPayload {
86 Reply: {
87 test: boolean;
88 };
89}
90// typed sync error handler
91server.setErrorHandler<CustomError, ReplyPayload>((error, request, reply) => {
92 expectType<CustomError>(error)
93 expectType<((payload?: ReplyPayload['Reply']) => FastifyReply<RawServerDefault, RawRequestDefaultExpression<RawServerDefault>, RawReplyDefaultExpression<RawServerDefault>, ReplyPayload>)>(reply.send)
94})
95// typed async error handler send
96server.setErrorHandler<CustomError, ReplyPayload>(async (error, request, reply) => {
97 expectType<CustomError>(error)
98 expectType<((payload?: ReplyPayload['Reply']) => FastifyReply<RawServerDefault, RawRequestDefaultExpression<RawServerDefault>, RawReplyDefaultExpression<RawServerDefault>, ReplyPayload>)>(reply.send)
99})
100// typed async error handler return
101server.setErrorHandler<CustomError, ReplyPayload>(async (error, request, reply) => {
102 expectType<CustomError>(error)
103 return { test: true }
104})
105// typed sync error handler send error
106expectError(server.setErrorHandler<CustomError, ReplyPayload>((error, request, reply) => {
107 expectType<CustomError>(error)
108 reply.send({ test: 'foo' })
109}))
110// typed sync error handler return error
111server.setErrorHandler<CustomError, ReplyPayload>((error, request, reply) => {
112 expectType<CustomError>(error)
113 return { test: 'foo' }
114})
115// typed async error handler send error
116expectError(server.setErrorHandler<CustomError, ReplyPayload>(async (error, request, reply) => {
117 expectType<CustomError>(error)
118 reply.send({ test: 'foo' })
119}))
120// typed async error handler return error
121server.setErrorHandler<CustomError, ReplyPayload>(async (error, request, reply) => {
122 expectType<CustomError>(error)
123 return { test: 'foo' }
124})
125
126function notFoundHandler (request: FastifyRequest, reply: FastifyReply) {}
127async function notFoundAsyncHandler (request: FastifyRequest, reply: FastifyReply) {}
128function notFoundpreHandlerHandler (request: FastifyRequest, reply: FastifyReply, done: HookHandlerDoneFunction) { done() }
129async function notFoundpreHandlerAsyncHandler (request: FastifyRequest, reply: FastifyReply) {}
130function notFoundpreValidationHandler (request: FastifyRequest, reply: FastifyReply, done: HookHandlerDoneFunction) { done() }
131async function notFoundpreValidationAsyncHandler (request: FastifyRequest, reply: FastifyReply) {}
132
133server.setNotFoundHandler(notFoundHandler)
134server.setNotFoundHandler({ preHandler: notFoundpreHandlerHandler }, notFoundHandler)
135server.setNotFoundHandler({ preHandler: notFoundpreHandlerAsyncHandler }, notFoundHandler)
136server.setNotFoundHandler({ preValidation: notFoundpreValidationHandler }, notFoundHandler)
137server.setNotFoundHandler({ preValidation: notFoundpreValidationAsyncHandler }, notFoundHandler)
138server.setNotFoundHandler({ preHandler: notFoundpreHandlerHandler, preValidation: notFoundpreValidationHandler }, notFoundHandler)
139
140server.setNotFoundHandler(notFoundAsyncHandler)
141server.setNotFoundHandler({ preHandler: notFoundpreHandlerHandler }, notFoundAsyncHandler)
142server.setNotFoundHandler({ preHandler: notFoundpreHandlerAsyncHandler }, notFoundAsyncHandler)
143server.setNotFoundHandler({ preValidation: notFoundpreValidationHandler }, notFoundAsyncHandler)
144server.setNotFoundHandler({ preValidation: notFoundpreValidationAsyncHandler }, notFoundAsyncHandler)
145server.setNotFoundHandler({ preHandler: notFoundpreHandlerHandler, preValidation: notFoundpreValidationHandler }, notFoundAsyncHandler)
146
147server.setNotFoundHandler(function (_, reply) {
148 return reply.send('')
149})
150
151function invalidErrorHandler (error: number) {
152 if (error) throw error
153}
154
155expectError(server.setErrorHandler(invalidErrorHandler))
156
157server.setSchemaController({
158 bucket: (parentSchemas: unknown) => {
159 return {
160 add (schema: unknown) {
161 expectType<unknown>(schema)
162 expectType<FastifyInstance>(server.addSchema({ type: 'null' }))
163 return server.addSchema({ type: 'null' })
164 },
165 getSchema (schemaId: string) {
166 expectType<string>(schemaId)
167 return server.getSchema('SchemaId')
168 },
169 getSchemas () {
170 expectType<Record<string, unknown>>(server.getSchemas())
171 return server.getSchemas()
172 }
173 }
174 }
175})
176
177function invalidSchemaController (schemaControllerOptions: FastifySchemaControllerOptions) {}
178expectError(server.setSchemaController(invalidSchemaController))
179
180server.setReplySerializer(function (payload, statusCode) {
181 expectType<unknown>(payload)
182 expectType<number>(statusCode)
183 return 'serialized'
184})
185
186function invalidReplySerializer (payload: number, statusCode: string) {}
187expectError(server.setReplySerializer(invalidReplySerializer))
188
189function serializerWithInvalidReturn (payload: unknown, statusCode: number) {}
190expectError(server.setReplySerializer(serializerWithInvalidReturn))
191
192function invalidSchemaErrorFormatter (err: Error) {
193 if (err) { throw err }
194}
195expectError(server.setSchemaErrorFormatter(invalidSchemaErrorFormatter))
196
197// test listen method callback
198expectAssignable<void>(server.listen(3000, '', 0, (err, address) => {
199 expectType<Error | null>(err)
200}))
201expectAssignable<void>(server.listen('3000', '', 0, (err, address) => {
202 expectType<Error | null>(err)
203}))
204expectAssignable<void>(server.listen(3000, '', (err, address) => {
205 expectType<Error | null>(err)
206}))
207expectAssignable<void>(server.listen('3000', '', (err, address) => {
208 expectType<Error | null>(err)
209}))
210expectAssignable<void>(server.listen(3000, (err, address) => {
211 expectType<Error | null>(err)
212}))
213expectAssignable<void>(server.listen('3000', (err, address) => {
214 expectType<Error | null>(err)
215}))
216
217// test listen method callback types
218expectAssignable<void>(server.listen('3000', (err, address) => {
219 expectAssignable<Error|null>(err)
220 expectAssignable<string>(address)
221}))
222
223// test listen method promise
224expectAssignable<PromiseLike<string>>(server.listen(3000))
225expectAssignable<PromiseLike<string>>(server.listen('3000'))
226expectAssignable<PromiseLike<string>>(server.listen(3000, '', 0))
227expectAssignable<PromiseLike<string>>(server.listen('3000', '', 0))
228expectAssignable<PromiseLike<string>>(server.listen(3000, ''))
229expectAssignable<PromiseLike<string>>(server.listen('3000', ''))
230
231// Test variadic listen signatures Typescript deprecation
232expectDeprecated(server.listen(3000))
233expectDeprecated(server.listen('3000'))
234expectDeprecated(server.listen(3000, '', 0))
235expectDeprecated(server.listen('3000', '', 0))
236expectDeprecated(server.listen(3000, ''))
237expectDeprecated(server.listen('3000', ''))
238
239// test listen opts objects
240expectAssignable<PromiseLike<string>>(server.listen())
241expectAssignable<PromiseLike<string>>(server.listen({ port: 3000 }))
242expectAssignable<PromiseLike<string>>(server.listen({ port: 3000, listenTextResolver: (address) => { return `address: ${address}` } }))
243expectAssignable<PromiseLike<string>>(server.listen({ port: 3000, host: '0.0.0.0' }))
244expectAssignable<PromiseLike<string>>(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42 }))
245expectAssignable<PromiseLike<string>>(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42, exclusive: true }))
246expectAssignable<PromiseLike<string>>(server.listen({ port: 3000, host: '::/0', ipv6Only: true }))
247
248expectAssignable<void>(server.listen(() => {}))
249expectAssignable<void>(server.listen({ port: 3000 }, () => {}))
250expectAssignable<void>(server.listen({ port: 3000, listenTextResolver: (address) => { return `address: ${address}` } }, () => {}))
251expectAssignable<void>(server.listen({ port: 3000, host: '0.0.0.0' }, () => {}))
252expectAssignable<void>(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42 }, () => {}))
253expectAssignable<void>(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42, exclusive: true }, () => {}))
254expectAssignable<void>(server.listen({ port: 3000, host: '::/0', ipv6Only: true }, () => {}))
255
256// test listen opts objects Typescript deprecation exclusion
257expectNotDeprecated(server.listen())
258expectNotDeprecated(server.listen({ port: 3000 }))
259expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0' }))
260expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42 }))
261expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42, exclusive: true }))
262expectNotDeprecated(server.listen({ port: 3000, host: '::/0', ipv6Only: true }))
263
264expectNotDeprecated(server.listen(() => {}))
265expectNotDeprecated(server.listen({ port: 3000 }, () => {}))
266expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0' }, () => {}))
267expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42 }, () => {}))
268expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42, exclusive: true }, () => {}))
269expectNotDeprecated(server.listen({ port: 3000, host: '::/0', ipv6Only: true }, () => {}))
270
271// test after method
272expectAssignable<FastifyInstance>(server.after())
273expectAssignable<FastifyInstance>(server.after((err) => {
274 expectType<Error | null>(err)
275}))
276
277// test ready method
278expectAssignable<FastifyInstance>(server.ready())
279expectAssignable<FastifyInstance>(server.ready((err) => {
280 expectType<Error | null>(err)
281}))
282
283expectAssignable<void>(server.routing({} as RawRequestDefaultExpression, {} as RawReplyDefaultExpression))
284
285expectType<FastifyInstance>(fastify().get<RouteGenericInterface, { contextKey: string }>('/', {
286 handler: () => {},
287 errorHandler: (error, request, reply) => {
288 expectAssignable<FastifyError>(error)
289 expectAssignable<FastifyRequest>(request)
290 expectAssignable<{ contextKey: string }>(request.routeConfig)
291 expectAssignable<FastifyReply>(reply)
292 expectAssignable<void>(server.errorHandler(error, request, reply))
293 }
294}))
295
296expectType<FastifyInstance>(fastify().get('/', {
297 handler: () => {},
298 childLoggerFactory: (logger, bindings, opts, req) => {
299 expectAssignable<FastifyBaseLogger>(server.childLoggerFactory(logger, bindings, opts, req))
300 return server.childLoggerFactory(logger, bindings, opts, req)
301 }
302}))
303
304expectAssignable<FastifyInstance>(
305 server.setChildLoggerFactory(function (logger, bindings, opts, req) {
306 expectType<FastifyBaseLogger>(logger)
307 expectType<Bindings>(bindings)
308 expectType<ChildLoggerOptions>(opts)
309 expectType<RawRequestDefaultExpression>(req)
310 expectAssignable<FastifyInstance>(this)
311 return logger.child(bindings, opts)
312 })
313)
314
315expectAssignable<FastifyInstance>(
316 server.setErrorHandler<FastifyError>(function (error, request, reply) {
317 expectType<FastifyError>(error)
318 })
319)
320
321function childLoggerFactory (this: FastifyInstance, logger: FastifyBaseLogger, bindings: Bindings, opts: ChildLoggerOptions, req: RawRequestDefaultExpression) {
322 return logger.child(bindings, opts)
323}
324server.setChildLoggerFactory(childLoggerFactory)
325server.setChildLoggerFactory(server.childLoggerFactory)
326
327type InitialConfig = Readonly<{
328 connectionTimeout?: number,
329 keepAliveTimeout?: number,
330 bodyLimit?: number,
331 caseSensitive?: boolean,
332 allowUnsafeRegex?: boolean,
333 forceCloseConnections?: boolean,
334 http2?: boolean,
335 https?: boolean | Readonly<{ allowHTTP1: boolean }>,
336 ignoreTrailingSlash?: boolean,
337 ignoreDuplicateSlashes?: boolean,
338 disableRequestLogging?: boolean,
339 maxParamLength?: number,
340 onProtoPoisoning?: 'error' | 'remove' | 'ignore',
341 onConstructorPoisoning?: 'error' | 'remove' | 'ignore',
342 pluginTimeout?: number,
343 requestIdHeader?: string | false,
344 requestIdLogLabel?: string,
345 http2SessionTimeout?: number,
346 useSemicolonDelimiter?: boolean
347}>
348
349expectType<InitialConfig>(fastify().initialConfig)
350
351expectType<FastifyBodyParser<string>>(server.defaultTextParser)
352
353expectType<FastifyBodyParser<string>>(server.getDefaultJsonParser('ignore', 'error'))
354
355expectType<string>(server.printRoutes({ includeHooks: true, commonPrefix: false, includeMeta: true }))
356
357expectType<string>(server.printRoutes({ includeMeta: ['key1', Symbol('key2')] }))
358
359expectType<string>(server.printRoutes({ method: 'GET' }))
360
361expectType<string>(server.printRoutes())
362
363server.decorate<(x: string) => void>('test', function (x: string): void {
364 expectType<FastifyInstance>(this)
365})
366server.decorate('test', function (x: string): void {
367 expectType<FastifyInstance>(this)
368})
369server.decorate<string>('test', {
370 getter () {
371 expectType<FastifyInstance>(this)
372 return 'foo'
373 }
374})
375server.decorate<string>('test', {
376 getter () {
377 expectType<FastifyInstance>(this)
378 return 'foo'
379 },
380 setter (x) {
381 expectType<string>(x)
382 expectType<FastifyInstance>(this)
383 }
384})
385server.decorate('test')
386server.decorate('test', null, ['foo'])
387
388server.decorateRequest<(x: string, y: number) => void>('test', function (x: string, y: number): void {
389 expectType<FastifyRequest>(this)
390})
391server.decorateRequest('test', function (x: string, y: number): void {
392 expectType<FastifyRequest>(this)
393})
394server.decorateRequest('test')
395server.decorateRequest('test', null, ['foo'])
396
397server.decorateReply<(x: string) => void>('test', function (x: string): void {
398 expectType<FastifyReply>(this)
399})
400server.decorateReply('test', function (x: string): void {
401 expectType<FastifyReply>(this)
402})
403server.decorateReply('test')
404server.decorateReply('test', null, ['foo'])
405
406expectError(server.decorate<string>('test', true))
407expectError(server.decorate<(myNumber: number) => number>('test', function (myNumber: number): string {
408 return ''
409}))
410expectError(server.decorate<string>('test', {
411 getter () {
412 return true
413 }
414}))
415expectError(server.decorate<string>('test', {
416 setter (x) {}
417}))
418
419declare module '../../fastify' {
420 interface FastifyInstance {
421 typedTestProperty: boolean
422 typedTestPropertyGetterSetter: string
423 typedTestMethod (x: string): string
424 }
425
426 interface FastifyRequest {
427 typedTestRequestProperty: boolean
428 typedTestRequestPropertyGetterSetter: string
429 typedTestRequestMethod (x: string): string
430 }
431
432 interface FastifyReply {
433 typedTestReplyProperty: boolean
434 typedTestReplyPropertyGetterSetter: string
435 typedTestReplyMethod (x: string): string
436 }
437}
438
439server.decorate('typedTestProperty', false)
440server.decorate('typedTestProperty', {
441 getter () {
442 return false
443 }
444})
445server.decorate('typedTestProperty', {
446 getter (): boolean {
447 return true
448 },
449 setter (x) {
450 expectType<boolean>(x)
451 expectType<FastifyInstance>(this)
452 }
453})
454server.decorate('typedTestProperty')
455server.decorate('typedTestProperty', null, ['foo'])
456server.decorate('typedTestProperty', null)
457expectError(server.decorate('typedTestProperty', 'foo'))
458expectError(server.decorate('typedTestProperty', {
459 getter () {
460 return 'foo'
461 }
462}))
463server.decorate('typedTestMethod', function (x) {
464 expectType<string>(x)
465 expectType<FastifyInstance>(this)
466 return 'foo'
467})
468server.decorate('typedTestMethod', x => x)
469expectError(server.decorate('typedTestMethod', function (x: boolean) {
470 return 'foo'
471}))
472expectError(server.decorate('typedTestMethod', function (x) {
473 return true
474}))
475expectError(server.decorate('typedTestMethod', async function (x) {
476 return 'foo'
477}))
478
479server.decorateRequest('typedTestRequestProperty', false)
480server.decorateRequest('typedTestRequestProperty', {
481 getter () {
482 return false
483 }
484})
485server.decorateRequest('typedTestRequestProperty', {
486 getter (): boolean {
487 return true
488 },
489 setter (x) {
490 expectType<boolean>(x)
491 expectType<FastifyRequest>(this)
492 }
493})
494server.decorateRequest('typedTestRequestProperty')
495server.decorateRequest('typedTestRequestProperty', null, ['foo'])
496server.decorateRequest('typedTestRequestProperty', null)
497expectError(server.decorateRequest('typedTestRequestProperty', 'foo'))
498expectError(server.decorateRequest('typedTestRequestProperty', {
499 getter () {
500 return 'foo'
501 }
502}))
503server.decorateRequest('typedTestRequestMethod', function (x) {
504 expectType<string>(x)
505 expectType<FastifyRequest>(this)
506 return 'foo'
507})
508server.decorateRequest('typedTestRequestMethod', x => x)
509expectError(server.decorateRequest('typedTestRequestMethod', function (x: boolean) {
510 return 'foo'
511}))
512expectError(server.decorateRequest('typedTestRequestMethod', function (x) {
513 return true
514}))
515expectError(server.decorateRequest('typedTestRequestMethod', async function (x) {
516 return 'foo'
517}))
518
519server.decorateReply('typedTestReplyProperty', false)
520server.decorateReply('typedTestReplyProperty', {
521 getter () {
522 return false
523 }
524})
525server.decorateReply('typedTestReplyProperty', {
526 getter (): boolean {
527 return true
528 },
529 setter (x) {
530 expectType<boolean>(x)
531 expectType<FastifyReply>(this)
532 }
533})
534server.decorateReply('typedTestReplyProperty')
535server.decorateReply('typedTestReplyProperty', null, ['foo'])
536server.decorateReply('typedTestReplyProperty', null)
537expectError(server.decorateReply('typedTestReplyProperty', 'foo'))
538expectError(server.decorateReply('typedTestReplyProperty', {
539 getter () {
540 return 'foo'
541 }
542}))
543server.decorateReply('typedTestReplyMethod', function (x) {
544 expectType<string>(x)
545 expectType<FastifyReply>(this)
546 return 'foo'
547})
548server.decorateReply('typedTestReplyMethod', x => x)
549expectError(server.decorateReply('typedTestReplyMethod', function (x: boolean) {
550 return 'foo'
551}))
552expectError(server.decorateReply('typedTestReplyMethod', function (x) {
553 return true
554}))
555expectError(server.decorateReply('typedTestReplyMethod', async function (x) {
556 return 'foo'
557}))
558
559const versionConstraintStrategy = {
560 name: 'version',
561 storage: () => ({
562 get: () => () => {},
563 set: () => { },
564 del: () => { },
565 empty: () => { }
566 }),
567 validate () {},
568 deriveConstraint: () => 'foo'
569}
570expectType<void>(server.addConstraintStrategy(versionConstraintStrategy))
571expectType<boolean>(server.hasConstraintStrategy(versionConstraintStrategy.name))
572
573expectType<boolean>(server.hasPlugin(''))
574
575expectAssignable<DefaultRoute<RawRequestDefaultExpression, RawReplyDefaultExpression>>(server.getDefaultRoute())
576
577expectType<FastifySchemaCompiler<any> | undefined>(server.validatorCompiler)
578expectType<FastifySerializerCompiler<any> | undefined>(server.serializerCompiler)