import * as which from 'which' ; import * as execa from 'execa' ; import chalk from 'chalk' ; export abstract class NodeManager { constructor ( private cwd , private manager ) { } installAll ( cwd ? , stream ? ) { return this . _exec ( 'install' , [ ] , cwd ) , stream ; } installAllInBackground ( cwd ? ) { return this . _execInBackground ( 'install' , [ ] , cwd ) ; } protected async _exec ( command , params ? , cwd ? , stream ? ) { try { const managerExecutable = await this . _getManagerExecutable ( this . manager ) ; if ( stream ) { stream ( `$ ${ this . manager } ${ command } ${ params . join ( ' ' ) }` ) ; } const proc = execa ( managerExecutable , [ command , ... params ] , { cwd : cwd ? cwd : this . cwd } ) ; proc . stdout . on ( 'data' , d => { if ( stream ) { stream ( d . toString ( ) ) ; } } ) ; proc . stderr . on ( 'data' , ( d ) => { if ( stream ) { stream ( this . _colorizeErrorOutput ( d . toString ( ) ) , true ) ; } } ) ; return proc ; } catch ( err ) { return Promise . reject ( err ) ; } } protected async _execInBackground ( command , params ? , cwd ? ) { try { const managerExecutable = await this . _getManagerExecutable ( this . manager ) ; const proc = execa ( managerExecutable , [ command , ... params ] , { cwd : cwd ? cwd : this . cwd } ) ; return { proc } ; } catch ( err ) { return Promise . reject ( err ) ; } } protected _getManagerExecutable ( manager ) { return new Promise ( ( resolve , reject ) => { which ( manager , ( err , yarnPath ) => { if ( err && ! yarnPath ) { reject ( err ) ; } else { resolve ( yarnPath ) ; } } ) ; } ) ; } abstract getExecutable ( ) ; abstract installDev ( packageName , cwd , stream ? ) ; abstract install ( packageName , cwd , stream ? ) ; abstract uninstall ( packageName , cwd , stream ? ) ; abstract upgrade ( packageName , cwd , stream ? ) ; abstract runScript ( scriptName , cwd , stream ? ) ; abstract runScriptInBackground ( scriptName , cwd ? ) ; private _colorizeErrorOutput ( stderr ) { return stderr . includes ( this . manager === 'yarn' ? 'err' : 'ERR' ) ? chalk . red ( stderr ) : chalk . yellow ( stderr ) ; } }