import { ReactNode, MutableRefObject, createContext, useContext, useMemo, useRef, } from 'react' import { Fetcher, SWRHook, MutationHook } from './utils/types' import type { FetchCartInput } from './cart/use-cart' import type { Cart, Wishlist, Customer, SearchProductsData } from './types' const Commerce = createContext | {}>({}) export type Provider = CommerceConfig & { fetcher: Fetcher cart?: { useCart?: SWRHook useAddItem?: MutationHook useUpdateItem?: MutationHook useRemoveItem?: MutationHook } wishlist?: { useWishlist?: SWRHook useAddItem?: MutationHook useRemoveItem?: MutationHook } customer?: { useCustomer?: SWRHook } products?: { useSearch?: SWRHook } auth?: { useSignup?: MutationHook useLogin?: MutationHook useLogout?: MutationHook } } export type CommerceProps

= { children?: ReactNode provider: P config: CommerceConfig } export type CommerceConfig = Omit< CommerceContextValue, 'providerRef' | 'fetcherRef' > export type CommerceContextValue

= { providerRef: MutableRefObject

fetcherRef: MutableRefObject locale: string cartCookie: string } export function CommerceProvider

({ provider, children, config, }: CommerceProps

) { if (!config) { throw new Error('CommerceProvider requires a valid config object') } const providerRef = useRef(provider) // TODO: Remove the fetcherRef const fetcherRef = useRef(provider.fetcher) // Because the config is an object, if the parent re-renders this provider // will re-render every consumer unless we memoize the config const cfg = useMemo( () => ({ providerRef, fetcherRef, locale: config.locale, cartCookie: config.cartCookie, }), [config.locale, config.cartCookie] ) return {children} } export function useCommerce

() { return useContext(Commerce) as CommerceContextValue

}