From e0da7f42610787c60dbd031900ea1f8322579423 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 14 Jun 2021 23:06:54 +0200 Subject: [PATCH] avoid circular dependency in bigcommerce --- framework/bigcommerce/api/index.ts | 8 +- .../api/utils/fetch-graphql-api.ts | 58 ++++++------ .../bigcommerce/api/utils/fetch-store-api.ts | 94 +++++++++---------- 3 files changed, 79 insertions(+), 81 deletions(-) diff --git a/framework/bigcommerce/api/index.ts b/framework/bigcommerce/api/index.ts index 300f1087b..f28f2a1f4 100644 --- a/framework/bigcommerce/api/index.ts +++ b/framework/bigcommerce/api/index.ts @@ -4,8 +4,8 @@ import { CommerceAPIConfig, getCommerceApi as commerceApi, } from '@commerce/api' -import fetchGraphqlApi from './utils/fetch-graphql-api' -import fetchStoreApi from './utils/fetch-store-api' +import createFetchGraphqlApi from './utils/fetch-graphql-api' +import createFetchStoreApi from './utils/fetch-store-api' import type { CartAPI } from './endpoints/cart' import type { CustomerAPI } from './endpoints/customer' @@ -68,14 +68,14 @@ const config: BigcommerceConfig = { customerCookie: 'SHOP_TOKEN', cartCookie: process.env.BIGCOMMERCE_CART_COOKIE ?? 'bc_cartId', cartCookieMaxAge: ONE_DAY * 30, - fetch: fetchGraphqlApi, + fetch: createFetchGraphqlApi(() => getCommerceApi().getConfig()), applyLocale: true, // REST API only storeApiUrl: STORE_API_URL, storeApiToken: STORE_API_TOKEN, storeApiClientId: STORE_API_CLIENT_ID, storeChannelId: STORE_CHANNEL_ID, - storeApiFetch: fetchStoreApi, + storeApiFetch: createFetchStoreApi(() => getCommerceApi().getConfig()), } const operations = { diff --git a/framework/bigcommerce/api/utils/fetch-graphql-api.ts b/framework/bigcommerce/api/utils/fetch-graphql-api.ts index 7dc39f987..8cc76c067 100644 --- a/framework/bigcommerce/api/utils/fetch-graphql-api.ts +++ b/framework/bigcommerce/api/utils/fetch-graphql-api.ts @@ -1,38 +1,36 @@ import { FetcherError } from '@commerce/utils/errors' import type { GraphQLFetcher } from '@commerce/api' -import { provider } from '..' +import type { BigcommerceConfig } from '../index' import fetch from './fetch' -const fetchGraphqlApi: GraphQLFetcher = async ( - query: string, - { variables, preview } = {}, - fetchOptions -) => { - // log.warn(query) - const { config } = provider - const res = await fetch(config.commerceUrl + (preview ? '/preview' : ''), { - ...fetchOptions, - method: 'POST', - headers: { - Authorization: `Bearer ${config.apiToken}`, - ...fetchOptions?.headers, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - query, - variables, - }), - }) - - const json = await res.json() - if (json.errors) { - throw new FetcherError({ - errors: json.errors ?? [{ message: 'Failed to fetch Bigcommerce API' }], - status: res.status, +const fetchGraphqlApi: (getConfig: () => BigcommerceConfig) => GraphQLFetcher = + (getConfig) => + async (query: string, { variables, preview } = {}, fetchOptions) => { + // log.warn(query) + const config = getConfig() + const res = await fetch(config.commerceUrl + (preview ? '/preview' : ''), { + ...fetchOptions, + method: 'POST', + headers: { + Authorization: `Bearer ${config.apiToken}`, + ...fetchOptions?.headers, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + query, + variables, + }), }) + + const json = await res.json() + if (json.errors) { + throw new FetcherError({ + errors: json.errors ?? [{ message: 'Failed to fetch Bigcommerce API' }], + status: res.status, + }) + } + + return { data: json.data, res } } - return { data: json.data, res } -} - export default fetchGraphqlApi diff --git a/framework/bigcommerce/api/utils/fetch-store-api.ts b/framework/bigcommerce/api/utils/fetch-store-api.ts index a00b3777a..1e44b28f9 100644 --- a/framework/bigcommerce/api/utils/fetch-store-api.ts +++ b/framework/bigcommerce/api/utils/fetch-store-api.ts @@ -1,56 +1,56 @@ import type { RequestInit, Response } from '@vercel/fetch' -import { provider } from '..' +import type { BigcommerceConfig } from '../index' import { BigcommerceApiError, BigcommerceNetworkError } from './errors' import fetch from './fetch' -export default async function fetchStoreApi( - endpoint: string, - options?: RequestInit -): Promise { - const { config } = provider - let res: Response +const fetchStoreApi = + (getConfig: () => BigcommerceConfig) => + async (endpoint: string, options?: RequestInit): Promise => { + const config = getConfig() + let res: Response - try { - res = await fetch(config.storeApiUrl + endpoint, { - ...options, - headers: { - ...options?.headers, - 'Content-Type': 'application/json', - 'X-Auth-Token': config.storeApiToken, - 'X-Auth-Client': config.storeApiClientId, - }, - }) - } catch (error) { - throw new BigcommerceNetworkError( - `Fetch to Bigcommerce failed: ${error.message}` - ) + try { + res = await fetch(config.storeApiUrl + endpoint, { + ...options, + headers: { + ...options?.headers, + 'Content-Type': 'application/json', + 'X-Auth-Token': config.storeApiToken, + 'X-Auth-Client': config.storeApiClientId, + }, + }) + } catch (error) { + throw new BigcommerceNetworkError( + `Fetch to Bigcommerce failed: ${error.message}` + ) + } + + const contentType = res.headers.get('Content-Type') + const isJSON = contentType?.includes('application/json') + + if (!res.ok) { + const data = isJSON ? await res.json() : await getTextOrNull(res) + const headers = getRawHeaders(res) + const msg = `Big Commerce API error (${ + res.status + }) \nHeaders: ${JSON.stringify(headers, null, 2)}\n${ + typeof data === 'string' ? data : JSON.stringify(data, null, 2) + }` + + throw new BigcommerceApiError(msg, res, data) + } + + if (res.status !== 204 && !isJSON) { + throw new BigcommerceApiError( + `Fetch to Bigcommerce API failed, expected JSON content but found: ${contentType}`, + res + ) + } + + // If something was removed, the response will be empty + return res.status === 204 ? null : await res.json() } - - const contentType = res.headers.get('Content-Type') - const isJSON = contentType?.includes('application/json') - - if (!res.ok) { - const data = isJSON ? await res.json() : await getTextOrNull(res) - const headers = getRawHeaders(res) - const msg = `Big Commerce API error (${ - res.status - }) \nHeaders: ${JSON.stringify(headers, null, 2)}\n${ - typeof data === 'string' ? data : JSON.stringify(data, null, 2) - }` - - throw new BigcommerceApiError(msg, res, data) - } - - if (res.status !== 204 && !isJSON) { - throw new BigcommerceApiError( - `Fetch to Bigcommerce API failed, expected JSON content but found: ${contentType}`, - res - ) - } - - // If something was removed, the response will be empty - return res.status === 204 ? null : await res.json() -} +export default fetchStoreApi function getRawHeaders(res: Response) { const headers: { [key: string]: string } = {}