redux-supermodel
Advanced tools
Comparing version 0.14.0 to 0.15.0
@@ -99,2 +99,6 @@ 'use strict'; | ||
memo[action] = function (inputData) { | ||
if (inputData && inputData.nativeEvent) { | ||
inputData = undefined; | ||
} | ||
var requestUrl = getResourceUrl(inputData); | ||
@@ -101,0 +105,0 @@ |
@@ -17,2 +17,6 @@ 'use strict'; | ||
function getPreviousData(previous) { | ||
return previous && previous.data && previous.data.slice(0) || []; | ||
} | ||
function collectionTransform(payload, previous, isFulfilled) { | ||
@@ -23,61 +27,54 @@ var meta = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; | ||
var getPreviousData = function getPreviousData() { | ||
return previous && previous.data && previous.data.slice(0) || []; | ||
}; | ||
switch (action) { | ||
case 'create': | ||
{ | ||
if (!isFulfilled) { | ||
return previous; | ||
} | ||
function create() { | ||
if (!isFulfilled) return previous; | ||
var data = getPreviousData(); | ||
data.push(payload.data); | ||
var data = getPreviousData(previous); | ||
data.push(payload.data); | ||
return _extends({}, previous, { data: data }); | ||
} | ||
case 'update': | ||
{ | ||
if (!isFulfilled) { | ||
return previous; | ||
} | ||
return _extends({}, previous, { data: data }); | ||
} | ||
if (!inputData) { | ||
return previous; | ||
} | ||
function update() { | ||
if (!isFulfilled || !inputData) return previous; | ||
var _data = getPreviousData(); | ||
var index = (0, _findIndex2.default)(_data, function (x) { | ||
return x.id === inputData.id; | ||
}); | ||
if (index >= 0) { | ||
_data[index] = _extends({}, _data[index], payload.data); | ||
} | ||
var data = getPreviousData(previous); | ||
var index = (0, _findIndex2.default)(data, function (x) { | ||
return x.id === inputData.id; | ||
}); | ||
if (index >= 0) { | ||
data[index] = _extends({}, data[index], payload.data); | ||
} | ||
return _extends({}, payload, { data: _data }); | ||
} | ||
case 'destroy': | ||
{ | ||
if (!inputData) { | ||
return previous; | ||
} | ||
return _extends({}, payload, { data: data }); | ||
} | ||
var _data2 = getPreviousData(); | ||
if (isFulfilled) { | ||
_data2 = _data2.filter(function (x) { | ||
return x.id !== inputData.id; | ||
}); | ||
return _extends({}, payload, { data: _data2 }); | ||
} | ||
function destroy() { | ||
if (!inputData) return previous; | ||
var _index = (0, _findIndex2.default)(_data2, function (x) { | ||
return x.id === inputData.id; | ||
}); | ||
if (_index >= 0) { | ||
_data2[_index] = _extends({}, _data2[_index], { pendingDelete: true }); | ||
} | ||
var data = getPreviousData(previous); | ||
if (isFulfilled) { | ||
data = data.filter(function (x) { | ||
return x.id !== inputData.id; | ||
}); | ||
return _extends({}, payload, { data: data }); | ||
} | ||
return _extends({}, previous, { data: _data2 }); | ||
} | ||
var index = (0, _findIndex2.default)(data, function (x) { | ||
return x.id === inputData.id; | ||
}); | ||
if (index >= 0) { | ||
data[index] = _extends({}, data[index], { pendingDelete: true }); | ||
} | ||
return _extends({}, previous, { data: data }); | ||
} | ||
switch (action) { | ||
case 'create': | ||
return create(); | ||
case 'update': | ||
return update(); | ||
case 'destroy': | ||
return destroy(); | ||
default: | ||
@@ -84,0 +81,0 @@ return isFulfilled ? payload : previous; |
@@ -30,5 +30,3 @@ 'use strict'; | ||
if (!resource || !resource.initialized) { | ||
return _defineProperty({ | ||
payload: defaultPayload | ||
}, _metaTag, true); | ||
return _defineProperty({ payload: defaultPayload }, _metaTag, true); | ||
} | ||
@@ -35,0 +33,0 @@ |
@@ -27,91 +27,103 @@ 'use strict'; | ||
function reducer() { | ||
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState; | ||
var _ref = arguments[1]; | ||
var type = _ref.type, | ||
payload = _ref.payload, | ||
meta = _ref.meta; | ||
function reset(state, action) { | ||
var payload = action.payload, | ||
meta = action.meta; | ||
if (!type || !type.startsWith(types.PREFIX)) { | ||
return state; | ||
if (payload === undefined) { | ||
var newState = _extends({}, state); | ||
delete newState[meta.resourceName]; | ||
return newState; | ||
} | ||
if (type === types.NUKE) return {}; | ||
var resource = { initialized: true, busy: false, payload: payload, previous: null, meta: meta }; | ||
return _extends({}, state, _defineProperty({}, meta.resourceName, resource)); | ||
} | ||
if (!meta || !meta.resourceName) { | ||
throw new Error('Invalid ' + type + ': Missing "meta.resourceName" property'); | ||
} | ||
function pending(state, action) { | ||
var payload = action.payload, | ||
meta = action.meta; | ||
switch (type) { | ||
case types.RESET: | ||
{ | ||
if (payload === undefined) { | ||
var newState = _extends({}, state); | ||
delete newState[meta.resourceName]; | ||
return newState; | ||
} | ||
var previous = state[meta.resourceName] && state[meta.resourceName].payload; | ||
var transformer = function transformer(fn, val) { | ||
return fn(val, previous, false, meta); | ||
}; | ||
var transforms = meta.definition.transform || _defaultTransform2.default; | ||
var transformedPayload = Array.isArray(transforms) ? transforms.reduce(function (memo, transform) { | ||
return transformer(transform, memo); | ||
}, payload) : transformer(transforms, payload); | ||
var resource = { initialized: true, busy: false, payload: payload, previous: null, meta: meta }; | ||
return _extends({}, state, _defineProperty({}, meta.resourceName, resource)); | ||
} | ||
var resource = { | ||
initialized: true, | ||
busy: true, | ||
payload: transformedPayload, | ||
previous: previous, | ||
meta: meta | ||
}; | ||
case types.PENDING: | ||
{ | ||
var previous = state[meta.resourceName] && state[meta.resourceName].payload; | ||
var transformer = function transformer(fn, val) { | ||
return fn(val, previous, false, meta); | ||
}; | ||
var transforms = meta.definition.transform || _defaultTransform2.default; | ||
var transformedPayload = Array.isArray(transforms) ? transforms.reduce(function (memo, transform) { | ||
return transformer(transform, memo); | ||
}, payload) : transformer(transforms, payload); | ||
return _extends({}, state, _defineProperty({}, meta.resourceName, resource)); | ||
} | ||
var _resource = { | ||
initialized: true, | ||
busy: true, | ||
payload: transformedPayload, | ||
previous: previous, | ||
meta: meta | ||
}; | ||
function fulfilled(state, action) { | ||
var meta = action.meta, | ||
payload = action.payload; | ||
return _extends({}, state, _defineProperty({}, meta.resourceName, _resource)); | ||
} | ||
var previousState = state[meta.resourceName]; | ||
var transformer = function transformer(fn, val) { | ||
return fn(val, previousState.payload, true, meta); | ||
}; | ||
var transforms = meta.definition.transform || _defaultTransform2.default; | ||
var transformedPayload = Array.isArray(transforms) ? transforms.reduce(function (memo, transform) { | ||
return transformer(transform, memo); | ||
}, payload) : transformer(transforms, payload); | ||
case types.FULFILLED: | ||
{ | ||
var previousState = state[meta.resourceName]; | ||
var _transformer = function _transformer(fn, val) { | ||
return fn(val, previousState.payload, true, meta); | ||
}; | ||
var _transforms = meta.definition.transform || _defaultTransform2.default; | ||
var _transformedPayload = Array.isArray(_transforms) ? _transforms.reduce(function (memo, transform) { | ||
return _transformer(transform, memo); | ||
}, payload) : _transformer(_transforms, payload); | ||
var resource = { | ||
initialized: true, | ||
busy: false, | ||
payload: transformedPayload, | ||
previous: null, | ||
meta: meta | ||
}; | ||
var _resource2 = { | ||
initialized: true, | ||
busy: false, | ||
payload: _transformedPayload, | ||
previous: null, | ||
meta: meta | ||
}; | ||
return _extends({}, state, _defineProperty({}, meta.resourceName, resource)); | ||
} | ||
return _extends({}, state, _defineProperty({}, meta.resourceName, _resource2)); | ||
} | ||
function rejected(state, action) { | ||
var meta = action.meta, | ||
payload = action.payload; | ||
case types.REJECTED: | ||
{ | ||
var _previousState = state[meta.resourceName]; | ||
var _resource3 = { | ||
initialized: true, | ||
busy: false, | ||
payload: _previousState.payload, | ||
previous: null, | ||
error: payload, | ||
meta: meta | ||
}; | ||
var previousState = state[meta.resourceName]; | ||
var resource = { | ||
initialized: true, | ||
busy: false, | ||
payload: previousState.payload, | ||
previous: null, | ||
error: payload, | ||
meta: meta | ||
}; | ||
return _extends({}, state, _defineProperty({}, meta.resourceName, _resource3)); | ||
} | ||
return _extends({}, state, _defineProperty({}, meta.resourceName, resource)); | ||
} | ||
function reducer() { | ||
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState; | ||
var action = arguments[1]; | ||
var type = action.type, | ||
meta = action.meta; | ||
if (!type || !type.startsWith(types.PREFIX)) return state; | ||
if (type === types.NUKE) return {}; | ||
if (!meta || !meta.resourceName) { | ||
throw new Error('Invalid ' + type + ': Missing "meta.resourceName" property'); | ||
} | ||
switch (type) { | ||
case types.RESET: | ||
return reset(state, action); | ||
case types.PENDING: | ||
return pending(state, action); | ||
case types.FULFILLED: | ||
return fulfilled(state, action); | ||
case types.REJECTED: | ||
return rejected(state, action); | ||
default: | ||
@@ -118,0 +130,0 @@ throw new Error('Unrecognized action type: ' + type); |
@@ -7,6 +7,7 @@ "use strict"; | ||
exports.default = findIndex; | ||
var identity = function identity(x) { | ||
return x; | ||
}; | ||
function findIndex(arr) { | ||
var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function (x) { | ||
return x; | ||
}; | ||
var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : identity; | ||
@@ -13,0 +14,0 @@ if (!arr) { |
{ | ||
"name": "redux-supermodel", | ||
"version": "0.14.0", | ||
"version": "0.15.0", | ||
"description": "A package of action creator functions and reducers that deal with the state management of REST-like APIs for you... all you need is a URL!", | ||
@@ -5,0 +5,0 @@ "repository": "https://github.com/MrLeebo/redux-supermodel", |
# redux-supermodel | ||
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/13429c5aaf274e1189e839675cb31969)](https://www.codacy.com/app/MrLeebo/redux-supermodel?utm_source=github.com&utm_medium=referral&utm_content=MrLeebo/redux-supermodel&utm_campaign=badger) [![Build Status](https://travis-ci.org/MrLeebo/redux-supermodel.svg?branch=master)](https://travis-ci.org/MrLeebo/redux-supermodel) [![dependencies Status](https://david-dm.org/MrLeebo/redux-supermodel/status.svg)](https://david-dm.org/MrLeebo/redux-supermodel) [![devDependencies Status](https://david-dm.org/MrLeebo/redux-supermodel/dev-status.svg)](https://david-dm.org/MrLeebo/redux-supermodel?type=dev) | ||
[![BCH compliance](https://bettercodehub.com/edge/badge/MrLeebo/redux-supermodel?branch=master)](https://bettercodehub.com/) | ||
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/13429c5aaf274e1189e839675cb31969)](https://www.codacy.com/app/MrLeebo/redux-supermodel?utm_source=github.com&utm_medium=referral&utm_content=MrLeebo/redux-supermodel&utm_campaign=badger) | ||
[![Build Status](https://travis-ci.org/MrLeebo/redux-supermodel.svg?branch=master)](https://travis-ci.org/MrLeebo/redux-supermodel) | ||
[![dependencies Status](https://david-dm.org/MrLeebo/redux-supermodel/status.svg)](https://david-dm.org/MrLeebo/redux-supermodel) | ||
[![devDependencies Status](https://david-dm.org/MrLeebo/redux-supermodel/dev-status.svg)](https://david-dm.org/MrLeebo/redux-supermodel?type=dev) | ||
@@ -52,3 +56,3 @@ Streamline the effort it takes for you to communicate between your [Redux](http://redux.js.org/) Store and a REST-like API. This is a package of action creator functions and reducers built with [axios](https://github.com/mzabriskie/axios) and [redux-promise-middleware](https://github.com/pburtchaell/redux-promise-middleware) that handle the resource state management for you... all you need is a URL! | ||
```js | ||
```jsx | ||
// MyComponent.js | ||
@@ -60,6 +64,7 @@ | ||
function MyComponent ({ready, error, title, body, fetchPost}) { | ||
export function MyComponent (props) { | ||
const { ready, error, title, body, fetchPost } = props | ||
if (!ready) return <div className="loading">Loading...</div> | ||
if (error) return <div className="error">{error}</div> | ||
if (error) return <div className="error">{error.message}</div> | ||
return ( | ||
@@ -71,3 +76,3 @@ <div> | ||
</div> | ||
<button type="button" onClick={() => fetchPost()}>Refresh</button> | ||
<button type="button" onClick={fetchPost}>Refresh</button> | ||
</div> | ||
@@ -77,37 +82,14 @@ ) | ||
export function mergeProps (stateProps, dispatchProps, ownProps) { | ||
const { | ||
ready, | ||
error, | ||
payload | ||
} = stateProps.post | ||
const err = error && error.response && error.response.data | ||
const data = payload && payload.data | ||
// The stateProps parameter can get rather large and have lots of unwieldy data structures, | ||
// use mergeProps as an opportunity to be a bit selective and only return the stateProps | ||
// values that you are going to use in your component. | ||
// | ||
// The same advice also applies to dispatchProps and ownProps, to a lesser extent, its not as | ||
// important to do so in those cases because A) you will already be defining ownProps | ||
// somewhere else in your app and B) the `bindResource` higher-order component will dispatch | ||
// some callbacks on your behalf (by default `fetchAll()` on mount and `resetAll()` on unmount) | ||
return { | ||
...ownProps, | ||
...dispatchProps, | ||
ready, | ||
error: err && err.message, | ||
title: data && data.title, | ||
body: data && data.body | ||
} | ||
export function mapProps (state) { | ||
const { ready, error, payload } = post(state) | ||
const { data: { title, body } = {} } = payload | ||
return { ready, error, title, body } | ||
} | ||
const resources = { post } | ||
export default bindResource(resources, { mergeProps })(MyComponent) | ||
export default bindResource({post}, {mapProps})(MyComponent) | ||
``` | ||
The advice offered by this [blog post](https://goshakkk.name/redux-antipattern-mapstatetoprops/) is about mapStateToProps, but it applies to how we are using mergeProps here. | ||
The payload can be a massive object containing lots of information about the HTTP request and response, most of which you aren't going to need when you're rendering your component, so I suggest using the `mapProps` call to simplify the payload to just the stuff you're going to need. Try to avoid using payload directly. Check out this [blog post](https://goshakkk.name/redux-antipattern-mapstatetoprops/) for further reading. | ||
For details on mergeProps, read the [react-redux connect()](https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) documentation. | ||
For details on mapProps, read the [react-redux connect()](https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) documentation. | ||
@@ -114,0 +96,0 @@ For the full list of options, see [bindResource](docs/bindResource.md). |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
18
642
0
37743
2
114