diff --git a/framework/spree/utils/expand-options.ts b/framework/spree/utils/expand-options.ts index f9381a738..3b7b31b7b 100644 --- a/framework/spree/utils/expand-options.ts +++ b/framework/spree/utils/expand-options.ts @@ -6,9 +6,10 @@ import type { JsonApiDocument, JsonApiResponse, } from '@spree/storefront-api-v2-sdk/types/interfaces/JsonApi' +import { jsonApi } from '@spree/storefront-api-v2-sdk' import type { RelationType } from '@spree/storefront-api-v2-sdk/types/interfaces/Relationships' import SpreeResponseContentError from '../errors/SpreeResponseContentError' -import { findIncluded } from './find-json-api-documents' +import type { OptionTypeAttr } from '@framework/types' const isColorProductOption = (productOption: ProductOption) => { return productOption.displayName === 'Color' @@ -29,10 +30,9 @@ const expandOptions = ( let option: ProductOption if (existingOptionIndex === -1) { - const spreeOptionType = findIncluded( + const spreeOptionType = jsonApi.findDocument( spreeSuccessResponse, - spreeOptionTypeIdentifier.type, - spreeOptionTypeIdentifier.id + spreeOptionTypeIdentifier ) if (!spreeOptionType) { diff --git a/framework/spree/utils/find-json-api-documents.ts b/framework/spree/utils/find-json-api-documents.ts deleted file mode 100644 index 6dc30f89f..000000000 --- a/framework/spree/utils/find-json-api-documents.ts +++ /dev/null @@ -1,46 +0,0 @@ -// Based on https://github.com/spark-solutions/spree2vuestorefront - -import type { - JsonApiResponse, - JsonApiDocument, -} from '@spree/storefront-api-v2-sdk/types/interfaces/JsonApi' - -export const findIncluded = ( - response: JsonApiResponse, - objectType: string, - objectId: string -): T | null => { - if (!response.included) { - return null - } - - return ( - (response.included.find( - (includedObject) => - includedObject.type === objectType && includedObject.id === objectId - ) as T) || null - ) -} - -export const findIncludedOfType = ( - response: JsonApiResponse, - singlePrimaryRecord: JsonApiDocument, - objectRelationshipType: string -): T[] => { - if (!response.included) { - return [] - } - - const typeRelationships = - singlePrimaryRecord.relationships[objectRelationshipType] - - if (!typeRelationships) { - return [] - } - - return typeRelationships.data - .map((typeObject: JsonApiDocument) => - findIncluded(response, typeObject.type, typeObject.id) - ) - .filter((typeRecord: JsonApiDocument | null) => !!typeRecord) -} diff --git a/framework/spree/utils/normalize-cart.ts b/framework/spree/utils/normalize-cart.ts index ce4098b63..6aa6197ab 100644 --- a/framework/spree/utils/normalize-cart.ts +++ b/framework/spree/utils/normalize-cart.ts @@ -6,23 +6,19 @@ import type { } from '@commerce/types/cart' import MissingLineItemVariantError from '../errors/MissingLineItemVariantError' import { requireConfigValue } from '../isomorphic-config' -import type { - JsonApiListResponse, - JsonApiSingleResponse, -} from '@spree/storefront-api-v2-sdk/types/interfaces/JsonApi' import type { OrderAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Order' 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 createGetAbsoluteImageUrl from './create-get-absolute-image-url' import getMediaGallery from './get-media-gallery' -import { findIncluded, findIncludedOfType } from './find-json-api-documents' import type { LineItemAttr, OptionTypeAttr, + SpreeProductImage, SpreeSdkResponse, VariantAttr, } from '../types' import type { Image } from '@commerce/types/common' +import { jsonApi } from '@spree/storefront-api-v2-sdk' const placeholderImage = requireConfigValue('lineItemPlaceholderImageUrl') as | string @@ -36,25 +32,24 @@ const normalizeVariant = ( spreeSuccessResponse: SpreeSdkResponse, spreeVariant: VariantAttr ): ProductVariant => { - const productIdentifier = spreeVariant.relationships.product - .data as RelationType - const spreeProduct = findIncluded( + const spreeProduct = jsonApi.findSingleRelationshipDocument( spreeSuccessResponse, - productIdentifier.type, - productIdentifier.id + spreeVariant, + 'product' ) if (spreeProduct === null) { throw new MissingLineItemVariantError( - `Couldn't find product with id ${productIdentifier.id}.` + `Couldn't find product for variant with id ${spreeVariant.id}.` ) } - const spreeVariantImageRecords = findIncludedOfType( - spreeSuccessResponse, - spreeVariant, - 'images' - ) + const spreeVariantImageRecords = + jsonApi.findRelationshipDocuments( + spreeSuccessResponse, + spreeVariant, + 'images' + ) let lineItemImage @@ -66,11 +61,12 @@ const normalizeVariant = ( if (variantImage) { lineItemImage = variantImage } else { - const spreeProductImageRecords = findIncludedOfType( - spreeSuccessResponse, - spreeProduct, - 'images' - ) + const spreeProductImageRecords = + jsonApi.findRelationshipDocuments( + spreeSuccessResponse, + spreeProduct, + 'images' + ) const productImage = getMediaGallery( spreeProductImageRecords, @@ -110,36 +106,33 @@ const normalizeLineItem = ( spreeSuccessResponse: SpreeSdkResponse, spreeLineItem: LineItemAttr ): LineItem => { - const variantIdentifier = spreeLineItem.relationships.variant - .data as RelationType - const variant = findIncluded( + const variant = jsonApi.findSingleRelationshipDocument( spreeSuccessResponse, - variantIdentifier.type, - variantIdentifier.id + spreeLineItem, + 'variant' ) if (variant === null) { throw new MissingLineItemVariantError( - `Couldn't find variant with id ${variantIdentifier.id}.` + `Couldn't find variant for line item with id ${spreeLineItem.id}.` ) } - const productIdentifier = variant.relationships.product.data as RelationType - const product = findIncluded( + const product = jsonApi.findSingleRelationshipDocument( spreeSuccessResponse, - productIdentifier.type, - productIdentifier.id + variant, + 'product' ) if (product === null) { throw new MissingLineItemVariantError( - `Couldn't find product with id ${productIdentifier.id}.` + `Couldn't find product for variant with id ${variant.id}.` ) } const path = `/${product.attributes.slug}` - const spreeOptionValues = findIncludedOfType( + const spreeOptionValues = jsonApi.findRelationshipDocuments( spreeSuccessResponse, variant, 'option_values' @@ -147,18 +140,16 @@ const normalizeLineItem = ( const options: SelectedOption[] = spreeOptionValues.map( (spreeOptionValue) => { - const spreeOptionTypeIdentifier = spreeOptionValue.relationships - .option_type.data as RelationType - - const spreeOptionType = findIncluded( - spreeSuccessResponse, - spreeOptionTypeIdentifier.type, - spreeOptionTypeIdentifier.id - ) + const spreeOptionType = + jsonApi.findSingleRelationshipDocument( + spreeSuccessResponse, + spreeOptionValue, + 'option_type' + ) if (spreeOptionType === null) { throw new MissingLineItemVariantError( - `Couldn't find option type with id ${spreeOptionTypeIdentifier.id}.` + `Couldn't find option type of option value with id ${spreeOptionValue.id}.` ) } @@ -177,7 +168,7 @@ const normalizeLineItem = ( return { id: spreeLineItem.id, variantId: variant.id, - productId: productIdentifier.id, + productId: product.id, name: spreeLineItem.attributes.name, quantity: spreeLineItem.attributes.quantity, discounts: [], // TODO: Implement when the template starts displaying them. @@ -191,11 +182,13 @@ const normalizeCart = ( spreeSuccessResponse: SpreeSdkResponse, spreeCart: OrderAttr ): Cart => { - const lineItems = findIncludedOfType( - spreeSuccessResponse, - spreeCart, - 'line_items' - ).map((lineItem) => normalizeLineItem(spreeSuccessResponse, lineItem)) + const lineItems = jsonApi + .findRelationshipDocuments( + spreeSuccessResponse, + spreeCart, + 'line_items' + ) + .map((lineItem) => normalizeLineItem(spreeSuccessResponse, lineItem)) return { id: spreeCart.id, diff --git a/framework/spree/utils/normalize-product.ts b/framework/spree/utils/normalize-product.ts index 5fa466c51..6ef53f8a5 100644 --- a/framework/spree/utils/normalize-product.ts +++ b/framework/spree/utils/normalize-product.ts @@ -5,20 +5,16 @@ import type { ProductPrice, ProductVariant, } from '@commerce/types/product' -import type { - JsonApiListResponse, - 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' import { requireConfigValue } from '../isomorphic-config' import createGetAbsoluteImageUrl from './create-get-absolute-image-url' import expandOptions from './expand-options' import getMediaGallery from './get-media-gallery' -import { findIncluded, findIncludedOfType } from './find-json-api-documents' import getProductPath from './get-product-path' import MissingPrimaryVariantError from '../errors/MissingPrimaryVariantError' -import type { SpreeSdkResponse } from '@framework/types' +import type { SpreeSdkResponse, VariantAttr } from '@framework/types' +import { jsonApi } from '@spree/storefront-api-v2-sdk' const placeholderImage = requireConfigValue('productPlaceholderImageUrl') as | string @@ -28,23 +24,21 @@ const normalizeProduct = ( spreeSuccessResponse: SpreeSdkResponse, spreeProduct: ProductAttr ): Product => { - const primaryVariantIdentifier = spreeProduct.relationships.primary_variant - .data as RelationType - const primaryVariant = findIncluded( + const primaryVariant = jsonApi.findSingleRelationshipDocument( spreeSuccessResponse, - primaryVariantIdentifier.type, - primaryVariantIdentifier.id + spreeProduct, + 'primary_variant' ) if (primaryVariant === null) { throw new MissingPrimaryVariantError( - `Couldn't find primary variant with id ${primaryVariantIdentifier.id}.` + `Couldn't find primary variant for product with id ${spreeProduct.id}.` ) } const sku = primaryVariant.attributes.sku - const spreeImageRecords = findIncludedOfType( + const spreeImageRecords = jsonApi.findRelationshipDocuments( spreeSuccessResponse, spreeProduct, 'images' @@ -77,7 +71,7 @@ const normalizeProduct = ( let variants: ProductVariant[] let options: ProductOption[] = [] - const spreeVariantRecords = findIncludedOfType( + const spreeVariantRecords = jsonApi.findRelationshipDocuments( spreeSuccessResponse, spreeProduct, 'variants' @@ -87,7 +81,7 @@ const normalizeProduct = ( let variantOptions: ProductOption[] = [] if (showOptions) { - const spreeOptionValues = findIncludedOfType( + const spreeOptionValues = jsonApi.findRelationshipDocuments( spreeSuccessResponse, spreeVariantRecord, 'option_values' diff --git a/package.json b/package.json index 2a6a05388..466371f53 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "@react-spring/web": "^9.2.1", - "@spree/storefront-api-v2-sdk": "^4.7.1", + "@spree/storefront-api-v2-sdk": "^4.9.0", "@types/qs": "^6.9.7", "@vercel/fetch": "^6.1.0", "autoprefixer": "^10.2.6", diff --git a/yarn.lock b/yarn.lock index a647414d7..ee6808957 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1066,12 +1066,12 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== -"@spree/storefront-api-v2-sdk@^4.7.1": - version "4.7.1" - resolved "https://registry.yarnpkg.com/@spree/storefront-api-v2-sdk/-/storefront-api-v2-sdk-4.7.1.tgz#af83c0d0de9ed9d3dade89ef96b251161c789b64" - integrity sha512-Z4vt1UwTf7rYfo6UIpfnsidyOsiw043FTwLfyVHDqFnXKXaTG4E6uV75gKrM7+d5SScTWj5qlq6YRAfwL/WacA== +"@spree/storefront-api-v2-sdk@^4.9.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@spree/storefront-api-v2-sdk/-/storefront-api-v2-sdk-4.9.0.tgz#57aa40b5b880e039c6810c4be17043b6b6ec2a2a" + integrity sha512-2PrwXx9VKnrB3G6lNbLJlHvwuQn52IxShys3wN413dHQ742w8uOh5yPWvnG/EifJTZs2ejB41Yb0XhqmPHAeXA== dependencies: - axios "^0.21.1" + axios "^0.21.4" lodash "^4.17.21" qs "^6.10.1" optionalDependencies: @@ -1636,12 +1636,12 @@ axe-core@^4.0.2: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.2.tgz#fcf8777b82c62cfc69c7e9f32c0d2226287680e7" integrity sha512-5LMaDRWm8ZFPAEdzTYmgjjEdj1YnQcpfrVajO/sn/LhbpGp0Y0H64c2hLZI1gRMxfA+w1S71Uc/nHaOXgcCvGg== -axios@^0.21.1: - version "0.21.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" - integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== +axios@^0.21.4: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== dependencies: - follow-redirects "^1.10.0" + follow-redirects "^1.14.0" axobject-query@^2.2.0: version "2.2.0" @@ -3197,10 +3197,10 @@ flatten@^1.0.2: resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== -follow-redirects@^1.10.0: - version "1.14.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.2.tgz#cecb825047c00f5e66b142f90fed4f515dec789b" - integrity sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA== +follow-redirects@^1.14.0: + version "1.14.3" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.3.tgz#6ada78118d8d24caee595595accdc0ac6abd022e" + integrity sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw== foreach@^2.0.5: version "2.0.5"