@johngw/stream
Version:
Reactive programming tools using the WHATWG Streams API.
73 lines (68 loc) • 1.68 kB
text/typescript
import { Predicate } from '@johngw/stream-common/Function'
import { Flushable, pipeFlushes } from '@johngw/stream-common/Stream'
/**
* Runs every chunk through a predicate. If anything fails the
* predicate, `false` is queued and the stream terminated.
* Otherwise this will wait for the entire stream to finish
* before queuing `true`.
*
* @group Transformers
* @see {@link some:function}
* @example
* When every chunk passes the predicate.
* ```
* --1--2--3--4--5--6--7--8--9-|
*
* every((x) => x < 10)
*
* ----------------------------T-|
* ```
*
* When something fails the predicate.
* ```
* --1--2--3--4--5--6--X
*
* every((x) => x < 5)
*
* ------------------F-|
* ```
*
* A `flushes` stream can be used to force the transformer to queue
* it's current state downstream.
*
* ```
* --1--2--3--4--5--6--7--8--9-|
*
* every((x) => x < 10, { flushes:
* -----------N-----------------
* })
*
* -----------T----------------T-|
* ```
*/
export function every<T>(predicate: Predicate<T>, options?: Flushable) {
const finishController = new AbortController()
return new TransformStream<T, boolean>({
start(controller) {
pipeFlushes(
() => controller.enqueue(true),
(error) => controller.error(error),
{ ...options, signal: finishController.signal }
)
},
async transform(chunk, controller) {
try {
if (!(await predicate(chunk))) {
controller.enqueue(false)
controller.terminate()
}
} catch (error) {
controller.error(error)
}
},
flush(controller) {
controller.enqueue(true)
finishController.abort()
},
})
}