diff --git a/framework/bigcommerce/index.tsx b/framework/bigcommerce/index.tsx index 2ff73366c..83fbdbcbc 100644 --- a/framework/bigcommerce/index.tsx +++ b/framework/bigcommerce/index.tsx @@ -1,91 +1,13 @@ import { ReactNode } from 'react' -import * as React from 'react' -import { Fetcher } from '@commerce/utils/types' import { CommerceConfig, CommerceProvider as CoreCommerceProvider, useCommerce as useCoreCommerce, } from '@commerce' -import { FetcherError } from '@commerce/utils/errors' -import type { HookHandler } from '@commerce/utils/types' -import type { FetchCartInput } from '@commerce/cart/use-cart' -import { normalizeCart } from './lib/normalize' -import { Cart } from './types' +import { bigcommerceProvider, BigcommerceProvider } from './provider' -async function getText(res: Response) { - try { - return (await res.text()) || res.statusText - } catch (error) { - return res.statusText - } -} - -async function getError(res: Response) { - if (res.headers.get('Content-Type')?.includes('application/json')) { - const data = await res.json() - return new FetcherError({ errors: data.errors, status: res.status }) - } - return new FetcherError({ message: await getText(res), status: res.status }) -} - -const fetcher: Fetcher = async ({ - url, - method = 'GET', - variables, - body: bodyObj, -}) => { - const hasBody = Boolean(variables || bodyObj) - const body = hasBody - ? JSON.stringify(variables ? { variables } : bodyObj) - : undefined - const headers = hasBody ? { 'Content-Type': 'application/json' } : undefined - const res = await fetch(url!, { method, body, headers }) - - if (res.ok) { - const { data } = await res.json() - return data - } - - throw await getError(res) -} - -const useCart: HookHandler< - Cart | null, - [], - FetchCartInput, - any, - any, - { isEmpty?: boolean } -> = { - fetchOptions: { - url: '/api/bigcommerce/cart', - method: 'GET', - }, - swrOptions: { - revalidateOnFocus: false, - }, - normalizer: normalizeCart, - onResponse(response) { - return Object.create(response, { - isEmpty: { - get() { - return (response.data?.lineItems.length ?? 0) <= 0 - }, - enumerable: true, - }, - }) - }, -} - -export const bigcommerceProvider = { - locale: 'en-us', - cartCookie: 'bc_cartId', - fetcher, - cartNormalizer: normalizeCart, - cart: { useCart }, -} - -export type BigcommerceProvider = typeof bigcommerceProvider +export { bigcommerceProvider } +export type { BigcommerceProvider } export const bigcommerceConfig: CommerceConfig = { locale: 'en-us', diff --git a/framework/bigcommerce/provider.ts b/framework/bigcommerce/provider.ts new file mode 100644 index 000000000..b6385546c --- /dev/null +++ b/framework/bigcommerce/provider.ts @@ -0,0 +1,108 @@ +import { FetcherError } from '@commerce/utils/errors' +import type { Fetcher, HookHandler } from '@commerce/utils/types' +import type { FetchCartInput } from '@commerce/cart/use-cart' +import { normalizeCart } from './lib/normalize' +import type { Cart } from './types' + +async function getText(res: Response) { + try { + return (await res.text()) || res.statusText + } catch (error) { + return res.statusText + } +} + +async function getError(res: Response) { + if (res.headers.get('Content-Type')?.includes('application/json')) { + const data = await res.json() + return new FetcherError({ errors: data.errors, status: res.status }) + } + return new FetcherError({ message: await getText(res), status: res.status }) +} + +const fetcher: Fetcher = async ({ + url, + method = 'GET', + variables, + body: bodyObj, +}) => { + const hasBody = Boolean(variables || bodyObj) + const body = hasBody + ? JSON.stringify(variables ? { variables } : bodyObj) + : undefined + const headers = hasBody ? { 'Content-Type': 'application/json' } : undefined + const res = await fetch(url!, { method, body, headers }) + + if (res.ok) { + const { data } = await res.json() + return data + } + + throw await getError(res) +} + +const useCart: HookHandler< + Cart | null, + [], + FetchCartInput, + any, + any, + { isEmpty?: boolean } +> = { + fetchOptions: { + url: '/api/bigcommerce/cart', + method: 'GET', + }, + swrOptions: { + revalidateOnFocus: false, + }, + normalizer: normalizeCart, + onResponse(response) { + return Object.create(response, { + isEmpty: { + get() { + return (response.data?.lineItems.length ?? 0) <= 0 + }, + enumerable: true, + }, + }) + }, +} + +const useWishlist: HookHandler< + Cart | null, + [], + FetchCartInput, + any, + any, + { isEmpty?: boolean } +> = { + fetchOptions: { + url: '/api/bigcommerce/wishlist', + method: 'GET', + }, + swrOptions: { + revalidateOnFocus: false, + }, + onResponse(response) { + return Object.create(response, { + isEmpty: { + get() { + return (response.data?.lineItems.length ?? 0) <= 0 + }, + enumerable: true, + }, + }) + }, +} + +export const bigcommerceProvider = { + locale: 'en-us', + cartCookie: 'bc_cartId', + fetcher, + cartNormalizer: normalizeCart, + cart: { useCart }, + wishlist: { useWishlist }, +} + +export type BigcommerceProvider = typeof bigcommerceProvider diff --git a/framework/commerce/index.tsx b/framework/commerce/index.tsx index cb2fafcd7..82e86947d 100644 --- a/framework/commerce/index.tsx +++ b/framework/commerce/index.tsx @@ -18,6 +18,9 @@ export type Provider = CommerceConfig & { cart?: { useCart?: HookHandler } + wishlist?: { + useWishlist?: HookHandler + } } export type CommerceProps

= {