import xs, {Stream} from 'xstream'; import concat from 'xstream/extra/concat'; import {MainFn, Reducer} from './types'; import {StateSource} from './StateSource'; import microtask from 'quicktask'; const schedule = microtask(); /** * While we are waiting for keyof subtraction to land in TypeScript, * https://github.com/Microsoft/TypeScript/issues/12215, * we must use `any` as the type of sources or sinks in the mainOnionified. * This is because the correct type is *not* * * Main * * *neither* * * Main, Partial> * * The former will signal to Cycle.run that a driver for 'onion' is needed, * while the latter will make valid channels like 'DOM' become optional. * The correct type should be * * Main, Omit> */ export type Omit = any; // type Omit = { // [P in keyof T - K]: T[P]; // }; export type OSo = {onion: StateSource}; export type OSi = {onion: Stream>}; export type MainOnionified, Si extends OSi> = MainFn, Omit>; export function onionify, Si extends OSi>( main: MainFn, name: string = 'onion'): MainOnionified { return function mainOnionified(sources: Omit): Omit { const reducerMimic$ = xs.create>(); const state$ = reducerMimic$ .fold((state, reducer) => reducer(state), void 0 as (T | undefined)) .drop(1); sources[name] = new StateSource(state$, name); const sinks = main(sources as So); if (sinks[name]) { const stream$ = concat( xs.fromObservable>(sinks[name]), xs.never(), ); stream$.subscribe({ next: i => schedule(() => reducerMimic$._n(i)), error: err => schedule(() => reducerMimic$._e(err)), complete: () => schedule(() => reducerMimic$._c()), }) } return sinks; }; }