From a87d35727c2ce74643c70bd6390a57c3a4ecacb0 Mon Sep 17 00:00:00 2001 From: Jichao Ouyang <oyanglulu@gmail.com> Date: Sat, 20 May 2017 18:03:52 +0800 Subject: [PATCH] more specific about types --- src/classGenerator.ts | 26 ++++++++++++++------------ src/engine/most.ts | 7 +++++-- src/engine/rx.ts | 18 +++++++++++------- src/history.ts | 9 ++++----- src/interfaces.ts | 29 ++++++++++++++++++----------- types/engine/most.d.ts | 3 ++- types/engine/rx.d.ts | 7 ++++--- types/history.d.ts | 7 +++---- types/interfaces.d.ts | 28 +++++++++++++++++----------- 9 files changed, 78 insertions(+), 56 deletions(-) diff --git a/src/classGenerator.ts b/src/classGenerator.ts index f4c34de..7d53d89 100644 --- a/src/classGenerator.ts +++ b/src/classGenerator.ts @@ -1,8 +1,9 @@ import * as React from 'react'; import { PropTypes } from 'prop-types'; import initHistory, { Traveler } from './history'; -import { Plan, Connect, ConnectClass } from './interfaces' -import Engine from './engine/most'; +import {Observable} from '@reactivex/rxjs' +import { Stream,Plan, Connect, ConnectClass, ContextEngine, Actions, Subject,RunableMachine,BindActions } from './interfaces' + // unfortunately React doesn't support symbol as context key yet, so let me just preteding using Symbol until react implement the Symbol version of Object.assign export const REACT_MOST_ENGINE = '@@reactive-react/react-most.engine'; @@ -19,11 +20,11 @@ export function genNodeClass<I, S>(WrappedComponent: ConnectClass<I, S>, main: P return class ConnectNode extends WrappedComponent { static contextTypes = CONTEXT_TYPE static displayName = `Connect(${getDisplayName(WrappedComponent)})` - constructor(props, context) { + constructor(props, context: ContextEngine<I,S>) { super(props, context); let { actions, update$ } = main(context[REACT_MOST_ENGINE].intentStream, props) this.machine = { - update$: this.machine.update$.merge(update$), + update$: context[REACT_MOST_ENGINE].merge(this.machine.update$, update$), actions: Object.assign({}, bindActions(actions, context[REACT_MOST_ENGINE].intentStream, this), this.machine.actions) } } @@ -33,14 +34,15 @@ export function genLeafClass<I, S>(WrappedComponent: React.SFC<any> | React.Comp return class ConnectLeaf extends Connect<I, S> { static contextTypes = CONTEXT_TYPE static displayName = `Connect(${getDisplayName(WrappedComponent)})` - constructor(props, context) { + constructor(props, context: ContextEngine<I,S>) { super(props, context); - let engine: Engine<I, S> = context[REACT_MOST_ENGINE] + let engine = context[REACT_MOST_ENGINE] if (opts.history || props.history) { this.traveler = initHistory(engine.historyStream, engine.travelStream); - this.traveler.travel.forEach(state => { - return this.setState(state); - }); + this.context[REACT_MOST_ENGINE].observe( + this.traveler.travel, + state => this.setState(state), + ) } let { actions, update$ } = main(engine.intentStream, props) this.machine = { @@ -110,13 +112,13 @@ export function genLeafClass<I, S>(WrappedComponent: React.SFC<any> | React.Comp function getDisplayName(WrappedComponent) { return WrappedComponent.displayName || WrappedComponent.name || 'Component'; } -function bindActions(actions, intent$, self) { +function bindActions<I>(actions: Actions<I>, intent$: Subject<I>, self):BindActions<I> { let _actions = { - fromEvent(e, f = x => x) { + fromEvent(e, f:(x:any)=>I = x => x) { return intent$.next(f(e)); }, fromPromise(p) { - return p.then(x => intent$.next(x)); + return p.then((x:I) => intent$.next(x)); }, }; diff --git a/src/engine/most.ts b/src/engine/most.ts index 84cce81..24ed294 100644 --- a/src/engine/most.ts +++ b/src/engine/most.ts @@ -1,4 +1,4 @@ -import { from, of, mergeArray, Stream, never, Subscription } from 'most' +import { from, of, merge as mostMerge, Stream, never, Subscription } from 'most' import { async as subject, AsyncSubject, Subject } from 'most-subject' import { Update, Engine } from '../interfaces' export default class MostEngine<T, S> implements Engine<T, S> { @@ -11,7 +11,7 @@ export default class MostEngine<T, S> implements Engine<T, S> { this.travelStream = subject() as Subject<(n: number) => number>; } - observe(actionsSinks: Stream<Update<S>>, f, end): Subscription<S> { + observe(actionsSinks: Stream<Update<S>>, f, end): Subscription<any> { let errorHandled = actionsSinks .recoverWith((e: Error) => { console.error('There is Error in your reducer:', e, e.stack) @@ -24,4 +24,7 @@ export default class MostEngine<T, S> implements Engine<T, S> { complete: end }); } + merge<T>(a: Stream<T>, b: Stream<T>) { + return mostMerge(a, b) + } } diff --git a/src/engine/rx.ts b/src/engine/rx.ts index f0625d9..d642873 100644 --- a/src/engine/rx.ts +++ b/src/engine/rx.ts @@ -1,20 +1,24 @@ -import { Subject, Observable, Subscription } from '@reactivex/rxjs' -import { Update, Engine } from '../interfaces' +import { Subject as RxSubject, Observable, Subscription } from '@reactivex/rxjs' +import { Update, Engine, Subject } from '../interfaces' export default class RxEngine<T, S> implements Engine<T, S> { intentStream: Subject<T> historyStream: Subject<S> travelStream: Subject<(n: number) => number> constructor() { - this.intentStream = new Subject() - this.historyStream = new Subject() - this.travelStream = new Subject() + this.intentStream = new RxSubject() + this.historyStream = new RxSubject() + this.travelStream = new RxSubject() } - observe(actionsSinks: Observable<Update<S>>, f): Subscription { + observe(actionsSinks: Observable<Update<S>>, f, end): Subscription { return actionsSinks.subscribe( f, - (e) => console.error('Something is Wrong:', e, e.stack) + (e) => console.error('Something is Wrong:', e, e.stack), + end, ) } + merge<T>(a: Observable<T>, b: Observable<T>) { + return Observable.merge(a, b) + } } diff --git a/src/history.ts b/src/history.ts index 2ff7125..b633fa2 100644 --- a/src/history.ts +++ b/src/history.ts @@ -1,12 +1,11 @@ -import { from, Stream } from 'most' -import { Subject } from 'most-subject' -import { Stamp } from './interfaces' +import { Stamp, Stream, Subject } from './interfaces' +import {from, Stream as MStream} from 'most' export class Traveler<S> { cursor: number path: Subject<(n: number) => number> history: Stream<Stamp<S>[]> travel: Stream<S> - constructor(history: Stream<Stamp<S>[]>, path: Subject<(n: number) => number>) { + constructor(history: MStream<Stamp<S>[]>, path: Subject<(n: number) => number>) { this.history = history this.path = path this.travel = from(this.path) @@ -16,7 +15,7 @@ export class Traveler<S> { this.cursor = offset(this.cursor) return states[cursor].value; } - }, this.path, this.history) + }, from(this.path), this.history) .filter(x => !!x) } forward = () => { diff --git a/src/interfaces.ts b/src/interfaces.ts index ac4328f..88c5239 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -1,20 +1,22 @@ import * as React from 'react' import { Traveler } from './history' +import {Stream as MostStream} from 'most' +import {Subject as MostSubject} from 'most-subject' +import {Observable as RxStream, Subject as RxSubject} from '@reactivex/rxjs' export interface Actions<T> { - [propName: string]: (...v: any[]) => T + [actionName: string]: (...p: any[]) => T } -export interface Subject<T> { - next: (v?: T) => void - complete: (v?: any) => void + +export interface BindActions<T> { + [actionName: string]: (...p: any[]) => void } +export type Subject<T> = MostSubject<T> | RxSubject<T> export interface Subscription<A> { unsubscribe(): void; } -export interface Stream<A> { - merge: (a: Stream<A>) => Stream<A> -} +export type Stream<A> = MostStream<A> | RxStream<A> export interface Plan<I, S> { (intent: Subject<I>, props?: {}): Machine<I, S> @@ -27,6 +29,10 @@ export interface Machine<I, S> { update$: Stream<Update<S>> } +export interface RunableMachine<I, S> { + actions?: BindActions<I>, + update$: Stream<Update<S>> +} export interface ConnectProps<I> { actions?: Actions<I> history?: boolean @@ -34,15 +40,14 @@ export interface ConnectProps<I> { } export class Connect<I, S> extends React.PureComponent<ConnectProps<I>, S> { - machine: Machine<I, S> + machine: RunableMachine<I, S> traveler: Traveler<S> subscription: Subscription<S> } export interface ConnectClass<I, S> { - contextTypes?: any - defaultProps?: any - new (props?: ConnectProps<I>, context?: any): Connect<I, S>; + contextTypes?: ContextEngine<I,S> + new (props: ConnectProps<I>, context: ContextEngine<I,S>): Connect<I, S>; } export interface History<S> { @@ -59,6 +64,8 @@ export interface Engine<I, S> { intentStream: Subject<I> historyStream: Subject<S> travelStream: Subject<(n: number) => number> + merge(a: Stream<Update<S>>, b: Stream<Update<S>>): Stream<Update<S>> + observe(actionsSinks: Stream<Update<S>>, f, end): Subscription<S> } export interface MostProps<T, S> { diff --git a/types/engine/most.d.ts b/types/engine/most.d.ts index 74814ff..9c83bc1 100644 --- a/types/engine/most.d.ts +++ b/types/engine/most.d.ts @@ -6,5 +6,6 @@ export default class MostEngine<T, S> implements Engine<T, S> { historyStream: Subject<S>; travelStream: Subject<(n: number) => number>; constructor(); - observe(actionsSinks: Stream<Update<S>>, f: any, end: any): Subscription<S>; + observe(actionsSinks: Stream<Update<S>>, f: any, end: any): Subscription<any>; + merge<T>(a: Stream<T>, b: Stream<T>): Stream<T>; } diff --git a/types/engine/rx.d.ts b/types/engine/rx.d.ts index 8ca26c9..d0ba251 100644 --- a/types/engine/rx.d.ts +++ b/types/engine/rx.d.ts @@ -1,9 +1,10 @@ -import { Subject, Observable, Subscription } from '@reactivex/rxjs'; -import { Update, Engine } from '../interfaces'; +import { Observable, Subscription } from '@reactivex/rxjs'; +import { Update, Engine, Subject } from '../interfaces'; export default class RxEngine<T, S> implements Engine<T, S> { intentStream: Subject<T>; historyStream: Subject<S>; travelStream: Subject<(n: number) => number>; constructor(); - observe(actionsSinks: Observable<Update<S>>, f: any): Subscription; + observe(actionsSinks: Observable<Update<S>>, f: any, end: any): Subscription; + merge<T>(a: Observable<T>, b: Observable<T>): Observable<T>; } diff --git a/types/history.d.ts b/types/history.d.ts index 3b62cd2..ba6f9a2 100644 --- a/types/history.d.ts +++ b/types/history.d.ts @@ -1,12 +1,11 @@ -import { Stream } from 'most'; -import { Subject } from 'most-subject'; -import { Stamp } from './interfaces'; +import { Stamp, Stream, Subject } from './interfaces'; +import { Stream as MStream } from 'most'; export declare class Traveler<S> { cursor: number; path: Subject<(n: number) => number>; history: Stream<Stamp<S>[]>; travel: Stream<S>; - constructor(history: Stream<Stamp<S>[]>, path: Subject<(n: number) => number>); + constructor(history: MStream<Stamp<S>[]>, path: Subject<(n: number) => number>); forward: () => void; backward: () => void; } diff --git a/types/interfaces.d.ts b/types/interfaces.d.ts index e367732..374adfd 100644 --- a/types/interfaces.d.ts +++ b/types/interfaces.d.ts @@ -1,19 +1,20 @@ /// <reference types="react" /> import * as React from 'react'; import { Traveler } from './history'; +import { Stream as MostStream } from 'most'; +import { Subject as MostSubject } from 'most-subject'; +import { Observable as RxStream, Subject as RxSubject } from '@reactivex/rxjs'; export interface Actions<T> { - [propName: string]: (...v: any[]) => T; + [actionName: string]: (...p: any[]) => T; } -export interface Subject<T> { - next: (v?: T) => void; - complete: (v?: any) => void; +export interface BindActions<T> { + [actionName: string]: (...p: any[]) => void; } +export declare type Subject<T> = MostSubject<T> | RxSubject<T>; export interface Subscription<A> { unsubscribe(): void; } -export interface Stream<A> { - merge: (a: Stream<A>) => Stream<A>; -} +export declare type Stream<A> = MostStream<A> | RxStream<A>; export interface Plan<I, S> { (intent: Subject<I>, props?: {}): Machine<I, S>; } @@ -24,20 +25,23 @@ export interface Machine<I, S> { actions?: Actions<I>; update$: Stream<Update<S>>; } +export interface RunableMachine<I, S> { + actions?: BindActions<I>; + update$: Stream<Update<S>>; +} export interface ConnectProps<I> { actions?: Actions<I>; history?: boolean; [propName: string]: any; } export declare class Connect<I, S> extends React.PureComponent<ConnectProps<I>, S> { - machine: Machine<I, S>; + machine: RunableMachine<I, S>; traveler: Traveler<S>; subscription: Subscription<S>; } export interface ConnectClass<I, S> { - contextTypes?: any; - defaultProps?: any; - new (props?: ConnectProps<I>, context?: any): Connect<I, S>; + contextTypes?: ContextEngine<I, S>; + new (props: ConnectProps<I>, context: ContextEngine<I, S>): Connect<I, S>; } export interface History<S> { path: Subject<(n: number) => number>; @@ -51,6 +55,8 @@ export interface Engine<I, S> { intentStream: Subject<I>; historyStream: Subject<S>; travelStream: Subject<(n: number) => number>; + merge(a: Stream<Update<S>>, b: Stream<Update<S>>): Stream<Update<S>>; + observe(actionsSinks: Stream<Update<S>>, f: any, end: any): Subscription<S>; } export interface MostProps<T, S> { engine?: new () => Engine<T, S>;