import { CommerceAPI, CommerceAPIOptions, CommerceAPIFetchOptions, } from 'lib/commerce/api'; import { GetAllProductsQuery, GetAllProductsQueryVariables } from '../schema'; import { getAllProductsQuery } from './operations/get-all-products'; type RecursivePartial = { [P in keyof T]?: RecursivePartial; }; export interface GetAllProductsResult { products: T extends GetAllProductsQuery ? T['site']['products']['edges'] : unknown; } export interface Images { small?: ImageOptions; medium?: ImageOptions; large?: ImageOptions; xl?: ImageOptions; } export interface ImageOptions { width: number; height?: number; } export interface BigcommerceAPIOptions extends CommerceAPIOptions { images?: Images; } export type ProductImageVariables = Pick< GetAllProductsQueryVariables, | 'imgSmallWidth' | 'imgSmallHeight' | 'imgMediumWidth' | 'imgMediumHeight' | 'imgLargeWidth' | 'imgLargeHeight' | 'imgXLWidth' | 'imgXLHeight' >; export type ProductVariables = Images & Omit; export default class BigcommerceAPI implements CommerceAPI { commerceUrl: string; apiToken: string; imageVariables?: ProductImageVariables; constructor({ commerceUrl, apiToken, images }: BigcommerceAPIOptions) { this.commerceUrl = commerceUrl; this.apiToken = apiToken; this.imageVariables = { imgSmallWidth: images?.small?.width, imgSmallHeight: images?.small?.height, imgMediumWidth: images?.medium?.height, imgMediumHeight: images?.medium?.height, imgLargeWidth: images?.large?.height, imgLargeHeight: images?.large?.height, imgXLWidth: images?.xl?.height, imgXLHeight: images?.xl?.height, }; } async fetch( query: string, { variables, preview }: CommerceAPIFetchOptions = {} ): Promise { const res = await fetch(this.commerceUrl + (preview ? '/preview' : ''), { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${this.apiToken}`, }, body: JSON.stringify({ query, variables, }), }); const json = await res.json(); if (json.errors) { console.error(json.errors); throw new Error('Failed to fetch API'); } return json.data; } async getAllProducts(opts: { query: string; variables?: V; }): Promise>; async getAllProducts(opts?: { query?: string; variables?: ProductVariables; }): Promise>; async getAllProducts({ query = getAllProductsQuery, variables: vars, }: { query?: string; variables?: ProductVariables; } = {}): Promise< GetAllProductsResult> > { const variables: GetAllProductsQueryVariables = { ...this.imageVariables, ...vars, }; const data = await this.fetch>( query, { variables } ); return { products: data?.site?.products?.edges, }; } }