author xiaojue
 *  fileoverview internal import KoaLogger = require ( 'daruk-logger' ) ; import { EventEmitter } from 'events' ; import { injectable } from 'inversify' ; import { buildProviderModule } from 'inversify-binding-decorators' ; internal import Koa = require ( 'koa' ) ; import { ListenOptions } from 'net' ; internal import deepAssign = require ( 'object-assign-deep' ) ; import { dirname , join } from 'path' ; internal import recursive = require ( 'recursive-readdir' ) ; import mockHttp from '../mock/http_server' ; import { PluginClass , Server } from '../typings/daruk' ; import { Options , PartialOptions } from '../typings/daruk_options' ; import { debugLog , isJsTsFile , JsTsReg } from '../utils' ; import getDefaultOptions from './daruk_default_options' ; import { darukContainer } from './inversify.config' ; import { TYPES } from './types' ; class Daruk extends EventEmitter { [ key ] : any ; public name ! : string ; public app : Koa ; public httpServer ! : Server ; public logger ! : KoaLogger . logger ; public options ! : Options ; public constructor ( ) { super ( ) ; this . app = new Koa ( ) ; const self = this ; this . app . on ( 'error' , function handleKoaError ( err ) { self . prettyLog ( '[koa error] ' + ( err . stack || err . message ) , { level : 'error' } ) ; } ) ; } public _initOptions ( options = { } ) { const rootPath = options . rootPath || dirname ( require ?. main ?. filename as string ) ; const defaultOptions = getDefaultOptions ( rootPath , options . name , options . debug ) ; const customLogger = options . customLogger ; delete options . customLogger ; this . options = deepAssign ( { } , defaultOptions , options ) ; this . options . customLogger = options . customLogger = customLogger ; this . logger = customLogger || new KoaLogger . logger ( this . options . loggerOptions ) ; this . name = this . options . name ; } public async loadFile ( path ) { return this . _loadFile ( join ( this . options . rootPath , path ) ) ; } public async binding ( ) { await this . _loadFile ( join ( __dirname , '../plugins' ) ) ; await this . _loadFile ( join ( __dirname , '../built_in' ) ) ; const plugins = darukContainer . getAll < PluginClass > ( TYPES . PLUGINCLASS ) ; for ( let plugin of plugins ) { let retValue = await plugin . initPlugin ( this ) ; if ( ! darukContainer . isBoundNamed ( TYPES . PluginInstance , plugin . constructor . name ) ) { darukContainer . bind ( TYPES . PluginInstance ) . toConstantValue ( retValue ) . whenTargetNamed ( plugin . constructor . name ) ; } } darukContainer . load ( buildProviderModule ( ) ) ; this . emit ( 'init' , darukContainer ) ; } desc param { Object return public mockContext ( req ? ) { const { request , response } = mockHttp ( req ) ; const ctx = this . app . createContext ( request , response ) ; return ctx ; } desc public listen ( port ? , hostname ? , backlog ? , listeningListener ? ) ; public listen ( port , hostname ? , listeningListener ? ) ; public listen ( port , backlog ? , listeningListener ? ) ; public listen ( port , listeningListener ? ) ; public listen ( path , backlog ? , listeningListener ? ) ; public listen ( path , listeningListener ? ) ; public listen ( handle , backlog ? , listeningListener ? ) ; public listen ( handle , listeningListener ? ) ; public listen ( options , listeningListener ? ) ; public listen ( ... args ) { this . httpServer = this . app . listen . apply ( this . app , args ) ; this . emit ( 'serverReady' , this . httpServer ) ; return this . httpServer ; } desc public prettyLog ( msg , ext ? ) { const { type , level , init } = { type : '' , level : 'info' , init : false , ... ext } ; const prefixInfo = [ init ? '[init] ' : '' , type ? `[${ type }] ` : ' ' ] . join ( '' ) ; if ( this . options . debug ) { debugLog ( `[${ new Date ( ) . toLocaleString ( ) }] [debug] ${ prefixInfo }${ msg }` , level ) ; } else { this . logger [ level ] ( prefixInfo + msg ) ; } } private async _loadFile ( path ) { return recursive ( path ) . then ( ( files ) => { return files . filter ( ( file ) => isJsTsFile ( file ) ) . map ( ( file ) => file . replace ( JsTsReg , '' ) ) . forEach ( ( path ) => { require ( path ) ; } ) ; } ) ; } } export default Daruk ;