UNPKG

@klevu/core

Version:

Typescript SDK that simplifies development on Klevu backend. Klevu provides advanced AI-powered search and discovery solutions for online retailers.

305 lines (304 loc) 14 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _KlevuResponseQueryObject_instances, _KlevuResponseQueryObject_initRedirects, _KlevuResponseQueryObject_initEventFunctions; import { KlevuEvents } from "../events/KlevuEvents.js"; import { applyFilterWithManager } from "../modifiers/index.js"; import { extractActiveFilters } from "../utils/extractActiveFilters.js"; import { KlevuFetch, removeListFilters } from "./klevuFetch.js"; import { getAnnotationsForProduct } from "./resultHelpers/getAnnotationsForProduct.js"; import { getBanners } from "./resultHelpers/getBanners.js"; import { getRedirects } from "./resultHelpers/getRedirects.js"; /** * Result object for each query. A storage for results. Can be used to fetch more data, send events etc. */ export class KlevuResponseQueryObject { constructor(responseObject, query, func) { _KlevuResponseQueryObject_instances.add(this); /** * Hooks that can be used to listen for events */ this.hooks = []; this.responseObject = responseObject; this.query = query; this.func = func; __classPrivateFieldGet(this, _KlevuResponseQueryObject_instances, "m", _KlevuResponseQueryObject_initEventFunctions).call(this); __classPrivateFieldGet(this, _KlevuResponseQueryObject_instances, "m", _KlevuResponseQueryObject_initRedirects).call(this); } /** * All filters related to this query */ get filters() { return this.query.filters; } /** * Id if the query */ get id() { return this.query.id; } /** * Meta data of the query */ get meta() { return this.query.meta; } /** * Records of the query */ get records() { return this.query.records; } /** * Special parameters that are saved to query */ get functionParams() { return this.func.params; } /** * Fetches page of results. If pageIndex is not defined it will fetch next page. * * @param params * @returns */ getPage(params) { var _a, _b, _c, _d; return __awaiter(this, void 0, void 0, function* () { const newFunc = Object.assign({}, this.func); const prevQueryResponse = this.query; if (!newFunc.queries) { return undefined; } for (let i = 0; i < newFunc.queries.length; i++) { const prevQuery = newFunc.queries[i]; if (!prevQuery.settings) { prevQuery.settings = {}; } if ((params === null || params === void 0 ? void 0 : params.pageIndex) !== undefined) { prevQuery.settings.offset = prevQueryResponse.meta.noOfResults * params.pageIndex; } else { prevQuery.settings.offset = prevQueryResponse.meta.noOfResults + prevQueryResponse.meta.offset; } prevQuery.settings.limit = (_c = (_a = params === null || params === void 0 ? void 0 : params.limit) !== null && _a !== void 0 ? _a : (_b = prevQuery.settings) === null || _b === void 0 ? void 0 : _b.limit) !== null && _c !== void 0 ? _c : 5; newFunc.queries[i] = prevQuery; } // add previous filters with manager if (params === null || params === void 0 ? void 0 : params.filterManager) { if (!newFunc.modifiers) { newFunc.modifiers = []; } newFunc.modifiers.push(applyFilterWithManager(params.filterManager)); } newFunc.previousResultRecords = [ ...((_d = this.func.previousResultRecords) !== null && _d !== void 0 ? _d : []), ...prevQueryResponse.records, ]; return yield KlevuFetch(removeListFilters(newFunc, prevQueryResponse)); }); } /** * * @returns true if there are more pages to fetch */ hasNextPage() { return (this.query.meta.totalResultsFound > this.query.meta.offset + this.query.meta.noOfResults); } /** * * @returns total number of pages */ getTotalPages() { return Math.ceil(this.query.meta.totalResultsFound / this.query.meta.offset); } annotationsById(productId, languageCode) { return getAnnotationsForProduct(this.query, productId, languageCode); } /** * @returns List of banners that were received for this query * @param params in case of search query you need to specify location of search */ getBanners(params = {}) { return __awaiter(this, void 0, void 0, function* () { return getBanners(this, params.searchType); }); } /** * @returns List of params used in the query and the metadata that was generated during * the query. This is useful for example to fetching KMC metadata that was received * for recommendations query. */ getQueryParameters() { return this.func.params; } } _KlevuResponseQueryObject_instances = new WeakSet(), _KlevuResponseQueryObject_initRedirects = function _KlevuResponseQueryObject_initRedirects() { if (this.func.klevuFunctionId === "search") { this.getRedirects = () => { var _a; if (!((_a = this.func.params) === null || _a === void 0 ? void 0 : _a.term)) { return Promise.resolve([]); } return getRedirects(this.func.params.term); }; } }, _KlevuResponseQueryObject_initEventFunctions = function _KlevuResponseQueryObject_initEventFunctions() { var _a, _b, _c; switch ((_a = this.func) === null || _a === void 0 ? void 0 : _a.klevuFunctionId) { case "search": { this.searchClickEvent = function ({ productId, variantId, autoSendViewEvent = true, override, }) { var _a, _b, _c; if (!this.func) { return; } if (autoSendViewEvent && !((_a = this.func.params) === null || _a === void 0 ? void 0 : _a.searchSendEventSent)) { KlevuEvents.search({ term: this.query.meta.searchedTerm, totalResults: this.query.meta.noOfResults, typeOfSearch: this.query.meta.typeOfSearch, activeFilters: extractActiveFilters(this.query), override, tags: this.query.meta.tags, }); if (!this.func.params) { this.func.params = {}; } this.func.params.searchSendEventSent = true; } const record = [ ...this.query.records, ...((_b = this.func.previousResultRecords) !== null && _b !== void 0 ? _b : []), ].find((r) => r.id === productId); if (!record) { throw new Error(`KlevuEvents: Given "${productId}" doesn't exists in this.querys`); } KlevuEvents.searchProductClick({ product: record, searchTerm: this.query.meta.searchedTerm, variantId, tags: this.query.meta.tags, }); for (const hook of (_c = this.hooks) !== null && _c !== void 0 ? _c : []) { hook({ type: "search", productId, variantId }); } }; break; } case "categoryMerchandising": { this.categoryMerchandisingClickEvent = function ({ productId, categoryTitle, variantId, override, }) { var _a, _b, _c, _d, _e, _f; if (!this.func) { return; } const record = [ ...this.query.records, ...((_a = this.func.previousResultRecords) !== null && _a !== void 0 ? _a : []), ].find((r) => r.id === productId); if (!record) { throw new Error(`KlevuEvents: Given "${productId}" doesn't exists in this.querys`); } const index = this.query.records.findIndex((r) => r.id === productId); const q = (_b = this.func.queries) === null || _b === void 0 ? void 0 : _b.find((q) => { var _a, _b; return Boolean((_b = (_a = q.settings) === null || _a === void 0 ? void 0 : _a.query) === null || _b === void 0 ? void 0 : _b.categoryPath); }); let abTestId, abTestVariantId; if (!this.func.params) { this.func.params = {}; } if (this.func.params.abtest) { abTestId = this.func.params.abtest.abTestId; abTestVariantId = this.func.params.abtest.abTestVariantId; } KlevuEvents.categoryMerchandisingProductClick({ product: record, categoryTitle, klevuCategory: (_e = (_d = (_c = q === null || q === void 0 ? void 0 : q.settings) === null || _c === void 0 ? void 0 : _c.query) === null || _d === void 0 ? void 0 : _d.categoryPath) !== null && _e !== void 0 ? _e : "unknown", variantId, productPosition: (this.query.meta.offset || 0) + index + 1, abTestId, abTestVariantId, activeFilters: extractActiveFilters(this.query), override, }); for (const hook of (_f = this.hooks) !== null && _f !== void 0 ? _f : []) { hook({ type: "categoryMerchandising", productId, variantId }); } }; break; } case "kmcRecommendation": { if (!((_b = this.func.params) === null || _b === void 0 ? void 0 : _b.kmcConfig)) { break; } const config = (_c = this.func.params) === null || _c === void 0 ? void 0 : _c.kmcConfig; if (config.metadata.action === "HIDE_RECOMMENDATION") { break; } if (config.metadata.action === "STATIC_CONTENT") { if (!config.staticContent) { break; } this.recommendationBannerClickEvent = function ({ resolution }) { var _a; if (!config.staticContent || config.staticContent.length === 0) { return; } const image = (_a = config.staticContent[0].image.find((image) => image.resolution === resolution)) !== null && _a !== void 0 ? _a : config.staticContent[0].image[0]; if (!image) { return; } KlevuEvents.recommendationClick({ recommendationMetadata: config.metadata, bannerInfo: { resolution, index: 1, banner_alt_tag: image.altTag, banner_image_url: image.url, content_type: "image", }, }); }; break; } this.recommendationClickEvent = function ({ productId, variantId, override, }) { var _a, _b; if (!this.func) { return; } const record = [ ...this.query.records, ...((_a = this.func.previousResultRecords) !== null && _a !== void 0 ? _a : []), ].find((r) => r.id === productId); if (!record) { throw new Error(`KlevuEvents: Given "${productId}" doesn't exists in this.querys`); } if (!config) { throw new Error("KlevuEvents: Recommendation kmcConfig not available"); } const index = this.query.records.findIndex((r) => r.id === productId); KlevuEvents.recommendationClick({ recommendationMetadata: config.metadata, product: record, productIndexInList: index + 1, variantId, override, }); for (const hook of (_b = this.hooks) !== null && _b !== void 0 ? _b : []) { hook({ type: "recommendation", productId, variantId }); } }; } } };