Skip to content

Commit 53fd792

Browse files
committed
Merge branch 'master' into webpack-upgrade-and-eslint
# Conflicts: # dist/addsearch-js-client.min.js # package-lock.json # package.json # src/index.js
2 parents 73934ef + 6854e68 commit 53fd792

File tree

8 files changed

+1509
-982
lines changed

8 files changed

+1509
-982
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,17 @@ is handy for applications like range filtering.
265265
client.addStatsField('custom_fields.price');
266266
```
267267

268+
### Recommendations
269+
#### Frequently bought together items
270+
Get frequently bought together items, given "configurationKey" and "itemId"
271+
```js
272+
// fetch frequently bought together items
273+
client.recommendations({
274+
configurationKey: "config1",
275+
itemId: "1065921"
276+
});
277+
```
278+
268279
### Search analytics
269280
#### Send search event to analytics
270281
When search is executed, send the event to your AddSearch Analytics Dashboard.

dist/addsearch-js-client.min.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 1398 additions & 919 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "addsearch-js-client",
3-
"version": "0.6.6",
3+
"version": "0.7.1",
44
"description": "AddSearch API JavaScript client",
55
"main": "index.js",
66
"jsdelivr": "./dist/addsearch-js-client.min.js",
@@ -36,8 +36,8 @@
3636
],
3737
"license": "MIT",
3838
"dependencies": {
39+
"axios": "^0.27.2",
3940
"es6-promise": "^4.2.8",
40-
"isomorphic-fetch": "^3.0.0",
4141
"js-base64": "^3.6.0"
4242
},
4343
"devDependencies": {
@@ -51,7 +51,6 @@
5151
"esm": "^3.2.25",
5252
"fetch-mock": "^9.11.0",
5353
"mocha": "^8.2.1",
54-
"node-fetch": "^2.6.7",
5554
"uglify-js": "^3.12.0",
5655
"webpack": "^5.72.0",
5756
"webpack-cli": "^3.3.12",

src/apifetch.js

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
'use strict';
22

33
require('es6-promise').polyfill();
4-
require('isomorphic-fetch');
4+
const axios = require('axios').default;
55

66
/**
77
* Fetch search results of search suggestions from the Addsearch API
88
*/
9-
var executeApiFetch = function(apiHostname, sitekey, type, settings, cb, fuzzyRetry, customFilterObject) {
9+
var executeApiFetch = function(apiHostname, sitekey, type, settings, cb, fuzzyRetry, customFilterObject, recommendOptions) {
1010

1111
const RESPONSE_BAD_REQUEST = 400;
1212
const RESPONSE_SERVER_ERROR = 500;
@@ -20,7 +20,7 @@ var executeApiFetch = function(apiHostname, sitekey, type, settings, cb, fuzzyRe
2020

2121

2222
// Validate query type
23-
if (type !== 'search' && type !== 'suggest' && type !== 'autocomplete') {
23+
if (type !== 'search' && type !== 'suggest' && type !== 'autocomplete' && type !== 'recommend') {
2424
cb({error: {response: RESPONSE_BAD_REQUEST, message: 'invalid query type'}});
2525
return;
2626
}
@@ -30,6 +30,7 @@ var executeApiFetch = function(apiHostname, sitekey, type, settings, cb, fuzzyRe
3030
var qs = '';
3131

3232
// API Path (eq. /search, /suggest, /autocomplete/document-field)
33+
var api = null;
3334
var apiPath = null;
3435

3536
// Search
@@ -137,7 +138,8 @@ var executeApiFetch = function(apiHostname, sitekey, type, settings, cb, fuzzyRe
137138
// Suggest
138139
else if (type === 'suggest') {
139140
apiPath = type;
140-
qs = settingToQueryParam(settings.suggestionsSize, 'size');
141+
qs = settingToQueryParam(settings.suggestionsSize, 'size') +
142+
settingToQueryParam(settings.lang, 'lang');
141143
kw = settings.suggestionsPrefix;
142144
}
143145

@@ -149,36 +151,42 @@ var executeApiFetch = function(apiHostname, sitekey, type, settings, cb, fuzzyRe
149151
kw = settings.autocomplete.prefix;
150152
}
151153

154+
else if (type === 'recommend') {
155+
apiPath = 'recommendations';
156+
qs = settingToQueryParam(recommendOptions.itemId, 'itemId');
157+
}
152158

153159
// Execute API call
154-
fetch('https://' + apiHostname + '/v1/' + apiPath + '/' + sitekey + '?term=' + kw + qs)
155-
.then(function(response) {
156-
return response.json();
157-
}).then(function(json) {
160+
api = type === 'recommend' ?
161+
'https://' + apiHostname + '/v1/' + apiPath + '/' + sitekey + '?configurationKey=' + recommendOptions.configurationKey + qs :
162+
'https://' + apiHostname + '/v1/' + apiPath + '/' + sitekey + '?term=' + kw + qs;
158163

159-
// Search again with fuzzy=true if no hits
160-
if (type === 'search' && settings.fuzzy === 'retry' && json.total_hits === 0 && fuzzyRetry !== true) {
161-
executeApiFetch(apiHostname, sitekey, type, settings, cb, true);
162-
}
164+
axios.get(api)
165+
.then(function(response) {
166+
var json = response.data;
167+
// Search again with fuzzy=true if no hits
168+
if (type === 'search' && settings.fuzzy === 'retry' && json.total_hits === 0 && fuzzyRetry !== true) {
169+
executeApiFetch(apiHostname, sitekey, type, settings, cb, true);
170+
}
163171

164-
// Fuzzy not "retry" OR fuzzyRetry already returning
165-
else {
172+
// Fuzzy not "retry" OR fuzzyRetry already returning
173+
else {
166174

167-
// Cap fuzzy results to one page as quality decreases quickly
168-
if (fuzzyRetry === true) {
169-
var pageSize = settings.paging.pageSize;
170-
if (json.total_hits >= pageSize) {
171-
json.total_hits = pageSize;
175+
// Cap fuzzy results to one page as quality decreases quickly
176+
if (fuzzyRetry === true) {
177+
var pageSize = settings.paging.pageSize;
178+
if (json.total_hits >= pageSize) {
179+
json.total_hits = pageSize;
180+
}
172181
}
173-
}
174182

175-
// Callback
176-
cb(json);
177-
}
178-
179-
}).catch(function(ex) {
180-
console.log(ex);
181-
cb({error: {response: RESPONSE_SERVER_ERROR, message: 'invalid server response'}});
182-
});
183+
// Callback
184+
cb(json);
185+
}
186+
})
187+
.catch(function(ex) {
188+
console.log(ex);
189+
cb({error: {response: RESPONSE_SERVER_ERROR, message: 'invalid server response'}});
190+
});
183191
};
184192
module.exports = executeApiFetch;

src/index.js

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,38 @@ var client = function(sitekey, privatekey) {
103103
executeApiFetch(this.apiHostname, this.sitekey, 'search', settingsCloned, callback, null, customFilterObject);
104104
}
105105

106+
/**
107+
* Fetch Range Facets
108+
*/
109+
this.fetchRangeFacets = function(options, customFilterObject, callback) {
110+
var settingsCloned = Object.assign({}, this.settings.getSettings());
111+
112+
if (!settingsCloned.rangeFacets) {
113+
settingsCloned.rangeFacets = [];
114+
}
115+
settingsCloned.rangeFacets.push({
116+
field: options.field,
117+
ranges: options.ranges
118+
});
119+
executeApiFetch(this.apiHostname, this.sitekey, 'search', settingsCloned, callback, null, customFilterObject);
120+
}
121+
122+
/**
123+
* Fetch recommendations
124+
*
125+
* @param item
126+
*/
127+
this.recommendations = function(options, callback) {
128+
if (!options || !callback || !util.isFunction(callback)) {
129+
throw "Illegal recommendations parameters. Should be (options, callbackFunction)";
130+
}
131+
132+
if (!this.throttledSuggestionsFetch) {
133+
this.throttledSuggestionsFetch = throttle(this.settings.getSettings().throttleTimeMs, executeApiFetch);
134+
}
135+
this.throttledSuggestionsFetch(this.apiHostname, this.sitekey, 'recommend', null, callback, false, null, options);
136+
}
137+
106138
/**
107139
* Indexing API functions
108140
*/
@@ -182,19 +214,19 @@ var client = function(sitekey, privatekey) {
182214
numberOfResults: res.numberOfResults,
183215
analyticsTag: this.getSettings().analyticsTag
184216
};
185-
sendStats(this.apiHostname, this.sitekey, data);
217+
sendStats(this.apiHostname, this.sitekey, payload);
186218
}
187219

188220
else if (type === 'click') {
189-
let data = {
221+
var payload = {
190222
action: 'click',
191223
session: this.sessionId,
192224
keyword: keyword,
193225
docid: res.documentId,
194226
position: res.position,
195227
analyticsTag: this.getSettings().analyticsTag
196228
};
197-
sendStats(this.apiHostname, this.sitekey, data);
229+
sendStats(this.apiHostname, this.sitekey, payload);
198230
}
199231

200232
else {

src/indexingapi.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'use strict';
22

3-
require('isomorphic-fetch');
43
const util = require('./util');
54
const Promise = require('es6-promise').Promise;
5+
const axios = require('axios').default;
66

77
const getHeaders = function(sitekey, privatekey) {
88
return {
@@ -18,14 +18,13 @@ const getHeaders = function(sitekey, privatekey) {
1818
var getDocument = function(apiHostname, sitekey, privatekey, id) {
1919
const promise = new Promise((resolve, reject) => {
2020

21-
fetch('https://' + apiHostname + '/v2/indices/' + sitekey + '/documents/' + id,
21+
axios.get('https://' + apiHostname + '/v2/indices/' + sitekey + '/documents/' + id,
2222
{
23-
method: 'GET',
2423
headers: getHeaders(sitekey, privatekey)
2524
})
2625
.then((response) => {
2726
if (response.status == 200) {
28-
resolve(response.json());
27+
resolve(response.data);
2928
}
3029
else {
3130
reject({status: response.status, text: response.statusText});
@@ -44,14 +43,16 @@ var getDocument = function(apiHostname, sitekey, privatekey, id) {
4443
var saveDocument = function(apiHostname, sitekey, privatekey, document) {
4544

4645
// If the doc has id or url field, PUT instead of POST
46+
4747
const isPut = document.id || document.url;
4848

4949
const promise = new Promise((resolve, reject) => {
50-
fetch('https://' + apiHostname + '/v2/indices/' + sitekey + '/documents/',
50+
axios(
5151
{
52-
method: isPut ? 'PUT' : 'POST',
52+
url: 'https://' + apiHostname + '/v2/indices/' + sitekey + '/documents/',
53+
method: isPut ? 'put' : 'post',
5354
headers: getHeaders(sitekey, privatekey),
54-
body: JSON.stringify(document)
55+
data: document
5556
})
5657
.then((response) => {
5758
if (response.status == 202) {
@@ -61,8 +62,8 @@ var saveDocument = function(apiHostname, sitekey, privatekey, document) {
6162
reject({status: response.status, text: response.statusText});
6263
}
6364
}).catch((ex) => {
64-
reject({status: 400, text: ex});
65-
});
65+
reject({status: 400, text: ex});
66+
});
6667
});
6768

6869
return promise;
@@ -75,11 +76,12 @@ var saveDocument = function(apiHostname, sitekey, privatekey, document) {
7576
var saveDocumentsBatch = function(apiHostname, sitekey, privatekey, documents) {
7677

7778
const promise = new Promise((resolve, reject) => {
78-
fetch('https://' + apiHostname + '/v2/indices/' + sitekey + '/documents:batch',
79+
axios(
7980
{
80-
method: 'PUT',
81+
method: 'put',
82+
url: 'https://' + apiHostname + '/v2/indices/' + sitekey + '/documents:batch',
8183
headers: getHeaders(sitekey, privatekey),
82-
body: JSON.stringify(documents)
84+
data: documents
8385
})
8486
.then((response) => {
8587
if (response.status == 202) {
@@ -102,9 +104,8 @@ var saveDocumentsBatch = function(apiHostname, sitekey, privatekey, documents) {
102104
*/
103105
var deleteDocument = function(apiHostname, sitekey, privatekey, id) {
104106
const promise = new Promise((resolve, reject) => {
105-
fetch('https://' + apiHostname + '/v2/indices/' + sitekey + '/documents/' + id,
107+
axios.delete('https://' + apiHostname + '/v2/indices/' + sitekey + '/documents/' + id,
106108
{
107-
method: 'DELETE',
108109
headers: getHeaders(sitekey, privatekey)
109110
})
110111
.then((response) => {
@@ -128,11 +129,10 @@ var deleteDocument = function(apiHostname, sitekey, privatekey, id) {
128129
*/
129130
var deleteDocumentsBatch = function(apiHostname, sitekey, privatekey, batch) {
130131
const promise = new Promise((resolve, reject) => {
131-
fetch('https://' + apiHostname + '/v2/indices/' + sitekey + '/documents:batch',
132+
axios.delete('https://' + apiHostname + '/v2/indices/' + sitekey + '/documents:batch',
132133
{
133-
method: 'DELETE',
134134
headers: getHeaders(sitekey, privatekey),
135-
body: JSON.stringify(batch)
135+
data: batch
136136
})
137137
.then((response) => {
138138
if (response.status == 202) {

src/stats.js

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
11
'use strict';
22

33
require('es6-promise').polyfill();
4-
require('isomorphic-fetch');
4+
const axios = require('axios').default;
55

6-
var sendStats = function(apiHostname, sitekey, data) {
6+
var sendStats = function(apiHostname, sitekey, payload) {
77

88
// Beacon in browsers
99
if (typeof window !== 'undefined' && window.navigator && window.navigator.sendBeacon) {
10-
navigator.sendBeacon('https://' + apiHostname + '/v1/stats/' + sitekey + '/', JSON.stringify(data));
10+
navigator.sendBeacon('https://' + apiHostname + '/v1/stats/' + sitekey + '/', JSON.stringify(payload));
1111
}
1212

1313
// POST in node
1414
else {
15-
fetch('https://' + apiHostname + '/v1/stats/' + sitekey + '/', {
16-
method: 'POST',
17-
headers: {
18-
'Content-Type': 'text/plain',
19-
},
20-
body: JSON.stringify(data)
15+
axios.post('https://' + apiHostname + '/v1/stats/' + sitekey + '/', payload, {
16+
headers: {
17+
'Content-Type': 'text/plain',
18+
}
2119
});
2220
}
2321
};

0 commit comments

Comments
 (0)