Get Product List

The getProductsList function performs comprehensive product search operations with advanced filtering, faceted navigation, and pagination capabilities. This function serves as the primary search engine for the e-commerce platform, enabling users to discover products through text search, attribute filtering, brand selection, and supplier restrictions.

The function supports sophisticated search scenarios including full-text search across product names, descriptions, and SKUs, combined with multi-dimensional filtering through attributes, brands, suppliers, and product tags. It provides faceted navigation data to enable dynamic filter interfaces and supports efficient pagination for handling large result sets.

This function is critical for B2B e-commerce scenarios where buyers need to quickly locate specific products from extensive catalogs, compare offerings across suppliers, and apply complex business-specific filtering criteria for procurement workflows.

Process Flow

sequenceDiagram
    participant User as User
    participant Component as Vue Component
    participant useSearchProduct as useSearchProduct
    participant SDK as Djust SDK
    participant API as API Server
    participant Auth as Auth Service

    User->>Component: Enter Search Criteria
    Component->>useSearchProduct: getProductsList(params)

    useSearchProduct->>useSearchProduct: Build Search Parameters
    useSearchProduct->>SDK: useFetch('/api/search/products')

    SDK->>Auth: Verify Authentication Token
    Auth-->>SDK: Token Valid

    SDK->>API: GET /api/search/products

    alt Success Response
        API-->>SDK: 200 - Search Results + Facets
        SDK-->>useSearchProduct: SearchProductsResponse
        useSearchProduct->>useSearchProduct: Process Results & Facets
        useSearchProduct-->>Component: Products + Pagination + Filters
        Component-->>User: Display Search Results
    else No Results Found
        API-->>SDK: 200 - Empty Results
        SDK-->>useSearchProduct: Empty Response
        useSearchProduct-->>Component: Empty Results
        Component-->>User: "No products found"
    else Authentication Error
        Auth-->>SDK: 401 - Unauthorized
        SDK-->>useSearchProduct: Auth Error
        useSearchProduct-->>Component: Authentication Error
        Component-->>User: Redirect to Login
    else Permission Error
        API-->>SDK: 403 - Search Access Denied
        SDK-->>useSearchProduct: Permission Error
        useSearchProduct-->>Component: Access Denied
        Component-->>User: "Search access restricted"
    else Server Error
        API-->>SDK: 500 - Internal Error
        SDK-->>useSearchProduct: Server Error
        useSearchProduct->>useSearchProduct: Log Server Error
        useSearchProduct-->>Component: Error Response
        Component-->>User: "Search service unavailable"
    end

Call Parameters

The function accepts a SearchProductsRequest object with the following structure:

SearchProductsRequest Interface (from SDK)

interface SearchProductsRequest {
  locale?: string;
  filters?: SearchFilters;
  pageable?: Pageable;
  includeFacets?: boolean;
}

interface SearchFilters {
  currency?: string;
  locale?: string;
  brand?: string[];
  attributes?: string[];
  productTags?: string[];
  suppliers?: string[];
  aggregation?: AggregationType;
  query?: string;
  categoryIds?: string[];
  priceRange?: PriceRange;
}

interface Pageable {
  page?: number;
  size?: number;
  sort?: string[];
}

interface PriceRange {
  min?: number;
  max?: number;
  currency?: string;
}

enum AggregationType {
  PRODUCT = "PRODUCT",
  VARIANT = "VARIANT",
  OFFER = "OFFER",
}

Parameter Details

| Parameter | Type | Required | Default | Example | Business Impact | | --------------------- | ----------------- | ----------- | -------------- | ----------------------------- | --------------------------------------------------------------- | ------------ | ------ | ------------------------------------- | | locale | string | ❌ Optional | Runtime config | "en-GB", "fr-FR" | Localization: Affects search relevance and content language | | filters.query | string | ❌ Optional | - | "laptop dell i7" | Search Scope: Text search across product content | | filters.currency | string | ❌ Optional | Runtime config | "EUR", "USD" | Pricing: Currency context for price filtering | | filters.brand | string[] | ❌ Optional | [] | ["Dell", "HP"] | Brand Filtering: Restricts results to specific brands | | filters.attributes | string[] | ❌ Optional | [] | ["RAM:16GB", "Color:Black"] | Attribute Filtering: Product specification filtering | | filters.suppliers | string[] | ❌ Optional | [] | ["supplier-001"] | Supplier Filtering: Business relationship filtering | | filters.productTags | string[] | ❌ Optional | [] | ["electronics", "business"] | Category Filtering: Tag-based product grouping | | filters.aggregation | AggregationType | ❌ Optional | PRODUCT | PRODUCT, VARIANT | Data Scope: Result aggregation level | | pageable.page | number | ❌ Optional | 0 | 0, 1, 2 | Performance: Controls pagination | | pageable.size | number | ❌ Optional | 20 | 10, 20, 50 | Performance: Results per page | | pageable.sort | string[] | ❌ Optional | ["name | ASC"] | ["price | DESC", "name | ASC"] | Ordering: Result sorting criteria | | includeFacets | boolean | ❌ Optional | true | true, false | Performance: Include faceting data |

Complete Example Call

const searchParams: SearchProductsRequest = {
  locale: "en-GB",
  filters: {
    query: "business laptop",
    currency: "EUR",
    brand: ["Dell", "HP"],
    attributes: ["RAM:16GB", "Storage:SSD"],
    productTags: ["business", "professional"],
    suppliers: ["supplier-techpro"],
    aggregation: AggregationType.PRODUCT,
    priceRange: {
      min: 500,
      max: 2000,
      currency: "EUR",
    },
  },
  pageable: {
    page: 0,
    size: 20,
    sort: ["relevance|DESC", "price|ASC"],
  },
  includeFacets: true,
};

const searchResults = await getProductsList(searchParams);

Returns from Composable

The function returns a SearchProductsResponse object with the following structure:

SearchProductsResponse Interface (from SDK)

interface SearchProductsResponse {
  success: boolean;
  products: ProductsSearchList;
  facets?: Facets;
  includeFacets: boolean;
}

interface ProductsSearchList {
  content: ProductSearchContent[];
  pageable: Pageable;
  totalElements: number;
  totalPages: number;
  size: number;
  number: number;
  first: boolean;
  last: boolean;
  empty?: boolean;
}

interface Facets {
  attributes: AttributeFacet[];
  suppliers?: SupplierFacet[];
  brands?: BrandFacet[];
  productTags?: ProductTagFacet[];
  customFields?: CustomFieldFacet[];
  priceRange?: PriceRangeFacet;
}

interface AttributeFacet {
  id: string;
  name: string;
  values: AttributeValueFacet[];
}

interface AttributeValueFacet {
  value: string;
  count: number;
  selected: boolean;
}

Realistic Example JSON Response

{
  "success": true,
  "products": {
    "content": [
      {
        "offerPrice": {
          "unitPrice": 1299.99,
          "currency": "EUR",
          "taxIncluded": false
        },
        "offer": {
          "id": "offer-001",
          "externalId": "EXT-OFFER-001",
          "quantityPerItem": 1,
          "stock": 85,
          "currency": "EUR",
          "minOrderQuantity": 1,
          "maxOrderQuantity": 50,
          "leadTimeToShip": 3
        },
        "variant": {
          "id": "variant-001",
          "externalId": "DELL-LAT-7420-16GB",
          "sku": "DELL-LAT-7420-16GB-BLK",
          "name": "Dell Latitude 7420 - 16GB RAM - Black",
          "description": "Premium business laptop with Intel i7 processor",
          "pictureUrls": [
            {
              "url": "https://cdn.example.com/dell-latitude-7420-main.jpg",
              "width": 1200,
              "height": 900
            }
          ],
          "ean": "1234567890125",
          "mpn": "LAT7420-16-BLK"
        },
        "product": {
          "id": "product-001",
          "externalId": "DELL-LATITUDE-7420",
          "sku": "DELL-LAT-7420",
          "name": "Dell Latitude 7420",
          "description": "Premium business laptop series with enhanced security features",
          "brand": "Dell",
          "mainPictureUrl": "https://cdn.example.com/dell-latitude-7420-hero.jpg",
          "tags": [
            {
              "name": "Business",
              "category": "USE_CASE"
            },
            {
              "name": "Professional",
              "category": "TIER"
            }
          ],
          "unit": "piece"
        },
        "attributes": [
          {
            "name": "RAM Size",
            "externalId": "RAM_SIZE",
            "value": "16GB",
            "values": ["16GB"]
          },
          {
            "name": "Storage Type",
            "externalId": "STORAGE_TYPE",
            "value": "SSD",
            "values": ["SSD"]
          },
          {
            "name": "Color",
            "externalId": "COLOR",
            "value": "Black",
            "values": ["Black"]
          }
        ],
        "supplier": {
          "id": "supplier-001",
          "name": "TechPro Distribution",
          "externalId": "TECH-PRO-001"
        }
      }
    ],
    "pageable": {
      "page": 0,
      "size": 20,
      "sort": ["relevance|DESC", "price|ASC"]
    },
    "totalElements": 127,
    "totalPages": 7,
    "size": 20,
    "number": 0,
    "first": true,
    "last": false,
    "empty": false
  },
  "facets": {
    "attributes": [
      {
        "id": "RAM_SIZE",
        "name": "RAM Size",
        "values": [
          {
            "value": "8GB",
            "count": 45,
            "selected": false
          },
          {
            "value": "16GB",
            "count": 67,
            "selected": true
          },
          {
            "value": "32GB",
            "count": 15,
            "selected": false
          }
        ]
      },
      {
        "id": "STORAGE_TYPE",
        "name": "Storage Type",
        "values": [
          {
            "value": "SSD",
            "count": 98,
            "selected": true
          },
          {
            "value": "HDD",
            "count": 29,
            "selected": false
          }
        ]
      }
    ],
    "brands": [
      {
        "name": "Dell",
        "count": 67,
        "selected": true
      },
      {
        "name": "HP",
        "count": 45,
        "selected": true
      },
      {
        "name": "Lenovo",
        "count": 15,
        "selected": false
      }
    ],
    "suppliers": [
      {
        "name": "TechPro Distribution",
        "count": 89,
        "selected": true
      },
      {
        "name": "Business Tech Solutions",
        "count": 38,
        "selected": false
      }
    ],
    "productTags": [
      {
        "id": "business",
        "name": "Business",
        "count": 127,
        "selected": true
      },
      {
        "id": "professional",
        "name": "Professional",
        "count": 94,
        "selected": true
      }
    ],
    "priceRange": {
      "min": 599.99,
      "max": 2899.99,
      "currency": "EUR",
      "distribution": [
        {
          "range": "600-1000",
          "count": 34
        },
        {
          "range": "1000-1500",
          "count": 67
        },
        {
          "range": "1500-2000",
          "count": 23
        },
        {
          "range": "2000+",
          "count": 3
        }
      ]
    }
  },
  "includeFacets": true
}

Error Management

HTTP Error Codes and Handling

Error CodeCauseSystem ActionUser MessageReturn Format
400Invalid search parameters or malformed filtersLog validation error, return empty results"Invalid search criteria"{ success: false, products: { content: [] } }
401Authentication token missing/invalidTrigger re-authentication flow"Please log in to search products"Authentication redirect
403User lacks search permissionsLog access attempt, return restricted results"Limited search access"Filtered results based on permissions
404Search service or endpoint not foundLog service error, return empty results"Search service unavailable"{ success: false, products: { content: [] } }
429Rate limit exceeded for search requestsLog rate limit hit, return cached results"Too many search requests"Cached results or empty
500Internal server error in search serviceLog server error, return empty results"Search temporarily unavailable"{ success: false, products: { content: [] } }

Error Handling Example Code

// Global error handling in composable
const getProductsList = async ({
  locale = defaultLocale,
  filters = defaultFilters,
  pageable = defaultPageable,
  includeFacets = true,
}: SearchProductsRequest) => {
  try {
    // Input validation
    if (filters?.query && filters.query.length > 100) {
      console.warn("Search query too long, truncating");
      filters.query = filters.query.substring(0, 100);
    }

    loading.value = true;

    const { data, status, error } = await useFetch("/api/search/products", {
      params: {
        locale,
        filters: JSON.stringify(filters),
        pageable: JSON.stringify(pageable),
        includeFacets: includeFacets,
      },
      key: `products-${locale}-${JSON.stringify(filters)}-${JSON.stringify(
        pageable
      )}-${includeFacets}`,
    });

    loading.value = status.value === "pending";

    if (error.value) {
      console.error("Error fetching products:", {
        locale,
        filters,
        error: error.value,
      });
      return {
        success: false,
        products: { content: [], totalElements: 0 },
        facets: undefined,
        includeFacets: false,
      } as SearchProductsResponse;
    }

    return (
      data.value ||
      ({
        success: false,
        products: { content: [], totalElements: 0 },
        facets: undefined,
        includeFacets: false,
      } as SearchProductsResponse)
    );
  } catch (error) {
    console.error("Unexpected error in getProductsList:", error);
    return {
      success: false,
      products: { content: [], totalElements: 0 },
      facets: undefined,
      includeFacets: false,
    } as SearchProductsResponse;
  } finally {
    loading.value = false;
  }
};

// Component-level error handling
const performProductSearch = async (searchCriteria: SearchProductsRequest) => {
  try {
    isSearching.value = true;

    const response = await getProductsList(searchCriteria);

    if (!response.success) {
      throw new Error("Search request failed");
    }

    // Process successful response
    searchResults.value = response.products.content;
    totalResults.value = response.products.totalElements;
    currentFacets.value = response.facets;
  } catch (error) {
    console.error("Product search error:", error);

    // User notification
    useToast().add({
      title: "Search Error",
      description: "Unable to perform product search. Please try again.",
      color: "red",
    });

    // Fallback to empty results
    searchResults.value = [];
    totalResults.value = 0;
    currentFacets.value = undefined;
  } finally {
    isSearching.value = false;
  }
};

Use Cases

1. Text-based Product Discovery

Enable users to find products using natural language queries across product names, descriptions, and specifications.

Scenario: User searches for "business laptop with SSD storage" to find suitable professional computing devices. Parameters: { filters: { query: "business laptop with SSD storage" }, pageable: { page: 0, size: 20 }, includeFacets: true } Expected Outcome: Relevant business laptops displayed with SSD storage, along with filtering options for further refinement.

2. Advanced Attribute Filtering

Support complex product searches using multiple attribute filters for precise product specification matching.

Scenario: IT procurement manager needs laptops with specific RAM, storage, and color requirements for enterprise deployment. Parameters: { filters: { attributes: ["RAM:16GB", "Storage:SSD", "Color:Black"], brand: ["Dell", "HP"] } } Expected Outcome: Filtered results showing only products matching exact specifications with pricing and availability.

3. Supplier-specific Product Search

Enable buyers to search within their approved supplier network for compliance and relationship management.

Scenario: Company policy requires purchases from specific approved suppliers for warranty and support guarantees. Parameters: { filters: { suppliers: ["approved-supplier-001", "preferred-supplier-002"], query: "monitors" } } Expected Outcome: Monitor products available only from approved suppliers with negotiated pricing.

4. Faceted Navigation and Refinement

Provide dynamic filtering interface allowing users to progressively refine search results using available facets.

Scenario: User starts with broad "electronics" search and progressively narrows using brand, price range, and attribute facets. Parameters: { filters: { productTags: ["electronics"] }, includeFacets: true, pageable: { page: 0, size: 24 } } Expected Outcome: Electronics products with comprehensive facet data enabling progressive search refinement.

Important Points

Performance Considerations

  • Intelligent Caching: Search results cached with complex keys including all filter parameters
  • Facet Optimization: Conditional facet loading to reduce response size and improve performance
  • Pagination Strategy: Efficient pagination handling for large result sets with configurable page sizes
  • Query Optimization: Server-side query optimization for complex attribute and text-based searches

Security Aspects

  • Permission Filtering: Backend automatically filters results based on user's product access permissions
  • Supplier Restrictions: Results limited to user's approved supplier network and contract agreements
  • Data Privacy: Sensitive pricing and stock information filtered based on user role and permissions
  • Input Sanitization: All search inputs sanitized to prevent injection attacks and ensure data integrity

Flexibility Features

  • Multi-language Search: Search adapts to user's locale for language-specific product matching
  • Currency-aware Results: Pricing and filtering respects user's preferred currency settings
  • Configurable Aggregation: Support for product, variant, or offer-level result aggregation
  • Extensible Filtering: Flexible filter system supports new attribute types and business rules

Integration Capabilities

  • Analytics Integration: Search behavior tracking for business intelligence and catalog optimization
  • Cart Integration: Direct "add to cart" functionality from search results for streamlined purchasing
  • Quote Integration: Bulk quote generation from filtered search results for enterprise workflows
  • Catalog Management: Search results inform catalog managers about popular products and search patterns

Technical Implementation

Composable Function with Complete JSDoc

/**
 * Performs comprehensive product search with filtering and faceted navigation
 *
 * @param params - Search request parameters
 * @param params.locale - Locale for internationalized search
 * @param params.filters - Search filters and criteria
 * @param params.pageable - Pagination configuration
 * @param params.includeFacets - Whether to include faceting data
 * @returns Promise resolving to search results with products and facets
 *
 * @example
 * ```typescript
 * const { getProductsList } = useSearchProduct();
 *
 * const searchResults = await getProductsList({
 *   locale: "en-GB",
 *   filters: {
 *     query: "business laptop",
 *     brand: ["Dell", "HP"],
 *     attributes: ["RAM:16GB"]
 *   },
 *   pageable: { page: 0, size: 20 },
 *   includeFacets: true
 * });
 *
 * if (searchResults.success) {
 *   console.log('Products found:', searchResults.products.totalElements);
 *   console.log('Available facets:', Object.keys(searchResults.facets || {}));
 * }
 * ```
 *
 * @throws {Error} When network request fails or invalid parameters provided
 * @since 1.0.0
 */
const getProductsList = async ({
  locale = defaultLocale,
  filters = defaultFilters,
  pageable = defaultPageable,
  includeFacets = true,
}: SearchProductsRequest): Promise<SearchProductsResponse> => {
  try {
    // Input validation and sanitization
    if (filters?.query && filters.query.length > 200) {
      console.warn("Search query exceeds maximum length, truncating");
      filters.query = filters.query.substring(0, 200);
    }

    // Set loading state
    loading.value = true;

    // Runtime configuration for defaults
    const runtimeConfig = useRuntimeConfig();
    const effectiveLocale = locale || runtimeConfig.public.locale;
    const effectiveCurrency =
      filters?.currency || runtimeConfig.public.currency;

    const { data, status, error } = await useFetch("/api/search/products", {
      params: {
        locale: effectiveLocale,
        filters: JSON.stringify({
          ...defaultFilters,
          ...filters,
          currency: effectiveCurrency,
        }),
        pageable: JSON.stringify({
          ...defaultPageable,
          ...pageable,
        }),
        includeFacets: includeFacets,
      },
      // Generate unique cache key
      key: `products-${effectiveLocale}-${JSON.stringify(
        filters
      )}-${JSON.stringify(pageable)}-${includeFacets}`,
    });

    // Update loading state
    loading.value = status.value === "pending";

    if (error.value) {
      console.error("Error fetching products:", {
        locale: effectiveLocale,
        filters,
        pageable,
        error: error.value,
      });

      return {
        success: false,
        products: {
          content: [],
          totalElements: 0,
          totalPages: 0,
          size: pageable?.size || 20,
          number: pageable?.page || 0,
          first: true,
          last: true,
          empty: true,
        },
        facets: undefined,
        includeFacets: false,
      } as SearchProductsResponse;
    }

    return (
      data.value ||
      ({
        success: false,
        products: { content: [], totalElements: 0 },
        facets: undefined,
        includeFacets: false,
      } as SearchProductsResponse)
    );
  } catch (error) {
    console.error("Unexpected error in getProductsList:", error);

    return {
      success: false,
      products: { content: [], totalElements: 0 },
      facets: undefined,
      includeFacets: false,
    } as SearchProductsResponse;
  } finally {
    loading.value = false;
  }
};

Execution Flow

Step-by-Step Process

  1. Parameter Validation and Sanitization

    // Validate and clean search parameters
    if (filters?.query && filters.query.length > 200) {
      filters.query = filters.query.substring(0, 200);
    }
  2. Loading State Management

    // Set loading indicator for UI feedback
    loading.value = true;
  3. Configuration Setup

    // Apply runtime defaults and merge parameters
    const runtimeConfig = useRuntimeConfig();
    const effectiveLocale = locale || runtimeConfig.public.locale;
    const mergedFilters = { ...defaultFilters, ...filters };
  4. Cache Key Generation

    // Generate comprehensive cache key
    const cacheKey = `products-${locale}-${JSON.stringify(
      filters
    )}-${JSON.stringify(pageable)}-${includeFacets}`;
  5. API Request Construction

    // Build search API request
    const requestParams = {
      locale: effectiveLocale,
      filters: JSON.stringify(mergedFilters),
      pageable: JSON.stringify(mergedPageable),
      includeFacets: includeFacets,
    };
  6. Search Execution

    // Execute product search request
    const { data, status, error } = await useFetch("/api/search/products", {
      params: requestParams,
      key: cacheKey,
    });
  7. Response Processing

    // Handle search results or errors
    if (error.value) {
      logError("Product search failed", { filters, error: error.value });
      return emptySearchResponse;
    }
  8. Result Formatting

    // Return formatted search response
    return {
      success: true,
      products: data.value.products,
      facets: data.value.facets,
      includeFacets: includeFacets,
    };
  9. State Cleanup

    // Reset loading state
    loading.value = false;