From 8780d31b5803ed2ceb78a36b11797f0a4a4f19ff Mon Sep 17 00:00:00 2001 From: Elias Schablowski <31389869+eschablowski@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:52:11 -0700 Subject: [PATCH 1/7] Add mapped types to index.d.ts This update removes the "standard" utility method definitions to log to the defined log levels, and check whether they are activated and replaces them with mapped types. This change allows for better intellisense, as well as more rigorous type checking in typescript --- index.d.ts | 43 ++++++++++++++----------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/index.d.ts b/index.d.ts index 929ef4ae0..a94ca8bd0 100644 --- a/index.d.ts +++ b/index.d.ts @@ -19,6 +19,8 @@ declare namespace winston { export import transports = Transports; export import transport = Transport; + type defaultLevels = "error" | "warn" | "info" | "http" | "verbose" | "debug" | "silly"; + class ExceptionHandler { constructor(logger: Logger); logger: Logger; @@ -92,8 +94,8 @@ declare namespace winston { (infoObject: object): Logger; } - interface LoggerOptions { - levels?: Config.AbstractConfigSetLevels; + interface LoggerOptions { + levels?: Config.AbstractConfigSetLevels; silent?: boolean; format?: logform.Format; level?: string; @@ -106,7 +108,15 @@ declare namespace winston { rejectionHandlers?: any; } - class Logger extends NodeJSStream.Transform { + // Used to dynamically add log levels + type LoggerLogFunctionsMap = { + [key in T]: LeveledLogMethod; + }; + type LoggerLogEnabledMap = { + [key in T]: () => boolean; + }; + + interface LoggerBase extends NodeJSStream.Transform { constructor(options?: LoggerOptions); silent: boolean; @@ -126,26 +136,6 @@ declare namespace winston { clear(): this; close(): this; - // for cli and npm levels - error: LeveledLogMethod; - warn: LeveledLogMethod; - help: LeveledLogMethod; - data: LeveledLogMethod; - info: LeveledLogMethod; - debug: LeveledLogMethod; - prompt: LeveledLogMethod; - http: LeveledLogMethod; - verbose: LeveledLogMethod; - input: LeveledLogMethod; - silly: LeveledLogMethod; - - // for syslog levels only - emerg: LeveledLogMethod; - alert: LeveledLogMethod; - crit: LeveledLogMethod; - warning: LeveledLogMethod; - notice: LeveledLogMethod; - query( options?: QueryOptions, callback?: (err: Error, results: any) => void @@ -160,13 +150,8 @@ declare namespace winston { child(options: Object): this; isLevelEnabled(level: string): boolean; - isErrorEnabled(): boolean; - isWarnEnabled(): boolean; - isInfoEnabled(): boolean; - isVerboseEnabled(): boolean; - isDebugEnabled(): boolean; - isSillyEnabled(): boolean; } + export type Logger = LoggerBase & LoggerLogFunctionsMap & LoggerLogEnabledMap; class Container { loggers: Map; From caa5fad30661859cf8ff1c1795780ba74cf4785e Mon Sep 17 00:00:00 2001 From: Elias Schablowski <31389869+eschablowski@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:55:10 -0700 Subject: [PATCH 2/7] Fix Log level enabled map This is a fix to get the actual `isEnabled`, which was a bug in the previous commit --- index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index a94ca8bd0..bc4154e23 100644 --- a/index.d.ts +++ b/index.d.ts @@ -113,7 +113,7 @@ declare namespace winston { [key in T]: LeveledLogMethod; }; type LoggerLogEnabledMap = { - [key in T]: () => boolean; + [key in `is${Capitalize}Enabled`]: () => boolean; }; interface LoggerBase extends NodeJSStream.Transform { From a62643de12fb3c3ce9a9fa92b78c73f26f4ef204 Mon Sep 17 00:00:00 2001 From: Elias Schablowski <31389869+eschablowski@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:57:25 -0700 Subject: [PATCH 3/7] Add type parameter to AbstractConfigSetLevels to allow type sensing in previous commits --- lib/winston/config/index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/winston/config/index.d.ts b/lib/winston/config/index.d.ts index 639f317e8..6c4e370ee 100644 --- a/lib/winston/config/index.d.ts +++ b/lib/winston/config/index.d.ts @@ -4,8 +4,8 @@ /// declare namespace winston { - interface AbstractConfigSetLevels { - [key: string]: number; + interface AbstractConfigSetLevels { + [key: T]: number; } interface AbstractConfigSetColors { From b1b6e1ef2996efefd03e3efb91cb95851fdab816 Mon Sep 17 00:00:00 2001 From: Elias Schablowski Date: Thu, 14 Sep 2023 15:12:54 -0700 Subject: [PATCH 4/7] Fix some misc. ts issues with the new template types --- index.d.ts | 20 ++++++++++---------- lib/winston/config/index.d.ts | 9 +++++---- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/index.d.ts b/index.d.ts index bc4154e23..75da553c0 100644 --- a/index.d.ts +++ b/index.d.ts @@ -94,7 +94,7 @@ declare namespace winston { (infoObject: object): Logger; } - interface LoggerOptions { + interface LoggerOptions { levels?: Config.AbstractConfigSetLevels; silent?: boolean; format?: logform.Format; @@ -117,11 +117,11 @@ declare namespace winston { }; interface LoggerBase extends NodeJSStream.Transform { - constructor(options?: LoggerOptions); + constructor(options?: LoggerOptions): Logger; silent: boolean; format: logform.Format; - levels: Config.AbstractConfigSetLevels; + levels: Config.AbstractConfigSetLevels; level: string; transports: Transport[]; exceptions: ExceptionHandler; @@ -145,7 +145,7 @@ declare namespace winston { startTimer(): Profiler; profile(id: string | number, meta?: Record): this; - configure(options: LoggerOptions): void; + configure(options: LoggerOptions): void; child(options: Object): this; @@ -155,21 +155,21 @@ declare namespace winston { class Container { loggers: Map; - options: LoggerOptions; + options: LoggerOptions; - add(id: string, options?: LoggerOptions): Logger; - get(id: string, options?: LoggerOptions): Logger; + add(id: string, options?: LoggerOptions): Logger; + get(id: string, options?: LoggerOptions): Logger; has(id: string): boolean; close(id?: string): void; - constructor(options?: LoggerOptions); + constructor(options?: LoggerOptions); } let version: string; let loggers: Container; let addColors: (target: Config.AbstractConfigSetColors) => any; - let createLogger: (options?: LoggerOptions) => Logger; + let createLogger: (options?: LoggerOptions) => Logger; // Pass-through npm level methods routed to the default logger. let error: LeveledLogMethod; @@ -192,7 +192,7 @@ declare namespace winston { let clear: () => Logger; let startTimer: () => Profiler; let profile: (id: string | number) => Logger; - let configure: (options: LoggerOptions) => void; + let configure: (options: LoggerOptions) => void; let child: (options: Object) => Logger; let level: string; let exceptions: ExceptionHandler; diff --git a/lib/winston/config/index.d.ts b/lib/winston/config/index.d.ts index 6c4e370ee..6fb9b0669 100644 --- a/lib/winston/config/index.d.ts +++ b/lib/winston/config/index.d.ts @@ -3,17 +3,18 @@ /// + declare namespace winston { - interface AbstractConfigSetLevels { - [key: T]: number; + type AbstractConfigSetLevels = { + [key in T]: number; } interface AbstractConfigSetColors { [key: string]: string | string[]; } - interface AbstractConfigSet { - levels: AbstractConfigSetLevels; + interface AbstractConfigSet { + levels: AbstractConfigSetLevels; colors: AbstractConfigSetColors; } From 4d967299ca5b66d381ba4656b4389e8cfbac28f0 Mon Sep 17 00:00:00 2001 From: Elias Schablowski Date: Tue, 19 Sep 2023 09:45:32 -0700 Subject: [PATCH 5/7] Fix some template type errors --- index.d.ts | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/index.d.ts b/index.d.ts index 75da553c0..1dd46874a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -65,25 +65,25 @@ declare namespace winston { done(info?: any): boolean; } - type LogCallback = ( + type LogCallback = ( error?: any, - level?: string, + level?: T, message?: string, meta?: any ) => void; - interface LogEntry { - level: string; + interface LogEntry { + level: T; message: string; [optionName: string]: any; } - interface LogMethod { - (level: string, message: string, callback: LogCallback): Logger; - (level: string, message: string, meta: any, callback: LogCallback): Logger; - (level: string, message: string, ...meta: any[]): Logger; - (entry: LogEntry): Logger; - (level: string, message: any): Logger; + interface LogMethod { + (level: T, message: string, callback: LogCallback): Logger; + (level: T, message: string, meta: any, callback: LogCallback): Logger; + (level: T, message: string, ...meta: any[]): Logger; + (entry: LogEntry): Logger; + (level: T, message: any): Logger; } interface LeveledLogMethod { @@ -117,7 +117,7 @@ declare namespace winston { }; interface LoggerBase extends NodeJSStream.Transform { - constructor(options?: LoggerOptions): Logger; + new (options?: LoggerOptions): Logger; silent: boolean; format: logform.Format; @@ -130,7 +130,7 @@ declare namespace winston { exitOnError: Function | boolean; defaultMeta?: any; - log: LogMethod; + log: LogMethod; add(transport: Transport): this; remove(transport: Transport): this; clear(): this; @@ -149,10 +149,10 @@ declare namespace winston { child(options: Object): this; - isLevelEnabled(level: string): boolean; + isLevelEnabled(level: T): boolean; } export type Logger = LoggerBase & LoggerLogFunctionsMap & LoggerLogEnabledMap; - + export const Logger: Logger; class Container { loggers: Map; options: LoggerOptions; @@ -181,7 +181,7 @@ declare namespace winston { let silly: LeveledLogMethod; // Other pass-through methods routed to the default logger. - let log: LogMethod; + let log: LogMethod; let query: ( options?: QueryOptions, callback?: (err: Error, results: any) => void @@ -192,7 +192,7 @@ declare namespace winston { let clear: () => Logger; let startTimer: () => Profiler; let profile: (id: string | number) => Logger; - let configure: (options: LoggerOptions) => void; + let configure: (options: LoggerOptions) => void; let child: (options: Object) => Logger; let level: string; let exceptions: ExceptionHandler; From e02faf7d13eee20970fa68292950b9204b89173f Mon Sep 17 00:00:00 2001 From: Elias Schablowski Date: Tue, 19 Sep 2023 09:45:45 -0700 Subject: [PATCH 6/7] Add more rigorous type error checking --- test/typescript-definitions.ts | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/typescript-definitions.ts b/test/typescript-definitions.ts index 4fb3b6553..a067fffc7 100644 --- a/test/typescript-definitions.ts +++ b/test/typescript-definitions.ts @@ -57,3 +57,42 @@ logger.isInfoEnabled(); logger.isVerboseEnabled(); logger.isDebugEnabled(); logger.isSillyEnabled(); + +let logger2 = winston.createLogger({ + levels: { + "one": 1, + two: 2 + }, + level: 'info', + format: winston.format.json(), + transports: [ + new winston.transports.Console({ level: 'info' }), + ], +}); + +logger2.isOneEnabled(); +// @ts-expect-error +logger2.isSillyEnabled(); + +let loggerFromClass = new winston.Logger({}); +loggerFromClass.isInfoEnabled(); +loggerFromClass.debug(""); +// @ts-expect-error +loggerFromClass.a(""); +// @ts-expect-error +loggerFromClass.isAEnabled(); + + +let loggerFromClass2 = new winston.Logger({ + levels: { + "a": 2, + "b": 3 + } +}); +// @ts-expect-error +loggerFromClass2.isInfoEnabled(); +// @ts-expect-error +loggerFromClass2.debug(""); + +loggerFromClass2.a(""); +loggerFromClass2.isAEnabled(); \ No newline at end of file From 851966caae609f4c8e955ed2207fcfda804574fc Mon Sep 17 00:00:00 2001 From: Elias Schablowski Date: Tue, 19 Sep 2023 10:04:22 -0700 Subject: [PATCH 7/7] Slightly stricter type checking for setting/getting the log level --- index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.d.ts b/index.d.ts index 1dd46874a..66daa8fcd 100644 --- a/index.d.ts +++ b/index.d.ts @@ -98,7 +98,7 @@ declare namespace winston { levels?: Config.AbstractConfigSetLevels; silent?: boolean; format?: logform.Format; - level?: string; + level?: T; exitOnError?: Function | boolean; defaultMeta?: any; transports?: Transport[] | Transport; @@ -122,7 +122,7 @@ declare namespace winston { silent: boolean; format: logform.Format; levels: Config.AbstractConfigSetLevels; - level: string; + level: T; transports: Transport[]; exceptions: ExceptionHandler; rejections: RejectionHandler;