@gjv/redux-slice-factory
Version:
Generic factory functions for common slice data structures
426 lines (370 loc) • 14.9 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var toolkit = require('@reduxjs/toolkit');
var merge = _interopDefault(require('lodash.merge'));
/**
* @public
*/
var StatusEnum;
(function (StatusEnum) {
StatusEnum["Settled"] = "Settled";
StatusEnum["Requesting"] = "Requesting";
StatusEnum["Failed"] = "Failed";
})(StatusEnum || (StatusEnum = {}));
var StatusEnum$1 = StatusEnum;
function _extends() {
_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;
};
return _extends.apply(this, arguments);
}
var create = function create(args) {
var _args$status, _args$error, _args$lastModified, _args$lastHydrated;
if (args === void 0) {
args = {};
}
return {
status: (_args$status = args.status) != null ? _args$status : StatusEnum$1.Settled,
error: (_args$error = args.error) != null ? _args$error : null,
lastModified: (_args$lastModified = args.lastModified) != null ? _args$lastModified : null,
lastHydrated: (_args$lastHydrated = args.lastHydrated) != null ? _args$lastHydrated : null
};
};
/**
* @public
*/
var MetaState = {
create: create
};
var create$1 = function create(args) {
var _args$ids, _args$entities;
if (args === void 0) {
args = {};
}
var metaState = MetaState.create(args);
return _extends({}, metaState, {
ids: (_args$ids = args.ids) != null ? _args$ids : [],
entities: (_args$entities = args.entities) != null ? _args$entities : {}
});
};
/**
* @public
*/
var EntityState = {
create: create$1
};
/**
* @internal
*/
var getISOString = function getISOString(dateTime) {
if (dateTime === void 0) {
dateTime = new Date();
}
return dateTime.toISOString();
};
/**
* @public
*/
function createEntitySlice(options) {
var defaultCanRequestSelector = function defaultCanRequestSelector(sliceState) {
return sliceState.status !== StatusEnum$1.Requesting && sliceState.error === null && sliceState.lastModified === null;
};
var defaultShouldRequestSelector = function defaultShouldRequestSelector(sliceState, canRequest) {
return canRequest && sliceState.lastHydrated === null;
};
var name = options.name,
selectId = options.selectId,
sortComparer = options.sortComparer,
selectSliceState = options.selectSliceState,
_options$selectShould = options.selectShouldRequest,
selectShouldRequest = _options$selectShould === void 0 ? defaultShouldRequestSelector : _options$selectShould,
_options$selectCanReq = options.selectCanRequest,
selectCanRequest = _options$selectCanReq === void 0 ? defaultCanRequestSelector : _options$selectCanReq,
_options$initialState = options.initialState,
initialState = _options$initialState === void 0 ? {} : _options$initialState,
_options$createTimest = options.createTimestamp,
createTimestamp = _options$createTimest === void 0 ? getISOString : _options$createTimest; // intentional, necessary with immer
/* eslint-disable no-param-reassign */
var setEntityState = function setEntityState(state, entityState) {
state.ids = entityState.ids;
state.entities = entityState.entities;
};
var _setError = function setError(state, error) {
state.error = error === null ? null : error;
};
var _setStatus = function setStatus(state, status) {
state.status = status;
};
var setLastModified = function setLastModified(state, lastModified) {
state.lastModified = lastModified;
};
var setLastHydrated = function setLastHydrated(state, lastHydrated) {
state.lastHydrated = lastHydrated;
};
/* eslint-enable no-param-reassign */
var modifyState = function modifyState(state, entityState) {
setEntityState(state, entityState); // TODO: should not have a side effect: https://redux.js.org/style-guide/style-guide#reducers-must-not-have-side-effects
setLastModified(state, createTimestamp());
};
var hydrateState = function hydrateState(state, entityState) {
setEntityState(state, entityState);
setLastModified(state, null); // TODO: should not have a side effect: https://redux.js.org/style-guide/style-guide#reducers-must-not-have-side-effects
setLastHydrated(state, createTimestamp());
};
var entityAdapter = toolkit.createEntityAdapter({
selectId: selectId,
sortComparer: sortComparer
});
var initialEntityState = entityAdapter.getInitialState(initialState);
var initialSliceState = EntityState.create(initialEntityState);
/* eslint-disable no-param-reassign */
var slice = toolkit.createSlice({
name: name,
initialState: initialSliceState,
reducers: {
addOne: function addOne(state, action) {
var newEntityState = entityAdapter.addOne(state, action.payload);
modifyState(state, newEntityState);
},
addMany: function addMany(state, action) {
var newEntityState = entityAdapter.addMany(state, action.payload);
modifyState(state, newEntityState);
},
hydrateOne: function hydrateOne(state, action) {
var newEntityState = entityAdapter.upsertOne(state, action.payload);
hydrateState(state, newEntityState);
},
hydrateMany: function hydrateMany(state, action) {
var newEntityState = entityAdapter.upsertMany(state, action.payload);
hydrateState(state, newEntityState);
},
hydrateAll: function hydrateAll(state, action) {
var newEntityState = entityAdapter.setAll(state, action.payload);
hydrateState(state, newEntityState);
},
updateOne: function updateOne(state, action) {
var newEntityState = entityAdapter.updateOne(state, action.payload);
modifyState(state, newEntityState);
},
updateMany: function updateMany(state, action) {
var newEntityState = entityAdapter.updateMany(state, action.payload);
modifyState(state, newEntityState);
},
upsertOne: function upsertOne(state, action) {
var newEntityState = entityAdapter.upsertOne(state, action.payload);
modifyState(state, newEntityState);
},
upsertMany: function upsertMany(state, action) {
var newEntityState = entityAdapter.upsertMany(state, action.payload);
modifyState(state, newEntityState);
},
removeOne: function removeOne(state, action) {
var newEntityState = entityAdapter.removeOne(state, action.payload);
modifyState(state, newEntityState);
},
removeMany: function removeMany(state, action) {
var newEntityState = entityAdapter.removeMany(state, action.payload);
modifyState(state, newEntityState);
},
removeAll: function removeAll(state) {
var newEntityState = entityAdapter.removeAll(state);
modifyState(state, newEntityState);
},
reset: function reset() {
return initialSliceState;
},
setAll: function setAll(state, action) {
var newEntityState = entityAdapter.setAll(state, action.payload);
modifyState(state, newEntityState);
},
setError: function setError(state, action) {
_setError(state, action.payload);
},
setStatus: function setStatus(state, action) {
_setStatus(state, action.payload);
},
setMetaState: function setMetaState(state, action) {
var _createNextState, _createNextState2;
state.status = (_createNextState = toolkit.createNextState(state.status, function () {
return action.payload.status;
})) != null ? _createNextState : state.status;
state.error = (_createNextState2 = toolkit.createNextState(state.error, function () {
return action.payload.error;
})) != null ? _createNextState2 : state.error;
}
}
});
var entitySelectors = entityAdapter.getSelectors(function (state) {
return selectSliceState(state);
});
var selectors = {
selectIds: entitySelectors.selectIds,
selectEntities: entitySelectors.selectEntities,
selectAll: entitySelectors.selectAll,
selectTotal: entitySelectors.selectTotal,
selectById: entitySelectors.selectById,
/* TODO remove type assertion */
selectSliceState: toolkit.createSelector([selectSliceState], function (sliceState) {
return sliceState;
}),
selectStatus: toolkit.createSelector([selectSliceState], function (sliceState) {
return sliceState.status;
}),
selectError: toolkit.createSelector([selectSliceState], function (sliceState) {
return sliceState.error;
}),
selectLastModified: toolkit.createSelector([selectSliceState], function (sliceState) {
return sliceState.lastModified;
}),
selectLastHydrated: toolkit.createSelector([selectSliceState], function (sliceState) {
return sliceState.lastHydrated;
}),
selectCanRequest: toolkit.createSelector([selectSliceState], function (sliceState) {
return selectCanRequest(sliceState);
}),
selectShouldRequest: toolkit.createSelector([selectSliceState], function (sliceState) {
return selectShouldRequest(sliceState, selectCanRequest(sliceState));
})
};
return {
name: slice.name,
reducer: slice.reducer,
actions: slice.actions,
selectors: selectors
};
}
var create$2 = function create(args) {
if (args === void 0) {
args = {};
}
var metaState = MetaState.create(args);
return _extends({}, metaState, {
model: args.model
});
};
/**
* @public
*/
var ModelState = {
create: create$2
};
/**
* @public
*/
function createModelSlice(options) {
var defaultCanRequestSelector = function defaultCanRequestSelector(sliceState) {
return sliceState.status !== 'Requesting' && sliceState.error === null && sliceState.lastModified === null;
};
var defaultShouldRequestSelector = function defaultShouldRequestSelector(sliceState, canRequest) {
return canRequest && sliceState.lastHydrated === null;
};
var name = options.name,
_options$handleUpdate = options.handleUpdate,
handleUpdate = _options$handleUpdate === void 0 ? function (current, update) {
return merge(current, update);
} : _options$handleUpdate,
selectSliceState = options.selectSliceState,
_options$selectCanReq = options.selectCanRequest,
selectCanRequest = _options$selectCanReq === void 0 ? defaultCanRequestSelector : _options$selectCanReq,
_options$selectShould = options.selectShouldRequest,
selectShouldRequest = _options$selectShould === void 0 ? defaultShouldRequestSelector : _options$selectShould,
_options$initialState = options.initialState,
initialState = _options$initialState === void 0 ? {} : _options$initialState,
_options$createTimest = options.createTimestamp,
createTimestamp = _options$createTimest === void 0 ? getISOString : _options$createTimest;
var initialSliceState = ModelState.create(initialState);
var slice = toolkit.createSlice({
name: name,
initialState: initialSliceState,
// intentional, necessary with immer
/* eslint-disable no-param-reassign */
reducers: {
hydrate: function hydrate(state, action) {
state.model = toolkit.createNextState(state.model, function () {
return action.payload;
});
state.lastModified = null; // TODO: should not have a side effect: https://redux.js.org/style-guide/style-guide#reducers-must-not-have-side-effects
state.lastHydrated = createTimestamp();
},
update: function update(state, action) {
state.model = toolkit.createNextState(state.model, function () {
return handleUpdate(state.model, action.payload);
}); // TODO: should not have a side effect: https://redux.js.org/style-guide/style-guide#reducers-must-not-have-side-effects
state.lastModified = createTimestamp();
},
reset: function reset() {
return initialSliceState;
},
set: function set(state, action) {
state.model = toolkit.createNextState(state.model, function () {
return action.payload;
}); // TODO: should not have a side effect: https://redux.js.org/style-guide/style-guide#reducers-must-not-have-side-effects
state.lastModified = createTimestamp();
},
setError: function setError(state, action) {
state.error = toolkit.createNextState(state.error, function () {
return action.payload;
});
},
setStatus: function setStatus(state, action) {
state.status = toolkit.createNextState(state.status, function () {
return action.payload;
});
},
setMetaState: function setMetaState(state, action) {
var _createNextState, _createNextState2;
state.status = (_createNextState = toolkit.createNextState(state.status, function () {
return action.payload.status;
})) != null ? _createNextState : state.status;
state.error = (_createNextState2 = toolkit.createNextState(state.error, function () {
return action.payload.error;
})) != null ? _createNextState2 : state.error;
}
}
});
var selectors = {
selectSliceState: toolkit.createSelector([selectSliceState], function (sliceState) {
return sliceState;
}),
selectModel: toolkit.createSelector([selectSliceState], function (sliceState) {
return sliceState.model;
}),
selectStatus: toolkit.createSelector([selectSliceState], function (sliceState) {
return sliceState.status;
}),
selectError: toolkit.createSelector([selectSliceState], function (sliceState) {
return sliceState.error;
}),
selectLastModified: toolkit.createSelector([selectSliceState], function (sliceState) {
return sliceState.lastModified;
}),
selectLastHydrated: toolkit.createSelector([selectSliceState], function (sliceState) {
return sliceState.lastHydrated;
}),
selectCanRequest: toolkit.createSelector([selectSliceState], function (sliceState) {
return selectCanRequest(sliceState);
}),
selectShouldRequest: toolkit.createSelector([selectSliceState], function (sliceState) {
return selectShouldRequest(sliceState, selectCanRequest(sliceState));
})
};
return {
name: slice.name,
reducer: slice.reducer,
actions: slice.actions,
selectors: selectors
};
}
exports.StatusEnum = StatusEnum$1;
exports.createEntitySlice = createEntitySlice;
exports.createModelSlice = createModelSlice;
//# sourceMappingURL=redux-slice-factory.cjs.development.js.map