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>;