UNPKG

cyclejs-stream

Version:

Observable (events stream) to which you can inject another streams.

93 lines (68 loc) 2.65 kB
import 'core-js/fn/object/entries'; import 'core-js/fn/array/from'; import { Rx } from '@cycle/core'; import InputProxy from './input-proxy'; function _throwIfNotObservable(thing, msg) { if(!(thing instanceof Rx.Observable)) { throw new TypeError(msg); } } function _passToProxies(sources, proxies, disposable) { sources.forEach((source, index) => { _throwIfNotObservable(source, `Only Observables can be injected to Stream, but argument ${index} does not look to be one`); let proxy = proxies[index]; if(!proxy.wasPassed) { let subscription = proxy.pass(source); disposable.add(subscription); } }); } class InjectableStream extends Rx.ReplaySubject { constructor(definitionFn) { super(1); if('function' !== typeof definitionFn) { throw new TypeError('the first argument must be a function!'); } this._definitionFn = definitionFn; this._wasInjected = false; this._wasSubscribed = false; this._proxies = Array.from(new Array(this._definitionFn.length), () => (new InputProxy())); this._subscriptions = new Rx.CompositeDisposable(); } dispose() { super.dispose(); this._subscriptions.dispose(); } inject(...dependencies) { if(this._wasInjected) { throw new Error('you can inject only once! (do it wisely, then)'); } if(dependencies.length !== this._definitionFn.length) { throw new Error(`stream requires ${this._definitionFn.length} dependencies, but ${dependencies.length} have been provided`); } this._dependencies = dependencies; this._wasInjected = true; if(this._wasSubscribed) { _passToProxies(this._dependencies, this._proxies, this._subscriptions); } return this; } subscribe(...args) { if(!this._wasSubscribed) { let source$ = this._definitionFn(...this._proxies); _throwIfNotObservable(source$, 'Stream definition function must return an Observable.'); let subscription = source$.subscribe(this.asObserver()); this._subscriptions.add(subscription); this._wasSubscribed = true; if(this._wasInjected) { _passToProxies(this._dependencies, this._proxies, this._subscriptions); } } return super.subscribe(...args); } } export default function createInjectableStream(fn) { return new InjectableStream(fn); }