Vue Storefront is now Alokai! Learn More
SearchProducts

SearchProducts

Implements SearchProducts Unified Method.

Source

import "./extended";
import type { SearchProducts, SearchProductsArgs } from "@alokai/connect";
import { assignToNormalizerContext, getNormalizers } from "@alokai/connect/integration-kit";
import { getLogger } from "@alokai/connect/middleware";
import type { SapccIntegrationContext } from "@vsf-enterprise/sapcc-api";

import { defineApi } from "@vsf-enterprise/unified-api-sapcc";
import { buildFilters, buildProductsResponse, buildQueryString } from "@vsf-enterprise/unified-api-sapcc";

export const searchProducts = defineApi.searchProducts(async (context, args) => {
  const logger = getLogger(context);
  try {
    return await searchProductsByQuery(context, args);
  } catch (error) {
    logger.error(error);
    return {
      facets: [],
      pagination: {
        currentPage: 0,
        pageSize: 0,
        totalPages: 0,
        totalResults: 0,
      },
      products: [],
    };
  }
});

function translateSort(sortBy: SearchProductsArgs["sortBy"]) {
  switch (sortBy) {
    case "price-high-to-low": {
      return "price-desc";
    }
    case "price-low-to-high": {
      return "price-asc";
    }
    case "relevant": {
      return "relevance";
    }
    default: {
      return sortBy;
    }
  }
}

async function searchProductsByQuery(
  context: SapccIntegrationContext,
  { category, currentPage = 1, facets: facetsQuery, pageSize, search, sortBy }: SearchProductsArgs,
): ReturnType<SearchProducts> {
  const { api } = await context.getApiClient();
  const filters = buildFilters({ category, facets: facetsQuery });
  const { filterFacets = () => true } = context.config.unified;
  const { normalizeFacet, normalizePagination } = getNormalizers(context);

  const sort = translateSort(sortBy);
  const searchTerm = search;

  const { data: searchProductResponse } = await api.getProducts({
    currentPage: Math.max(currentPage - 1, 0),
    pageSize,
    query: buildQueryString({ filters, searchTerm, sort }),
    sort,
  });

  const {
    currentQuery,
    facets: rawFacets = [],
    pagination: rawPagination = {},
    products: rawProducts = [],
  } = searchProductResponse;

  assignToNormalizerContext(context, {
    currentQuery,
  });

  return {
    facets: rawFacets
      .filter((facet) => filterFacets(facet))
      .map((facet) => normalizeFacet(facet))
      .filter(Boolean),
    pagination: normalizePagination(rawPagination),
    ...buildProductsResponse(context, rawProducts),
  };
}