import { ChildProcessWithoutNullStreams , spawn , SpawnOptionsWithoutStdio } from 'child_process' ; import { logger } from 'flex-dev-utils' ; import { homeDir , testParams } from '../core' ; interface SpawnResult { stdout : string ; stderr : string ; child ? : ChildProcessWithoutNullStreams ; } /**
 * Logs the output in real time
 */ const logInfo = ( data , level ) : void => { data = data . toString ( ) . trim ( ) ; if ( data ) { logger [ level ] ( `[${ new Date ( ) . toUTCString ( ) }] -` , data . toString ( ) . replace ( /-/g , '\\-' ) ) ; } } ; param cmd param args param options export const promisifiedSpawn = async ( cmd , args , options ? ) : Promise < SpawnResult > => { return new Promise ( ( resolve , reject ) => { const defaultOptions = { cwd : homeDir , env : { PATH : `${ testParams . environment . path }:/${ homeDir }/bin` , TWILIO_ACCOUNT_SID : testParams . secrets . api . accountSid , TWILIO_AUTH_TOKEN : testParams . secrets . api . authToken , TWILIO_REGION : testParams . config . region , } , shell : true , } ; const spawnOptions = { ... defaultOptions , ... options } ; logger . info ( `Running spawn command: **${ cmd } ${ args . join ( ' ' ) . replace ( /-/g , '\\-' ) }**` ) ; logger . debug ( `Spawn options are **${ JSON . stringify ( spawnOptions ) }**` ) ; const child = spawn ( cmd , args , spawnOptions ) ; const stdoutArr = [ ] ; const stderrArr = [ ] ; child . on ( 'error' , reject ) ; child . stdin . on ( 'error' , reject ) ; child . stdout . on ( 'error' , reject ) ; child . stderr . setEncoding ( 'utf8' ) ; child . stderr . on ( 'error' , reject ) ; child . stderr . on ( 'data' , ( data ) => { logInfo ( data , 'warning' ) ; if ( typeof data === 'string' ) { stderrArr . push ( Buffer . from ( data , 'utf-8' ) ) ; } else { stderrArr . push ( data ) ; } } ) ; child . stdout . on ( 'data' , ( data ) => { logInfo ( data , 'info' ) ; if ( typeof data === 'string' ) { stdoutArr . push ( Buffer . from ( data , 'utf-8' ) ) ; } else { stdoutArr . push ( data ) ; } } ) ; child . on ( 'close' , ( code ) => { const stdout = Buffer . concat ( stdoutArr ) . toString ( ) ; const stderr = Buffer . concat ( stderrArr ) . toString ( ) ; if ( code === 0 ) { return resolve ( { stdout , stderr } ) ; } return reject ( new Error ( `Command exited with code ${ code } and message ${ stdout }: ${ stderr }` ) ) ; } ) ; if ( options ?. detached ) { return resolve ( { stdout : Buffer . concat ( stdoutArr ) . toString ( ) , stderr : Buffer . concat ( stderrArr ) . toString ( ) , child , } ) ; } } ) ; } ; param result export const logResult = ( result ) : void => { logger . info ( result . stdout . replace ( /-/g , '\\-' ) ) ; if ( result . stderr ) { logger . warning ( result . stderr . replace ( /-/g , '\\-' ) ) ; } } ; param child param os export const killChildProcess = async ( child , os ) : Promise < void > => { if ( ! child ) { throw new Error ( 'Could not kill child process, process does not exist' ) ; } if ( os === 'win32' ) { await promisifiedSpawn ( 'taskkill' , [ '/pid' , `${ child . pid }` , '/f' , '/t' ] ) ; } else { child . kill ( ) ; } } ;