import chalk from 'chalk' ; import * as log from 'log-update' ; import { loggerSymbols } from './logger-symbols' ; import { supportsAdvancedLogging } from '../utilities/supports-advanced-logging' ; import { isWindows } from '../utilities/is-windows' ; import { AngularPackageLoggerTask , AngularPackageLoggerMessage , AngularPackageLoggerMessageType , AngularPackageLoggerTaskStatus } from './angular-package-logger.interfaces' ; /**
 * Angular Package Logger
 */ export class AngularPackageLogger { /**
     * Logging state (for advanced logging only)
     */ private static state : Array < AngularPackageLoggerTask > = [ ] ; /**
     * Number of build steps (used for the build progress logging)
     */ private static numberOfBuildSteps : number = 0 ; /**
     * Number of the currently executed build step (used for the build progress logging)
     */ private static currentBuildStepNumber : number = 0 ; /**
     * Runtime of the current build, in ms (used for task success logging)
     */ private static currentBuildRuntime : number ; /**
     * Indentation on the left (used whne logging build details)
     */ private static leftIndentation : string = '' ; /**
     * Maximum number of build number digits (used for padding the current task number to the same length)
     */ private static buildNumberMaxNumberOfDigits : number ; param numberOfBuildSteps public static configureNumberOfBuildSteps ( numberOfBuildSteps ) { this . currentBuildStepNumber = 0 ; this . currentBuildRuntime = undefined ; this . numberOfBuildSteps = numberOfBuildSteps ; this . buildNumberMaxNumberOfDigits = this . numberOfBuildSteps . toString ( ) . length ; this . leftIndentation = this . numberOfBuildSteps === 1 ? '' : ' ' . repeat ( this . buildNumberMaxNumberOfDigits * 2 + 4 ) ; } param name public static logTitle ( name ) { console . log ( '' ) ; console . log ( isWindows ( ) ? chalk . white ( name ) : chalk . white . underline ( name ) ) ; console . log ( '' ) ; } param packageName public static logBuildStart ( packageName ) { this . currentBuildRuntime = new Date ( ) . getTime ( ) ; this . currentBuildStepNumber ++ ; const currentBuildStepNumberPaddingLeft = '0' . repeat ( this . numberOfBuildSteps . toString ( ) . length - this . currentBuildStepNumber . toString ( ) . length ) ; const buildProgressLog = this . numberOfBuildSteps === 1 ? '' : `[${ currentBuildStepNumberPaddingLeft }${ this . currentBuildStepNumber }/${ this . numberOfBuildSteps }] ` ; console . log ( '' ) ; console . log ( `${ chalk . bold . blue ( buildProgressLog ) }${ chalk . bold . white ( `Package "${ packageName }"` ) }` ) ; console . log ( '' ) ; } /**
     * Log the current build success
     */ public static logBuildSuccess ( ) { if ( supportsAdvancedLogging ( ) ) { log . done ( ) ; this . state = [ ] ; } this . currentBuildRuntime = new Date ( ) . getTime ( ) - this . currentBuildRuntime ; console . log ( '' ) ; console . log ( chalk . bold . green ( `${ this . leftIndentation }Success!` ) , chalk . grey ( `(${ ( this . currentBuildRuntime / 1000 ) . toFixed ( 2 ) } seconds)` ) ) ; console . log ( '' ) ; } /**
     * Log the current build error
     */ public static logBuildError ( ) { if ( supportsAdvancedLogging ( ) ) { log . done ( ) ; this . state = [ ] ; } this . currentBuildRuntime = new Date ( ) . getTime ( ) - this . currentBuildRuntime ; console . log ( '' ) ; console . log ( chalk . bold . red ( `${ this . leftIndentation }Error!` ) , chalk . grey ( `(${ ( this . currentBuildRuntime / 1000 ) . toFixed ( 2 ) } seconds)` ) ) ; console . log ( '' ) ; } param task public static logTaskStart ( task ) { if ( supportsAdvancedLogging ( ) ) { this . state . push ( { task , status : 'running' , messages : [ ] } ) ; this . logToConsoleAdvanced ( ) ; } else { console . log ( this . createTaskLogOutput ( task , 'running' ) ) ; } } /**
     * Log the current task success
     */ public static logTaskSuccess ( ) { if ( supportsAdvancedLogging ( ) ) { this . state . slice ( - 1 ) [ 0 ] . status = 'success' ; this . logToConsoleAdvanced ( ) ; } } /**
     * Log the current task error
     */ public static logTaskError ( ) { if ( supportsAdvancedLogging ( ) ) { this . state . slice ( - 1 ) [ 0 ] . status = 'error' ; this . logToConsoleAdvanced ( ) ; } } public static logPreparationMessage ( message , type ) { console . log ( this . createMessageLogOutput ( message , type ) ) ; } param message public static logMessage ( message , type = 'default' ) { if ( supportsAdvancedLogging ( ) ) { this . state . slice ( - 1 ) [ 0 ] . messages = [ ... this . state . slice ( - 1 ) [ 0 ] . messages . filter ( ( loggerMessage ) : boolean => { return loggerMessage . type !== 'default' ; } ) , { type , message : message } ] ; this . logToConsoleAdvanced ( ) ; } else { if ( type !== 'default' ) { console . log ( this . createMessageLogOutput ( message , type ) ) ; } } } /**
     * Advanced / dynamic logging to console, based on the current state
     */ private static logToConsoleAdvanced ( ) { const logOutput = this . state . reduce ( ( logLines , loggerTask ) : Array < string > => { logLines . push ( this . createTaskLogOutput ( loggerTask . task , loggerTask . status ) ) ; logLines . push ( ... loggerTask . messages . filter ( ( loggerMessage ) : boolean => { return loggerTask . status === 'running' ? true : loggerMessage . type !== 'default' ; } ) . map ( ( loggerMessage ) : string => { return this . createMessageLogOutput ( loggerMessage . message , loggerMessage . type ) ; } ) ) ; return logLines ; } , [ ] ) ; log ( logOutput . join ( '\n' ) ) ; } param task param status private static createTaskLogOutput ( task , status ) { switch ( status ) { case 'success' : return chalk . white ( `${ this . leftIndentation }${ chalk . green ( loggerSymbols . tick ) } ${ task }` ) ; case 'error' : return chalk . white ( `${ this . leftIndentation }${ chalk . red ( loggerSymbols . error ) } ${ task }` ) ; default : return chalk . white ( `${ this . leftIndentation }${ loggerSymbols . pointer } ${ task }` ) ; } } param message param type private static createMessageLogOutput ( message , type ) { const leftIndentation = this . leftIndentation && this . leftIndentation !== '' ? `${ this . leftIndentation }  ` : '' ; switch ( type ) { case 'warning' : return chalk . white ( [ '' , ... message . split ( '\n' ) , '' ] . map ( ( messagePart , index ) : string => { return index === 1 ? chalk . yellow ( `${ leftIndentation }${ chalk . bgYellow . white ( ' WARNING ' ) } ${ messagePart }` ) : messagePart . startsWith ( 'Tip' ) ? chalk . yellow ( `${ leftIndentation }          ${ messagePart }` ) : messagePart . startsWith ( 'Note' ) ? chalk . gray ( `${ leftIndentation }          ${ messagePart }` ) : chalk . white ( `${ leftIndentation }          ${ messagePart }` ) ; } ) . join ( '\n' ) ) ; case 'error' : return chalk . white ( [ '' , ... message . split ( '\n' ) ] . map ( ( messagePart , index ) : string => { return index === 1 ? chalk . red ( `${ leftIndentation }${ chalk . bgRed . white ( ' ERROR ' ) } ${ messagePart }` ) : messagePart . startsWith ( 'Tip' ) ? chalk . yellow ( `${ leftIndentation }        ${ messagePart }` ) : messagePart . startsWith ( 'Note' ) ? chalk . gray ( `${ leftIndentation }        ${ messagePart }` ) : chalk . white ( `${ leftIndentation }        ${ messagePart }` ) ; } ) . join ( '\n' ) ) ; default : return chalk . grey ( `${ leftIndentation }${ loggerSymbols . arrow } ${ message }` ) ; } } }