@type-r/mixture
Version:
React-style mixins, Backbone-style events, logging router.
93 lines (73 loc) • 3.27 kB
text/typescript
import { Messenger } from './events'
import { define } from './mixins';
export type LogLevel = 'error' | 'warn' | 'debug' | 'info' | 'log';
export type LoggerEventHandler = ( topic : string, msg : string, props : object ) => void;
export const isProduction = typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'production',
logEvents : LogLevel[] = isProduction ?
[ 'error', 'info' ] :
[ 'error', 'warn', 'debug', 'info', 'log' ];
export class Logger extends Messenger {
counter : { [ level in LogLevel ]? : number } = {}
// Log events of the given log level to the console, optionally filtered by topic
logToConsole( level : LogLevel, filter? : RegExp ) : this {
return this.on( level, ( topic, msg, props ) => {
if( !filter || filter.test( topic ) ){
const args = [ `[${topic}] ${msg}` ];
for( let name in props ){
args.push( `\n\t${name}:`, toString( props[ name ] ) );
}
console[ level ].apply( console, args );
}
});
}
// Fire exception on the events of the given log level, optionally filtered by topic
throwOn( level : LogLevel, filter? : RegExp ) : this {
return this.on( level, ( topic, msg, props ) => {
if( !filter || filter.test( topic ) ){
throw new Error( `[${topic}] ${msg}` );
}
});
}
// Count log events of the given level, optionally filtered by topic
count( level : LogLevel, filter? : RegExp ) : this {
return this.on( level, ( topic, msg, props ) => {
if( !filter || filter.test( topic ) ){
this.counter[ level ] = ( this.counter[ level ] || 0 ) + 1;
}
});
}
trigger : ( level : LogLevel, topic : string, message : string, props? : object ) => this;
off : ( event? : LogLevel ) => this;
on( handlers : { [ name in LogLevel ] : LoggerEventHandler } ) : this;
on( handlers : LogLevel, handler : LoggerEventHandler ) : this;
on( handlers : 'all', handler : ( level : LogLevel, topic : string, msg : string, props : object ) => void ) : this;
on( a : any, b? : any ){
return super.on( a, b );
}
}
/**
* Convert objects to the plain text friendly format.
* primitives as in JSON.
*/
let toString = typeof window === 'undefined' ?
something => {
if( something && typeof something === 'object' ){
// Support custom object wrappers...
const value = something.__inner_state__ || something,
isArray = Array.isArray( value );
const body = isArray ? `[ length = ${ value.length } ]` : `{ ${ Object.keys( value ).join( ', ' )} }`;
return something.constructor.name + ' ' + body;
}
return JSON.stringify( something );
}
: x => x;
export const logger = new Logger();
if( typeof console !== 'undefined' ) {
for( let event of logEvents ){
logger.logToConsole( event );
}
}
export const throwingLogger = new Logger();
throwingLogger.throwOn( 'error' ).throwOn( 'warn' );
export const log : typeof logger.trigger = logger.trigger.bind( logger );