Vue Storefront is now Alokai! Learn More
SearchProducts

SearchProducts

Implements SearchProducts Unified Method.

Source

import { defineApi } from "@vsf-enterprise/unified-api-bigcommerce";
import type { GraphQL } from "@vsf-enterprise/bigcommerce-api";
import type {
  ProductsResponse,
  BigcommerceIntegrationContext,
} from "@vsf-enterprise/bigcommerce-api";
import { getNormalizers } from "@vsf-enterprise/unified-api-bigcommerce/udl";
import { type NormalizedRequestArgs, getBuilders, normalizeRequestParams } from "@vsf-enterprise/unified-api-bigcommerce";

export const searchProducts = defineApi.searchProducts(async (context, args) => {
  const { normalizeProductCatalogItem } = getNormalizers(context);
  const normalizedParams = await normalizeRequestParams(context, args);
  const [productsResponse, filtersResponse] = await Promise.all([
    getProductsWithFilter(context, normalizedParams),
    getFilters(context, normalizedParams),
  ]);

  const products = productsResponse.data.map((product) => normalizeProductCatalogItem(product));

  const { buildFacets, buildPagination } = getBuilders(context);

  return {
    products,
    ...buildFacets(filtersResponse, context),
    ...buildPagination(productsResponse, normalizedParams),
  };
});

async function getProductsWithFilter(
  context: BigcommerceIntegrationContext,
  args: NormalizedRequestArgs,
): Promise<ProductsResponse> {
  const {
    currentPage,
    categoryEntityId,
    searchTerm,
    productAttributes,
    pageSize,
    sort,
    brandEntityIds,
  } = args;
  let products: ProductsResponse;

  products = await context.api.getProductsWithFilter({
    filters: {
      categoryEntityId,
      searchTerm,
      productAttributes,
      brandEntityIds,
    },
    currencyCode: context.config.normalizerContext.currency as GraphQL.CurrencyCode,
    // API does not support offset pagination, so we have to fetch all products and then slice them
    first: pageSize * currentPage,
    sort,
  });

  products = {
    ...products,
    data: products.data.slice(-pageSize),
  };

  return products;
}

async function getFilters(
  context: BigcommerceIntegrationContext,
  args: NormalizedRequestArgs,
): Promise<GraphQL.SearchProductFilterConnection> {
  const { categoryEntityId, searchTerm, productAttributes } = args;
  try {
    return await context.api.getFilters({
      filters: {
        categoryEntityId,
        searchTerm,
        productAttributes,
      },
    });
  } catch {
    return {} as any;
  }
}