Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,16 @@ callbackFn = function (response) {
client.putSentimentClick('conversation_id', 'sentiment_value');
```

## POST API
:exclamation: POST API is not fully supported. If you need to use some methods in the library, please contact our support.

#### Fetch AI answers

```js
// default method: "GET"
client.setApiMethod('POST');
```

## Indexing API

With the Indexing API, you can fetch, create, update, and delete single documents or batches of
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "addsearch-js-client",
"version": "1.0.5",
"version": "1.1.0",
"description": "AddSearch API JavaScript client",
"repository": {
"type": "git",
Expand Down
186 changes: 151 additions & 35 deletions src/apifetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'es6-promise/auto';
import { apiInstance, RESPONSE_BAD_REQUEST, RESPONSE_SERVER_ERROR } from './api';
import { Settings } from './settings';
import { AxiosResponse } from 'axios';
import { isEmptyObject } from './util';

interface RecommendOptions {
type: 'RELATED_ITEMS' | 'FREQUENTLY_BOUGHT_TOGETHER';
Expand Down Expand Up @@ -121,6 +122,7 @@ const executeApiFetch: ExecuteApiFetch = function (

let keyword = '';
let queryParamsString = '';
let requestPayloadObject = {};

// API Path (eq. /search, /suggest, /autocomplete/document-field)
let apiEndpoint: string | null = null;
Expand Down Expand Up @@ -155,6 +157,7 @@ const executeApiFetch: ExecuteApiFetch = function (
}
}

// GET Parameters
queryParamsString =
settingToQueryParam(settings?.lang, 'lang') +
settingToQueryParam(fuzzy, 'fuzzy') +
Expand All @@ -176,8 +179,37 @@ const executeApiFetch: ExecuteApiFetch = function (
settingToQueryParam(settings?.searchOperator, 'defaultOperator') +
settingToQueryParam(settings?.analyticsTag, 'analyticsTag');

// POST Parameters

requestPayloadObject = {
...requestPayloadObject,
language: settings?.lang,
fuzzy: fuzzy !== true && fuzzy !== false ? fuzzy : JSON.stringify(fuzzy),
collectAnalytics: settings?.collectAnalytics,
postfixWildcard: settings?.postfixWildcard,
categories: settings?.categories ? settings?.categories.split(',') : undefined,
priceFromCents: settings?.priceFromCents ? parseFloat(settings?.priceFromCents) : undefined,
priceToCents: settings?.priceToCents ? parseFloat(settings?.priceToCents) : undefined,
dateFrom: settings?.dateFrom,
dateTo: settings?.dateTo,
paging: {
page: settings?.paging.page ?? 1,
pageSize: settings?.paging.pageSize ?? 10,
shuffleAndLimitTo: settings?.shuffleAndLimitTo ?? undefined,
sortByField: settings?.paging.sortBy,
sortOrder: settings?.paging.sortOrder
},
jwt: settings?.jwt,
resultType: settings?.resultType,
userToken: settings?.userToken ?? undefined,
numFacets: settings?.numFacets,
cacheResponseWithTtlSeconds: settings?.cacheResponseTime ?? undefined,
defaultOperator: settings?.searchOperator ?? undefined,
analyticsTag: settings?.analyticsTag
};

// Add sortBy and sortOrder
if (Array.isArray(settings?.paging.sortBy)) {
if (Array.isArray(settings?.paging.sortBy) && settings?.paging.sortBy.length > 1) {
settings?.paging.sortBy.forEach(function (value, index) {
queryParamsString =
queryParamsString +
Expand All @@ -193,16 +225,34 @@ const executeApiFetch: ExecuteApiFetch = function (

// Add custom field filters
if (settings?.customFieldFilters) {
const customFieldFiltersValues: any = {};
for (let i = 0; i < settings?.customFieldFilters.length; i++) {
queryParamsString = queryParamsString + '&customField=' + settings?.customFieldFilters[i];

const decodedCustomFieldFilter = decodeURIComponent(settings?.customFieldFilters[i]);
const customFieldFilterPair = decodedCustomFieldFilter.split('=');
const customFieldName = customFieldFilterPair[0];
const customFieldValue = customFieldFilterPair[1];
customFieldFiltersValues[customFieldName] = customFieldValue;
}

requestPayloadObject = {
...requestPayloadObject,
customField: isEmptyObject(customFieldFiltersValues) ? undefined : customFieldFiltersValues
};
}

// Add facet fields
if (settings?.facetFields) {
const facetFieldsValues: string[] = [];
for (let i = 0; i < settings?.facetFields.length; i++) {
queryParamsString = queryParamsString + '&facet=' + settings?.facetFields[i];
facetFieldsValues.push(settings?.facetFields[i]);
}
requestPayloadObject = {
...requestPayloadObject,
facet: facetFieldsValues.length > 0 ? facetFieldsValues : undefined
};
}

// Range facets
Expand All @@ -211,6 +261,10 @@ const executeApiFetch: ExecuteApiFetch = function (
queryParamsString +
'&rangeFacets=' +
encodeURIComponent(JSON.stringify(settings?.rangeFacets));
requestPayloadObject = {
...requestPayloadObject,
rangeFacets: settings?.rangeFacets
};
}

// Hierarchical facets
Expand All @@ -219,32 +273,56 @@ const executeApiFetch: ExecuteApiFetch = function (
queryParamsString +
'&hierarchicalFacets=' +
encodeURIComponent(JSON.stringify(settings?.hierarchicalFacetSetting));
requestPayloadObject = {
...requestPayloadObject,
hierarchicalFacets: settings?.hierarchicalFacetSetting
};
}

// Stats fields
if (settings?.statsFields) {
const statsFieldsValues: string[] = [];
for (let i = 0; i < settings?.statsFields.length; i++) {
queryParamsString = queryParamsString + '&fieldStat=' + settings?.statsFields[i];
statsFieldsValues.push(settings?.statsFields[i]);
}
requestPayloadObject = {
...requestPayloadObject,
statsFields: statsFieldsValues
};
}

// Personalization events
if (settings?.personalizationEvents && Array.isArray(settings?.personalizationEvents)) {
const personalizationEventsValues: any[] = [];
for (let i = 0; i < settings?.personalizationEvents.length; i++) {
const obj = settings?.personalizationEvents[i];
const key = Object.keys(obj)[0];
queryParamsString =
queryParamsString + '&personalizationEvent=' + encodeURIComponent(key + '=' + obj[key]);
personalizationEventsValues.push(obj);
}
requestPayloadObject = {
...requestPayloadObject,
personalizationEvents: personalizationEventsValues
};
}

// Filter object
if (customFilterObject) {
queryParamsString =
queryParamsString + '&filter=' + encodeURIComponent(JSON.stringify(customFilterObject));
requestPayloadObject = {
...requestPayloadObject,
filter: customFilterObject
};
} else if (settings?.filterObject) {
queryParamsString =
queryParamsString + '&filter=' + encodeURIComponent(JSON.stringify(settings?.filterObject));
requestPayloadObject = {
...requestPayloadObject,
filter: isEmptyObject(settings?.filterObject) ? undefined : settings?.filterObject
};
}

apiEndpoint =
Expand Down Expand Up @@ -295,6 +373,12 @@ const executeApiFetch: ExecuteApiFetch = function (
queryParamsString =
settingToQueryParam(settings?.suggestionsSize, 'size') +
settingToQueryParam(settings?.lang, 'language');
requestPayloadObject = {
...requestPayloadObject,
size: settings?.suggestionsSize,
language: settings?.lang
};

keyword = settings?.suggestionsPrefix as string;
apiEndpoint =
'https://' +
Expand Down Expand Up @@ -325,6 +409,12 @@ const executeApiFetch: ExecuteApiFetch = function (
'?term=' +
keyword +
queryParamsString;

requestPayloadObject = {
...requestPayloadObject,
source: settings?.autocomplete.field,
size: settings?.autocomplete.size
};
} else if (type === 'recommend') {
if (recommendOptions?.type === 'RELATED_ITEMS') {
queryParamsString = settingToQueryParam(recommendOptions.itemId, 'itemId');
Expand All @@ -335,6 +425,12 @@ const executeApiFetch: ExecuteApiFetch = function (
recommendOptions.blockId +
'?' +
queryParamsString;

requestPayloadObject = {
...requestPayloadObject,
itemId: recommendOptions.itemId ?? undefined,
blockId: recommendOptions.blockId
};
} else if (recommendOptions?.type === 'FREQUENTLY_BOUGHT_TOGETHER') {
queryParamsString = settingToQueryParam(recommendOptions.itemId, 'itemId');
apiPath =
Expand All @@ -343,49 +439,69 @@ const executeApiFetch: ExecuteApiFetch = function (
'?configurationKey=' +
recommendOptions.configurationKey +
queryParamsString;

requestPayloadObject = {
...requestPayloadObject,
itemId: recommendOptions.itemId ?? undefined,
configurationKey: recommendOptions.configurationKey
};
}
apiEndpoint = 'https://' + apiHostname + '/v1/' + apiPath;
}

// Handle API response for all types except ai-answers
if (type !== 'ai-answers') {
apiInstance
.get(apiEndpoint as string)
.then(function (response: AxiosResponse<GenericApiResponse>) {
const json = response.data;

// Search again with fuzzy=true if no hits
if (
type === 'search' &&
settings?.fuzzy === 'retry' &&
json.total_hits === 0 &&
fuzzyRetry !== true
) {
executeApiFetch(apiHostname, sitekey, type, settings, cb, true);
const handleApiResponse = function (response: AxiosResponse<GenericApiResponse>) {
const json = response.data;

// Search again with fuzzy=true if no hits
if (
type === 'search' &&
settings?.fuzzy === 'retry' &&
json.total_hits === 0 &&
fuzzyRetry !== true
) {
executeApiFetch(apiHostname, sitekey, type, settings, cb, true);
} else {
// Cap fuzzy results to one page as quality decreases quickly
if (fuzzyRetry === true) {
json.total_hits = Math.min(
json.total_hits ?? Infinity,
settings?.paging?.pageSize ?? Infinity
);
}
// Fuzzy not "retry" OR fuzzyRetry already returning
else {
// Cap fuzzy results to one page as quality decreases quickly
if (fuzzyRetry === true) {
json.total_hits = Math.min(
json.total_hits ?? Infinity,
settings?.paging?.pageSize ?? Infinity
);
}

// Callback
cb(json);
// Callback
cb(json);
}
};

const handleApiError = function (error: any) {
console.error(error);
cb({
error: {
response: RESPONSE_SERVER_ERROR,
message: 'invalid server response'
}
})
.catch(function (error) {
console.error(error);

cb({
error: {
response: RESPONSE_SERVER_ERROR,
message: 'invalid server response'
}
});
});
};

if (settings?.apiMethod === 'POST' && ['search', 'suggest', 'autocomplete'].includes(type)) {
apiEndpoint = 'https://' + apiHostname + '/v1/' + apiPath + '/' + sitekey;
requestPayloadObject = {
term: decodeURIComponent(keyword),
...requestPayloadObject
};
apiInstance
.post(apiEndpoint, requestPayloadObject)
.then(handleApiResponse)
.catch(handleApiError);
} else {
apiInstance
.get(apiEndpoint as string)
.then(handleApiResponse)
.catch(handleApiError);
}
}
};

Expand Down
Loading