Skip to content

Commit

Permalink
chore(rename): deprecate thunkservables, rename reduxObservable() t…
Browse files Browse the repository at this point in the history
…o `createEpicMiddleware()`, `combineDelegators()` to `combineEpics()`

BREAKING CHANGE: We are deprecating thunkservables in favor of the new "epic"-style. Now, creating the middleware is done with `createEpicMiddleware(rootEpic)` instead of `reduxObservable(rootEpic)` and `combineDelegators()` has been renamed `combineEpics()`. See the brand new gitbook documentation for more details on Epics.
  • Loading branch information
jayphelps committed Jul 12, 2016
1 parent c11a0fa commit 5cbcce4
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 43 deletions.
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Middleware } from 'redux';
import { Observable } from 'rxjs/Observable';
import { Operator } from 'rxjs/Operator';

export declare function reduxObservable(): Middleware;
export declare function createEpicMiddleware(): Middleware;

// ./node_modules/rxjs/Observable.d.ts
export declare class ActionsObservable<T> extends Observable<T> {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"build:umd:min": "cross-env NODE_ENV=production webpack src/index.js dist/redux-observable.min.js",
"build_tests": "rm -rf temp && babel test -d temp",
"clean": "rimraf lib temp dist",
"test": "npm run build && npm run build_tests && mocha temp && npm run test_typings",
"test": "npm run lint && npm run build && npm run build_tests && mocha temp && npm run test_typings",
"test_typings": "tsc test/typings.ts --outFile temp/typings.js --target ES2015 --moduleResolution node",
"prepublish": "npm run clean && npm run lint && npm test"
},
Expand Down Expand Up @@ -77,6 +77,7 @@
"redux": "^3.5.1",
"rimraf": "^2.5.2",
"rxjs": "^5.0.0-beta.6",
"sinon": "1.17.4",
"symbol-observable": "^0.2.4",
"typescript": "^1.8.10",
"webpack": "^1.13.1",
Expand Down
7 changes: 0 additions & 7 deletions src/combineDelegators.js

This file was deleted.

7 changes: 7 additions & 0 deletions src/combineEpics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { merge } from 'rxjs/observable/merge';

/**
Merges all epics into a single one.
*/
export const combineEpics = (...epics) => (actions, store) =>
merge(...(epics.map(epic => epic(actions, store))));
10 changes: 7 additions & 3 deletions src/reduxObservable.js → src/createEpicMiddleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@ import { Subject } from 'rxjs/Subject';
import { from } from 'rxjs/observable/from';
import { ActionsObservable } from './ActionsObservable';

export function reduxObservable(processor) {
export function createEpicMiddleware(epic) {
let actions = new Subject();
let actionsObs = new ActionsObservable(actions);

let middleware = (store) => (next) => {
if (processor) {
processor(actionsObs, store).subscribe(store.dispatch);
if (epic) {
epic(actionsObs, store).subscribe(store.dispatch);
}
return (action) => {
if (typeof action === 'function') {
if (typeof console !== 'undefined' && typeof console.warn !== 'undefined') {
console.warn('DEPRECATION: Using thunkservables with redux-observable is now deprecated in favor of the new "Epics" feature. See https://github.com/redux-observable/redux-observable/blob/docs/docs/SUMMARY.md');
}

let obs = from(action(actionsObs, store));
let sub = obs.subscribe(store.dispatch);
return sub;
Expand Down
4 changes: 2 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { reduxObservable } from './reduxObservable';
export { createEpicMiddleware } from './createEpicMiddleware';
export { ActionsObservable } from './ActionsObservable';
export { combineDelegators } from './combineDelegators';
export { combineEpics } from './combineEpics';
4 changes: 2 additions & 2 deletions test/ActionsObservable-spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* globals describe it */
import { expect } from 'chai';
import { ActionsObservable, reduxObservable } from '../';
import { ActionsObservable, createEpicMiddleware } from '../';
import { createStore, applyMiddleware } from 'redux';
import { of } from 'rxjs/observable/of';
import { Subject } from 'rxjs/Subject';
Expand All @@ -11,7 +11,7 @@ describe('ActionsObservable', () => {
});

it('should be the type provided to a dispatched function', () => {
let middleware = reduxObservable();
let middleware = createEpicMiddleware();
let reducer = (state, action) => {
return state;
};
Expand Down
24 changes: 12 additions & 12 deletions test/combineDelegators-spec.js → test/combineEpics-spec.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
/* globals describe it */
import { expect } from 'chai';
import { combineDelegators, ActionsObservable } from '../';
import { combineEpics, ActionsObservable } from '../';
import { Subject } from 'rxjs/Subject';
import { map } from 'rxjs/operator/map';

describe('combineDelegators', () => {
it('should combine delegators', () => {
let delegator1 = (actions, store) =>
describe('combineEpics', () => {
it('should combine epics', () => {
let epic1 = (actions, store) =>
actions.ofType('ACTION1')::map(action => ({ type: 'DELEGATED1', action, store }));
let delegator2 = (actions, store) =>
let epic2 = (actions, store) =>
actions.ofType('ACTION2')::map(action => ({ type: 'DELEGATED2', action, store }));

let delegator = combineDelegators(
delegator1,
delegator2
let epic = combineEpics(
epic1,
epic2
);

let store = { I: 'am', a: 'store' };
let subject = new Subject();
let actions = new ActionsObservable(subject);
let result = delegator(actions, store);
let delegatedActions = [];
let result = epic(actions, store);
let emittedActions = [];

result.subscribe(delegatedAction => delegatedActions.push(delegatedAction));
result.subscribe(emittedAction => emittedActions.push(emittedAction));

subject.next({ type: 'ACTION1' });
subject.next({ type: 'ACTION2' });

expect(delegatedActions).to.deep.equal([
expect(emittedActions).to.deep.equal([
{ type: 'DELEGATED1', action: { type: 'ACTION1' }, store },
{ type: 'DELEGATED2', action: { type: 'ACTION2' }, store },
]);
Expand Down
44 changes: 31 additions & 13 deletions test/reduxObservable-spec.js → test/createEpicMiddleware-spec.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
/* globals describe it */
import { expect } from 'chai';
import sinon from 'sinon';
import { createStore, applyMiddleware } from 'redux';
import { reduxObservable } from '../';
import { createEpicMiddleware } from '../';
import * as Rx from 'rxjs';
import Promise from 'promise';
import 'babel-polyfill';
import $$observable from 'symbol-observable';

const { Observable } = Rx;

describe('reduxObservable', () => {
it('should accept a processor argument that wires up a stream of actions to a stream of actions', () => {
describe('createEpicMiddleware', () => {
it('should accept a epic argument that wires up a stream of actions to a stream of actions', () => {
const reducer = (state = [], action) => state.concat(action);

const middleware = reduxObservable((actions, store) =>
const epic = (actions, store) =>
Observable.merge(
actions.ofType('FIRE_1').mapTo({ type: 'ACTION_1' }),
actions.ofType('FIRE_2').mapTo({ type: 'ACTION_2' })
)
);
);

const middleware = createEpicMiddleware(epic);

const store = createStore(reducer, applyMiddleware(middleware));

Expand All @@ -34,10 +35,27 @@ describe('reduxObservable', () => {
]);
});

it('emit warning that thunkservable are deprecated', () => {
sinon.spy(console, 'warn');

const reducer = (state = [], action) => state.concat(action);
const middleware = createEpicMiddleware();
const store = createStore(reducer, applyMiddleware(middleware));

store.dispatch(() => Observable.of({ type: 'ASYNC_ACTION_1' }));

expect(console.warn.calledOnce).to.equal(true);
expect(
console.warn.calledWith('DEPRECATION: Using thunkservables with redux-observable is now deprecated in favor of the new "Epics" feature. See https://github.com/redux-observable/redux-observable/blob/docs/docs/SUMMARY.md')
).to.equal(true);

console.warn.restore();
});

it('should intercept and process actions', (done) => {
const reducer = (state = [], action) => state.concat(action);

const middleware = reduxObservable();
const middleware = createEpicMiddleware();

const store = createStore(reducer, applyMiddleware(middleware));

Expand All @@ -58,7 +76,7 @@ describe('reduxObservable', () => {
it('should work dispatched functions that return a promise', (done) => {
const reducer = (state = [], action) => state.concat(action);

const middleware = reduxObservable();
const middleware = createEpicMiddleware();

const store = createStore(reducer, applyMiddleware(middleware));

Expand All @@ -79,7 +97,7 @@ describe('reduxObservable', () => {
it('should work with iterators/generators', (done) => {
const reducer = (state = [], action) => state.concat(action);

const middleware = reduxObservable();
const middleware = createEpicMiddleware();

const store = createStore(reducer, applyMiddleware(middleware));

Expand All @@ -102,7 +120,7 @@ describe('reduxObservable', () => {
it('should work with observablesque arguments', (done) => {
const reducer = (state = [], action) => state.concat(action);

const middleware = reduxObservable();
const middleware = createEpicMiddleware();

const store = createStore(reducer, applyMiddleware(middleware));

Expand Down Expand Up @@ -142,7 +160,7 @@ describe('reduxObservable', () => {
it('should emit POJO actions to the actions Subject', (done) => {
const reducer = (state = [], action) => state.concat(action);

const middleware = reduxObservable();
const middleware = createEpicMiddleware();

const store = createStore(reducer, applyMiddleware(middleware));

Expand Down Expand Up @@ -175,7 +193,7 @@ describe('reduxObservable', () => {
it('should store.dispatch onNext to allow async actions to emit other async actions', (done) => {
const reducer = (state = [], action) => state.concat(action);

const middleware = reduxObservable();
const middleware = createEpicMiddleware();

const store = createStore(reducer, applyMiddleware(middleware));

Expand Down
4 changes: 2 additions & 2 deletions test/typings.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { reduxObservable, ActionsObservable } from '../index';
import { createEpicMiddleware, ActionsObservable } from '../index';
import { Observable } from 'rxjs/Observable';

// should be a function
reduxObservable();
createEpicMiddleware();

// should be a constructor that returns an observable
const actionsSubject = Observable.create(() => {});
Expand Down

0 comments on commit 5cbcce4

Please sign in to comment.