import type pino from "pino"; import type { Context, Elysia, RouteSchema, ErrorHandler, SingletonBase, EphemeralType } from "elysia"; /** * The StreamLogger is used to write log entries to a stream such as the console output. */ export interface StreamLoggerOptions extends BaseLoggerOptions { stream?: pino.DestinationStream; } export interface ElysiaStreamLoggerOptions extends StreamLoggerOptions, ElysiaLoggerOptions { } /** * A FileLogger lets you store log entries in a file. */ export interface FileLoggerOptions extends BaseLoggerOptions { file: string | number | pino.DestinationStream | NodeJS.WritableStream; } export interface ElysiaFileLoggerOptions extends FileLoggerOptions, ElysiaLoggerOptions { } export type StandaloneLoggerOptions = StreamLoggerOptions | FileLoggerOptions; export type LoggerOptions = StandaloneLoggerOptions & ElysiaLoggerOptions; export type ErrorContext = {}, Route extends RouteSchema = RouteSchema, Singleton extends SingletonBase = SingletonBase, Ephemeral extends EphemeralType = EphemeralType, Volatile extends EphemeralType = EphemeralType> = Parameters>[0]; export type ElysiaLoggerContext = ({ isError: false; } & Context) | ({ isError: true; } & ErrorContext); export type ElysiaLoggerOptions = { /** * This function will be invoked for each `log`-method called with `context` * where you can pass additional properties that need to be logged */ customProps?: (ctx: ElysiaLoggerContext) => object; /** * Disable the automatic "onAfterResponse" & "onError" logging * * @default true */ autoLogging?: boolean | { ignore: (ctx: ElysiaLoggerContext) => boolean; }; /** * The log level to use for logging the response * * @default "info" */ useLevel?: pino.LevelWithSilent; }; export interface ElysiaLogger extends Logger { /** * Call `into` to use the logger instance in both `ctx` and standalone * * @example * const log = createPinoLogger(...); * app * .use(log.into()) * .onError((ctx) => { * log.error(ctx, ctx.error.name); * return 'onError'; * }) * .get('/', (ctx) => { * ctx.log.info(ctx, 'Context'); * throw { message: '1234', name: 'MyError' }; * }) */ into(options?: _INTERNAL_ElysiaLoggerPluginAutoLoggingEnabledOptions): _INTERNAL_ElysiaLoggerPlugin<_INTERNAL_ElysiaLoggerPluginAutoLoggingState>; into(options?: _INTERNAL_ElysiaLoggerPluginAutoLoggingDisabledOptions): _INTERNAL_ElysiaLoggerPlugin; into(options?: ElysiaLoggerOptions): E; } export interface BaseLoggerOptions extends pino.LoggerOptions { } export type Logger = pino.Logger & BaseLoggerOptions; export type InferContext = T extends Elysia ? ({ isError: false; } & Context; store: Partial; derive: Partial; resolve: Partial; }>) | ({ isError: true; } & ErrorContext; store: Partial; derive: Partial; resolve: Partial; }>) : never; /** * Make all properties in T NOT readonly * * based on @see Readonly */ export type _INTERNAL_Writeonly = { -readonly [P in keyof T]: T[P]; }; export type _INTERNAL_ElysiaLoggerPluginAutoLoggingState = { readonly startTime?: number; readonly endTime?: number; readonly responseTime?: number; }; export type _INTERNAL_ElysiaLoggerPlugin = Elysia<"", { store: Store; derive: { readonly log: Logger; }; decorator: {}; resolve: {}; }>; export type _INTERNAL_ElysiaLoggerPluginAutoLoggingEnabledOptions = Omit & { autoLogging?: true | { ignore: (ctx: ElysiaLoggerContext) => boolean; }; }; export type _INTERNAL_ElysiaLoggerPluginAutoLoggingDisabledOptions = Omit & { autoLogging: false | boolean; };