UNPKG

@apptus/esales-api

Version:

Library for making requests to Elevate 4 API v3

271 lines (252 loc) 9.68 kB
import { assert, addUrlParams, createBaseUrl, facetsToParams, ResponseError, type Type, type UrlParams } from './util/mod.ts'; import type { FullOptions } from './config.ts'; import type { FacetParams } from './mod.ts'; import type * as m from './models/mod.ts'; export class Query { constructor(private readonly __config: FullOptions) {} /** * Retrieve recommendations for a product that has just been added to the cart. * * @param params query parameter options to submit * @param body configuration options to submit * * @example * ```ts * const res = await api.query.addToCartPopup({ variantKey: 'variant-key-123' }, { * recommendationLists: [{ * id: 'addons', * algorithm: 'ADD_TO_CART_RECS' * }] * }); * ``` * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/add-to-cart-popup/ */ addToCartPopup(params: m.AddToCartPopupParams, recommendationLists: m.AddToCartPopupBody) { return this.__query<m.AddToCartPopup>('add-to-cart-popup', { params: params as Type<m.AddToCartPopupParams>, body: { recommendationLists } }); } /** * Autocomplete based on provided query parameter, for search suggestions, * product suggestions, and more. * * @param params query parameter options to submit * @param body configuration options to submit * * @example * ```ts * const res = await api.query.autocomplete({ q: 'shirt' }); * const sale = await api.query.autocomplete({ q: 'dress' }, { * productFilter: { discount: 50 } * p}); * ``` * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/autocomplete/ */ autocomplete(params: m.AutocompleteParams, body?: m.AutocompleteBody) { return this.__query<m.Autocomplete>('autocomplete', { params: params as Type<m.AutocompleteParams>, body }); } /** * Retrieve the complete navigation tree, suitable for a top/mobile navigation of the site. * * @param params query parameter options to submit * * @example * ```ts * const tree = await api.query.navigationTree(); * ``` * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/navigation-tree/ */ navigationTree(params?: m.NavigationTreeParams) { return this.__query<m.NavigationTree>('navigation-tree', { params: params as Type<m.NavigationTreeParams> }); } /** * Returns a product listing with facets based on provided query, optionally * with related navigation included. * * @param params query parameter options to submit * @param body configuration options to submit * * @example * ```ts * const res = await api.query.searchPage({ q: 'shirt' }); * const sale = await api.query.searchPage({ q: 'dress' }, { * primaryList: { * productFilter: { discount: 50 } * }, * navigation: { include: true } * }); * ``` * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/search-page/ */ searchPage(params: m.SearchPageParams, body?: m.SearchPageBody) { const { facets, ...p } = params; return this.__query<m.SearchPage>('search-page', { facets, params: { ...p }, body }); } /** * Retrieves product information and related info suitable to show on a Product page. * Can be configured to show various recommendation lists based on body configuration settings. * * @param params query parameter options to submit * @param body configuration options to submit * * @example * ```ts * const res = await api.query.productPage({ productKey: 'p123' }, { * recommendationLists: [{ * id: 'alts', * algorithm: 'ALTERNATIVES' * }] * }); * ``` * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/product-page/ */ productPage(params: m.ProductPageParams, body?: m.ProductPageBody) { return this.__query<m.ProductPage>('product-page', { params: params as Type<m.ProductPageParams>, body }); } /** * Retrieve products - and possibly recommendation lists - suitable for display * on a cart page. * * @param params query parameter options to submit * @param body configuration options to submit * * @example * ```ts * const res = await api.query.cartPage({ cart: ['p123', 'p456'] }, { * recommendationLists: [{ * id: 'addons', * algorithm: 'CART' * }] * }); * ``` * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/cart-page/ */ cartPage(params: m.CartPageParams, body?: m.CartPageBody) { return this.__query<m.CartPage>('cart-page', { params: params as Type<m.CartPageParams>, body }); } /** * Request for generic landing pages, or category pages. Can return product listing with facets, * recommendation lists, or both. Suitable for the start/home page, intermediate category pages, * brand pages, and more. * * @param params query parameter options to submit * @param body configuration options to submit * * @example * ```ts * const res = await api.query.landingPage(); * const sale = await api.query.landingPage({ limit: 30, skip: 0 }, { * primaryList: { * productFilter: { discount: 50 } * }, * recommendationLists: [{ * id: 'personal', * algorithm: 'PERSONAL' * }] * }); * ``` * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/landing-page/ */ landingPage(params: m.LandingPageParams = {}, body?: m.LandingPageBody) { const { facets, ...p } = params; return this.__query<m.LandingPage>('landing-page', { facets, params: { ...p }, body }); } /** * Request for retrieving a list of sponsored products for a Page. * * @beta ⚠️ This request is currently limited to a private beta and will fail otherwise. * * @param params query parameter options to submit * * @example * ```ts * const res = await api.query.sponsoredPage({ * pageReference: '/women/tops' * }); * ``` * @see https://docs.apptus.com/elevate/4/integration/api/specifications/storefront/v3/queries/sponsored-page/ */ sponsoredPage(params: m.SponsoredPageParams) { return this.__query<m.SponsoredPage>('sponsored-page', { params: params as Type<m.SponsoredPageParams> }); } /** * Request for retrieving a list of banners for a Page. * * @beta ⚠️ This request is currently limited to a private beta and will fail otherwise. * * @param params query parameter options to submit * * @example * ```ts * const res = await api.query.banners({ * pageReference: '/women/tops' * }); * ``` * @see https://docs.apptus.com/elevate/4/integration/api/specifications/storefront/v3/queries/banners/ */ banners(params: m.BannersParams) { return this.__query<m.Banners>('banners', { params: params as Type<m.BannersParams> }); } /** * Mirrors the Product Page, but for Content instead of Products. Retrieves content * information for the provided `contentKeys` (required). * * @param params query parameter options to submit * * @example * ```ts * const res = await api.query.contentInformation({ * contentKeys: ['ck_123456', 'ck_234567'] * }); * ``` * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/content-information/ */ contentInformation(params: m.ContentInformationParams) { return this.__query<m.ContentInformation>('content-information', { params: params as Type<m.ContentInformationParams> }); } /** * Mirrors the Search Page request, but for Content instead of Products. Returns content * results matching the provided query. Suiteable for searching in e.g. FAQ or customer service, * where no product results are required. * * @param params query parameter options to submit * @param body configuration options to submit * * @example * ```ts * const res = await this.contentSearchPage({ q: 'returns' }); * ``` * @example * ```ts * const res = await this.contentSearchPage({ q: 'shipping', skip: 20 }, { * primaryList: { * contentFilter: { * type: 'faq' * } * } * }); * ``` * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/content-search-page/ */ contentSearchPage(params: m.ContentSearchPageParams, body?: m.ContentSearchPageBody) { return this.__query<m.ContentSearchPage>('content-search-page', { params: params as Type<m.ContentSearchPageParams>, body }); } private async __query<T>(endpoint: string, options: { params?: UrlParams, facets?: FacetParams, body?: object }) { const { params = {}, facets, body } = options; assert(typeof params === 'object', 'If provided, params must be an object'); const url = await createBaseUrl(`queries/${endpoint}`, this.__config); const { locale, touchpoint } = this.__config; addUrlParams(url, { locale, touchpoint, ...params, ...facetsToParams(facets) }); const init: RequestInit = !body ? { method: 'GET' } : { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: JSON.stringify(body) }; const res = await fetch(url, init); const content = await res.json(); // TODO: res.ok if (res.status >= 200 && res.status < 400) { return content as T; } throw new ResponseError(content); } }