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> = {
getCheckout: GetCheckoutHandler<T>
submitCheckout?: SubmitCheckoutHandler<T>
submitCheckout: SubmitCheckoutHandler<T>
}
export type CheckoutSchema<T extends CheckoutTypes = CheckoutTypes> = {

View File

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

View File

@ -1,30 +1,30 @@
export interface Card {
id: string;
mask: string;
provider: string;
id: string
mask: string
provider: string
}
export interface CardFields {
cardHolder: string;
cardNumber: string;
cardExpireDate: string;
cardCvc: string;
firstName: string;
lastName: string;
company: string;
streetNumber: string;
zipCode: string;
city: string;
country: string;
cardHolder: string
cardNumber: string
cardExpireDate: string
cardCvc: string
firstName: string
lastName: string
company: string
streetNumber: string
zipCode: string
city: string
country: string
}
export type CustomerCardTypes = {
card?: Card;
fields: CardFields;
card?: Card
fields: CardFields
}
export type GetCardsHook<T extends CustomerCardTypes = CustomerCardTypes> = {
data: T['card'] | null
data: T['card'][] | null
input: {}
fetcherInput: { cartId?: string }
swrState: { isEmpty: boolean }
@ -48,26 +48,29 @@ export type UpdateItemHook<T extends CustomerCardTypes = CustomerCardTypes> = {
export type RemoveItemHook<T extends CustomerCardTypes = CustomerCardTypes> = {
data: T['card'] | null
input: { item?: T['fields'] }
input: { item?: T['card'] }
fetcherInput: { itemId: string }
body: { itemId: string }
actionInput: { id: string }
}
export type CustomerCardHooks<T extends CustomerCardTypes = CustomerCardTypes> = {
getCards: GetCardsHook<T>
addItem: AddItemHook<T>
updateItem: UpdateItemHook<T>
removeItem: RemoveItemHook<T>
}
export type CustomerCardHooks<T extends CustomerCardTypes = CustomerCardTypes> =
{
getCards: GetCardsHook<T>
addItem: AddItemHook<T>
updateItem: UpdateItemHook<T>
removeItem: RemoveItemHook<T>
}
export type CardsHandler<T extends CustomerCardTypes = CustomerCardTypes> = GetCardsHook<T> & {
body: { cartId?: string }
}
export type CardsHandler<T extends CustomerCardTypes = CustomerCardTypes> =
GetCardsHook<T> & {
body: { cartId?: string }
}
export type AddItemHandler<T extends CustomerCardTypes = CustomerCardTypes> = AddItemHook<T> & {
body: { cartId: string }
}
export type AddItemHandler<T extends CustomerCardTypes = CustomerCardTypes> =
AddItemHook<T> & {
body: { cartId: string }
}
export type UpdateItemHandler<T extends CustomerCardTypes = CustomerCardTypes> =
UpdateItemHook<T> & {
@ -80,15 +83,18 @@ export type RemoveItemHandler<T extends CustomerCardTypes = CustomerCardTypes> =
body: { cartId: string }
}
export type CustomerCardHandlers<T extends CustomerCardTypes = CustomerCardTypes> = {
export type CustomerCardHandlers<
T extends CustomerCardTypes = CustomerCardTypes
> = {
getCards: GetCardsHook<T>
addItem: AddItemHandler<T>
updateItem: UpdateItemHandler<T>
removeItem: RemoveItemHandler<T>
}
export type CustomerCardSchema<T extends CustomerCardTypes = CustomerCardTypes> = {
export type CustomerCardSchema<
T extends CustomerCardTypes = CustomerCardTypes
> = {
endpoint: {
options: {}
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 { useCallback } from 'react'
import { CommerceError } from '@commerce/utils/errors'
import useAddItem, { UseAddItem } from '@commerce/customer/address/use-add-item'
import useAddresses from './use-addresses'
@ -14,15 +13,6 @@ export const handler: MutationHook<AddItemHook> = {
method: 'POST',
},
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({
...options,
body: { item },
@ -38,7 +28,7 @@ export const handler: MutationHook<AddItemHook> = {
async function addItem(input) {
const data = await fetch({ input })
await mutate(data, false)
await mutate([data], false)
return data
},

View File

@ -2,7 +2,9 @@ import type { GetAddressesHook } from '@commerce/types/customer/address'
import { useMemo } from 'react'
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>
@ -22,7 +24,7 @@ export const handler: SWRHook<GetAddressesHook> = {
Object.create(response, {
isEmpty: {
get() {
return (response.data?.lineItems?.length ?? 0) <= 0
return (response.data?.length ?? 0) <= 0
},
enumerable: true,
},

View File

@ -2,20 +2,22 @@ import type {
MutationHookContext,
HookFetcherContext,
} 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 { 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'
export type RemoveItemFn<T = any> = T extends LineItem
? (input?: RemoveItemActionInput<T>) => Promise<Cart | null | undefined>
: (input: RemoveItemActionInput<T>) => Promise<Cart | null>
export type RemoveItemFn<T = any> = T extends Address
? (input?: RemoveItemActionInput<T>) => Promise<Address | null | undefined>
: (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']>
: RemoveItemHook['actionInput']
@ -34,12 +36,12 @@ export const handler = {
return await fetch({ ...options, body: { itemId } })
},
useHook: ({ fetch }: MutationHookContext<RemoveItemHook>) =>
function useHook<T extends LineItem | undefined = undefined>(
function useHook<T extends Address | undefined = undefined>(
ctx: { item?: T } = {}
) {
const { item } = ctx
const { mutate } = useAddresses()
const removeItem: RemoveItemFn<LineItem> = async (input) => {
const removeItem: RemoveItemFn<Address> = async (input) => {
const itemId = input?.id ?? item?.id
if (!itemId) {
@ -50,7 +52,7 @@ export const handler = {
const data = await fetch({ input: { itemId } })
await mutate(data, false)
await mutate([], false)
return data
}

View File

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

View File

@ -2,7 +2,6 @@ import type { AddItemHook } from '@commerce/types/customer/card'
import type { MutationHook } from '@commerce/utils/types'
import { useCallback } from 'react'
import { CommerceError } from '@commerce/utils/errors'
import useAddItem, { UseAddItem } from '@commerce/customer/card/use-add-item'
import useCards from './use-cards'
@ -14,15 +13,6 @@ export const handler: MutationHook<AddItemHook> = {
method: 'POST',
},
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({
...options,
body: { item },
@ -38,7 +28,7 @@ export const handler: MutationHook<AddItemHook> = {
async function addItem(input) {
const data = await fetch({ input })
await mutate(data, false)
await mutate([data], false)
return data
},

View File

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

View File

@ -2,20 +2,22 @@ import type {
MutationHookContext,
HookFetcherContext,
} 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 { 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'
export type RemoveItemFn<T = any> = T extends LineItem
? (input?: RemoveItemActionInput<T>) => Promise<Cart | null | undefined>
: (input: RemoveItemActionInput<T>) => Promise<Cart | null>
export type RemoveItemFn<T = any> = T extends Card
? (input?: RemoveItemActionInput<T>) => Promise<Card | null | undefined>
: (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']>
: RemoveItemHook['actionInput']
@ -34,12 +36,12 @@ export const handler = {
return await fetch({ ...options, body: { itemId } })
},
useHook: ({ fetch }: MutationHookContext<RemoveItemHook>) =>
function useHook<T extends LineItem | undefined = undefined>(
function useHook<T extends Card | undefined = undefined>(
ctx: { item?: T } = {}
) {
const { item } = ctx
const { mutate } = useCards()
const removeItem: RemoveItemFn<LineItem> = async (input) => {
const removeItem: RemoveItemFn<Card> = async (input) => {
const itemId = input?.id ?? item?.id
if (!itemId) {
@ -50,7 +52,7 @@ export const handler = {
const data = await fetch({ input: { itemId } })
await mutate(data, false)
await mutate([], false)
return data
}

View File

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