Skip to content

Commit 7bb3928

Browse files
authored
feat(javascript): expose transporter, remove nullish coalescing and optional chaining (#799)
1 parent 8823a24 commit 7bb3928

File tree

9 files changed

+173
-35
lines changed

9 files changed

+173
-35
lines changed

.eslintrc.js

+22-1
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ module.exports = {
9696
rules: {
9797
// disabled
9898
'no-bitwise': 0,
99-
'@typescript-eslint/no-namespace': 0,
10099
'max-classes-per-file': 0,
101100
'no-continue': 0,
102101
'@typescript-eslint/prefer-enum-initializers': 0,
102+
'@typescript-eslint/no-namespace': 0,
103103

104104
'unused-imports/no-unused-imports-ts': 2,
105105
'@typescript-eslint/no-unused-vars': 2,
@@ -127,6 +127,27 @@ module.exports = {
127127
],
128128
},
129129
},
130+
// JS client rules
131+
{
132+
files: ['clients/algoliasearch-client-javascript/packages/**/*.ts'],
133+
rules: {
134+
// For a wider browser support (IE>=11), we forbid those two
135+
'no-restricted-syntax': [
136+
'error',
137+
{
138+
selector: "LogicalExpression[operator='??']",
139+
message:
140+
'For wider browser support, nullish coalescing operator is not allowed.',
141+
},
142+
{
143+
selector: 'ChainExpression',
144+
message:
145+
'For wider browser support, optional chaining is not allowed.',
146+
},
147+
],
148+
'@typescript-eslint/prefer-optional-chain': 0,
149+
},
150+
},
130151
{
131152
files: ['*.json'],
132153

clients/algoliasearch-client-javascript/bundlesize.config.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"files": [
33
{
44
"path": "packages/algoliasearch/dist/algoliasearch.umd.js",
5-
"maxSize": "8.40KB"
5+
"maxSize": "8.35KB"
66
},
77
{
88
"path": "packages/algoliasearch/dist/lite/lite.umd.js",
@@ -30,15 +30,15 @@
3030
},
3131
{
3232
"path": "packages/client-search/dist/client-search.umd.js",
33-
"maxSize": "6.65KB"
33+
"maxSize": "6.60KB"
3434
},
3535
{
3636
"path": "packages/client-sources/dist/client-sources.umd.js",
3737
"maxSize": "3.85KB"
3838
},
3939
{
4040
"path": "packages/predict/dist/predict.umd.js",
41-
"maxSize": "3.85KB"
41+
"maxSize": "3.90KB"
4242
},
4343
{
4444
"path": "packages/recommend/dist/recommend.umd.js",

clients/algoliasearch-client-javascript/packages/algoliasearch/__tests__/algoliasearch.test.ts

+99
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import type { EchoResponse } from '@algolia/client-common';
2+
import {
3+
DEFAULT_CONNECT_TIMEOUT_NODE,
4+
DEFAULT_READ_TIMEOUT_NODE,
5+
DEFAULT_WRITE_TIMEOUT_NODE,
6+
} from '@algolia/client-common';
27
import { echoRequester } from '@algolia/requester-node-http';
38

49
import { algoliasearch, apiClientVersion } from '../builds/node';
@@ -39,6 +44,100 @@ describe('api', () => {
3944
expect(client.search).not.toBeUndefined();
4045
});
4146

47+
describe('_ua', () => {
48+
it('provides a backward compatible `_ua` variable at the root of the client', () => {
49+
expect(client._ua).toEqual(
50+
expect.stringContaining(
51+
`Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion});`
52+
)
53+
);
54+
});
55+
56+
it('keeps `_ua` updated with the transporter algolia agent', () => {
57+
expect(client._ua).toEqual(
58+
expect.stringMatching(/.*; Node\.js \(.*\)$/g)
59+
);
60+
61+
client.addAlgoliaAgent('Jest', '0.0.1');
62+
63+
expect(client._ua).toEqual(
64+
expect.stringMatching(/.*; Jest \(0\.0\.1\)$/g)
65+
);
66+
});
67+
});
68+
69+
it('exposes the search client transporter for the algoliasearch client', () => {
70+
expect(client.transporter).not.toBeUndefined();
71+
expect(client.transporter).toEqual({
72+
algoliaAgent: {
73+
add: expect.any(Function),
74+
value: expect.stringContaining(
75+
`Algolia for JavaScript (${apiClientVersion}); Search (${apiClientVersion});`
76+
),
77+
},
78+
baseHeaders: {
79+
'content-type': 'text/plain',
80+
'x-algolia-api-key': 'API_KEY',
81+
'x-algolia-application-id': 'APP_ID',
82+
},
83+
baseQueryParameters: {},
84+
hosts: expect.arrayContaining([
85+
{
86+
accept: 'read',
87+
protocol: 'https',
88+
url: 'APP_ID-dsn.algolia.net',
89+
},
90+
{
91+
accept: 'write',
92+
protocol: 'https',
93+
url: 'APP_ID.algolia.net',
94+
},
95+
{
96+
accept: 'readWrite',
97+
protocol: 'https',
98+
url: 'APP_ID-3.algolianet.com',
99+
},
100+
{
101+
accept: 'readWrite',
102+
protocol: 'https',
103+
url: 'APP_ID-1.algolianet.com',
104+
},
105+
{
106+
accept: 'readWrite',
107+
protocol: 'https',
108+
url: 'APP_ID-2.algolianet.com',
109+
},
110+
]),
111+
hostsCache: {
112+
clear: expect.any(Function),
113+
delete: expect.any(Function),
114+
get: expect.any(Function),
115+
set: expect.any(Function),
116+
},
117+
request: expect.any(Function),
118+
requester: {
119+
send: expect.any(Function),
120+
},
121+
requestsCache: {
122+
clear: expect.any(Function),
123+
delete: expect.any(Function),
124+
get: expect.any(Function),
125+
set: expect.any(Function),
126+
},
127+
responsesCache: {
128+
clear: expect.any(Function),
129+
delete: expect.any(Function),
130+
get: expect.any(Function),
131+
set: expect.any(Function),
132+
},
133+
timeouts: {
134+
connect: DEFAULT_CONNECT_TIMEOUT_NODE,
135+
read: DEFAULT_READ_TIMEOUT_NODE,
136+
write: DEFAULT_WRITE_TIMEOUT_NODE,
137+
},
138+
});
139+
});
140+
42141
describe('init clients', () => {
43142
it('provides an init method for the analytics client', () => {
44143
expect(client.initAnalytics).not.toBeUndefined();

clients/algoliasearch-client-javascript/packages/client-common/src/transporter/createTransporter.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export function createTransporter({
112112
...dataQueryParameters,
113113
};
114114

115-
if (requestOptions?.queryParameters) {
115+
if (requestOptions && requestOptions.queryParameters) {
116116
for (const key of Object.keys(requestOptions.queryParameters)) {
117117
// We want to keep `undefined` and `null` values,
118118
// but also avoid stringifying `object`s, as they are
@@ -237,29 +237,29 @@ export function createTransporter({
237237

238238
function createRequest<TResponse>(
239239
baseRequest: Request,
240-
baseRequestOptions?: RequestOptions
240+
baseRequestOptions: RequestOptions = {}
241241
): Promise<TResponse> {
242242
const mergedData: Request['data'] = Array.isArray(baseRequest.data)
243243
? baseRequest.data
244244
: {
245245
...baseRequest.data,
246-
...baseRequestOptions?.data,
246+
...baseRequestOptions.data,
247247
};
248248
const request: Request = {
249249
...baseRequest,
250250
data: mergedData,
251251
};
252252
const requestOptions: RequestOptions = {
253-
cacheable: baseRequestOptions?.cacheable,
254-
timeout: baseRequestOptions?.timeout,
253+
cacheable: baseRequestOptions.cacheable,
254+
timeout: baseRequestOptions.timeout,
255255
queryParameters: {
256256
...baseRequest.queryParameters,
257-
...baseRequestOptions?.queryParameters,
257+
...baseRequestOptions.queryParameters,
258258
},
259259
headers: {
260260
Accept: 'application/json',
261261
...baseRequest.headers,
262-
...baseRequestOptions?.headers,
262+
...baseRequestOptions.headers,
263263
},
264264
};
265265

clients/algoliasearch-client-javascript/packages/client-common/src/transporter/errors.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import type { Response, StackFrame } from '../types';
22

33
export class AlgoliaError extends Error {
4-
name: string;
4+
name: string = 'AlgoliaError';
55

66
constructor(message: string, name: string) {
77
super(message);
8-
this.name = name ?? 'AlgoliaError';
8+
9+
if (name) {
10+
this.name = name;
11+
}
912
}
1013
}
1114

templates/javascript/clients/algoliasearch/builds/browser.mustache

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ export function algoliasearch(
1919
) {
2020
{{> algoliasearch/builds/checkParameters}}
2121

22-
const commonOptions: Omit<CreateClientOptions, 'apiKey' | 'appId'> = {
22+
const commonOptions: CreateClientOptions = {
23+
apiKey,
24+
appId,
2325
timeouts: {
2426
connect: DEFAULT_CONNECT_TIMEOUT_BROWSER,
2527
read: DEFAULT_READ_TIMEOUT_BROWSER,
2628
write: DEFAULT_WRITE_TIMEOUT_BROWSER,
2729
},
28-
requester: options?.requester ?? createXhrRequester(),
30+
requester: createXhrRequester(),
2931
algoliaAgents: [{ segment: 'Browser' }],
3032
authMode: 'WithinQueryParameters',
3133
responsesCache: createMemoryCache(),

templates/javascript/clients/algoliasearch/builds/initClients.mustache

+13-13
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@ function initAnalytics(initOptions: CommonInitOptions & InitRegion<AnalyticsRegi
1010
}
1111

1212
return createAnalyticsClient({
13-
...initOptions.options,
1413
...commonOptions,
15-
appId: initOptions.appId ?? appId,
16-
apiKey: initOptions.apiKey ?? apiKey,
17-
region: initOptions.region,
14+
...initOptions.options,
15+
...initOptions,
1816
});
1917
}
2018

@@ -30,11 +28,9 @@ function initAbtesting(initOptions: CommonInitOptions & InitRegion<AbtestingRegi
3028
}
3129

3230
return createAbtestingClient({
33-
...initOptions.options,
3431
...commonOptions,
35-
appId: initOptions.appId ?? appId,
36-
apiKey: initOptions.apiKey ?? apiKey,
37-
region: initOptions.region,
32+
...initOptions.options,
33+
...initOptions,
3834
});
3935
}
4036

@@ -54,16 +50,20 @@ function initPersonalization(initOptions: CommonInitOptions & Required<InitRegio
5450
}
5551

5652
return createPersonalizationClient({
57-
...initOptions.options,
5853
...commonOptions,
59-
appId: initOptions.appId ?? appId,
60-
apiKey: initOptions.apiKey ?? apiKey,
61-
region: initOptions.region,
54+
...initOptions.options,
55+
...initOptions,
6256
});
6357
}
6458

6559
return {
66-
...createSearchClient({ appId, apiKey, ...commonOptions }),
60+
...createSearchClient(commonOptions),
61+
/**
62+
* Get the value of the `algoliaAgent`, used by our libraries internally and telemetry system.
63+
*/
64+
get _ua(): string {
65+
return this.transporter.algoliaAgent.value;
66+
},
6767
initAnalytics,
6868
initPersonalization,
6969
initAbtesting,

templates/javascript/clients/algoliasearch/builds/node.mustache

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ export function algoliasearch(
1818
) {
1919
{{> algoliasearch/builds/checkParameters}}
2020

21-
const commonOptions: Omit<CreateClientOptions, 'apiKey' | 'appId'> = {
21+
const commonOptions: CreateClientOptions = {
22+
apiKey,
23+
appId,
2224
timeouts: {
2325
connect: DEFAULT_CONNECT_TIMEOUT_NODE,
2426
read: DEFAULT_READ_TIMEOUT_NODE,
2527
write: DEFAULT_WRITE_TIMEOUT_NODE,
2628
},
27-
requester: options?.requester ?? createHttpRequester(),
29+
requester: createHttpRequester(),
2830
algoliaAgents: [{ segment: 'Node.js', version: process.versions.node }],
2931
responsesCache: createNullCache(),
3032
requestsCache: createNullCache(),

templates/javascript/clients/api-single.mustache

+16-5
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,23 @@ export function create{{capitalizedApiName}}({
3333
},
3434
});
3535

36-
function addAlgoliaAgent(segment: string, version?: string): void {
37-
transporter.algoliaAgent.add({ segment, version });
38-
}
39-
4036
return {
41-
addAlgoliaAgent,
37+
transporter,
38+
/**
39+
* Get the value of the `algoliaAgent`, used by our libraries internally and telemetry system.
40+
*/
41+
get _ua(): string {
42+
return transporter.algoliaAgent.value;
43+
},
44+
/**
45+
* Adds a `segment` to the `x-algolia-agent` sent with every requests.
46+
*
47+
* @param segment - The algolia agent (user-agent) segment to add.
48+
* @param version - The version of the agent.
49+
*/
50+
addAlgoliaAgent(segment: string, version?: string): void {
51+
transporter.algoliaAgent.add({ segment, version });
52+
},
4253
{{#isSearchClient}}
4354
{{> client/api/helpers}}
4455
{{/isSearchClient}}

0 commit comments

Comments
 (0)