ts-stream
Version:
Type-safe object streams with seamless support for backpressure, ending, and error handling
986 lines (985 loc) • 45.8 kB
TypeScript
/**
* Promise-based object stream with seamless support for back-pressure and error
* handling, written in Typescript.
*
* Copyright (C) 2015 Martin Poelstra
* License: MIT
*/
import BaseError from "./BaseError";
import { Transform } from "./Transform";
/**
* Required methods for both readable and writable parts of a stream.
*/
export interface Common<T> {
/**
* Obtain a promise that resolves when all parts of a stream chain have
* completely ended.
*
* Specifically:
* - `end()` has been called (possibly with an Error),
* - `ender` callback has run and its returned promise resolved,
* - `end()`'s result parameter (if any) has been resolved.
*
* @return Promise resolved when stream chain has completely ended
*/
result(): Promise<void>;
/**
* Signal that the stream is aborted: it will no longer read incoming
* elements and will no longer write elements except in the course of
* processing any pending asynchronous reader callbacks (i.e. unresolved
* Promises returned by `forEach()` or other stream iterators). Does not
* end the stream.
*
* An upstream source can handle this `abort()` by catching the exception
* from its own `aborted()` method--for example, to cancel pending fetch
* operations, or close a continuous data stream.
*
* If the stream's `forEach()` function provided an `aborter` callback and
* the stream is not yet ended, `aborter` will be called with the abort reason.
* This can be used to cancel any remaining operations inside the asynchronous
* reader callback.
*
* Once the last pending callback is resolved, any pending and future `write()`s
* to this stream will be rejected with the error provided to `abort()`.
*
* It is still necessary to explicitly `end()` the stream, to ensure that any
* resources can be cleaned up correctly both on the reader and writer side.
* The stream's `ender` callback will be called with the abort error (i.e. any
* error passed to `end()` is ignored.)
*
* The abort is ignored if the stream is already aborted.
*
* It's possible to abort an ended stream. This can be used to 'bubble' an
* abort signal to other parts in a chain of streams which may not have ended
* yet. It will not change the end-state of this part of the stream though.
*
* @param reason Optional Error value to signal a reason for the abort
*/
abort(reason?: Error): void;
/**
* Obtain promise that resolves to a rejection when `abort()` is called.
*
* Useful to pass abort to upstream sources.
*
* Note: this promise either stays pending, or is rejected. It is never
* fulfilled.
*
* @return Promise that is rejected with abort error when stream is aborted
*/
aborted(): Promise<never>;
/**
* Obtain promise that resolves to a rejection when `abort()` is called.
*
* Useful to pass abort to upstream sources.
*
* Note: this promise either stays pending, or is rejected. It is never
* fulfilled.
*
* @return Promise that is rejected with abort error when stream is aborted
*/
aborted(aborter: (reason: Error) => void): void;
}
/**
* Required methods for the readable part of a stream.
*/
export interface Readable<T> extends Common<T> {
/**
* Read all values from stream, optionally waiting for explicit stream end.
*
* `reader` is called for every written value.
*
* `ender` is called once, when the writer `end()`s the stream, either with
* or without an error.
*
* `reader` and `ender` callbacks can return a promise to indicate when the
* value or end-of-stream condition has been completely processed. This
* ensures that a fast writer can never overload a slow reader, and is
* called 'backpressure'.
*
* The `reader` callback is never called while its previously returned
* promise is still pending, and the `ender` callback is likewise only
* called after all reads have completed.
*
* The corresponding `write()` or `end()` operation is blocked until the
* value returned from the reader or ender callback is resolved. If the
* callback throws an error or the returned promise resolves to a rejection,
* the `write()` or `end()` will be rejected with it.
*
* All callbacks are always called asynchronously (i.e. some time after
* `forEach()`, `write()`, `end()` or `abort()` returns), and their `this`
* argument will be undefined.
*
* `aborter` is called once if the stream is aborted and has not ended yet.
* (I.e. it will be called if e.g. `ender`'s returned promise is still
* pending, to allow early termination, but it will no longer be called
* if its promise has resolved).
*
* The `aborter` callback can be called while a reader callback's promise is
* still pending, and should try to let `reader` or `ender` finish as fast
* as possible.
*
* Note that even when a stream is aborted, it still needs to be `end()`'ed
* correctly.
*
* If no `ender` is given, a default end handler is installed that directly
* acknowledges the end-of-stream, also in case of an error. Note that that
* error will still be returned from `forEach()`.
*
* If no `aborter` is given, an abort is ignored (but will still cause
* further writes to fail, and it will be reflected in the returned promise).
*
* It is an error to call `forEach()` multiple times, and it is not possible
* to 'detach' already attached callbacks. Reason is that the exact behaviour
* of such actions (e.g. block or simply ignore further writes) is application
* dependent, and should be implemented as a transform instead.
*
* The return value of `forEach()` is `result()`, a promise that resolves
* when all parts in the stream(-chain) have completely finished.
*
* @param reader Callback called with every written value
* @param ender Optional callback called when stream is ended
* @param aborter Optional callback called when stream is aborted
* @return Promise for completely finished stream, i.e. same promise as `result()`
*/
forEach(reader: (value: T) => void | PromiseLike<void>, ender?: (error?: Error) => void | PromiseLike<void>, aborter?: (error: Error) => void): Promise<void>;
}
/**
* Required methods for the writable part of a stream.
*/
export interface Writable<T> extends Common<T> {
/**
* Write value (or promise for value) to stream.
*
* Writer is blocked until the value is read by the read handler passed to
* `forEach()`, and the value returned by that read handler is resolved.
*
* It is an error to write an `undefined` value (as this is a common
* programming error). Writing a promise for a void is currently allowed,
* but discouraged.
*
* The promise returned by `write()` will be rejected with the same reason if:
* - the written value is a PromiseLike that resolves to a rejection
* - the read handler throws an error or returns a rejected promise
* It is still possible to write another value after that, or e.g. `end()`
* the stream with or without an error.
*
* @param value Value to write, or promise for it
* @return Void-promise that resolves when value was processed by reader
*/
write(value: T | PromiseLike<T>): Promise<void>;
/**
* End the stream, optionally passing an error.
*
* Already pending writes will be processed by the reader passed to
* `forEach()` before passing the end-of-stream to its end handler.
*
* The returned promise will resolve after the end handler has finished
* processing. It is rejected if the end handler throws an error or returns
* a rejected promise.
*
* All calls to `write()` or `end()` after the first `end()` will be
* rejected with a `WriteAfterEndError`.
*
* By default, this stream's `result()` will be resolved when `end()`
* resolves, or rejected with the error if `end()` is called with an error.
* It is possible to let this stream's `result()` 'wait' until any upstream
* streams have completed by e.g. passing that upstream's `result()` as the
* second argument to `end()`.
*
* Note: even if a stream is aborted, it is still necessary to call `end()`
* to allow any resources to correctly be cleaned up.
*
* @param error Optional Error to pass to `forEach()` end handler
* @param result Optional promise that determines final value of `result()`
* @return Void-promise that resolves when `ended`-handler has processed the
* end-of-stream
*/
end(error?: Error, result?: PromiseLike<void>): Promise<void>;
}
export interface CommonStream<T> {
/**
* Determine whether `end()` has been called on the stream, but the stream
* is still processing it.
*
* @return true when `end()` was called but not acknowledged yet, false
* otherwise
*/
isEnding(): boolean;
/**
* Determine whether stream has completely ended (i.e. end handler has been
* called and its return PromiseLike, if any, is resolved).
*
* @return true when stream has ended, false otherwise
*/
isEnded(): boolean;
/**
* Determine whether `end()` has been called on the stream.
*
* @return true when `end()` was called
*/
isEndingOrEnded(): boolean;
/**
* Determine whether `forEach()` callback(s) are currently attached to the
* stream.
*
* @return true when `forEach()` has been called on this stream
*/
hasReader(): boolean;
}
/**
* Readable part of a generic Stream, which contains handy helpers such as
* .map() in addition to the basic requirements of a Readable interface.
*/
export interface ReadableStream<T> extends Readable<T>, CommonStream<T> {
/**
* Run all input values through a mapping callback, which must produce a new
* value (or promise for a value), similar to e.g. `Array`'s `map()`.
*
* Stream end in the input stream (normal or with error) will be passed to
* the output stream, after awaiting the result of the optional ender.
*
* Any error (thrown or rejection) in mapper or ender is returned to the
* input stream.
*
* @param mapper Callback which receives each value from this stream, and
* must produce a new value (or promise for a value)
* @param ender Called when stream is ending, result is waited for before
* passing on `end()`
* @param aborter Called when stream is aborted
* @return New stream with mapped values
*/
map<R>(mapper: (value: T) => R | PromiseLike<R>, ender?: (error?: Error) => void | PromiseLike<void>, aborter?: (error: Error) => void): ReadableStream<R>;
/**
* Run all input values through a filtering callback. If the filter callback
* returns a truthy value (or a promise for a truthy value), the input value
* is written to the output stream, otherwise it is ignored.
* Similar to e.g. `Array`'s `filter()`.
*
* Stream end in the input stream (normal or with error) will be passed to
* the output stream, after awaiting the result of the optional ender.
*
* Any error (thrown or rejection) in mapper or ender is returned to the
* input stream.
*
* @param filterer Callback which receives each value from this stream,
* input value is written to output if callback returns a
* (promise for) a truthy value.
* @param ender Called when stream is ending, result is waited for before
* passing on `end()`
* @param aborter Called when stream is aborted
* @return New stream with filtered values.
*/
filter(filterer: (value: T) => boolean | PromiseLike<boolean>, ender?: (error?: Error) => void | PromiseLike<void>, aborter?: (error: Error) => void): ReadableStream<T>;
/**
* Reduce the stream into a single value by calling a reducer callback for
* each value in the stream. Similar to `Array#reduce()`.
*
* The output of the previous call to `reducer` (aka `accumulator`) is given
* as the first argument of the next call. For the first call, either the
* `initial` value to `reduce()` is passed, or the first value of the stream
* is used (and `current` will be the second value).
*
* The result of `reduce()` is a promise for the last value returned by
* `reducer` (or the initial value, if there were no calls to `reducer`).
* If no initial value could be determined, the result is rejected with a
* TypeError.
* If the stream is ended with an error, the result is rejected with that
* error.
*
* It is possible for `reducer` to return a promise for its result.
*
* If the `reducer` throws an error or returns a rejected promise, the
* originating `write()` will fail with that error.
*
* Examples:
* s.reduce((acc, val) => acc + val); // sums all values
* s.reduce((acc, val) => { acc.push(val); return acc; }, []); // toArray()
*
* @param reducer Callback called for each value in the stream, with
* accumulator, current value, index of current value, and
* this stream.
* @param initial Optional initial value for accumulator. If no initial
* value is given, first value of stream is used.
* @return Promise for final accumulator.
*/
reduce(reducer: (accumulator: T, current: T, index: number, stream: ReadableStream<T>) => T | PromiseLike<T>, initial?: T): Promise<T>;
/**
* Reduce the stream into a single value by calling a reducer callback for
* each value in the stream. Similar to `Array#reduce()`.
*
* The output of the previous call to `reducer` (aka `accumulator`) is given
* as the first argument of the next call. For the first call, either the
* `initial` value to `reduce()` is passed, or the first value of the stream
* is used (and `current` will be the second value).
*
* The result of `reduce()` is a promise for the last value returned by
* `reducer` (or the initial value, if there were no calls to `reducer`).
* If no initial value could be determined, the result is rejected with a
* TypeError.
* If the stream is ended with an error, the result is rejected with that
* error.
*
* It is possible for `reducer` to return a promise for its result.
*
* If the `reducer` throws an error or returns a rejected promise, the
* originating `write()` will fail with that error.
*
* Examples:
* s.reduce((acc, val) => acc + val); // sums all values
* s.reduce((acc, val) => { acc.push(val); return acc; }, []); // toArray()
*
* @param reducer Callback called for each value in the stream, with
* accumulator, current value, index of current value, and
* this stream.
* @param initial Optional initial value for accumulator. If no initial
* value is given, first value of stream is used.
* @return Promise for final accumulator.
*/
reduce<R>(reducer: (accumulator: R, current: T, index: number, stream: ReadableStream<T>) => PromiseLike<R>, initial: R): Promise<R>;
/**
* Reduce the stream into a single value by calling a reducer callback for
* each value in the stream. Similar to `Array#reduce()`.
*
* The output of the previous call to `reducer` (aka `accumulator`) is given
* as the first argument of the next call. For the first call, either the
* `initial` value to `reduce()` is passed, or the first value of the stream
* is used (and `current` will be the second value).
*
* The result of `reduce()` is a promise for the last value returned by
* `reducer` (or the initial value, if there were no calls to `reducer`).
* If no initial value could be determined, the result is rejected with a
* TypeError.
* If the stream is ended with an error, the result is rejected with that
* error.
*
* It is possible for `reducer` to return a promise for its result.
*
* If the `reducer` throws an error or returns a rejected promise, the
* originating `write()` will fail with that error.
*
* Examples:
* s.reduce((acc, val) => acc + val); // sums all values
* s.reduce((acc, val) => { acc.push(val); return acc; }, []); // toArray()
*
* @param reducer Callback called for each value in the stream, with
* accumulator, current value, index of current value, and
* this stream.
* @param initial Optional initial value for accumulator. If no initial
* value is given, first value of stream is used.
* @return Promise for final accumulator.
*/
reduce<R>(reducer: (accumulator: R, current: T, index: number, stream: ReadableStream<T>) => R, initial: R): Promise<R>;
/**
* Read all stream values into an array.
*
* Returns a promise that resolves to that array if the stream ends
* normally, or to the error if the stream is ended with an error.
*
* @return Promise for an array of all stream values
*/
toArray(): Promise<T[]>;
/**
* Read all values and end-of-stream from this stream, writing them to
* `writable`.
*
* @param writable Destination stream
* @return The stream passed in, for easy chaining
*/
pipe<R extends Writable<T>>(writable: R): R;
/**
* Return a new stream with the results of running the given
* transform.
*
* @param transformer Function that receives this stream and result stream
* as inputs.
* @return Readable stream with the transformed results
*/
transform<R>(transformer: Transform<T, R>): ReadableStream<R>;
}
/**
* Writable part of a generic Stream, which contains handy helpers such as
* .mappedBy() in addition to the basic requirements of a Writable interface.
*/
export interface WritableStream<T> extends Writable<T>, CommonStream<T> {
/**
* Repeatedly call `writer` and write its returned value (or promise for it)
* to the stream.
* The stream is ended when `writer` returns `undefined` (or a promise that
* resolves to `undefined`).
*
* `writer` is only called again when its previously returned value has been
* processed by the stream.
*
* If writing of a value fails (either by the `writer` throwing an error,
* returning a rejection, or the write call failing), the stream is aborted
* and ended with that error.
*
* `ender` is always called once, just before the stream is ended. I.e.
* after `writer` returned (a promise for) `undefined` or the stream is
* aborted.
* It can be used to e.g. close a resource such as a database.
* Note: `ender` will only be called when `writer`'s promise (if any) has
* resolved.
*
* `aborter` is called once iff the stream is aborted. It can be called
* while e.g. a promise returned from the writer or ender is still pending,
* and can be used to make sure that that promise is resolved/rejected
* sooner.
* Note: the aborter should be considered a 'signal to abort', but cleanup
* of resources should be done in the `ender` (i.e. it cannot return a
* promise).
* It can be called (long) after `ender` has been called, because a stream
* can be aborted even after it is already ended, which is useful if this
* stream element is part of a larger chain of streams.
* An aborter must never throw an error.
*
* @param writer Called when the next value can be written to the stream,
* should return (a promise for) a value to be written,
* or `undefined` (or void promise) to end the stream.
* Will always be called asynchronously.
* @param ender Optional callback called once after `writer` indicated
* end-of-stream, or when the stream is aborted (and
* previously written value resolved/rejected). It's called
* without an argument if stream was not aborted (yet), and
* the abort reason if it was aborted (`aborter` will have
* been called, too). Will always be called asynchronously.
* @param aborter Optional callback called once when stream is aborted.
* Receives abort reason as its argument. Should be used
* to prematurely terminate any pending promises of
* `writer` or `ender`. Will always be called
* asynchronously. Can be called before and after
* `writer` or `ender` have been called, even when `ender`
* is completely finished (useful to e.g. abort other streams, which may
* not be aborted yet).
* Must not throw any errors, will lead to unhandled
* rejected promise if it does.
* @return Promise for completely finished stream, i.e. same promise as `result()`
*/
writeEach(writer: () => T | undefined | void | PromiseLike<T | undefined | void>, ender?: (abortReason?: Error) => void | PromiseLike<void>, aborter?: (abortReason: Error) => void): Promise<void>;
mappedBy<X>(mapper: (value: X) => T | PromiseLike<T>): WritableStream<X>;
filterBy(filterer: (value: T) => boolean | PromiseLike<boolean>): WritableStream<T>;
}
/**
* Used when writing to an already-ended stream.
*/
export declare class WriteAfterEndError extends BaseError {
constructor();
}
/**
* Used when read callback(s) have already been attached.
*/
export declare class AlreadyHaveReaderError extends BaseError {
constructor();
}
/**
* Object stream with seamless support for backpressure, ending and error
* handling.
*/
export declare class Stream<T> implements ReadableStream<T>, WritableStream<T> {
/**
* Writers waiting for `_reader` to retrieve and process their value.
*/
private _writers;
/**
* Read handler that is called for every written value, as set by
* `forEach()`.
*/
private _reader?;
/**
* End handler that is called when the stream is ended, as set by
* `forEach()`. Note that `forEach()` installs a default handler if the user
* did not supply one.
* Set to 'undefined' when it has been called.
*/
private _ender?;
/**
* Abort handler that is called when the stream is aborted, as set by
* `forEach()` (can be undefined).
* Set to 'undefined' when it has been called.
*/
private _aborter?;
/**
* When a written value is being processed by the `_reader`, this property
* is set to a promise that resolves when the reader's returned PromiseLike is
* resolved (or rejected).
*/
private _readBusy?;
/**
* Set to an instance of an Eof object, containing optional error and final
* result of this stream. Set when `end()` is called.
*/
private _ending?;
/**
* Set to an instance of an Eof object, containing optional error and final
* result of this stream. Set when `_ender` is being called but not finished
* yet, unset when `_ended` is set.
*/
private _endPending?;
/**
* Set to the error passed to `end()` (or the special value `eof`) when the
* stream has ended, and the operation was confirmed by the `_ender`.
*/
private _ended?;
/**
* Set to a rejected promise when the stream is explicitly `abort()`'ed.
*/
private _abortPromise?;
/**
* Error given in abort() method
*/
private _abortReason?;
/**
* Resolved to a rejection when `abort()` is called.
*/
private _abortDeferred;
/**
* Resolved to the result of calling `_ender`, then the `result` property of
* the end-of-stream value.
*/
private _resultDeferred;
/**
* Write value (or promise for value) to stream.
*
* Writer is blocked until the value is read by the read handler passed to
* `forEach()`, and the value returned by that read handler is resolved.
*
* It is an error to write an `undefined` value (as this is a common
* programming error). Writing a promise for a void is currently allowed,
* but discouraged.
*
* The promise returned by `write()` will be rejected with the same reason if:
* - the written value is a PromiseLike that resolves to a rejection
* - the read handler throws an error or returns a rejected promise
* It is still possible to write another value after that, or e.g. `end()`
* the stream with or without an error.
*
* @param value Value to write, or promise for it
* @return Void-promise that resolves when value was processed by reader
*/
write(value: T | PromiseLike<T>): Promise<void>;
/**
* End the stream, optionally passing an error.
*
* Already pending writes will be processed by the reader passed to
* `forEach()` before passing the end-of-stream to its end handler.
*
* The returned promise will resolve after the end handler has finished
* processing. It is rejected if the end handler throws an error or returns
* a rejected promise.
*
* All calls to `write()` or `end()` after the first `end()` will be
* rejected with a `WriteAfterEndError`.
*
* By default, this stream's `result()` will be resolved when `end()`
* resolves, or rejected with the error if `end()` is called with an error.
* It is possible to let this stream's `result()` 'wait' until any upstream
* streams have completed by e.g. passing that upstream's `result()` as the
* second argument to `end()`.
*
* Note: even if a stream is aborted, it is still necessary to call `end()`
* to allow any resources to correctly be cleaned up.
*
* @param error Optional Error to pass to `forEach()` end handler
* @param result Optional promise that determines final value of `result()`
* @return Void-promise that resolves when `ended`-handler has processed the
* end-of-stream
*/
end(error?: Error, endedResult?: PromiseLike<void>): Promise<void>;
/**
* Read all values from stream, optionally waiting for explicit stream end.
*
* `reader` is called for every written value.
*
* `ender` is called once, when the writer `end()`s the stream, either with
* or without an error.
*
* `reader` and `ender` callbacks can return a promise to indicate when the
* value or end-of-stream condition has been completely processed. This
* ensures that a fast writer can never overload a slow reader, and is
* called 'backpressure'.
*
* The `reader` callback is never called while its previously returned
* promise is still pending, and the `ender` callback is likewise only
* called after all reads have completed.
*
* The corresponding `write()` or `end()` operation is blocked until the
* value returned from the reader or ender callback is resolved. If the
* callback throws an error or the returned promise resolves to a rejection,
* the `write()` or `end()` will be rejected with it.
*
* All callbacks are always called asynchronously (i.e. some time after
* `forEach()`, `write()`, `end()` or `abort()` returns), and their `this`
* argument will be undefined.
*
* `aborter` is called once if the stream is aborted and has not ended yet.
* (I.e. it will be called if e.g. `ender`'s returned promise is still
* pending, to allow early termination, but it will no longer be called
* if its promise has resolved).
*
* The `aborter` callback can be called while a reader callback's promise is
* still pending, and should try to let `reader` or `ender` finish as fast
* as possible.
*
* Note that even when a stream is aborted, it still needs to be `end()`'ed
* correctly.
*
* If no `ender` is given, a default end handler is installed that directly
* acknowledges the end-of-stream, also in case of an error. Note that that
* error will still be returned from `forEach()`.
*
* If no `aborter` is given, an abort is ignored (but will still cause
* further writes to fail, and it will be reflected in the returned promise).
*
* It is an error to call `forEach()` multiple times, and it is not possible
* to 'detach' already attached callbacks. Reason is that the exact behaviour
* of such actions (e.g. block or simply ignore further writes) is application
* dependent, and should be implemented as a transform instead.
*
* The return value of `forEach()` is `result()`, a promise that resolves
* when all parts in the stream(-chain) have completely finished.
*
* @param reader Callback called with every written value
* @param ender Optional callback called when stream is ended
* @param aborter Optional callback called when stream is aborted
* @return Promise for completely finished stream, i.e. same promise as `result()`
*/
forEach(reader: (value: T) => void | PromiseLike<void>, ender?: (error?: Error) => void | PromiseLike<void>, aborter?: (error: Error) => void): Promise<void>;
/**
* Signal that the stream is aborted: it will no longer read incoming
* elements and will no longer write elements except in the course of
* processing any pending asynchronous reader callbacks (i.e. unresolved
* Promises returned by `forEach()` or other stream iterators). Does not
* end the stream.
*
* An upstream source can handle this `abort()` by catching the exception
* from its own `aborted()` method--for example, to cancel pending fetch
* operations, or close a continuous data stream.
*
* If the stream's `forEach()` function provided an `aborter` callback and
* the stream is not yet ended, `aborter` will be called with the abort reason.
* This can be used to cancel any remaining operations inside the asynchronous
* reader callback.
*
* Once the last pending callback is resolved, any pending and future `write()`s
* to this stream will be rejected with the error provided to `abort()`.
*
* It is still necessary to explicitly `end()` the stream, to ensure that any
* resources can be cleaned up correctly both on the reader and writer side.
* The stream's `ender` callback will be called with the abort error (i.e. any
* error passed to `end()` is ignored.)
*
* The abort is ignored if the stream is already aborted.
*
* It's possible to abort an ended stream. This can be used to 'bubble' an
* abort signal to other parts in a chain of streams which may not have ended
* yet. It will not change the end-state of this part of the stream though.
*
* @param reason Optional Error value to signal a reason for the abort
*/
abort(reason?: Error): void;
/**
* Obtain promise that resolves to a rejection when `abort()` is called.
*
* Useful to pass abort to up- and down-stream sources.
*
* Note: this promise either stays pending, or is rejected. It is never
* fulfilled.
*
* @return Promise that is rejected with abort error when stream is aborted
*/
aborted(): Promise<never>;
/**
* Obtain a promise that resolves when the stream has completely ended:
* - `end()` has been called (possibly with an Error),
* - `ender` callback has run and its returned promise resolved,
* - `end()`'s result parameter (if any) has been resolved.
*
* @return Promise resolved when stream has completely ended
*/
result(): Promise<void>;
/**
* Determine whether `end()` has been called on the stream, but the stream
* is still processing it.
*
* @return true when `end()` was called but not acknowledged yet, false
* otherwise
*/
isEnding(): boolean;
/**
* Determine whether stream has completely ended (i.e. end handler has been
* called and its return PromiseLike, if any, is resolved).
* @return true when stream has ended, false otherwise
*/
isEnded(): boolean;
/**
* Determine whether `end()` has been called on the stream.
*
* @return true when `end()` was called
*/
isEndingOrEnded(): boolean;
/**
* Determine whether `forEach()` callback(s) are currently attached to the
* stream.
*
* @return true when `forEach()` has been called on this stream
*/
hasReader(): boolean;
/**
* Run all input values through a mapping callback, which must produce a new
* value (or promise for a value), similar to e.g. `Array`'s `map()`.
*
* Stream end in the input stream (normal or with error) will be passed to
* the output stream, after awaiting the result of the optional ender.
*
* Any error (thrown or rejection) in mapper or ender is returned to the
* input stream.
*
* @param mapper Callback which receives each value from this stream, and
* must produce a new value (or promise for a value)
* @param ender Called when stream is ending, result is waited for before
* passing on `end()`
* @param aborter Called when stream is aborted
* @return New stream with mapped values
*/
map<R>(mapper: (value: T) => R | PromiseLike<R>, ender?: (error?: Error) => void | PromiseLike<void>, aborter?: (error: Error) => void): ReadableStream<R>;
/**
* Run all input values through a filtering callback. If the filter callback
* returns a truthy value (or a promise for a truthy value), the input value
* is written to the output stream, otherwise it is ignored.
* Similar to e.g. `Array`'s `filter()`.
*
* Stream end in the input stream (normal or with error) will be passed to
* the output stream, after awaiting the result of the optional ender.
*
* Any error (thrown or rejection) in mapper or ender is returned to the
* input stream.
*
* @param filterer Callback which receives each value from this stream,
* input value is written to output if callback returns a
* (promise for) a truthy value.
* @param ender Called when stream is ending, result is waited for before
* passing on `end()`
* @param aborter Called when stream is aborted
* @return New stream with filtered values.
*/
filter(filterer: (value: T) => boolean | PromiseLike<boolean>, ender?: (error?: Error) => void | PromiseLike<void>, aborter?: (error: Error) => void): ReadableStream<T>;
/**
* Reduce the stream into a single value by calling a reducer callback for
* each value in the stream. Similar to `Array#reduce()`.
*
* The output of the previous call to `reducer` (aka `accumulator`) is given
* as the first argument of the next call. For the first call, either the
* `initial` value to `reduce()` is passed, or the first value of the stream
* is used (and `current` will be the second value).
*
* The result of `reduce()` is a promise for the last value returned by
* `reducer` (or the initial value, if there were no calls to `reducer`).
* If no initial value could be determined, the result is rejected with a
* TypeError.
* If the stream is ended with an error, the result is rejected with that
* error.
*
* It is possible for `reducer` to return a promise for its result.
*
* If the `reducer` throws an error or returns a rejected promise, the
* originating `write()` will fail with that error.
*
* Examples:
* s.reduce((acc, val) => acc + val); // sums all values
* s.reduce((acc, val) => { acc.push(val); return acc; }, []); // toArray()
*
* @param reducer Callback called for each value in the stream, with
* accumulator, current value, index of current value, and
* this stream.
* @param initial Optional initial value for accumulator. If no initial
* value is given, first value of stream is used.
* @return Promise for final accumulator.
*/
reduce(reducer: (accumulator: T, current: T, index: number, stream: ReadableStream<T>) => T | PromiseLike<T>, initial?: T): Promise<T>;
/**
* Reduce the stream into a single value by calling a reducer callback for
* each value in the stream. Similar to `Array#reduce()`.
*
* The output of the previous call to `reducer` (aka `accumulator`) is given
* as the first argument of the next call. For the first call, either the
* `initial` value to `reduce()` is passed, or the first value of the stream
* is used (and `current` will be the second value).
*
* The result of `reduce()` is a promise for the last value returned by
* `reducer` (or the initial value, if there were no calls to `reducer`).
* If no initial value could be determined, the result is rejected with a
* TypeError.
* If the stream is ended with an error, the result is rejected with that
* error.
*
* It is possible for `reducer` to return a promise for its result.
*
* If the `reducer` throws an error or returns a rejected promise, the
* originating `write()` will fail with that error.
*
* Examples:
* s.reduce((acc, val) => acc + val); // sums all values
* s.reduce((acc, val) => { acc.push(val); return acc; }, []); // toArray()
*
* @param reducer Callback called for each value in the stream, with
* accumulator, current value, index of current value, and
* this stream.
* @param initial Optional initial value for accumulator. If no initial
* value is given, first value of stream is used.
* @return Promise for final accumulator.
*/
reduce<R>(reducer: (accumulator: R, current: T, index: number, stream: ReadableStream<T>) => PromiseLike<R>, initial: R): Promise<R>;
/**
* Read all stream values into an array.
*
* Returns a promise that resolves to that array if the stream ends
* normally, or to the error if the stream is ended with an error.
*
* @return Promise for an array of all stream values
*/
toArray(): Promise<T[]>;
/**
* Read all values and end-of-stream from this stream, writing them to
* `writable`.
*
* @param writable Destination stream
* @return The stream passed in, for easy chaining
*/
pipe<R extends Writable<T>>(writable: R): R;
/**
* Return a new stream with the results of running the given
* transform.
*
* @param transformer Function that receives this stream and result stream
* as inputs.
* @return Readable stream with the transformed results
*/
transform<R>(transformer: Transform<T, R>): ReadableStream<R>;
/**
* Repeatedly call `writer` and write its returned value (or promise for it)
* to the stream.
* The stream is ended when `writer` returns `undefined` (or a promise that
* resolves to `undefined`).
*
* `writer` is only called again when its previously returned value has been
* processed by the stream.
*
* If writing of a value fails (either by the `writer` throwing an error,
* returning a rejection, or the write call failing), the stream is aborted
* and ended with that error.
*
* `ender` is always called once, just before the stream is ended. I.e.
* after `writer` returned (a promise for) `undefined` or the stream is
* aborted.
* It can be used to e.g. close a resource such as a database.
* Note: `ender` will only be called when `writer`'s promise (if any) has
* resolved.
*
* `aborter` is called once iff the stream is aborted. It can be called
* while e.g. a promise returned from the writer or ender is still pending,
* and can be used to make sure that that promise is resolved/rejected
* sooner.
* Note: the aborter should be considered a 'signal to abort', but cleanup
* of resources should be done in the `ender` (i.e. it cannot return a
* promise).
* It can be called (long) after `ender` has been called, because a stream
* can be aborted even after it is already ended, which is useful if this
* stream element is part of a larger chain of streams.
* An aborter must never throw an error.
*
* @param writer Called when the next value can be written to the stream,
* should return (a promise for) a value to be written,
* or `undefined` (or void promise) to end the stream.
* Will always be called asynchronously.
* @param ender Optional callback called once after `writer` indicated
* end-of-stream, or when the stream is aborted (and
* previously written value resolved/rejected). It's called
* without an argument if stream was not aborted (yet), and
* the abort reason if it was aborted (`aborter` will have
* been called, too). Will always be called asynchronously.
* @param aborter Optional callback called once when stream is aborted.
* Receives abort reason as its argument. Should be used
* to prematurely terminate any pending promises of
* `writer` or `ender`. Will always be called
* asynchronously. Can be called before and after
* `writer` or `ender` have been called, even when `ender`
* is completely finished (useful to e.g. abort other streams, which may
* not be aborted yet).
* Must not throw any errors, will lead to unhandled
* rejected promise if it does.
* @return Promise for completely finished stream, i.e. same promise as `result()`
*/
writeEach(writer: () => T | undefined | void | PromiseLike<T | undefined | void>, ender?: (abortReason?: Error) => void | PromiseLike<void>, aborter?: (abortReason: Error) => void): Promise<void>;
mappedBy<X>(mapper: (value: X) => T | PromiseLike<T>): WritableStream<X>;
filterBy(filterer: (value: T) => boolean | PromiseLike<boolean>): WritableStream<T>;
/**
* Return a Stream for all values in the input array.
*
* The stream is ended as soon as the first `undefined` value is
* encountered.
*
* The array itself, and/or the values in the array may also be promises.
*
* @see result() to wait for completion
* @see writeEach() for error handling behavior
*
* @param data (Promise for) input array of (promises for) values
* @return Stream of all values in the input array
*/
static from<T>(data: PromiseLike<PromiseLike<T>[]>): ReadableStream<T>;
/**
* Return a Stream for all values in the input array.
*
* The stream is ended as soon as the first `undefined` value is
* encountered.
*
* The array itself, and/or the values in the array may also be promises.
*
* @see result() to wait for completion
* @see writeEach() for error handling behavior
*
* @param data (Promise for) input array of (promises for) values
* @return Stream of all values in the input array
*/
static from<T>(data: PromiseLike<T>[]): ReadableStream<T>;
/**
* Return a Stream for all values in the input array.
*
* The stream is ended as soon as the first `undefined` value is
* encountered.
*
* The array itself, and/or the values in the array may also be promises.
*
* @see result() to wait for completion
* @see writeEach() for error handling behavior
*
* @param data (Promise for) input array of (promises for) values
* @return Stream of all values in the input array
*/
static from<T>(data: PromiseLike<T[]>): ReadableStream<T>;
/**
* Return a Stream for all values in the input array.
*
* The stream is ended as soon as the first `undefined` value is
* encountered.
*
* The array itself, and/or the values in the array may also be promises.
*
* @see result() to wait for completion
* @see writeEach() for error handling behavior
*
* @param data (Promise for) input array of (promises for) values
* @return Stream of all values in the input array
*/
static from<T>(data: T[]): ReadableStream<T>;
/**
* Bound callback to be passed as handlers to Promise.then()
*/
private _pumper;
/**
* Pump written values to `_reader` and `_ender`, resolve results of
* `write()` and `end()`.
*/
private _pump;
}
export default Stream;