Skip to content

Commit

Permalink
Allow query hook parameters to be null. (#1046)
Browse files Browse the repository at this point in the history
* Remove unused util.

* Allow query hook parameters to be `null`.
  • Loading branch information
wjhsf authored Mar 9, 2023
1 parent 246d484 commit fc789fe
Show file tree
Hide file tree
Showing 23 changed files with 508 additions and 295 deletions.
69 changes: 42 additions & 27 deletions packages/commerce-sdk-react/src/hooks/ShopperBaskets/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,25 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import {UseQueryResult} from '@tanstack/react-query'
import {ApiClients, ApiQueryOptions, Argument, DataType} from '../types'
import {ApiClients, ApiQueryOptions, Argument, DataType, NullableParameters} from '../types'
import useCommerceApi from '../useCommerceApi'
import {useQuery} from '../useQuery'
import {mergeOptions} from '../utils'
import {mergeOptions, omitNullableParameters} from '../utils'
import * as queryKeyHelpers from './queryKeyHelpers'

type Client = ApiClients['shopperBaskets']

/**
* Gets a basket.
* @parameter apiOptions - Options to pass through to `commerce-sdk-isomorphic`, with `null` accepted for unset API parameters.
* @parameter queryOptions - TanStack Query query options, with `enabled` by default set to check that all required API parameters have been set.
* @returns A TanStack Query query hook with data from the Shopper Baskets `getBasket` endpoint.
* @see {@link https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets?meta=getBasket| Salesforce Developer Center} for more information about the API endpoint.
* @see {@link https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/classes/shopperbaskets.shopperbaskets-1.html#getbasket | `commerce-sdk-isomorphic` documentation} for more information on the parameters and returned data type.
* @see {@link https://tanstack.com/query/latest/docs/react/reference/useQuery | TanStack Query `useQuery` reference} for more information about the return value.
*/
export const useBasket = (
apiOptions: Argument<Client['getBasket']>,
apiOptions: NullableParameters<Argument<Client['getBasket']>>,
queryOptions: ApiQueryOptions<Client['getBasket']> = {}
): UseQueryResult<DataType<Client['getBasket']>> => {
type Options = Argument<Client['getBasket']>
Expand All @@ -30,29 +32,32 @@ export const useBasket = (
const methodName = 'getBasket'
const requiredParameters = ['organizationId', 'basketId', 'siteId'] as const

// Parameters can be set in `apiOptions` or `client.clientConfig`, we must merge them in order
// to generate the correct query key.
const netOptions = mergeOptions(client, apiOptions)
// Parameters can be set in `apiOptions` or `client.clientConfig`;
// we must merge them in order to generate the correct query key.
const netOptions = omitNullableParameters(mergeOptions(client, apiOptions))
const queryKey = queryKeyHelpers[methodName].queryKey(netOptions.parameters)
// We don't use `netOptions` here because we manipulate the options in `useQuery`.
const method = async (options: Options) => await client[methodName](options)

// For some reason, if we don't explicitly set these generic parameters, the inferred type for
// `Data` sometimes, but not always, includes `Response`, which is incorrect. I don't know why.
return useQuery<Options, Data>(netOptions, queryOptions, {
return useQuery<Client, Options, Data>(netOptions, queryOptions, {
method,
queryKey,
requiredParameters
})
}
/**
* Gets applicable payment methods for an existing basket considering the open payment amount only.
* @parameter apiOptions - Options to pass through to `commerce-sdk-isomorphic`, with `null` accepted for unset API parameters.
* @parameter queryOptions - TanStack Query query options, with `enabled` by default set to check that all required API parameters have been set.
* @returns A TanStack Query query hook with data from the Shopper Baskets `getPaymentMethodsForBasket` endpoint.
* @see {@link https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets?meta=getPaymentMethodsForBasket| Salesforce Developer Center} for more information about the API endpoint.
* @see {@link https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/classes/shopperbaskets.shopperbaskets-1.html#getpaymentmethodsforbasket | `commerce-sdk-isomorphic` documentation} for more information on the parameters and returned data type.
* @see {@link https://tanstack.com/query/latest/docs/react/reference/useQuery | TanStack Query `useQuery` reference} for more information about the return value.
*/
export const usePaymentMethodsForBasket = (
apiOptions: Argument<Client['getPaymentMethodsForBasket']>,
apiOptions: NullableParameters<Argument<Client['getPaymentMethodsForBasket']>>,
queryOptions: ApiQueryOptions<Client['getPaymentMethodsForBasket']> = {}
): UseQueryResult<DataType<Client['getPaymentMethodsForBasket']>> => {
type Options = Argument<Client['getPaymentMethodsForBasket']>
Expand All @@ -61,29 +66,32 @@ export const usePaymentMethodsForBasket = (
const methodName = 'getPaymentMethodsForBasket'
const requiredParameters = ['organizationId', 'basketId', 'siteId'] as const

// Parameters can be set in `apiOptions` or `client.clientConfig`, we must merge them in order
// to generate the correct query key.
const netOptions = mergeOptions(client, apiOptions)
// Parameters can be set in `apiOptions` or `client.clientConfig`;
// we must merge them in order to generate the correct query key.
const netOptions = omitNullableParameters(mergeOptions(client, apiOptions))
const queryKey = queryKeyHelpers[methodName].queryKey(netOptions.parameters)
// We don't use `netOptions` here because we manipulate the options in `useQuery`.
const method = async (options: Options) => await client[methodName](options)

// For some reason, if we don't explicitly set these generic parameters, the inferred type for
// `Data` sometimes, but not always, includes `Response`, which is incorrect. I don't know why.
return useQuery<Options, Data>(netOptions, queryOptions, {
return useQuery<Client, Options, Data>(netOptions, queryOptions, {
method,
queryKey,
requiredParameters
})
}
/**
* Gets applicable price books for an existing basket.
* @parameter apiOptions - Options to pass through to `commerce-sdk-isomorphic`, with `null` accepted for unset API parameters.
* @parameter queryOptions - TanStack Query query options, with `enabled` by default set to check that all required API parameters have been set.
* @returns A TanStack Query query hook with data from the Shopper Baskets `getPriceBooksForBasket` endpoint.
* @see {@link https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets?meta=getPriceBooksForBasket| Salesforce Developer Center} for more information about the API endpoint.
* @see {@link https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/classes/shopperbaskets.shopperbaskets-1.html#getpricebooksforbasket | `commerce-sdk-isomorphic` documentation} for more information on the parameters and returned data type.
* @see {@link https://tanstack.com/query/latest/docs/react/reference/useQuery | TanStack Query `useQuery` reference} for more information about the return value.
*/
export const usePriceBooksForBasket = (
apiOptions: Argument<Client['getPriceBooksForBasket']>,
apiOptions: NullableParameters<Argument<Client['getPriceBooksForBasket']>>,
queryOptions: ApiQueryOptions<Client['getPriceBooksForBasket']> = {}
): UseQueryResult<DataType<Client['getPriceBooksForBasket']>> => {
type Options = Argument<Client['getPriceBooksForBasket']>
Expand All @@ -92,29 +100,32 @@ export const usePriceBooksForBasket = (
const methodName = 'getPriceBooksForBasket'
const requiredParameters = ['organizationId', 'basketId', 'siteId'] as const

// Parameters can be set in `apiOptions` or `client.clientConfig`, we must merge them in order
// to generate the correct query key.
const netOptions = mergeOptions(client, apiOptions)
// Parameters can be set in `apiOptions` or `client.clientConfig`;
// we must merge them in order to generate the correct query key.
const netOptions = omitNullableParameters(mergeOptions(client, apiOptions))
const queryKey = queryKeyHelpers[methodName].queryKey(netOptions.parameters)
// We don't use `netOptions` here because we manipulate the options in `useQuery`.
const method = async (options: Options) => await client[methodName](options)

// For some reason, if we don't explicitly set these generic parameters, the inferred type for
// `Data` sometimes, but not always, includes `Response`, which is incorrect. I don't know why.
return useQuery<Options, Data>(netOptions, queryOptions, {
return useQuery<Client, Options, Data>(netOptions, queryOptions, {
method,
queryKey,
requiredParameters
})
}
/**
* Gets the applicable shipping methods for a certain shipment of a basket.
* @parameter apiOptions - Options to pass through to `commerce-sdk-isomorphic`, with `null` accepted for unset API parameters.
* @parameter queryOptions - TanStack Query query options, with `enabled` by default set to check that all required API parameters have been set.
* @returns A TanStack Query query hook with data from the Shopper Baskets `getShippingMethodsForShipment` endpoint.
* @see {@link https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets?meta=getShippingMethodsForShipment| Salesforce Developer Center} for more information about the API endpoint.
* @see {@link https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/classes/shopperbaskets.shopperbaskets-1.html#getshippingmethodsforshipment | `commerce-sdk-isomorphic` documentation} for more information on the parameters and returned data type.
* @see {@link https://tanstack.com/query/latest/docs/react/reference/useQuery | TanStack Query `useQuery` reference} for more information about the return value.
*/
export const useShippingMethodsForShipment = (
apiOptions: Argument<Client['getShippingMethodsForShipment']>,
apiOptions: NullableParameters<Argument<Client['getShippingMethodsForShipment']>>,
queryOptions: ApiQueryOptions<Client['getShippingMethodsForShipment']> = {}
): UseQueryResult<DataType<Client['getShippingMethodsForShipment']>> => {
type Options = Argument<Client['getShippingMethodsForShipment']>
Expand All @@ -123,29 +134,32 @@ export const useShippingMethodsForShipment = (
const methodName = 'getShippingMethodsForShipment'
const requiredParameters = ['organizationId', 'basketId', 'shipmentId', 'siteId'] as const

// Parameters can be set in `apiOptions` or `client.clientConfig`, we must merge them in order
// to generate the correct query key.
const netOptions = mergeOptions(client, apiOptions)
// Parameters can be set in `apiOptions` or `client.clientConfig`;
// we must merge them in order to generate the correct query key.
const netOptions = omitNullableParameters(mergeOptions(client, apiOptions))
const queryKey = queryKeyHelpers[methodName].queryKey(netOptions.parameters)
// We don't use `netOptions` here because we manipulate the options in `useQuery`.
const method = async (options: Options) => await client[methodName](options)

// For some reason, if we don't explicitly set these generic parameters, the inferred type for
// `Data` sometimes, but not always, includes `Response`, which is incorrect. I don't know why.
return useQuery<Options, Data>(netOptions, queryOptions, {
return useQuery<Client, Options, Data>(netOptions, queryOptions, {
method,
queryKey,
requiredParameters
})
}
/**
* This method gives you the external taxation data set by the PUT taxes API. This endpoint can be called only if external taxation mode was used for basket creation. See POST /baskets for more information.
* @parameter apiOptions - Options to pass through to `commerce-sdk-isomorphic`, with `null` accepted for unset API parameters.
* @parameter queryOptions - TanStack Query query options, with `enabled` by default set to check that all required API parameters have been set.
* @returns A TanStack Query query hook with data from the Shopper Baskets `getTaxesFromBasket` endpoint.
* @see {@link https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets?meta=getTaxesFromBasket| Salesforce Developer Center} for more information about the API endpoint.
* @see {@link https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/classes/shopperbaskets.shopperbaskets-1.html#gettaxesfrombasket | `commerce-sdk-isomorphic` documentation} for more information on the parameters and returned data type.
* @see {@link https://tanstack.com/query/latest/docs/react/reference/useQuery | TanStack Query `useQuery` reference} for more information about the return value.
*/
export const useTaxesFromBasket = (
apiOptions: Argument<Client['getTaxesFromBasket']>,
apiOptions: NullableParameters<Argument<Client['getTaxesFromBasket']>>,
queryOptions: ApiQueryOptions<Client['getTaxesFromBasket']> = {}
): UseQueryResult<DataType<Client['getTaxesFromBasket']>> => {
type Options = Argument<Client['getTaxesFromBasket']>
Expand All @@ -154,15 +168,16 @@ export const useTaxesFromBasket = (
const methodName = 'getTaxesFromBasket'
const requiredParameters = ['organizationId', 'basketId', 'siteId'] as const

// Parameters can be set in `apiOptions` or `client.clientConfig`, we must merge them in order
// to generate the correct query key.
const netOptions = mergeOptions(client, apiOptions)
// Parameters can be set in `apiOptions` or `client.clientConfig`;
// we must merge them in order to generate the correct query key.
const netOptions = omitNullableParameters(mergeOptions(client, apiOptions))
const queryKey = queryKeyHelpers[methodName].queryKey(netOptions.parameters)
// We don't use `netOptions` here because we manipulate the options in `useQuery`.
const method = async (options: Options) => await client[methodName](options)

// For some reason, if we don't explicitly set these generic parameters, the inferred type for
// `Data` sometimes, but not always, includes `Response`, which is incorrect. I don't know why.
return useQuery<Options, Data>(netOptions, queryOptions, {
return useQuery<Client, Options, Data>(netOptions, queryOptions, {
method,
queryKey,
requiredParameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,46 @@ import {pick} from '../utils'

// We must use a client with no parameters in order to have required/optional match the API spec
type Client = ShopperBaskets<{shortCode: string}>
type Params<T extends keyof QueryKeys> = NonNullable<Argument<Client[T]>['parameters']>
type Params<T extends keyof QueryKeys> = Partial<Argument<Client[T]>['parameters']>
export type QueryKeys = {
getBasket: ['/organizations/', string, '/baskets/', string, Params<'getBasket'>]
getBasket: [
'/organizations/',
string | undefined,
'/baskets/',
string | undefined,
Params<'getBasket'>
]
getPaymentMethodsForBasket: [
'/organizations/',
string,
string | undefined,
'/baskets/',
string,
string | undefined,
'/payment-methods',
Params<'getPaymentMethodsForBasket'>
]
getPriceBooksForBasket: [
'/organizations/',
string,
string | undefined,
'/baskets/',
string,
string | undefined,
'/price-books',
Params<'getPriceBooksForBasket'>
]
getShippingMethodsForShipment: [
'/organizations/',
string,
string | undefined,
'/baskets/',
string,
string | undefined,
'/shipments/',
string,
string | undefined,
'/shipping-methods',
Params<'getShippingMethodsForShipment'>
]
getTaxesFromBasket: [
'/organizations/',
string,
string | undefined,
'/baskets/',
string,
string | undefined,
'/taxes',
Params<'getTaxesFromBasket'>
]
Expand Down
17 changes: 10 additions & 7 deletions packages/commerce-sdk-react/src/hooks/ShopperContexts/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,25 @@
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import {UseQueryResult} from '@tanstack/react-query'
import {ApiClients, ApiQueryOptions, Argument, DataType} from '../types'
import {ApiClients, ApiQueryOptions, Argument, DataType, NullableParameters} from '../types'
import useCommerceApi from '../useCommerceApi'
import {useQuery} from '../useQuery'
import {mergeOptions} from '../utils'
import {mergeOptions, omitNullableParameters} from '../utils'
import * as queryKeyHelpers from './queryKeyHelpers'

type Client = ApiClients['shopperContexts']

/**
* Gets the shopper's context based on the shopperJWT. ******** This API is currently a work in progress, and not available to use yet. ********
* @parameter apiOptions - Options to pass through to `commerce-sdk-isomorphic`, with `null` accepted for unset API parameters.
* @parameter queryOptions - TanStack Query query options, with `enabled` by default set to check that all required API parameters have been set.
* @returns A TanStack Query query hook with data from the Shopper Contexts `getShopperContext` endpoint.
* @see {@link https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-contexts?meta=getShopperContext| Salesforce Developer Center} for more information about the API endpoint.
* @see {@link https://salesforcecommercecloud.github.io/commerce-sdk-isomorphic/classes/shoppercontexts.shoppercontexts-1.html#getshoppercontext | `commerce-sdk-isomorphic` documentation} for more information on the parameters and returned data type.
* @see {@link https://tanstack.com/query/latest/docs/react/reference/useQuery | TanStack Query `useQuery` reference} for more information about the return value.
*/
export const useShopperContext = (
apiOptions: Argument<Client['getShopperContext']>,
apiOptions: NullableParameters<Argument<Client['getShopperContext']>>,
queryOptions: ApiQueryOptions<Client['getShopperContext']> = {}
): UseQueryResult<DataType<Client['getShopperContext']>> => {
type Options = Argument<Client['getShopperContext']>
Expand All @@ -30,15 +32,16 @@ export const useShopperContext = (
const methodName = 'getShopperContext'
const requiredParameters = ['organizationId', 'usid'] as const

// Parameters can be set in `apiOptions` or `client.clientConfig`, we must merge them in order
// to generate the correct query key.
const netOptions = mergeOptions(client, apiOptions)
// Parameters can be set in `apiOptions` or `client.clientConfig`;
// we must merge them in order to generate the correct query key.
const netOptions = omitNullableParameters(mergeOptions(client, apiOptions))
const queryKey = queryKeyHelpers[methodName].queryKey(netOptions.parameters)
// We don't use `netOptions` here because we manipulate the options in `useQuery`.
const method = async (options: Options) => await client[methodName](options)

// For some reason, if we don't explicitly set these generic parameters, the inferred type for
// `Data` sometimes, but not always, includes `Response`, which is incorrect. I don't know why.
return useQuery<Options, Data>(netOptions, queryOptions, {
return useQuery<Client, Options, Data>(netOptions, queryOptions, {
method,
queryKey,
requiredParameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import {pick} from '../utils'

// We must use a client with no parameters in order to have required/optional match the API spec
type Client = ShopperContexts<{shortCode: string}>
type Params<T extends keyof QueryKeys> = NonNullable<Argument<Client[T]>['parameters']>
type Params<T extends keyof QueryKeys> = Partial<Argument<Client[T]>['parameters']>
export type QueryKeys = {
getShopperContext: [
'/organizations/',
string,
string | undefined,
'/shopper-context/',
string,
string | undefined,
Params<'getShopperContext'>
]
}
Expand Down
Loading

0 comments on commit fc789fe

Please sign in to comment.