import fs from 'fs' ; import { Readable , Transform , TransformCallback } from 'stream' ; import * as messages from '@cucumber/messages' ; export default class CucumberHtmlStream extends Transform { private template : string | null = null ; private preMessageWritten = false ; private postMessageWritten = false ; private firstMessageWritten = false ; param cssPath param jsPath constructor ( private readonly cssPath , private readonly jsPath ) { super ( { objectMode : true } ) ; } public _transform ( envelope , encoding , callback ) { if ( this . postMessageWritten ) { return callback ( new Error ( 'Stream closed' ) ) ; } this . writePreMessageUnlessAlreadyWritten ( ( err ) => { if ( err ) return callback ( err ) ; this . writeMessage ( envelope ) ; callback ( ) ; } ) ; } public _flush ( callback ) { this . writePostMessage ( callback ) ; } private writePreMessageUnlessAlreadyWritten ( callback ) { if ( this . preMessageWritten ) { return callback ( ) ; } this . preMessageWritten = true ; this . writeTemplateBetween ( null , '{{css}}' , ( err ) => { if ( err ) return callback ( err ) ; this . writeFile ( this . cssPath , ( err ) => { if ( err ) return callback ( err ) ; this . writeTemplateBetween ( '{{css}}' , '{{messages}}' , ( err ) => { if ( err ) return callback ( err ) ; callback ( ) ; } ) ; } ) ; } ) ; } private writePostMessage ( callback ) { this . writePreMessageUnlessAlreadyWritten ( ( err ) => { if ( err ) return callback ( err ) ; this . writeTemplateBetween ( '{{messages}}' , '{{script}}' , ( err ) => { if ( err ) return callback ( err ) ; this . writeFile ( this . jsPath , ( err ) => { if ( err ) return callback ( err ) ; this . writeTemplateBetween ( '{{script}}' , null , callback ) ; } ) ; } ) ; } ) ; } private writeFile ( path , callback ) { const cssStream = fs . createReadStream ( path , { encoding : 'utf-8' } ) ; cssStream . on ( 'data' , ( chunk ) => this . push ( chunk ) ) ; cssStream . on ( 'error' , ( err ) => callback ( err ) ) ; cssStream . on ( 'end' , callback ) ; } private writeTemplateBetween ( begin , end , callback ) { this . readTemplate ( ( err , template ) => { if ( err ) return callback ( err ) ; const beginIndex = begin == null ? 0 : template . indexOf ( begin ) + begin . length ; const endIndex = end == null ? template . length : template . indexOf ( end ) ; this . push ( template . substring ( beginIndex , endIndex ) ) ; callback ( ) ; } ) ; } private readTemplate ( callback ) { if ( this . template !== null ) { return callback ( null , this . template ) ; } fs . readFile ( __dirname + '/index.mustache.html' , { encoding : 'utf-8' } , ( err , template ) => { if ( err ) return callback ( err ) ; this . template = template ; return callback ( null , template ) ; } ) ; } private writeMessage ( envelope ) { if ( ! this . firstMessageWritten ) { this . firstMessageWritten = true ; } else { this . push ( ',' ) ; } this . push ( JSON . stringify ( envelope ) ) ; } }