import fs from 'fs' ; import path from 'path' ; import { spawn } from 'child_process' ; import { HOOK_TYPE_BEFORE , HOOK_TYPE_AFTER , REPORT_JSON , REPORT_COMMAND_ERR } from './constants' ; import { getProject , getKeyFormFile , setKeyToFile } from './common/utils' ; const reportProcess = path . join ( __dirname , './report' ) ; class Report { ctx : ReportContext ; cmd ? : string ; args : object ; commandSource ? : string ; lastCommand : string ; project : string ; generatorProject : string ; startTime : number ; costTime : number ; cachePath : string ; cacheData : string ; constructor ( feflowContext , cmd ? , args ? ) { this . ctx = feflowContext ; this . cmd = cmd ; this . args = args ; this . commandSource = '' ; this . lastCommand = '' ; this . generatorProject = '' ; this . startTime = 0 ; this . costTime = 0 ; this . cachePath = path . join ( this . ctx . root , REPORT_JSON ) ; this . cacheData = '' ; this . project = getProject ( this . ctx ) ; this . loadContextLogger ( ) ; } setCommandSource ( commandSource ) { this . commandSource = commandSource ; } init ( cmd ) { this . cmd = cmd ; this . args = this . ctx . args ; if ( this . ctx . hook ) { this . registerHook ( ) ; } if ( this . cacheData && fs . existsSync ( this . cachePath ) ) { fs . writeFileSync ( this . cachePath , '{}' , 'utf-8' ) ; } fs . open ( this . cachePath , 'w+' , ( err ) => { if ( err ) return this . ctx . log . debug ( `${ this . cachePath } 打开失败 => ${ err }` ) ; fs . writeFileSync ( this . cachePath , '{}' , 'utf-8' ) ; } ) ; } report ( cmd , args ? , recall ? ) { if ( ! this . checkBeforeReport ( cmd ) ) return ; const child = spawn ( process . argv [ 0 ] , [ reportProcess ] , { detached : true , stdio : 'ignore' , env : { ... process . env , cmd , args : JSON . stringify ( args ) , commandSource : this . commandSource , lastCommand : this . lastCommand , project : this . project , version : this . ctx . version , cachePath : this . cachePath , costTime : String ( this . costTime ) , recall , } , windowsHide : true , } ) ; child . unref ( ) ; } reportInitResult ( ) { const { cmd } = this ; if ( cmd !== 'init' ) { return ; } this . costTime = Date . now ( ) - this . startTime ; this . generatorProject = getProject ( this . ctx , true ) ; this . report ( this . cmd , this . args , true ) ; } reportCommandError ( err ) { if ( ! err ) { return ; } setKeyToFile ( this . cachePath , 'errMsg' , err . message ) ; if ( getKeyFormFile ( this . cachePath , 'reCallId' ) && ! getKeyFormFile ( this . cachePath , 'hasRecalled' ) ) { this . report ( this . cmd , this . args , true ) ; } else { this . report ( REPORT_COMMAND_ERR ) ; } } private registerHook ( ) { this . ctx . hook . on ( HOOK_TYPE_BEFORE , this . reportOnHookBefore ) ; this . ctx . hook . on ( HOOK_TYPE_AFTER , this . reportOnHookAfter ) ; } private loadContextLogger ( ) { this . ctx . log = this . ctx . log || this . ctx . logger ; this . ctx . log = this . ctx . log ? this . ctx . log : { info : console . log , debug : console . log } ; } private reportOnHookBefore = ( ) : any => { const { cmd , args } = this ; let commandWithoutVersion ; try { commandWithoutVersion = cmd ?. split ( '@' ) [ 0 ] ; } catch ( error ) { this . ctx . log . debug ( `reportOnHookBefore: command parse error: ${ error }` ) ; commandWithoutVersion = '' ; } const store = this . ctx . commander ?. store [ commandWithoutVersion ] || this . ctx . commander ?. store [ cmd ] || { } ; this . commandSource = store ?. pluginName || this . commandSource ; if ( ! this . commandSource && typeof store . options === 'string' ) { this . commandSource = store . options ; } this . ctx . log . debug ( 'HOOK_TYPE_BEFORE' ) ; this . startTime = Date . now ( ) ; this . report ( cmd , args ) ; } ; private reportOnHookAfter = ( ) : any => { this . ctx . log . debug ( 'HOOK_TYPE_AFTER' ) ; this . costTime = Date . now ( ) - this . startTime ; this . report ( this . cmd , this . args , true ) ; } ; private checkBeforeReport = ( cmd ) : any => { if ( this . cmd && this . cmd !== cmd ) { this . lastCommand = this . cmd ; } this . cmd = cmd ; return ! ! cmd ; } ; } module . exports = Report ;