cyclejs-stream
Version:
Observable (events stream) to which you can inject another streams.
93 lines (68 loc) • 2.65 kB
JavaScript
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);
}