import entityTypeReducer from './entityTypeReducer';
import { ADD_ENTITIES } from '../../actions/entities/entityActions';
import { strictIdCheck } from '../../data/entityTypes';
/**
* The root reducer for all entities. It contains a entityTypeReducer for each
* entity type. These reducers are called automatically when an action of the
* relevant type is dispatched.
*
* state structure:
* {
* [entity type]: entityTypeReducer(),
* ...
* }
*/
const entitiesReducer = (state = {}, action) => {
// if an action is targeted towards a specific entity type, update that key
if (action.meta && action.meta.entityType) {
return {
...state,
[action.meta.entityType]: entityTypeReducer(
state[action.meta.entityType],
action,
strictIdCheck.includes(action.meta.entityType),
),
};
}
// handle actions that are not targeted towards a specific entity type
switch (action.type) {
case ADD_ENTITIES: {
const newState = { ...state };
Object.keys(action.payload).forEach(entityType => {
if (strictIdCheck.includes(entityType)) {
Object.keys(action.payload[entityType]).forEach(id => {
if (action.payload[entityType][id].id !== id) {
throw new Error(
`Strict id check failed: key of ${entityType} entity must match entity id`,
);
}
});
}
newState[entityType] = {
...(state[entityType] || {}),
...action.payload[entityType],
};
});
return newState;
}
default:
return state;
}
};
/**
* This is a simple helper function to get a specific entity from the entities reducer.
* Because memoization is not really needed here, we use this simple util instead of creating
* a reselect selector
*
* @param state {object} The current state.entities state
* @param type {string} The type of entity to get
* @param id {string} The entity id to get
*/
export const getEntity = (state, type, id) => state[type] && state[type][id];
export default entitiesReducer;