mirror of
https://github.com/vercel/commerce.git
synced 2025-07-25 19:21:23 +00:00
Add configuration to show product options when there's one variant available
This commit is contained in:
72
framework/spree/utils/createCreateFetchFetcher.ts
Normal file
72
framework/spree/utils/createCreateFetchFetcher.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import * as qs from 'qs'
|
||||
import { errors } from '@spree/storefront-api-v2-sdk'
|
||||
import type { CreateFetcher } from '@spree/storefront-api-v2-sdk/types/interfaces/ClientConfig'
|
||||
import { Request } from 'node-fetch'
|
||||
|
||||
// TODO: Fix rawFetch any type.
|
||||
const createCreateFetchFetcher =
|
||||
({ fetch: rawFetch }): CreateFetcher =>
|
||||
(fetcherOptions) => {
|
||||
const { FetchError } = errors
|
||||
const sharedHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
|
||||
return {
|
||||
fetch: async (fetchOptions) => {
|
||||
// This fetcher always returns request equal null,
|
||||
// because @vercel/fetch doesn't accept a Request object as argument
|
||||
// and it's not used by NJC anyway.
|
||||
try {
|
||||
const { url, params, method, headers } = fetchOptions
|
||||
const absoluteUrl = new URL(url, fetcherOptions.host)
|
||||
let payload
|
||||
|
||||
switch (method.toUpperCase()) {
|
||||
case 'PUT':
|
||||
case 'POST':
|
||||
case 'DELETE':
|
||||
case 'PATCH':
|
||||
payload = { body: JSON.stringify(params) }
|
||||
break
|
||||
default:
|
||||
payload = null
|
||||
absoluteUrl.search = qs.stringify(params, {
|
||||
arrayFormat: 'brackets',
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await rawFetch(absoluteUrl.toString(), {
|
||||
method,
|
||||
headers: { ...sharedHeaders, ...headers },
|
||||
...payload,
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
if (!response.ok) {
|
||||
// Use the "traditional" approach and reject non 2xx responses.
|
||||
throw new FetchError(response, null, data)
|
||||
}
|
||||
|
||||
return {
|
||||
// Add response key to the prototype so it can be passed inside the GraphQLFetcherResult type.
|
||||
// TODO: Search for a better solution than adding response to the prototype.
|
||||
data: Object.setPrototypeOf({ data }, { response }),
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof TypeError) {
|
||||
throw new FetchError(null, null, null)
|
||||
}
|
||||
|
||||
throw error
|
||||
}
|
||||
} catch (error) {
|
||||
throw new FetchError(null, null, null, error.message)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default createCreateFetchFetcher
|
@@ -5,7 +5,7 @@ import type {
|
||||
} from '@commerce/types/product'
|
||||
import type {
|
||||
JsonApiListResponse,
|
||||
JsonApiResponse,
|
||||
JsonApiSingleResponse,
|
||||
} from '@spree/storefront-api-v2-sdk/types/interfaces/JsonApi'
|
||||
import type { ProductAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Product'
|
||||
import type { RelationType } from '@spree/storefront-api-v2-sdk/types/interfaces/Relationships'
|
||||
@@ -16,7 +16,7 @@ import getMediaGallery from './getMediaGallery'
|
||||
import { findIncludedOfType } from './jsonApi'
|
||||
|
||||
const normalizeProduct = (
|
||||
spreeSuccessResponse: JsonApiResponse | JsonApiListResponse,
|
||||
spreeSuccessResponse: JsonApiSingleResponse | JsonApiListResponse,
|
||||
spreeProduct: ProductAttr
|
||||
) => {
|
||||
const spreeImageRecords = findIncludedOfType(
|
||||
@@ -27,7 +27,7 @@ const normalizeProduct = (
|
||||
|
||||
const images = getMediaGallery(
|
||||
spreeImageRecords,
|
||||
createGetAbsoluteImageUrl(requireConfigValue('spreeImageHost'))
|
||||
createGetAbsoluteImageUrl(requireConfigValue('spreeImageHost') as string)
|
||||
)
|
||||
|
||||
const price: ProductPrice = {
|
||||
@@ -41,6 +41,10 @@ const normalizeProduct = (
|
||||
const hasNonMasterVariants =
|
||||
(spreeProduct.relationships.variants.data as RelationType[]).length > 1
|
||||
|
||||
const showOptions =
|
||||
(requireConfigValue('showSingleVariantOptions') as boolean) ||
|
||||
hasNonMasterVariants
|
||||
|
||||
let variants: ProductVariant[]
|
||||
let options: ProductOption[] = []
|
||||
|
||||
@@ -53,7 +57,7 @@ const normalizeProduct = (
|
||||
variants = spreeVariantRecords.map((spreeVariantRecord) => {
|
||||
let variantOptions: ProductOption[] = []
|
||||
|
||||
if (hasNonMasterVariants) {
|
||||
if (showOptions) {
|
||||
const spreeOptionValues = findIncludedOfType(
|
||||
spreeSuccessResponse,
|
||||
spreeVariantRecord,
|
||||
|
Reference in New Issue
Block a user