UNPKG

redux-observable-sans

Version:
150 lines (119 loc) 5.61 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.httpAction = exports.httpEpic = exports.createType = exports.rpcFailure = exports.rpcSuccess = exports.rpcRequest = undefined; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; require('whatwg-fetch'); var _reduxObservable = require('redux-observable'); var _rxjs = require('rxjs'); var _operators = require('rxjs/operators'); function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } // fetch does not throw on anything but network errors // thus status needs to be passed down along with body var responseToJson = function responseToJson(response) { return response.json().then(function (cleanJson) { return { code: response.status, body: cleanJson }; }); }; // check kind of response by code // then return stream of success actions or stream of failure actions // in case of 401, then failure stream includes action.type === `UNAUTHORIZED` var mapResponseToSuccessOrFailureStream = function mapResponseToSuccessOrFailureStream(type, url, httpType) { return function (response) { console.error('response =', response); if (response.code >= 200 && response.code < 300) { return (0, _rxjs.from)([rpcSuccess(type)(response.body)]); } return (0, _rxjs.from)(rpcFailure(type, url, httpType)(response)); }; }; // action creators var rpcRequest = exports.rpcRequest = function rpcRequest(type) { return function (payload) { return { type: type + '_REQUEST', payload: payload }; }; }; var rpcSuccess = exports.rpcSuccess = function rpcSuccess(type) { return function (payload) { return { type: type + '_SUCCESS', payload: payload }; }; }; var rpcFailure = exports.rpcFailure = function rpcFailure(type, url, httpType) { return function (response) { return [{ type: type + '_FAILURE', payload: _extends({ error: true, message: response.message }, response && response.xhr ? response.xhr.response : response.body) }, { type: response && response.code === 401 ? httpType + '_UNAUTHORIZED' : httpType + '_ERROR', payload: _extends({ url: url, error: true, message: response.message || response.body && response.body.message }, response) }]; }; }; var createType = exports.createType = function createType(id) { return 'HTTP' + (id ? '_' + id : ''); }; // Race between the AJAX call and an EPIC_END. // If the EPIC_END, emit a cancel action to // put the store in the correct state // This is needed for hot reloading var httpEpic = function httpEpic() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var preUrl = !options.url ? '/' : options.url[options.url.length] === '/' ? options.url : options.url + '/'; var setHeaders = typeof options.setHeaders === 'function' ? options.setHeaders : function () { return {}; }; var httpType = createType(options.id); return function (action$, state$, deps) { return action$.pipe((0, _reduxObservable.ofType)(httpType), (0, _operators.mergeMap)(function (_ref) { var payload = _ref.payload; var rawBody = payload.body, postUrl = payload.url, type = payload.type, settings = _objectWithoutProperties(payload, ['body', 'url', 'type']); var headers = _extends({ Accept: 'application/json', 'Content-Type': 'application/json' }, setHeaders(state$, deps)); var options = _extends({ headers: headers }, settings); var body = rawBody && typeof rawBody.toJS === 'function' ? rawBody.toJS() // handle immutable : rawBody; if (body && ['POST', 'PATCH', 'PUT'].some(function (method) { return method === settings.method; })) options.body = JSON.stringify(body); var url = preUrl + (typeof postUrl === 'function' ? postUrl(payload.body) : postUrl || ''); var reqAction$ = (0, _rxjs.from)([rpcRequest(type)(_extends({ url: url }, settings, { body: body }))]); console.error('options =', options); var sideEffect$ = (0, _rxjs.from)(fetch(url, options).then(responseToJson)).pipe((0, _operators.mergeMap)(mapResponseToSuccessOrFailureStream(type, url, httpType)), (0, _operators.takeUntil)(action$.ofType(type + '_CANCELLED')), (0, _operators.catchError)(function (err) { return (0, _rxjs.from)(rpcFailure(type, url, httpType)(err)); })); var hotReloading$ = action$.pipe((0, _reduxObservable.ofType)('EPIC_END'), (0, _operators.mapTo)({ type: type + '_CANCELLED' }), (0, _operators.take)(1)); return (0, _rxjs.merge)(reqAction$, (0, _rxjs.race)(sideEffect$, hotReloading$)); })); }; }; exports.httpEpic = httpEpic; var httpAction = exports.httpAction = function httpAction(dispatch, id) { return function (type, url) { var method = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'GET'; var settings = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; return function (body) { return dispatch({ type: createType(id), payload: _extends({ type: type, url: url, method: method }, settings, { body: body }) }); }; }; };