fastify
Version:
Fast and low overhead web framework, for Node.js
541 lines (482 loc) • 19.1 kB
text/typescript
import { expectAssignable, expectError, expectNotDeprecated, expectType } from 'tsd'
import fastify, {
FastifyBaseLogger,
FastifyBodyParser,
FastifyError,
FastifyInstance,
RawReplyDefaultExpression,
RawRequestDefaultExpression,
RawServerDefault,
RouteGenericInterface
} from '../../fastify'
import { HookHandlerDoneFunction } from '../../types/hooks'
import { FastifyReply } from '../../types/reply'
import { FastifyRequest } from '../../types/request'
import { FastifySchemaControllerOptions, FastifySchemaCompiler, FastifySerializerCompiler } from '../../types/schema'
import { AddressInfo } from 'node:net'
import { Bindings, ChildLoggerOptions } from '../../types/logger'
const server = fastify()
expectAssignable<FastifyInstance>(server.addSchema({
type: 'null'
}))
expectAssignable<FastifyInstance>(server.addSchema({
schemaId: 'id'
}))
expectAssignable<FastifyInstance>(server.addSchema({
schemas: []
}))
expectType<string>(server.pluginName)
expectType<Record<string, unknown>>(server.getSchemas())
expectType<AddressInfo[]>(server.addresses())
expectType<unknown>(server.getSchema('SchemaId'))
expectType<string>(server.printRoutes())
expectType<string>(server.printPlugins())
expectType<string>(server.listeningOrigin)
expectType<string[]>(server.supportedMethods)
expectAssignable<FastifyInstance>(
server.setErrorHandler(function (error, request, reply) {
expectType<FastifyError>(error)
expectAssignable<FastifyInstance>(this)
})
)
expectAssignable<FastifyInstance>(
server.setErrorHandler<FastifyError>(function (error, request, reply) {
expectType<FastifyError>(error)
})
)
expectAssignable<FastifyInstance>(
server.setGenReqId(function (req) {
expectType<RawRequestDefaultExpression>(req)
return 'foo'
})
)
function fastifySetGenReqId (req: RawRequestDefaultExpression) {
return 'foo'
}
server.setGenReqId(fastifySetGenReqId)
function fastifyErrorHandler (this: FastifyInstance, error: FastifyError) {}
server.setErrorHandler(fastifyErrorHandler)
async function asyncFastifyErrorHandler (this: FastifyInstance, error: FastifyError) {}
server.setErrorHandler(asyncFastifyErrorHandler)
function nodeJSErrorHandler (error: NodeJS.ErrnoException) {
if (error) { throw error }
}
server.setErrorHandler(nodeJSErrorHandler)
function asyncNodeJSErrorHandler (error: NodeJS.ErrnoException) {
if (error) { throw error }
}
server.setErrorHandler(asyncNodeJSErrorHandler)
class CustomError extends Error {
private __brand: any
}
interface ReplyPayload {
Reply: {
test: boolean;
};
}
// typed sync error handler
server.setErrorHandler<CustomError, ReplyPayload>((error, request, reply) => {
expectType<CustomError>(error)
expectType<((payload?: ReplyPayload['Reply']) => FastifyReply<ReplyPayload, RawServerDefault, RawRequestDefaultExpression<RawServerDefault>, RawReplyDefaultExpression<RawServerDefault>>)>(reply.send)
})
// typed async error handler send
server.setErrorHandler<CustomError, ReplyPayload>(async (error, request, reply) => {
expectType<CustomError>(error)
expectType<((payload?: ReplyPayload['Reply']) => FastifyReply<ReplyPayload, RawServerDefault, RawRequestDefaultExpression<RawServerDefault>, RawReplyDefaultExpression<RawServerDefault>>)>(reply.send)
})
// typed async error handler return
server.setErrorHandler<CustomError, ReplyPayload>(async (error, request, reply) => {
expectType<CustomError>(error)
return { test: true }
})
// typed sync error handler send error
expectError(server.setErrorHandler<CustomError, ReplyPayload>((error, request, reply) => {
expectType<CustomError>(error)
reply.send({ test: 'foo' })
}))
// typed sync error handler return error
server.setErrorHandler<CustomError, ReplyPayload>((error, request, reply) => {
expectType<CustomError>(error)
return { test: 'foo' }
})
// typed async error handler send error
expectError(server.setErrorHandler<CustomError, ReplyPayload>(async (error, request, reply) => {
expectType<CustomError>(error)
reply.send({ test: 'foo' })
}))
// typed async error handler return error
server.setErrorHandler<CustomError, ReplyPayload>(async (error, request, reply) => {
expectType<CustomError>(error)
return { test: 'foo' }
})
function notFoundHandler (request: FastifyRequest, reply: FastifyReply) {}
async function notFoundAsyncHandler (request: FastifyRequest, reply: FastifyReply) {}
function notFoundpreHandlerHandler (request: FastifyRequest, reply: FastifyReply, done: HookHandlerDoneFunction) { done() }
async function notFoundpreHandlerAsyncHandler (request: FastifyRequest, reply: FastifyReply) {}
function notFoundpreValidationHandler (request: FastifyRequest, reply: FastifyReply, done: HookHandlerDoneFunction) { done() }
async function notFoundpreValidationAsyncHandler (request: FastifyRequest, reply: FastifyReply) {}
server.setNotFoundHandler(notFoundHandler)
server.setNotFoundHandler({ preHandler: notFoundpreHandlerHandler }, notFoundHandler)
server.setNotFoundHandler({ preHandler: notFoundpreHandlerAsyncHandler }, notFoundHandler)
server.setNotFoundHandler({ preValidation: notFoundpreValidationHandler }, notFoundHandler)
server.setNotFoundHandler({ preValidation: notFoundpreValidationAsyncHandler }, notFoundHandler)
server.setNotFoundHandler({ preHandler: notFoundpreHandlerHandler, preValidation: notFoundpreValidationHandler }, notFoundHandler)
server.setNotFoundHandler(notFoundAsyncHandler)
server.setNotFoundHandler({ preHandler: notFoundpreHandlerHandler }, notFoundAsyncHandler)
server.setNotFoundHandler({ preHandler: notFoundpreHandlerAsyncHandler }, notFoundAsyncHandler)
server.setNotFoundHandler({ preValidation: notFoundpreValidationHandler }, notFoundAsyncHandler)
server.setNotFoundHandler({ preValidation: notFoundpreValidationAsyncHandler }, notFoundAsyncHandler)
server.setNotFoundHandler({ preHandler: notFoundpreHandlerHandler, preValidation: notFoundpreValidationHandler }, notFoundAsyncHandler)
server.setNotFoundHandler(function (_, reply) {
return reply.send('')
})
function invalidErrorHandler (error: number) {
if (error) throw error
}
expectError(server.setErrorHandler(invalidErrorHandler))
server.setSchemaController({
bucket: (parentSchemas: unknown) => {
return {
add (schema: unknown) {
expectType<unknown>(schema)
expectType<FastifyInstance>(server.addSchema({ type: 'null' }))
return server.addSchema({ type: 'null' })
},
getSchema (schemaId: string) {
expectType<string>(schemaId)
return server.getSchema('SchemaId')
},
getSchemas () {
expectType<Record<string, unknown>>(server.getSchemas())
return server.getSchemas()
}
}
}
})
function invalidSchemaController (schemaControllerOptions: FastifySchemaControllerOptions) {}
expectError(server.setSchemaController(invalidSchemaController))
server.setReplySerializer(function (payload, statusCode) {
expectType<unknown>(payload)
expectType<number>(statusCode)
return 'serialized'
})
function invalidReplySerializer (payload: number, statusCode: string) {}
expectError(server.setReplySerializer(invalidReplySerializer))
function serializerWithInvalidReturn (payload: unknown, statusCode: number) {}
expectError(server.setReplySerializer(serializerWithInvalidReturn))
function invalidSchemaErrorFormatter (err: Error) {
if (err) { throw err }
}
expectError(server.setSchemaErrorFormatter(invalidSchemaErrorFormatter))
expectType<FastifyInstance>(server.addHttpMethod('SEARCH', { hasBody: true }))
// test listen opts objects
expectAssignable<PromiseLike<string>>(server.listen())
expectAssignable<PromiseLike<string>>(server.listen({ port: 3000 }))
expectAssignable<PromiseLike<string>>(server.listen({ port: 3000, listenTextResolver: (address) => { return `address: ${address}` } }))
expectAssignable<PromiseLike<string>>(server.listen({ port: 3000, host: '0.0.0.0' }))
expectAssignable<PromiseLike<string>>(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42 }))
expectAssignable<PromiseLike<string>>(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42, exclusive: true }))
expectAssignable<PromiseLike<string>>(server.listen({ port: 3000, host: '::/0', ipv6Only: true }))
expectAssignable<void>(server.listen(() => {}))
expectAssignable<void>(server.listen({ port: 3000 }, () => {}))
expectAssignable<void>(server.listen({ port: 3000, listenTextResolver: (address) => { return `address: ${address}` } }, () => {}))
expectAssignable<void>(server.listen({ port: 3000, host: '0.0.0.0' }, () => {}))
expectAssignable<void>(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42 }, () => {}))
expectAssignable<void>(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42, exclusive: true }, () => {}))
expectAssignable<void>(server.listen({ port: 3000, host: '::/0', ipv6Only: true }, () => {}))
// test listen opts objects Typescript deprecation exclusion
expectNotDeprecated(server.listen())
expectNotDeprecated(server.listen({ port: 3000 }))
expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0' }))
expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42 }))
expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42, exclusive: true }))
expectNotDeprecated(server.listen({ port: 3000, host: '::/0', ipv6Only: true }))
expectNotDeprecated(server.listen(() => {}))
expectNotDeprecated(server.listen({ port: 3000 }, () => {}))
expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0' }, () => {}))
expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42 }, () => {}))
expectNotDeprecated(server.listen({ port: 3000, host: '0.0.0.0', backlog: 42, exclusive: true }, () => {}))
expectNotDeprecated(server.listen({ port: 3000, host: '::/0', ipv6Only: true }, () => {}))
// test after method
expectAssignable<FastifyInstance>(server.after())
expectAssignable<FastifyInstance>(server.after((err) => {
expectType<Error | null>(err)
}))
// test ready method
expectAssignable<FastifyInstance>(server.ready())
expectAssignable<FastifyInstance>(server.ready((err) => {
expectType<Error | null>(err)
}))
expectAssignable<FastifyInstance>(server.ready(async (err) => {
expectType<Error | null>(err)
}))
expectAssignable<Parameters<typeof server.ready>[0]>(async (err) => {
expectType<Error | null>(err)
})
expectAssignable<void>(server.routing({} as RawRequestDefaultExpression, {} as RawReplyDefaultExpression))
expectType<FastifyInstance>(fastify().get<RouteGenericInterface, { contextKey: string }>('/', {
handler: () => {},
errorHandler: (error, request, reply) => {
expectAssignable<FastifyError>(error)
expectAssignable<FastifyRequest>(request)
expectAssignable<{ contextKey: string }>(request.routeOptions.config)
expectAssignable<FastifyReply>(reply)
expectAssignable<void>(server.errorHandler(error, request, reply))
}
}))
expectType<FastifyInstance>(fastify().get('/', {
handler: () => {},
childLoggerFactory: (logger, bindings, opts, req) => {
expectAssignable<FastifyBaseLogger>(server.childLoggerFactory(logger, bindings, opts, req))
return server.childLoggerFactory(logger, bindings, opts, req)
}
}))
expectAssignable<FastifyInstance>(
server.setChildLoggerFactory(function (logger, bindings, opts, req) {
expectType<FastifyBaseLogger>(logger)
expectType<Bindings>(bindings)
expectType<ChildLoggerOptions>(opts)
expectType<RawRequestDefaultExpression>(req)
expectAssignable<FastifyInstance>(this)
return logger.child(bindings, opts)
})
)
expectAssignable<FastifyInstance>(
server.setErrorHandler<FastifyError>(function (error, request, reply) {
expectType<FastifyError>(error)
})
)
function childLoggerFactory (this: FastifyInstance, logger: FastifyBaseLogger, bindings: Bindings, opts: ChildLoggerOptions, req: RawRequestDefaultExpression) {
return logger.child(bindings, opts)
}
server.setChildLoggerFactory(childLoggerFactory)
server.setChildLoggerFactory(server.childLoggerFactory)
type InitialConfig = Readonly<{
connectionTimeout?: number,
keepAliveTimeout?: number,
bodyLimit?: number,
caseSensitive?: boolean,
allowUnsafeRegex?: boolean,
forceCloseConnections?: boolean,
http2?: boolean,
https?: boolean | Readonly<{ allowHTTP1: boolean }>,
ignoreTrailingSlash?: boolean,
ignoreDuplicateSlashes?: boolean,
disableRequestLogging?: boolean,
maxParamLength?: number,
onProtoPoisoning?: 'error' | 'remove' | 'ignore',
onConstructorPoisoning?: 'error' | 'remove' | 'ignore',
pluginTimeout?: number,
requestIdHeader?: string | false,
requestIdLogLabel?: string,
http2SessionTimeout?: number,
useSemicolonDelimiter?: boolean
}>
expectType<InitialConfig>(fastify().initialConfig)
expectType<FastifyBodyParser<string>>(server.defaultTextParser)
expectType<FastifyBodyParser<string>>(server.getDefaultJsonParser('ignore', 'error'))
expectType<string>(server.printRoutes({ includeHooks: true, commonPrefix: false, includeMeta: true }))
expectType<string>(server.printRoutes({ includeMeta: ['key1', Symbol('key2')] }))
expectType<string>(server.printRoutes({ method: 'GET' }))
expectType<string>(server.printRoutes())
server.decorate<(x: string) => void>('test', function (x: string): void {
expectType<FastifyInstance>(this)
})
server.decorate('test', function (x: string): void {
expectType<FastifyInstance>(this)
})
server.decorate<string>('test', {
getter () {
expectType<FastifyInstance>(this)
return 'foo'
}
})
server.decorate<string>('test', {
getter () {
expectType<FastifyInstance>(this)
return 'foo'
},
setter (x) {
expectType<string>(x)
expectType<FastifyInstance>(this)
}
})
server.decorate('test')
server.decorate('test', null, ['foo'])
server.decorateRequest<(x: string, y: number) => void>('test', function (x: string, y: number): void {
expectType<FastifyRequest>(this)
})
server.decorateRequest('test', function (x: string, y: number): void {
expectType<FastifyRequest>(this)
})
server.decorateRequest('test')
server.decorateRequest('test', null, ['foo'])
server.decorateReply<(x: string) => void>('test', function (x: string): void {
expectType<FastifyReply>(this)
})
server.decorateReply('test', function (x: string): void {
expectType<FastifyReply>(this)
})
server.decorateReply('test')
server.decorateReply('test', null, ['foo'])
expectError(server.decorate<string>('test', true))
expectError(server.decorate<(myNumber: number) => number>('test', function (myNumber: number): string {
return ''
}))
expectError(server.decorate<string>('test', {
getter () {
return true
}
}))
expectError(server.decorate<string>('test', {
setter (x) {}
}))
declare module '../../fastify' {
interface FastifyInstance {
typedTestProperty: boolean
typedTestPropertyGetterSetter: string
typedTestMethod (x: string): string
}
interface FastifyRequest {
typedTestRequestProperty: boolean
typedTestRequestPropertyGetterSetter: string
typedTestRequestMethod (x: string): string
}
interface FastifyReply {
typedTestReplyProperty: boolean
typedTestReplyPropertyGetterSetter: string
typedTestReplyMethod (x: string): string
}
}
server.decorate('typedTestProperty', false)
server.decorate('typedTestProperty', {
getter () {
return false
}
})
server.decorate('typedTestProperty', {
getter (): boolean {
return true
},
setter (x) {
expectType<boolean>(x)
expectType<FastifyInstance>(this)
}
})
server.decorate('typedTestProperty')
server.decorate('typedTestProperty', null, ['foo'])
expectError(server.decorate('typedTestProperty', null))
expectError(server.decorate('typedTestProperty', 'foo'))
expectError(server.decorate('typedTestProperty', {
getter () {
return 'foo'
}
}))
server.decorate('typedTestMethod', function (x) {
expectType<string>(x)
expectType<FastifyInstance>(this)
return 'foo'
})
server.decorate('typedTestMethod', x => x)
expectError(server.decorate('typedTestMethod', function (x: boolean) {
return 'foo'
}))
expectError(server.decorate('typedTestMethod', function (x) {
return true
}))
expectError(server.decorate('typedTestMethod', async function (x) {
return 'foo'
}))
server.decorateRequest('typedTestRequestProperty', false)
server.decorateRequest('typedTestRequestProperty', {
getter () {
return false
}
})
server.decorateRequest('typedTestRequestProperty', {
getter (): boolean {
return true
},
setter (x) {
expectType<boolean>(x)
expectType<FastifyRequest>(this)
}
})
server.decorateRequest('typedTestRequestProperty')
server.decorateRequest('typedTestRequestProperty', null, ['foo'])
expectError(server.decorateRequest('typedTestRequestProperty', null))
expectError(server.decorateRequest('typedTestRequestProperty', 'foo'))
expectError(server.decorateRequest('typedTestRequestProperty', {
getter () {
return 'foo'
}
}))
server.decorateRequest('typedTestRequestMethod', function (x) {
expectType<string>(x)
expectType<FastifyRequest>(this)
return 'foo'
})
server.decorateRequest('typedTestRequestMethod', x => x)
expectError(server.decorateRequest('typedTestRequestMethod', function (x: boolean) {
return 'foo'
}))
expectError(server.decorateRequest('typedTestRequestMethod', function (x) {
return true
}))
expectError(server.decorateRequest('typedTestRequestMethod', async function (x) {
return 'foo'
}))
server.decorateReply('typedTestReplyProperty', false)
server.decorateReply('typedTestReplyProperty', {
getter () {
return false
}
})
server.decorateReply('typedTestReplyProperty', {
getter (): boolean {
return true
},
setter (x) {
expectType<boolean>(x)
expectType<FastifyReply>(this)
}
})
server.decorateReply('typedTestReplyProperty')
server.decorateReply('typedTestReplyProperty', null, ['foo'])
expectError(server.decorateReply('typedTestReplyProperty', null))
expectError(server.decorateReply('typedTestReplyProperty', 'foo'))
expectError(server.decorateReply('typedTestReplyProperty', {
getter () {
return 'foo'
}
}))
server.decorateReply('typedTestReplyMethod', function (x) {
expectType<string>(x)
expectType<FastifyReply>(this)
return 'foo'
})
server.decorateReply('typedTestReplyMethod', x => x)
expectError(server.decorateReply('typedTestReplyMethod', function (x: boolean) {
return 'foo'
}))
expectError(server.decorateReply('typedTestReplyMethod', function (x) {
return true
}))
expectError(server.decorateReply('typedTestReplyMethod', async function (x) {
return 'foo'
}))
const versionConstraintStrategy = {
name: 'version',
storage: () => ({
get: () => () => {},
set: () => { },
del: () => { },
empty: () => { }
}),
validate () {},
deriveConstraint: () => 'foo'
}
expectType<void>(server.addConstraintStrategy(versionConstraintStrategy))
expectType<boolean>(server.hasConstraintStrategy(versionConstraintStrategy.name))
expectType<FastifySchemaCompiler<any> | undefined>(server.validatorCompiler)
expectType<FastifySerializerCompiler<any> | undefined>(server.serializerCompiler)