Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

redux-toolbelt-saga

Package Overview
Dependencies
Maintainers
2
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

redux-toolbelt-saga - npm Package Compare versions

Comparing version 1.0.10 to 2.0.0

CHANGELOG.md

101

lib/makeAsyncSaga.js

@@ -10,17 +10,21 @@ 'use strict';

var _marked3 = /*#__PURE__*/regeneratorRuntime.mark(getArgs);
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
/**
* @param {AsyncActionCreator} asyncActionCreator
* @param {function} fn
* @param {...*} [args]
* @param options? = {mapArgs?, args?})
*
* @returns {Function}
*/
function makeAsyncSaga(asyncActionCreator, fn) {
for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
args[_key - 2] = arguments[_key];
}
var _marked = /*#__PURE__*/regeneratorRuntime.mark(exec),
_marked2 = /*#__PURE__*/regeneratorRuntime.mark(waitFor);
function exec() {
var result;
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
function exec(action) {
var args, result;
return regeneratorRuntime.wrap(function exec$(_context) {

@@ -30,22 +34,36 @@ while (1) {

case 0:
_context.prev = 0;
_context.next = 3;
return _effects.call.apply(undefined, [fn].concat(args));
_context.next = 2;
return getArgs(action, options);
case 3:
case 2:
args = _context.sent;
if (Array.isArray(args)) {
_context.next = 5;
break;
}
throw new Error('makeAsyncSaga expected an array of args, instead got: ' + args);
case 5:
_context.prev = 5;
_context.next = 8;
return _effects.call.apply(undefined, [fn].concat(_toConsumableArray(args)));
case 8:
result = _context.sent;
_context.next = 6;
_context.next = 11;
return (0, _effects.put)(asyncActionCreator.success(result));
case 6:
_context.next = 12;
case 11:
_context.next = 17;
break;
case 8:
_context.prev = 8;
_context.t0 = _context['catch'](0);
_context.next = 12;
case 13:
_context.prev = 13;
_context.t0 = _context['catch'](5);
_context.next = 17;
return (0, _effects.put)(asyncActionCreator.failure(_context.t0));
case 12:
case 17:
case 'end':

@@ -55,3 +73,3 @@ return _context.stop();

}
}, _marked, this, [[0, 8]]);
}, _marked, this, [[5, 13]]);
}

@@ -76,2 +94,45 @@

return waitFor;
}
function getArgs(action, options) {
return regeneratorRuntime.wrap(function getArgs$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
if (!options.mapArgs) {
_context3.next = 4;
break;
}
_context3.next = 3;
return options.mapArgs(action);
case 3:
return _context3.abrupt('return', _context3.sent);
case 4:
if (!options.args) {
_context3.next = 6;
break;
}
return _context3.abrupt('return', options.args);
case 6:
if (!action.payload) {
_context3.next = 8;
break;
}
return _context3.abrupt('return', [action.payload]);
case 8:
return _context3.abrupt('return', []);
case 9:
case 'end':
return _context3.stop();
}
}
}, _marked3, this);
}

2

package.json
{
"name": "redux-toolbelt-saga",
"version": "1.0.10",
"version": "2.0.0",
"description": "Saga helpers for redux-toolbelt",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -50,4 +50,2 @@ # redux-toolbelt-saga

Other arguments are passed to the function when it is run.
```js

@@ -57,5 +55,31 @@ const fetchTodos = makeAsyncActionCreator('FETCH_TODOS')

// Returns promise
const fetchTodosFromServer = () => {/*...*/}
const fetchTodosFromServer = ({id, url}, debug = false) => {/*...*/}
const saga = makeAsyncSaga(fetchTodos, fetchTodosFromServer)
//...
dispatch(fetchTodos({id: 100, url: 'http://google.com'}))
```
By default, the payload of the action is what passed to the function as it's argument.
You have two ways of changing it, using `options`:
```js
const options = {
// pass specific arguments
args: [{id, url}],
// OR
// map the action to arguments using a regular or a generator function
mapArgs: function* mapArgs(action){
const {todosId} = action.payload
const url = yield select(urlSelector)
return [{id: todosId, url}, true]
}
}
const saga = makeAsyncSaga(fetchTodos, fetchTodosFromServer, options)
```

@@ -6,6 +6,14 @@ import { call, put, takeLatest } from 'redux-saga/effects'

* @param {function} fn
* @param {...*} [args]
* @param options? = {mapArgs?, args?})
*
* @returns {Function}
*/
export default function makeAsyncSaga(asyncActionCreator, fn, ...args){
function* exec(){
export default function makeAsyncSaga(asyncActionCreator, fn, options = {}){
function* exec(action){
const args = yield getArgs(action, options)
if(!Array.isArray(args)){
throw new Error(`makeAsyncSaga expected an array of args, instead got: ${args}`)
}
try {

@@ -26,1 +34,18 @@ const result = yield call(fn, ...args)

}
function* getArgs(action, options){
if (options.mapArgs){
return yield options.mapArgs(action)
}
if (options.args){
return options.args
}
if (action.payload){
return [action.payload]
}
return []
}
import 'babel-polyfill'
import {makeAsyncActionCreator} from '../../redux-toolbelt/src'
import {makeAsyncSaga} from '../src'
import { makeAsyncActionCreator } from '../../redux-toolbelt/src'
import { makeAsyncSaga } from '../src'
import { select } from 'redux-saga/effects'
import createSagaMiddleware from 'redux-saga'
import configureMockStore from 'redux-mock-store'
function createStoreForTest(mySaga) {
function createStoreForTest(mySaga, initialState = {}) {
const sagaMiddleware = createSagaMiddleware()
const mockStore = configureMockStore([sagaMiddleware])
const store = mockStore()
const store = mockStore(initialState)
sagaMiddleware.run(mySaga)

@@ -17,47 +19,128 @@ return store

function mockRequest({shouldReject = false} = {}){
return Promise.resolve().then(() => {
if(shouldReject){
throw 'some error'
function mockRequest(...args){
return new Promise((resolve, reject) => {
if(args[0] === 'fail'){
reject('failed!')
}
return { 'dummy': 'object' }
else{
resolve(args)
}
})
}
test('saga dispatches success actions for a successful request', done => {
describe('saga dispatches success actions for a successful request', () => {
test('with no args', done => {
const requestActionCreator = makeAsyncActionCreator('REQUEST')
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest)
const requestActionCreator = makeAsyncActionCreator('REQUEST')
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest)
const store = createStoreForTest(mySaga)
store.dispatch(requestActionCreator())
const store = createStoreForTest(mySaga)
store.dispatch(requestActionCreator())
setImmediate(() => {
const actualActions = store.getActions()
expect(actualActions).toEqual([
requestActionCreator(),
requestActionCreator.success([]),
])
done()
})
})
setTimeout(() => {
expect(store.getActions()).toEqual([
requestActionCreator(),
requestActionCreator.success({ 'dummy': 'object' }),
])
test('with args', done => {
const requestActionCreator = makeAsyncActionCreator('REQUEST')
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest)
done()
const store = createStoreForTest(mySaga)
store.dispatch(requestActionCreator('some-arg'))
setImmediate(() => {
const actualActions = store.getActions()
expect(actualActions).toEqual([
requestActionCreator('some-arg'),
requestActionCreator.success(['some-arg']),
])
done()
})
})
test('with pre-set args', done => {
const requestActionCreator = makeAsyncActionCreator('REQUEST')
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest, {
args: ['preset-arg'],
})
const store = createStoreForTest(mySaga)
store.dispatch(requestActionCreator('some-arg'))
setImmediate(() => {
const actualActions = store.getActions()
expect(actualActions).toEqual([
requestActionCreator('some-arg'),
requestActionCreator.success(['preset-arg']),
])
done()
})
})
test('with simple args mapping', done => {
const requestActionCreator = makeAsyncActionCreator('REQUEST')
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest, {
mapArgs: () => ['mapped-arg'],
})
const store = createStoreForTest(mySaga)
store.dispatch(requestActionCreator('some-arg'))
setImmediate(() => {
const actualActions = store.getActions()
expect(actualActions).toEqual([
requestActionCreator('some-arg'),
requestActionCreator.success(['mapped-arg']),
])
done()
})
})
test('with complex args mapping', done => {
const initialState = {
arg0: 'arg0',
}
const requestActionCreator = makeAsyncActionCreator('REQUEST')
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest, {
mapArgs: function* (action){
const state = yield select()
return [state.arg0, action.payload.arg1]
},
})
const store = createStoreForTest(mySaga, initialState)
store.dispatch(requestActionCreator({arg1: 'arg1'}))
setImmediate(() => {
const actualActions = store.getActions()
expect(actualActions).toEqual([
requestActionCreator({arg1: 'arg1'}),
requestActionCreator.success(['arg0', 'arg1']),
])
done()
})
})
})
test('saga dispatches failure actions for a successful request', done => {
test('saga dispatches failure actions for a failed request', done => {
const requestActionCreator = makeAsyncActionCreator('REQUEST')
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest, {shouldReject: true})
const mySaga = makeAsyncSaga(requestActionCreator, mockRequest)
const store = createStoreForTest(mySaga)
store.dispatch(requestActionCreator())
store.dispatch(requestActionCreator('fail'))
setTimeout(() => {
expect(store.getActions()).toEqual([
requestActionCreator(),
requestActionCreator.failure('some error'),
setImmediate(() => {
const actualActions = store.getActions()
expect(actualActions).toEqual([
requestActionCreator('fail'),
requestActionCreator.failure('failed!'),
])
done()
})
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc