4
0
forked from crowetic/commerce
2021-04-15 12:35:31 -03:00

166 lines
4.1 KiB
TypeScript

import { Product } from '@commerce/types'
import {
Product as ShopifyProduct,
Checkout,
CheckoutLineItemEdge,
SelectedOption,
ImageConnection,
ProductVariantConnection,
MoneyV2,
ProductOption,
} from '../schema'
import type { Cart, LineItem } from '../types'
const money = ({ amount, currencyCode }: MoneyV2) => {
return {
value: +amount,
currencyCode,
}
}
const normalizeProductOption = ({
id,
name: displayName,
values,
}: ProductOption) => {
return {
__typename: 'MultipleChoiceOption',
id,
displayName,
values: values.map((value) => {
let output: any = {
label: value,
}
if (displayName.match(/colou?r/gi)) {
output = {
...output,
hexColors: [value],
}
}
return output
}),
}
}
const normalizeProductImages = ({ edges }: ImageConnection) =>
edges?.map(({ node: { originalSrc: url, ...rest } }) => ({
url,
...rest,
}))
const normalizeProductVariants = ({ edges }: ProductVariantConnection) => {
return edges?.map(
({
node: { id, selectedOptions, sku, title, priceV2, compareAtPriceV2 },
}) => {
return {
id,
name: title,
sku: sku ?? id,
price: +priceV2.amount,
listPrice: +compareAtPriceV2?.amount,
requiresShipping: true,
options: selectedOptions.map(({ name, value }: SelectedOption) => {
const options = normalizeProductOption({
id,
name,
values: [value],
})
return options
}),
}
}
)
}
export function normalizeProduct(productNode: ShopifyProduct): Product {
const {
id,
title: name,
vendor,
images,
variants,
description,
descriptionHtml,
handle,
priceRange,
options,
...rest
} = productNode
const product = {
id,
name,
vendor,
path: `/${handle}`,
slug: handle?.replace(/^\/+|\/+$/g, ''),
price: money(priceRange?.minVariantPrice),
images: normalizeProductImages(images),
variants: variants ? normalizeProductVariants(variants) : [],
options: options
? options
.filter((o) => o.name !== 'Title') // By default Shopify adds a 'Title' name when there's only one option. We don't need it. https://community.shopify.com/c/Shopify-APIs-SDKs/Adding-new-product-variant-is-automatically-adding-quot-Default/td-p/358095
.map((o) => normalizeProductOption(o))
: [],
...(description && { description }),
...(descriptionHtml && { descriptionHtml }),
...rest,
}
return product
}
export function normalizeCart(checkout: Checkout): Cart {
return {
id: checkout.id,
customerId: '',
email: '',
createdAt: checkout.createdAt,
currency: {
code: checkout.totalPriceV2?.currencyCode,
},
taxesIncluded: checkout.taxesIncluded,
lineItems: checkout.lineItems?.edges.map(normalizeLineItem),
lineItemsSubtotalPrice: +checkout.subtotalPriceV2?.amount,
subtotalPrice: +checkout.subtotalPriceV2?.amount,
totalPrice: checkout.totalPriceV2?.amount,
discounts: [],
}
}
function normalizeLineItem({
node: { id, title, variant, quantity, ...rest },
}: CheckoutLineItemEdge): LineItem {
return {
id,
variantId: String(variant?.id),
productId: String(variant?.id),
name: `${title}`,
quantity,
variant: {
id: String(variant?.id),
sku: variant?.sku ?? '',
name: variant?.title!,
image: {
url: variant?.image?.originalSrc ?? '/product-img-placeholder.svg',
},
requiresShipping: variant?.requiresShipping ?? false,
price: variant?.priceV2?.amount,
listPrice: variant?.compareAtPriceV2?.amount,
},
path: String(variant?.product?.handle),
discounts: [],
options:
// By default Shopify adds a default variant with default names, we're removing it. https://community.shopify.com/c/Shopify-APIs-SDKs/Adding-new-product-variant-is-automatically-adding-quot-Default/td-p/358095
variant?.title == 'Default Title'
? []
: [
{
value: variant?.title,
},
],
}
}