@wordpress/core-data
Version:
Access to and manipulation of core WordPress entities.
186 lines (185 loc) • 5.26 kB
JavaScript
// packages/core-data/src/queried-data/reducer.js
import { combineReducers } from "@wordpress/data";
import { compose } from "@wordpress/compose";
import {
conservativeMapItem,
ifMatchingAction,
replaceAction,
onSubKey
} from "../utils/index.mjs";
import { DEFAULT_ENTITY_KEY } from "../entities.mjs";
import getQueryParts from "./get-query-parts.mjs";
function getContextFromAction(action) {
const { query } = action;
if (!query) {
return "default";
}
const queryParts = getQueryParts(query);
return queryParts.context;
}
function getMergedItemIds(itemIds, nextItemIds, page, perPage) {
const receivedAllIds = page === 1 && perPage === -1;
if (receivedAllIds) {
return nextItemIds;
}
const nextItemIdsStartIndex = (page - 1) * perPage;
const size = Math.max(
itemIds?.length ?? 0,
nextItemIdsStartIndex + nextItemIds.length
);
const mergedItemIds = new Array(size);
for (let i = 0; i < size; i++) {
const isInNextItemsRange = i >= nextItemIdsStartIndex && i < nextItemIdsStartIndex + perPage;
mergedItemIds[i] = isInNextItemsRange ? nextItemIds[i - nextItemIdsStartIndex] : itemIds?.[i];
}
return mergedItemIds;
}
function removeEntitiesById(entities, ids) {
return Object.fromEntries(
Object.entries(entities).filter(
([id]) => !ids.some((itemId) => {
if (Number.isInteger(itemId)) {
return itemId === +id;
}
return itemId === id;
})
)
);
}
function items(state = {}, action) {
switch (action.type) {
case "RECEIVE_ITEMS": {
const context = getContextFromAction(action);
const key = action.key || DEFAULT_ENTITY_KEY;
return {
...state,
[context]: {
...state[context],
...action.items.reduce((accumulator, value) => {
const itemId = value?.[key];
accumulator[itemId] = conservativeMapItem(
state?.[context]?.[itemId],
value
);
return accumulator;
}, {})
}
};
}
case "REMOVE_ITEMS":
return Object.fromEntries(
Object.entries(state).map(([itemId, contextState]) => [
itemId,
removeEntitiesById(contextState, action.itemIds)
])
);
}
return state;
}
function itemIsComplete(state = {}, action) {
switch (action.type) {
case "RECEIVE_ITEMS": {
const context = getContextFromAction(action);
const { query, key = DEFAULT_ENTITY_KEY } = action;
const queryParts = query ? getQueryParts(query) : {};
const isCompleteQuery = !query || !Array.isArray(queryParts.fields);
return {
...state,
[context]: {
...state[context],
...action.items.reduce((result, item) => {
const itemId = item?.[key];
result[itemId] = state?.[context]?.[itemId] || isCompleteQuery;
return result;
}, {})
}
};
}
case "REMOVE_ITEMS":
return Object.fromEntries(
Object.entries(state).map(([itemId, contextState]) => [
itemId,
removeEntitiesById(contextState, action.itemIds)
])
);
}
return state;
}
var receiveQueries = compose([
// Limit to matching action type so we don't attempt to replace action on
// an unhandled action.
ifMatchingAction((action) => "query" in action),
// Inject query parts into action for use both in `onSubKey` and reducer.
replaceAction((action) => {
if (action.query) {
return {
...action,
...getQueryParts(action.query)
};
}
return action;
}),
onSubKey("context"),
// Queries shape is shared, but keyed by query `stableKey` part. Original
// reducer tracks only a single query object.
onSubKey("stableKey")
])((state = {}, action) => {
const { type, page, perPage, key = DEFAULT_ENTITY_KEY } = action;
if (type !== "RECEIVE_ITEMS") {
return state;
}
return {
itemIds: getMergedItemIds(
state?.itemIds || [],
action.items.map((item) => item?.[key]).filter(Boolean),
page,
perPage
),
meta: action.meta
};
});
var queries = (state = {}, action) => {
switch (action.type) {
case "RECEIVE_ITEMS":
return receiveQueries(state, action);
case "REMOVE_ITEMS":
const removedItems = action.itemIds.reduce((result, itemId) => {
result[itemId] = true;
return result;
}, {});
return Object.fromEntries(
Object.entries(state).map(
([queryGroup, contextQueries]) => [
queryGroup,
Object.fromEntries(
Object.entries(contextQueries).map(
([query, queryItems]) => [
query,
{
...queryItems,
itemIds: queryItems.itemIds.filter(
(queryId) => !removedItems[queryId]
)
}
]
)
)
]
)
);
default:
return state;
}
};
var reducer_default = combineReducers({
items,
itemIsComplete,
queries
});
export {
reducer_default as default,
getMergedItemIds,
itemIsComplete,
items
};
//# sourceMappingURL=reducer.mjs.map