import { _ } from 'streamline-runtime' ; import { Reader } from '../reader' ; import { Writer } from '../writer' ; import * as generic from './generic' ; import { parser as linesParser } from '../transforms/lines' ; import * as node from './node' ; import { stringify } from '../mappers/convert' ; import { ChildProcess } from 'child_process' ; export interface ReaderOptions { acceptCode ? : ( code : number ) => boolean ; encoding ? : string ; dataHandler ? : ( reader : Reader < string | Buffer > ) => Reader < string | Buffer > ; errorHandler ? : ( reader : Reader < string | Buffer > ) => Reader < string | Buffer > ; errorPrefix ? : string ; errorThrow ? : boolean ; } export function reader ( proc , options ? ) { var opts = options || { } ; var err , closeCb , closed ; proc . on ( 'close' , ( ec ) => { closed = true ; if ( ec === - 1 ) { proc . stdout . emit ( 'end' ) ; proc . stderr . emit ( 'end' ) ; } if ( ec && ! ( opts . acceptCode && opts . acceptCode ( ec ) ) ) { err = new Error ( "process exited with code:" + ec ) ; err . errno = ec ; var anyErr = err ; anyErr . code = ec ; } if ( closeCb ) closeCb ( err ) ; closeCb = null ; } ) ; proc . on ( 'error' , ( e ) => { err = err || e ; } ) ; var stdout = node . reader ( proc . stdout , opts ) ; var stderr = node . reader ( proc . stderr , opts ) ; const stops = [ stdout . stop . bind ( stdout ) , stderr . stop . bind ( stderr ) ] ; stdout . stop = stderr . stop = ( _ ) => { } ; function stopStreams ( _ , arg ? ) { stops . forEach_ ( _ , ( _ , stop ) => { stop ( _ , arg ) ; } ) ; } if ( opts . encoding !== 'buffer' ) { stdout = stdout . map ( stringify ( ) ) . transform ( linesParser ( ) ) ; stderr = stderr . map ( stringify ( ) ) . transform ( linesParser ( ) ) ; } if ( opts . dataHandler ) stdout = opts . dataHandler ( stdout ) ; if ( opts . errorHandler ) stderr = opts . errorHandler ( stderr ) ; if ( opts . errorPrefix || opts . errorThrow ) stderr = stderr . map ( function ( _ , data ) { if ( opts . errorThrow ) throw new Error ( ( opts . errorPrefix || "" ) + data ) ; return opts . errorPrefix + data ; } ) ; const rd = stdout . join ( stderr ) ; return generic . reader ( function read ( _ ) { if ( err ) throw err ; const data = rd . read ( _ ) ; if ( data !== undefined ) return data ; if ( closed ) { if ( err ) throw err ; } else { _ . cast ( function ( cb ) { closeCb = cb ; } ) ( _ ) ; stopStreams ( _ ) ; } return undefined ; } , stopStreams ) ; } export function writer ( proc , options ) { return node . writer ( proc . stdin , options ) ; }