frontitygit
Version:
A Frontity source package for the REST API of self-hosted and WordPress.com sites
115 lines (105 loc) • 3.32 kB
text/typescript
import { PostTypeData } from "@frontity/source/types/data";
import { Handler } from "../../../types";
import capitalize from "./utils/capitalize";
/**
* The parameters for {@link postTypeWithQueryHandler}.
*/
interface PostTypeWithQueryHandlerOptions {
/**
* The type of entities that are going to be fetched.
*/
type: string;
/**
* A [WP REST API
* endpoint](https://developer.wordpress.org/rest-api/reference/) from which
* the generated handler is going to fetch the data.
*/
endpoint: string;
/**
* Name of the query parameter where the ID is stored. Default is `p`.
*/
idParamName?: string;
}
/**
* A {@link Handler} function generator for WordPress Post Types.
*
* This function will generate a handler function for a specific [WP REST API
* endpoint](https://developer.wordpress.org/rest-api/reference/) from which the
* data is going to be fetched.
*
* The generated function is intended to be used with handlers for fetching post
* type entities using plain permalinks (e.g. Http://frontity.site/?page_id=42).
*
* @param options - Options for the handler generator: {@link
* PostTypeWithQueryHandlerOptions}.
*
* @example
* ```js
* const postWithQuery = postTypeWithQueryHandler({ endpoint: "posts" });
* libraries.source.handlers.push({
* name: "post with query permalink",
* priority: 10,
* pattern: "RegExp:(\\?|&)p=\\d+",
* func: postWithQuery,
* });
* ```
*
* @example
* ```js
* const pageWithQuery = postTypeWithQueryHandler({
* endpoint: "pages",
* idParamName: "page_id"
* });
* libraries.source.handlers.push({
* name: "page with query permalink",
* priority: 10,
* pattern: "RegExp:(\\?|&)page_id=\\d+",
* func: pageWithQuery,
* });
* ```
*
* @returns An async "handler" function that can be passed as an argument to the
* handler object. This function will be invoked by the frontity framework when
* calling `actions.source.fetch()` for a specific entity.
*/
const postTypeWithQueryHandler = ({
type,
endpoint,
idParamName = "p",
}: PostTypeWithQueryHandlerOptions): Handler => async ({
link,
state,
libraries,
force,
}) => {
const { query } = libraries.source.parse(link);
// Get the ID from the query.
const id = parseInt(query[idParamName], 10);
// Search for the entity in the state.
const entity = state.source[type] && state.source[type][id];
// If not found, fetch the entity. Also if force is `true`.
if (!entity || force) {
// Fetch the entity. The `api.get` call will throw a `ServerError` if the
// request has failed.
const response = await libraries.source.api.get({
endpoint: `${endpoint}/${id}`,
params: { _embed: true, ...state.source.params },
auth: state.source.auth,
});
// Populate the entity. We can be sure here that the entity is being
// populated because the previous call would have been thrown a
// `ServerError` otherwise.
await libraries.source.populate({ response, state, force });
}
// Assign props to data.
const data = state.source.get(link);
Object.assign(data, {
type,
link,
query,
id,
isPostType: true,
[`is${capitalize(type)}`]: true,
}) as PostTypeData; // This ensures the resulting type is correct.
};
export default postTypeWithQueryHandler;