Skip to content

Instantly share code, notes, and snippets.

@typoerr
Created July 22, 2017 14:13
Show Gist options
  • Select an option

  • Save typoerr/baeb2ffd9e1707f306608fdecd7380e6 to your computer and use it in GitHub Desktop.

Select an option

Save typoerr/baeb2ffd9e1707f306608fdecd7380e6 to your computer and use it in GitHub Desktop.
export interface Action<T = any, K extends keyof T= any> {
type: K;
payload: T[K];
}
///////////////////////////////////////////////////////////
import { Stream, mergeArray } from 'most';
import { Action } from './types';
import { async } from 'most-subject';
export interface Dispatch<A> {
<K extends keyof A>(type: K, payload: A[K]): Action<A, K>;
}
export interface MergedCtx<A> {
dispatch: Dispatch<A>;
}
export interface Epic<A, C = any> {
(action$: Stream<Action<A>>, context: C & MergedCtx<A>): Stream<any>;
}
export default function connect<A, C>(epics: Epic<A, C>[]) {
return (context: C) => {
const ctx: C & MergedCtx<A> = Object.assign({ dispatch }, context);
const actionIn$ = async<any>();
const epicArray$ = epics.map(ep => ep(actionIn$, ctx));
mergeArray(epicArray$).drain();
return dispatch as Dispatch<A>;
function dispatch<K extends keyof A>(type: K, payload: A[K]) {
const action = { type, payload };
actionIn$.next(action);
return action;
}
};
}
///////////////////////////////////////////////
import { Stream } from 'most';
import { Action } from './types';
export default function select<T, K extends keyof T>(type: K, action$: Stream<Action<T>>): Stream<T[K]> {
return (action$ as Stream<Action<T, K>>)
.filter(x => x.type === type)
.map(x => x.payload);
}
///////////////////////////////////////////////////
@typoerr

typoerr commented Jul 22, 2017

Copy link
Copy Markdown
Author
// test.ts
import connect, { Epic as _Epic } from './connect-epics';

interface ActionMap {
    a: number;
    b: string;
}

type Epic = _Epic<ActionMap, { ctx: 'ctx' }>;

test('connect', (done) => {
    expect.assertions(4);
    const ep1: Epic = ($, ctx) => {
        return $.filter(x => x.type === 'a')
            .map(x => x.payload)
            .tap(_ => expect(ctx.ctx).toBe('ctx'))
            .tap(x => expect(x).toBe(1))
            .tap(x => ctx.dispatch('b', `${x}`));
    };

    const ep2: Epic = ($) => {
        return $.filter(x => x.type === 'b')
            .map(x => x.payload)
            .tap(x => expect(x).toBe('1'))
            .tap(done);
    };

    const dispatch = connect([ep1, ep2])({ ctx: 'ctx' });
    const action = dispatch('a', 1);
    expect(action).toEqual({ type: 'a', payload: 1 });
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment