Skip to content

Commit

Permalink
fix: receiving and returning StorePropertyValue now works correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
icazevedo committed May 18, 2022
1 parent 495675a commit fb39540
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 58 deletions.
26 changes: 9 additions & 17 deletions packages/api/src/__generated__/schema.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export interface OrderFormItem {
sellingPrices: SellingPrice[]
total: number
}
attachments: Attachment[]
}

export interface SKUSpecification {
Expand Down
2 changes: 2 additions & 0 deletions packages/api/src/platforms/vtex/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -67,6 +68,7 @@ const Resolvers = {
StoreReview,
StoreProductGroup,
StoreSearchResult,
ObjectOrString,
Query,
Mutation,
}
Expand Down
46 changes: 46 additions & 0 deletions packages/api/src/platforms/vtex/resolvers/objectOrString.ts
Original file line number Diff line number Diff line change
@@ -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<any>) {
if (typeof value === 'string') {
try {
return JSON.parse(value)
} catch (e) {
return value
}
}

return null
}

function stringify(value: GraphQLScalarSerializer<any>) {
if (typeof value === 'object') {
return JSON.stringify(value)
}

if (typeof value === 'string') {
return value
}

return null
}
12 changes: 11 additions & 1 deletion packages/api/src/platforms/vtex/resolvers/offer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,17 @@ export const StoreOffer: Record<string, Resolver<Root>> = {

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
Expand Down
33 changes: 9 additions & 24 deletions packages/api/src/platforms/vtex/resolvers/product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ import type { Attachment } from '../clients/commerce/types/OrderForm'

type QueryProduct = PromiseType<ReturnType<typeof Query.product>>

type Root = Omit<QueryProduct, 'attachments'> & {
attachments: AttachmentDefinition[] | Attachment[]
type Root = QueryProduct & {
attachmentsValues?: Attachment[]
}

type AttachmentDefinition = QueryProduct['attachments'][number]

const DEFAULT_IMAGE = {
imageText: 'image',
imageUrl:
Expand All @@ -26,10 +24,6 @@ const getPath = (link: string, id: string) => `/${getSlug(link, id)}/p`
const nonEmptyArray = <T>(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<string, Resolver<Root>> & {
offers: Resolver<
Root,
Expand Down Expand Up @@ -94,7 +88,7 @@ export const StoreProduct: Record<string, Resolver<Root>> & {
)
.sort(bestOfferFirst),
isVariantOf: (root) => root,
additionalProperty: ({ variations = [], attachments }) => {
additionalProperty: ({ variations = [], attachmentsValues }) => {
const propertyValueVariations = variations.flatMap(({ name, values }) =>
values.map((value) => ({
name,
Expand All @@ -103,22 +97,13 @@ export const StoreProduct: Record<string, Resolver<Root>> & {
}))
)

// Typescript don't understand (A[] | B[]) as an array, only Array<A | B>
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]
},
Expand Down
2 changes: 2 additions & 0 deletions packages/api/src/typeDefs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -46,6 +47,7 @@ export const typeDefs = [
Status,
PropertyValue,
Person,
ObjectOrString,
]
.map(print)
.join('\n')
1 change: 1 addition & 0 deletions packages/api/src/typeDefs/objectOrString.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
scalar ObjectOrString
24 changes: 8 additions & 16 deletions packages/api/src/typeDefs/propertyValue.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -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!
}

0 comments on commit fb39540

Please sign in to comment.