KnodesCommunity/typedoc-plugins

View on GitHub
packages/pluginutils/src/plugin-logger.ts

Summary

Maintainability
A
0 mins
Test Coverage
C
77%
import { isString } from 'lodash';
import { LogLevel, Logger } from 'typedoc';

import type { ABasePlugin } from './base-plugin';

export class PluginLogger extends Logger {
    public constructor( private readonly _parent: Logger, private readonly _plugin: ABasePlugin, private readonly _context?: string ){
        super();
        this.level = this._parent.level;
    }

    /**
     * Create a new {@link PluginLogger} for the given context.
     *
     * @param context - The new logger context.
     * @returns the new logger.
     */
    public makeChildLogger( context?: string ){
        const newLogger = new PluginLogger( this._parent, this._plugin, context );
        newLogger.level = this.level;
        return newLogger;
    }

    /**
     * Log the given verbose message.
     *
     * @param text  - The message that should be logged.
     */
    public verbose( text: string | ( () => string ) ): void {
        this.log( text, LogLevel.Verbose );
    }

    /**
     * Log the given info message.
     *
     * @param text  - The message that should be logged.
     */
    public info( text: string | ( () => string ) ): void {
        this.log( text, LogLevel.Info );
    }

    /**
     * Log the given warning message.
     *
     * @param text  - The warning that should be logged.
     */
    public warn( text: string | ( () => string ) ): void {
        this.log( text, LogLevel.Warn );
    }

    /**
     * Log the given deprecation message.
     *
     * @param text  - The message that should be logged.
     * @param addStack - TODO: Not sure why ?
     */
    public deprecated( text: string | ( () => string ), addStack?: boolean ): void {
        if ( addStack ) {
            const stack = new Error().stack?.split( '\n' );
            if ( stack && stack.length >= 4 ) {
                text = () => `${text}\n${stack[3]}`;
            }
        }
        this.warn( text );
    }

    /**
     * Log the given error message.
     *
     * @param text  - The error that should be logged.
     */
    public error( text: string | ( () => string ) ): void {
        this.log( text, LogLevel.Error );
    }

    /**
     * Print a log message.
     *
     * @param message  - The message itself.
     * @param level  - The urgency of the log message.
     */
    public log( message: string | ( () => string ), level: LogLevel ): void {
        if( level < this.level ){
            return;
        }
        this._logThroughParent( message, level );
    }

    /**
     * Pass a log message to the parent.
     *
     * @param message  - The message itself.
     * @param level  - The urgency of the log message.
     */
    private _logThroughParent( message: string | ( () => string ), level: LogLevel ){
        if( this._parent instanceof PluginLogger ){
            this._parent._logThroughParent( message, level );
        } else {
            const loggerMethodMapper = {
                [LogLevel.Error]: 'error',
                [LogLevel.Warn]: 'warn',
                [LogLevel.Info]: 'info',
                [LogLevel.Verbose]: 'verbose',
            } as const;
            const parentMethod = loggerMethodMapper[level];
            const orignalLevel = this._parent.level;
            this._parent.level = LogLevel.Verbose;
            this._parent[parentMethod]( this._formatMessage( isString( message ) ? message : message() ) );
            this._parent.level = orignalLevel;
        }
    }

    /**
     * Format the given message.
     *
     * @param message - The message to format.
     * @returns the formatted message;
     */
    private _formatMessage( message: string ){
        let fullMessage = `[${this._plugin.package.name}]`;
        if( this._context ){
            fullMessage += ': ';
            fullMessage += this._context;
        }
        fullMessage += ' ⇒ ';
        fullMessage += message;
        return fullMessage;
    }
}