UNPKG

fastify

Version:

Fast and low overhead web framework, for Node.js

186 lines (174 loc) 8.96 kB
import { Buffer } from 'buffer' import { expectAssignable, expectDeprecated, expectError, expectType } from 'tsd' import fastify, { FastifyReplyContext, FastifyReply, FastifyRequest, FastifySchema, FastifySchemaCompiler, FastifyTypeProviderDefault, RawRequestDefaultExpression, RouteHandler, RouteHandlerMethod } from '../../fastify' import { FastifyInstance } from '../../types/instance' import { FastifyLoggerInstance } from '../../types/logger' import { ResolveReplyTypeWithRouteGeneric } from '../../types/reply' import { RouteGenericInterface } from '../../types/route' import { ContextConfigDefault, RawReplyDefaultExpression, RawServerDefault } from '../../types/utils' type DefaultSerializationFunction = (payload: { [key: string]: unknown }) => string type DefaultFastifyReplyWithCode<Code extends number> = FastifyReply<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RouteGenericInterface, ContextConfigDefault, FastifySchema, FastifyTypeProviderDefault, ResolveReplyTypeWithRouteGeneric<RouteGenericInterface['Reply'], Code, FastifySchema, FastifyTypeProviderDefault>> const getHandler: RouteHandlerMethod = function (_request, reply) { expectType<RawReplyDefaultExpression>(reply.raw) expectType<FastifyReplyContext<ContextConfigDefault>>(reply.context) expectType<FastifyReplyContext<ContextConfigDefault>['config']>(reply.context.config) expectType<FastifyLoggerInstance>(reply.log) expectType<FastifyRequest<RouteGenericInterface, RawServerDefault, RawRequestDefaultExpression>>(reply.request) expectType<<Code extends number>(statusCode: Code) => DefaultFastifyReplyWithCode<Code>>(reply.code) expectType<<Code extends number>(statusCode: Code) => DefaultFastifyReplyWithCode<Code>>(reply.status) expectType<(payload?: unknown) => FastifyReply>(reply.code(100 as number).send) expectType<number>(reply.elapsedTime) expectType<number>(reply.statusCode) expectType<boolean>(reply.sent) expectType<((payload?: unknown) => FastifyReply)>(reply.send) expectAssignable<(key: string, value: any) => FastifyReply>(reply.header) expectAssignable<(values: {[key: string]: any}) => FastifyReply>(reply.headers) expectAssignable<(key: string) => number | string | string[] | undefined>(reply.getHeader) expectAssignable<() => { [key: string]: number | string | string[] | undefined }>(reply.getHeaders) expectAssignable<(key: string) => FastifyReply>(reply.removeHeader) expectAssignable<(key: string) => boolean>(reply.hasHeader) expectType<{(statusCode: number, url: string): FastifyReply;(url: string, statusCode?: number): FastifyReply;}>(reply.redirect) expectType<() => FastifyReply>(reply.hijack) expectType<() => void>(reply.callNotFound) // Test reply.getResponseTime() deprecation expectDeprecated(reply.getResponseTime) expectType<(contentType: string) => FastifyReply>(reply.type) expectType<(fn: (payload: any) => string) => FastifyReply>(reply.serializer) expectType<(payload: any) => string | ArrayBuffer | Buffer>(reply.serialize) expectType<(fulfilled: () => void, rejected: (err: Error) => void) => void>(reply.then) expectType<(key: string, fn: ((reply: FastifyReply, payload: string | Buffer | null) => Promise<string>) | ((reply: FastifyReply, payload: string | Buffer | null, done: (err: Error | null, value?: string) => void) => void)) => FastifyReply>(reply.trailer) expectType<(key: string) => boolean>(reply.hasTrailer) expectType<(key: string) => FastifyReply>(reply.removeTrailer) expectType<FastifyInstance>(reply.server) expectAssignable<((httpStatus: string) => DefaultSerializationFunction | undefined)>(reply.getSerializationFunction) expectAssignable<((schema: {[key: string]: unknown}) => DefaultSerializationFunction | undefined)>(reply.getSerializationFunction) expectAssignable<((schema: {[key: string]: unknown}, httpStatus?: string) => DefaultSerializationFunction)>(reply.compileSerializationSchema) expectAssignable<((input: {[key: string]: unknown}, schema: {[key: string]: unknown}, httpStatus?: string) => unknown)>(reply.serializeInput) expectAssignable<((input: {[key: string]: unknown}, httpStatus: string) => unknown)>(reply.serializeInput) } interface ReplyPayload { Reply: { test: boolean; }; } interface ReplyArrayPayload { Reply: string[] } interface ReplyUnion { Reply: { success: boolean; } | { error: string; } } interface ReplyHttpCodes { Reply: { '1xx': number, 200: 'abc', 201: boolean, 300: { foo: string }, } } interface InvalidReplyHttpCodes { Reply: { '1xx': number, 200: string, 999: boolean, } } const typedHandler: RouteHandler<ReplyPayload> = async (request, reply) => { expectType<((payload?: ReplyPayload['Reply']) => FastifyReply<RawServerDefault, RawRequestDefaultExpression<RawServerDefault>, RawReplyDefaultExpression<RawServerDefault>, ReplyPayload>)>(reply.send) expectType<((payload?: ReplyPayload['Reply']) => FastifyReply<RawServerDefault, RawRequestDefaultExpression<RawServerDefault>, RawReplyDefaultExpression<RawServerDefault>, ReplyPayload>)>(reply.code(100).send) } const server = fastify() server.get('/get', getHandler) server.get('/typed', typedHandler) server.get<ReplyPayload>('/get-generic-send', async function handler (request, reply) { reply.send({ test: true }) }) server.get<ReplyPayload>('/get-generic-return', async function handler (request, reply) { return { test: false } }) expectError(server.get<ReplyPayload>('/get-generic-send-error', async function handler (request, reply) { reply.send({ foo: 'bar' }) })) expectError(server.get<ReplyPayload>('/get-generic-return-error', async function handler (request, reply) { return { foo: 'bar' } })) server.get<ReplyUnion>('/get-generic-union-send', async function handler (request, reply) { if (0 as number === 0) { reply.send({ success: true }) } else { reply.send({ error: 'error' }) } }) server.get<ReplyUnion>('/get-generic-union-return', async function handler (request, reply) { if (0 as number === 0) { return { success: true } } else { return { error: 'error' } } }) expectError(server.get<ReplyUnion>('/get-generic-union-send-error-1', async function handler (request, reply) { reply.send({ successes: true }) })) expectError(server.get<ReplyUnion>('/get-generic-union-send-error-2', async function handler (request, reply) { reply.send({ error: 500 }) })) expectError(server.get<ReplyUnion>('/get-generic-union-return-error-1', async function handler (request, reply) { return { successes: true } })) expectError(server.get<ReplyUnion>('/get-generic-union-return-error-2', async function handler (request, reply) { return { error: 500 } })) server.get<ReplyHttpCodes>('/get-generic-http-codes-send', async function handler (request, reply) { reply.code(200).send('abc') reply.code(201).send(true) reply.code(300).send({ foo: 'bar' }) reply.code(101).send(123) }) expectError(server.get<ReplyHttpCodes>('/get-generic-http-codes-send-error-1', async function handler (request, reply) { reply.code(200).send('def') })) expectError(server.get<ReplyHttpCodes>('/get-generic-http-codes-send-error-2', async function handler (request, reply) { reply.code(201).send(0) })) expectError(server.get<ReplyHttpCodes>('/get-generic-http-codes-send-error-3', async function handler (request, reply) { reply.code(300).send({ foo: 123 }) })) expectError(server.get<ReplyHttpCodes>('/get-generic-http-codes-send-error-4', async function handler (request, reply) { reply.code(100).send('asdasd') })) expectError(server.get<ReplyHttpCodes>('/get-generic-http-codes-send-error-5', async function handler (request, reply) { reply.code(401).send({ foo: 123 }) })) server.get<ReplyArrayPayload>('/get-generic-array-send', async function handler (request, reply) { reply.code(200).send(['']) }) expectError(server.get<InvalidReplyHttpCodes>('get-invalid-http-codes-reply-error', async function handler (request, reply) { reply.code(200).send('') })) server.get<InvalidReplyHttpCodes>('get-invalid-http-codes-reply-error', async function handler (request, reply) { reply.code(200).send({ '1xx': 0, 200: '', 999: false }) }) const httpHeaderHandler: RouteHandlerMethod = function (_request, reply) { // accept is a header provided by @types/node reply.getHeader('accept') reply.getHeaders().accept // eslint-disable-line no-unused-expressions reply.hasHeader('accept') reply.header('accept', 'test') reply.headers({ accept: 'test' }) reply.removeHeader('accept') // x-fastify-test is not a header provided by @types/node // and should not result in a typing error reply.getHeader('x-fastify-test') reply.getHeaders()['x-fastify-test'] // eslint-disable-line no-unused-expressions reply.hasHeader('x-fastify-test') reply.header('x-fastify-test', 'test') reply.headers({ 'x-fastify-test': 'test' }) reply.removeHeader('x-fastify-test') }