11/* eslint-disable @typescript-eslint/no-explicit-any */
22
3+ import { EOL } from 'os' ;
4+ import util from 'util' ;
5+ import cloneDeep from 'lodash/cloneDeep' ;
6+
37export default interface Logger {
48 info ( message ?: any , ...args : any [ ] ) : void ;
59 warn ( message ?: any , ...args : any [ ] ) : void ;
@@ -14,41 +18,94 @@ function isExLogger(obj: any): obj is ExLogger {
1418 return typeof obj . success === 'function' ;
1519}
1620
21+ let _logger : Logger ;
22+ export const logger = ( ) => _logger ?? console ;
23+ export const initLogger = ( logger : Logger ) => _logger = logger ;
24+
1725export class PrefixLogger implements ExLogger {
1826 constructor (
1927 public log : Logger ,
20- public prefix : string ,
28+ public prefix : string = '' ,
2129 public debugMode = false ,
30+ private mask = ! debugMode ,
2231 ) {
2332 this . debugMode = this . debugMode || process . argv . includes ( '-D' ) || process . argv . includes ( '--debug' ) ;
2433 }
2534
2635 debug ( message ?: any , ...args : any [ ] ) {
36+ message = typeof message === 'string' ? this . masking ( message ) : this . maskingValue ( message ) ;
37+ args = args ?. map ( arg => typeof arg === 'string' ? this . masking ( arg ) : arg ) ;
2738 if ( this . debugMode ) {
28- this . log . info ( ( this . prefix ? `[ ${ this . prefix } ] ` : '' ) + message , ...args ) ;
39+ this . log . info ( util . format ( `[%s] ${ typeof message === 'string' ? '%s' : '%O' } ` , this . prefix , message ) , ...args ) ;
2940 } else {
30- this . log . debug ( ( this . prefix ? `[ ${ this . prefix } ] ` : '' ) + message , ...args ) ;
41+ this . log . debug ( util . format ( `[%s] ${ typeof message === 'string' ? '%s' : '%O' } ` , this . prefix , message ) , ...args ) ;
3142 }
3243 }
3344
3445 info ( message ?: any , ...args : any [ ] ) {
35- this . log . info ( ( this . prefix ? `[${ this . prefix } ] ` : '' ) + message , ...args ) ;
46+ message = typeof message === 'string' ? this . masking ( message ) : this . maskingValue ( message ) ;
47+ args = args ?. map ( arg => typeof arg === 'string' ? this . masking ( arg ) : arg ) ;
48+ this . log . info ( util . format ( `[%s] ${ typeof message === 'string' ? '%s' : '%O' } ` , this . prefix , message ) , ...args ) ;
3649 }
3750
3851 warn ( message ?: any , ...args : any [ ] ) {
39- this . log . warn ( ( this . prefix ? `[${ this . prefix } ] ` : '' ) + message , ...args ) ;
52+ message = typeof message === 'string' ? this . masking ( message ) : this . maskingValue ( message ) ;
53+ args = args ?. map ( arg => typeof arg === 'string' ? this . masking ( arg ) : arg ) ;
54+ this . log . warn ( util . format ( `[%s] ${ typeof message === 'string' ? '%s' : '%O' } ` , this . prefix , message ) , ...args ) ;
4055 }
4156
4257 error ( message ?: any , ...args : any [ ] ) {
43- this . log . error ( ( this . prefix ? `[${ this . prefix } ] ` : '' ) + message , ...args ) ;
58+ message = typeof message === 'string' ? this . masking ( message ) : this . maskingValue ( message ) ;
59+ args = args ?. map ( arg => typeof arg === 'string' ? this . masking ( arg ) : arg ) ;
60+ this . log . error ( util . format ( `[%s] ${ typeof message === 'string' ? '%s' : '%O' } ` , this . prefix , message ) , ...args ) ;
4461 }
4562
4663 success ( message ?: any , ...args : any [ ] ) {
64+ message = typeof message === 'string' ? this . masking ( message ) : this . maskingValue ( message ) ;
65+ args = args ?. map ( arg => typeof arg === 'string' ? this . masking ( arg ) : this . maskingValue ( arg ) ) ;
4766 if ( isExLogger ( this . log ) ) {
48- this . log . success ( ( this . prefix ? `[ ${ this . prefix } ] ` : '' ) + message , ...args ) ;
67+ this . log . success ( util . format ( `[%s] ${ typeof message === 'string' ? '%s' : '%O' } ` , this . prefix , message ) , ...args ) ;
4968 } else {
50- this . log . info ( ( this . prefix ? `[ ${ this . prefix } ] ` : '' ) + message , ...args ) ;
69+ this . log . info ( util . format ( `[%s] ${ typeof message === 'string' ? '%s' : '%O' } ` , this . prefix , message ) , ...args ) ;
5170 }
5271 }
5372
54- }
73+ private masking ( str : string ) : string {
74+ if ( ! this . mask || typeof str !== 'string' ) {
75+ return str ;
76+ }
77+ const regex_single = / ' ( p a s s w o r d | t o k e n | a c c e s s _ ? t o k e n | a c c e s s K e y | t u y a K e y | a p i _ ? k e y | s e c r e t ) ' \s * : \s * ' [ ^ ' ] * ' / gi;
78+ const regex_double = / " ( p a s s w o r d | t o k e n | a c c e s s _ ? t o k e n | a c c e s s K e y | t u y a K e y | a p i _ ? k e y | s e c r e t ) " \s * : \s * " [ ^ " ] * " / gi;
79+ const spilts = str . split ( / \r \n | \n | \r / ) ;
80+ if ( ! spilts . some ( s => regex_single . test ( s ) ) && ! spilts . some ( s => regex_double . test ( s ) ) ) {
81+ return str ;
82+ }
83+ const results = spilts
84+ . map ( a => a . replace ( regex_single , '\'$1\': \'********\'' ) )
85+ . map ( a => a . replace ( regex_double , '"$1": "********"' ) ) ;
86+ return results . join ( EOL ) ;
87+ }
88+
89+ private maskingValue ( obj : any ) {
90+ if ( ! this . mask ) {
91+ return obj ;
92+ }
93+ const cloneObj = cloneDeep ( obj ) ;
94+ const regex = / ( p a s s w o r d | t o k e n | a c c e s s _ ? t o k e n | a c c e s s K e y | t u y a k e y | a p i _ ? k e y | s e c r e t ) / i;
95+ for ( const key in cloneObj ) {
96+ const value = cloneObj [ key ] ;
97+ if ( typeof value === 'function' ) {
98+ continue ;
99+ }
100+ if ( typeof value === 'string' ) {
101+ if ( ! regex . test ( key ) ) {
102+ continue ;
103+ }
104+ cloneObj [ key ] = '*' . repeat ( value . length ) ;
105+ } else {
106+ cloneObj [ key ] = this . maskingValue ( value ) ;
107+ }
108+ }
109+ return cloneObj ;
110+ }
111+ }
0 commit comments