diff --git a/types/clerk.io/clerk.io-tests.ts b/types/clerk.io/clerk.io-tests.ts index a2613d7715b2ba..c07b7cf7116340 100644 --- a/types/clerk.io/clerk.io-tests.ts +++ b/types/clerk.io/clerk.io-tests.ts @@ -1,31 +1,34 @@ -// @ts-expect-error -window.Clerk("click", 1); - -// @ts-expect-error -window.Clerk("call", "test"); +if (window.Clerk) { + // @ts-expect-error + window.Clerk("click", 1); -(async () => { - if (!window.Clerk) { - return; - } + // @ts-expect-error + window.Clerk("call", "invalid-endpoint"); - // $ExpectType ClerkResponseSearchPredictive - const response = await window.Clerk("call", "search/predictive", { - query: "predictive", + // Test basic API calls + window.Clerk("call", "search/predictive", { + key: "test-key", + query: "test", limit: 5, + }, (response) => { + response.result; // $ExpectType (string | number)[] + response.query; // $ExpectType string + // @ts-expect-error + response.results; }); - // @ts-expect-error - response.results; + // Test config + window.Clerk("config", { + key: "test-key", + visitor: "auto", + }); - // $ExpectType number[] - response.result; + // Test cart operations + window.Clerk("cart", "add", "product-123"); - const searchResponse = await window.Clerk("call", "search/search", { - query: "test", - limit: 10, + // Test event handling + window.Clerk("on", "rendered", (content) => { + content.element; // $ExpectType HTMLElement + content.more(5); }); - - // $ExpectType string - searchResponse.query; -}); +} diff --git a/types/clerk.io/index.d.ts b/types/clerk.io/index.d.ts index 8e6bc0ecae3340..1ddc5d639aae1f 100644 --- a/types/clerk.io/index.d.ts +++ b/types/clerk.io/index.d.ts @@ -1,227 +1,217 @@ -import { Optional } from "./types/optional"; +import * as Config from "./types/config"; +import * as Response from "./types/response"; -declare global { - const Clerk: Clerk; - - interface Window { - /** - * @link https://docs.clerk.io/docs - */ - Clerk?: Clerk; - } -} - -export interface Clerk { - ( - method: "call", - endpoint: T, - config?: ConfigType, - ): Promise>; - (method: "click", attribute: string): void; -} - -export interface ClerkProductAttributes { - age: number; - categories: number[]; - created_at: number; - description: string; - handle: string; - id: number; - image: string; - images: string[]; - name: string; - on_sale: boolean; - price: number; - price_min: number; - price_max: number; - published: boolean; - sku: string[]; - status: boolean; - stock: number; - tags: string[]; - type: string; - url: string; - variant_inventory_policy: Array<"deny" | "continue">; - variant_list_prices: number[]; - variant_names: string[]; - variant_prices: number[]; - variant_stocks: number[]; - variant_weight: number[]; - variant_weight_unit: string[]; - variants: string[]; - vendor: string; -} - -export interface ClerkCategory { - children: unknown[]; - description: string; - id: number; - image: string; - name: string; - parent: unknown; - subcategories: unknown[]; - url: string; -} - -export interface ClerkPage { - id: number; - type: string; - title: string; - url: string; - created_at: number; - image: string; - tags: string[]; - text: string; -} - -export interface ClerkArticle extends ClerkPage { - author: string; - blog: string; -} - -export interface ClerkBaseConfig { - /** - * Limit amount of results - */ - limit: number; - - /** - * @description Required for tracking - */ - labels?: string[]; - - /** - * @link https://docs.clerk.io/docs/filters - */ - filter?: string; -} +export {}; -export interface ClerkFacets { - /** - * @description Facets are most known in searches to narrow down results to eg a single category, brand or price range but can be used with any API endpoint that takes the facets parameter. - * @link https://docs.clerk.io/docs/facets - */ - facets?: string[]; -} - -export interface ClerkConfigProducts extends ClerkBaseConfig { - products: Array; - attributes: Array; - offset?: number; - exclude?: string[]; -} - -export interface ClerkConfigSearch extends ClerkBaseConfig { - query: string; +export interface InitConfig { + key: string; + visitor?: "auto" | "persistent" | null | string; language?: string; + collect_email?: boolean; + formatters?: { + [key: string]: CallableFunction; + }; + globals?: { + [key: string]: unknown; + }; + debug?: { + enable?: boolean; + level?: "warn" | "log" | "error"; + collect?: boolean; + }; + + [key: string]: unknown; +} + +export type SearchEndpoints = Extract; +export type RecommendationsEndpoints = Extract; +export type ClerkEndpoints = keyof ConfigTypes; + +export type ClerkObject = Record; + +export interface ClerkErrorResponse { + status: string; + message: string; + type: string; } -export interface ClerkConfigSearchResults extends ClerkConfigSearch, ClerkFacets { - longtail?: boolean; - offset?: number; - order?: "asc" | "desc"; - orderby?: keyof ClerkProductAttributes; - attributes?: Array; -} - -export interface ClerkConfigSearchPages extends ClerkConfigSearch { - type?: "blog" | "page"; -} - -export interface ClerkConfigSearchPredictive extends ClerkConfigSearch, ClerkFacets { - exclude?: string[]; - attributes?: Array; +export interface ClerkContent { + more: (param: number) => void; + param: (param: string) => void; + element: HTMLElement; + id: string; } -export type ClerkEndpointsSearch = - | "search/search" - | "search/popular" - | "search/predictive" - | "search/categories" - | "search/pages" - | "search/suggestions"; - -export type ClerkEndpointsProducts = - | "recommendations/popular" - | "recommendations/trending" - | "recommendations/new" - | "recommendations/currently_watched" - | "recommendations/recently_bought" - | "recommendations/keywords" - | "recommendations/complementary" - | "recommendations/substituting"; - -export type ClerkEndpoints = ClerkEndpointsProducts | ClerkEndpointsSearch; - export interface ConfigTypes { - "search/search": ClerkConfigSearchResults; - "search/pages": ClerkConfigSearchPages; - "search/predictive": ClerkConfigSearchPredictive; - "search/categories": ClerkConfigSearch; - "search/suggestions": Omit; - - "recommendations/popular": Omit & ClerkFacets; - "recommendations/trending": ClerkConfigProducts & ClerkFacets; - "recommendations/new": Omit; - "recommendations/currently_watched": Omit; - "recommendations/recently_bought": Omit, "offset">; - "recommendations/keywords": Omit; - "recommendations/complementary": ClerkConfigProducts; - "recommendations/substituting": ClerkConfigProducts; -} - -export type ConfigType = T extends keyof ConfigTypes ? ConfigTypes[T] : never; + "search/search": Config.searchSearchConfig; + "search/predictive": Config.searchPredictiveConfig; + "search/suggestions": Config.searchSuggestionsConfig; + "search/categories": Config.searchCategoriesConfig; + "search/pages": Config.searchPagesConfig; + "search/popular": Config.searchPopularConfig; + "recommendations/popular": Config.recommendationsPopularConfig; + "recommendations/trending": Config.recommendationsTrendingConfig; + "recommendations/new": Config.recommendationsNewConfig; + "recommendations/currently_watched": Config.recommendationsCurrentlyWatchedConfig; + "recommendations/recently_bought": Config.recommendationsRecentlyBoughtConfig; + "recommendations/keywords": Config.recommendationsKeywordsConfig; + "recommendations/complementary": Config.recommendationsComplementaryConfig; + "recommendations/substituting": Config.recommendationsSubstitutingConfig; + "recommendations/most_sold_with": Config.recommendationsMostSoldWithConfig; + "recommendations/category/popular": Config.recommendationsCategoryPopularConfig; + "recommendations/category/trending": Config.recommendationsCategoryTrendingConfig; + "recommendations/category/new": Config.recommendationsCategoryNewConfig; + "recommendations/category/popular_subcategories": Config.recommendationsCategoryPopularSubcategoriesConfig; + "recommendations/visitor/history": Config.recommendationsVisitorHistoryConfig; + "recommendations/visitor/complementary": Config.recommendationsVisitorComplementaryConfig; + "recommendations/visitor/substituting": Config.recommendationsVisitorSubstitutingConfig; + "recommendations/customer/history": Config.recommendationsCustomerHistoryConfig; + "recommendations/customer/complementary": Config.recommendationsCustomerComplementaryConfig; + "recommendations/customer/substituting": Config.recommendationsCustomerSubstitutingConfig; + "recommendations/page/substituting": Config.recommendationsPageSubstitutingConfig; + "recommendations/page/product": Config.recommendationsPageProductConfig; + "recommendations/page/category": Config.recommendationsPageCategoryConfig; + "recommendations/page/related_products": Config.recommendationsPageRelatedProductsConfig; + "recommendations/page/related_categories": Config.recommendationsPageRelatedCategoriesConfig; +} + +export interface ResponseTypes { + "search/search": Response.searchSearchResponse; + "search/predictive": Response.searchPredictiveResponse; + "search/suggestions": Response.searchSuggestionsResponse; + "search/categories": Response.searchCategoriesResponse; + "search/pages": Response.searchPagesResponse; + "search/popular": Response.searchPopularResponse; + "recommendations/popular": Response.recommendationsPopularResponse; + "recommendations/trending": Response.recommendationsTrendingResponse; + "recommendations/new": Response.recommendationsNewResponse; + "recommendations/currently_watched": Response.recommendationsCurrentlyWatchedResponse; + "recommendations/recently_bought": Response.recommendationsRecentlyBoughtResponse; + "recommendations/keywords": Response.recommendationsKeywordsResponse; + "recommendations/complementary": Response.recommendationsComplementaryResponse; + "recommendations/substituting": Response.recommendationsSubstitutingResponse; + "recommendations/most_sold_with": Response.recommendationsMostSoldWithResponse; + "recommendations/category/popular": Response.recommendationsCategoryPopularResponse; + "recommendations/category/trending": Response.recommendationsCategoryTrendingResponse; + "recommendations/category/new": Response.recommendationsCategoryNewResponse; + "recommendations/category/popular_subcategories": Response.recommendationsCategoryPopularSubcategoriesResponse; + "recommendations/visitor/history": Response.recommendationsVisitorHistoryResponse; + "recommendations/visitor/complementary": Response.recommendationsVisitorComplementaryResponse; + "recommendations/visitor/substituting": Response.recommendationsVisitorSubstitutingResponse; + "recommendations/customer/history": Response.recommendationsCustomerHistoryResponse; + "recommendations/customer/complementary": Response.recommendationsCustomerComplementaryResponse; + "recommendations/customer/substituting": Response.recommendationsCustomerSubstitutingResponse; + "recommendations/page/substituting": Response.recommendationsPageSubstitutingResponse; + "recommendations/page/product": Response.recommendationsPageProductResponse; + "recommendations/page/category": Response.recommendationsPageCategoryResponse; + "recommendations/page/related_products": Response.recommendationsPageRelatedProductsResponse; + "recommendations/page/related_categories": Response.recommendationsPageRelatedCategoriesResponse; +} + +/** + * @see https://docs.clerk.io/docs/clerkjs-custom-api-calls + * @description Calls a Clerk.js endpoint + */ +export function Clerk( + method: "call", + endpoint: T, + config: ConfigTypes[T], + callback?: (response: ResponseTypes[T]) => void, + error?: (error: ClerkErrorResponse) => void, +): void; +/** + * @see https://docs.clerk.io/docs/clerkjs-configuration + */ +export function Clerk(method: "config", config: InitConfig): void; +/** + * @see https://docs.clerk.io/docs/clerkjs-shopping-cart#customising-add-to-cart-functionality + * @description Defines a custom callback for the cart updates + */ +export function Clerk(method: "config", config: string, callback: (...args: unknown[]) => void): void; +/** + * @see https://docs.clerk.io/docs/chat + * @description Similar to the shopping cart API, the Chat API allows you to configure hooks for chat events and perform various actions through simple commands + */ +export function Clerk(method: "chat", action: "open" | "close" | "toggle" | "clear" | "enable" | "disable"): void; +/** + * @see https://docs.clerk.io/docs/chat + * @description Displays toast notification with supplied arguments + */ +export function Clerk(method: "chat", action: "toast", text: string, emoji?: string): void; +/** + * @see https://docs.clerk.io/docs/chat + * @description Sends message as user or assistant + */ +export function Clerk(method: "chat", action: "user_message" | "assistant_message", text: string): void; +/** + * @see https://docs.clerk.io/docs/chat + * @description Listens to Chat events and adds a callback for specified event + */ +export function Clerk( + method: "chat", + action: "on", + event: "message" | "open" | "enable" | "support", + callback: () => void, +): void; +/** + * @see https://docs.clerk.io/docs/ui + * @description Displays a popup or slider UI element + */ +export function Clerk(method: "ui", ui: "popup" | "slider", css_selector: string, action?: "show" | "hide"): void; +export function Clerk( + method: "on", + event: "live_search_update" | "rendered" | "render" | "response" | "update" | "model", + callback: (content: ClerkContent, data?: any) => void, +): void; +export function Clerk( + method: "on", + event: "live_search_update" | "rendered" | "render" | "response" | "update" | "model", + css_selector: string, + callback: (content: ClerkContent, data: any) => void, +): void; +/** + * @description Load more results + * @see https://docs.clerk.io/docs/clerkjs-content + */ +export function Clerk(method: "content", selector: string, action: "more", number: number): void; +/** + * @description JavaScript interface for interacting with Clerk.js Content + * @see https://docs.clerk.io/docs/clerkjs-content + */ +export function Clerk( + method: "content", + selector: string, + config?: unknown, + content?: (content: ClerkContent) => void, +): void; +/** + * Clerk uses Shopping Cart tracking for two purposes: + * 1. Adding products to the cart through Clerk elements + * 2. Tracking the content of the cart for use in Abandon Cart emails + * + * @see https://docs.clerk.io/docs/clerkjs-shopping-cart + * @description Adds, sets, or removes an item from the shopping cart + */ +export function Clerk( + method: "cart", + action: "add" | "set" | "remove", + id: string | number | string[] | number[], +): void; +/** + * @see https://docs.clerk.io/docs/clerkjs-click-tracking + * @description Adds click tracking to elements with the data-clerk-product-id attribute + */ +export function Clerk(method: "click", selector: "*[data-clerk-product-id]" | string): void; +/** + * @description Product view tracking + */ +export function Clerk(method: "product", productId: string): void; -export interface ClerkBaseResponse { - status: "ok"; - result: number[]; -} - -export interface ClerkResponseProducts extends ClerkBaseResponse { - count: number; - product_data: ClerkProductAttributes[]; -} - -export interface ClerkResponseSearchCategory extends ClerkBaseResponse { - categories: ClerkCategory[]; -} - -export interface ClerkResponseSearchSuggestions extends Omit { - results: string[]; -} - -export interface ClerkResponseSearchPredictive extends ClerkResponseProducts { - hits: number; -} - -export interface ClerkResponseSearchPages extends Omit { - pages: Array; - results: Array; -} - -export interface ClerkResponseSearchPage extends ClerkBaseResponse { - count: number; - hits: number; - query: string; - product_data: ClerkProductAttributes[]; -} - -export interface ClerkResponseTypes { - "search/search": ClerkResponseSearchPage; - "search/pages": ClerkResponseSearchPages; - "search/predictive": ClerkResponseSearchPredictive; - "search/categories": ClerkResponseSearchCategory; - "search/suggestions": ClerkResponseSearchSuggestions; - - "recommendations/popular": ClerkResponseProducts; - "recommendations/trending": ClerkResponseProducts; - "recommendations/new": ClerkResponseProducts; - "recommendations/currently_watched": ClerkResponseProducts; - "recommendations/recently_bought": ClerkResponseProducts; - "recommendations/keywords": ClerkResponseProducts; - "recommendations/complementary": ClerkResponseProducts; - "recommendations/substituting": ClerkResponseProducts; +declare global { + interface Window { + /** + * @link https://docs.clerk.io/ + */ + Clerk?: typeof Clerk; + } } - -export type ClerkResponseType = T extends keyof ClerkResponseTypes ? ClerkResponseTypes[T] - : never; diff --git a/types/clerk.io/package.json b/types/clerk.io/package.json index 18e399f57b49f0..c7097da7507bd0 100644 --- a/types/clerk.io/package.json +++ b/types/clerk.io/package.json @@ -19,5 +19,5 @@ "projects": [ "https://docs.clerk.io/docs" ], - "version": "1.0.9999" + "version": "2.0.9999" } diff --git a/types/clerk.io/tsconfig.json b/types/clerk.io/tsconfig.json index 03aa6e6ca638b8..9a955be355cd1d 100644 --- a/types/clerk.io/tsconfig.json +++ b/types/clerk.io/tsconfig.json @@ -16,6 +16,6 @@ "files": [ "index.d.ts", "clerk.io-tests.ts", - "types/optional.ts" + "types/helpers.ts" ] } diff --git a/types/clerk.io/types/config.ts b/types/clerk.io/types/config.ts new file mode 100644 index 00000000000000..872be051b15dce --- /dev/null +++ b/types/clerk.io/types/config.ts @@ -0,0 +1,212 @@ +import type { IntRange } from "./helpers"; + +// Base types +interface BaseConfig { + key: string; + /** + * @description Required for tracking. Visitor ID for the given visitor. If auto, an anonymous ID is generated + */ + visitor?: "auto" | string; + /** + * @description The language used for finding results. If not provided, the language configured on the Store in my.clerk.io will be used. + */ + language?: string; + /** + * @description JSONP - Wraps the response as a function call with the name of the string + */ + callback?: string; + /** + * @description When `true`, the response will include a JSON dictionary of the various customisations made to the results shown by Synonyms, Customized Search, Merchandising etc + */ + debug?: boolean; +} + +type BaseLimitConfig = BaseConfig & { + limit: number; +}; + +type BaseSearchConfig = BaseLimitConfig & { + /** + * @description Required for tracking - A list of one or more text labels, used to track the labels performance in Analytics + */ + labels?: string[]; + /** + * @description Filters results based on the provided filter string + * @see https://docs.clerk.io/docs/filters + */ + filter?: string; + /** + * @description List of product IDs to exclude from the result + */ + exclude?: string[]; + /** + * @see https://docs.clerk.io/docs/product-metadata + */ + attributes?: string[]; +}; + +type BaseFacetedConfig = BaseSearchConfig & { + /** + * @description List of facets to be returned for the products in the result + * @see https://docs.clerk.io/docs/facets + */ + facets?: string[]; +}; + +// Search configs +export type searchSearchConfig = BaseFacetedConfig & { + query: string; + /** + * @description Should all products matching any word in the query be in the result + */ + longtail?: boolean; + offset?: number; + orderby?: string; + order?: "asc" | "desc"; +}; + +export type searchPredictiveConfig = BaseFacetedConfig & { + query: string; + limit: IntRange<1, 10>; +}; + +export type searchSuggestionsConfig = BaseConfig & { + query: string; + limit: IntRange<1, 10>; +}; + +export type searchCategoriesConfig = BaseConfig & { + query?: string; + limit: IntRange<1, 10>; +}; + +export type searchPagesConfig = BaseConfig & { + query: string; + limit: IntRange<1, 10>; + type?: string; +}; + +export type searchPopularConfig = BaseConfig & { + limit: IntRange<1, 10>; +}; + +// Recommendations configs +export type recommendationsPopularConfig = BaseFacetedConfig & { + offset?: number; + orderby?: string; + order?: "asc" | "desc"; +}; + +export type recommendationsTrendingConfig = BaseFacetedConfig & { + offset?: number; +}; + +export type recommendationsNewConfig = BaseSearchConfig; + +export type recommendationsCurrentlyWatchedConfig = BaseSearchConfig; + +export type recommendationsRecentlyBoughtConfig = BaseSearchConfig; + +export type recommendationsKeywordsConfig = BaseSearchConfig & { + keywords: string; +}; + +export type recommendationsComplementaryConfig = BaseSearchConfig & { + products: string[]; +}; + +export type recommendationsSubstitutingConfig = BaseSearchConfig & { + products: string[]; +}; + +export type recommendationsMostSoldWithConfig = BaseSearchConfig & { + products: string[]; +}; + +// Category endpoints +export type recommendationsCategoryPopularConfig = BaseFacetedConfig & { + category: string; + offset?: number; + orderby?: string; + order?: "asc" | "desc"; +}; + +export type recommendationsCategoryTrendingConfig = BaseFacetedConfig & { + category: string; + offset?: number; +}; + +export type recommendationsCategoryNewConfig = BaseSearchConfig & { + category: string; +}; + +export type recommendationsCategoryPopularSubcategoriesConfig = BaseSearchConfig & { + category: string; + offset?: number; + order?: "asc" | "desc"; +}; + +// Visitor endpoints +export type recommendationsVisitorHistoryConfig = BaseSearchConfig & { + email?: string; +}; + +export type recommendationsVisitorComplementaryConfig = BaseSearchConfig & { + email?: string; +}; + +export type recommendationsVisitorSubstitutingConfig = BaseSearchConfig & { + email?: string; +}; + +// Customer endpoints +export type recommendationsCustomerHistoryConfig = BaseSearchConfig & { + email: string; + customer?: string; +}; + +export type recommendationsCustomerComplementaryConfig = BaseSearchConfig & { + email: string; + customer?: string; +}; + +export type recommendationsCustomerSubstitutingConfig = BaseSearchConfig & { + email: string; + customer?: string; +}; + +// Page endpoints +export type recommendationsPageSubstitutingConfig = BaseConfig & { + page: string; + limit: number; + visitor: "auto" | string; + labels?: string[]; + type?: string; + attributes?: string[]; +}; + +export type recommendationsPageProductConfig = BaseConfig & { + page: string; + limit: number; + visitor: "auto" | string; + labels?: string[]; + attributes?: string[]; + type?: string; +}; + +export type recommendationsPageCategoryConfig = BaseConfig & { + category: string; + limit: number; + visitor: "auto" | string; + labels?: string[]; + attributes?: string[]; + type?: string; +}; + +export type recommendationsPageRelatedProductsConfig = BaseSearchConfig & { + page: string; +}; + +export type recommendationsPageRelatedCategoriesConfig = BaseSearchConfig & { + page: string; +}; diff --git a/types/clerk.io/types/helpers.ts b/types/clerk.io/types/helpers.ts new file mode 100644 index 00000000000000..b313213d33bd37 --- /dev/null +++ b/types/clerk.io/types/helpers.ts @@ -0,0 +1,8 @@ +import type { ClerkObject } from "clerk.io"; + +type Enumerate = Acc["length"] extends N ? Acc[number] + : Enumerate; + +export type IntRange = Exclude, Enumerate>; + +export type PickAttributes = Pick; diff --git a/types/clerk.io/types/optional.ts b/types/clerk.io/types/optional.ts deleted file mode 100644 index 35301044ff1adf..00000000000000 --- a/types/clerk.io/types/optional.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Util for making a list of items partials from a generic - */ -export type Optional = Pick, K> & Omit; diff --git a/types/clerk.io/types/response.ts b/types/clerk.io/types/response.ts new file mode 100644 index 00000000000000..efd73397e99d73 --- /dev/null +++ b/types/clerk.io/types/response.ts @@ -0,0 +1,115 @@ +import type { PickAttributes } from "./helpers"; + +// Base types +interface BaseResponse { + result: (string | number)[]; + status: string; + debug?: Record; +} + +type BaseProductResponse = BaseResponse & { + product_data?: PickAttributes[]; +}; + +type BaseCountedResponse = BaseProductResponse & { + count: number; + facets: unknown | null; +}; + +// Common types +interface Category { + children: number[]; + description: string; + id: number; + image: string | null; + name: string; + parent: number | null; + subcategories: number[]; + url: string; +} + +interface Page { + author: string | null; + blog?: string; + created_at: number; + id: number; + image?: string | null; + tags?: string[]; + preprocessed_text?: string; + text: string; + title: string; + type: string; + url: string; + [key: string]: unknown; +} + +// Search responses +export type searchSearchResponse = BaseCountedResponse; + +export type searchPredictiveResponse = BaseProductResponse & { + facets: unknown | null; + hits: number; + query: string; +}; + +export type searchSuggestionsResponse = BaseResponse; + +export type searchCategoriesResponse = BaseResponse & { + categories: Category[]; +}; + +export type searchPagesResponse = BaseResponse & { + pages: Page[]; + result: Page[]; +}; + +export type searchPopularResponse = BaseResponse; + +// Recommendations responses +export type recommendationsPopularResponse = BaseCountedResponse; +export type recommendationsTrendingResponse = BaseCountedResponse; +export type recommendationsNewResponse = BaseCountedResponse; +export type recommendationsCurrentlyWatchedResponse = BaseProductResponse; +export type recommendationsRecentlyBoughtResponse = BaseProductResponse; +export type recommendationsKeywordsResponse = BaseProductResponse; +export type recommendationsComplementaryResponse = BaseProductResponse; +export type recommendationsSubstitutingResponse = BaseProductResponse; +export type recommendationsMostSoldWithResponse = BaseCountedResponse; + +// Category endpoints +export type recommendationsCategoryPopularResponse = BaseCountedResponse; +export type recommendationsCategoryTrendingResponse = BaseProductResponse & { + count: number; + facets?: unknown | null; +}; +export type recommendationsCategoryNewResponse = BaseCountedResponse; +export type recommendationsCategoryPopularSubcategoriesResponse = BaseCountedResponse; + +// Visitor endpoints +export type recommendationsVisitorHistoryResponse = BaseProductResponse; +export type recommendationsVisitorComplementaryResponse = BaseProductResponse; +export type recommendationsVisitorSubstitutingResponse = BaseProductResponse; + +// Customer endpoints +export type recommendationsCustomerHistoryResponse = BaseProductResponse; +export type recommendationsCustomerComplementaryResponse = BaseProductResponse; +export type recommendationsCustomerSubstitutingResponse = BaseProductResponse; + +// Page endpoints +export type recommendationsPageSubstitutingResponse = BaseResponse & { + pages: Page[]; + product_data?: null[]; +}; + +export type recommendationsPageProductResponse = BaseProductResponse & { + pages: Page[]; +}; + +export type recommendationsPageCategoryResponse = BaseProductResponse & { + pages: Page[]; +}; + +export type recommendationsPageRelatedProductsResponse = BaseCountedResponse; +export type recommendationsPageRelatedCategoriesResponse = BaseCountedResponse & { + categories: Category[]; +};