UNPKG

@klevu/core

Version:

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

109 lines (108 loc) 5.03 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()); }); }; import { KlevuConfig } from "../../config.js"; import { post } from "../../connection/fetch.js"; import { KlevuTypeOfRequest } from "../../models/KlevuTypeOfRequest.js"; import { isBrowser } from "../../utils/isBrowser.js"; import { KlevuStorage } from "../../utils/storage.js"; const STORAGE_TS_KEY = "abtest-data-ts"; const STORAGE_KEY = "abtest-data"; const STORAGE_PERMANENT_KEY = "abtest-permanent-data"; const HALF_HOUR = 1800000; /** * Enables AB test functionality. This will make extra request to Klevu servers and it is recommended only if you wish to use A/B testing feature. * * Currently not supported in server side rendering. * * @category Modifier * @returns */ export function abTest() { return { klevuModifierId: "abtest", modifyAfter: (queries, func) => __awaiter(this, void 0, void 0, function* () { var _a, _b, _c; // A/B test is not supported in the serverside if (!isBrowser()) { return Array.from(queries); } const data = yield fetchAbTestInfo(); const permanent = JSON.parse((_a = KlevuStorage.getItem(STORAGE_PERMANENT_KEY)) !== null && _a !== void 0 ? _a : "[]"); if (!data) { throw new Error("Failed to fetch AB test data"); } // clean permanent data const newpermanent = []; for (const perm of permanent) { if (data.assigned.some((a) => a.abTestId === perm.abTestId && a.sourceId === perm.sourceId)) { newpermanent.push(perm); } } const copy = Array.from(queries); for (const q of copy) { if (q.typeOfRequest !== KlevuTypeOfRequest.CategoryNavigation) { throw new Error("abtest can only be applied to category navigation"); } const path = (_c = (_b = q.settings) === null || _b === void 0 ? void 0 : _b.query) === null || _c === void 0 ? void 0 : _c.categoryPath; if (!path) { throw new Error("missing category path from abtest"); } const perm = newpermanent.find((a) => a.sourceId.toLocaleLowerCase() === path.toLocaleLowerCase()); if (!func.params) { func.params = {}; } if (perm) { q.abTestId = perm.abTestId; q.abTestVariantId = perm.abTestVariantId; func.params.abtest = perm; continue; } const test = data.assigned.find((a) => a.sourceId.toLocaleLowerCase() === path.toLocaleLowerCase()); if (!test) { continue; } if (!newpermanent.some((a) => a.abTestId === test.abTestId && a.sourceId === test.sourceId)) { newpermanent.push(test); post(`https://api.ksearchnet.com/abtest/public/usage/${KlevuConfig.getDefault().apiKey}`, test, true); } q.abTestId = test.abTestId; q.abTestVariantId = test.abTestVariantId; func.params.abtest = test; } KlevuStorage.setItem(STORAGE_PERMANENT_KEY, JSON.stringify(newpermanent)); return copy; }), }; } /** * This function never wait for result if there is one in cache. Returns new results on next time. * * @returns */ function fetchAbTestInfo() { return __awaiter(this, void 0, void 0, function* () { const ts = KlevuStorage.getItem(STORAGE_TS_KEY); const res = KlevuStorage.getItem(STORAGE_KEY); const fetch = () => __awaiter(this, void 0, void 0, function* () { const data = yield post(`https://api.ksearchnet.com/abtest/public/allocation/${KlevuConfig.getDefault().apiKey}/`, {}); KlevuStorage.setItem(STORAGE_TS_KEY, new Date().getTime().toString()); KlevuStorage.setItem(STORAGE_KEY, JSON.stringify(data)); return data; }); if (res && ts) { if (new Date().getTime() - parseInt(ts, 10) > HALF_HOUR) { // do not wait fetch(); } return JSON.parse(res); } return fetch(); }); }