Skip to content

Commit 4f644b6

Browse files
committed
[sc-11365] add types, setup linting
1 parent 0e2013a commit 4f644b6

26 files changed

+2067
-1345
lines changed

.eslintrc

+21-4
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,30 @@
44
"commonjs": true,
55
"es2021": true
66
},
7+
"parser": "@typescript-eslint/parser",
78
"parserOptions": {
8-
"ecmaVersion": "latest"
9+
"ecmaVersion": "latest",
10+
"sourceType": "module",
11+
"project": "./tsconfig.json"
912
},
10-
"extends": "eslint:recommended",
13+
"extends": [
14+
"eslint:recommended",
15+
"plugin:@typescript-eslint/recommended",
16+
"plugin:@typescript-eslint/recommended-requiring-type-checking",
17+
"plugin:prettier/recommended"
18+
],
19+
"plugins": ["@typescript-eslint"],
1120
"rules": {
1221
"no-eval": ["error"],
1322
"no-trailing-spaces": "error",
14-
"no-irregular-whitespace": "off"
15-
}
23+
"no-irregular-whitespace": "off",
24+
"@typescript-eslint/no-unused-vars": ["warn"],
25+
"@typescript-eslint/explicit-function-return-type": "off"
26+
},
27+
"ignorePatterns": [
28+
"dist/",
29+
"node_modules/",
30+
"webpack.config.js",
31+
"test/"
32+
]
1633
}

index.js

-3
This file was deleted.

index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Client from './src/index';
2+
export default Client;

package-lock.json

+661-197
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+14-3
Original file line numberDiff line numberDiff line change
@@ -30,39 +30,50 @@
3030
],
3131
"main": "index.js",
3232
"jsdelivr": "./dist/addsearch-js-client.min.js",
33-
"types": "index.d.ts",
33+
"types": "dist/types/index.d.ts",
3434
"files": [
3535
"dist",
3636
"index.d.ts",
3737
"src"
3838
],
3939
"scripts": {
4040
"build": "npm run test && ./node_modules/webpack-cli/bin/cli.js",
41+
"build:new": "webpack",
4142
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
4243
"test": "./node_modules/mocha/bin/mocha.js --recursive --require @babel/register",
43-
"watch": "./node_modules/webpack-cli/bin/cli.js --watch"
44+
"watch": "./node_modules/webpack-cli/bin/cli.js --watch",
45+
"lint": "eslint . --ext .ts,.js",
46+
"lint:fix": "eslint . --ext .ts,.js --fix",
47+
"lint:watch": "nodemon --exec 'npm run lint' --watch src --ext ts"
4448
},
4549
"dependencies": {
4650
"axios": "^1.7.2",
4751
"buffer": "^6.0.3",
4852
"es6-promise": "^4.2.8",
4953
"js-base64": "^3.6.0",
50-
"uuid": "^9.0.0"
54+
"uuid": "^11.0.3"
5155
},
5256
"devDependencies": {
5357
"@babel/cli": "^7.23.9",
5458
"@babel/core": "^7.23.9",
5559
"@babel/preset-env": "^7.23.9",
60+
"@babel/preset-typescript": "^7.26.0",
5661
"@babel/register": "^7.12.1",
62+
"@typescript-eslint/parser": "^8.18.1",
5763
"axios-mock-adapter": "^1.21.2",
5864
"babel-loader": "^9.1.2",
5965
"eslint": "^8.45.0",
66+
"eslint-config-prettier": "^9.1.0",
67+
"eslint-plugin-prettier": "^5.2.1",
6068
"eslint-webpack-plugin": "^3.1.1",
6169
"esm": "^3.2.25",
6270
"fetch-mock": "^12.1.0",
6371
"mocha": "^10.0.0",
72+
"nodemon": "^3.1.9",
6473
"prettier": "^3.3.3",
6574
"terser-webpack-plugin": "^5.3.1",
75+
"typescript": "^5.7.2",
76+
"typescript-eslint": "^8.18.1",
6677
"uglify-js": "^3.12.0",
6778
"webpack": "^5.76.1",
6879
"webpack-cli": "^4.10.0"

src/api.js

-35
This file was deleted.

src/api.ts

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import axios, { AxiosInstance, InternalAxiosRequestConfig } from 'axios';
2+
3+
const apiInstance: AxiosInstance = axios.create();
4+
const statsInstance: AxiosInstance = axios.create();
5+
const conversationalSearchInteractionsInstance: AxiosInstance = axios.create();
6+
7+
const RESPONSE_BAD_REQUEST = 400;
8+
const RESPONSE_SERVER_ERROR = 500;
9+
10+
export type RequestInterceptorCallback = (config: {
11+
url?: string;
12+
headers?: Record<string, string>;
13+
}) => Partial<InternalAxiosRequestConfig>;
14+
15+
type RequestType = 'searchApi' | 'statsApi';
16+
17+
const setRequestInterceptor = (
18+
callback: RequestInterceptorCallback,
19+
requestType: RequestType
20+
): void => {
21+
const axiosInstance = requestType === 'searchApi' ? apiInstance : statsInstance;
22+
23+
axiosInstance.interceptors.request.use(
24+
(config: InternalAxiosRequestConfig) => {
25+
const updatedConfig = callback({
26+
url: config.url,
27+
headers: config.headers as Record<string, string>
28+
});
29+
config = { ...config, ...updatedConfig };
30+
return config;
31+
},
32+
(error) => {
33+
return Promise.reject(new Error(JSON.stringify(error)));
34+
}
35+
);
36+
};
37+
38+
export {
39+
apiInstance,
40+
statsInstance,
41+
conversationalSearchInteractionsInstance,
42+
setRequestInterceptor,
43+
RESPONSE_BAD_REQUEST,
44+
RESPONSE_SERVER_ERROR
45+
};

src/apifetch.js renamed to src/apifetch.ts

+69-20
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,59 @@
1-
'use strict';
2-
require('es6-promise').polyfill();
3-
const apiInstance = require('./api').apiInstance;
4-
const RESPONSE_BAD_REQUEST = require('./api').RESPONSE_BAD_REQUEST;
5-
const RESPONSE_SERVER_ERROR = require('./api').RESPONSE_SERVER_ERROR;
1+
import 'es6-promise/auto';
2+
import { apiInstance, RESPONSE_BAD_REQUEST, RESPONSE_SERVER_ERROR } from './api';
3+
import { Settings } from './settings';
4+
import { AxiosResponse } from 'axios';
5+
6+
interface RecommendOptions {
7+
type: 'RELATED_ITEMS' | 'FREQUENTLY_BOUGHT_TOGETHER';
8+
itemId?: string;
9+
blockId?: string;
10+
configurationKey?: string;
11+
}
12+
13+
/* eslint-disable @typescript-eslint/no-explicit-any */
14+
export interface Callback {
15+
(response: any): void;
16+
}
17+
/* eslint-enable @typescript-eslint/no-explicit-any */
18+
19+
interface SourceDocuments {
20+
page: number;
21+
hits: Document[];
22+
total_hits: number;
23+
}
24+
25+
interface GenericApiResponse {
26+
total_hits?: number;
27+
}
28+
29+
interface ConversationsApiResponse {
30+
response: {
31+
conversation_id: string;
32+
answer: string;
33+
ids: string[];
34+
source_documents: SourceDocuments;
35+
};
36+
errors: string[];
37+
status: number;
38+
}
39+
40+
/* eslint-disable @typescript-eslint/no-explicit-any */
41+
export type ExecuteApiFetch = (
42+
apiHostname: string,
43+
sitekey: string,
44+
type: string,
45+
settings: Settings,
46+
cb: Callback,
47+
fuzzyRetry?: boolean,
48+
customFilterObject?: Record<string, any>,
49+
recommendOptions?: RecommendOptions
50+
) => void;
51+
/* eslint-enable @typescript-eslint/no-explicit-any */
652

753
/**
854
* Fetch search results of search suggestions from the Addsearch API
955
*/
10-
var executeApiFetch = function (
56+
const executeApiFetch: ExecuteApiFetch = function (
1157
apiHostname,
1258
sitekey,
1359
type,
@@ -17,12 +63,14 @@ var executeApiFetch = function (
1763
customFilterObject,
1864
recommendOptions
1965
) {
20-
var settingToQueryParam = function (setting, key) {
66+
/* eslint-disable @typescript-eslint/no-explicit-any */
67+
const settingToQueryParam = function (setting: any, key: string) {
2168
if (setting || setting === false) {
2269
return '&' + key + '=' + setting;
2370
}
2471
return '';
2572
};
73+
/* eslint-enable @typescript-eslint/no-explicit-any */
2674

2775
// Validate query type
2876
if (
@@ -38,12 +86,12 @@ var executeApiFetch = function (
3886
return;
3987
}
4088

41-
var keyword = '';
42-
var queryParamsString = '';
89+
let keyword = '';
90+
let queryParamsString = '';
4391

4492
// API Path (eq. /search, /suggest, /autocomplete/document-field)
45-
var apiEndpoint = null;
46-
var apiPath = null;
93+
let apiEndpoint: string | null = null;
94+
let apiPath = null;
4795

4896
// Search
4997
if (type === 'search') {
@@ -62,7 +110,7 @@ var executeApiFetch = function (
62110
keyword = encodeURIComponent(keyword);
63111

64112
// Fuzzy
65-
var fuzzy = settings.fuzzy;
113+
let fuzzy = settings.fuzzy;
66114
if (fuzzy === 'retry') {
67115
// First call, non fuzzy
68116
if (fuzzyRetry !== true) {
@@ -142,16 +190,16 @@ var executeApiFetch = function (
142190

143191
// Stats fields
144192
if (settings.statsFields) {
145-
for (var i = 0; i < settings.statsFields.length; i++) {
193+
for (let i = 0; i < settings.statsFields.length; i++) {
146194
queryParamsString = queryParamsString + '&fieldStat=' + settings.statsFields[i];
147195
}
148196
}
149197

150198
// Personalization events
151199
if (settings.personalizationEvents && Array.isArray(settings.personalizationEvents)) {
152200
for (let i = 0; i < settings.personalizationEvents.length; i++) {
153-
var obj = settings.personalizationEvents[i];
154-
var key = Object.keys(obj);
201+
const obj = settings.personalizationEvents[i];
202+
const key = Object.keys(obj)[0];
155203
queryParamsString =
156204
queryParamsString + '&personalizationEvent=' + encodeURIComponent(key + '=' + obj[key]);
157205
}
@@ -185,7 +233,7 @@ var executeApiFetch = function (
185233
.post(`https://api.addsearch.com/v2/indices/${sitekey}/conversations`, {
186234
question: settings.keyword
187235
})
188-
.then(function (response) {
236+
.then(function (response: AxiosResponse<ConversationsApiResponse>) {
189237
if (response.data.response) {
190238
cb(response.data.response);
191239
} else {
@@ -269,8 +317,8 @@ var executeApiFetch = function (
269317
if (type !== 'conversational-search') {
270318
apiInstance
271319
.get(apiEndpoint)
272-
.then(function (response) {
273-
var json = response.data;
320+
.then(function (response: AxiosResponse<GenericApiResponse>) {
321+
const json = response.data;
274322

275323
// Search again with fuzzy=true if no hits
276324
if (
@@ -285,7 +333,7 @@ var executeApiFetch = function (
285333
else {
286334
// Cap fuzzy results to one page as quality decreases quickly
287335
if (fuzzyRetry === true) {
288-
var pageSize = settings.paging.pageSize;
336+
const pageSize = settings.paging.pageSize;
289337
if (json.total_hits >= pageSize) {
290338
json.total_hits = pageSize;
291339
}
@@ -307,4 +355,5 @@ var executeApiFetch = function (
307355
});
308356
}
309357
};
310-
module.exports = executeApiFetch;
358+
359+
export default executeApiFetch;

src/conversational-search-interactions-api.js

-34
This file was deleted.

0 commit comments

Comments
 (0)