import { Stream, Source, Sink, Disposable, Scheduler } from '@tempest/core' export interface DebugSubscriber { next?: (x: T) => any error?: (e: Error) => any complete?: (x?: T) => any dispose?: () => any } export interface CurriedDebug { (): (infoOrSpy: string | DebugSubscriber, stream: Stream) => Stream (infoOrSpy: string | DebugSubscriber): (stream: Stream) => Stream (infoOrSpy: string | DebugSubscriber, stream: Stream): Stream } export const debug: CurriedDebug = function (infoOrSpy: string | DebugSubscriber, stream: Stream): ((infoOrSpy: string | DebugSubscriber, stream: Stream) => Stream) | ((stream: Stream) => Stream) | Stream { switch (arguments.length) { case 1: return function (stream: Stream): Stream { return new Stream(new Debug(infoOrSpy, stream.source)) } case 2: return new Stream(new Debug(infoOrSpy, stream.source)) default: return debug } } export class Debug implements Source { constructor (private infoOrSpy: string | DebugSubscriber, private source: Source) {} run (sink: Sink, scheduler: Scheduler): Disposable { if (typeof this.infoOrSpy === 'object') { if (typeof (this.infoOrSpy as DebugSubscriber).dispose === 'function') { const disposeSpy = (this.infoOrSpy as DebugSubscriber).dispose const disposable = this.source.run(new DebugSink(this.infoOrSpy, sink), scheduler) return { dispose () { disposeSpy() return disposable.dispose() } } } } else { return this.source.run(new DebugSink(this.infoOrSpy, sink), scheduler) } } } class DebugSink implements Sink { constructor (private infoOrSpy: string | DebugSubscriber, private sink: Sink) {} event (time: number, value: T) { if (typeof this.infoOrSpy === 'string') { console.log(this.infoOrSpy as string + ':', value) } else if (typeof this.infoOrSpy === 'object') { if (typeof (this.infoOrSpy as DebugSubscriber).next === 'function') { (this.infoOrSpy as DebugSubscriber).next(value) } } this.sink.event(time, value) } error (time: number, err: Error) { if (typeof this.infoOrSpy === 'object') { if (typeof (this.infoOrSpy as DebugSubscriber).error === 'function') { (this.infoOrSpy as DebugSubscriber).error(err) } } this.sink.error(time, err) } end (time: number, value?: T) { if (typeof this.infoOrSpy === 'string') { console.log(this.infoOrSpy as string + ': ending') } else if (typeof this.infoOrSpy === 'object') { if (typeof (this.infoOrSpy as DebugSubscriber).complete === 'function') { (this.infoOrSpy as DebugSubscriber).complete(value) } } this.sink.end(time, value) } }