frontitygit
Version:
A Frontity source package for the REST API of self-hosted and WordPress.com sites
112 lines (103 loc) • 3.44 kB
text/typescript
import WpSource from "../../types";
import { normalize } from "normalizr";
import * as schemas from "./schemas";
import { transformLink } from "./transform-link";
/**
* A library helper to add entities to the Frontity state.
*
* @remarks
* Entities are not overwritten. If an entity already exists in the state
* and a new one is fetched, the one in the state will prevail. If you
* want to overwrite them, use the `force` option.
*
* @example
* ```js
* const response = await libraries.source.api.get({ endpoint: "posts" });
* const entities = await libraries.source.populate({ response, state });
* ```
*
* @param populateParams - Types specified in {@link WpSource}.
*
* @returns
* Returns a promise that resolves with an array of objects with
* attributes `type`, `id` and `link` representing the added entities.
*/
const populate: WpSource["libraries"]["source"]["populate"] = async ({
response,
state,
subdirectory,
force,
}) => {
// Normalize response
const json = await response.json();
const isList = Array.isArray(json);
const { entities, result } = normalize(
json,
isList ? schemas.list : schemas.entity
);
// Add entities to source
Object.entries(entities).forEach(([schema, entityMap]) => {
Object.entries(entityMap).forEach(([, entity]) => {
// Fix links that come from the REST API
// to match the Frontity server location.
if (entity.link) transformLink({ entity, state, subdirectory });
// Get or init data using the transformed link
const { data } = state.source;
const entityData =
data[entity.link] ||
(data[entity.link] = {
isReady: false,
isFetching: false,
link: entity.link,
route: entity.link,
query: {},
page: 1,
});
let entityMap: any;
let entityKey: string | number;
if (
schema === "postEntity" ||
schema === "attachmentEntity" ||
schema === "commentEntity"
) {
if (!state.source[entity.type]) state.source[entity.type] = {};
entityMap = state.source[entity.type];
entityKey = entity.id;
Object.assign(entityData, {
type: entity.type,
id: entity.id,
});
} else if (schema === "taxonomyEntity") {
if (!state.source[entity.taxonomy]) state.source[entity.taxonomy] = {};
entityMap = state.source[entity.taxonomy];
entityKey = entity.id;
Object.assign(entityData, {
taxonomy: entity.taxonomy,
id: entity.id,
});
} else if (schema === "authorEntity") {
entityMap = state.source.author;
entityKey = entity.id;
Object.assign(entityData, {
id: entity.id,
});
} else if (schema === "postType") {
entityMap = state.source.type;
entityKey = entity.slug;
} else if (schema === "taxonomyType") {
entityMap = state.source.taxonomy;
entityKey = entity.slug;
}
// Add the entity if it doesn't exist.
if (entityMap && (!entityMap[entityKey] || force)) {
entityMap[entityKey] = entity;
}
});
});
// Return type, id and link of added entities
return (isList ? result : [result]).map(({ id: entityId, schema }) => {
const { type, id, link } = entities[schema][entityId];
return { type, id, link };
});
};
export default populate;