mirror of
https://github.com/vercel/commerce.git
synced 2025-03-14 22:42:33 +00:00
Moved more hooks and updated types to make them smaller
This commit is contained in:
parent
a7df259bda
commit
2e1d2610bb
@ -1,13 +1,12 @@
|
||||
import { useMemo } from 'react'
|
||||
import { HookHandler } from '@commerce/utils/types'
|
||||
import { SWRHook } from '@commerce/utils/types'
|
||||
import useCart, { UseCart, FetchCartInput } from '@commerce/cart/use-cart'
|
||||
import { normalizeCart } from '../lib/normalize'
|
||||
import type { Cart } from '../types'
|
||||
import type { BigcommerceProvider } from '..'
|
||||
|
||||
export default useCart as UseCart<BigcommerceProvider>
|
||||
export default useCart as UseCart<typeof handler>
|
||||
|
||||
export const handler: HookHandler<
|
||||
export const handler: SWRHook<
|
||||
Cart | null,
|
||||
{},
|
||||
FetchCartInput,
|
||||
@ -21,9 +20,9 @@ export const handler: HookHandler<
|
||||
const data = cartId ? await fetch(options) : null
|
||||
return data && normalizeCart(data)
|
||||
},
|
||||
useHook({ input, useData }) {
|
||||
useHook: ({ useData }) => (input) => {
|
||||
const response = useData({
|
||||
swrOptions: { revalidateOnFocus: false, ...input.swrOptions },
|
||||
swrOptions: { revalidateOnFocus: false, ...input?.swrOptions },
|
||||
})
|
||||
|
||||
return useMemo(
|
||||
|
@ -46,7 +46,7 @@ export const handler = {
|
||||
ctx: { item?: T } = {}
|
||||
) => {
|
||||
const { item } = ctx
|
||||
const { mutate } = useCart() as any
|
||||
const { mutate } = useCart()
|
||||
const removeItem: RemoveItemFn<LineItem> = async (input) => {
|
||||
const itemId = input?.id ?? item?.id
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import useHook, { useHookHandler } from '../utils/use-hook'
|
||||
import { useHook, useMutationHook } from '../utils/use-hook'
|
||||
import { mutationFetcher } from '../utils/default-fetcher'
|
||||
import type { MutationHook, HookFetcherFn } from '../utils/types'
|
||||
import type { Cart, CartItemBody, AddCartItemBody } from '../types'
|
||||
import type { Provider } from '..'
|
||||
@ -6,9 +7,7 @@ import type { Provider } from '..'
|
||||
export const fetcher: HookFetcherFn<
|
||||
Cart,
|
||||
AddCartItemBody<CartItemBody>
|
||||
> = async ({ options, input, fetch }) => {
|
||||
return fetch({ ...options, body: input })
|
||||
}
|
||||
> = mutationFetcher
|
||||
|
||||
export type UseAddItem<
|
||||
H extends MutationHook<any, any, any> = MutationHook<Cart, {}, CartItemBody>
|
||||
@ -17,8 +16,8 @@ export type UseAddItem<
|
||||
const fn = (provider: Provider) => provider.cart?.useAddItem!
|
||||
|
||||
const useAddItem: UseAddItem = (...args) => {
|
||||
const handler = useHookHandler(fn, fetcher)
|
||||
return handler(useHook(fn, fetcher))(...args)
|
||||
const hook = useHook(fn)
|
||||
return useMutationHook({ fetcher, ...hook })(...args)
|
||||
}
|
||||
|
||||
export default useAddItem
|
||||
|
@ -1,34 +1,21 @@
|
||||
import Cookies from 'js-cookie'
|
||||
import type { Cart } from '../types'
|
||||
import type {
|
||||
Prop,
|
||||
HookFetcherFn,
|
||||
UseHookInput,
|
||||
UseHookResponse,
|
||||
} from '../utils/types'
|
||||
import useData from '../utils/use-data'
|
||||
import type { HookFetcherFn, SWRHook } from '../utils/types'
|
||||
import { Provider, useCommerce } from '..'
|
||||
import { useHook, useSWRHook } from '@commerce/utils/use-hook'
|
||||
|
||||
export type FetchCartInput = {
|
||||
cartId?: Cart['id']
|
||||
}
|
||||
|
||||
export type UseCartHandler<P extends Provider> = Prop<
|
||||
Prop<P, 'cart'>,
|
||||
'useCart'
|
||||
>
|
||||
|
||||
export type UseCartInput<P extends Provider> = UseHookInput<UseCartHandler<P>>
|
||||
|
||||
export type CartResponse<P extends Provider> = UseHookResponse<
|
||||
UseCartHandler<P>
|
||||
>
|
||||
|
||||
export type UseCart<P extends Provider> = Partial<
|
||||
UseCartInput<P>
|
||||
> extends UseCartInput<P>
|
||||
? (input?: UseCartInput<P>) => CartResponse<P>
|
||||
: (input: UseCartInput<P>) => CartResponse<P>
|
||||
export type UseCart<
|
||||
H extends SWRHook<any, any, any> = SWRHook<
|
||||
Cart | null,
|
||||
{},
|
||||
FetchCartInput,
|
||||
{ isEmpty?: boolean }
|
||||
>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher: HookFetcherFn<Cart | null, FetchCartInput> = async ({
|
||||
options,
|
||||
@ -38,32 +25,17 @@ export const fetcher: HookFetcherFn<Cart | null, FetchCartInput> = async ({
|
||||
return cartId ? await fetch({ ...options }) : null
|
||||
}
|
||||
|
||||
export default function useCart<P extends Provider>(
|
||||
input: UseCartInput<P> = {}
|
||||
) {
|
||||
const { providerRef, fetcherRef, cartCookie } = useCommerce<P>()
|
||||
|
||||
const provider = providerRef.current
|
||||
const opts = provider.cart?.useCart
|
||||
|
||||
const fetcherFn = opts?.fetcher ?? fetcher
|
||||
const useHook = opts?.useHook ?? ((ctx) => ctx.useData())
|
||||
const fn = (provider: Provider) => provider.cart?.useCart!
|
||||
|
||||
const useCart: UseCart = (input) => {
|
||||
const hook = useHook(fn)
|
||||
const { cartCookie } = useCommerce()
|
||||
const fetcherFn = hook.fetcher ?? fetcher
|
||||
const wrapper: typeof fetcher = (context) => {
|
||||
context.input.cartId = Cookies.get(cartCookie)
|
||||
return fetcherFn(context)
|
||||
}
|
||||
|
||||
return useHook({
|
||||
input,
|
||||
useData(ctx) {
|
||||
const response = useData(
|
||||
{ ...opts!, fetcher: wrapper },
|
||||
ctx?.input ?? [],
|
||||
provider.fetcher ?? fetcherRef.current,
|
||||
ctx?.swrOptions ?? input.swrOptions
|
||||
)
|
||||
return response
|
||||
},
|
||||
})
|
||||
return useSWRHook({ ...hook, fetcher: wrapper })(input)
|
||||
}
|
||||
|
||||
export default useCart
|
||||
|
@ -1,6 +1,6 @@
|
||||
import useHook, { useHookHandler } from '../utils/use-hook'
|
||||
import { useHook, useMutationHook } from '../utils/use-hook'
|
||||
import { mutationFetcher } from '../utils/default-fetcher'
|
||||
import type { MutationHook } from '../utils/types'
|
||||
import type { HookFetcherFn, MutationHook } from '../utils/types'
|
||||
import type { Cart, LineItem, RemoveCartItemBody } from '../types'
|
||||
import type { Provider } from '..'
|
||||
|
||||
@ -20,13 +20,16 @@ export type UseRemoveItem<
|
||||
>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher = mutationFetcher
|
||||
export const fetcher: HookFetcherFn<
|
||||
Cart | null,
|
||||
RemoveCartItemBody
|
||||
> = mutationFetcher
|
||||
|
||||
const fn = (provider: Provider) => provider.cart?.useRemoveItem!
|
||||
|
||||
const useRemoveItem: UseRemoveItem = (input) => {
|
||||
const handler = useHookHandler(fn, fetcher)
|
||||
return handler(useHook(fn, fetcher))(input)
|
||||
const hook = useHook(fn)
|
||||
return useMutationHook({ fetcher, ...hook })(input)
|
||||
}
|
||||
|
||||
export default useRemoveItem
|
||||
|
@ -1,6 +1,6 @@
|
||||
import useHook, { useHookHandler } from '../utils/use-hook'
|
||||
import { useHook, useMutationHook } from '../utils/use-hook'
|
||||
import { mutationFetcher } from '../utils/default-fetcher'
|
||||
import type { MutationHook } from '../utils/types'
|
||||
import type { HookFetcherFn, MutationHook } from '../utils/types'
|
||||
import type { Cart, CartItemBody, LineItem, UpdateCartItemBody } from '../types'
|
||||
import type { Provider } from '..'
|
||||
|
||||
@ -23,13 +23,16 @@ export type UseUpdateItem<
|
||||
>
|
||||
> = ReturnType<H['useHook']>
|
||||
|
||||
export const fetcher = mutationFetcher
|
||||
export const fetcher: HookFetcherFn<
|
||||
Cart | null,
|
||||
UpdateCartItemBody<CartItemBody>
|
||||
> = mutationFetcher
|
||||
|
||||
const fn = (provider: Provider) => provider.cart?.useUpdateItem!
|
||||
|
||||
const useUpdateItem: UseUpdateItem = (input) => {
|
||||
const handler = useHookHandler(fn, fetcher)
|
||||
return handler(useHook(fn, fetcher))(input)
|
||||
const hook = useHook(fn)
|
||||
return useMutationHook({ fetcher, ...hook })(input)
|
||||
}
|
||||
|
||||
export default useUpdateItem
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
useMemo,
|
||||
useRef,
|
||||
} from 'react'
|
||||
import { Fetcher, HookHandler, MutationHook } from './utils/types'
|
||||
import { Fetcher, HookHandler, SWRHook, MutationHook } from './utils/types'
|
||||
import type { FetchCartInput } from './cart/use-cart'
|
||||
import type { Cart, Wishlist, Customer, SearchProductsData } from './types'
|
||||
|
||||
@ -15,7 +15,7 @@ const Commerce = createContext<CommerceContextValue<any> | {}>({})
|
||||
export type Provider = CommerceConfig & {
|
||||
fetcher: Fetcher
|
||||
cart?: {
|
||||
useCart?: HookHandler<Cart | null, any, FetchCartInput>
|
||||
useCart?: SWRHook<Cart | null, any, FetchCartInput>
|
||||
useAddItem?: MutationHook<any, any, any>
|
||||
useUpdateItem?: MutationHook<any, any, any>
|
||||
useRemoveItem?: MutationHook<any, any, any>
|
||||
|
@ -3,7 +3,7 @@ import type { HookFetcherFn } from './types'
|
||||
const defaultFetcher: HookFetcherFn<any> = ({ options, fetch }) =>
|
||||
fetch(options)
|
||||
|
||||
export const mutationFetcher: HookFetcherFn<any> = ({
|
||||
export const mutationFetcher: HookFetcherFn<any, any> = ({
|
||||
input,
|
||||
options,
|
||||
fetch,
|
||||
|
@ -9,7 +9,9 @@ export type Override<T, K> = Omit<T, keyof K> & K
|
||||
* Returns the properties in T with the properties in type K changed from optional to required
|
||||
*/
|
||||
export type PickRequired<T, K extends keyof T> = Omit<T, K> &
|
||||
Required<Pick<T, K>>
|
||||
{
|
||||
[P in K]-?: NonNullable<T[P]>
|
||||
}
|
||||
|
||||
/**
|
||||
* Core fetcher added by CommerceProvider
|
||||
@ -83,6 +85,36 @@ export type HookFunction<
|
||||
? (input?: Input) => T
|
||||
: (input: Input) => T
|
||||
|
||||
export type SWRHook<
|
||||
// Data obj returned by the hook and fetch operation
|
||||
Data,
|
||||
// Input expected by the hook
|
||||
Input extends { [k: string]: unknown } = {},
|
||||
// Input expected before doing a fetch operation
|
||||
FetchInput extends HookFetchInput = {},
|
||||
// Custom state added to the response object of SWR
|
||||
State = {}
|
||||
> = {
|
||||
useHook(
|
||||
context: SWRHookContext<Data, FetchInput>
|
||||
): HookFunction<
|
||||
Input & { swrOptions?: SwrOptions<Data, FetchInput> },
|
||||
ResponseState<Data> & State
|
||||
>
|
||||
fetchOptions: HookFetcherOptions
|
||||
fetcher?: HookFetcherFn<Data, FetchInput>
|
||||
}
|
||||
|
||||
export type SWRHookContext<
|
||||
Data,
|
||||
FetchInput extends { [k: string]: unknown } = {}
|
||||
> = {
|
||||
useData(context?: {
|
||||
input?: HookFetchInput | HookSwrInput
|
||||
swrOptions?: SwrOptions<Data, FetchInput>
|
||||
}): ResponseState<Data>
|
||||
}
|
||||
|
||||
export type MutationHook<
|
||||
// Data obj returned by the hook and fetch operation
|
||||
Data,
|
||||
@ -118,9 +150,7 @@ export type SwrOptions<Data, Input = null, Result = any> = ConfigInterface<
|
||||
*/
|
||||
export type Prop<T, K extends keyof T> = NonNullable<T[K]>
|
||||
|
||||
export type HookHandlerType =
|
||||
| HookHandler<any, any, any>
|
||||
| MutationHandler<any, any, any>
|
||||
export type HookHandlerType = HookHandler<any, any, any>
|
||||
|
||||
export type UseHookParameters<H extends HookHandlerType> = Parameters<
|
||||
Prop<H, 'useHook'>
|
||||
|
@ -1,11 +1,11 @@
|
||||
import useSWR, { responseInterface } from 'swr'
|
||||
import type {
|
||||
HookHandler,
|
||||
HookSwrInput,
|
||||
HookFetchInput,
|
||||
PickRequired,
|
||||
Fetcher,
|
||||
SwrOptions,
|
||||
HookFetcherOptions,
|
||||
HookFetcherFn,
|
||||
} from './types'
|
||||
import defineProperty from './define-property'
|
||||
import { CommerceError } from './errors'
|
||||
@ -19,7 +19,10 @@ export type UseData = <
|
||||
Input extends { [k: string]: unknown } = {},
|
||||
FetchInput extends HookFetchInput = {}
|
||||
>(
|
||||
options: PickRequired<HookHandler<Data, Input, FetchInput>, 'fetcher'>,
|
||||
options: {
|
||||
fetchOptions: HookFetcherOptions
|
||||
fetcher: HookFetcherFn<Data, FetchInput>
|
||||
},
|
||||
input: HookFetchInput | HookSwrInput,
|
||||
fetcherFn: Fetcher,
|
||||
swrOptions?: SwrOptions<Data, FetchInput>
|
||||
|
@ -1,43 +1,50 @@
|
||||
import { useCallback } from 'react'
|
||||
import type { MutationHook } from './types'
|
||||
import type { Fetcher, MutationHook, PickRequired, SWRHook } from './types'
|
||||
import { Provider, useCommerce } from '..'
|
||||
import useData from './use-data'
|
||||
|
||||
export function useHookHandler<P extends Provider>(
|
||||
fn: (provider: P) => MutationHook<any, any, any>,
|
||||
fetcher: any
|
||||
) {
|
||||
export function useFetcher() {
|
||||
const { providerRef, fetcherRef } = useCommerce()
|
||||
return providerRef.current.fetcher ?? fetcherRef.current
|
||||
}
|
||||
|
||||
export function useHook<
|
||||
P extends Provider,
|
||||
H extends MutationHook<any, any, any> | SWRHook<any, any, any>
|
||||
>(fn: (provider: P) => H) {
|
||||
const { providerRef } = useCommerce<P>()
|
||||
const provider = providerRef.current
|
||||
const opts = fn(provider)
|
||||
const handler =
|
||||
opts.useHook ??
|
||||
(() => {
|
||||
const { fetch } = useHook(fn, fetcher)
|
||||
return (input: any) => fetch({ input })
|
||||
})
|
||||
|
||||
return handler
|
||||
return fn(provider)
|
||||
}
|
||||
|
||||
export default function useHook<P extends Provider>(
|
||||
fn: (provider: P) => MutationHook<any, any, any>,
|
||||
fetcher: any
|
||||
export function useSWRHook<H extends SWRHook<any, any, any>>(
|
||||
hook: PickRequired<H, 'fetcher'>
|
||||
) {
|
||||
const { providerRef, fetcherRef } = useCommerce<P>()
|
||||
const provider = providerRef.current
|
||||
const opts = fn(provider)
|
||||
const fetcherFn = opts.fetcher ?? fetcher
|
||||
const fetchFn = provider.fetcher ?? fetcherRef.current
|
||||
const fetch = useCallback(
|
||||
({ input }: { input: any }) => {
|
||||
return fetcherFn({
|
||||
input,
|
||||
options: opts.fetchOptions,
|
||||
fetch: fetchFn,
|
||||
})
|
||||
},
|
||||
[fetchFn, opts.fetchOptions]
|
||||
)
|
||||
const fetcher = useFetcher()
|
||||
|
||||
return { fetch }
|
||||
return hook.useHook({
|
||||
useData(ctx) {
|
||||
const response = useData(hook, ctx?.input ?? [], fetcher, ctx?.swrOptions)
|
||||
return response
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useMutationHook<H extends MutationHook<any, any, any>>(
|
||||
hook: PickRequired<H, 'fetcher'>
|
||||
) {
|
||||
const fetcher = useFetcher()
|
||||
|
||||
return hook.useHook({
|
||||
fetch: useCallback(
|
||||
({ input }) => {
|
||||
return hook.fetcher({
|
||||
input,
|
||||
options: hook.fetchOptions,
|
||||
fetch: fetcher,
|
||||
})
|
||||
},
|
||||
[fetcher, hook.fetchOptions]
|
||||
),
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user