diff --git a/framework/bigcommerce/index.tsx b/framework/bigcommerce/index.tsx
index 83fbdbcbc..b35785ed2 100644
--- a/framework/bigcommerce/index.tsx
+++ b/framework/bigcommerce/index.tsx
@@ -1,4 +1,4 @@
-import { ReactNode } from 'react'
+import type { ReactNode } from 'react'
import {
CommerceConfig,
CommerceProvider as CoreCommerceProvider,
diff --git a/framework/bigcommerce/provider.ts b/framework/bigcommerce/provider.ts
index b6385546c..e4ab5c757 100644
--- a/framework/bigcommerce/provider.ts
+++ b/framework/bigcommerce/provider.ts
@@ -43,7 +43,7 @@ const fetcher: Fetcher = async ({
const useCart: HookHandler<
Cart | null,
- [],
+ {},
FetchCartInput,
any,
any,
@@ -71,7 +71,7 @@ const useCart: HookHandler<
const useWishlist: HookHandler<
Cart | null,
- [],
+ {},
FetchCartInput,
any,
any,
diff --git a/framework/commerce/cart/use-cart.tsx b/framework/commerce/cart/use-cart.tsx
index b19e609da..8f40fd055 100644
--- a/framework/commerce/cart/use-cart.tsx
+++ b/framework/commerce/cart/use-cart.tsx
@@ -1,8 +1,8 @@
import { useMemo } from 'react'
import Cookies from 'js-cookie'
-import type { Cart } from '../types'
import type { HookFetcherFn } from '../utils/types'
import useData from '../utils/use-data-2'
+import type { Cart } from '../types'
import { Provider, useCommerce } from '..'
export type FetchCartInput = {
@@ -13,13 +13,17 @@ export type CartResponse
= ReturnType<
NonNullable['useCart']>['onResponse']>
>
-export type UseCart = (
- ...input: UseCartInput
-) => CartResponse
+export type UseCartInput
= Parameters<
+ NonNullable<
+ NonNullable['useCart']>>['input']
+ >
+>[0]
-export type UseCartInput = NonNullable<
- NonNullable['useCart']>>['input']
->
+export type UseCart = Partial<
+ UseCartInput
+> extends UseCartInput
+ ? (input?: UseCartInput
) => CartResponse
+ : (input: UseCartInput
) => CartResponse
export const fetcher: HookFetcherFn = async ({
options,
@@ -31,7 +35,7 @@ export const fetcher: HookFetcherFn = async ({
return data && normalize ? normalize(data) : data
}
-export default function useCart(...input: UseCartInput
) {
+export default function useCart
(input?: UseCartInput
) {
const { providerRef, fetcherRef, cartCookie } = useCommerce
()
const provider = providerRef.current
@@ -43,7 +47,7 @@ export default function useCart
(...input: UseCartInput
) {
}
const response = useData(
{ ...opts, fetcher: wrapper },
- input,
+ opts?.input ? opts.input(input ?? {}) : [],
provider.fetcher ?? fetcherRef.current
)
const memoizedResponse = useMemo(
diff --git a/framework/commerce/index.tsx b/framework/commerce/index.tsx
index 82e86947d..fa7e3e7e8 100644
--- a/framework/commerce/index.tsx
+++ b/framework/commerce/index.tsx
@@ -16,10 +16,10 @@ const Commerce = createContext | {}>({})
export type Provider = CommerceConfig & {
fetcher: Fetcher
cart?: {
- useCart?: HookHandler
+ useCart?: HookHandler
}
wishlist?: {
- useWishlist?: HookHandler
+ useWishlist?: HookHandler
}
}
diff --git a/framework/commerce/utils/types.ts b/framework/commerce/utils/types.ts
index d84ec07f0..6b4f1ddbe 100644
--- a/framework/commerce/utils/types.ts
+++ b/framework/commerce/utils/types.ts
@@ -4,11 +4,15 @@ import type { ResponseState } from './use-data'
export type Override = Omit & 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 = Omit &
Required>
-// Core fetcher added by CommerceProvider
+/**
+ * Core fetcher added by CommerceProvider
+ */
export type Fetcher = (
options: FetcherOptions
) => T | Promise
@@ -47,15 +51,17 @@ export type HookFetcherOptions = {
export type HookInputValue = string | number | boolean | undefined
-export type HookInput = [string, HookInputValue][]
+export type HookSwrInput = [string, HookInputValue][]
export type HookFetchInput = { [k: string]: HookInputValue }
+export type HookInput = {}
+
export type HookHandler<
// Data obj returned by the hook and fetch operation
Data,
// Input expected by the hook
- Input = [...any],
+ Input extends { [k: string]: unknown } = {},
// Input expected before doing a fetch operation
FetchInput extends HookFetchInput = never,
// Data returned by the API after a fetch operation
@@ -65,7 +71,9 @@ export type HookHandler<
// Custom state added to the response object of SWR
State = {}
> = {
- input?: Input
+ input?(
+ input: Input & { swrOptions?: SwrOptions }
+ ): HookFetchInput | HookSwrInput
swrOptions?: SwrOptions
onResponse?(response: ResponseState): ResponseState & State
onMutation?: any
diff --git a/framework/commerce/utils/use-data-2.ts b/framework/commerce/utils/use-data-2.ts
index 5536bb02c..d9a9e9a39 100644
--- a/framework/commerce/utils/use-data-2.ts
+++ b/framework/commerce/utils/use-data-2.ts
@@ -1,7 +1,7 @@
import useSWR, { responseInterface } from 'swr'
import type {
HookHandler,
- HookInput,
+ HookSwrInput,
HookFetchInput,
PickRequired,
Fetcher,
@@ -15,7 +15,7 @@ export type ResponseState = responseInterface & {
export type UseData = <
Data = any,
- Input = [...any],
+ Input extends { [k: string]: unknown } = {},
FetchInput extends HookFetchInput = never,
Result = any,
Body = any
@@ -24,11 +24,12 @@ export type UseData = <
HookHandler,
'fetcher'
>,
- input: HookInput,
+ input: HookFetchInput | HookSwrInput,
fetcherFn: Fetcher
) => ResponseState
const useData: UseData = (options, input, fetcherFn) => {
+ const hookInput = Array.isArray(input) ? input : Object.entries(input)
const fetcher = async (
url?: string,
query?: string,
@@ -40,7 +41,7 @@ const useData: UseData = (options, input, fetcherFn) => {
options: { url, query, method },
// Transform the input array into an object
input: args.reduce((obj, val, i) => {
- obj[input[i][0]!] = val
+ obj[hookInput[i][0]!] = val
return obj
}, {}),
fetch: fetcherFn,
@@ -59,7 +60,7 @@ const useData: UseData = (options, input, fetcherFn) => {
() => {
const opts = options.fetchOptions
return opts
- ? [opts.url, opts.query, opts.method, ...input.map((e) => e[1])]
+ ? [opts.url, opts.query, opts.method, ...hookInput.map((e) => e[1])]
: null
},
fetcher,
diff --git a/framework/commerce/utils/use-data.tsx b/framework/commerce/utils/use-data.tsx
index 38af46a44..58a1a0a47 100644
--- a/framework/commerce/utils/use-data.tsx
+++ b/framework/commerce/utils/use-data.tsx
@@ -1,5 +1,5 @@
import useSWR, { ConfigInterface, responseInterface } from 'swr'
-import type { HookInput, HookFetcher, HookFetcherOptions } from './types'
+import type { HookSwrInput, HookFetcher, HookFetcherOptions } from './types'
import defineProperty from './define-property'
import { CommerceError } from './errors'
import { useCommerce } from '..'
@@ -16,7 +16,7 @@ export type ResponseState = responseInterface & {
export type UseData = (
options: HookFetcherOptions | (() => HookFetcherOptions | null),
- input: HookInput,
+ input: HookSwrInput,
fetcherFn: HookFetcher,
swrOptions?: SwrOptions
) => ResponseState
diff --git a/framework/commerce/wishlist/use-wishlist.tsx b/framework/commerce/wishlist/use-wishlist.tsx
index df8bebe5c..5272766c6 100644
--- a/framework/commerce/wishlist/use-wishlist.tsx
+++ b/framework/commerce/wishlist/use-wishlist.tsx
@@ -1,4 +1,8 @@
-import type { HookInput, HookFetcher, HookFetcherOptions } from '../utils/types'
+import type {
+ HookSwrInput,
+ HookFetcher,
+ HookFetcherOptions,
+} from '../utils/types'
import useData, { ResponseState, SwrOptions } from '../utils/use-data'
export type WishlistResponse = ResponseState & {
@@ -7,7 +11,7 @@ export type WishlistResponse = ResponseState & {
export default function useWishlist(
options: HookFetcherOptions,
- input: HookInput,
+ input: HookSwrInput,
fetcherFn: HookFetcher,
swrOptions?: SwrOptions
): WishlistResponse {