From 3afc174b1581dc8646cbabab269d84b4aa18c82e Mon Sep 17 00:00:00 2001 From: Dom Sip Date: Tue, 19 Apr 2022 18:50:09 +0100 Subject: [PATCH] prettier --- .../catalog/products/get-products.ts | 30 ++-- packages/sfcc/src/api/index.ts | 8 +- .../api/operations/get-all-product-paths.ts | 19 +- .../src/api/operations/get-all-products.ts | 17 +- .../sfcc/src/api/operations/get-product.ts | 12 +- packages/sfcc/src/api/utils/get-auth-token.ts | 29 ++-- .../sfcc/src/api/utils/normalise-product.ts | 164 ++++++++++-------- packages/sfcc/src/api/utils/sfcc-sdk.ts | 18 +- 8 files changed, 153 insertions(+), 144 deletions(-) diff --git a/packages/sfcc/src/api/endpoints/catalog/products/get-products.ts b/packages/sfcc/src/api/endpoints/catalog/products/get-products.ts index 8100c6f58..3b676e5ef 100644 --- a/packages/sfcc/src/api/endpoints/catalog/products/get-products.ts +++ b/packages/sfcc/src/api/endpoints/catalog/products/get-products.ts @@ -1,33 +1,31 @@ -import { normalizeSearchProducts } from '../../../utils/normalise-product'; +import { normalizeSearchProducts } from '../../../utils/normalise-product' import { ProductsEndpoint } from '.' - const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({ req, res, body: { search, categoryId, brandId, sort }, - config + config, }) => { - const { sdk } = config; + const { sdk } = config // 'clothing' is our main category default, and a manually set category has priority - const searchTerm = categoryId ? categoryId as string : search || 'clothing'; + const searchTerm = categoryId ? (categoryId as string) : search || 'clothing' - const searchClient = await sdk.getSearchClient(); + const searchClient = await sdk.getSearchClient() // use SDK search API for initial products const searchResults = await searchClient.productSearch({ - parameters: { - q: searchTerm, - limit: 20 - } - }); - let products = []; - let found = false; + parameters: { + q: searchTerm, + limit: 20, + }, + }) + let products = [] + let found = false if (searchResults.total) { - found = true; - products = normalizeSearchProducts(searchResults.hits) as any[]; + found = true + products = normalizeSearchProducts(searchResults.hits) as any[] } - res.status(200).json({ data: { products, found } }) } diff --git a/packages/sfcc/src/api/index.ts b/packages/sfcc/src/api/index.ts index d26bcca19..50c6f468c 100644 --- a/packages/sfcc/src/api/index.ts +++ b/packages/sfcc/src/api/index.ts @@ -11,7 +11,6 @@ import getAllProductPaths from './operations/get-all-product-paths' import getAllProducts from './operations/get-all-products' import getProduct from './operations/get-product' - export interface SFCCConfig extends CommerceAPIConfig { sdk: Sdk } @@ -22,8 +21,7 @@ const config: SFCCConfig = { customerCookie: '', cartCookieMaxAge: 2592000, fetch: createFetcher(() => getCommerceApi().getConfig()), - sdk // SalesForce Cloud Commerce API SDK - + sdk, // SalesForce Cloud Commerce API SDK } const operations = { @@ -39,7 +37,9 @@ const operations = { export const provider = { config, operations } export type Provider = typeof provider -export type SFCCProviderAPI

= CommerceAPI

+export type SFCCProviderAPI

= CommerceAPI< + P | any +> export function getCommerceApi

( customProvider: P = provider as any diff --git a/packages/sfcc/src/api/operations/get-all-product-paths.ts b/packages/sfcc/src/api/operations/get-all-product-paths.ts index 88d5f5135..6a9ec7a0b 100644 --- a/packages/sfcc/src/api/operations/get-all-product-paths.ts +++ b/packages/sfcc/src/api/operations/get-all-product-paths.ts @@ -1,13 +1,15 @@ import { Product } from '@vercel/commerce/types/product' import { OperationContext } from '@vercel/commerce/api/operations' -import { normalizeSearchProducts } from '../utils/normalise-product'; +import { normalizeSearchProducts } from '../utils/normalise-product' import { SFCCConfig } from '..' export type GetAllProductPathsResult = { products: Array<{ path: string }> } -export default function getAllProductPathsOperation({ commerce }: OperationContext) { +export default function getAllProductPathsOperation({ + commerce, +}: OperationContext) { async function getAllProductPaths({ query, config, @@ -17,23 +19,22 @@ export default function getAllProductPathsOperation({ commerce }: OperationConte config?: SFCCConfig variables?: any } = {}): Promise { - // TODO: support locale const { sdk, locale } = commerce.getConfig(config) as SFCCConfig const searchClient = await sdk.getSearchClient() - + // use SDK search API for initial products same as getAllProductsOperation const searchResults = await searchClient.productSearch({ - parameters: { q: "dress", limit: variables?.first }, - }); - - let products = [] as Product[]; + parameters: { q: 'dress', limit: variables?.first }, + }) + + let products = [] as Product[] if (searchResults.total) { products = normalizeSearchProducts(searchResults.hits) } else { // TODO: handle this better? - console.log("No results for search"); + console.log('No results for search') } return { diff --git a/packages/sfcc/src/api/operations/get-all-products.ts b/packages/sfcc/src/api/operations/get-all-products.ts index e909a9c22..69b4538c4 100644 --- a/packages/sfcc/src/api/operations/get-all-products.ts +++ b/packages/sfcc/src/api/operations/get-all-products.ts @@ -2,7 +2,7 @@ import { Product } from '@vercel/commerce/types/product' import { GetAllProductsOperation } from '@vercel/commerce/types/product' import type { OperationContext } from '@vercel/commerce/api/operations' import type { SFCCConfig } from '../index' -import { normalizeSearchProducts } from '../utils/normalise-product'; +import { normalizeSearchProducts } from '../utils/normalise-product' export default function getAllProductsOperation({ commerce, @@ -17,26 +17,25 @@ export default function getAllProductsOperation({ config?: Partial preview?: boolean } = {}): Promise<{ products: Product[] | any[] }> { - // TODO: support locale const { sdk, locale } = commerce.getConfig(config) as SFCCConfig const searchClient = await sdk.getSearchClient() - + // use SDK search API for initial products const searchResults = await searchClient.productSearch({ - parameters: { q: "dress", limit: variables?.first }, - }); - - let products = [] as Product[]; + parameters: { q: 'dress', limit: variables?.first }, + }) + + let products = [] as Product[] if (searchResults.total) { products = normalizeSearchProducts(searchResults.hits) } else { // TODO: handle this better? - console.log("No results for search"); + console.log('No results for search') } return { - products: products + products: products, } } return getAllProducts diff --git a/packages/sfcc/src/api/operations/get-product.ts b/packages/sfcc/src/api/operations/get-product.ts index 4d7cfda0b..72449c56b 100644 --- a/packages/sfcc/src/api/operations/get-product.ts +++ b/packages/sfcc/src/api/operations/get-product.ts @@ -1,8 +1,7 @@ - import { GetProductOperation, Product } from '@vercel/commerce/types/product' import type { SFCCConfig } from '../index' import type { OperationContext } from '@vercel/commerce/api/operations' -import { normalizeProduct } from '../utils/normalise-product'; +import { normalizeProduct } from '../utils/normalise-product' export default function getProductOperation({ commerce, @@ -16,14 +15,15 @@ export default function getProductOperation({ variables?: T['variables'] config?: Partial preview?: boolean - } = {}): Promise { - + } = {}): Promise { // TODO: support locale const { sdk, locale } = commerce.getConfig(config) as SFCCConfig const shopperProductsClient = await sdk.getshopperProductsClient() - const product = await shopperProductsClient.getProduct({parameters: {id: variables?.slug as string}}); + const product = await shopperProductsClient.getProduct({ + parameters: { id: variables?.slug as string }, + }) const normalizedProduct = normalizeProduct(product) - + return { product: normalizedProduct, } diff --git a/packages/sfcc/src/api/utils/get-auth-token.ts b/packages/sfcc/src/api/utils/get-auth-token.ts index d9adadf44..373d6c6cd 100644 --- a/packages/sfcc/src/api/utils/get-auth-token.ts +++ b/packages/sfcc/src/api/utils/get-auth-token.ts @@ -1,9 +1,9 @@ -import { ClientConfig, Customer } from "commerce-sdk"; +import { ClientConfig, Customer } from 'commerce-sdk' // client configuration parameters export const clientConfig: ClientConfig = { headers: { - authorization: `` + authorization: ``, }, parameters: { clientId: process.env.SFCC_CLIENT_ID || '', @@ -11,7 +11,7 @@ export const clientConfig: ClientConfig = { shortCode: process.env.SFCC_SHORT_CODE || '', siteId: process.env.SFCC_SITE_ID || '', }, -}; +} /** * Get the shopper or guest JWT/access token, along with a refresh token, using client credentials @@ -19,25 +19,24 @@ export const clientConfig: ClientConfig = { * @returns guest user authorization token */ export async function getGuestUserAuthToken(): Promise { - const credentials = `${process.env.SFCC_CLIENT_ID}:${process.env.SFCC_CLIENT_SECRET}`; - const base64data = Buffer.from(credentials).toString("base64"); - const headers = { Authorization: `Basic ${base64data}` }; - const client = new Customer.ShopperLogin(clientConfig); + const credentials = `${process.env.SFCC_CLIENT_ID}:${process.env.SFCC_CLIENT_SECRET}` + const base64data = Buffer.from(credentials).toString('base64') + const headers = { Authorization: `Basic ${base64data}` } + const client = new Customer.ShopperLogin(clientConfig) return await client.getAccessToken({ headers, body: { - grant_type: "client_credentials", + grant_type: 'client_credentials', }, - }); + }) } export const getConfigAuth = async () => { - const shopperToken = await getGuestUserAuthToken(); + const shopperToken = await getGuestUserAuthToken() const configAuth = { - ...clientConfig, - headers: {"authorization":`Bearer ${shopperToken.access_token}`} - }; - return configAuth; + ...clientConfig, + headers: { authorization: `Bearer ${shopperToken.access_token}` }, + } + return configAuth } - diff --git a/packages/sfcc/src/api/utils/normalise-product.ts b/packages/sfcc/src/api/utils/normalise-product.ts index ad27f8e36..b8d0e2ed4 100644 --- a/packages/sfcc/src/api/utils/normalise-product.ts +++ b/packages/sfcc/src/api/utils/normalise-product.ts @@ -1,84 +1,96 @@ -import { Product as SFCCProduct, Search } from "commerce-sdk"; -import type { Product, ProductImage, ProductOption, ProductVariant } from '@vercel/commerce/types/product' +import { Product as SFCCProduct, Search } from 'commerce-sdk' +import type { + Product, + ProductImage, + ProductOption, + ProductVariant, +} from '@vercel/commerce/types/product' -const normaliseOptions = (options: SFCCProduct.ShopperProducts.Product["variationAttributes"]): Product["options"] => { - if (!Array.isArray(options)) return [] +const normaliseOptions = ( + options: SFCCProduct.ShopperProducts.Product['variationAttributes'] +): Product['options'] => { + if (!Array.isArray(options)) return [] - return options.map(option => { - return { - id: option.id, - displayName: option.name as string, - values: option.values!.map(value => ({label: value.name})) - } as ProductOption - }); -} - -const normaliseVariants = (variants: SFCCProduct.ShopperProducts.Product["variants"]): Product["variants"] => { - if (!Array.isArray(variants)) return [] - - return variants.map(variant => { - - const options = [] as ProductOption[]; - - if (variant.variationValues) { - for (const [key, value] of Object.entries(variant.variationValues)) { - const variantOptionObject = { - id: `${variant.productId}-${key}`, - displayName: key, - values: [{ - label: value, - }] - } - options.push(variantOptionObject); - } - } - - return { - id: variant.productId, - options - } as ProductVariant; - }); -} - -export function normalizeProduct(product: SFCCProduct.ShopperProducts.Product): Product { + return options.map((option) => { return { - id: product.id, - // TODO: use `name-ID` as a virtual slug (for search 1:1) - slug: product.id, // use product ID as a slug - name: product.name!, - description: product.longDescription!, - price: { - value: product.price!, - currencyCode: product.currency - }, - images: product.imageGroups![0].images.map(image => ({ - url: image.disBaseLink, - altText: image.title - })) as ProductImage[], - variants: normaliseVariants(product.variants), - options: normaliseOptions(product.variationAttributes), - }; + id: option.id, + displayName: option.name as string, + values: option.values!.map((value) => ({ label: value.name })), + } as ProductOption + }) } -export function normalizeSearchProducts(products: Search.ShopperSearch.ProductSearchHit[]): Product[] { +const normaliseVariants = ( + variants: SFCCProduct.ShopperProducts.Product['variants'] +): Product['variants'] => { + if (!Array.isArray(variants)) return [] - return products.map(product => ({ - id: product.productId, - slug: product.productId, // use product ID as a slug - name: product.productName!, - description: '', - price: { - value: product.price!, - currencyCode: product.currency - }, - images: [ + return variants.map((variant) => { + const options = [] as ProductOption[] + + if (variant.variationValues) { + for (const [key, value] of Object.entries(variant.variationValues)) { + const variantOptionObject = { + id: `${variant.productId}-${key}`, + displayName: key, + values: [ { - url: product.image!.link, - altText: product.productName - } as ProductImage - ], - variants: normaliseVariants(product.variants), - options: normaliseOptions(product.variationAttributes), - })); + label: value, + }, + ], + } + options.push(variantOptionObject) + } + } -} \ No newline at end of file + return { + id: variant.productId, + options, + } as ProductVariant + }) +} + +export function normalizeProduct( + product: SFCCProduct.ShopperProducts.Product +): Product { + return { + id: product.id, + // TODO: use `name-ID` as a virtual slug (for search 1:1) + slug: product.id, // use product ID as a slug + name: product.name!, + description: product.longDescription!, + price: { + value: product.price!, + currencyCode: product.currency, + }, + images: product.imageGroups![0].images.map((image) => ({ + url: image.disBaseLink, + altText: image.title, + })) as ProductImage[], + variants: normaliseVariants(product.variants), + options: normaliseOptions(product.variationAttributes), + } +} + +export function normalizeSearchProducts( + products: Search.ShopperSearch.ProductSearchHit[] +): Product[] { + return products.map((product) => ({ + id: product.productId, + slug: product.productId, // use product ID as a slug + name: product.productName!, + description: '', + price: { + value: product.price!, + currencyCode: product.currency, + }, + images: [ + { + url: product.image!.link, + altText: product.productName, + } as ProductImage, + ], + variants: normaliseVariants(product.variants), + options: normaliseOptions(product.variationAttributes), + })) +} diff --git a/packages/sfcc/src/api/utils/sfcc-sdk.ts b/packages/sfcc/src/api/utils/sfcc-sdk.ts index 7f2e5cb6a..8d20b677e 100644 --- a/packages/sfcc/src/api/utils/sfcc-sdk.ts +++ b/packages/sfcc/src/api/utils/sfcc-sdk.ts @@ -1,19 +1,19 @@ -import { Product, Search } from "commerce-sdk"; -import { getConfigAuth } from "./get-auth-token"; +import { Product, Search } from 'commerce-sdk' +import { getConfigAuth } from './get-auth-token' const getSearchClient = async () => { - const configAuth = await getConfigAuth(); - return new Search.ShopperSearch(configAuth); + const configAuth = await getConfigAuth() + return new Search.ShopperSearch(configAuth) } const getshopperProductsClient = async () => { - const configAuth = await getConfigAuth(); - return new Product.ShopperProducts(configAuth) + const configAuth = await getConfigAuth() + return new Product.ShopperProducts(configAuth) } export const sdk = { - getshopperProductsClient, - getSearchClient + getshopperProductsClient, + getSearchClient, } export type Sdk = typeof sdk -export default sdk \ No newline at end of file +export default sdk