@algolia/client-common 5.0.0-alpha.26 → 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.
@@ -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 = { ...request,
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; // We've changed the namespace to avoid conflicts with v4, as this version is a huge breaking change
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
- return { ...host,
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); // the array and object should be frozen to reflect the stackTrace at the time of the error
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
- const data = Array.isArray(request.data) ? request.data : { ...request.data,
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 { ...stackFrame,
469
- request: { ...stackFrame.request,
470
- headers: { ...stackFrame.request.headers,
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()); // Note, we put the hosts that previously timed out on the end of the list.
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); // On `GET`, the data is proxied to query parameters.
529
-
530
- const dataQueryParameters = request.method === 'GET' ? { ...request.data,
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); // If response is a timeout, we increase the number of timeouts so we can increase the timeout later.
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 = { ...request,
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; // We've changed the namespace to avoid conflicts with v4, as this version is a huge breaking change
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
- return { ...host,
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); // the array and object should be frozen to reflect the stackTrace at the time of the error
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
- const data = Array.isArray(request.data) ? request.data : { ...request.data,
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 { ...stackFrame,
465
- request: { ...stackFrame.request,
466
- headers: { ...stackFrame.request.headers,
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()); // Note, we put the hosts that previously timed out on the end of the list.
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); // On `GET`, the data is proxied to query parameters.
525
-
526
- const dataQueryParameters = request.method === 'GET' ? { ...request.data,
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); // If response is a timeout, we increase the number of timeouts so we can increase the timeout later.
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.26",
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.0.3",
25
- "jest-environment-jsdom": "29.0.3",
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
  },