frontitygit
Version:
A Frontity source package for the REST API of self-hosted and WordPress.com sites
147 lines (129 loc) • 3.6 kB
text/typescript
import { fetch } from "frontity";
import { stringify } from "query-string";
import { ServerError } from "@frontity/source";
/**
* The initialization method of the Api.
*/
interface Init {
/**
* The URL of the WordPress REST API.
*/
api: string;
/**
* Whether the REST API belongs to a site hosted on wordpress.com.
*/
isWpCom?: boolean;
}
/**
* Parameters of the `Api.get()` method.
*/
interface Get {
/**
* Used to specify the kind of the WordPress REST API endpoint. Used to
* construct the final URL from which data will be fetched.
*
* It should be the name of the endpoint if is a `/wp/v2 endpoint` (e.g.
* `posts`), or the full path of other REST endpoints (e.g. `/acf/v3/posts`).
*
* @example "posts", "pages"
*/
endpoint: string;
/**
* The URL params used to create the query string in the final `fetch()`
* request.
*
* @example
* ```
* { _embed: true }
* ```
*/
params?: Record<string, any>;
/**
* Optionally override the value of Api.api.
*/
api?: string;
/**
* Optionally override the value of Api.isWpCom.
*/
isWpCom?: boolean;
/**
* The optional authentication information.
*
* This can be e.g. A Basic Authentication string or a Bearer token.
*/
auth?: string;
}
/**
* A container class which handles fetching the data from the WordPress REST
* API.
*/
class Api {
api = "";
isWpCom = false;
/**
* The initialization method of the class.
*
* @param this - The instance of the {@link Api}.
* @param params - Defined in {@link Init}.
*/
init(this: Api, { api, isWpCom = false }: Init) {
this.api = api;
this.isWpCom = isWpCom;
}
/**
* Request entity from the WordPress REST API.
*
* @param this - The instance of the {@link Api}.
* @param params - Defined in {@link Get}.
*
* @returns A Promise that resolves to the `Response` object retuned from
* `fetch()`.
*/
get(
this: Api,
{ endpoint, params, api = this.api, isWpCom = this.isWpCom, auth }: Get
): Promise<Response> {
// Ensure there is a final slash
const baseUrl = api.replace(/\/?$/, "/");
// Add the REST path depending on whether it should start with "/wp/v2" or
// not
const requestUrl =
isWpCom || endpoint.startsWith("/")
? `${baseUrl}${endpoint.replace(/^\//, "")}`
: `${baseUrl}wp/v2/${endpoint}`;
// Add query parameters
const query = stringify(params, { arrayFormat: "bracket", encode: false });
// If `auth` was passed, add it to the headers
const headers = auth ? { Authorization: auth } : {};
// Send request
return fetch(`${requestUrl}${query && "?"}${query}`, { headers }).then(
(response: Response) => {
if (!response.ok) {
const { status, statusText } = response;
throw new ServerError(statusText, status, statusText);
}
return response;
}
);
}
/**
* A helper method for getting the ID of a particular entity based on it's
* slug.
*
* @param endpoint - The endpoint from which to fetch the entity.
* @param slug - The slug of the entity.
*
* @returns The ID of the particular entity.
*/
async getIdBySlug(endpoint: string, slug: string) {
const response = await this.get({ endpoint, params: { slug } });
const [entity] = await response.clone().json();
if (!entity)
throw new ServerError(
`entity from endpoint '${endpoint}' with slug '${slug}' not found`,
404
);
return entity.id;
}
}
export default Api;