redux-resource-plugins
Version:
Official plugins for Redux Resource
428 lines (305 loc) • 11.2 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('redux-resource')) :
typeof define === 'function' && define.amd ? define(['exports', 'redux-resource'], factory) :
(factory((global.ReduxResourcePlugins = {}),global.ReduxResource));
}(this, (function (exports,reduxResource) { 'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var defineProperty = function (obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
};
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;
};
var toConsumableArray = function (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);
}
};
// End actions can be failed, succeeded, or idle. Idle should be dispatched
// when the request is aborted (with a status code of 0).
var createEndActions = [reduxResource.actionTypes.CREATE_RESOURCES_FAILED, reduxResource.actionTypes.CREATE_RESOURCES_SUCCEEDED, reduxResource.actionTypes.CREATE_RESOURCES_IDLE];
var readEndActions = [reduxResource.actionTypes.READ_RESOURCES_FAILED, reduxResource.actionTypes.READ_RESOURCES_SUCCEEDED, reduxResource.actionTypes.READ_RESOURCES_IDLE];
var updateEndActions = [reduxResource.actionTypes.UPDATE_RESOURCES_FAILED, reduxResource.actionTypes.UPDATE_RESOURCES_SUCCEEDED, reduxResource.actionTypes.UPDATE_RESOURCES_IDLE];
var deleteEndActions = [reduxResource.actionTypes.DELETE_RESOURCES_FAILED, reduxResource.actionTypes.DELETE_RESOURCES_SUCCEEDED, reduxResource.actionTypes.DELETE_RESOURCES_IDLE];
// This sets a new meta property on resource and request metadata: `statusCode`.
// This will be equal to the last status code for a request
function httpStatusCodes(resourceType) {
return function (state, action) {
var typeToCheck = action.resourceType || action.resourceName;
if (typeToCheck !== resourceType) {
return state;
}
var isCreateEndAction = createEndActions.indexOf(action.type) !== -1;
var isReadEndAction = readEndActions.indexOf(action.type) !== -1;
var isUpdateEndAction = updateEndActions.indexOf(action.type) !== -1;
var isDeleteEndAction = deleteEndActions.indexOf(action.type) !== -1;
if (!isCreateEndAction && !isReadEndAction && !isUpdateEndAction && !isDeleteEndAction) {
return state;
}
var statusCode = typeof action.statusCode === 'number' ? action.statusCode : null;
var resources = action.resources;
var request = void 0;
var naiveKey = action.requestKey || action.request;
if (naiveKey && typeof naiveKey === 'string') {
request = naiveKey;
}
var newRequests = void 0,
newMeta = void 0,
idList = void 0;
if (resources) {
idList = resources.map(function (r) {
if ((typeof r === 'undefined' ? 'undefined' : _typeof(r)) === 'object') {
return r.id;
} else {
return r;
}
});
} else {
idList = [];
}
if (request) {
var existingRequest = state.requests[request] || {};
newRequests = _extends({}, state.requests, defineProperty({}, request, _extends({}, existingRequest, {
statusCode: statusCode
})));
} else {
newRequests = _extends({}, state.requests);
}
if (idList.length) {
var metaPrefix = void 0;
if (isCreateEndAction) {
metaPrefix = 'create';
} else if (isReadEndAction) {
metaPrefix = 'read';
} else if (isUpdateEndAction) {
metaPrefix = 'update';
} else if (isDeleteEndAction) {
metaPrefix = 'delete';
}
newMeta = reduxResource.setResourceMeta({
meta: state.meta,
newMeta: defineProperty({}, metaPrefix + 'StatusCode', statusCode),
resources: idList,
mergeMeta: true
});
} else {
newMeta = state.meta;
}
return _extends({}, state, {
requests: newRequests,
meta: newMeta
});
};
}
// This plugin adds support for "compound documents," or including multiple
// resource types in a single action.
function includedResources(resourceType) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return function (state, action) {
var initialResourceMeta = options.initialResourceMeta;
var includedResources = action.includedResources,
mergeMeta = action.mergeMeta,
mergeResources = action.mergeResources,
type = action.type;
var isReadType = type === reduxResource.actionTypes.READ_RESOURCES_SUCCEEDED;
var isCreateType = type === reduxResource.actionTypes.CREATE_RESOURCES_SUCCEEDED;
var isUpdateType = type === reduxResource.actionTypes.UPDATE_RESOURCES_SUCCEEDED;
if (!isReadType && !isCreateType && !isUpdateType) {
return state;
}
// If this action has no includedResources, then there is nothing to do
if (!includedResources) {
return state;
}
// If there are no included resources for this slice, then we do nothing
var includedResourceList = includedResources[resourceType];
if (!includedResourceList) {
return state;
}
var resources = reduxResource.upsertResources(state.resources, includedResourceList, mergeResources);
var newMeta = {
readStatus: reduxResource.requestStatuses.SUCCEEDED
};
if (isCreateType) {
newMeta.createStatus = reduxResource.requestStatuses.SUCCEEDED;
} else if (isUpdateType) {
newMeta.updateStatus = reduxResource.requestStatuses.SUCCEEDED;
}
var meta = reduxResource.setResourceMeta({
resources: includedResourceList,
meta: state.meta,
newMeta: newMeta,
initialResourceMeta: initialResourceMeta,
mergeMeta: mergeMeta
});
return _extends({}, state, {
meta: meta,
resources: resources
});
};
}
var actionTypes$1 = {
SELECT_RESOURCES: 'SELECT_RESOURCES',
DESELECT_RESOURCES: 'DESELECT_RESOURCES',
CLEAR_SELECTED_RESOURCES: 'CLEAR_SELECTED_RESOURCES'
};
var initialState = {
selectedIds: []
};
function selectResources(resourceType, resources) {
return {
type: actionTypes$1.SELECT_RESOURCES,
resourceType: resourceType,
resources: resources
};
}
function deselectResources(resourceType, resources) {
return {
type: actionTypes$1.DESELECT_RESOURCES,
resourceType: resourceType,
resources: resources
};
}
function clearSelectedResources(resourceType) {
return {
type: actionTypes$1.CLEAR_SELECTED_RESOURCES,
resourceType: resourceType
};
}
function selection(resourceType) {
return function (state, action) {
// Ignore actions that were dispatched for another resource type
var typeToUse = action.resourceType || action.resourceName;
if (typeToUse !== resourceType) {
return state;
}
var selectedIds = void 0,
resourceIds = void 0;
var resources = action.resources || [];
if (action.type === actionTypes$1.SELECT_RESOURCES) {
selectedIds = [].concat(toConsumableArray(state.selectedIds)) || [];
resourceIds = resources.map(function (r) {
return (typeof r === 'undefined' ? 'undefined' : _typeof(r)) === 'object' ? r.id : r;
});
var selectedIdsSet = new Set(selectedIds);
resourceIds.forEach(function (id) {
if (!selectedIdsSet.has(id)) {
selectedIds.push(id);
}
});
return _extends({}, state, {
selectedIds: selectedIds
});
} else if (action.type === actionTypes$1.DESELECT_RESOURCES) {
selectedIds = [].concat(toConsumableArray(state.selectedIds)) || [];
resourceIds = resources.map(function (r) {
return (typeof r === 'undefined' ? 'undefined' : _typeof(r)) === 'object' ? r.id : r;
});
var resourceIdsSet = new Set(resourceIds);
return _extends({}, state, {
selectedIds: selectedIds.filter(function (id) {
return !resourceIdsSet.has(id);
})
});
} else if (action.type === actionTypes$1.CLEAR_SELECTED_RESOURCES) {
return _extends({}, state, {
selectedIds: []
});
}
return state;
};
}
selection.actionTypes = actionTypes$1;
selection.selectResources = selectResources;
selection.deselectResources = deselectResources;
selection.clearSelectedResources = clearSelectedResources;
selection.initialState = initialState;
var actionTypes$2 = {
RESET_RESOURCE: 'RESET_RESOURCE'
};
function resetResource(resourceType) {
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
request = _ref.request,
requestKey = _ref.requestKey,
list = _ref.list;
return {
type: 'RESET_RESOURCE',
resourceType: resourceType,
request: request,
requestKey: requestKey,
list: list
};
}
function reset(resourceType) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return function (state, action) {
var typeToUse = action.resourceType || action.resourceName;
if (action.type !== actionTypes$2.RESET_RESOURCE || typeToUse !== resourceType) {
return state;
}
var request = action.request,
requestKey = action.requestKey,
list = action.list;
var keyToUse = requestKey || request;
if (!keyToUse && !list) {
return _extends({
resources: {},
meta: {},
lists: {},
requests: {}
}, options.initialState);
}
var newState = _extends({}, state);
if (keyToUse) {
var existingRequest = state.requests[keyToUse];
var requestName = existingRequest && existingRequest.requestName;
var newRequest = {
resourceType: typeToUse,
requestKey: keyToUse,
ids: [],
status: reduxResource.requestStatuses.IDLE
};
if (requestName) {
newRequest.requestName = requestName;
}
newState.requests = _extends({}, state.requests, defineProperty({}, keyToUse, newRequest));
}
if (list) {
newState.lists = _extends({}, state.lists, defineProperty({}, list, []));
}
return newState;
};
}
reset.actionTypes = actionTypes$2;
reset.resetResource = resetResource;
exports.httpStatusCodes = httpStatusCodes;
exports.selection = selection;
exports.reset = reset;
exports.includedResources = includedResources;
Object.defineProperty(exports, '__esModule', { value: true });
})));