Fetch single product during build time

This commit is contained in:
tniezg
2021-07-28 14:05:46 +02:00
parent 24e635b048
commit a7a75e7f69
6 changed files with 193 additions and 115 deletions

View File

@@ -2,8 +2,10 @@ import type {
ProductOption,
ProductOptionValues,
} from '@commerce/types/product'
import type { JsonApiDocument } from '@spree/storefront-api-v2-sdk/types/interfaces/JsonApi'
import type { IProducts } from '@spree/storefront-api-v2-sdk/types/interfaces/Product'
import type {
JsonApiDocument,
JsonApiResponse,
} from '@spree/storefront-api-v2-sdk/types/interfaces/JsonApi'
import type { RelationType } from '@spree/storefront-api-v2-sdk/types/interfaces/Relationships'
import SpreeResponseContentError from '../errors/SpreeResponseContentError'
import { findIncluded } from './jsonApi'
@@ -12,7 +14,7 @@ const isColorProductOption = (productOption: ProductOption) =>
productOption.displayName === 'Color'
const expandOptions = (
spreeSuccessResponse: IProducts,
spreeSuccessResponse: JsonApiResponse,
spreeOptionValue: JsonApiDocument,
accumulatedOptions: ProductOption[]
): ProductOption[] => {

View File

@@ -0,0 +1,100 @@
import type {
ProductOption,
ProductPrice,
ProductVariant,
} from '@commerce/types/product'
import type {
JsonApiListResponse,
JsonApiResponse,
} 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'
import { requireConfigValue } from '../isomorphicConfig'
import createGetAbsoluteImageUrl from './createGetAbsoluteImageUrl'
import expandOptions from './expandOptions'
import getMediaGallery from './getMediaGallery'
import { findIncludedOfType } from './jsonApi'
const normalizeProduct = (
spreeSuccessResponse: JsonApiResponse | JsonApiListResponse,
spreeProduct: ProductAttr
) => {
const spreeImageRecords = findIncludedOfType(
spreeSuccessResponse,
spreeProduct,
'images'
)
const images = getMediaGallery(
spreeImageRecords,
createGetAbsoluteImageUrl(requireConfigValue('spreeImageHost'))
)
const price: ProductPrice = {
value: parseFloat(spreeProduct.attributes.price),
currencyCode: spreeProduct.attributes.currency,
}
// TODO: Add sku to product object equal to master SKU from Spree.
// Currently, the Spree API doesn't return it.
const hasNonMasterVariants =
(spreeProduct.relationships.variants.data as RelationType[]).length > 0
let variants: ProductVariant[]
let options: ProductOption[] = []
if (hasNonMasterVariants) {
const spreeVariantRecords = findIncludedOfType(
spreeSuccessResponse,
spreeProduct,
'variants'
)
variants = spreeVariantRecords.map((spreeVariantRecord) => {
const spreeOptionValues = findIncludedOfType(
spreeSuccessResponse,
spreeVariantRecord,
'option_values'
)
let variantOptions: ProductOption[] = []
// Only include options which are used by variants.
spreeOptionValues.forEach((spreeOptionValue) => {
variantOptions = expandOptions(
spreeSuccessResponse,
spreeOptionValue,
variantOptions
)
options = expandOptions(spreeSuccessResponse, spreeOptionValue, options)
})
return {
id: spreeVariantRecord.id,
options: variantOptions,
}
})
} else {
variants = []
}
const slug = spreeProduct.attributes.slug
const path = `/${spreeProduct.attributes.slug}`
return {
id: spreeProduct.id,
name: spreeProduct.attributes.name,
description: spreeProduct.attributes.description,
images,
variants,
options,
price,
slug,
path,
}
}
export default normalizeProduct