@algolia/client-common 5.0.0-alpha.25 → 5.0.0-alpha.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client-common.cjs.js +26 -112
- package/dist/client-common.esm.node.js +26 -112
- package/package.json +3 -3
|
@@ -11,11 +11,9 @@ function createAuth(appId, apiKey, authMode = 'WithinHeaders') {
|
|
|
11
11
|
headers() {
|
|
12
12
|
return authMode === 'WithinHeaders' ? credentials : {};
|
|
13
13
|
},
|
|
14
|
-
|
|
15
14
|
queryParameters() {
|
|
16
15
|
return authMode === 'WithinQueryParameters' ? credentials : {};
|
|
17
16
|
}
|
|
18
|
-
|
|
19
17
|
};
|
|
20
18
|
}
|
|
21
19
|
|
|
@@ -26,15 +24,12 @@ function getUrlParams({
|
|
|
26
24
|
}) {
|
|
27
25
|
const algoliaAgent = urlSearchParams.get('x-algolia-agent') || '';
|
|
28
26
|
const searchParams = {};
|
|
29
|
-
|
|
30
27
|
for (const [k, v] of urlSearchParams) {
|
|
31
28
|
if (k === 'x-algolia-agent') {
|
|
32
29
|
continue;
|
|
33
30
|
}
|
|
34
|
-
|
|
35
31
|
searchParams[k] = v;
|
|
36
32
|
}
|
|
37
|
-
|
|
38
33
|
return {
|
|
39
34
|
host,
|
|
40
35
|
algoliaAgent,
|
|
@@ -42,7 +37,6 @@ function getUrlParams({
|
|
|
42
37
|
path: pathname
|
|
43
38
|
};
|
|
44
39
|
}
|
|
45
|
-
|
|
46
40
|
function createEchoRequester({
|
|
47
41
|
getURL,
|
|
48
42
|
status = 200
|
|
@@ -54,7 +48,8 @@ function createEchoRequester({
|
|
|
54
48
|
algoliaAgent,
|
|
55
49
|
path
|
|
56
50
|
} = getUrlParams(getURL(request.url));
|
|
57
|
-
const content = {
|
|
51
|
+
const content = {
|
|
52
|
+
...request,
|
|
58
53
|
data: request.data ? JSON.parse(request.data) : undefined,
|
|
59
54
|
path,
|
|
60
55
|
host,
|
|
@@ -67,7 +62,6 @@ function createEchoRequester({
|
|
|
67
62
|
status
|
|
68
63
|
});
|
|
69
64
|
}
|
|
70
|
-
|
|
71
65
|
return {
|
|
72
66
|
send
|
|
73
67
|
};
|
|
@@ -96,15 +90,12 @@ function createIterablePromise({
|
|
|
96
90
|
if (aggregator) {
|
|
97
91
|
aggregator(response);
|
|
98
92
|
}
|
|
99
|
-
|
|
100
93
|
if (validate(response)) {
|
|
101
94
|
return resolve(response);
|
|
102
95
|
}
|
|
103
|
-
|
|
104
96
|
if (error && error.validate(response)) {
|
|
105
97
|
return reject(new Error(error.message(response)));
|
|
106
98
|
}
|
|
107
|
-
|
|
108
99
|
return setTimeout(() => {
|
|
109
100
|
retry(response).then(resolve).catch(reject);
|
|
110
101
|
}, timeout());
|
|
@@ -113,27 +104,22 @@ function createIterablePromise({
|
|
|
113
104
|
});
|
|
114
105
|
});
|
|
115
106
|
};
|
|
116
|
-
|
|
117
107
|
return retry();
|
|
118
108
|
}
|
|
119
109
|
|
|
120
110
|
function createBrowserLocalStorageCache(options) {
|
|
121
|
-
let storage;
|
|
122
|
-
|
|
111
|
+
let storage;
|
|
112
|
+
// We've changed the namespace to avoid conflicts with v4, as this version is a huge breaking change
|
|
123
113
|
const namespaceKey = `algolia-client-js-${options.key}`;
|
|
124
|
-
|
|
125
114
|
function getStorage() {
|
|
126
115
|
if (storage === undefined) {
|
|
127
116
|
storage = options.localStorage || window.localStorage;
|
|
128
117
|
}
|
|
129
|
-
|
|
130
118
|
return storage;
|
|
131
119
|
}
|
|
132
|
-
|
|
133
120
|
function getNamespace() {
|
|
134
121
|
return JSON.parse(getStorage().getItem(namespaceKey) || '{}');
|
|
135
122
|
}
|
|
136
|
-
|
|
137
123
|
return {
|
|
138
124
|
get(key, defaultValue, events = {
|
|
139
125
|
miss: () => Promise.resolve()
|
|
@@ -146,7 +132,6 @@ function createBrowserLocalStorageCache(options) {
|
|
|
146
132
|
return Promise.all([value, exists || events.miss(value)]);
|
|
147
133
|
}).then(([value]) => value);
|
|
148
134
|
},
|
|
149
|
-
|
|
150
135
|
set(key, value) {
|
|
151
136
|
return Promise.resolve().then(() => {
|
|
152
137
|
const namespace = getNamespace();
|
|
@@ -155,7 +140,6 @@ function createBrowserLocalStorageCache(options) {
|
|
|
155
140
|
return value;
|
|
156
141
|
});
|
|
157
142
|
},
|
|
158
|
-
|
|
159
143
|
delete(key) {
|
|
160
144
|
return Promise.resolve().then(() => {
|
|
161
145
|
const namespace = getNamespace();
|
|
@@ -163,13 +147,11 @@ function createBrowserLocalStorageCache(options) {
|
|
|
163
147
|
getStorage().setItem(namespaceKey, JSON.stringify(namespace));
|
|
164
148
|
});
|
|
165
149
|
},
|
|
166
|
-
|
|
167
150
|
clear() {
|
|
168
151
|
return Promise.resolve().then(() => {
|
|
169
152
|
getStorage().removeItem(namespaceKey);
|
|
170
153
|
});
|
|
171
154
|
}
|
|
172
|
-
|
|
173
155
|
};
|
|
174
156
|
}
|
|
175
157
|
|
|
@@ -181,30 +163,24 @@ function createNullCache() {
|
|
|
181
163
|
const value = defaultValue();
|
|
182
164
|
return value.then(result => Promise.all([result, events.miss(result)])).then(([result]) => result);
|
|
183
165
|
},
|
|
184
|
-
|
|
185
166
|
set(_key, value) {
|
|
186
167
|
return Promise.resolve(value);
|
|
187
168
|
},
|
|
188
|
-
|
|
189
169
|
delete(_key) {
|
|
190
170
|
return Promise.resolve();
|
|
191
171
|
},
|
|
192
|
-
|
|
193
172
|
clear() {
|
|
194
173
|
return Promise.resolve();
|
|
195
174
|
}
|
|
196
|
-
|
|
197
175
|
};
|
|
198
176
|
}
|
|
199
177
|
|
|
200
178
|
function createFallbackableCache(options) {
|
|
201
179
|
const caches = [...options.caches];
|
|
202
180
|
const current = caches.shift();
|
|
203
|
-
|
|
204
181
|
if (current === undefined) {
|
|
205
182
|
return createNullCache();
|
|
206
183
|
}
|
|
207
|
-
|
|
208
184
|
return {
|
|
209
185
|
get(key, defaultValue, events = {
|
|
210
186
|
miss: () => Promise.resolve()
|
|
@@ -215,7 +191,6 @@ function createFallbackableCache(options) {
|
|
|
215
191
|
}).get(key, defaultValue, events);
|
|
216
192
|
});
|
|
217
193
|
},
|
|
218
|
-
|
|
219
194
|
set(key, value) {
|
|
220
195
|
return current.set(key, value).catch(() => {
|
|
221
196
|
return createFallbackableCache({
|
|
@@ -223,7 +198,6 @@ function createFallbackableCache(options) {
|
|
|
223
198
|
}).set(key, value);
|
|
224
199
|
});
|
|
225
200
|
},
|
|
226
|
-
|
|
227
201
|
delete(key) {
|
|
228
202
|
return current.delete(key).catch(() => {
|
|
229
203
|
return createFallbackableCache({
|
|
@@ -231,7 +205,6 @@ function createFallbackableCache(options) {
|
|
|
231
205
|
}).delete(key);
|
|
232
206
|
});
|
|
233
207
|
},
|
|
234
|
-
|
|
235
208
|
clear() {
|
|
236
209
|
return current.clear().catch(() => {
|
|
237
210
|
return createFallbackableCache({
|
|
@@ -239,7 +212,6 @@ function createFallbackableCache(options) {
|
|
|
239
212
|
}).clear();
|
|
240
213
|
});
|
|
241
214
|
}
|
|
242
|
-
|
|
243
215
|
};
|
|
244
216
|
}
|
|
245
217
|
|
|
@@ -252,30 +224,24 @@ function createMemoryCache(options = {
|
|
|
252
224
|
miss: () => Promise.resolve()
|
|
253
225
|
}) {
|
|
254
226
|
const keyAsString = JSON.stringify(key);
|
|
255
|
-
|
|
256
227
|
if (keyAsString in cache) {
|
|
257
228
|
return Promise.resolve(options.serializable ? JSON.parse(cache[keyAsString]) : cache[keyAsString]);
|
|
258
229
|
}
|
|
259
|
-
|
|
260
230
|
const promise = defaultValue();
|
|
261
231
|
return promise.then(value => events.miss(value)).then(() => promise);
|
|
262
232
|
},
|
|
263
|
-
|
|
264
233
|
set(key, value) {
|
|
265
234
|
cache[JSON.stringify(key)] = options.serializable ? JSON.stringify(value) : value;
|
|
266
235
|
return Promise.resolve(value);
|
|
267
236
|
},
|
|
268
|
-
|
|
269
237
|
delete(key) {
|
|
270
238
|
delete cache[JSON.stringify(key)];
|
|
271
239
|
return Promise.resolve();
|
|
272
240
|
},
|
|
273
|
-
|
|
274
241
|
clear() {
|
|
275
242
|
cache = {};
|
|
276
243
|
return Promise.resolve();
|
|
277
244
|
}
|
|
278
|
-
|
|
279
245
|
};
|
|
280
246
|
}
|
|
281
247
|
|
|
@@ -284,16 +250,14 @@ function createMemoryCache(options = {
|
|
|
284
250
|
const EXPIRATION_DELAY = 2 * 60 * 1000;
|
|
285
251
|
function createStatefulHost(host, status = 'up') {
|
|
286
252
|
const lastUpdate = Date.now();
|
|
287
|
-
|
|
288
253
|
function isUp() {
|
|
289
254
|
return status === 'up' || Date.now() - lastUpdate > EXPIRATION_DELAY;
|
|
290
255
|
}
|
|
291
|
-
|
|
292
256
|
function isTimedOut() {
|
|
293
257
|
return status === 'timed out' && Date.now() - lastUpdate <= EXPIRATION_DELAY;
|
|
294
258
|
}
|
|
295
|
-
|
|
296
|
-
|
|
259
|
+
return {
|
|
260
|
+
...host,
|
|
297
261
|
status,
|
|
298
262
|
lastUpdate,
|
|
299
263
|
isUp,
|
|
@@ -312,92 +276,74 @@ function _defineProperty(obj, key, value) {
|
|
|
312
276
|
} else {
|
|
313
277
|
obj[key] = value;
|
|
314
278
|
}
|
|
315
|
-
|
|
316
279
|
return obj;
|
|
317
280
|
}
|
|
318
281
|
|
|
319
282
|
class AlgoliaError extends Error {
|
|
320
283
|
constructor(message, name) {
|
|
321
284
|
super(message);
|
|
322
|
-
|
|
323
285
|
_defineProperty(this, "name", 'AlgoliaError');
|
|
324
|
-
|
|
325
286
|
if (name) {
|
|
326
287
|
this.name = name;
|
|
327
288
|
}
|
|
328
289
|
}
|
|
329
|
-
|
|
330
290
|
}
|
|
331
291
|
class ErrorWithStackTrace extends AlgoliaError {
|
|
332
292
|
constructor(message, stackTrace, name) {
|
|
333
|
-
super(message, name);
|
|
334
|
-
|
|
293
|
+
super(message, name);
|
|
294
|
+
// the array and object should be frozen to reflect the stackTrace at the time of the error
|
|
335
295
|
_defineProperty(this, "stackTrace", void 0);
|
|
336
|
-
|
|
337
296
|
this.stackTrace = stackTrace;
|
|
338
297
|
}
|
|
339
|
-
|
|
340
298
|
}
|
|
341
299
|
class RetryError extends ErrorWithStackTrace {
|
|
342
300
|
constructor(stackTrace) {
|
|
343
301
|
super('Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.', stackTrace, 'RetryError');
|
|
344
302
|
}
|
|
345
|
-
|
|
346
303
|
}
|
|
347
304
|
class ApiError extends ErrorWithStackTrace {
|
|
348
305
|
constructor(message, status, stackTrace) {
|
|
349
306
|
super(message, stackTrace, 'ApiError');
|
|
350
|
-
|
|
351
307
|
_defineProperty(this, "status", void 0);
|
|
352
|
-
|
|
353
308
|
this.status = status;
|
|
354
309
|
}
|
|
355
|
-
|
|
356
310
|
}
|
|
357
311
|
class DeserializationError extends AlgoliaError {
|
|
358
312
|
constructor(message, response) {
|
|
359
313
|
super(message, 'DeserializationError');
|
|
360
|
-
|
|
361
314
|
_defineProperty(this, "response", void 0);
|
|
362
|
-
|
|
363
315
|
this.response = response;
|
|
364
316
|
}
|
|
365
|
-
|
|
366
317
|
}
|
|
367
318
|
|
|
368
319
|
function shuffle(array) {
|
|
369
320
|
const shuffledArray = array;
|
|
370
|
-
|
|
371
321
|
for (let c = array.length - 1; c > 0; c--) {
|
|
372
322
|
const b = Math.floor(Math.random() * (c + 1));
|
|
373
323
|
const a = array[c];
|
|
374
324
|
shuffledArray[c] = array[b];
|
|
375
325
|
shuffledArray[b] = a;
|
|
376
326
|
}
|
|
377
|
-
|
|
378
327
|
return shuffledArray;
|
|
379
328
|
}
|
|
380
329
|
function serializeUrl(host, path, queryParameters) {
|
|
381
330
|
const queryParametersAsString = serializeQueryParameters(queryParameters);
|
|
382
331
|
let url = `${host.protocol}://${host.url}/${path.charAt(0) === '/' ? path.substr(1) : path}`;
|
|
383
|
-
|
|
384
332
|
if (queryParametersAsString.length) {
|
|
385
333
|
url += `?${queryParametersAsString}`;
|
|
386
334
|
}
|
|
387
|
-
|
|
388
335
|
return url;
|
|
389
336
|
}
|
|
390
337
|
function serializeQueryParameters(parameters) {
|
|
391
338
|
const isObjectOrArray = value => Object.prototype.toString.call(value) === '[object Object]' || Object.prototype.toString.call(value) === '[object Array]';
|
|
392
|
-
|
|
393
339
|
return Object.keys(parameters).map(key => `${key}=${encodeURIComponent(isObjectOrArray(parameters[key]) ? JSON.stringify(parameters[key]) : parameters[key])}`).join('&');
|
|
394
340
|
}
|
|
395
341
|
function serializeData(request, requestOptions) {
|
|
396
342
|
if (request.method === 'GET' || request.data === undefined && requestOptions.data === undefined) {
|
|
397
343
|
return undefined;
|
|
398
344
|
}
|
|
399
|
-
|
|
400
|
-
|
|
345
|
+
const data = Array.isArray(request.data) ? request.data : {
|
|
346
|
+
...request.data,
|
|
401
347
|
...requestOptions.data
|
|
402
348
|
};
|
|
403
349
|
return JSON.stringify(data);
|
|
@@ -428,12 +374,11 @@ function deserializeFailure({
|
|
|
428
374
|
status
|
|
429
375
|
}, stackFrame) {
|
|
430
376
|
let message = content;
|
|
431
|
-
|
|
432
377
|
try {
|
|
433
378
|
message = JSON.parse(content).message;
|
|
434
|
-
} catch (e) {
|
|
379
|
+
} catch (e) {
|
|
380
|
+
// ..
|
|
435
381
|
}
|
|
436
|
-
|
|
437
382
|
return new ApiError(message, status, stackFrame);
|
|
438
383
|
}
|
|
439
384
|
|
|
@@ -465,9 +410,12 @@ function stackFrameWithoutCredentials(stackFrame) {
|
|
|
465
410
|
const modifiedHeaders = stackFrame.request.headers['x-algolia-api-key'] ? {
|
|
466
411
|
'x-algolia-api-key': '*****'
|
|
467
412
|
} : {};
|
|
468
|
-
return {
|
|
469
|
-
|
|
470
|
-
|
|
413
|
+
return {
|
|
414
|
+
...stackFrame,
|
|
415
|
+
request: {
|
|
416
|
+
...stackFrame.request,
|
|
417
|
+
headers: {
|
|
418
|
+
...stackFrame.request.headers,
|
|
471
419
|
...modifiedHeaders
|
|
472
420
|
}
|
|
473
421
|
}
|
|
@@ -492,13 +440,12 @@ function createTransporter({
|
|
|
492
440
|
});
|
|
493
441
|
}));
|
|
494
442
|
const hostsUp = statefulHosts.filter(host => host.isUp());
|
|
495
|
-
const hostsTimedOut = statefulHosts.filter(host => host.isTimedOut());
|
|
496
|
-
|
|
443
|
+
const hostsTimedOut = statefulHosts.filter(host => host.isTimedOut());
|
|
444
|
+
// Note, we put the hosts that previously timed out on the end of the list.
|
|
497
445
|
const hostsAvailable = [...hostsUp, ...hostsTimedOut];
|
|
498
446
|
const compatibleHostsAvailable = hostsAvailable.length > 0 ? hostsAvailable : compatibleHosts;
|
|
499
447
|
return {
|
|
500
448
|
hosts: compatibleHostsAvailable,
|
|
501
|
-
|
|
502
449
|
getTimeout(timeoutsCount, baseTimeout) {
|
|
503
450
|
/**
|
|
504
451
|
* Imagine that you have 4 hosts, if timeouts will increase
|
|
@@ -514,20 +461,18 @@ function createTransporter({
|
|
|
514
461
|
const timeoutMultiplier = hostsTimedOut.length === 0 && timeoutsCount === 0 ? 1 : hostsTimedOut.length + 3 + timeoutsCount;
|
|
515
462
|
return timeoutMultiplier * baseTimeout;
|
|
516
463
|
}
|
|
517
|
-
|
|
518
464
|
};
|
|
519
465
|
}
|
|
520
|
-
|
|
521
466
|
async function retryableRequest(request, requestOptions, isRead = true) {
|
|
522
467
|
const stackTrace = [];
|
|
523
468
|
/**
|
|
524
469
|
* First we prepare the payload that do not depend from hosts.
|
|
525
470
|
*/
|
|
526
|
-
|
|
527
471
|
const data = serializeData(request, requestOptions);
|
|
528
|
-
const headers = serializeHeaders(baseHeaders, request.headers, requestOptions.headers);
|
|
529
|
-
|
|
530
|
-
const dataQueryParameters = request.method === 'GET' ? {
|
|
472
|
+
const headers = serializeHeaders(baseHeaders, request.headers, requestOptions.headers);
|
|
473
|
+
// On `GET`, the data is proxied to query parameters.
|
|
474
|
+
const dataQueryParameters = request.method === 'GET' ? {
|
|
475
|
+
...request.data,
|
|
531
476
|
...requestOptions.data
|
|
532
477
|
} : {};
|
|
533
478
|
const queryParameters = {
|
|
@@ -536,7 +481,6 @@ function createTransporter({
|
|
|
536
481
|
...request.queryParameters,
|
|
537
482
|
...dataQueryParameters
|
|
538
483
|
};
|
|
539
|
-
|
|
540
484
|
if (requestOptions && requestOptions.queryParameters) {
|
|
541
485
|
for (const key of Object.keys(requestOptions.queryParameters)) {
|
|
542
486
|
// We want to keep `undefined` and `null` values,
|
|
@@ -549,25 +493,19 @@ function createTransporter({
|
|
|
549
493
|
}
|
|
550
494
|
}
|
|
551
495
|
}
|
|
552
|
-
|
|
553
496
|
let timeoutsCount = 0;
|
|
554
|
-
|
|
555
497
|
const retry = async (retryableHosts, getTimeout) => {
|
|
556
498
|
/**
|
|
557
499
|
* We iterate on each host, until there is no host left.
|
|
558
500
|
*/
|
|
559
501
|
const host = retryableHosts.pop();
|
|
560
|
-
|
|
561
502
|
if (host === undefined) {
|
|
562
503
|
throw new RetryError(stackTraceWithoutCredentials(stackTrace));
|
|
563
504
|
}
|
|
564
|
-
|
|
565
505
|
let responseTimeout = requestOptions.timeout;
|
|
566
|
-
|
|
567
506
|
if (responseTimeout === undefined) {
|
|
568
507
|
responseTimeout = isRead ? timeouts.read : timeouts.write;
|
|
569
508
|
}
|
|
570
|
-
|
|
571
509
|
const payload = {
|
|
572
510
|
data,
|
|
573
511
|
headers,
|
|
@@ -581,7 +519,6 @@ function createTransporter({
|
|
|
581
519
|
* can have information about onRetry and onFailure
|
|
582
520
|
* decisions.
|
|
583
521
|
*/
|
|
584
|
-
|
|
585
522
|
const pushToStackTrace = response => {
|
|
586
523
|
const stackFrame = {
|
|
587
524
|
request: payload,
|
|
@@ -592,12 +529,10 @@ function createTransporter({
|
|
|
592
529
|
stackTrace.push(stackFrame);
|
|
593
530
|
return stackFrame;
|
|
594
531
|
};
|
|
595
|
-
|
|
596
532
|
const response = await requester.send(payload);
|
|
597
|
-
|
|
598
533
|
if (isRetryable(response)) {
|
|
599
|
-
const stackFrame = pushToStackTrace(response);
|
|
600
|
-
|
|
534
|
+
const stackFrame = pushToStackTrace(response);
|
|
535
|
+
// If response is a timeout, we increase the number of timeouts so we can increase the timeout later.
|
|
601
536
|
if (response.isTimedOut) {
|
|
602
537
|
timeoutsCount++;
|
|
603
538
|
}
|
|
@@ -607,23 +542,18 @@ function createTransporter({
|
|
|
607
542
|
* when a retry error does not happen.
|
|
608
543
|
*/
|
|
609
544
|
// eslint-disable-next-line no-console -- this will be fixed by exposing a `logger` to the transporter
|
|
610
|
-
|
|
611
|
-
|
|
612
545
|
console.log('Retryable failure', stackFrameWithoutCredentials(stackFrame));
|
|
613
546
|
/**
|
|
614
547
|
* We also store the state of the host in failure cases. If the host, is
|
|
615
548
|
* down it will remain down for the next 2 minutes. In a timeout situation,
|
|
616
549
|
* this host will be added end of the list of hosts on the next request.
|
|
617
550
|
*/
|
|
618
|
-
|
|
619
551
|
await hostsCache.set(host, createStatefulHost(host, response.isTimedOut ? 'timed out' : 'down'));
|
|
620
552
|
return retry(retryableHosts, getTimeout);
|
|
621
553
|
}
|
|
622
|
-
|
|
623
554
|
if (isSuccess(response)) {
|
|
624
555
|
return deserializeSuccess(response);
|
|
625
556
|
}
|
|
626
|
-
|
|
627
557
|
pushToStackTrace(response);
|
|
628
558
|
throw deserializeFailure(response, stackTrace);
|
|
629
559
|
};
|
|
@@ -635,20 +565,16 @@ function createTransporter({
|
|
|
635
565
|
* 2. We also get from the retryable options a timeout multiplier that is tailored
|
|
636
566
|
* for the current context.
|
|
637
567
|
*/
|
|
638
|
-
|
|
639
|
-
|
|
640
568
|
const compatibleHosts = hosts.filter(host => host.accept === 'readWrite' || (isRead ? host.accept === 'read' : host.accept === 'write'));
|
|
641
569
|
const options = await createRetryableOptions(compatibleHosts);
|
|
642
570
|
return retry([...options.hosts].reverse(), options.getTimeout);
|
|
643
571
|
}
|
|
644
|
-
|
|
645
572
|
function createRequest(request, requestOptions = {}) {
|
|
646
573
|
/**
|
|
647
574
|
* A read request is either a `GET` request, or a request that we make
|
|
648
575
|
* via the `read` transporter (e.g. `search`).
|
|
649
576
|
*/
|
|
650
577
|
const isRead = request.useReadTransporter || request.method === 'GET';
|
|
651
|
-
|
|
652
578
|
if (!isRead) {
|
|
653
579
|
/**
|
|
654
580
|
* On write requests, no cache mechanisms are applied, and we
|
|
@@ -656,7 +582,6 @@ function createTransporter({
|
|
|
656
582
|
*/
|
|
657
583
|
return retryableRequest(request, requestOptions, isRead);
|
|
658
584
|
}
|
|
659
|
-
|
|
660
585
|
const createRetryableRequest = () => {
|
|
661
586
|
/**
|
|
662
587
|
* Then, we prepare a function factory that contains the construction of
|
|
@@ -670,14 +595,11 @@ function createTransporter({
|
|
|
670
595
|
* request is "cacheable" - should be cached. Note that, once again,
|
|
671
596
|
* the user can force this option.
|
|
672
597
|
*/
|
|
673
|
-
|
|
674
|
-
|
|
675
598
|
const cacheable = requestOptions.cacheable || request.cacheable;
|
|
676
599
|
/**
|
|
677
600
|
* If is not "cacheable", we immediately trigger the retryable request, no
|
|
678
601
|
* need to check cache implementations.
|
|
679
602
|
*/
|
|
680
|
-
|
|
681
603
|
if (cacheable !== true) {
|
|
682
604
|
return createRetryableRequest();
|
|
683
605
|
}
|
|
@@ -686,8 +608,6 @@ function createTransporter({
|
|
|
686
608
|
* the cache implementations if this request is on progress or if the
|
|
687
609
|
* response already exists on the cache.
|
|
688
610
|
*/
|
|
689
|
-
|
|
690
|
-
|
|
691
611
|
const key = {
|
|
692
612
|
request,
|
|
693
613
|
requestOptions,
|
|
@@ -700,7 +620,6 @@ function createTransporter({
|
|
|
700
620
|
* With the computed key, we first ask the responses cache
|
|
701
621
|
* implementation if this request was been resolved before.
|
|
702
622
|
*/
|
|
703
|
-
|
|
704
623
|
return responsesCache.get(key, () => {
|
|
705
624
|
/**
|
|
706
625
|
* If the request has never resolved before, we actually ask if there
|
|
@@ -722,7 +641,6 @@ function createTransporter({
|
|
|
722
641
|
miss: response => responsesCache.set(key, response)
|
|
723
642
|
});
|
|
724
643
|
}
|
|
725
|
-
|
|
726
644
|
return {
|
|
727
645
|
hostsCache,
|
|
728
646
|
requester,
|
|
@@ -740,17 +658,13 @@ function createTransporter({
|
|
|
740
658
|
function createAlgoliaAgent(version) {
|
|
741
659
|
const algoliaAgent = {
|
|
742
660
|
value: `Algolia for JavaScript (${version})`,
|
|
743
|
-
|
|
744
661
|
add(options) {
|
|
745
662
|
const addedAlgoliaAgent = `; ${options.segment}${options.version !== undefined ? ` (${options.version})` : ''}`;
|
|
746
|
-
|
|
747
663
|
if (algoliaAgent.value.indexOf(addedAlgoliaAgent) === -1) {
|
|
748
664
|
algoliaAgent.value = `${algoliaAgent.value}${addedAlgoliaAgent}`;
|
|
749
665
|
}
|
|
750
|
-
|
|
751
666
|
return algoliaAgent;
|
|
752
667
|
}
|
|
753
|
-
|
|
754
668
|
};
|
|
755
669
|
return algoliaAgent;
|
|
756
670
|
}
|
|
@@ -7,11 +7,9 @@ function createAuth(appId, apiKey, authMode = 'WithinHeaders') {
|
|
|
7
7
|
headers() {
|
|
8
8
|
return authMode === 'WithinHeaders' ? credentials : {};
|
|
9
9
|
},
|
|
10
|
-
|
|
11
10
|
queryParameters() {
|
|
12
11
|
return authMode === 'WithinQueryParameters' ? credentials : {};
|
|
13
12
|
}
|
|
14
|
-
|
|
15
13
|
};
|
|
16
14
|
}
|
|
17
15
|
|
|
@@ -22,15 +20,12 @@ function getUrlParams({
|
|
|
22
20
|
}) {
|
|
23
21
|
const algoliaAgent = urlSearchParams.get('x-algolia-agent') || '';
|
|
24
22
|
const searchParams = {};
|
|
25
|
-
|
|
26
23
|
for (const [k, v] of urlSearchParams) {
|
|
27
24
|
if (k === 'x-algolia-agent') {
|
|
28
25
|
continue;
|
|
29
26
|
}
|
|
30
|
-
|
|
31
27
|
searchParams[k] = v;
|
|
32
28
|
}
|
|
33
|
-
|
|
34
29
|
return {
|
|
35
30
|
host,
|
|
36
31
|
algoliaAgent,
|
|
@@ -38,7 +33,6 @@ function getUrlParams({
|
|
|
38
33
|
path: pathname
|
|
39
34
|
};
|
|
40
35
|
}
|
|
41
|
-
|
|
42
36
|
function createEchoRequester({
|
|
43
37
|
getURL,
|
|
44
38
|
status = 200
|
|
@@ -50,7 +44,8 @@ function createEchoRequester({
|
|
|
50
44
|
algoliaAgent,
|
|
51
45
|
path
|
|
52
46
|
} = getUrlParams(getURL(request.url));
|
|
53
|
-
const content = {
|
|
47
|
+
const content = {
|
|
48
|
+
...request,
|
|
54
49
|
data: request.data ? JSON.parse(request.data) : undefined,
|
|
55
50
|
path,
|
|
56
51
|
host,
|
|
@@ -63,7 +58,6 @@ function createEchoRequester({
|
|
|
63
58
|
status
|
|
64
59
|
});
|
|
65
60
|
}
|
|
66
|
-
|
|
67
61
|
return {
|
|
68
62
|
send
|
|
69
63
|
};
|
|
@@ -92,15 +86,12 @@ function createIterablePromise({
|
|
|
92
86
|
if (aggregator) {
|
|
93
87
|
aggregator(response);
|
|
94
88
|
}
|
|
95
|
-
|
|
96
89
|
if (validate(response)) {
|
|
97
90
|
return resolve(response);
|
|
98
91
|
}
|
|
99
|
-
|
|
100
92
|
if (error && error.validate(response)) {
|
|
101
93
|
return reject(new Error(error.message(response)));
|
|
102
94
|
}
|
|
103
|
-
|
|
104
95
|
return setTimeout(() => {
|
|
105
96
|
retry(response).then(resolve).catch(reject);
|
|
106
97
|
}, timeout());
|
|
@@ -109,27 +100,22 @@ function createIterablePromise({
|
|
|
109
100
|
});
|
|
110
101
|
});
|
|
111
102
|
};
|
|
112
|
-
|
|
113
103
|
return retry();
|
|
114
104
|
}
|
|
115
105
|
|
|
116
106
|
function createBrowserLocalStorageCache(options) {
|
|
117
|
-
let storage;
|
|
118
|
-
|
|
107
|
+
let storage;
|
|
108
|
+
// We've changed the namespace to avoid conflicts with v4, as this version is a huge breaking change
|
|
119
109
|
const namespaceKey = `algolia-client-js-${options.key}`;
|
|
120
|
-
|
|
121
110
|
function getStorage() {
|
|
122
111
|
if (storage === undefined) {
|
|
123
112
|
storage = options.localStorage || window.localStorage;
|
|
124
113
|
}
|
|
125
|
-
|
|
126
114
|
return storage;
|
|
127
115
|
}
|
|
128
|
-
|
|
129
116
|
function getNamespace() {
|
|
130
117
|
return JSON.parse(getStorage().getItem(namespaceKey) || '{}');
|
|
131
118
|
}
|
|
132
|
-
|
|
133
119
|
return {
|
|
134
120
|
get(key, defaultValue, events = {
|
|
135
121
|
miss: () => Promise.resolve()
|
|
@@ -142,7 +128,6 @@ function createBrowserLocalStorageCache(options) {
|
|
|
142
128
|
return Promise.all([value, exists || events.miss(value)]);
|
|
143
129
|
}).then(([value]) => value);
|
|
144
130
|
},
|
|
145
|
-
|
|
146
131
|
set(key, value) {
|
|
147
132
|
return Promise.resolve().then(() => {
|
|
148
133
|
const namespace = getNamespace();
|
|
@@ -151,7 +136,6 @@ function createBrowserLocalStorageCache(options) {
|
|
|
151
136
|
return value;
|
|
152
137
|
});
|
|
153
138
|
},
|
|
154
|
-
|
|
155
139
|
delete(key) {
|
|
156
140
|
return Promise.resolve().then(() => {
|
|
157
141
|
const namespace = getNamespace();
|
|
@@ -159,13 +143,11 @@ function createBrowserLocalStorageCache(options) {
|
|
|
159
143
|
getStorage().setItem(namespaceKey, JSON.stringify(namespace));
|
|
160
144
|
});
|
|
161
145
|
},
|
|
162
|
-
|
|
163
146
|
clear() {
|
|
164
147
|
return Promise.resolve().then(() => {
|
|
165
148
|
getStorage().removeItem(namespaceKey);
|
|
166
149
|
});
|
|
167
150
|
}
|
|
168
|
-
|
|
169
151
|
};
|
|
170
152
|
}
|
|
171
153
|
|
|
@@ -177,30 +159,24 @@ function createNullCache() {
|
|
|
177
159
|
const value = defaultValue();
|
|
178
160
|
return value.then(result => Promise.all([result, events.miss(result)])).then(([result]) => result);
|
|
179
161
|
},
|
|
180
|
-
|
|
181
162
|
set(_key, value) {
|
|
182
163
|
return Promise.resolve(value);
|
|
183
164
|
},
|
|
184
|
-
|
|
185
165
|
delete(_key) {
|
|
186
166
|
return Promise.resolve();
|
|
187
167
|
},
|
|
188
|
-
|
|
189
168
|
clear() {
|
|
190
169
|
return Promise.resolve();
|
|
191
170
|
}
|
|
192
|
-
|
|
193
171
|
};
|
|
194
172
|
}
|
|
195
173
|
|
|
196
174
|
function createFallbackableCache(options) {
|
|
197
175
|
const caches = [...options.caches];
|
|
198
176
|
const current = caches.shift();
|
|
199
|
-
|
|
200
177
|
if (current === undefined) {
|
|
201
178
|
return createNullCache();
|
|
202
179
|
}
|
|
203
|
-
|
|
204
180
|
return {
|
|
205
181
|
get(key, defaultValue, events = {
|
|
206
182
|
miss: () => Promise.resolve()
|
|
@@ -211,7 +187,6 @@ function createFallbackableCache(options) {
|
|
|
211
187
|
}).get(key, defaultValue, events);
|
|
212
188
|
});
|
|
213
189
|
},
|
|
214
|
-
|
|
215
190
|
set(key, value) {
|
|
216
191
|
return current.set(key, value).catch(() => {
|
|
217
192
|
return createFallbackableCache({
|
|
@@ -219,7 +194,6 @@ function createFallbackableCache(options) {
|
|
|
219
194
|
}).set(key, value);
|
|
220
195
|
});
|
|
221
196
|
},
|
|
222
|
-
|
|
223
197
|
delete(key) {
|
|
224
198
|
return current.delete(key).catch(() => {
|
|
225
199
|
return createFallbackableCache({
|
|
@@ -227,7 +201,6 @@ function createFallbackableCache(options) {
|
|
|
227
201
|
}).delete(key);
|
|
228
202
|
});
|
|
229
203
|
},
|
|
230
|
-
|
|
231
204
|
clear() {
|
|
232
205
|
return current.clear().catch(() => {
|
|
233
206
|
return createFallbackableCache({
|
|
@@ -235,7 +208,6 @@ function createFallbackableCache(options) {
|
|
|
235
208
|
}).clear();
|
|
236
209
|
});
|
|
237
210
|
}
|
|
238
|
-
|
|
239
211
|
};
|
|
240
212
|
}
|
|
241
213
|
|
|
@@ -248,30 +220,24 @@ function createMemoryCache(options = {
|
|
|
248
220
|
miss: () => Promise.resolve()
|
|
249
221
|
}) {
|
|
250
222
|
const keyAsString = JSON.stringify(key);
|
|
251
|
-
|
|
252
223
|
if (keyAsString in cache) {
|
|
253
224
|
return Promise.resolve(options.serializable ? JSON.parse(cache[keyAsString]) : cache[keyAsString]);
|
|
254
225
|
}
|
|
255
|
-
|
|
256
226
|
const promise = defaultValue();
|
|
257
227
|
return promise.then(value => events.miss(value)).then(() => promise);
|
|
258
228
|
},
|
|
259
|
-
|
|
260
229
|
set(key, value) {
|
|
261
230
|
cache[JSON.stringify(key)] = options.serializable ? JSON.stringify(value) : value;
|
|
262
231
|
return Promise.resolve(value);
|
|
263
232
|
},
|
|
264
|
-
|
|
265
233
|
delete(key) {
|
|
266
234
|
delete cache[JSON.stringify(key)];
|
|
267
235
|
return Promise.resolve();
|
|
268
236
|
},
|
|
269
|
-
|
|
270
237
|
clear() {
|
|
271
238
|
cache = {};
|
|
272
239
|
return Promise.resolve();
|
|
273
240
|
}
|
|
274
|
-
|
|
275
241
|
};
|
|
276
242
|
}
|
|
277
243
|
|
|
@@ -280,16 +246,14 @@ function createMemoryCache(options = {
|
|
|
280
246
|
const EXPIRATION_DELAY = 2 * 60 * 1000;
|
|
281
247
|
function createStatefulHost(host, status = 'up') {
|
|
282
248
|
const lastUpdate = Date.now();
|
|
283
|
-
|
|
284
249
|
function isUp() {
|
|
285
250
|
return status === 'up' || Date.now() - lastUpdate > EXPIRATION_DELAY;
|
|
286
251
|
}
|
|
287
|
-
|
|
288
252
|
function isTimedOut() {
|
|
289
253
|
return status === 'timed out' && Date.now() - lastUpdate <= EXPIRATION_DELAY;
|
|
290
254
|
}
|
|
291
|
-
|
|
292
|
-
|
|
255
|
+
return {
|
|
256
|
+
...host,
|
|
293
257
|
status,
|
|
294
258
|
lastUpdate,
|
|
295
259
|
isUp,
|
|
@@ -308,92 +272,74 @@ function _defineProperty(obj, key, value) {
|
|
|
308
272
|
} else {
|
|
309
273
|
obj[key] = value;
|
|
310
274
|
}
|
|
311
|
-
|
|
312
275
|
return obj;
|
|
313
276
|
}
|
|
314
277
|
|
|
315
278
|
class AlgoliaError extends Error {
|
|
316
279
|
constructor(message, name) {
|
|
317
280
|
super(message);
|
|
318
|
-
|
|
319
281
|
_defineProperty(this, "name", 'AlgoliaError');
|
|
320
|
-
|
|
321
282
|
if (name) {
|
|
322
283
|
this.name = name;
|
|
323
284
|
}
|
|
324
285
|
}
|
|
325
|
-
|
|
326
286
|
}
|
|
327
287
|
class ErrorWithStackTrace extends AlgoliaError {
|
|
328
288
|
constructor(message, stackTrace, name) {
|
|
329
|
-
super(message, name);
|
|
330
|
-
|
|
289
|
+
super(message, name);
|
|
290
|
+
// the array and object should be frozen to reflect the stackTrace at the time of the error
|
|
331
291
|
_defineProperty(this, "stackTrace", void 0);
|
|
332
|
-
|
|
333
292
|
this.stackTrace = stackTrace;
|
|
334
293
|
}
|
|
335
|
-
|
|
336
294
|
}
|
|
337
295
|
class RetryError extends ErrorWithStackTrace {
|
|
338
296
|
constructor(stackTrace) {
|
|
339
297
|
super('Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.', stackTrace, 'RetryError');
|
|
340
298
|
}
|
|
341
|
-
|
|
342
299
|
}
|
|
343
300
|
class ApiError extends ErrorWithStackTrace {
|
|
344
301
|
constructor(message, status, stackTrace) {
|
|
345
302
|
super(message, stackTrace, 'ApiError');
|
|
346
|
-
|
|
347
303
|
_defineProperty(this, "status", void 0);
|
|
348
|
-
|
|
349
304
|
this.status = status;
|
|
350
305
|
}
|
|
351
|
-
|
|
352
306
|
}
|
|
353
307
|
class DeserializationError extends AlgoliaError {
|
|
354
308
|
constructor(message, response) {
|
|
355
309
|
super(message, 'DeserializationError');
|
|
356
|
-
|
|
357
310
|
_defineProperty(this, "response", void 0);
|
|
358
|
-
|
|
359
311
|
this.response = response;
|
|
360
312
|
}
|
|
361
|
-
|
|
362
313
|
}
|
|
363
314
|
|
|
364
315
|
function shuffle(array) {
|
|
365
316
|
const shuffledArray = array;
|
|
366
|
-
|
|
367
317
|
for (let c = array.length - 1; c > 0; c--) {
|
|
368
318
|
const b = Math.floor(Math.random() * (c + 1));
|
|
369
319
|
const a = array[c];
|
|
370
320
|
shuffledArray[c] = array[b];
|
|
371
321
|
shuffledArray[b] = a;
|
|
372
322
|
}
|
|
373
|
-
|
|
374
323
|
return shuffledArray;
|
|
375
324
|
}
|
|
376
325
|
function serializeUrl(host, path, queryParameters) {
|
|
377
326
|
const queryParametersAsString = serializeQueryParameters(queryParameters);
|
|
378
327
|
let url = `${host.protocol}://${host.url}/${path.charAt(0) === '/' ? path.substr(1) : path}`;
|
|
379
|
-
|
|
380
328
|
if (queryParametersAsString.length) {
|
|
381
329
|
url += `?${queryParametersAsString}`;
|
|
382
330
|
}
|
|
383
|
-
|
|
384
331
|
return url;
|
|
385
332
|
}
|
|
386
333
|
function serializeQueryParameters(parameters) {
|
|
387
334
|
const isObjectOrArray = value => Object.prototype.toString.call(value) === '[object Object]' || Object.prototype.toString.call(value) === '[object Array]';
|
|
388
|
-
|
|
389
335
|
return Object.keys(parameters).map(key => `${key}=${encodeURIComponent(isObjectOrArray(parameters[key]) ? JSON.stringify(parameters[key]) : parameters[key])}`).join('&');
|
|
390
336
|
}
|
|
391
337
|
function serializeData(request, requestOptions) {
|
|
392
338
|
if (request.method === 'GET' || request.data === undefined && requestOptions.data === undefined) {
|
|
393
339
|
return undefined;
|
|
394
340
|
}
|
|
395
|
-
|
|
396
|
-
|
|
341
|
+
const data = Array.isArray(request.data) ? request.data : {
|
|
342
|
+
...request.data,
|
|
397
343
|
...requestOptions.data
|
|
398
344
|
};
|
|
399
345
|
return JSON.stringify(data);
|
|
@@ -424,12 +370,11 @@ function deserializeFailure({
|
|
|
424
370
|
status
|
|
425
371
|
}, stackFrame) {
|
|
426
372
|
let message = content;
|
|
427
|
-
|
|
428
373
|
try {
|
|
429
374
|
message = JSON.parse(content).message;
|
|
430
|
-
} catch (e) {
|
|
375
|
+
} catch (e) {
|
|
376
|
+
// ..
|
|
431
377
|
}
|
|
432
|
-
|
|
433
378
|
return new ApiError(message, status, stackFrame);
|
|
434
379
|
}
|
|
435
380
|
|
|
@@ -461,9 +406,12 @@ function stackFrameWithoutCredentials(stackFrame) {
|
|
|
461
406
|
const modifiedHeaders = stackFrame.request.headers['x-algolia-api-key'] ? {
|
|
462
407
|
'x-algolia-api-key': '*****'
|
|
463
408
|
} : {};
|
|
464
|
-
return {
|
|
465
|
-
|
|
466
|
-
|
|
409
|
+
return {
|
|
410
|
+
...stackFrame,
|
|
411
|
+
request: {
|
|
412
|
+
...stackFrame.request,
|
|
413
|
+
headers: {
|
|
414
|
+
...stackFrame.request.headers,
|
|
467
415
|
...modifiedHeaders
|
|
468
416
|
}
|
|
469
417
|
}
|
|
@@ -488,13 +436,12 @@ function createTransporter({
|
|
|
488
436
|
});
|
|
489
437
|
}));
|
|
490
438
|
const hostsUp = statefulHosts.filter(host => host.isUp());
|
|
491
|
-
const hostsTimedOut = statefulHosts.filter(host => host.isTimedOut());
|
|
492
|
-
|
|
439
|
+
const hostsTimedOut = statefulHosts.filter(host => host.isTimedOut());
|
|
440
|
+
// Note, we put the hosts that previously timed out on the end of the list.
|
|
493
441
|
const hostsAvailable = [...hostsUp, ...hostsTimedOut];
|
|
494
442
|
const compatibleHostsAvailable = hostsAvailable.length > 0 ? hostsAvailable : compatibleHosts;
|
|
495
443
|
return {
|
|
496
444
|
hosts: compatibleHostsAvailable,
|
|
497
|
-
|
|
498
445
|
getTimeout(timeoutsCount, baseTimeout) {
|
|
499
446
|
/**
|
|
500
447
|
* Imagine that you have 4 hosts, if timeouts will increase
|
|
@@ -510,20 +457,18 @@ function createTransporter({
|
|
|
510
457
|
const timeoutMultiplier = hostsTimedOut.length === 0 && timeoutsCount === 0 ? 1 : hostsTimedOut.length + 3 + timeoutsCount;
|
|
511
458
|
return timeoutMultiplier * baseTimeout;
|
|
512
459
|
}
|
|
513
|
-
|
|
514
460
|
};
|
|
515
461
|
}
|
|
516
|
-
|
|
517
462
|
async function retryableRequest(request, requestOptions, isRead = true) {
|
|
518
463
|
const stackTrace = [];
|
|
519
464
|
/**
|
|
520
465
|
* First we prepare the payload that do not depend from hosts.
|
|
521
466
|
*/
|
|
522
|
-
|
|
523
467
|
const data = serializeData(request, requestOptions);
|
|
524
|
-
const headers = serializeHeaders(baseHeaders, request.headers, requestOptions.headers);
|
|
525
|
-
|
|
526
|
-
const dataQueryParameters = request.method === 'GET' ? {
|
|
468
|
+
const headers = serializeHeaders(baseHeaders, request.headers, requestOptions.headers);
|
|
469
|
+
// On `GET`, the data is proxied to query parameters.
|
|
470
|
+
const dataQueryParameters = request.method === 'GET' ? {
|
|
471
|
+
...request.data,
|
|
527
472
|
...requestOptions.data
|
|
528
473
|
} : {};
|
|
529
474
|
const queryParameters = {
|
|
@@ -532,7 +477,6 @@ function createTransporter({
|
|
|
532
477
|
...request.queryParameters,
|
|
533
478
|
...dataQueryParameters
|
|
534
479
|
};
|
|
535
|
-
|
|
536
480
|
if (requestOptions && requestOptions.queryParameters) {
|
|
537
481
|
for (const key of Object.keys(requestOptions.queryParameters)) {
|
|
538
482
|
// We want to keep `undefined` and `null` values,
|
|
@@ -545,25 +489,19 @@ function createTransporter({
|
|
|
545
489
|
}
|
|
546
490
|
}
|
|
547
491
|
}
|
|
548
|
-
|
|
549
492
|
let timeoutsCount = 0;
|
|
550
|
-
|
|
551
493
|
const retry = async (retryableHosts, getTimeout) => {
|
|
552
494
|
/**
|
|
553
495
|
* We iterate on each host, until there is no host left.
|
|
554
496
|
*/
|
|
555
497
|
const host = retryableHosts.pop();
|
|
556
|
-
|
|
557
498
|
if (host === undefined) {
|
|
558
499
|
throw new RetryError(stackTraceWithoutCredentials(stackTrace));
|
|
559
500
|
}
|
|
560
|
-
|
|
561
501
|
let responseTimeout = requestOptions.timeout;
|
|
562
|
-
|
|
563
502
|
if (responseTimeout === undefined) {
|
|
564
503
|
responseTimeout = isRead ? timeouts.read : timeouts.write;
|
|
565
504
|
}
|
|
566
|
-
|
|
567
505
|
const payload = {
|
|
568
506
|
data,
|
|
569
507
|
headers,
|
|
@@ -577,7 +515,6 @@ function createTransporter({
|
|
|
577
515
|
* can have information about onRetry and onFailure
|
|
578
516
|
* decisions.
|
|
579
517
|
*/
|
|
580
|
-
|
|
581
518
|
const pushToStackTrace = response => {
|
|
582
519
|
const stackFrame = {
|
|
583
520
|
request: payload,
|
|
@@ -588,12 +525,10 @@ function createTransporter({
|
|
|
588
525
|
stackTrace.push(stackFrame);
|
|
589
526
|
return stackFrame;
|
|
590
527
|
};
|
|
591
|
-
|
|
592
528
|
const response = await requester.send(payload);
|
|
593
|
-
|
|
594
529
|
if (isRetryable(response)) {
|
|
595
|
-
const stackFrame = pushToStackTrace(response);
|
|
596
|
-
|
|
530
|
+
const stackFrame = pushToStackTrace(response);
|
|
531
|
+
// If response is a timeout, we increase the number of timeouts so we can increase the timeout later.
|
|
597
532
|
if (response.isTimedOut) {
|
|
598
533
|
timeoutsCount++;
|
|
599
534
|
}
|
|
@@ -603,23 +538,18 @@ function createTransporter({
|
|
|
603
538
|
* when a retry error does not happen.
|
|
604
539
|
*/
|
|
605
540
|
// eslint-disable-next-line no-console -- this will be fixed by exposing a `logger` to the transporter
|
|
606
|
-
|
|
607
|
-
|
|
608
541
|
console.log('Retryable failure', stackFrameWithoutCredentials(stackFrame));
|
|
609
542
|
/**
|
|
610
543
|
* We also store the state of the host in failure cases. If the host, is
|
|
611
544
|
* down it will remain down for the next 2 minutes. In a timeout situation,
|
|
612
545
|
* this host will be added end of the list of hosts on the next request.
|
|
613
546
|
*/
|
|
614
|
-
|
|
615
547
|
await hostsCache.set(host, createStatefulHost(host, response.isTimedOut ? 'timed out' : 'down'));
|
|
616
548
|
return retry(retryableHosts, getTimeout);
|
|
617
549
|
}
|
|
618
|
-
|
|
619
550
|
if (isSuccess(response)) {
|
|
620
551
|
return deserializeSuccess(response);
|
|
621
552
|
}
|
|
622
|
-
|
|
623
553
|
pushToStackTrace(response);
|
|
624
554
|
throw deserializeFailure(response, stackTrace);
|
|
625
555
|
};
|
|
@@ -631,20 +561,16 @@ function createTransporter({
|
|
|
631
561
|
* 2. We also get from the retryable options a timeout multiplier that is tailored
|
|
632
562
|
* for the current context.
|
|
633
563
|
*/
|
|
634
|
-
|
|
635
|
-
|
|
636
564
|
const compatibleHosts = hosts.filter(host => host.accept === 'readWrite' || (isRead ? host.accept === 'read' : host.accept === 'write'));
|
|
637
565
|
const options = await createRetryableOptions(compatibleHosts);
|
|
638
566
|
return retry([...options.hosts].reverse(), options.getTimeout);
|
|
639
567
|
}
|
|
640
|
-
|
|
641
568
|
function createRequest(request, requestOptions = {}) {
|
|
642
569
|
/**
|
|
643
570
|
* A read request is either a `GET` request, or a request that we make
|
|
644
571
|
* via the `read` transporter (e.g. `search`).
|
|
645
572
|
*/
|
|
646
573
|
const isRead = request.useReadTransporter || request.method === 'GET';
|
|
647
|
-
|
|
648
574
|
if (!isRead) {
|
|
649
575
|
/**
|
|
650
576
|
* On write requests, no cache mechanisms are applied, and we
|
|
@@ -652,7 +578,6 @@ function createTransporter({
|
|
|
652
578
|
*/
|
|
653
579
|
return retryableRequest(request, requestOptions, isRead);
|
|
654
580
|
}
|
|
655
|
-
|
|
656
581
|
const createRetryableRequest = () => {
|
|
657
582
|
/**
|
|
658
583
|
* Then, we prepare a function factory that contains the construction of
|
|
@@ -666,14 +591,11 @@ function createTransporter({
|
|
|
666
591
|
* request is "cacheable" - should be cached. Note that, once again,
|
|
667
592
|
* the user can force this option.
|
|
668
593
|
*/
|
|
669
|
-
|
|
670
|
-
|
|
671
594
|
const cacheable = requestOptions.cacheable || request.cacheable;
|
|
672
595
|
/**
|
|
673
596
|
* If is not "cacheable", we immediately trigger the retryable request, no
|
|
674
597
|
* need to check cache implementations.
|
|
675
598
|
*/
|
|
676
|
-
|
|
677
599
|
if (cacheable !== true) {
|
|
678
600
|
return createRetryableRequest();
|
|
679
601
|
}
|
|
@@ -682,8 +604,6 @@ function createTransporter({
|
|
|
682
604
|
* the cache implementations if this request is on progress or if the
|
|
683
605
|
* response already exists on the cache.
|
|
684
606
|
*/
|
|
685
|
-
|
|
686
|
-
|
|
687
607
|
const key = {
|
|
688
608
|
request,
|
|
689
609
|
requestOptions,
|
|
@@ -696,7 +616,6 @@ function createTransporter({
|
|
|
696
616
|
* With the computed key, we first ask the responses cache
|
|
697
617
|
* implementation if this request was been resolved before.
|
|
698
618
|
*/
|
|
699
|
-
|
|
700
619
|
return responsesCache.get(key, () => {
|
|
701
620
|
/**
|
|
702
621
|
* If the request has never resolved before, we actually ask if there
|
|
@@ -718,7 +637,6 @@ function createTransporter({
|
|
|
718
637
|
miss: response => responsesCache.set(key, response)
|
|
719
638
|
});
|
|
720
639
|
}
|
|
721
|
-
|
|
722
640
|
return {
|
|
723
641
|
hostsCache,
|
|
724
642
|
requester,
|
|
@@ -736,17 +654,13 @@ function createTransporter({
|
|
|
736
654
|
function createAlgoliaAgent(version) {
|
|
737
655
|
const algoliaAgent = {
|
|
738
656
|
value: `Algolia for JavaScript (${version})`,
|
|
739
|
-
|
|
740
657
|
add(options) {
|
|
741
658
|
const addedAlgoliaAgent = `; ${options.segment}${options.version !== undefined ? ` (${options.version})` : ''}`;
|
|
742
|
-
|
|
743
659
|
if (algoliaAgent.value.indexOf(addedAlgoliaAgent) === -1) {
|
|
744
660
|
algoliaAgent.value = `${algoliaAgent.value}${addedAlgoliaAgent}`;
|
|
745
661
|
}
|
|
746
|
-
|
|
747
662
|
return algoliaAgent;
|
|
748
663
|
}
|
|
749
|
-
|
|
750
664
|
};
|
|
751
665
|
return algoliaAgent;
|
|
752
666
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@algolia/client-common",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.27",
|
|
4
4
|
"description": "Common package for the Algolia JavaScript API client.",
|
|
5
5
|
"repository": "algolia/algoliasearch-client-javascript",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/jest": "28.1.8",
|
|
23
23
|
"@types/node": "16.11.59",
|
|
24
|
-
"jest": "29.
|
|
25
|
-
"jest-environment-jsdom": "29.
|
|
24
|
+
"jest": "29.2.2",
|
|
25
|
+
"jest-environment-jsdom": "29.2.2",
|
|
26
26
|
"ts-jest": "28.0.8",
|
|
27
27
|
"typescript": "4.8.3"
|
|
28
28
|
},
|