diff --git a/framework/bigcommerce/provider.ts b/framework/bigcommerce/provider.tsx similarity index 86% rename from framework/bigcommerce/provider.ts rename to framework/bigcommerce/provider.tsx index e4ab5c757..0d794edd9 100644 --- a/framework/bigcommerce/provider.ts +++ b/framework/bigcommerce/provider.tsx @@ -1,3 +1,4 @@ +import { useMemo } from 'react' import { FetcherError } from '@commerce/utils/errors' import type { Fetcher, HookHandler } from '@commerce/utils/types' import type { FetchCartInput } from '@commerce/cart/use-cart' @@ -57,6 +58,22 @@ const useCart: HookHandler< revalidateOnFocus: false, }, normalizer: normalizeCart, + useHook({ input, useData }) { + const response = useData({ input }) + + return useMemo( + () => + Object.create(response, { + isEmpty: { + get() { + return (response.data?.lineItems.length ?? 0) <= 0 + }, + enumerable: true, + }, + }), + [response] + ) + }, onResponse(response) { return Object.create(response, { isEmpty: { diff --git a/framework/commerce/cart/use-cart.tsx b/framework/commerce/cart/use-cart.tsx index 8f40fd055..4ca20df69 100644 --- a/framework/commerce/cart/use-cart.tsx +++ b/framework/commerce/cart/use-cart.tsx @@ -1,23 +1,24 @@ import { useMemo } from 'react' import Cookies from 'js-cookie' -import type { HookFetcherFn } from '../utils/types' -import useData from '../utils/use-data-2' import type { Cart } from '../types' +import type { Prop, HookFetcherFn, UseHookInput } from '../utils/types' +import useData from '../utils/use-data-2' import { Provider, useCommerce } from '..' export type FetchCartInput = { cartId?: Cart['id'] } -export type CartResponse

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

= Prop< + Prop, + 'useCart' > -export type UseCartInput

= Parameters< - NonNullable< - NonNullable['useCart']>>['input'] - > ->[0] +export type CartResponse

= ReturnType< + Prop, 'onResponse'> +> + +export type UseCartInput

= UseHookInput> export type UseCart

= Partial< UseCartInput

@@ -35,25 +36,59 @@ export const fetcher: HookFetcherFn = async ({ return data && normalize ? normalize(data) : data } -export default function useCart

(input?: UseCartInput

) { +type X = UseCartInput + +export default function useCart

( + input: UseCartInput

= {} +) { const { providerRef, fetcherRef, cartCookie } = useCommerce

() const provider = providerRef.current const opts = provider.cart?.useCart - const fetcherFn = opts?.fetcher ?? fetcher - const wrapper: typeof fetcher = (context) => { - context.input.cartId = Cookies.get(cartCookie) - return fetcherFn(context) - } - const response = useData( - { ...opts, fetcher: wrapper }, - opts?.input ? opts.input(input ?? {}) : [], - provider.fetcher ?? fetcherRef.current - ) - const memoizedResponse = useMemo( - () => (opts?.onResponse ? opts.onResponse(response) : response), - [response] - ) - return memoizedResponse as CartResponse

+ const { swrOptions, ...hookInput } = input + + return opts?.useHook!({ + input: hookInput, + swrOptions, + useData(ctx) { + const fetcherFn = opts?.fetcher ?? fetcher + const wrapper: typeof fetcher = (context) => { + context.input.cartId = Cookies.get(cartCookie) + return fetcherFn(context) + } + const response = useData( + { + ...opts, + fetcher: wrapper, + swrOptions: { + ...opts.swrOptions, + ...(ctx?.swrOptions ?? swrOptions), + }, + }, + ctx?.input ?? [], + provider.fetcher ?? fetcherRef.current + ) + return response + }, + }) + + // console.log(i) + + // const fetcherFn = opts?.fetcher ?? fetcher + // const wrapper: typeof fetcher = (context) => { + // context.input.cartId = Cookies.get(cartCookie) + // return fetcherFn(context) + // } + // const response = useData( + // { ...opts, fetcher: wrapper }, + // opts?.input ? opts.input(input ?? {}) : [], + // provider.fetcher ?? fetcherRef.current + // ) + // const memoizedResponse = useMemo( + // () => (opts?.onResponse ? opts.onResponse(response) : response), + // [response] + // ) + + // return memoizedResponse as CartResponse

} diff --git a/framework/commerce/utils/types.ts b/framework/commerce/utils/types.ts index 6b4f1ddbe..d4d767ae1 100644 --- a/framework/commerce/utils/types.ts +++ b/framework/commerce/utils/types.ts @@ -74,9 +74,16 @@ export type HookHandler< input?( input: Input & { swrOptions?: SwrOptions } ): HookFetchInput | HookSwrInput + useHook?(context: { + input: Input + swrOptions?: SwrOptions + useData(context?: { + input?: HookFetchInput | HookSwrInput + swrOptions?: SwrOptions + }): ResponseState + }): ResponseState & State swrOptions?: SwrOptions onResponse?(response: ResponseState): ResponseState & State - onMutation?: any fetchOptions?: HookFetcherOptions fetcher?: HookFetcherFn normalizer?(data: Result): Data @@ -87,3 +94,18 @@ export type SwrOptions = ConfigInterface< CommerceError, HookFetcher > + +/** + * Returns the property K from type T excluding nullables + */ +export type Prop = NonNullable + +export type UseHookParameters> = Parameters< + Prop +> + +export type UseHookInput< + H extends HookHandler +> = UseHookParameters[0]['input'] & { + swrOptions?: UseHookParameters[0]['swrOptions'] +}