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