Updated cart hooks

This commit is contained in:
Luis Alvarez 2021-03-31 22:12:45 -06:00
parent 731486e07b
commit 6d06d8b705
10 changed files with 56 additions and 96 deletions

View File

@ -3,12 +3,11 @@ import type { MutationHook } from '@commerce/utils/types'
import { CommerceError } from '@commerce/utils/errors'
import useAddItem, { UseAddItem } from '@commerce/cart/use-add-item'
import { normalizeCart } from '../lib/normalize'
import type { BigcommerceCart, AddItemHook } from '../types/cart'
import type { BigcommerceCart, AddItemHook, CartTypes } from '../types/cart'
import useCart from './use-cart'
export default useAddItem as UseAddItem<typeof handler>
// export const handler: MutationHook<Cart, {}, CartItemBody> = {
export const handler: MutationHook<AddItemHook> = {
fetchOptions: {
url: '/api/bigcommerce/cart',

View File

@ -4,26 +4,23 @@ import type {
HookFetcherContext,
} from '@commerce/utils/types'
import { ValidationError } from '@commerce/utils/errors'
import useRemoveItem, {
RemoveItemInput as RemoveItemInputBase,
UseRemoveItem,
} from '@commerce/cart/use-remove-item'
import useRemoveItem, { UseRemoveItem } from '@commerce/cart/use-remove-item'
import { normalizeCart } from '../lib/normalize'
import type {
RemoveCartItemBody,
Cart,
BigcommerceCart,
LineItem,
} from '../types'
RemoveItemHook,
BigcommerceCart,
} from '../types/cart'
import useCart from './use-cart'
export type RemoveItemFn<T = any> = T extends LineItem
? (input?: RemoveItemInput<T>) => Promise<Cart | null>
: (input: RemoveItemInput<T>) => Promise<Cart | null>
? (input?: RemoveItemActionInput<T>) => Promise<Cart | null>
: (input: RemoveItemActionInput<T>) => Promise<Cart | null>
export type RemoveItemInput<T = any> = T extends LineItem
? Partial<RemoveItemInputBase>
: RemoveItemInputBase
export type RemoveItemActionInput<T = any> = T extends LineItem
? Partial<RemoveItemHook['actionInput']>
: RemoveItemHook['actionInput']
export default useRemoveItem as UseRemoveItem<typeof handler>
@ -36,16 +33,14 @@ export const handler = {
input: { itemId },
options,
fetch,
}: HookFetcherContext<RemoveCartItemBody>) {
}: HookFetcherContext<RemoveItemHook>) {
const data = await fetch<BigcommerceCart>({
...options,
body: { itemId },
})
return normalizeCart(data)
},
useHook: ({
fetch,
}: MutationHookContext<Cart | null, RemoveCartItemBody>) => <
useHook: ({ fetch }: MutationHookContext<RemoveItemHook>) => <
T extends LineItem | undefined = undefined
>(
ctx: { item?: T } = {}

View File

@ -5,23 +5,15 @@ import type {
HookFetcherContext,
} from '@commerce/utils/types'
import { ValidationError } from '@commerce/utils/errors'
import useUpdateItem, {
UpdateItemInput as UpdateItemInputBase,
UseUpdateItem,
} from '@commerce/cart/use-update-item'
import useUpdateItem, { UseUpdateItem } from '@commerce/cart/use-update-item'
import { normalizeCart } from '../lib/normalize'
import type {
UpdateCartItemBody,
Cart,
BigcommerceCart,
LineItem,
} from '../types'
import type { Cart, BigcommerceCart, LineItem, UpdateItemHook } from '../types'
import { handler as removeItemHandler } from './use-remove-item'
import useCart from './use-cart'
export type UpdateItemInput<T = any> = T extends LineItem
? Partial<UpdateItemInputBase<LineItem>>
: UpdateItemInputBase<LineItem>
export type UpdateItemActionInput<T = any> = T extends LineItem
? Partial<UpdateItemHook['actionInput']>
: UpdateItemHook['actionInput']
export default useUpdateItem as UseUpdateItem<typeof handler>
@ -34,7 +26,7 @@ export const handler = {
input: { itemId, item },
options,
fetch,
}: HookFetcherContext<UpdateCartItemBody>) {
}: HookFetcherContext<UpdateItemHook>) {
if (Number.isInteger(item.quantity)) {
// Also allow the update hook to remove an item if the quantity is lower than 1
if (item.quantity! < 1) {
@ -50,16 +42,14 @@ export const handler = {
})
}
const data = await fetch<BigcommerceCart, UpdateCartItemBody>({
const data = await fetch<BigcommerceCart>({
...options,
body: { itemId, item },
})
return normalizeCart(data)
},
useHook: ({
fetch,
}: MutationHookContext<Cart | null, UpdateCartItemBody>) => <
useHook: ({ fetch }: MutationHookContext<UpdateItemHook>) => <
T extends LineItem | undefined = undefined
>(
ctx: {
@ -71,7 +61,7 @@ export const handler = {
const { mutate } = useCart() as any
return useCallback(
debounce(async (input: UpdateItemInput<T>) => {
debounce(async (input: UpdateItemActionInput<T>) => {
const itemId = input.id ?? item?.id
const productId = input.productId ?? item?.productId
const variantId = input.productId ?? item?.variantId

View File

@ -45,7 +45,8 @@ export type CartItemBody = Core.CartItemBody & {
export type CartTypes = {
cart: Cart
item: CartItemBody
item: Core.LineItem
itemBody: CartItemBody
}
export type CartHooks = Core.CartHooks<CartTypes>

View File

@ -5,6 +5,10 @@ import type { AddItemHook } from '../types/cart'
import type { Provider } from '..'
export type UseAddItem<
H extends MutationHook<AddItemHook<any>> = MutationHook<AddItemHook>
> = ReturnType<H['useHook']>
export type UseAddItem2<
H extends MutationHook<any> = MutationHook<AddItemHook>
> = ReturnType<H['useHook']>

View File

@ -4,9 +4,9 @@ import type { SWRHook, HookFetcherFn } from '../utils/types'
import type { GetCartHook } from '../types/cart'
import { Provider, useCommerce } from '..'
export type UseCart<H extends SWRHook<any> = SWRHook<GetCartHook>> = ReturnType<
H['useHook']
>
export type UseCart<
H extends SWRHook<GetCartHook<any>> = SWRHook<GetCartHook>
> = ReturnType<H['useHook']>
export const fetcher: HookFetcherFn<GetCartHook> = async ({
options,

View File

@ -1,29 +1,14 @@
import { useHook, useMutationHook } from '../utils/use-hook'
import { mutationFetcher } from '../utils/default-fetcher'
import type { HookFetcherFn, MutationHook } from '../utils/types'
import type { Cart, LineItem, RemoveCartItemBody } from '../types'
import type { RemoveItemHook } from '../types/cart'
import type { Provider } from '..'
/**
* Input expected by the action returned by the `useRemoveItem` hook
*/
export type RemoveItemInput = {
id: string
}
export type UseRemoveItem<
H extends MutationHook<any, any, any> = MutationHook<
Cart | null,
{ item?: LineItem },
RemoveItemInput,
RemoveCartItemBody
>
H extends MutationHook<RemoveItemHook<any>> = MutationHook<RemoveItemHook>
> = ReturnType<H['useHook']>
export const fetcher: HookFetcherFn<
Cart | null,
RemoveCartItemBody
> = mutationFetcher
export const fetcher: HookFetcherFn<RemoveItemHook> = mutationFetcher
const fn = (provider: Provider) => provider.cart?.useRemoveItem!

View File

@ -1,32 +1,14 @@
import { useHook, useMutationHook } from '../utils/use-hook'
import { mutationFetcher } from '../utils/default-fetcher'
import type { HookFetcherFn, MutationHook } from '../utils/types'
import type { Cart, CartItemBody, LineItem, UpdateCartItemBody } from '../types'
import type { UpdateItemHook } from '../types/cart'
import type { Provider } from '..'
/**
* Input expected by the action returned by the `useUpdateItem` hook
*/
export type UpdateItemInput<T extends CartItemBody> = T & {
id: string
}
export type UseUpdateItem<
H extends MutationHook<any, any, any> = MutationHook<
Cart | null,
{
item?: LineItem
wait?: number
},
UpdateItemInput<CartItemBody>,
UpdateCartItemBody<CartItemBody>
>
H extends MutationHook<UpdateItemHook<any>> = MutationHook<UpdateItemHook>
> = ReturnType<H['useHook']>
export const fetcher: HookFetcherFn<
Cart | null,
UpdateCartItemBody<CartItemBody>
> = mutationFetcher
export const fetcher: HookFetcherFn<UpdateItemHook> = mutationFetcher
const fn = (provider: Provider) => provider.cart?.useUpdateItem!

View File

@ -87,7 +87,8 @@ export type CartItemBody = {
export type CartTypes = {
cart: Cart
item: CartItemBody
item: LineItem
itemBody: CartItemBody
}
export type CartHooks<T extends CartTypes = CartTypes> = {
@ -106,20 +107,26 @@ export type GetCartHook<T extends CartTypes = CartTypes> = {
export type AddItemHook<T extends CartTypes = CartTypes> = {
data: T['cart']
body: { item: T['item'] }
input: T['item']
fetchInput: T['item']
actionInput: T['item']
body: { item: T['itemBody'] }
input: T['itemBody']
fetchInput: T['itemBody']
actionInput: T['itemBody']
}
export type UpdateItemHook<T extends CartTypes = CartTypes> = {
data: T['cart']
body: { itemId: string; item: T['item'] }
data: T['cart'] | null
body: { itemId: string; item: T['itemBody'] }
input: { item?: T['item']; wait?: number }
fetchInput: { itemId: string; item: T['itemBody'] }
actionInput: T['itemBody'] & { id: string }
}
export type RemoveItemHook<T extends CartTypes = CartTypes> = {
data: T['cart'] | null
body: { itemId: string }
input: { item?: T['item'] }
fetchInput: { itemId: string }
actionInput: { id: string }
}
/**
@ -155,6 +162,7 @@ export type AddItemOperation<
export type UpdateItemOperation<
T extends CartTypes = CartTypes
> = UpdateItemHook<T> & {
data: T['cart']
body: { cartId: string }
}

View File

@ -36,18 +36,14 @@ export type HookFetcher<Data, Input = null, Result = any> = (
fetch: <T = Result, Body = any>(options: FetcherOptions<Body>) => Promise<T>
) => Data | Promise<Data>
export type HookFetcherFn<
H extends HookSchemaBase,
Result = any,
Body = H['body']
> = (
context: HookFetcherContext<H['fetchInput'], Result, Body>
export type HookFetcherFn<H extends HookSchemaBase> = (
context: HookFetcherContext<H>
) => H['data'] | Promise<H['data']>
export type HookFetcherContext<Input = undefined, Result = any, Body = any> = {
export type HookFetcherContext<H extends HookSchemaBase> = {
options: HookFetcherOptions
input: Input
fetch: <T = Result, B = Body>(options: FetcherOptions<B>) => Promise<T>
input: H['fetchInput']
fetch: <T = any, B = H['body']>(options: FetcherOptions<B>) => Promise<T>
}
export type HookFetcherOptions = { method?: string } & (