UNPKG

@johngw/stream

Version:

Reactive programming tools using the WHATWG Streams API.

81 lines 2.88 kB
import { ForkableStream } from '../sinks/ForkableStream.js'; import { ControllableStream } from '../sources/ControllableStream.js'; /** * The base class for all subjects. * * @group Subjects * @see {@link Subject:class} * @see {@link StatefulSubject:class} */ export class Subject { #controllable; #controllers = new Set(); #forkable; constructor(options = {}) { const { pre = [], post = [], transform, pipeThroughOptions, pipeToOptions, } = options; const controllable = 'controllable' in options && options.controllable ? options.controllable : new ControllableStream(options.controllableStrategy); const forkable = 'forkable' in options && options.forkable ? options.forkable : new ForkableStream(options.forkableStrategy); this.#controllable = controllable; this.#forkable = forkable; const inReadable = pre.reduce((readable, transform) => readable.pipeThrough(transform, pipeThroughOptions), controllable); (transform ? post.reduce((readable, transform) => readable.pipeThrough(transform, pipeThroughOptions), inReadable.pipeThrough(transform, pipeThroughOptions)) : inReadable) .pipeTo(this.forkable, pipeToOptions) .catch(() => { // errors can be handled in downstream forks }); } get controllable() { return this.#controllable; } get finished() { return this.#forkable.finished; } get forkable() { return this.#forkable; } fork(underlyingSource, queuingStrategy) { return this.#forkable.fork(underlyingSource, queuingStrategy); } write(queuingStrategy) { const controller = this.control(); return new WritableStream({ abort(reason) { controller.error(reason); }, close() { controller.close(); }, write(chunk) { controller.enqueue(chunk); }, }, queuingStrategy); } /** * Returns a proxy to the ControllableStream. Once all proxies * have been closed, then the source is also closed. */ control() { const controller = new Proxy(this.#controllable, { get: (target, prop) => { if (prop === 'close') return this.#closeController.bind(this, controller); const value = target[prop]; return typeof value === 'function' ? value.bind(target) : value; }, }); this.#controllers.add(controller); return controller; } #closeController(controller) { this.#controllers.delete(controller); if (!this.#controllers.size) this.#controllable.close(); } } //# sourceMappingURL=Subject.js.map