import { expect } from 'tstyche' import fastify, { ContextConfigDefault, FastifyContextConfig, FastifyLogFn, FastifySchema, FastifyTypeProviderDefault, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault, RequestBodyDefault, RequestGenericInterface, RouteHandler, RouteHandlerMethod, SafePromiseLike } from '../../fastify.js' import { FastifyInstance } from '../../types/instance.js' import { FastifyBaseLogger } from '../../types/logger.js' import { FastifyReply } from '../../types/reply.js' import { FastifyRequest, RequestRouteOptions, ValidationFunction } from '../../types/request.js' import { FastifyRouteConfig, RouteGenericInterface } from '../../types/route.js' import { RequestHeadersDefault, RequestParamsDefault, RequestQuerystringDefault } from '../../types/utils.js' interface RequestBody { content: string; } interface RequestQuerystring { from: string; } interface RequestParams { id: number; } interface RequestHeaders { 'x-foobar': string; } interface RequestData extends RequestGenericInterface { Body: RequestBody; Querystring: RequestQuerystring; Params: RequestParams; Headers: RequestHeaders; } type Handler = RouteHandler type CustomRequest = FastifyRequest<{ Body: RequestBody | undefined; Querystring: RequestQuerystring; Params: RequestParams; Headers: RequestHeaders; }> type HTTPRequestPart = 'body' | 'query' | 'querystring' | 'params' | 'headers' type ExpectedGetValidationFunction = (input: { [key: string]: unknown }) => boolean interface CustomLoggerInterface extends FastifyBaseLogger { foo: FastifyLogFn; // custom severity logger method } const getHandler: RouteHandler = function (request, _reply) { expect(request.url).type.toBe() expect(request.originalUrl).type.toBe() expect(request.method).type.toBe() expect(request.routeOptions).type.toBe>() expect(request.is404).type.toBe() expect(request.hostname).type.toBe() expect(request.host).type.toBe() expect(request.port).type.toBe() expect(request.ip).type.toBe() expect(request.ips).type.toBe() expect(request.raw).type.toBe() expect(request.body).type.toBe() expect(request.params).type.toBe() expect(request.routeOptions.config).type.toBe() expect(request.routeOptions.schema).type.toBe() expect(request.routeOptions.handler).type.toBe() expect(request.routeOptions.url).type.toBe() expect(request.routeOptions.version).type.toBe() expect(request.headers).type.toBe() request.headers = {} expect(request.query).type.toBe() expect(request.id).type.toBe() expect(request.log).type.toBe() expect(request.socket).type.toBe() expect(request.signal).type.toBe() expect(request.validationError).type.toBe() expect(request.server).type.toBe() expect(request.getValidationFunction).type.toBeAssignableTo< (httpPart: HTTPRequestPart) => ExpectedGetValidationFunction | undefined >() expect(request.getValidationFunction).type.toBeAssignableTo< (schema: { [key: string]: unknown }) => ExpectedGetValidationFunction | undefined >() expect(request.getValidationFunction('body')).type.toBe() expect(request.getValidationFunction({ type: 'object' })).type.toBe() expect(request.validateInput).type.toBeAssignableTo< (input: { [key: string]: unknown }, schema: { [key: string]: unknown }, httpPart?: HTTPRequestPart) => boolean >() expect(request.validateInput).type.toBeAssignableTo< (input: { [key: string]: unknown }, httpPart?: HTTPRequestPart) => boolean >() expect(request.getDecorator('foo')).type.toBe() expect(request.setDecorator('foo', 'hello')).type.toBe() expect(request.setDecorator('foo', 'hello')).type.toBe() expect(request.setDecorator).type.not.toBeCallableWith('foo', true) } const getHandlerWithCustomLogger: RouteHandlerMethod< RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RouteGenericInterface, ContextConfigDefault, FastifySchema, FastifyTypeProviderDefault, CustomLoggerInterface > = function (request, _reply) { expect(request.log).type.toBe() } const postHandler: Handler = function (request) { expect(request.body).type.toBe() expect(request.params).type.toBe() expect( request.headers ).type.toBe() expect(request.query).type.toBe() expect(request.body.content).type.toBe() expect(request.query.from).type.toBe() expect(request.params.id).type.toBe() expect(request.headers['x-foobar']).type.toBe() expect(request.server).type.toBe() expect(request.routeOptions.config).type.toBe() } function putHandler (request: CustomRequest, reply: FastifyReply) { expect(request.body).type.toBe() expect(request.params).type.toBe() expect(request.headers).type.toBe() expect(request.query).type.toBe() if (request.body === undefined) { expect(request.body).type.toBe() } else { expect(request.body.content).type.toBe() } expect(request.query.from).type.toBe() expect(request.params.id).type.toBe() expect(request.headers['x-foobar']).type.toBe() expect(request.server).type.toBe() expect(request.routeOptions.config).type.toBe() } const server = fastify() server.get('/get', getHandler) server.post('/post', postHandler) server.put('/put', putHandler) const customLogger: CustomLoggerInterface = { level: 'info', silent: () => { }, info: () => { }, warn: () => { }, error: () => { }, fatal: () => { }, trace: () => { }, debug: () => { }, foo: () => { }, // custom severity logger method child: () => customLogger } const serverWithCustomLogger = fastify({ loggerInstance: customLogger }) expect(serverWithCustomLogger).type.not.toBeAssignableTo< FastifyInstance & Promise< FastifyInstance > >() expect(serverWithCustomLogger).type.toBeAssignableTo< FastifyInstance & PromiseLike< FastifyInstance > >() expect(serverWithCustomLogger).type.toBe< FastifyInstance & SafePromiseLike< FastifyInstance > >() serverWithCustomLogger.get('/get', getHandlerWithCustomLogger)