UNPKG

fastify

Version:

Fast and low overhead web framework, for Node.js

545 lines (498 loc) 21.2 kB
import { FastifyError } from '@fastify/error' import { expectAssignable, expectError, expectType } from 'tsd' import fastify, { ContextConfigDefault, FastifyContextConfig, FastifyInstance, FastifyPluginOptions, FastifyReply, FastifyRequest, FastifySchema, FastifyTypeProviderDefault, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault, RegisterOptions, RouteOptions, // preClose hook types should be exported correctly https://github.com/fastify/fastify/pull/5335 preCloseAsyncHookHandler, preCloseHookHandler } from '../../fastify' import { DoneFuncWithErrOrRes, HookHandlerDoneFunction, RequestPayload, preHandlerAsyncHookHandler } from '../../types/hooks' import { FastifyRouteConfig, RouteGenericInterface } from '../../types/route' const server = fastify() // Test payload generic pass through for preSerialization and onSend type TestPayloadType = { foo: string; bar: number; } // Synchronous Tests server.addHook('onRequest', function (request, reply, done) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectAssignable<(err?: FastifyError) => void>(done) expectAssignable<(err?: NodeJS.ErrnoException) => void>(done) expectType<void>(done(new Error())) }) server.addHook('preParsing', function (request, reply, payload, done) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<RequestPayload>(payload) expectAssignable<(err?: FastifyError | null, res?: RequestPayload) => void>(done) expectAssignable<(err?: NodeJS.ErrnoException) => void>(done) expectType<void>(done(new Error())) }) server.addHook('preValidation', function (request, reply, done) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectAssignable<(err?: FastifyError) => void>(done) expectAssignable<(err?: NodeJS.ErrnoException) => void>(done) expectType<void>(done(new Error())) }) server.addHook('preHandler', function (request, reply, done) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectAssignable<(err?: FastifyError) => void>(done) expectAssignable<(err?: NodeJS.ErrnoException) => void>(done) expectType<void>(done(new Error())) }) server.addHook<TestPayloadType>('preSerialization', function (request, reply, payload, done) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<TestPayloadType>(payload) // we expect this to be unknown when not specified like in the previous test expectType<void>(done(new Error())) expectType<void>(done(null, 'foobar')) expectType<void>(done()) expectError<void>(done(new Error(), 'foobar')) }) server.addHook<TestPayloadType>('onSend', function (request, reply, payload, done) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<TestPayloadType>(payload) expectType<void>(done(new Error())) expectType<void>(done(null, 'foobar')) expectType<void>(done()) expectError<void>(done(new Error(), 'foobar')) }) server.addHook('onResponse', function (request, reply, done) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectAssignable<(err?: FastifyError) => void>(done) expectAssignable<(err?: NodeJS.ErrnoException) => void>(done) expectType<void>(done(new Error())) }) server.addHook('onTimeout', function (request, reply, done) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectAssignable<(err?: FastifyError) => void>(done) expectAssignable<(err?: NodeJS.ErrnoException) => void>(done) expectType<void>(done(new Error())) }) server.addHook('onError', function (request, reply, error, done) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<FastifyError>(error) expectType<() => void>(done) expectType<void>(done()) }) server.addHook('onRequestAbort', function (request, done) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectAssignable<(err?: FastifyError) => void>(done) expectAssignable<(err?: NodeJS.ErrnoException) => void>(done) expectType<void>(done(new Error())) }) server.addHook('onRoute', function (opts) { expectType<FastifyInstance>(this) expectType<RouteOptions & { routePath: string; path: string; prefix: string }>(opts) }) server.addHook('onRegister', (instance, opts, done) => { expectType<FastifyInstance>(instance) expectType<RegisterOptions & FastifyPluginOptions>(opts) expectAssignable<(err?: FastifyError) => void>(done) expectAssignable<(err?: NodeJS.ErrnoException) => void>(done) expectType<void>(done(new Error())) }) server.addHook('onReady', function (done) { expectType<FastifyInstance>(this) expectAssignable<(err?: FastifyError) => void>(done) expectAssignable<(err?: NodeJS.ErrnoException) => void>(done) expectType<void>(done(new Error())) }) server.addHook('onListen', function (done) { expectType<FastifyInstance>(this) expectAssignable<(err?: FastifyError) => void>(done) expectAssignable<(err?: NodeJS.ErrnoException) => void>(done) }) server.addHook('onClose', (instance, done) => { expectType<FastifyInstance>(instance) expectAssignable<(err?: FastifyError) => void>(done) expectAssignable<(err?: NodeJS.ErrnoException) => void>(done) expectType<void>(done(new Error())) }) // Asynchronous server.addHook('onRequest', async function (request, reply) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) }) server.addHook('preParsing', async function (request, reply, payload) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<RequestPayload>(payload) }) server.addHook('preValidation', async function (request, reply) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) }) server.addHook('preHandler', async function (request, reply) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) }) server.addHook<TestPayloadType>('preSerialization', async function (request, reply, payload) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<TestPayloadType>(payload) // we expect this to be unknown when not specified like in the previous test }) server.addHook<TestPayloadType>('onSend', async function (request, reply, payload) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<TestPayloadType>(payload) }) server.addHook('onResponse', async function (request, reply) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) }) server.addHook('onTimeout', async function (request, reply) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) }) server.addHook('onError', async function (request, reply, error) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<FastifyError>(error) }) server.addHook('onRequestAbort', async function (request) { expectType<FastifyInstance>(this) expectType<FastifyRequest>(request) }) server.addHook('onRegister', async (instance, opts) => { expectType<FastifyInstance>(instance) expectType<RegisterOptions & FastifyPluginOptions>(opts) }) server.addHook('onReady', async function () { expectType<FastifyInstance>(this) }) server.addHook('onListen', async function () { expectType<FastifyInstance>(this) }) server.addHook('onClose', async (instance) => { expectType<FastifyInstance>(instance) }) // Use case to monitor any regression on issue #3620 // ref.: https://github.com/fastify/fastify/issues/3620 const customTypedHook: preHandlerAsyncHookHandler< RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RouteGenericInterface, ContextConfigDefault, FastifySchema, FastifyTypeProviderDefault > = async function (request, reply): Promise<void> { expectType<FastifyInstance>(this) expectAssignable<FastifyRequest>(request) expectAssignable<FastifyReply>(reply) } server.register(async (instance) => { instance.addHook('preHandler', customTypedHook) }) // Test custom Context Config types for hooks type CustomContextConfig = FastifyContextConfig & { foo: string; bar: number; } type CustomContextConfigWithDefault = CustomContextConfig & FastifyRouteConfig server.route<RouteGenericInterface, CustomContextConfig>({ method: 'GET', url: '/', handler: () => { }, onRequest: (request, reply, done) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, preParsing: (request, reply, payload, done) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, preValidation: (request, reply, done) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, preHandler: (request, reply, done) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, preSerialization: (request, reply, payload, done) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, onSend: (request, reply, payload, done) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, onResponse: (request, reply, done) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, onTimeout: (request, reply, done) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, onError: (request, reply, error, done) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) } }) server.get<RouteGenericInterface, CustomContextConfig>('/', { onRequest: async (request, reply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, preParsing: async (request, reply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, preValidation: async (request, reply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, preHandler: async (request, reply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, preSerialization: async (request, reply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, onSend: async (request, reply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, onResponse: async (request, reply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, onTimeout: async (request, reply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, onError: async (request, reply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) } }, async (request, reply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }) type CustomContextRequest = FastifyRequest<any, any, any, any, any, CustomContextConfig, any> type CustomContextReply = FastifyReply<any, any, any, any, CustomContextConfig, any, any> server.route<RouteGenericInterface, CustomContextConfig>({ method: 'GET', url: '/', handler: () => { }, onRequest: async (request: CustomContextRequest, reply: CustomContextReply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, preParsing: async (request: CustomContextRequest, reply: CustomContextReply, payload: RequestPayload) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, preValidation: async (request: CustomContextRequest, reply: CustomContextReply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, preHandler: async (request: CustomContextRequest, reply: CustomContextReply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, preSerialization: async (request: CustomContextRequest, reply: CustomContextReply, payload: any) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, onSend: async (request: CustomContextRequest, reply: CustomContextReply, payload: any) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, onResponse: async (request: CustomContextRequest, reply: CustomContextReply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, onTimeout: async (request: CustomContextRequest, reply: CustomContextReply) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) }, onError: async (request: CustomContextRequest, reply: CustomContextReply, error: FastifyError) => { expectType<CustomContextConfigWithDefault>(request.context.config) expectType<CustomContextConfigWithDefault>(reply.context.config) } }) server.route({ method: 'GET', url: '/', handler: (request, reply) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) }, onRequest: (request, reply, done) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<HookHandlerDoneFunction>(done) }, onRequestAbort: (request, done) => { expectType<FastifyRequest>(request) expectType<HookHandlerDoneFunction>(done) }, preParsing: (request, reply, payload, done) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<RequestPayload>(payload) expectType<<TError extends Error = FastifyError>(err?: TError | null | undefined, res?: RequestPayload | undefined) => void>(done) }, preValidation: (request, reply, done) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<HookHandlerDoneFunction>(done) }, preHandler: (request, reply, done) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<HookHandlerDoneFunction>(done) }, preSerialization: (request, reply, payload, done) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<unknown>(payload) expectType<DoneFuncWithErrOrRes>(done) }, onSend: (request, reply, payload, done) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<unknown>(payload) expectType<DoneFuncWithErrOrRes>(done) }, onResponse: (request, reply, done) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<HookHandlerDoneFunction>(done) }, onTimeout: (request, reply, done) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<HookHandlerDoneFunction>(done) }, onError: (request, reply, error, done) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<FastifyError>(error) expectType<() => void>(done) } }) server.get('/', { onRequest: async (request, reply) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) }, onRequestAbort: async (request, reply) => { expectType<FastifyRequest>(request) }, preParsing: async (request, reply, payload) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<RequestPayload>(payload) }, preValidation: async (request, reply) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) }, preHandler: async (request, reply) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) }, preSerialization: async (request, reply, payload) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<unknown>(payload) }, onSend: async (request, reply, payload) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<unknown>(payload) }, onResponse: async (request, reply) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) }, onTimeout: async (request, reply) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) }, onError: async (request, reply, error) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) expectType<FastifyError>(error) } }, async (request, reply) => { expectType<FastifyRequest>(request) expectType<FastifyReply>(reply) }) // TODO: Should throw errors // expectError(server.get('/', { onRequest: async (request, reply, done) => {} }, async (request, reply) => {})) // expectError(server.get('/', { onRequestAbort: async (request, done) => {} }, async (request, reply) => {})) // expectError(server.get('/', { preParsing: async (request, reply, payload, done) => {} }, async (request, reply) => {})) // expectError(server.get('/', { preValidation: async (request, reply, done) => {} }, async (request, reply) => {})) // expectError(server.get('/', { preHandler: async (request, reply, done) => {} }, async (request, reply) => {})) // expectError(server.get('/', { preSerialization: async (request, reply, payload, done) => {} }, async (request, reply) => {})) // expectError(server.get('/', { onSend: async (request, reply, payload, done) => {} }, async (request, reply) => {})) // expectError(server.get('/', { onResponse: async (request, reply, done) => {} }, async (request, reply) => {})) // expectError(server.get('/', { onTimeout: async (request, reply, done) => {} }, async (request, reply) => {})) // expectError(server.get('/', { onError: async (request, reply, error, done) => {} }, async (request, reply) => {})) server.addHook('preClose', function (done) { expectType<FastifyInstance>(this) expectAssignable<(err?: FastifyError) => void>(done) expectAssignable<(err?: NodeJS.ErrnoException) => void>(done) expectType<void>(done(new Error())) }) server.addHook('preClose', async function () { expectType<FastifyInstance>(this) }) expectError(server.addHook('onClose', async function (instance, done) {})) expectError(server.addHook('onError', async function (request, reply, error, done) {})) expectError(server.addHook('onReady', async function (done) {})) expectError(server.addHook('onListen', async function (done) {})) expectError(server.addHook('onRequest', async function (request, reply, done) {})) expectError(server.addHook('onRequestAbort', async function (request, done) {})) expectError(server.addHook('onResponse', async function (request, reply, done) {})) expectError(server.addHook('onSend', async function (request, reply, payload, done) {})) expectError(server.addHook('onTimeout', async function (request, reply, done) {})) expectError(server.addHook('preClose', async function (done) {})) expectError(server.addHook('preHandler', async function (request, reply, done) {})) expectError(server.addHook('preSerialization', async function (request, reply, payload, done) {})) expectError(server.addHook('preValidation', async function (request, reply, done) {}))