Fix provider errors

This commit is contained in:
goncy
2021-09-24 18:25:09 -03:00
parent f3bffa85ff
commit eb2aca92ad
11 changed files with 149 additions and 221 deletions

View File

@@ -46,7 +46,7 @@ export type SubmitCheckoutHandler<T extends CheckoutTypes = CheckoutTypes> =
export type CheckoutHandlers<T extends CheckoutTypes = CheckoutTypes> = { export type CheckoutHandlers<T extends CheckoutTypes = CheckoutTypes> = {
getCheckout: GetCheckoutHandler<T> getCheckout: GetCheckoutHandler<T>
submitCheckout?: SubmitCheckoutHandler<T> submitCheckout: SubmitCheckoutHandler<T>
} }
export type CheckoutSchema<T extends CheckoutTypes = CheckoutTypes> = { export type CheckoutSchema<T extends CheckoutTypes = CheckoutTypes> = {

View File

@@ -1,41 +1,46 @@
export interface Address { export interface Address {
id: string; id: string
mask: string; mask: string
} }
export interface AddressFields { export interface AddressFields {
type: string; type: string
firstName: string; firstName: string
lastName: string; lastName: string
company: string; company: string
streetNumber: string; streetNumber: string
apartments: string; apartments: string
zipCode: string; zipCode: string
city: string; city: string
country: string; country: string
} }
export type CustomerAddressTypes = { export type CustomerAddressTypes = {
address?: Address; address?: Address
fields: AddressFields; fields: AddressFields
} }
export type GetAddressesHook<T extends CustomerAddressTypes = CustomerAddressTypes> = { export type GetAddressesHook<
data: T['address'] | null T extends CustomerAddressTypes = CustomerAddressTypes
> = {
data: T['address'][] | null
input: {} input: {}
fetcherInput: { cartId?: string } fetcherInput: { cartId?: string }
swrState: { isEmpty: boolean } swrState: { isEmpty: boolean }
} }
export type AddItemHook<T extends CustomerAddressTypes = CustomerAddressTypes> = { export type AddItemHook<T extends CustomerAddressTypes = CustomerAddressTypes> =
data: T['address'] {
input?: T['fields'] data: T['address']
fetcherInput: T['fields'] input?: T['fields']
body: { item: T['fields'] } fetcherInput: T['fields']
actionInput: T['fields'] body: { item: T['fields'] }
} actionInput: T['fields']
}
export type UpdateItemHook<T extends CustomerAddressTypes = CustomerAddressTypes> = { export type UpdateItemHook<
T extends CustomerAddressTypes = CustomerAddressTypes
> = {
data: T['address'] | null data: T['address'] | null
input: { item?: T['fields']; wait?: number } input: { item?: T['fields']; wait?: number }
fetcherInput: { itemId: string; item: T['fields'] } fetcherInput: { itemId: string; item: T['fields'] }
@@ -43,49 +48,62 @@ export type UpdateItemHook<T extends CustomerAddressTypes = CustomerAddressTypes
actionInput: T['fields'] & { id: string } actionInput: T['fields'] & { id: string }
} }
export type RemoveItemHook<T extends CustomerAddressTypes = CustomerAddressTypes> = { export type RemoveItemHook<
T extends CustomerAddressTypes = CustomerAddressTypes
> = {
data: T['address'] | null data: T['address'] | null
input: { item?: T['fields'] } input: { item?: T['address'] }
fetcherInput: { itemId: string } fetcherInput: { itemId: string }
body: { itemId: string } body: { itemId: string }
actionInput: { id: string } actionInput: { id: string }
} }
export type CustomerAddressHooks<T extends CustomerAddressTypes = CustomerAddressTypes> = { export type CustomerAddressHooks<
T extends CustomerAddressTypes = CustomerAddressTypes
> = {
getAddresses: GetAddressesHook<T> getAddresses: GetAddressesHook<T>
addItem: AddItemHook<T> addItem: AddItemHook<T>
updateItem: UpdateItemHook<T> updateItem: UpdateItemHook<T>
removeItem: RemoveItemHook<T> removeItem: RemoveItemHook<T>
} }
export type AddresssHandler<T extends CustomerAddressTypes = CustomerAddressTypes> = GetAddressesHook<T> & { export type AddressHandler<
T extends CustomerAddressTypes = CustomerAddressTypes
> = GetAddressesHook<T> & {
body: { cartId?: string } body: { cartId?: string }
} }
export type AddItemHandler<T extends CustomerAddressTypes = CustomerAddressTypes> = AddItemHook<T> & { export type AddItemHandler<
T extends CustomerAddressTypes = CustomerAddressTypes
> = AddItemHook<T> & {
body: { cartId: string } body: { cartId: string }
} }
export type UpdateItemHandler<T extends CustomerAddressTypes = CustomerAddressTypes> = export type UpdateItemHandler<
UpdateItemHook<T> & { T extends CustomerAddressTypes = CustomerAddressTypes
data: T['address'] > = UpdateItemHook<T> & {
body: { cartId: string } data: T['address']
} body: { cartId: string }
}
export type RemoveItemHandler<T extends CustomerAddressTypes = CustomerAddressTypes> = export type RemoveItemHandler<
RemoveItemHook<T> & { T extends CustomerAddressTypes = CustomerAddressTypes
body: { cartId: string } > = RemoveItemHook<T> & {
} body: { cartId: string }
}
export type CustomerAddressHandlers<
export type CustomerAddressHandlers<T extends CustomerAddressTypes = CustomerAddressTypes> = { T extends CustomerAddressTypes = CustomerAddressTypes
> = {
getAddresses: GetAddressesHook<T> getAddresses: GetAddressesHook<T>
addItem: AddItemHandler<T> addItem: AddItemHandler<T>
updateItem: UpdateItemHandler<T> updateItem: UpdateItemHandler<T>
removeItem: RemoveItemHandler<T> removeItem: RemoveItemHandler<T>
} }
export type CustomerAddressSchema<T extends CustomerAddressTypes = CustomerAddressTypes> = { export type CustomerAddressSchema<
T extends CustomerAddressTypes = CustomerAddressTypes
> = {
endpoint: { endpoint: {
options: {} options: {}
handlers: CustomerAddressHandlers<T> handlers: CustomerAddressHandlers<T>

View File

@@ -1,30 +1,30 @@
export interface Card { export interface Card {
id: string; id: string
mask: string; mask: string
provider: string; provider: string
} }
export interface CardFields { export interface CardFields {
cardHolder: string; cardHolder: string
cardNumber: string; cardNumber: string
cardExpireDate: string; cardExpireDate: string
cardCvc: string; cardCvc: string
firstName: string; firstName: string
lastName: string; lastName: string
company: string; company: string
streetNumber: string; streetNumber: string
zipCode: string; zipCode: string
city: string; city: string
country: string; country: string
} }
export type CustomerCardTypes = { export type CustomerCardTypes = {
card?: Card; card?: Card
fields: CardFields; fields: CardFields
} }
export type GetCardsHook<T extends CustomerCardTypes = CustomerCardTypes> = { export type GetCardsHook<T extends CustomerCardTypes = CustomerCardTypes> = {
data: T['card'] | null data: T['card'][] | null
input: {} input: {}
fetcherInput: { cartId?: string } fetcherInput: { cartId?: string }
swrState: { isEmpty: boolean } swrState: { isEmpty: boolean }
@@ -48,26 +48,29 @@ export type UpdateItemHook<T extends CustomerCardTypes = CustomerCardTypes> = {
export type RemoveItemHook<T extends CustomerCardTypes = CustomerCardTypes> = { export type RemoveItemHook<T extends CustomerCardTypes = CustomerCardTypes> = {
data: T['card'] | null data: T['card'] | null
input: { item?: T['fields'] } input: { item?: T['card'] }
fetcherInput: { itemId: string } fetcherInput: { itemId: string }
body: { itemId: string } body: { itemId: string }
actionInput: { id: string } actionInput: { id: string }
} }
export type CustomerCardHooks<T extends CustomerCardTypes = CustomerCardTypes> = { export type CustomerCardHooks<T extends CustomerCardTypes = CustomerCardTypes> =
getCards: GetCardsHook<T> {
addItem: AddItemHook<T> getCards: GetCardsHook<T>
updateItem: UpdateItemHook<T> addItem: AddItemHook<T>
removeItem: RemoveItemHook<T> updateItem: UpdateItemHook<T>
} removeItem: RemoveItemHook<T>
}
export type CardsHandler<T extends CustomerCardTypes = CustomerCardTypes> = GetCardsHook<T> & { export type CardsHandler<T extends CustomerCardTypes = CustomerCardTypes> =
body: { cartId?: string } GetCardsHook<T> & {
} body: { cartId?: string }
}
export type AddItemHandler<T extends CustomerCardTypes = CustomerCardTypes> = AddItemHook<T> & { export type AddItemHandler<T extends CustomerCardTypes = CustomerCardTypes> =
body: { cartId: string } AddItemHook<T> & {
} body: { cartId: string }
}
export type UpdateItemHandler<T extends CustomerCardTypes = CustomerCardTypes> = export type UpdateItemHandler<T extends CustomerCardTypes = CustomerCardTypes> =
UpdateItemHook<T> & { UpdateItemHook<T> & {
@@ -80,15 +83,18 @@ export type RemoveItemHandler<T extends CustomerCardTypes = CustomerCardTypes> =
body: { cartId: string } body: { cartId: string }
} }
export type CustomerCardHandlers<
export type CustomerCardHandlers<T extends CustomerCardTypes = CustomerCardTypes> = { T extends CustomerCardTypes = CustomerCardTypes
> = {
getCards: GetCardsHook<T> getCards: GetCardsHook<T>
addItem: AddItemHandler<T> addItem: AddItemHandler<T>
updateItem: UpdateItemHandler<T> updateItem: UpdateItemHandler<T>
removeItem: RemoveItemHandler<T> removeItem: RemoveItemHandler<T>
} }
export type CustomerCardSchema<T extends CustomerCardTypes = CustomerCardTypes> = { export type CustomerCardSchema<
T extends CustomerCardTypes = CustomerCardTypes
> = {
endpoint: { endpoint: {
options: {} options: {}
handlers: CustomerCardHandlers<T> handlers: CustomerCardHandlers<T>

View File

@@ -2,7 +2,6 @@ import type { AddItemHook } from '@commerce/types/customer/address'
import type { MutationHook } from '@commerce/utils/types' import type { MutationHook } from '@commerce/utils/types'
import { useCallback } from 'react' import { useCallback } from 'react'
import { CommerceError } from '@commerce/utils/errors'
import useAddItem, { UseAddItem } from '@commerce/customer/address/use-add-item' import useAddItem, { UseAddItem } from '@commerce/customer/address/use-add-item'
import useAddresses from './use-addresses' import useAddresses from './use-addresses'
@@ -14,15 +13,6 @@ export const handler: MutationHook<AddItemHook> = {
method: 'POST', method: 'POST',
}, },
async fetcher({ input: item, options, fetch }) { async fetcher({ input: item, options, fetch }) {
if (
item.quantity &&
(!Number.isInteger(item.quantity) || item.quantity! < 1)
) {
throw new CommerceError({
message: 'The item quantity has to be a valid integer greater than 0',
})
}
const data = await fetch({ const data = await fetch({
...options, ...options,
body: { item }, body: { item },
@@ -38,7 +28,7 @@ export const handler: MutationHook<AddItemHook> = {
async function addItem(input) { 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
}, },

View File

@@ -2,7 +2,9 @@ import type { GetAddressesHook } from '@commerce/types/customer/address'
import { useMemo } from 'react' import { useMemo } from 'react'
import { SWRHook } from '@commerce/utils/types' import { SWRHook } from '@commerce/utils/types'
import useAddresses, { UseAddresses } from '@commerce/customer/address/use-addresses' import useAddresses, {
UseAddresses,
} from '@commerce/customer/address/use-addresses'
export default useAddresses as UseAddresses<typeof handler> export default useAddresses as UseAddresses<typeof handler>
@@ -22,7 +24,7 @@ export const handler: SWRHook<GetAddressesHook> = {
Object.create(response, { Object.create(response, {
isEmpty: { isEmpty: {
get() { get() {
return (response.data?.lineItems?.length ?? 0) <= 0 return (response.data?.length ?? 0) <= 0
}, },
enumerable: true, enumerable: true,
}, },

View File

@@ -2,20 +2,22 @@ import type {
MutationHookContext, MutationHookContext,
HookFetcherContext, HookFetcherContext,
} from '@commerce/utils/types' } from '@commerce/utils/types'
import type { Cart, LineItem, RemoveItemHook } from '@commerce/types/cart' import type { Address, RemoveItemHook } from '@commerce/types/customer/address'
import { useCallback } from 'react' import { useCallback } from 'react'
import { ValidationError } from '@commerce/utils/errors' import { ValidationError } from '@commerce/utils/errors'
import useRemoveItem, { UseRemoveItem } from '@commerce/customer/address/use-remove-item' import useRemoveItem, {
UseRemoveItem,
} from '@commerce/customer/address/use-remove-item'
import useAddresses from './use-addresses' import useAddresses from './use-addresses'
export type RemoveItemFn<T = any> = T extends LineItem export type RemoveItemFn<T = any> = T extends Address
? (input?: RemoveItemActionInput<T>) => Promise<Cart | null | undefined> ? (input?: RemoveItemActionInput<T>) => Promise<Address | null | undefined>
: (input: RemoveItemActionInput<T>) => Promise<Cart | null> : (input: RemoveItemActionInput<T>) => Promise<Address | null>
export type RemoveItemActionInput<T = any> = T extends LineItem export type RemoveItemActionInput<T = any> = T extends Address
? Partial<RemoveItemHook['actionInput']> ? Partial<RemoveItemHook['actionInput']>
: RemoveItemHook['actionInput'] : RemoveItemHook['actionInput']
@@ -34,12 +36,12 @@ export const handler = {
return await fetch({ ...options, body: { itemId } }) return await fetch({ ...options, body: { itemId } })
}, },
useHook: ({ fetch }: MutationHookContext<RemoveItemHook>) => useHook: ({ fetch }: MutationHookContext<RemoveItemHook>) =>
function useHook<T extends LineItem | undefined = undefined>( function useHook<T extends Address | undefined = undefined>(
ctx: { item?: T } = {} ctx: { item?: T } = {}
) { ) {
const { item } = ctx const { item } = ctx
const { mutate } = useAddresses() const { mutate } = useAddresses()
const removeItem: RemoveItemFn<LineItem> = async (input) => { const removeItem: RemoveItemFn<Address> = async (input) => {
const itemId = input?.id ?? item?.id const itemId = input?.id ?? item?.id
if (!itemId) { if (!itemId) {
@@ -50,7 +52,7 @@ export const handler = {
const data = await fetch({ input: { itemId } }) const data = await fetch({ input: { itemId } })
await mutate(data, false) await mutate([], false)
return data return data
} }

View File

@@ -2,19 +2,18 @@ import type {
HookFetcherContext, HookFetcherContext,
MutationHookContext, MutationHookContext,
} from '@commerce/utils/types' } from '@commerce/utils/types'
import type { UpdateItemHook, LineItem } from '@commerce/types/cart' import type { UpdateItemHook, Address } from '@commerce/types/customer/address'
import { useCallback } from 'react' import { useCallback } from 'react'
import debounce from 'lodash.debounce'
import { MutationHook } from '@commerce/utils/types' import { MutationHook } from '@commerce/utils/types'
import { ValidationError } from '@commerce/utils/errors' import useUpdateItem, {
import useUpdateItem, { UseUpdateItem } from '@commerce/customer/address/use-update-item' UseUpdateItem,
} from '@commerce/customer/address/use-update-item'
import { handler as removeItemHandler } from './use-remove-item'
import useAddresses from './use-addresses' import useAddresses from './use-addresses'
export type UpdateItemActionInput<T = any> = T extends LineItem export type UpdateItemActionInput<T = any> = T extends Address
? Partial<UpdateItemHook['actionInput']> ? Partial<UpdateItemHook['actionInput']>
: UpdateItemHook['actionInput'] : UpdateItemHook['actionInput']
@@ -30,63 +29,23 @@ export const handler: MutationHook<any> = {
options, options,
fetch, fetch,
}: HookFetcherContext<UpdateItemHook>) { }: 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) {
return removeItemHandler.fetcher({
options: removeItemHandler.fetchOptions,
input: { itemId },
fetch,
})
}
} else if (item.quantity) {
throw new ValidationError({
message: 'The item quantity has to be a valid integer',
})
}
return await fetch({ return await fetch({
...options, ...options,
body: { itemId, item }, body: { itemId, item },
}) })
}, },
useHook: ({ fetch }: MutationHookContext<UpdateItemHook>) => useHook: ({ fetch }: MutationHookContext<UpdateItemHook>) =>
function useHook<T extends LineItem | undefined = undefined>( function useHook() {
ctx: { const { mutate } = useAddresses()
item?: T
wait?: number
} = {}
) {
const { item } = ctx
const { mutate } = useAddresses() as any
return useCallback( return useCallback(
debounce(async (input: UpdateItemActionInput<T>) => { async function updateItem(input) {
const itemId = input.id ?? item?.id const data = await fetch({ input })
const productId = input.productId ?? item?.productId
const variantId = input.productId ?? item?.variantId
if (!itemId || !productId) { await mutate([], false)
throw new ValidationError({
message: 'Invalid input used for this operation',
})
}
const data = await fetch({
input: {
itemId,
item: {
productId,
variantId: variantId || '',
quantity: input.quantity,
},
},
})
await mutate(data, false)
return data return data
}, ctx.wait ?? 500), },
[fetch, mutate] [fetch, mutate]
) )
}, },

View File

@@ -2,7 +2,6 @@ import type { AddItemHook } from '@commerce/types/customer/card'
import type { MutationHook } from '@commerce/utils/types' import type { MutationHook } from '@commerce/utils/types'
import { useCallback } from 'react' import { useCallback } from 'react'
import { CommerceError } from '@commerce/utils/errors'
import useAddItem, { UseAddItem } from '@commerce/customer/card/use-add-item' import useAddItem, { UseAddItem } from '@commerce/customer/card/use-add-item'
import useCards from './use-cards' import useCards from './use-cards'
@@ -14,15 +13,6 @@ export const handler: MutationHook<AddItemHook> = {
method: 'POST', method: 'POST',
}, },
async fetcher({ input: item, options, fetch }) { async fetcher({ input: item, options, fetch }) {
if (
item.quantity &&
(!Number.isInteger(item.quantity) || item.quantity! < 1)
) {
throw new CommerceError({
message: 'The item quantity has to be a valid integer greater than 0',
})
}
const data = await fetch({ const data = await fetch({
...options, ...options,
body: { item }, body: { item },
@@ -38,7 +28,7 @@ export const handler: MutationHook<AddItemHook> = {
async function addItem(input) { 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
}, },

View File

@@ -22,7 +22,7 @@ export const handler: SWRHook<GetCardsHook> = {
Object.create(response, { Object.create(response, {
isEmpty: { isEmpty: {
get() { get() {
return (response.data?.lineItems?.length ?? 0) <= 0 return (response.data?.length ?? 0) <= 0
}, },
enumerable: true, enumerable: true,
}, },

View File

@@ -2,20 +2,22 @@ import type {
MutationHookContext, MutationHookContext,
HookFetcherContext, HookFetcherContext,
} from '@commerce/utils/types' } from '@commerce/utils/types'
import type { Cart, LineItem, RemoveItemHook } from '@commerce/types/customer/card' import type { Card, RemoveItemHook } from '@commerce/types/customer/card'
import { useCallback } from 'react' import { useCallback } from 'react'
import { ValidationError } from '@commerce/utils/errors' import { ValidationError } from '@commerce/utils/errors'
import useRemoveItem, { UseRemoveItem } from '@commerce/customer/card/use-remove-item' import useRemoveItem, {
UseRemoveItem,
} from '@commerce/customer/card/use-remove-item'
import useCards from './use-cards' import useCards from './use-cards'
export type RemoveItemFn<T = any> = T extends LineItem export type RemoveItemFn<T = any> = T extends Card
? (input?: RemoveItemActionInput<T>) => Promise<Cart | null | undefined> ? (input?: RemoveItemActionInput<T>) => Promise<Card | null | undefined>
: (input: RemoveItemActionInput<T>) => Promise<Cart | null> : (input: RemoveItemActionInput<T>) => Promise<Card | null>
export type RemoveItemActionInput<T = any> = T extends LineItem export type RemoveItemActionInput<T = any> = T extends Card
? Partial<RemoveItemHook['actionInput']> ? Partial<RemoveItemHook['actionInput']>
: RemoveItemHook['actionInput'] : RemoveItemHook['actionInput']
@@ -34,12 +36,12 @@ export const handler = {
return await fetch({ ...options, body: { itemId } }) return await fetch({ ...options, body: { itemId } })
}, },
useHook: ({ fetch }: MutationHookContext<RemoveItemHook>) => useHook: ({ fetch }: MutationHookContext<RemoveItemHook>) =>
function useHook<T extends LineItem | undefined = undefined>( function useHook<T extends Card | undefined = undefined>(
ctx: { item?: T } = {} ctx: { item?: T } = {}
) { ) {
const { item } = ctx const { item } = ctx
const { mutate } = useCards() const { mutate } = useCards()
const removeItem: RemoveItemFn<LineItem> = async (input) => { const removeItem: RemoveItemFn<Card> = async (input) => {
const itemId = input?.id ?? item?.id const itemId = input?.id ?? item?.id
if (!itemId) { if (!itemId) {
@@ -50,7 +52,7 @@ export const handler = {
const data = await fetch({ input: { itemId } }) const data = await fetch({ input: { itemId } })
await mutate(data, false) await mutate([], false)
return data return data
} }

View File

@@ -2,19 +2,18 @@ import type {
HookFetcherContext, HookFetcherContext,
MutationHookContext, MutationHookContext,
} from '@commerce/utils/types' } from '@commerce/utils/types'
import type { UpdateItemHook, LineItem } from '@commerce/types/customer/card' import type { UpdateItemHook, Card } from '@commerce/types/customer/card'
import { useCallback } from 'react' import { useCallback } from 'react'
import debounce from 'lodash.debounce'
import { MutationHook } from '@commerce/utils/types' import { MutationHook } from '@commerce/utils/types'
import { ValidationError } from '@commerce/utils/errors' import useUpdateItem, {
import useUpdateItem, { UseUpdateItem } from '@commerce/customer/card/use-update-item' UseUpdateItem,
} from '@commerce/customer/card/use-update-item'
import { handler as removeItemHandler } from './use-remove-item'
import useCards from './use-cards' import useCards from './use-cards'
export type UpdateItemActionInput<T = any> = T extends LineItem export type UpdateItemActionInput<T = any> = T extends Card
? Partial<UpdateItemHook['actionInput']> ? Partial<UpdateItemHook['actionInput']>
: UpdateItemHook['actionInput'] : UpdateItemHook['actionInput']
@@ -30,63 +29,23 @@ export const handler: MutationHook<any> = {
options, options,
fetch, fetch,
}: HookFetcherContext<UpdateItemHook>) { }: 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) {
return removeItemHandler.fetcher({
options: removeItemHandler.fetchOptions,
input: { itemId },
fetch,
})
}
} else if (item.quantity) {
throw new ValidationError({
message: 'The item quantity has to be a valid integer',
})
}
return await fetch({ return await fetch({
...options, ...options,
body: { itemId, item }, body: { itemId, item },
}) })
}, },
useHook: ({ fetch }: MutationHookContext<UpdateItemHook>) => useHook: ({ fetch }: MutationHookContext<UpdateItemHook>) =>
function useHook<T extends LineItem | undefined = undefined>( function useHook() {
ctx: { const { mutate } = useCards()
item?: T
wait?: number
} = {}
) {
const { item } = ctx
const { mutate } = useCards() as any
return useCallback( return useCallback(
debounce(async (input: UpdateItemActionInput<T>) => { async function updateItem(input) {
const itemId = input.id ?? item?.id const data = await fetch({ input })
const productId = input.productId ?? item?.productId
const variantId = input.productId ?? item?.variantId
if (!itemId || !productId) { await mutate([], false)
throw new ValidationError({
message: 'Invalid input used for this operation',
})
}
const data = await fetch({
input: {
itemId,
item: {
productId,
variantId: variantId || '',
quantity: input.quantity,
},
},
})
await mutate(data, false)
return data return data
}, ctx.wait ?? 500), },
[fetch, mutate] [fetch, mutate]
) )
}, },