From fb39540eae1fafb0f31f75bc0d62c7d17a1e2a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dcaro=20Azevedo?= Date: Wed, 18 May 2022 12:34:12 -0300 Subject: [PATCH] fix: receiving and returning StorePropertyValue now works correctly --- packages/api/src/__generated__/schema.ts | 26 ++++------- .../vtex/clients/commerce/types/OrderForm.ts | 1 + packages/api/src/platforms/vtex/index.ts | 2 + .../vtex/resolvers/objectOrString.ts | 46 +++++++++++++++++++ .../api/src/platforms/vtex/resolvers/offer.ts | 12 ++++- .../src/platforms/vtex/resolvers/product.ts | 33 ++++--------- packages/api/src/typeDefs/index.ts | 2 + .../api/src/typeDefs/objectOrString.graphql | 1 + .../api/src/typeDefs/propertyValue.graphql | 24 ++++------ 9 files changed, 89 insertions(+), 58 deletions(-) create mode 100644 packages/api/src/platforms/vtex/resolvers/objectOrString.ts create mode 100644 packages/api/src/typeDefs/objectOrString.graphql diff --git a/packages/api/src/__generated__/schema.ts b/packages/api/src/__generated__/schema.ts index 5fb18213ce..1e2a5c9160 100644 --- a/packages/api/src/__generated__/schema.ts +++ b/packages/api/src/__generated__/schema.ts @@ -9,7 +9,7 @@ export type Scalars = { Boolean: boolean; Int: number; Float: number; - Object: any; + ObjectOrString: any; }; /** Shopping cart identification input. */ @@ -69,10 +69,10 @@ export type IStoreProduct = { export type IStorePropertyValue = { /** Property name. */ name: Scalars['String']; - /** Property value. */ - value: Scalars['Object']; - /** Property value reference. */ - valueReference: ValueReference; + /** Property value. May hold a string or the string representation of an object. */ + value: Scalars['ObjectOrString']; + /** Specifies the nature of the value */ + valueReference: Scalars['String']; }; /** Selected facet input. */ @@ -335,8 +335,6 @@ export type StoreListItem = { /** Offer information. */ export type StoreOffer = { __typename?: 'StoreOffer'; - /** An additional offer that can only be obtained in combination with the first base offer (e.g. supplements and extensions that are available for a surcharge). */ - addOn: Array>; /** Offer item availability. */ availability: Scalars['String']; /** Offer item condition. */ @@ -474,10 +472,10 @@ export type StorePropertyValue = { __typename?: 'StorePropertyValue'; /** Property name. */ name: Scalars['String']; - /** Property value. */ - value: Scalars['String']; - /** Property value reference. */ - valueReference: ValueReference; + /** Property value. May hold a string or the string representation of an object. */ + value: Scalars['ObjectOrString']; + /** Specifies the nature of the value */ + valueReference: Scalars['String']; }; /** Information of a given review. */ @@ -560,9 +558,3 @@ export type StoreSuggestions = { /** Array with suggestion terms. */ terms?: Maybe>; }; - -export const enum ValueReference { - Attachment = 'ATTACHMENT', - Attribute = 'ATTRIBUTE', - Property = 'PROPERTY' -}; diff --git a/packages/api/src/platforms/vtex/clients/commerce/types/OrderForm.ts b/packages/api/src/platforms/vtex/clients/commerce/types/OrderForm.ts index f9ae2f4a67..9cd77e4ec3 100644 --- a/packages/api/src/platforms/vtex/clients/commerce/types/OrderForm.ts +++ b/packages/api/src/platforms/vtex/clients/commerce/types/OrderForm.ts @@ -54,6 +54,7 @@ export interface OrderFormItem { sellingPrices: SellingPrice[] total: number } + attachments: Attachment[] } export interface SKUSpecification { diff --git a/packages/api/src/platforms/vtex/index.ts b/packages/api/src/platforms/vtex/index.ts index 43c8dc2091..7143019e03 100644 --- a/packages/api/src/platforms/vtex/index.ts +++ b/packages/api/src/platforms/vtex/index.ts @@ -13,6 +13,7 @@ import { Query } from './resolvers/query' import { StoreReview } from './resolvers/review' import { StoreSearchResult } from './resolvers/searchResult' import { StoreSeo } from './resolvers/seo' +import { ObjectOrString } from './resolvers/objectOrString' import type { Loaders } from './loaders' import type { Clients } from './clients' import type { Channel } from './utils/channel' @@ -67,6 +68,7 @@ const Resolvers = { StoreReview, StoreProductGroup, StoreSearchResult, + ObjectOrString, Query, Mutation, } diff --git a/packages/api/src/platforms/vtex/resolvers/objectOrString.ts b/packages/api/src/platforms/vtex/resolvers/objectOrString.ts new file mode 100644 index 0000000000..b72dd85513 --- /dev/null +++ b/packages/api/src/platforms/vtex/resolvers/objectOrString.ts @@ -0,0 +1,46 @@ +import type { GraphQLScalarSerializer } from 'graphql' +import { GraphQLScalarType } from 'graphql' +import { Kind } from 'graphql/language' + +export const ObjectOrString = new GraphQLScalarType({ + name: 'ObjectOrString', + description: + 'A string or the string representation of an object (a stringified object).', + parseValue: toObjectOrString, + serialize: stringify, + parseLiteral(ast) { + if (ast.kind === Kind.STRING) { + try { + return JSON.parse(ast.value) + } catch (e) { + return ast.value + } + } + + return null + }, +}) + +function toObjectOrString(value: GraphQLScalarSerializer) { + if (typeof value === 'string') { + try { + return JSON.parse(value) + } catch (e) { + return value + } + } + + return null +} + +function stringify(value: GraphQLScalarSerializer) { + if (typeof value === 'object') { + return JSON.stringify(value) + } + + if (typeof value === 'string') { + return value + } + + return null +} diff --git a/packages/api/src/platforms/vtex/resolvers/offer.ts b/packages/api/src/platforms/vtex/resolvers/offer.ts index 6e34c580f9..4e5a8513b5 100644 --- a/packages/api/src/platforms/vtex/resolvers/offer.ts +++ b/packages/api/src/platforms/vtex/resolvers/offer.ts @@ -96,7 +96,17 @@ export const StoreOffer: Record> = { return null }, - itemOffered: ({ product }) => product, + itemOffered: async (root) => { + if (isSearchItem(root)) { + return root.product + } + + if (isOrderFormItem(root)) { + return { ...(await root.product), attachmentsValues: root.attachments } + } + + return null + }, quantity: (root) => { if (isSearchItem(root)) { return root.AvailableQuantity ?? 0 diff --git a/packages/api/src/platforms/vtex/resolvers/product.ts b/packages/api/src/platforms/vtex/resolvers/product.ts index a7cd830f33..98b5691b09 100644 --- a/packages/api/src/platforms/vtex/resolvers/product.ts +++ b/packages/api/src/platforms/vtex/resolvers/product.ts @@ -9,12 +9,10 @@ import type { Attachment } from '../clients/commerce/types/OrderForm' type QueryProduct = PromiseType> -type Root = Omit & { - attachments: AttachmentDefinition[] | Attachment[] +type Root = QueryProduct & { + attachmentsValues?: Attachment[] } -type AttachmentDefinition = QueryProduct['attachments'][number] - const DEFAULT_IMAGE = { imageText: 'image', imageUrl: @@ -26,10 +24,6 @@ const getPath = (link: string, id: string) => `/${getSlug(link, id)}/p` const nonEmptyArray = (array: T[] | null | undefined) => Array.isArray(array) && array.length > 0 ? array : null -const isAttachmentDefinition = ( - attachment: Root['attachments'][number] -): attachment is AttachmentDefinition => 'id' in attachment - export const StoreProduct: Record> & { offers: Resolver< Root, @@ -94,7 +88,7 @@ export const StoreProduct: Record> & { ) .sort(bestOfferFirst), isVariantOf: (root) => root, - additionalProperty: ({ variations = [], attachments }) => { + additionalProperty: ({ variations = [], attachmentsValues }) => { const propertyValueVariations = variations.flatMap(({ name, values }) => values.map((value) => ({ name, @@ -103,22 +97,13 @@ export const StoreProduct: Record> & { })) ) - // Typescript don't understand (A[] | B[]) as an array, only Array - const propertyValueAttachments = (attachments as Array< - Root['attachments'][number] - >) - .map((attachment: Root['attachments'][number]) => { - if (isAttachmentDefinition(attachment)) { - return - } - - return { - name: attachment.name, - value: attachment.content, - valueReference: VALUE_REFERENCES.attachment, - } + const propertyValueAttachments = (attachmentsValues ?? []).map( + (attachment) => ({ + name: attachment.name, + value: attachment.content, + valueReference: VALUE_REFERENCES.attachment, }) - .filter(Boolean) + ) return [...propertyValueVariations, ...propertyValueAttachments] }, diff --git a/packages/api/src/typeDefs/index.ts b/packages/api/src/typeDefs/index.ts index 57a1c75e77..fe39270c43 100644 --- a/packages/api/src/typeDefs/index.ts +++ b/packages/api/src/typeDefs/index.ts @@ -22,6 +22,7 @@ import Cart from './cart.graphql' import Status from './status.graphql' import PropertyValue from './propertyValue.graphql' import Person from './person.graphql' +import ObjectOrString from './objectOrString.graphql' export const typeDefs = [ Query, @@ -46,6 +47,7 @@ export const typeDefs = [ Status, PropertyValue, Person, + ObjectOrString, ] .map(print) .join('\n') diff --git a/packages/api/src/typeDefs/objectOrString.graphql b/packages/api/src/typeDefs/objectOrString.graphql new file mode 100644 index 0000000000..fd8a401db7 --- /dev/null +++ b/packages/api/src/typeDefs/objectOrString.graphql @@ -0,0 +1 @@ +scalar ObjectOrString \ No newline at end of file diff --git a/packages/api/src/typeDefs/propertyValue.graphql b/packages/api/src/typeDefs/propertyValue.graphql index 13b1b0419e..665c166eb1 100644 --- a/packages/api/src/typeDefs/propertyValue.graphql +++ b/packages/api/src/typeDefs/propertyValue.graphql @@ -3,38 +3,30 @@ Properties that can be associated with products and products groups. """ type StorePropertyValue { """ - Property value. + Property value. May hold a string or the string representation of an object. """ - value: String! + value: ObjectOrString! """ Property name. """ name: String! """ - Property value reference. + Specifies the nature of the value """ - valueReference: ValueReference! + valueReference: String! } -enum ValueReference { - ATTRIBUTE - ATTACHMENT - PROPERTY -} - -scalar Object - input IStorePropertyValue { """ - Property value. + Property value. May hold a string or the string representation of an object. """ - value: Object! + value: ObjectOrString! """ Property name. """ name: String! """ - Property value reference. + Specifies the nature of the value """ - valueReference: ValueReference! + valueReference: String! }