mirror of
https://github.com/vercel/commerce.git
synced 2025-06-19 05:31:22 +00:00
Updated getProduct operation
This commit is contained in:
parent
be5d47bac3
commit
a106629964
@ -23,6 +23,7 @@ import getSiteInfo from './operations/get-site-info'
|
||||
import getCustomerWishlist from './operations/get-customer-wishlist'
|
||||
import getAllProductPaths from './operations/get-all-product-paths'
|
||||
import getAllProducts from './operations/get-all-products'
|
||||
import getProduct from './operations/get-product'
|
||||
|
||||
export interface BigcommerceConfig extends CommerceAPIConfig {
|
||||
// Indicates if the returned metadata with translations should be applied to the
|
||||
@ -126,6 +127,7 @@ export const provider = {
|
||||
getCustomerWishlist,
|
||||
getAllProductPaths,
|
||||
getAllProducts,
|
||||
getProduct,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -56,27 +56,9 @@ export type GetAllProductsResult<
|
||||
}
|
||||
> = T
|
||||
|
||||
const FIELDS = [
|
||||
'products',
|
||||
'featuredProducts',
|
||||
'bestSellingProducts',
|
||||
'newestProducts',
|
||||
]
|
||||
|
||||
export type ProductTypes =
|
||||
| 'products'
|
||||
| 'featuredProducts'
|
||||
| 'bestSellingProducts'
|
||||
| 'newestProducts'
|
||||
|
||||
export type ProductVariables = { field?: ProductTypes } & Omit<
|
||||
GetAllProductsQueryVariables,
|
||||
ProductTypes | 'hasLocale'
|
||||
>
|
||||
|
||||
function getProductsType(
|
||||
relevance?: GetAllProductsOperation['variables']['relevance']
|
||||
): ProductTypes {
|
||||
) {
|
||||
switch (relevance) {
|
||||
case 'featured':
|
||||
return 'featuredProducts'
|
||||
@ -118,19 +100,13 @@ export default function getAllProductsOperation({
|
||||
} = {}): Promise<T['data']> {
|
||||
config = commerce.getConfig(config)
|
||||
|
||||
const locale = config.locale
|
||||
const { locale } = config
|
||||
const field = getProductsType(vars.relevance)
|
||||
const variables: GetAllProductsQueryVariables = {
|
||||
locale,
|
||||
hasLocale: !!locale,
|
||||
}
|
||||
|
||||
if (!FIELDS.includes(field)) {
|
||||
throw new Error(
|
||||
`The field variable has to match one of ${FIELDS.join(', ')}`
|
||||
)
|
||||
}
|
||||
|
||||
variables[field] = true
|
||||
|
||||
if (vars.first) variables.first = vars.first
|
||||
|
120
framework/bigcommerce/api/operations/get-product.ts
Normal file
120
framework/bigcommerce/api/operations/get-product.ts
Normal file
@ -0,0 +1,120 @@
|
||||
import type {
|
||||
OperationContext,
|
||||
OperationOptions,
|
||||
} from '@commerce/api/operations'
|
||||
import type { GetProductOperation } from '../../types/product'
|
||||
import type { GetProductQuery, GetProductQueryVariables } from '../../schema'
|
||||
import setProductLocaleMeta from '../utils/set-product-locale-meta'
|
||||
import { productInfoFragment } from '../fragments/product'
|
||||
import { BigcommerceConfig, Provider } from '..'
|
||||
import { normalizeProduct } from '../../lib/normalize'
|
||||
|
||||
export const getProductQuery = /* GraphQL */ `
|
||||
query getProduct(
|
||||
$hasLocale: Boolean = false
|
||||
$locale: String = "null"
|
||||
$path: String!
|
||||
) {
|
||||
site {
|
||||
route(path: $path) {
|
||||
node {
|
||||
__typename
|
||||
... on Product {
|
||||
...productInfo
|
||||
variants {
|
||||
edges {
|
||||
node {
|
||||
entityId
|
||||
defaultImage {
|
||||
urlOriginal
|
||||
altText
|
||||
isDefault
|
||||
}
|
||||
prices {
|
||||
...productPrices
|
||||
}
|
||||
inventory {
|
||||
aggregated {
|
||||
availableToSell
|
||||
warningLevel
|
||||
}
|
||||
isInStock
|
||||
}
|
||||
productOptions {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
entityId
|
||||
displayName
|
||||
...multipleChoiceOption
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
${productInfoFragment}
|
||||
`
|
||||
|
||||
// TODO: See if this type is useful for defining the Product type
|
||||
// export type ProductNode = Extract<
|
||||
// GetProductQuery['site']['route']['node'],
|
||||
// { __typename: 'Product' }
|
||||
// >
|
||||
|
||||
export default function getAllProductPathsOperation({
|
||||
commerce,
|
||||
}: OperationContext<Provider>) {
|
||||
async function getProduct<T extends GetProductOperation>(opts: {
|
||||
variables: T['variables']
|
||||
config?: BigcommerceConfig
|
||||
preview?: boolean
|
||||
}): Promise<T['data']>
|
||||
|
||||
async function getProduct<T extends GetProductOperation>(
|
||||
opts: {
|
||||
variables: T['variables']
|
||||
config?: BigcommerceConfig
|
||||
preview?: boolean
|
||||
} & OperationOptions
|
||||
): Promise<T['data']>
|
||||
|
||||
async function getProduct<T extends GetProductOperation>({
|
||||
query = getProductQuery,
|
||||
variables: { slug, ...vars },
|
||||
config,
|
||||
}: {
|
||||
query?: string
|
||||
variables: T['variables']
|
||||
config?: BigcommerceConfig
|
||||
preview?: boolean
|
||||
}): Promise<T['data']> {
|
||||
config = commerce.getConfig(config)
|
||||
|
||||
const { locale } = config
|
||||
const variables: GetProductQueryVariables = {
|
||||
locale,
|
||||
hasLocale: !!locale,
|
||||
path: slug ? `/${slug}/` : vars.path!,
|
||||
}
|
||||
const { data } = await config.fetch<GetProductQuery>(query, { variables })
|
||||
const product = data.site?.route?.node
|
||||
|
||||
if (product?.__typename === 'Product') {
|
||||
if (locale && config.applyLocale) {
|
||||
setProductLocaleMeta(product)
|
||||
}
|
||||
|
||||
return { product: normalizeProduct(product as any) }
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
return getProduct
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
import type { GetProductQuery, GetProductQueryVariables } from '../schema'
|
||||
import setProductLocaleMeta from '../api/utils/set-product-locale-meta'
|
||||
import { productInfoFragment } from '../api/fragments/product'
|
||||
import { BigcommerceConfig, getConfig } from '../api'
|
||||
import { normalizeProduct } from '../lib/normalize'
|
||||
import type { Product } from '@commerce/types'
|
||||
|
||||
export const getProductQuery = /* GraphQL */ `
|
||||
query getProduct(
|
||||
$hasLocale: Boolean = false
|
||||
$locale: String = "null"
|
||||
$path: String!
|
||||
) {
|
||||
site {
|
||||
route(path: $path) {
|
||||
node {
|
||||
__typename
|
||||
... on Product {
|
||||
...productInfo
|
||||
variants {
|
||||
edges {
|
||||
node {
|
||||
entityId
|
||||
defaultImage {
|
||||
urlOriginal
|
||||
altText
|
||||
isDefault
|
||||
}
|
||||
prices {
|
||||
...productPrices
|
||||
}
|
||||
inventory {
|
||||
aggregated {
|
||||
availableToSell
|
||||
warningLevel
|
||||
}
|
||||
isInStock
|
||||
}
|
||||
productOptions {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
entityId
|
||||
displayName
|
||||
...multipleChoiceOption
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
${productInfoFragment}
|
||||
`
|
||||
|
||||
export type ProductNode = Extract<
|
||||
GetProductQuery['site']['route']['node'],
|
||||
{ __typename: 'Product' }
|
||||
>
|
||||
|
||||
export type GetProductResult<
|
||||
T extends { product?: any } = { product?: ProductNode }
|
||||
> = T
|
||||
|
||||
export type ProductVariables = { locale?: string } & (
|
||||
| { path: string; slug?: never }
|
||||
| { path?: never; slug: string }
|
||||
)
|
||||
|
||||
async function getProduct(opts: {
|
||||
variables: ProductVariables
|
||||
config?: BigcommerceConfig
|
||||
preview?: boolean
|
||||
}): Promise<GetProductResult>
|
||||
|
||||
async function getProduct<T extends { product?: any }, V = any>(opts: {
|
||||
query: string
|
||||
variables: V
|
||||
config?: BigcommerceConfig
|
||||
preview?: boolean
|
||||
}): Promise<GetProductResult<T>>
|
||||
|
||||
async function getProduct({
|
||||
query = getProductQuery,
|
||||
variables: { slug, ...vars },
|
||||
config,
|
||||
}: {
|
||||
query?: string
|
||||
variables: ProductVariables
|
||||
config?: BigcommerceConfig
|
||||
preview?: boolean
|
||||
}): Promise<Product | {} | any> {
|
||||
config = getConfig(config)
|
||||
|
||||
const locale = vars.locale || config.locale
|
||||
const variables: GetProductQueryVariables = {
|
||||
...vars,
|
||||
locale,
|
||||
hasLocale: !!locale,
|
||||
path: slug ? `/${slug}/` : vars.path!,
|
||||
}
|
||||
const { data } = await config.fetch<GetProductQuery>(query, { variables })
|
||||
const product = data.site?.route?.node
|
||||
|
||||
if (product?.__typename === 'Product') {
|
||||
if (locale && config.applyLocale) {
|
||||
setProductLocaleMeta(product)
|
||||
}
|
||||
|
||||
return { product: normalizeProduct(product as any) }
|
||||
}
|
||||
|
||||
return {}
|
||||
}
|
||||
|
||||
export default getProduct
|
@ -1,4 +1,2 @@
|
||||
export { default as usePrice } from './use-price'
|
||||
export { default as useSearch } from './use-search'
|
||||
export { default as getProduct } from './get-product'
|
||||
export { default as getAllProducts } from '../api/operations/get-all-products'
|
||||
|
@ -6,6 +6,7 @@ import type { GetCustomerWishlistOperation } from '../types/wishlist'
|
||||
import type {
|
||||
GetAllProductPathsOperation,
|
||||
GetAllProductsOperation,
|
||||
GetProductOperation,
|
||||
} from '../types/product'
|
||||
import type { APIProvider, CommerceAPI } from '.'
|
||||
|
||||
@ -128,6 +129,22 @@ export type Operations<P extends APIProvider> = {
|
||||
} & OperationOptions
|
||||
): Promise<T['data']>
|
||||
}
|
||||
|
||||
getProduct: {
|
||||
<T extends GetProductOperation>(opts: {
|
||||
variables: T['variables']
|
||||
config?: P['config']
|
||||
preview?: boolean
|
||||
}): Promise<T['data']>
|
||||
|
||||
<T extends GetProductOperation>(
|
||||
opts: {
|
||||
variables: T['variables']
|
||||
config?: P['config']
|
||||
preview?: boolean
|
||||
} & OperationOptions
|
||||
): Promise<T['data']>
|
||||
}
|
||||
}
|
||||
|
||||
export type APIOperations<P extends APIProvider> = {
|
||||
|
@ -81,3 +81,8 @@ export type GetAllProductsOperation<T extends ProductTypes = ProductTypes> = {
|
||||
first?: number
|
||||
}
|
||||
}
|
||||
|
||||
export type GetProductOperation<T extends ProductTypes = ProductTypes> = {
|
||||
data: { product?: T['product'] }
|
||||
variables: { path: string; slug?: never } | { path?: never; slug: string }
|
||||
}
|
||||
|
@ -7,9 +7,7 @@ import { useRouter } from 'next/router'
|
||||
import commerce from '@lib/api/commerce'
|
||||
import { Layout } from '@components/common'
|
||||
import { ProductView } from '@components/product'
|
||||
|
||||
import { getConfig } from '@framework/api'
|
||||
import getProduct from '@framework/product/get-product'
|
||||
|
||||
export async function getStaticProps({
|
||||
params,
|
||||
@ -18,7 +16,7 @@ export async function getStaticProps({
|
||||
}: GetStaticPropsContext<{ slug: string }>) {
|
||||
const config = getConfig({ locale })
|
||||
const { pages } = await commerce.getAllPages({ config, preview })
|
||||
const { product } = await getProduct({
|
||||
const { product } = await commerce.getProduct({
|
||||
variables: { slug: params!.slug },
|
||||
config,
|
||||
preview,
|
||||
|
Loading…
x
Reference in New Issue
Block a user