diff --git a/framework/bigcommerce/index.tsx b/framework/bigcommerce/index.tsx index a4271226e..4f6c9316b 100644 --- a/framework/bigcommerce/index.tsx +++ b/framework/bigcommerce/index.tsx @@ -5,10 +5,10 @@ import { CommerceConfig, CommerceProvider as CoreCommerceProvider, useCommerce as useCoreCommerce, - HookHandler, } from '@commerce' import { FetcherError } from '@commerce/utils/errors' -import type { CartInput } from '@commerce/cart/use-cart' +import type { HookHandler } from '@commerce/utils/types' +import type { FetchCartInput } from '@commerce/cart/use-cart' import { normalizeCart } from './lib/normalize' import { Cart } from './types' @@ -51,7 +51,8 @@ const fetcher: Fetcher = async ({ const useCart: HookHandler< Cart | null, - CartInput, + [], + FetchCartInput, any, any, { isEmpty?: boolean } @@ -63,9 +64,6 @@ const useCart: HookHandler< swrOptions: { revalidateOnFocus: false, }, - // fetcher(context) { - // return undefined as any - // }, normalizer: normalizeCart, onResponse(response) { return Object.create(response, { diff --git a/framework/commerce/cart/use-cart.tsx b/framework/commerce/cart/use-cart.tsx index 77271b593..7c6730497 100644 --- a/framework/commerce/cart/use-cart.tsx +++ b/framework/commerce/cart/use-cart.tsx @@ -6,7 +6,7 @@ import useData from '../utils/use-data-2' import { Provider, useCommerce } from '..' // Input expected by the `useCart` hook -export type CartInput = { +export type FetchCartInput = { cartId?: Cart['id'] } @@ -14,9 +14,15 @@ export type CartResponse

= ReturnType< NonNullable['useCart']>['onResponse']> > -export type UseCart

= () => CartResponse

+export type UseCart

= ( + ...input: UseCartInput

+) => CartResponse

-export const fetcher: HookFetcherFn = async ({ +export type UseCartInput

= NonNullable< + NonNullable['useCart']>>['input'] +> + +export const fetcher: HookFetcherFn = async ({ options, input: { cartId }, fetch, @@ -26,7 +32,7 @@ export const fetcher: HookFetcherFn = async ({ return data && normalize ? normalize(data) : data } -export default function useCart

() { +export default function useCart

(...input: UseCartInput

) { const { providerRef, cartCookie } = useCommerce

() const provider = providerRef.current @@ -36,7 +42,7 @@ export default function useCart

() { context.input.cartId = Cookies.get(cartCookie) return fetcherFn(context) } - const response = useData(opts!, [], wrapper, opts?.swrOptions) + const response = useData(opts!, input, wrapper, opts?.swrOptions) const memoizedResponse = useMemo( () => (opts?.onResponse ? opts.onResponse(response) : response), [response] diff --git a/framework/commerce/index.tsx b/framework/commerce/index.tsx index bc660b1df..f329c8054 100644 --- a/framework/commerce/index.tsx +++ b/framework/commerce/index.tsx @@ -7,27 +7,16 @@ import { useRef, } from 'react' import * as React from 'react' -import { Fetcher, HookFetcherFn, HookFetcherOptions } from './utils/types' +import { Fetcher, HookHandler } from './utils/types' import { Cart } from './types' -import type { ResponseState, SwrOptions } from './utils/use-data' -import type { CartInput } from './cart/use-cart' +import type { FetchCartInput } from './cart/use-cart' const Commerce = createContext | {}>({}) export type Provider = CommerceConfig & { cart?: { - useCart?: HookHandler + useCart?: HookHandler } - cartNormalizer(data: any): Cart -} - -export type HookHandler = { - swrOptions?: SwrOptions - onResponse?(response: ResponseState): ResponseState & State - onMutation?: any - fetchOptions?: HookFetcherOptions - fetcher?: HookFetcherFn - normalizer?(data: Result): Data } export type CommerceProps

= { diff --git a/framework/commerce/utils/types.ts b/framework/commerce/utils/types.ts index 3428b5194..bef1f2d8b 100644 --- a/framework/commerce/utils/types.ts +++ b/framework/commerce/utils/types.ts @@ -1,3 +1,7 @@ +import type { ResponseState, SwrOptions } from './use-data' + +export type Override = Omit & K + // Core fetcher added by CommerceProvider export type Fetcher = (options: FetcherOptions) => T | Promise @@ -15,7 +19,12 @@ export type HookFetcher = ( fetch: (options: FetcherOptions) => Promise ) => Data | Promise -export type HookFetcherFn = (context: { +export type HookFetcherFn< + Data, + Input = unknown, + Result = any, + Body = any +> = (context: { options: HookFetcherOptions | null input: Input fetch: (options: FetcherOptions) => Promise @@ -30,4 +39,25 @@ export type HookFetcherOptions = { export type HookInput = [string, string | number | boolean | undefined][] -export type Override = Omit & K +export type HookHandler< + // Data obj returned by the hook and fetch operation + Data, + // Input expected by the hook + Input = [...any], + // Input expected before doing a fetch operation + FetchInput = unknown, + // Data returned by the API after a fetch operation + Result = any, + // Body expected by the API endpoint + Body = any, + // Custom state added to the response object of SWR + State = {} +> = { + input?: Input + swrOptions?: SwrOptions + onResponse?(response: ResponseState): ResponseState & State + onMutation?: any + fetchOptions?: HookFetcherOptions + fetcher?: HookFetcherFn + normalizer?(data: Result): Data +} diff --git a/framework/commerce/utils/use-data-2.ts b/framework/commerce/utils/use-data-2.ts index 76fce8960..840251409 100644 --- a/framework/commerce/utils/use-data-2.ts +++ b/framework/commerce/utils/use-data-2.ts @@ -1,8 +1,13 @@ import useSWR, { ConfigInterface, responseInterface } from 'swr' -import type { HookInput, HookFetcher, HookFetcherFn } from './types' +import type { + HookHandler, + HookInput, + HookFetcher, + HookFetcherFn, +} from './types' import defineProperty from './define-property' import { CommerceError } from './errors' -import { HookHandler, useCommerce } from '..' +import { useCommerce } from '..' export type SwrOptions = ConfigInterface< Data, @@ -14,11 +19,17 @@ export type ResponseState = responseInterface & { isLoading: boolean } -export type UseData = ( - options: HookHandler, +export type UseData = < + Data = any, + Input = [...any], + FetchInput = unknown, + Result = any, + Body = any +>( + options: HookHandler, input: HookInput, - fetcherFn: HookFetcherFn, - swrOptions?: SwrOptions + fetcherFn: HookFetcherFn, + swrOptions?: SwrOptions ) => ResponseState const useData: UseData = (options, input, fetcherFn, swrOptions) => {