mirror of
https://github.com/vercel/commerce.git
synced 2025-05-19 07:56:59 +00:00
136 lines
3.8 KiB
TypeScript
136 lines
3.8 KiB
TypeScript
import type {
|
|
OperationContext,
|
|
OperationOptions,
|
|
} from '@commerce/api/operations'
|
|
import type {
|
|
GetAllProductsQuery,
|
|
GetAllProductsQueryVariables,
|
|
} from '../../schema'
|
|
import type { GetAllProductsOperation } from '../../types/product'
|
|
import type { RecursivePartial, RecursiveRequired } from '../utils/types'
|
|
import filterEdges from '../utils/filter-edges'
|
|
import setProductLocaleMeta from '../utils/set-product-locale-meta'
|
|
import { productConnectionFragment } from '../fragments/product'
|
|
import { BigcommerceConfig, Provider } from '..'
|
|
import { normalizeProduct } from '../../lib/normalize'
|
|
|
|
export const getAllProductsQuery = /* GraphQL */ `
|
|
query getAllProducts(
|
|
$hasLocale: Boolean = false
|
|
$locale: String = "null"
|
|
$entityIds: [Int!]
|
|
$first: Int = 10
|
|
$products: Boolean = false
|
|
$featuredProducts: Boolean = false
|
|
$bestSellingProducts: Boolean = false
|
|
$newestProducts: Boolean = false
|
|
) {
|
|
site {
|
|
products(first: $first, entityIds: $entityIds) @include(if: $products) {
|
|
...productConnnection
|
|
}
|
|
featuredProducts(first: $first) @include(if: $featuredProducts) {
|
|
...productConnnection
|
|
}
|
|
bestSellingProducts(first: $first) @include(if: $bestSellingProducts) {
|
|
...productConnnection
|
|
}
|
|
newestProducts(first: $first) @include(if: $newestProducts) {
|
|
...productConnnection
|
|
}
|
|
}
|
|
}
|
|
|
|
${productConnectionFragment}
|
|
`
|
|
|
|
export type ProductEdge = NonNullable<
|
|
NonNullable<GetAllProductsQuery['site']['products']['edges']>[0]
|
|
>
|
|
|
|
export type ProductNode = ProductEdge['node']
|
|
|
|
export type GetAllProductsResult<
|
|
T extends Record<keyof GetAllProductsResult, any[]> = {
|
|
products: ProductEdge[]
|
|
}
|
|
> = T
|
|
|
|
function getProductsType(
|
|
relevance?: GetAllProductsOperation['variables']['relevance']
|
|
) {
|
|
switch (relevance) {
|
|
case 'featured':
|
|
return 'featuredProducts'
|
|
case 'best_selling':
|
|
return 'bestSellingProducts'
|
|
case 'newest':
|
|
return 'newestProducts'
|
|
default:
|
|
return 'products'
|
|
}
|
|
}
|
|
|
|
export default function getAllProductsOperation({
|
|
commerce,
|
|
}: OperationContext<Provider>) {
|
|
async function getAllProducts<T extends GetAllProductsOperation>(opts?: {
|
|
variables?: T['variables']
|
|
config?: Partial<BigcommerceConfig>
|
|
preview?: boolean
|
|
}): Promise<T['data']>
|
|
|
|
async function getAllProducts<T extends GetAllProductsOperation>(
|
|
opts: {
|
|
variables?: T['variables']
|
|
config?: Partial<BigcommerceConfig>
|
|
preview?: boolean
|
|
} & OperationOptions
|
|
): Promise<T['data']>
|
|
|
|
async function getAllProducts<T extends GetAllProductsOperation>({
|
|
query = getAllProductsQuery,
|
|
variables: vars = {},
|
|
config: cfg,
|
|
}: {
|
|
query?: string
|
|
variables?: T['variables']
|
|
config?: Partial<BigcommerceConfig>
|
|
preview?: boolean
|
|
} = {}): Promise<T['data']> {
|
|
const config = commerce.getConfig(cfg)
|
|
const { locale } = config
|
|
const field = getProductsType(vars.relevance)
|
|
const variables: GetAllProductsQueryVariables = {
|
|
locale,
|
|
hasLocale: !!locale,
|
|
}
|
|
|
|
variables[field] = true
|
|
|
|
if (vars.first) variables.first = vars.first
|
|
if (vars.ids) variables.entityIds = vars.ids.map((id) => Number(id))
|
|
|
|
// RecursivePartial forces the method to check for every prop in the data, which is
|
|
// required in case there's a custom `query`
|
|
const { data } = await config.fetch<RecursivePartial<GetAllProductsQuery>>(
|
|
query,
|
|
{ variables }
|
|
)
|
|
const edges = data.site?.[field]?.edges
|
|
const products = filterEdges(edges as RecursiveRequired<typeof edges>)
|
|
|
|
if (locale && config.applyLocale) {
|
|
products.forEach((product: RecursivePartial<ProductEdge>) => {
|
|
if (product.node) setProductLocaleMeta(product.node)
|
|
})
|
|
}
|
|
|
|
return {
|
|
products: products.map(({ node }) => normalizeProduct(node as any)),
|
|
}
|
|
}
|
|
|
|
return getAllProducts
|
|
}
|