Added useResponse hook
This commit is contained in:
		@@ -1,10 +1,9 @@
 | 
			
		||||
import { normalizeCart } from '../lib/normalize'
 | 
			
		||||
import type { HookFetcher } from '@commerce/utils/types'
 | 
			
		||||
import type { SwrOptions } from '@commerce/utils/use-data'
 | 
			
		||||
import defineProperty from '@commerce/utils/define-property'
 | 
			
		||||
import useResponse from '@commerce/utils/use-response'
 | 
			
		||||
import useCommerceCart, { CartInput } from '@commerce/cart/use-cart'
 | 
			
		||||
import type { Cart as BigCommerceCart } from '../api/cart'
 | 
			
		||||
import update from '@framework/lib/immutability'
 | 
			
		||||
 | 
			
		||||
const defaultOpts = {
 | 
			
		||||
  url: '/api/bigcommerce/cart',
 | 
			
		||||
@@ -30,25 +29,21 @@ export function extendHook(
 | 
			
		||||
      revalidateOnFocus: false,
 | 
			
		||||
      ...swrOptions,
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    // Uses a getter to only calculate the prop when required
 | 
			
		||||
    // response.data is also a getter and it's better to not trigger it early
 | 
			
		||||
    if (!('isEmpty' in response)) {
 | 
			
		||||
      defineProperty(response, 'isEmpty', {
 | 
			
		||||
        get() {
 | 
			
		||||
          return Object.values(response.data?.line_items ?? {}).every(
 | 
			
		||||
            (items) => !items.length
 | 
			
		||||
          )
 | 
			
		||||
    const res = useResponse(response, {
 | 
			
		||||
      normalizer: normalizeCart,
 | 
			
		||||
      descriptors: {
 | 
			
		||||
        isEmpty: {
 | 
			
		||||
          get() {
 | 
			
		||||
            return Object.values(response.data?.line_items ?? {}).every(
 | 
			
		||||
              (items) => !items.length
 | 
			
		||||
            )
 | 
			
		||||
          },
 | 
			
		||||
          enumerable: true,
 | 
			
		||||
        },
 | 
			
		||||
        set: (x) => x,
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    return response.data
 | 
			
		||||
      ? update(response, {
 | 
			
		||||
          data: { $set: normalizeCart(response.data) },
 | 
			
		||||
        })
 | 
			
		||||
      : response
 | 
			
		||||
    return res
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  useCart.extend = extendHook
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
import type { responseInterface } from 'swr'
 | 
			
		||||
import Cookies from 'js-cookie'
 | 
			
		||||
import type { HookInput, HookFetcher, HookFetcherOptions } from '../utils/types'
 | 
			
		||||
import useData, { ResponseState, SwrOptions } from '../utils/use-data'
 | 
			
		||||
@@ -17,12 +16,10 @@ export default function useCart<Result>(
 | 
			
		||||
  swrOptions?: SwrOptions<Result, CartInput>
 | 
			
		||||
): CartResponse<Result> {
 | 
			
		||||
  const { cartCookie } = useCommerce()
 | 
			
		||||
 | 
			
		||||
  const fetcher: typeof fetcherFn = (options, input, fetch) => {
 | 
			
		||||
    input.cartId = Cookies.get(cartCookie)
 | 
			
		||||
    return fetcherFn(options, input, fetch)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const response = useData(options, input, fetcher, swrOptions)
 | 
			
		||||
 | 
			
		||||
  return response
 | 
			
		||||
 
 | 
			
		||||
@@ -22,3 +22,5 @@ export type HookFetcherOptions = {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type HookInput = [string, string | number | boolean | undefined][]
 | 
			
		||||
 | 
			
		||||
export type Override<T, K> = Omit<T, keyof K> & K
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ const useData: UseData = (options, input, fetcherFn, swrOptions) => {
 | 
			
		||||
      get() {
 | 
			
		||||
        return response.data === undefined
 | 
			
		||||
      },
 | 
			
		||||
      set: (x) => x,
 | 
			
		||||
      enumerable: true,
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								framework/commerce/utils/use-response.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								framework/commerce/utils/use-response.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
import { useMemo } from 'react'
 | 
			
		||||
import { responseInterface } from 'swr'
 | 
			
		||||
import { CommerceError } from './errors'
 | 
			
		||||
import { Override } from './types'
 | 
			
		||||
 | 
			
		||||
export type UseResponseOptions<
 | 
			
		||||
  D,
 | 
			
		||||
  R extends responseInterface<any, CommerceError>
 | 
			
		||||
> = {
 | 
			
		||||
  descriptors?: PropertyDescriptorMap
 | 
			
		||||
  normalizer?: (data: R['data']) => D
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type UseResponse = <D, R extends responseInterface<any, CommerceError>>(
 | 
			
		||||
  response: R,
 | 
			
		||||
  options: UseResponseOptions<D, R>
 | 
			
		||||
) => D extends object ? Override<R, { data?: D }> : R
 | 
			
		||||
 | 
			
		||||
const useResponse: UseResponse = (response, { descriptors, normalizer }) => {
 | 
			
		||||
  const memoizedResponse = useMemo(
 | 
			
		||||
    () =>
 | 
			
		||||
      Object.create(response, {
 | 
			
		||||
        ...descriptors,
 | 
			
		||||
        ...(normalizer
 | 
			
		||||
          ? {
 | 
			
		||||
              data: {
 | 
			
		||||
                get() {
 | 
			
		||||
                  return normalizer(response.data)
 | 
			
		||||
                },
 | 
			
		||||
                enumerable: true,
 | 
			
		||||
              },
 | 
			
		||||
            }
 | 
			
		||||
          : {}),
 | 
			
		||||
      }),
 | 
			
		||||
    [response]
 | 
			
		||||
  )
 | 
			
		||||
  return memoizedResponse
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default useResponse
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
import type { responseInterface } from 'swr'
 | 
			
		||||
import type { HookInput, HookFetcher, HookFetcherOptions } from '../utils/types'
 | 
			
		||||
import useData, { ResponseState, SwrOptions } from '../utils/use-data'
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user