import readLine from 'readline' ; import { Readable } from 'stream' ; export class BufferLines extends Readable { private set = new Set < string > ( ) ; private boundary : string | null = null ; private readableText : boolean = false ; private paused : boolean = false ; private bufferSize : number ; constructor ( { input , bufferSize } ) { super ( { encoding : 'utf-8' } ) ; if ( bufferSize <= 0 ) { throw new RangeError ( 'bufferSize must be greater than zero' ) ; } this . bufferSize = bufferSize ; const readline = readLine . createInterface ( { input , } ) ; readline . on ( 'line' , ( line ) => { if ( this . boundary == null && line . startsWith ( '--' ) ) { this . boundary = `${ line }--` ; } else if ( this . boundary != null && ! this . readableText && line . trim ( ) !== '' ) { if ( line . startsWith ( 'Content-Disposition' ) ) { const fileNameMatch = RegExp ( 'filename="(?<fileName>.+)"' ) ; const matches = fileNameMatch . exec ( line ) ; if ( matches ?. groups ?. fileName != null ) { this . emit ( 'fileName' , matches . groups . fileName ) ; } } } else if ( this . boundary != null && ! this . readableText && line . trim ( ) === '' ) { this . readableText = true ; } else if ( this . readableText && line . trim ( ) === '' ) { } else if ( this . boundary != null && this . readableText && line === this . boundary ) { this . boundary = null ; this . readableText = false ; } else { this . push ( line ) ; } } ) ; readline . on ( 'close' , ( ) => { this . push ( null ) ; } ) ; } public _read ( ) { } public pause ( ) { this . paused = true ; return this ; } public resume ( ) { this . paused = false ; return this ; } private emptyBuffer ( ) { const arrayFromSet = Array . from ( this . set ) ; if ( arrayFromSet . length === 0 ) { this . emit ( 'lines' , [ ] ) ; } else { while ( arrayFromSet . length ) { const spliced = arrayFromSet . splice ( 0 , this . bufferSize ) ; this . emit ( 'lines' , spliced ) ; } } this . set . clear ( ) ; } public push ( line ) { if ( line != null ) { this . set . add ( line ) ; if ( this . paused ) { return false ; } else { if ( this . set . size > this . bufferSize ) { this . emptyBuffer ( ) ; } return true ; } } else { if ( this . paused ) { setTimeout ( ( ) => { this . push ( line ) ; } , 10 ) ; return false ; } else { this . emptyBuffer ( ) ; this . emit ( 'close' ) ; return true ; } } } }