mirror of
https://github.com/vercel/commerce.git
synced 2025-04-06 19:55:54 +00:00
Added better mutation types, and moved some hooks
This commit is contained in:
parent
c02d7fec62
commit
74da22d5f4
@ -33,7 +33,7 @@ const CartItem = ({
|
|||||||
currencyCode,
|
currencyCode,
|
||||||
})
|
})
|
||||||
|
|
||||||
const updateItem = useUpdateItem(item)
|
const updateItem = useUpdateItem({ item })
|
||||||
const removeItem = useRemoveItem()
|
const removeItem = useRemoveItem()
|
||||||
const [quantity, setQuantity] = useState(item.quantity)
|
const [quantity, setQuantity] = useState(item.quantity)
|
||||||
const [removing, setRemoving] = useState(false)
|
const [removing, setRemoving] = useState(false)
|
||||||
|
@ -1,29 +1,24 @@
|
|||||||
import type { MutationHandler } from '@commerce/utils/types'
|
import { useCallback } from 'react'
|
||||||
|
import type { MutationHook } from '@commerce/utils/types'
|
||||||
import { CommerceError } from '@commerce/utils/errors'
|
import { CommerceError } from '@commerce/utils/errors'
|
||||||
import useAddItem, { UseAddItem } from '@commerce/cart/use-add-item'
|
import useAddItem, { UseAddItem } from '@commerce/cart/use-add-item'
|
||||||
import { normalizeCart } from '../lib/normalize'
|
import { normalizeCart } from '../lib/normalize'
|
||||||
import type {
|
import type {
|
||||||
AddCartItemBody,
|
|
||||||
Cart,
|
Cart,
|
||||||
BigcommerceCart,
|
BigcommerceCart,
|
||||||
CartItemBody,
|
CartItemBody,
|
||||||
|
AddCartItemBody,
|
||||||
} from '../types'
|
} from '../types'
|
||||||
import useCart from './use-cart'
|
import useCart from './use-cart'
|
||||||
import { BigcommerceProvider } from '..'
|
|
||||||
|
|
||||||
const defaultOpts = {
|
export default useAddItem as UseAddItem<typeof handler>
|
||||||
url: '/api/bigcommerce/cart',
|
|
||||||
method: 'POST',
|
|
||||||
}
|
|
||||||
|
|
||||||
export default useAddItem as UseAddItem<BigcommerceProvider, CartItemBody>
|
export const handler: MutationHook<Cart, {}, CartItemBody> = {
|
||||||
|
|
||||||
export const handler: MutationHandler<Cart, {}, AddCartItemBody> = {
|
|
||||||
fetchOptions: {
|
fetchOptions: {
|
||||||
url: '/api/bigcommerce/cart',
|
url: '/api/bigcommerce/cart',
|
||||||
method: 'GET',
|
method: 'POST',
|
||||||
},
|
},
|
||||||
async fetcher({ input: { item }, options, fetch }) {
|
async fetcher({ input: item, options, fetch }) {
|
||||||
if (
|
if (
|
||||||
item.quantity &&
|
item.quantity &&
|
||||||
(!Number.isInteger(item.quantity) || item.quantity! < 1)
|
(!Number.isInteger(item.quantity) || item.quantity! < 1)
|
||||||
@ -34,20 +29,22 @@ export const handler: MutationHandler<Cart, {}, AddCartItemBody> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await fetch<BigcommerceCart, AddCartItemBody>({
|
const data = await fetch<BigcommerceCart, AddCartItemBody>({
|
||||||
...defaultOpts,
|
|
||||||
...options,
|
...options,
|
||||||
body: { item },
|
body: { item },
|
||||||
})
|
})
|
||||||
|
|
||||||
return normalizeCart(data)
|
return normalizeCart(data)
|
||||||
},
|
},
|
||||||
useHook() {
|
useHook: ({ fetch }) => () => {
|
||||||
const { mutate } = useCart()
|
const { mutate } = useCart()
|
||||||
|
|
||||||
return async function addItem({ input, fetch }) {
|
return useCallback(
|
||||||
|
async function addItem(input) {
|
||||||
const data = await fetch({ input })
|
const data = await fetch({ input })
|
||||||
await mutate(data, false)
|
await mutate(data, false)
|
||||||
return data
|
return data
|
||||||
}
|
},
|
||||||
|
[fetch, mutate]
|
||||||
|
)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
import debounce from 'lodash.debounce'
|
import debounce from 'lodash.debounce'
|
||||||
import type { HookFetcher } from '@commerce/utils/types'
|
import type { HookContext, HookFetcherContext } from '@commerce/utils/types'
|
||||||
import { ValidationError } from '@commerce/utils/errors'
|
import { ValidationError } from '@commerce/utils/errors'
|
||||||
import useCartUpdateItem, {
|
import useUpdateItem, {
|
||||||
UpdateItemInput as UseUpdateItemInput,
|
UpdateItemInput as UpdateItemInputBase,
|
||||||
|
UseUpdateItem,
|
||||||
} from '@commerce/cart/use-update-item'
|
} from '@commerce/cart/use-update-item'
|
||||||
import { normalizeCart } from '../lib/normalize'
|
import { normalizeCart } from '../lib/normalize'
|
||||||
import type {
|
import type {
|
||||||
@ -15,20 +16,22 @@ import type {
|
|||||||
import { fetcher as removeFetcher } from './use-remove-item'
|
import { fetcher as removeFetcher } from './use-remove-item'
|
||||||
import useCart from './use-cart'
|
import useCart from './use-cart'
|
||||||
|
|
||||||
const defaultOpts = {
|
export type UpdateItemInput<T = any> = T extends LineItem
|
||||||
|
? Partial<UpdateItemInputBase<LineItem>>
|
||||||
|
: UpdateItemInputBase<LineItem>
|
||||||
|
|
||||||
|
export default useUpdateItem as UseUpdateItem<typeof handler>
|
||||||
|
|
||||||
|
export const handler = {
|
||||||
|
fetchOptions: {
|
||||||
url: '/api/bigcommerce/cart',
|
url: '/api/bigcommerce/cart',
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
}
|
},
|
||||||
|
async fetcher({
|
||||||
export type UpdateItemInput<T = any> = T extends LineItem
|
input: { itemId, item },
|
||||||
? Partial<UseUpdateItemInput<LineItem>>
|
|
||||||
: UseUpdateItemInput<LineItem>
|
|
||||||
|
|
||||||
export const fetcher: HookFetcher<Cart | null, UpdateCartItemBody> = async (
|
|
||||||
options,
|
options,
|
||||||
{ itemId, item },
|
fetch,
|
||||||
fetch
|
}: HookFetcherContext<UpdateCartItemBody>) {
|
||||||
) => {
|
|
||||||
if (Number.isInteger(item.quantity)) {
|
if (Number.isInteger(item.quantity)) {
|
||||||
// Also allow the update hook to remove an item if the quantity is lower than 1
|
// Also allow the update hook to remove an item if the quantity is lower than 1
|
||||||
if (item.quantity! < 1) {
|
if (item.quantity! < 1) {
|
||||||
@ -41,23 +44,22 @@ export const fetcher: HookFetcher<Cart | null, UpdateCartItemBody> = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const data = await fetch<BigcommerceCart, UpdateCartItemBody>({
|
const data = await fetch<BigcommerceCart, UpdateCartItemBody>({
|
||||||
...defaultOpts,
|
|
||||||
...options,
|
...options,
|
||||||
body: { itemId, item },
|
body: { itemId, item },
|
||||||
})
|
})
|
||||||
|
|
||||||
return normalizeCart(data)
|
return normalizeCart(data)
|
||||||
}
|
},
|
||||||
|
useHook: ({ fetch }: HookContext<Cart | null, UpdateCartItemBody>) => <
|
||||||
function extendHook(customFetcher: typeof fetcher, cfg?: { wait?: number }) {
|
T extends LineItem | undefined = undefined
|
||||||
const useUpdateItem = <T extends LineItem | undefined = undefined>(
|
>(
|
||||||
|
ctx: {
|
||||||
item?: T
|
item?: T
|
||||||
|
wait?: number
|
||||||
|
} = {}
|
||||||
) => {
|
) => {
|
||||||
const { mutate } = useCart()
|
const { item } = ctx
|
||||||
const fn = useCartUpdateItem<Cart | null, UpdateCartItemBody>(
|
const { mutate } = useCart() as any
|
||||||
defaultOpts,
|
|
||||||
customFetcher
|
|
||||||
)
|
|
||||||
|
|
||||||
return useCallback(
|
return useCallback(
|
||||||
debounce(async (input: UpdateItemInput<T>) => {
|
debounce(async (input: UpdateItemInput<T>) => {
|
||||||
@ -71,20 +73,16 @@ function extendHook(customFetcher: typeof fetcher, cfg?: { wait?: number }) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await fn({
|
const data = await fetch({
|
||||||
|
input: {
|
||||||
itemId,
|
itemId,
|
||||||
item: { productId, variantId, quantity: input.quantity },
|
item: { productId, variantId, quantity: input.quantity },
|
||||||
|
},
|
||||||
})
|
})
|
||||||
await mutate(data, false)
|
await mutate(data, false)
|
||||||
return data
|
return data
|
||||||
}, cfg?.wait ?? 500),
|
}, ctx.wait ?? 500),
|
||||||
[fn, mutate]
|
[fetch, mutate]
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
|
||||||
useUpdateItem.extend = extendHook
|
|
||||||
|
|
||||||
return useUpdateItem
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default extendHook(fetcher)
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { handler as useCart } from './cart/use-cart'
|
import { handler as useCart } from './cart/use-cart'
|
||||||
import { handler as useAddItem } from './cart/use-add-item'
|
import { handler as useAddItem } from './cart/use-add-item'
|
||||||
|
import { handler as useUpdateItem } from './cart/use-update-item'
|
||||||
import { handler as useWishlist } from './wishlist/use-wishlist'
|
import { handler as useWishlist } from './wishlist/use-wishlist'
|
||||||
import { handler as useCustomer } from './customer/use-customer'
|
import { handler as useCustomer } from './customer/use-customer'
|
||||||
import { handler as useSearch } from './product/use-search'
|
import { handler as useSearch } from './product/use-search'
|
||||||
@ -9,7 +10,7 @@ export const bigcommerceProvider = {
|
|||||||
locale: 'en-us',
|
locale: 'en-us',
|
||||||
cartCookie: 'bc_cartId',
|
cartCookie: 'bc_cartId',
|
||||||
fetcher,
|
fetcher,
|
||||||
cart: { useCart, useAddItem },
|
cart: { useCart, useAddItem, useUpdateItem },
|
||||||
wishlist: { useWishlist },
|
wishlist: { useWishlist },
|
||||||
customer: { useCustomer },
|
customer: { useCustomer },
|
||||||
products: { useSearch },
|
products: { useSearch },
|
||||||
|
@ -43,9 +43,6 @@ export type CartItemBody = Core.CartItemBody & {
|
|||||||
optionSelections?: OptionSelections
|
optionSelections?: OptionSelections
|
||||||
}
|
}
|
||||||
|
|
||||||
type X = Core.CartItemBody extends CartItemBody ? any : never
|
|
||||||
type Y = CartItemBody extends Core.CartItemBody ? any : never
|
|
||||||
|
|
||||||
export type GetCartHandlerBody = Core.GetCartHandlerBody
|
export type GetCartHandlerBody = Core.GetCartHandlerBody
|
||||||
|
|
||||||
export type AddCartItemBody = Core.AddCartItemBody<CartItemBody>
|
export type AddCartItemBody = Core.AddCartItemBody<CartItemBody>
|
||||||
|
@ -1,33 +1,7 @@
|
|||||||
import { useCallback } from 'react'
|
import useHook, { useHookHandler } from '../utils/use-hook'
|
||||||
import type {
|
import type { MutationHook, HookFetcherFn } from '../utils/types'
|
||||||
Prop,
|
|
||||||
HookFetcherFn,
|
|
||||||
UseHookInput,
|
|
||||||
UseHookResponse,
|
|
||||||
} from '../utils/types'
|
|
||||||
import type { Cart, CartItemBody, AddCartItemBody } from '../types'
|
import type { Cart, CartItemBody, AddCartItemBody } from '../types'
|
||||||
import { Provider, useCommerce } from '..'
|
import type { Provider } from '..'
|
||||||
import { BigcommerceProvider } from '@framework'
|
|
||||||
|
|
||||||
export type UseAddItemHandler<P extends Provider> = Prop<
|
|
||||||
Prop<P, 'cart'>,
|
|
||||||
'useAddItem'
|
|
||||||
>
|
|
||||||
|
|
||||||
// Input expected by the action returned by the `useAddItem` hook
|
|
||||||
export type UseAddItemInput<P extends Provider> = UseHookInput<
|
|
||||||
UseAddItemHandler<P>
|
|
||||||
>
|
|
||||||
|
|
||||||
export type UseAddItemResult<P extends Provider> = ReturnType<
|
|
||||||
UseHookResponse<UseAddItemHandler<P>>
|
|
||||||
>
|
|
||||||
|
|
||||||
export type UseAddItem<P extends Provider, Input> = Partial<
|
|
||||||
UseAddItemInput<P>
|
|
||||||
> extends UseAddItemInput<P>
|
|
||||||
? (input?: UseAddItemInput<P>) => (input: Input) => UseAddItemResult<P>
|
|
||||||
: (input: UseAddItemInput<P>) => (input: Input) => UseAddItemResult<P>
|
|
||||||
|
|
||||||
export const fetcher: HookFetcherFn<
|
export const fetcher: HookFetcherFn<
|
||||||
Cart,
|
Cart,
|
||||||
@ -36,34 +10,15 @@ export const fetcher: HookFetcherFn<
|
|||||||
return fetch({ ...options, body: input })
|
return fetch({ ...options, body: input })
|
||||||
}
|
}
|
||||||
|
|
||||||
type X = UseAddItemResult<BigcommerceProvider>
|
export type UseAddItem<
|
||||||
|
H extends MutationHook<any, any, any> = MutationHook<Cart, {}, CartItemBody>
|
||||||
|
> = ReturnType<H['useHook']>
|
||||||
|
|
||||||
export default function useAddItem<P extends Provider, Input>(
|
const fn = (provider: Provider) => provider.cart?.useAddItem!
|
||||||
input: UseAddItemInput<P>
|
|
||||||
) {
|
|
||||||
const { providerRef, fetcherRef } = useCommerce<P>()
|
|
||||||
|
|
||||||
const provider = providerRef.current
|
const useAddItem: UseAddItem = (...args) => {
|
||||||
const opts = provider.cart?.useAddItem
|
const handler = useHookHandler(fn, fetcher)
|
||||||
|
return handler(useHook(fn, fetcher))(...args)
|
||||||
const fetcherFn = opts?.fetcher ?? fetcher
|
|
||||||
const useHook = opts?.useHook ?? (() => () => {})
|
|
||||||
const fetchFn = provider.fetcher ?? fetcherRef.current
|
|
||||||
const action = useHook({ input })
|
|
||||||
|
|
||||||
return useCallback(
|
|
||||||
function addItem(input: Input) {
|
|
||||||
return action({
|
|
||||||
input,
|
|
||||||
fetch({ input }) {
|
|
||||||
return fetcherFn({
|
|
||||||
input,
|
|
||||||
options: opts!.fetchOptions,
|
|
||||||
fetch: fetchFn,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[input, fetchFn, opts?.fetchOptions]
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default useAddItem
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { HookFetcher, HookFetcherOptions } from '../utils/types'
|
import type { HookFetcher, HookFetcherOptions } from '../utils/types'
|
||||||
import useAddItem from './use-add-item'
|
// import useAddItem from './use-add-item'
|
||||||
import useRemoveItem from './use-remove-item'
|
import useRemoveItem from './use-remove-item'
|
||||||
import useUpdateItem from './use-update-item'
|
import useUpdateItem from './use-update-item'
|
||||||
|
|
||||||
@ -9,9 +9,9 @@ export default function useCartActions<T, Input>(
|
|||||||
options: HookFetcherOptions,
|
options: HookFetcherOptions,
|
||||||
fetcher: HookFetcher<T, Input>
|
fetcher: HookFetcher<T, Input>
|
||||||
) {
|
) {
|
||||||
const addItem = useAddItem<T, Input>(options, fetcher)
|
// const addItem = useAddItem<T, Input>(options, fetcher)
|
||||||
const updateItem = useUpdateItem<T, Input>(options, fetcher)
|
const updateItem = useUpdateItem<T, Input>(options, fetcher)
|
||||||
const removeItem = useRemoveItem<T, Input>(options, fetcher)
|
const removeItem = useRemoveItem<T, Input>(options, fetcher)
|
||||||
|
|
||||||
return { addItem, updateItem, removeItem }
|
return { updateItem, removeItem }
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,39 @@
|
|||||||
import useAction from '../utils/use-action'
|
import useHook, { useHookHandler } from '../utils/use-hook'
|
||||||
import type { CartItemBody } from '../types'
|
import type { MutationHook, HookFetcherFn } from '../utils/types'
|
||||||
|
import type { Cart, CartItemBody, LineItem, UpdateCartItemBody } from '../types'
|
||||||
|
import type { Provider } from '..'
|
||||||
|
import debounce from 'lodash.debounce'
|
||||||
|
|
||||||
// Input expected by the action returned by the `useUpdateItem` hook
|
// Input expected by the action returned by the `useUpdateItem` hook
|
||||||
export type UpdateItemInput<T extends CartItemBody> = T & {
|
export type UpdateItemInput<T extends CartItemBody> = T & {
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const useUpdateItem = useAction
|
export type UseUpdateItem<
|
||||||
|
H extends MutationHook<any, any, any> = MutationHook<
|
||||||
|
Cart,
|
||||||
|
{
|
||||||
|
item?: LineItem
|
||||||
|
wait?: number
|
||||||
|
},
|
||||||
|
UpdateItemInput<CartItemBody>,
|
||||||
|
UpdateCartItemBody<CartItemBody>
|
||||||
|
>
|
||||||
|
> = ReturnType<H['useHook']>
|
||||||
|
|
||||||
|
export const fetcher: HookFetcherFn<any> = async ({
|
||||||
|
options,
|
||||||
|
input,
|
||||||
|
fetch,
|
||||||
|
}) => {
|
||||||
|
return fetch({ ...options, body: input })
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn = (provider: Provider) => provider.cart?.useUpdateItem!
|
||||||
|
|
||||||
|
const useUpdateItem: UseUpdateItem = (input = {}) => {
|
||||||
|
const handler = useHookHandler(fn, fetcher)
|
||||||
|
return debounce(handler(useHook(fn, fetcher))(input), input.wait ?? 500)
|
||||||
|
}
|
||||||
|
|
||||||
export default useUpdateItem
|
export default useUpdateItem
|
||||||
|
@ -6,7 +6,12 @@ import {
|
|||||||
useMemo,
|
useMemo,
|
||||||
useRef,
|
useRef,
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import { Fetcher, HookHandler, MutationHandler } from './utils/types'
|
import {
|
||||||
|
Fetcher,
|
||||||
|
HookHandler,
|
||||||
|
MutationHandler,
|
||||||
|
MutationHook,
|
||||||
|
} from './utils/types'
|
||||||
import type { FetchCartInput } from './cart/use-cart'
|
import type { FetchCartInput } from './cart/use-cart'
|
||||||
import type { Cart, Wishlist, Customer, SearchProductsData } from './types'
|
import type { Cart, Wishlist, Customer, SearchProductsData } from './types'
|
||||||
|
|
||||||
@ -16,7 +21,9 @@ export type Provider = CommerceConfig & {
|
|||||||
fetcher: Fetcher
|
fetcher: Fetcher
|
||||||
cart?: {
|
cart?: {
|
||||||
useCart?: HookHandler<Cart | null, any, FetchCartInput>
|
useCart?: HookHandler<Cart | null, any, FetchCartInput>
|
||||||
useAddItem?: MutationHandler<Cart, any, any>
|
useAddItem?: MutationHook<any, any, any>
|
||||||
|
useUpdateItem?: MutationHook<any, any, any>
|
||||||
|
useRemoveItem?: MutationHook<any, any, any>
|
||||||
}
|
}
|
||||||
wishlist?: {
|
wishlist?: {
|
||||||
useWishlist?: HookHandler<Wishlist | null, any, any>
|
useWishlist?: HookHandler<Wishlist | null, any, any>
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { LineItem } from '@framework/types'
|
||||||
import type { ConfigInterface } from 'swr'
|
import type { ConfigInterface } from 'swr'
|
||||||
import type { CommerceError } from './errors'
|
import type { CommerceError } from './errors'
|
||||||
import type { ResponseState } from './use-data'
|
import type { ResponseState } from './use-data'
|
||||||
@ -31,16 +32,15 @@ export type HookFetcher<Data, Input = null, Result = any> = (
|
|||||||
fetch: <T = Result, Body = any>(options: FetcherOptions<Body>) => Promise<T>
|
fetch: <T = Result, Body = any>(options: FetcherOptions<Body>) => Promise<T>
|
||||||
) => Data | Promise<Data>
|
) => Data | Promise<Data>
|
||||||
|
|
||||||
export type HookFetcherFn<
|
export type HookFetcherFn<Data, Input = never, Result = any, Body = any> = (
|
||||||
Data,
|
context: HookFetcherContext<Input, Result, Body>
|
||||||
Input = never,
|
) => Data | Promise<Data>
|
||||||
Result = any,
|
|
||||||
Body = any
|
export type HookFetcherContext<Input = never, Result = any, Body = any> = {
|
||||||
> = (context: {
|
|
||||||
options: HookFetcherOptions
|
options: HookFetcherOptions
|
||||||
input: Input
|
input: Input
|
||||||
fetch: <T = Result, B = Body>(options: FetcherOptions<B>) => Promise<T>
|
fetch: <T = Result, B = Body>(options: FetcherOptions<B>) => Promise<T>
|
||||||
}) => Data | Promise<Data>
|
}
|
||||||
|
|
||||||
export type HookFetcherOptions = { method?: string } & (
|
export type HookFetcherOptions = { method?: string } & (
|
||||||
| { query: string; url?: string }
|
| { query: string; url?: string }
|
||||||
@ -53,8 +53,6 @@ export type HookSwrInput = [string, HookInputValue][]
|
|||||||
|
|
||||||
export type HookFetchInput = { [k: string]: HookInputValue }
|
export type HookFetchInput = { [k: string]: HookInputValue }
|
||||||
|
|
||||||
export type HookInput = {}
|
|
||||||
|
|
||||||
export type HookHandler<
|
export type HookHandler<
|
||||||
// Data obj returned by the hook and fetch operation
|
// Data obj returned by the hook and fetch operation
|
||||||
Data,
|
Data,
|
||||||
@ -94,6 +92,39 @@ export type MutationHandler<
|
|||||||
fetcher?: HookFetcherFn<Data, FetchInput>
|
fetcher?: HookFetcherFn<Data, FetchInput>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type HookFunction<
|
||||||
|
Input extends { [k: string]: unknown } | {},
|
||||||
|
T
|
||||||
|
> = keyof Input extends never
|
||||||
|
? () => T
|
||||||
|
: Partial<Input> extends Input
|
||||||
|
? (input?: Input) => T
|
||||||
|
: (input: Input) => T
|
||||||
|
|
||||||
|
export type MutationHook<
|
||||||
|
// Data obj returned by the hook and fetch operation
|
||||||
|
Data,
|
||||||
|
// Input expected by the hook
|
||||||
|
Input extends { [k: string]: unknown } = {},
|
||||||
|
// Input expected by the action returned by the hook
|
||||||
|
ActionInput extends { [k: string]: unknown } = {},
|
||||||
|
// Input expected before doing a fetch operation
|
||||||
|
FetchInput extends { [k: string]: unknown } = ActionInput
|
||||||
|
> = {
|
||||||
|
useHook(
|
||||||
|
context: HookContext<Data, FetchInput>
|
||||||
|
): HookFunction<Input, HookFunction<ActionInput, Data | Promise<Data>>>
|
||||||
|
fetchOptions: HookFetcherOptions
|
||||||
|
fetcher?: HookFetcherFn<Data, FetchInput>
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HookContext<
|
||||||
|
Data,
|
||||||
|
FetchInput extends { [k: string]: unknown } = {}
|
||||||
|
> = {
|
||||||
|
fetch: (context: { input: FetchInput }) => Data | Promise<Data>
|
||||||
|
}
|
||||||
|
|
||||||
export type SwrOptions<Data, Input = null, Result = any> = ConfigInterface<
|
export type SwrOptions<Data, Input = null, Result = any> = ConfigInterface<
|
||||||
Data,
|
Data,
|
||||||
CommerceError,
|
CommerceError,
|
||||||
|
43
framework/commerce/utils/use-hook.ts
Normal file
43
framework/commerce/utils/use-hook.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { useCallback } from 'react'
|
||||||
|
import type { MutationHook } from './types'
|
||||||
|
import { Provider, useCommerce } from '..'
|
||||||
|
|
||||||
|
export function useHookHandler<P extends Provider>(
|
||||||
|
fn: (provider: P) => MutationHook<any, any, any>,
|
||||||
|
fetcher: any
|
||||||
|
) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function useHook<P extends Provider>(
|
||||||
|
fn: (provider: P) => MutationHook<any, any, any>,
|
||||||
|
fetcher: any
|
||||||
|
) {
|
||||||
|
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]
|
||||||
|
)
|
||||||
|
|
||||||
|
return { fetch }
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user