mirror of
https://github.com/vercel/commerce.git
synced 2025-05-18 07:26:59 +00:00
prettier
This commit is contained in:
parent
02b477bdea
commit
3afc174b15
@ -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;
|
||||
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 } })
|
||||
}
|
||||
|
||||
|
@ -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<P extends Provider = Provider> = CommerceAPI<P | any>
|
||||
export type SFCCProviderAPI<P extends Provider = Provider> = CommerceAPI<
|
||||
P | any
|
||||
>
|
||||
|
||||
export function getCommerceApi<P extends Provider>(
|
||||
customProvider: P = provider as any
|
||||
|
@ -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<any>) {
|
||||
export default function getAllProductPathsOperation({
|
||||
commerce,
|
||||
}: OperationContext<any>) {
|
||||
async function getAllProductPaths({
|
||||
query,
|
||||
config,
|
||||
@ -17,23 +19,22 @@ export default function getAllProductPathsOperation({ commerce }: OperationConte
|
||||
config?: SFCCConfig
|
||||
variables?: any
|
||||
} = {}): Promise<GetAllProductPathsResult> {
|
||||
|
||||
// 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 },
|
||||
});
|
||||
parameters: { q: 'dress', limit: variables?.first },
|
||||
})
|
||||
|
||||
let products = [] as Product[];
|
||||
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 {
|
||||
|
@ -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<SFCCConfig>
|
||||
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 },
|
||||
});
|
||||
parameters: { q: 'dress', limit: variables?.first },
|
||||
})
|
||||
|
||||
let products = [] as Product[];
|
||||
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
|
||||
|
@ -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,
|
||||
@ -17,11 +16,12 @@ export default function getProductOperation({
|
||||
config?: Partial<SFCCConfig>
|
||||
preview?: boolean
|
||||
} = {}): Promise<Product | {} | any> {
|
||||
|
||||
// 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 {
|
||||
|
@ -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<Customer.ShopperLogin.TokenResponse> {
|
||||
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;
|
||||
headers: { authorization: `Bearer ${shopperToken.access_token}` },
|
||||
}
|
||||
return configAuth
|
||||
}
|
||||
|
||||
|
@ -1,46 +1,58 @@
|
||||
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"] => {
|
||||
const normaliseOptions = (
|
||||
options: SFCCProduct.ShopperProducts.Product['variationAttributes']
|
||||
): Product['options'] => {
|
||||
if (!Array.isArray(options)) return []
|
||||
|
||||
return options.map(option => {
|
||||
return options.map((option) => {
|
||||
return {
|
||||
id: option.id,
|
||||
displayName: option.name as string,
|
||||
values: option.values!.map(value => ({label: value.name}))
|
||||
values: option.values!.map((value) => ({ label: value.name })),
|
||||
} as ProductOption
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
const normaliseVariants = (variants: SFCCProduct.ShopperProducts.Product["variants"]): Product["variants"] => {
|
||||
const normaliseVariants = (
|
||||
variants: SFCCProduct.ShopperProducts.Product['variants']
|
||||
): Product['variants'] => {
|
||||
if (!Array.isArray(variants)) return []
|
||||
|
||||
return variants.map(variant => {
|
||||
|
||||
const options = [] as ProductOption[];
|
||||
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: [{
|
||||
values: [
|
||||
{
|
||||
label: value,
|
||||
}]
|
||||
},
|
||||
],
|
||||
}
|
||||
options.push(variantOptionObject);
|
||||
options.push(variantOptionObject)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: variant.productId,
|
||||
options
|
||||
} as ProductVariant;
|
||||
});
|
||||
options,
|
||||
} as ProductVariant
|
||||
})
|
||||
}
|
||||
|
||||
export function normalizeProduct(product: SFCCProduct.ShopperProducts.Product): Product {
|
||||
export function normalizeProduct(
|
||||
product: SFCCProduct.ShopperProducts.Product
|
||||
): Product {
|
||||
return {
|
||||
id: product.id,
|
||||
// TODO: use `name-ID` as a virtual slug (for search 1:1)
|
||||
@ -49,36 +61,36 @@ export function normalizeProduct(product: SFCCProduct.ShopperProducts.Product):
|
||||
description: product.longDescription!,
|
||||
price: {
|
||||
value: product.price!,
|
||||
currencyCode: product.currency
|
||||
currencyCode: product.currency,
|
||||
},
|
||||
images: product.imageGroups![0].images.map(image => ({
|
||||
images: product.imageGroups![0].images.map((image) => ({
|
||||
url: image.disBaseLink,
|
||||
altText: image.title
|
||||
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 => ({
|
||||
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
|
||||
currencyCode: product.currency,
|
||||
},
|
||||
images: [
|
||||
{
|
||||
url: product.image!.link,
|
||||
altText: product.productName
|
||||
} as ProductImage
|
||||
altText: product.productName,
|
||||
} as ProductImage,
|
||||
],
|
||||
variants: normaliseVariants(product.variants),
|
||||
options: normaliseOptions(product.variationAttributes),
|
||||
}));
|
||||
|
||||
}))
|
||||
}
|
@ -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();
|
||||
const configAuth = await getConfigAuth()
|
||||
return new Product.ShopperProducts(configAuth)
|
||||
}
|
||||
|
||||
export const sdk = {
|
||||
getshopperProductsClient,
|
||||
getSearchClient
|
||||
getSearchClient,
|
||||
}
|
||||
export type Sdk = typeof sdk
|
||||
export default sdk
|
Loading…
x
Reference in New Issue
Block a user