feat: Create function to wrap streams to not lose errors

This commit is contained in:
Joachim Van Herwegen
2020-11-17 11:44:48 +01:00
parent 9c78c4f9ad
commit 1a30b51461
4 changed files with 221 additions and 4 deletions

View File

@@ -1,6 +1,9 @@
import type { Readable, Writable } from 'stream';
import type { Writable, ReadableOptions } from 'stream';
import { Readable } from 'stream';
import arrayifyStream from 'arrayify-stream';
import { getLoggerFor } from '../logging/LogUtil';
import type { Guarded } from './GuardedStream';
import { guardStream } from './GuardedStream';
const logger = getLoggerFor('StreamUtil');
@@ -15,6 +18,7 @@ export const readableToString = async(stream: Readable): Promise<string> => (awa
/**
* Pipes one stream into another and emits errors of the first stream with the second.
* In case of an error in the first stream the second one will be destroyed with the given error.
* This will also make the stream {@link Guarded}.
* @param readable - Initial readable stream.
* @param destination - The destination for writing data.
* @param mapError - Optional function that takes the error and converts it to a new error.
@@ -22,7 +26,7 @@ export const readableToString = async(stream: Readable): Promise<string> => (awa
* @returns The destination stream.
*/
export const pipeSafely = <T extends Writable>(readable: NodeJS.ReadableStream, destination: T,
mapError?: (error: Error) => Error): T => {
mapError?: (error: Error) => Error): Guarded<T> => {
// Not using `stream.pipeline` since the result there only emits an error event if the last stream has the error
readable.pipe(destination);
readable.on('error', (error): void => {
@@ -34,5 +38,13 @@ export const pipeSafely = <T extends Writable>(readable: NodeJS.ReadableStream,
// in order to prevent memory leaks."
destination.destroy(mapError ? mapError(error) : error);
});
return destination;
return guardStream(destination);
};
/**
* Converts an iterable to a stream and applies an error guard so that it is {@link Guarded}.
* @param iterable - Data to stream.
* @param options - Options to pass to the Readable constructor. See {@link Readable.from}.
*/
export const guardedStreamFrom = (iterable: Iterable<any>, options?: ReadableOptions): Guarded<Readable> =>
guardStream(Readable.from(iterable, options));