forked from crowetic/commerce
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 { 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 useCart, { UseCart, FetchCartInput } from '@commerce/cart/use-cart'
|
||||||
import { normalizeCart } from '../lib/normalize'
|
import { normalizeCart } from '../lib/normalize'
|
||||||
import type { Cart } from '../types'
|
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,
|
Cart | null,
|
||||||
{},
|
{},
|
||||||
FetchCartInput,
|
FetchCartInput,
|
||||||
@ -21,9 +20,9 @@ export const handler: HookHandler<
|
|||||||
const data = cartId ? await fetch(options) : null
|
const data = cartId ? await fetch(options) : null
|
||||||
return data && normalizeCart(data)
|
return data && normalizeCart(data)
|
||||||
},
|
},
|
||||||
useHook({ input, useData }) {
|
useHook: ({ useData }) => (input) => {
|
||||||
const response = useData({
|
const response = useData({
|
||||||
swrOptions: { revalidateOnFocus: false, ...input.swrOptions },
|
swrOptions: { revalidateOnFocus: false, ...input?.swrOptions },
|
||||||
})
|
})
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
|
@ -46,7 +46,7 @@ export const handler = {
|
|||||||
ctx: { item?: T } = {}
|
ctx: { item?: T } = {}
|
||||||
) => {
|
) => {
|
||||||
const { item } = ctx
|
const { item } = ctx
|
||||||
const { mutate } = useCart() as any
|
const { mutate } = useCart()
|
||||||
const removeItem: RemoveItemFn<LineItem> = async (input) => {
|
const removeItem: RemoveItemFn<LineItem> = async (input) => {
|
||||||
const itemId = input?.id ?? item?.id
|
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 { MutationHook, HookFetcherFn } from '../utils/types'
|
||||||
import type { Cart, CartItemBody, AddCartItemBody } from '../types'
|
import type { Cart, CartItemBody, AddCartItemBody } from '../types'
|
||||||
import type { Provider } from '..'
|
import type { Provider } from '..'
|
||||||
@ -6,9 +7,7 @@ import type { Provider } from '..'
|
|||||||
export const fetcher: HookFetcherFn<
|
export const fetcher: HookFetcherFn<
|
||||||
Cart,
|
Cart,
|
||||||
AddCartItemBody<CartItemBody>
|
AddCartItemBody<CartItemBody>
|
||||||
> = async ({ options, input, fetch }) => {
|
> = mutationFetcher
|
||||||
return fetch({ ...options, body: input })
|
|
||||||
}
|
|
||||||
|
|
||||||
export type UseAddItem<
|
export type UseAddItem<
|
||||||
H extends MutationHook<any, any, any> = MutationHook<Cart, {}, CartItemBody>
|
H extends MutationHook<any, any, any> = MutationHook<Cart, {}, CartItemBody>
|
||||||
@ -17,8 +16,8 @@ export type UseAddItem<
|
|||||||
const fn = (provider: Provider) => provider.cart?.useAddItem!
|
const fn = (provider: Provider) => provider.cart?.useAddItem!
|
||||||
|
|
||||||
const useAddItem: UseAddItem = (...args) => {
|
const useAddItem: UseAddItem = (...args) => {
|
||||||
const handler = useHookHandler(fn, fetcher)
|
const hook = useHook(fn)
|
||||||
return handler(useHook(fn, fetcher))(...args)
|
return useMutationHook({ fetcher, ...hook })(...args)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useAddItem
|
export default useAddItem
|
||||||
|
@ -1,34 +1,21 @@
|
|||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
import type { Cart } from '../types'
|
import type { Cart } from '../types'
|
||||||
import type {
|
import type { HookFetcherFn, SWRHook } from '../utils/types'
|
||||||
Prop,
|
|
||||||
HookFetcherFn,
|
|
||||||
UseHookInput,
|
|
||||||
UseHookResponse,
|
|
||||||
} from '../utils/types'
|
|
||||||
import useData from '../utils/use-data'
|
|
||||||
import { Provider, useCommerce } from '..'
|
import { Provider, useCommerce } from '..'
|
||||||
|
import { useHook, useSWRHook } from '@commerce/utils/use-hook'
|
||||||
|
|
||||||
export type FetchCartInput = {
|
export type FetchCartInput = {
|
||||||
cartId?: Cart['id']
|
cartId?: Cart['id']
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UseCartHandler<P extends Provider> = Prop<
|
export type UseCart<
|
||||||
Prop<P, 'cart'>,
|
H extends SWRHook<any, any, any> = SWRHook<
|
||||||
'useCart'
|
Cart | null,
|
||||||
>
|
{},
|
||||||
|
FetchCartInput,
|
||||||
export type UseCartInput<P extends Provider> = UseHookInput<UseCartHandler<P>>
|
{ isEmpty?: boolean }
|
||||||
|
>
|
||||||
export type CartResponse<P extends Provider> = UseHookResponse<
|
> = ReturnType<H['useHook']>
|
||||||
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 const fetcher: HookFetcherFn<Cart | null, FetchCartInput> = async ({
|
export const fetcher: HookFetcherFn<Cart | null, FetchCartInput> = async ({
|
||||||
options,
|
options,
|
||||||
@ -38,32 +25,17 @@ export const fetcher: HookFetcherFn<Cart | null, FetchCartInput> = async ({
|
|||||||
return cartId ? await fetch({ ...options }) : null
|
return cartId ? await fetch({ ...options }) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function useCart<P extends Provider>(
|
const fn = (provider: Provider) => provider.cart?.useCart!
|
||||||
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 useCart: UseCart = (input) => {
|
||||||
|
const hook = useHook(fn)
|
||||||
|
const { cartCookie } = useCommerce()
|
||||||
|
const fetcherFn = hook.fetcher ?? fetcher
|
||||||
const wrapper: typeof fetcher = (context) => {
|
const wrapper: typeof fetcher = (context) => {
|
||||||
context.input.cartId = Cookies.get(cartCookie)
|
context.input.cartId = Cookies.get(cartCookie)
|
||||||
return fetcherFn(context)
|
return fetcherFn(context)
|
||||||
}
|
}
|
||||||
|
return useSWRHook({ ...hook, fetcher: wrapper })(input)
|
||||||
return useHook({
|
|
||||||
input,
|
|
||||||
useData(ctx) {
|
|
||||||
const response = useData(
|
|
||||||
{ ...opts!, fetcher: wrapper },
|
|
||||||
ctx?.input ?? [],
|
|
||||||
provider.fetcher ?? fetcherRef.current,
|
|
||||||
ctx?.swrOptions ?? input.swrOptions
|
|
||||||
)
|
|
||||||
return response
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 { 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 { Cart, LineItem, RemoveCartItemBody } from '../types'
|
||||||
import type { Provider } from '..'
|
import type { Provider } from '..'
|
||||||
|
|
||||||
@ -20,13 +20,16 @@ export type UseRemoveItem<
|
|||||||
>
|
>
|
||||||
> = ReturnType<H['useHook']>
|
> = ReturnType<H['useHook']>
|
||||||
|
|
||||||
export const fetcher = mutationFetcher
|
export const fetcher: HookFetcherFn<
|
||||||
|
Cart | null,
|
||||||
|
RemoveCartItemBody
|
||||||
|
> = mutationFetcher
|
||||||
|
|
||||||
const fn = (provider: Provider) => provider.cart?.useRemoveItem!
|
const fn = (provider: Provider) => provider.cart?.useRemoveItem!
|
||||||
|
|
||||||
const useRemoveItem: UseRemoveItem = (input) => {
|
const useRemoveItem: UseRemoveItem = (input) => {
|
||||||
const handler = useHookHandler(fn, fetcher)
|
const hook = useHook(fn)
|
||||||
return handler(useHook(fn, fetcher))(input)
|
return useMutationHook({ fetcher, ...hook })(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useRemoveItem
|
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 { 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 { Cart, CartItemBody, LineItem, UpdateCartItemBody } from '../types'
|
||||||
import type { Provider } from '..'
|
import type { Provider } from '..'
|
||||||
|
|
||||||
@ -23,13 +23,16 @@ export type UseUpdateItem<
|
|||||||
>
|
>
|
||||||
> = ReturnType<H['useHook']>
|
> = ReturnType<H['useHook']>
|
||||||
|
|
||||||
export const fetcher = mutationFetcher
|
export const fetcher: HookFetcherFn<
|
||||||
|
Cart | null,
|
||||||
|
UpdateCartItemBody<CartItemBody>
|
||||||
|
> = mutationFetcher
|
||||||
|
|
||||||
const fn = (provider: Provider) => provider.cart?.useUpdateItem!
|
const fn = (provider: Provider) => provider.cart?.useUpdateItem!
|
||||||
|
|
||||||
const useUpdateItem: UseUpdateItem = (input) => {
|
const useUpdateItem: UseUpdateItem = (input) => {
|
||||||
const handler = useHookHandler(fn, fetcher)
|
const hook = useHook(fn)
|
||||||
return handler(useHook(fn, fetcher))(input)
|
return useMutationHook({ fetcher, ...hook })(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default useUpdateItem
|
export default useUpdateItem
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
useMemo,
|
useMemo,
|
||||||
useRef,
|
useRef,
|
||||||
} from 'react'
|
} 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 { FetchCartInput } from './cart/use-cart'
|
||||||
import type { Cart, Wishlist, Customer, SearchProductsData } from './types'
|
import type { Cart, Wishlist, Customer, SearchProductsData } from './types'
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ const Commerce = createContext<CommerceContextValue<any> | {}>({})
|
|||||||
export type Provider = CommerceConfig & {
|
export type Provider = CommerceConfig & {
|
||||||
fetcher: Fetcher
|
fetcher: Fetcher
|
||||||
cart?: {
|
cart?: {
|
||||||
useCart?: HookHandler<Cart | null, any, FetchCartInput>
|
useCart?: SWRHook<Cart | null, any, FetchCartInput>
|
||||||
useAddItem?: MutationHook<any, any, any>
|
useAddItem?: MutationHook<any, any, any>
|
||||||
useUpdateItem?: MutationHook<any, any, any>
|
useUpdateItem?: MutationHook<any, any, any>
|
||||||
useRemoveItem?: MutationHook<any, any, any>
|
useRemoveItem?: MutationHook<any, any, any>
|
||||||
|
@ -3,7 +3,7 @@ import type { HookFetcherFn } from './types'
|
|||||||
const defaultFetcher: HookFetcherFn<any> = ({ options, fetch }) =>
|
const defaultFetcher: HookFetcherFn<any> = ({ options, fetch }) =>
|
||||||
fetch(options)
|
fetch(options)
|
||||||
|
|
||||||
export const mutationFetcher: HookFetcherFn<any> = ({
|
export const mutationFetcher: HookFetcherFn<any, any> = ({
|
||||||
input,
|
input,
|
||||||
options,
|
options,
|
||||||
fetch,
|
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
|
* 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> &
|
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
|
* Core fetcher added by CommerceProvider
|
||||||
@ -83,6 +85,36 @@ export type HookFunction<
|
|||||||
? (input?: Input) => T
|
? (input?: Input) => T
|
||||||
: (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<
|
export type MutationHook<
|
||||||
// Data obj returned by the hook and fetch operation
|
// Data obj returned by the hook and fetch operation
|
||||||
Data,
|
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 Prop<T, K extends keyof T> = NonNullable<T[K]>
|
||||||
|
|
||||||
export type HookHandlerType =
|
export type HookHandlerType = HookHandler<any, any, any>
|
||||||
| HookHandler<any, any, any>
|
|
||||||
| MutationHandler<any, any, any>
|
|
||||||
|
|
||||||
export type UseHookParameters<H extends HookHandlerType> = Parameters<
|
export type UseHookParameters<H extends HookHandlerType> = Parameters<
|
||||||
Prop<H, 'useHook'>
|
Prop<H, 'useHook'>
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import useSWR, { responseInterface } from 'swr'
|
import useSWR, { responseInterface } from 'swr'
|
||||||
import type {
|
import type {
|
||||||
HookHandler,
|
|
||||||
HookSwrInput,
|
HookSwrInput,
|
||||||
HookFetchInput,
|
HookFetchInput,
|
||||||
PickRequired,
|
|
||||||
Fetcher,
|
Fetcher,
|
||||||
SwrOptions,
|
SwrOptions,
|
||||||
|
HookFetcherOptions,
|
||||||
|
HookFetcherFn,
|
||||||
} from './types'
|
} from './types'
|
||||||
import defineProperty from './define-property'
|
import defineProperty from './define-property'
|
||||||
import { CommerceError } from './errors'
|
import { CommerceError } from './errors'
|
||||||
@ -19,7 +19,10 @@ export type UseData = <
|
|||||||
Input extends { [k: string]: unknown } = {},
|
Input extends { [k: string]: unknown } = {},
|
||||||
FetchInput extends HookFetchInput = {}
|
FetchInput extends HookFetchInput = {}
|
||||||
>(
|
>(
|
||||||
options: PickRequired<HookHandler<Data, Input, FetchInput>, 'fetcher'>,
|
options: {
|
||||||
|
fetchOptions: HookFetcherOptions
|
||||||
|
fetcher: HookFetcherFn<Data, FetchInput>
|
||||||
|
},
|
||||||
input: HookFetchInput | HookSwrInput,
|
input: HookFetchInput | HookSwrInput,
|
||||||
fetcherFn: Fetcher,
|
fetcherFn: Fetcher,
|
||||||
swrOptions?: SwrOptions<Data, FetchInput>
|
swrOptions?: SwrOptions<Data, FetchInput>
|
||||||
|
@ -1,43 +1,50 @@
|
|||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
import type { MutationHook } from './types'
|
import type { Fetcher, MutationHook, PickRequired, SWRHook } from './types'
|
||||||
import { Provider, useCommerce } from '..'
|
import { Provider, useCommerce } from '..'
|
||||||
|
import useData from './use-data'
|
||||||
|
|
||||||
export function useHookHandler<P extends Provider>(
|
export function useFetcher() {
|
||||||
fn: (provider: P) => MutationHook<any, any, any>,
|
const { providerRef, fetcherRef } = useCommerce()
|
||||||
fetcher: any
|
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 { providerRef } = useCommerce<P>()
|
||||||
const provider = providerRef.current
|
const provider = providerRef.current
|
||||||
const opts = fn(provider)
|
return 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>(
|
export function useSWRHook<H extends SWRHook<any, any, any>>(
|
||||||
fn: (provider: P) => MutationHook<any, any, any>,
|
hook: PickRequired<H, 'fetcher'>
|
||||||
fetcher: any
|
|
||||||
) {
|
) {
|
||||||
const { providerRef, fetcherRef } = useCommerce<P>()
|
const fetcher = useFetcher()
|
||||||
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 }
|
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