fastify
Version:
Fast and low overhead web framework, for Node.js
230 lines (193 loc) • 6.4 kB
text/typescript
import { expectAssignable, expectDeprecated, expectError, expectNotAssignable, expectType } from 'tsd'
import fastify, {
FastifyLogFn,
LogLevel,
FastifyLoggerInstance,
FastifyRequest,
FastifyReply,
FastifyBaseLogger,
FastifyInstance
} from '../../fastify'
import { Server, IncomingMessage, ServerResponse } from 'http'
import * as fs from 'fs'
import P from 'pino'
import { ResSerializerReply } from '../../types/logger'
expectType<FastifyLoggerInstance>(fastify().log)
class Foo {}
['trace', 'debug', 'info', 'warn', 'error', 'fatal'].forEach(logLevel => {
expectType<FastifyLogFn>(fastify<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance>().log[logLevel as LogLevel])
expectType<void>(fastify<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance>().log[logLevel as LogLevel](''))
expectType<void>(fastify<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance>().log[logLevel as LogLevel]({}))
expectType<void>(fastify<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance>().log[logLevel as LogLevel]({ foo: 'bar' }))
expectType<void>(fastify<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance>().log[logLevel as LogLevel](new Error()))
expectType<void>(fastify<Server, IncomingMessage, ServerResponse, FastifyLoggerInstance>().log[logLevel as LogLevel](new Foo()))
})
interface CustomLogger extends FastifyBaseLogger {
customMethod(msg: string, ...args: unknown[]): void;
}
class CustomLoggerImpl implements CustomLogger {
level = 'info'
customMethod (msg: string, ...args: unknown[]) { console.log(msg, args) }
// Implementation signature must be compatible with all overloads of FastifyLogFn
info (arg1: unknown, arg2?: unknown, ...args: unknown[]): void {
console.log(arg1, arg2, ...args)
}
warn (...args: unknown[]) { console.log(args) }
error (...args: unknown[]) { console.log(args) }
fatal (...args: unknown[]) { console.log(args) }
trace (...args: unknown[]) { console.log(args) }
debug (...args: unknown[]) { console.log(args) }
silent (...args: unknown[]) { }
child (bindings: P.Bindings, options?: P.ChildLoggerOptions): CustomLoggerImpl { return new CustomLoggerImpl() }
}
const customLogger = new CustomLoggerImpl()
const serverWithCustomLogger = fastify<
Server,
IncomingMessage,
ServerResponse,
CustomLoggerImpl
>({ logger: customLogger })
expectType<CustomLoggerImpl>(serverWithCustomLogger.log)
const serverWithPino = fastify<
Server,
IncomingMessage,
ServerResponse,
P.Logger
>({
logger: P({
level: 'info',
redact: ['x-userinfo']
})
})
expectType<P.Logger>(serverWithPino.log)
serverWithPino.route({
method: 'GET',
url: '/',
handler (request) {
expectType<P.Logger>(this.log)
expectType<P.Logger>(request.log)
}
})
serverWithPino.get('/', function (request) {
expectType<P.Logger>(this.log)
expectType<P.Logger>(request.log)
})
const serverWithLogOptions = fastify<
Server,
IncomingMessage,
ServerResponse
>({
logger: {
level: 'info'
}
})
expectType<FastifyLoggerInstance>(serverWithLogOptions.log)
const serverWithFileOption = fastify<
Server,
IncomingMessage,
ServerResponse
>({
logger: {
level: 'info',
file: '/path/to/file'
}
})
expectType<FastifyLoggerInstance>(serverWithFileOption.log)
const serverAutoInferringTypes = fastify({
logger: {
level: 'info'
}
})
expectType<FastifyBaseLogger>(serverAutoInferringTypes.log)
const serverWithAutoInferredPino = fastify({
logger: P({
level: 'info',
redact: ['x-userinfo']
})
})
expectType<P.Logger>(serverWithAutoInferredPino.log)
const serverAutoInferredFileOption = fastify({
logger: {
level: 'info',
file: '/path/to/file'
}
})
expectType<FastifyBaseLogger>(serverAutoInferredFileOption.log)
const serverAutoInferredSerializerResponseObjectOption = fastify({
logger: {
serializers: {
res (ServerResponse) {
expectType<ResSerializerReply<Server, FastifyReply>>(ServerResponse)
expectAssignable<Partial<FastifyReply> & Pick<FastifyReply, 'statusCode'>>(ServerResponse)
expectNotAssignable<FastifyReply>(ServerResponse)
return {
status: '200'
}
}
}
}
})
expectType<FastifyBaseLogger>(serverAutoInferredSerializerResponseObjectOption.log)
const serverAutoInferredSerializerObjectOption = fastify({
logger: {
serializers: {
req (IncomingMessage) {
expectType<FastifyRequest>(IncomingMessage)
return {
method: 'method',
url: 'url',
version: 'version',
hostname: 'hostname',
remoteAddress: 'remoteAddress',
remotePort: 80,
other: ''
}
},
res (ServerResponse) {
expectType<ResSerializerReply<Server, FastifyReply>>(ServerResponse)
expectAssignable<Partial<FastifyReply> & Pick<FastifyReply, 'statusCode'>>(ServerResponse)
expectNotAssignable<FastifyReply>(ServerResponse)
return {
statusCode: 'statusCode'
}
},
err (FastifyError) {
return {
other: '',
type: 'type',
message: 'msg',
stack: 'stack'
}
}
}
}
})
expectType<FastifyBaseLogger>(serverAutoInferredSerializerObjectOption.log)
const passStreamAsOption = fastify({
logger: {
stream: fs.createWriteStream('/tmp/stream.out')
}
})
expectType<FastifyBaseLogger>(passStreamAsOption.log)
const passPinoOption = fastify({
logger: {
redact: ['custom'],
messageKey: 'msg',
nestedKey: 'nested',
enabled: true
}
})
expectType<FastifyBaseLogger>(passPinoOption.log)
// FastifyLoggerInstance is deprecated
expectDeprecated({} as FastifyLoggerInstance)
const childParent = fastify().log
// we test different option variant here
expectType<FastifyLoggerInstance>(childParent.child({}, { level: 'info' }))
expectType<FastifyLoggerInstance>(childParent.child({}, { level: 'silent' }))
expectType<FastifyLoggerInstance>(childParent.child({}, { redact: ['pass', 'pin'] }))
expectType<FastifyLoggerInstance>(childParent.child({}, { serializers: { key: () => {} } }))
expectType<FastifyLoggerInstance>(childParent.child({}, { level: 'info', redact: ['pass', 'pin'], serializers: { key: () => {} } }))
// no option pass
expectError(childParent.child())
// wrong option
expectError(childParent.child({}, { nonExist: true }))