@microlink/mql 0.10.33 → 0.10.35

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/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  <div align="center">
2
- <img src="https://cdn.microlink.io/banner/mql.png" alt="microlink logo">
2
+ <img src="https://github.com/microlinkhq/cdn/raw/master/dist/banner/mql.png#gh-light-mode-only" alt="microlink logo">
3
+ <img src="https://github.com/microlinkhq/cdn/raw/master/dist/banner/mql-dark.png#gh-dark-mode-only" alt="microlink logo">
3
4
  </div>
4
5
 
5
6
  ###### [Documentation](https://microlink.io/mql) | [CLI](https://github.com/microlinkhq/cli) | [Playground](https://mql.microlink.io) | [Chat](https://microlink.io/chat)
package/dist/mql.js CHANGED
@@ -6,11 +6,15 @@
6
6
 
7
7
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
8
8
 
9
+ function getDefaultExportFromCjs (x) {
10
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
11
+ }
12
+
9
13
  const URL$1 = globalThis.URL;
10
14
 
11
15
  const REGEX_HTTP_PROTOCOL = /^https?:\/\//i;
12
16
 
13
- var lightweight = url => {
17
+ var lightweight$2 = url => {
14
18
  try {
15
19
  const { href } = new URL$1(url);
16
20
  return REGEX_HTTP_PROTOCOL.test(href) && href
@@ -103,7 +107,7 @@
103
107
  }, {})
104
108
  };
105
109
 
106
- const fetchFromApi = async (apiUrl, opts = {}, retryCount = 0) => {
110
+ const fetchFromApi = async (apiUrl, opts = {}) => {
107
111
  try {
108
112
  const response = await got(apiUrl, opts);
109
113
  return opts.responseType === 'buffer'
@@ -124,10 +128,6 @@
124
128
  ? rawBody
125
129
  : parseBody(isBodyBuffer ? rawBody.toString() : rawBody, err, uri);
126
130
 
127
- if (body.code === 'EFATALCLIENT' && retryCount++ < 2) {
128
- return fetchFromApi(apiUrl, opts, retryCount)
129
- }
130
-
131
131
  throw new MicrolinkError({
132
132
  ...body,
133
133
  message: body.message,
@@ -181,11 +181,7 @@
181
181
 
182
182
  var factory_1 = factory$1;
183
183
 
184
- var kyExports = {};
185
- var ky$1 = {
186
- get exports(){ return kyExports; },
187
- set exports(v){ kyExports = v; },
188
- };
184
+ var ky$1 = {exports: {}};
189
185
 
190
186
  (function (module, exports) {
191
187
  (function (global, factory) {
@@ -199,6 +195,24 @@
199
195
  const status = `${code} ${title}`.trim();
200
196
  const reason = status ? `status code ${status}` : 'an unknown error';
201
197
  super(`Request failed with ${reason}`);
198
+ Object.defineProperty(this, "response", {
199
+ enumerable: true,
200
+ configurable: true,
201
+ writable: true,
202
+ value: void 0
203
+ });
204
+ Object.defineProperty(this, "request", {
205
+ enumerable: true,
206
+ configurable: true,
207
+ writable: true,
208
+ value: void 0
209
+ });
210
+ Object.defineProperty(this, "options", {
211
+ enumerable: true,
212
+ configurable: true,
213
+ writable: true,
214
+ value: void 0
215
+ });
202
216
  this.name = 'HTTPError';
203
217
  this.response = response;
204
218
  this.request = request;
@@ -209,6 +223,12 @@
209
223
  class TimeoutError extends Error {
210
224
  constructor(request) {
211
225
  super('Request timed out');
226
+ Object.defineProperty(this, "request", {
227
+ enumerable: true,
228
+ configurable: true,
229
+ writable: true,
230
+ value: void 0
231
+ });
212
232
  this.name = 'TimeoutError';
213
233
  this.request = request;
214
234
  }
@@ -219,7 +239,7 @@
219
239
 
220
240
  const validateAndMerge = (...sources) => {
221
241
  for (const source of sources) {
222
- if ((!isObject(source) || Array.isArray(source)) && typeof source !== 'undefined') {
242
+ if ((!isObject(source) || Array.isArray(source)) && source !== undefined) {
223
243
  throw new TypeError('The `options` argument must be an object');
224
244
  }
225
245
  }
@@ -266,8 +286,26 @@
266
286
  return returnValue;
267
287
  };
268
288
 
289
+ const supportsRequestStreams = (() => {
290
+ let duplexAccessed = false;
291
+ let hasContentType = false;
292
+ const supportsReadableStream = typeof globalThis.ReadableStream === 'function';
293
+ const supportsRequest = typeof globalThis.Request === 'function';
294
+ if (supportsReadableStream && supportsRequest) {
295
+ hasContentType = new globalThis.Request('https://empty.invalid', {
296
+ body: new globalThis.ReadableStream(),
297
+ method: 'POST',
298
+ // @ts-expect-error - Types are outdated.
299
+ get duplex() {
300
+ duplexAccessed = true;
301
+ return 'half';
302
+ },
303
+ }).headers.has('Content-Type');
304
+ }
305
+ return duplexAccessed && !hasContentType;
306
+ })();
269
307
  const supportsAbortController = typeof globalThis.AbortController === 'function';
270
- const supportsStreams = typeof globalThis.ReadableStream === 'function';
308
+ const supportsResponseStreams = typeof globalThis.ReadableStream === 'function';
271
309
  const supportsFormData = typeof globalThis.FormData === 'function';
272
310
  const requestMethods = ['get', 'post', 'put', 'patch', 'head', 'delete'];
273
311
  const responseTypes = {
@@ -291,6 +329,7 @@
291
329
  statusCodes: retryStatusCodes,
292
330
  afterStatusCodes: retryAfterStatusCodes,
293
331
  maxRetryAfter: Number.POSITIVE_INFINITY,
332
+ backoffLimit: Number.POSITIVE_INFINITY,
294
333
  };
295
334
  const normalizeRetryOptions = (retry = {}) => {
296
335
  if (typeof retry === 'number') {
@@ -313,30 +352,139 @@
313
352
  };
314
353
 
315
354
  // `Promise.race()` workaround (#91)
316
- const timeout = async (request, abortController, options) => new Promise((resolve, reject) => {
317
- const timeoutId = setTimeout(() => {
318
- if (abortController) {
319
- abortController.abort();
355
+ async function timeout(request, abortController, options) {
356
+ return new Promise((resolve, reject) => {
357
+ const timeoutId = setTimeout(() => {
358
+ if (abortController) {
359
+ abortController.abort();
360
+ }
361
+ reject(new TimeoutError(request));
362
+ }, options.timeout);
363
+ void options
364
+ .fetch(request)
365
+ .then(resolve)
366
+ .catch(reject)
367
+ .then(() => {
368
+ clearTimeout(timeoutId);
369
+ });
370
+ });
371
+ }
372
+
373
+ // https://github.com/sindresorhus/delay/tree/ab98ae8dfcb38e1593286c94d934e70d14a4e111
374
+ async function delay(ms, { signal }) {
375
+ return new Promise((resolve, reject) => {
376
+ if (signal) {
377
+ signal.throwIfAborted();
378
+ signal.addEventListener('abort', abortHandler, { once: true });
379
+ }
380
+ function abortHandler() {
381
+ clearTimeout(timeoutId);
382
+ reject(signal.reason);
320
383
  }
321
- reject(new TimeoutError(request));
322
- }, options.timeout);
323
- void options
324
- .fetch(request)
325
- .then(resolve)
326
- .catch(reject)
327
- .then(() => {
328
- clearTimeout(timeoutId);
384
+ const timeoutId = setTimeout(() => {
385
+ signal?.removeEventListener('abort', abortHandler);
386
+ resolve();
387
+ }, ms);
329
388
  });
330
- });
331
- const delay = async (ms) => new Promise(resolve => {
332
- setTimeout(resolve, ms);
333
- });
389
+ }
334
390
 
335
391
  class Ky {
392
+ static create(input, options) {
393
+ const ky = new Ky(input, options);
394
+ const fn = async () => {
395
+ if (typeof ky._options.timeout === 'number' && ky._options.timeout > maxSafeTimeout) {
396
+ throw new RangeError(`The \`timeout\` option cannot be greater than ${maxSafeTimeout}`);
397
+ }
398
+ // Delay the fetch so that body method shortcuts can set the Accept header
399
+ await Promise.resolve();
400
+ let response = await ky._fetch();
401
+ for (const hook of ky._options.hooks.afterResponse) {
402
+ // eslint-disable-next-line no-await-in-loop
403
+ const modifiedResponse = await hook(ky.request, ky._options, ky._decorateResponse(response.clone()));
404
+ if (modifiedResponse instanceof globalThis.Response) {
405
+ response = modifiedResponse;
406
+ }
407
+ }
408
+ ky._decorateResponse(response);
409
+ if (!response.ok && ky._options.throwHttpErrors) {
410
+ let error = new HTTPError(response, ky.request, ky._options);
411
+ for (const hook of ky._options.hooks.beforeError) {
412
+ // eslint-disable-next-line no-await-in-loop
413
+ error = await hook(error);
414
+ }
415
+ throw error;
416
+ }
417
+ // If `onDownloadProgress` is passed, it uses the stream API internally
418
+ /* istanbul ignore next */
419
+ if (ky._options.onDownloadProgress) {
420
+ if (typeof ky._options.onDownloadProgress !== 'function') {
421
+ throw new TypeError('The `onDownloadProgress` option must be a function');
422
+ }
423
+ if (!supportsResponseStreams) {
424
+ throw new Error('Streams are not supported in your environment. `ReadableStream` is missing.');
425
+ }
426
+ return ky._stream(response.clone(), ky._options.onDownloadProgress);
427
+ }
428
+ return response;
429
+ };
430
+ const isRetriableMethod = ky._options.retry.methods.includes(ky.request.method.toLowerCase());
431
+ const result = (isRetriableMethod ? ky._retry(fn) : fn());
432
+ for (const [type, mimeType] of Object.entries(responseTypes)) {
433
+ result[type] = async () => {
434
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
435
+ ky.request.headers.set('accept', ky.request.headers.get('accept') || mimeType);
436
+ const awaitedResult = await result;
437
+ const response = awaitedResult.clone();
438
+ if (type === 'json') {
439
+ if (response.status === 204) {
440
+ return '';
441
+ }
442
+ const arrayBuffer = await response.clone().arrayBuffer();
443
+ const responseSize = arrayBuffer.byteLength;
444
+ if (responseSize === 0) {
445
+ return '';
446
+ }
447
+ if (options.parseJson) {
448
+ return options.parseJson(await response.text());
449
+ }
450
+ }
451
+ return response[type]();
452
+ };
453
+ }
454
+ return result;
455
+ }
336
456
  // eslint-disable-next-line complexity
337
457
  constructor(input, options = {}) {
338
- var _a, _b, _c;
339
- this._retryCount = 0;
458
+ Object.defineProperty(this, "request", {
459
+ enumerable: true,
460
+ configurable: true,
461
+ writable: true,
462
+ value: void 0
463
+ });
464
+ Object.defineProperty(this, "abortController", {
465
+ enumerable: true,
466
+ configurable: true,
467
+ writable: true,
468
+ value: void 0
469
+ });
470
+ Object.defineProperty(this, "_retryCount", {
471
+ enumerable: true,
472
+ configurable: true,
473
+ writable: true,
474
+ value: 0
475
+ });
476
+ Object.defineProperty(this, "_input", {
477
+ enumerable: true,
478
+ configurable: true,
479
+ writable: true,
480
+ value: void 0
481
+ });
482
+ Object.defineProperty(this, "_options", {
483
+ enumerable: true,
484
+ configurable: true,
485
+ writable: true,
486
+ value: void 0
487
+ });
340
488
  this._input = input;
341
489
  this._options = {
342
490
  // TODO: credentials can be removed when the spec change is implemented in all browsers. Context: https://www.chromestatus.com/feature/4539473312350208
@@ -349,13 +497,13 @@
349
497
  beforeError: [],
350
498
  afterResponse: [],
351
499
  }, options.hooks),
352
- method: normalizeRequestMethod((_a = options.method) !== null && _a !== void 0 ? _a : this._input.method),
500
+ method: normalizeRequestMethod(options.method ?? this._input.method),
353
501
  // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
354
502
  prefixUrl: String(options.prefixUrl || ''),
355
503
  retry: normalizeRetryOptions(options.retry),
356
504
  throwHttpErrors: options.throwHttpErrors !== false,
357
- timeout: typeof options.timeout === 'undefined' ? 10000 : options.timeout,
358
- fetch: (_b = options.fetch) !== null && _b !== void 0 ? _b : globalThis.fetch.bind(globalThis),
505
+ timeout: options.timeout ?? 10000,
506
+ fetch: options.fetch ?? globalThis.fetch.bind(globalThis),
359
507
  };
360
508
  if (typeof this._input !== 'string' && !(this._input instanceof URL || this._input instanceof globalThis.Request)) {
361
509
  throw new TypeError('`input` must be a string, URL, or Request');
@@ -372,12 +520,17 @@
372
520
  if (supportsAbortController) {
373
521
  this.abortController = new globalThis.AbortController();
374
522
  if (this._options.signal) {
523
+ const originalSignal = this._options.signal;
375
524
  this._options.signal.addEventListener('abort', () => {
376
- this.abortController.abort();
525
+ this.abortController.abort(originalSignal.reason);
377
526
  });
378
527
  }
379
528
  this._options.signal = this.abortController.signal;
380
529
  }
530
+ if (supportsRequestStreams) {
531
+ // @ts-expect-error - Types are outdated.
532
+ this._options.duplex = 'half';
533
+ }
381
534
  this.request = new globalThis.Request(this._input, this._options);
382
535
  if (this._options.searchParams) {
383
536
  // eslint-disable-next-line unicorn/prevent-abbreviations
@@ -392,74 +545,15 @@
392
545
  || this._options.body instanceof URLSearchParams) && !(this._options.headers && this._options.headers['content-type'])) {
393
546
  this.request.headers.delete('content-type');
394
547
  }
395
- this.request = new globalThis.Request(new globalThis.Request(url, this.request), this._options);
548
+ // The spread of `this.request` is required as otherwise it misses the `duplex` option for some reason and throws.
549
+ this.request = new globalThis.Request(new globalThis.Request(url, { ...this.request }), this._options);
396
550
  }
397
551
  if (this._options.json !== undefined) {
398
552
  this._options.body = JSON.stringify(this._options.json);
399
- this.request.headers.set('content-type', (_c = this._options.headers.get('content-type')) !== null && _c !== void 0 ? _c : 'application/json');
553
+ this.request.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json');
400
554
  this.request = new globalThis.Request(this.request, { body: this._options.body });
401
555
  }
402
556
  }
403
- // eslint-disable-next-line @typescript-eslint/promise-function-async
404
- static create(input, options) {
405
- const ky = new Ky(input, options);
406
- const fn = async () => {
407
- if (ky._options.timeout > maxSafeTimeout) {
408
- throw new RangeError(`The \`timeout\` option cannot be greater than ${maxSafeTimeout}`);
409
- }
410
- // Delay the fetch so that body method shortcuts can set the Accept header
411
- await Promise.resolve();
412
- let response = await ky._fetch();
413
- for (const hook of ky._options.hooks.afterResponse) {
414
- // eslint-disable-next-line no-await-in-loop
415
- const modifiedResponse = await hook(ky.request, ky._options, ky._decorateResponse(response.clone()));
416
- if (modifiedResponse instanceof globalThis.Response) {
417
- response = modifiedResponse;
418
- }
419
- }
420
- ky._decorateResponse(response);
421
- if (!response.ok && ky._options.throwHttpErrors) {
422
- let error = new HTTPError(response, ky.request, ky._options);
423
- for (const hook of ky._options.hooks.beforeError) {
424
- // eslint-disable-next-line no-await-in-loop
425
- error = await hook(error);
426
- }
427
- throw error;
428
- }
429
- // If `onDownloadProgress` is passed, it uses the stream API internally
430
- /* istanbul ignore next */
431
- if (ky._options.onDownloadProgress) {
432
- if (typeof ky._options.onDownloadProgress !== 'function') {
433
- throw new TypeError('The `onDownloadProgress` option must be a function');
434
- }
435
- if (!supportsStreams) {
436
- throw new Error('Streams are not supported in your environment. `ReadableStream` is missing.');
437
- }
438
- return ky._stream(response.clone(), ky._options.onDownloadProgress);
439
- }
440
- return response;
441
- };
442
- const isRetriableMethod = ky._options.retry.methods.includes(ky.request.method.toLowerCase());
443
- const result = (isRetriableMethod ? ky._retry(fn) : fn());
444
- for (const [type, mimeType] of Object.entries(responseTypes)) {
445
- result[type] = async () => {
446
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
447
- ky.request.headers.set('accept', ky.request.headers.get('accept') || mimeType);
448
- const awaitedResult = await result;
449
- const response = awaitedResult.clone();
450
- if (type === 'json') {
451
- if (response.status === 204) {
452
- return '';
453
- }
454
- if (options.parseJson) {
455
- return options.parseJson(await response.text());
456
- }
457
- }
458
- return response[type]();
459
- };
460
- }
461
- return result;
462
- }
463
557
  _calculateRetryDelay(error) {
464
558
  this._retryCount++;
465
559
  if (this._retryCount < this._options.retry.limit && !(error instanceof TimeoutError)) {
@@ -476,7 +570,7 @@
476
570
  else {
477
571
  after *= 1000;
478
572
  }
479
- if (typeof this._options.retry.maxRetryAfter !== 'undefined' && after > this._options.retry.maxRetryAfter) {
573
+ if (this._options.retry.maxRetryAfter !== undefined && after > this._options.retry.maxRetryAfter) {
480
574
  return 0;
481
575
  }
482
576
  return after;
@@ -486,7 +580,7 @@
486
580
  }
487
581
  }
488
582
  const BACKOFF_FACTOR = 0.3;
489
- return BACKOFF_FACTOR * (2 ** (this._retryCount - 1)) * 1000;
583
+ return Math.min(this._options.retry.backoffLimit, BACKOFF_FACTOR * (2 ** (this._retryCount - 1)) * 1000);
490
584
  }
491
585
  return 0;
492
586
  }
@@ -499,12 +593,11 @@
499
593
  async _retry(fn) {
500
594
  try {
501
595
  return await fn();
502
- // eslint-disable-next-line @typescript-eslint/no-implicit-any-catch
503
596
  }
504
597
  catch (error) {
505
598
  const ms = Math.min(this._calculateRetryDelay(error), maxSafeTimeout);
506
599
  if (ms !== 0 && this._retryCount > 0) {
507
- await delay(ms);
600
+ await delay(ms, { signal: this._options.signal });
508
601
  for (const hook of this._options.hooks.beforeRetry) {
509
602
  // eslint-disable-next-line no-await-in-loop
510
603
  const hookResult = await hook({
@@ -544,6 +637,16 @@
544
637
  _stream(response, onDownloadProgress) {
545
638
  const totalBytes = Number(response.headers.get('content-length')) || 0;
546
639
  let transferredBytes = 0;
640
+ if (response.status === 204) {
641
+ if (onDownloadProgress) {
642
+ onDownloadProgress({ percent: 1, totalBytes, transferredBytes }, new Uint8Array());
643
+ }
644
+ return new globalThis.Response(null, {
645
+ status: response.status,
646
+ statusText: response.statusText,
647
+ headers: response.headers,
648
+ });
649
+ }
547
650
  return new globalThis.Response(new globalThis.ReadableStream({
548
651
  async start(controller) {
549
652
  const reader = response.body.getReader();
@@ -566,7 +669,11 @@
566
669
  }
567
670
  await read();
568
671
  },
569
- }));
672
+ }), {
673
+ status: response.status,
674
+ statusText: response.statusText,
675
+ headers: response.headers,
676
+ });
570
677
  }
571
678
  }
572
679
 
@@ -587,14 +694,16 @@
587
694
 
588
695
  exports.HTTPError = HTTPError;
589
696
  exports.TimeoutError = TimeoutError;
590
- exports["default"] = ky;
697
+ exports.default = ky;
591
698
 
592
699
  Object.defineProperty(exports, '__esModule', { value: true });
593
700
 
594
- }));
595
- } (ky$1, kyExports));
701
+ }));
702
+ } (ky$1, ky$1.exports));
596
703
 
597
- const urlHttp = lightweight;
704
+ var kyExports = ky$1.exports;
705
+
706
+ const urlHttp = lightweight$2;
598
707
  const { flattie: flatten } = dist;
599
708
 
600
709
  const factory = factory_1;
@@ -614,6 +723,7 @@
614
723
 
615
724
  const got = async (url, opts) => {
616
725
  try {
726
+ if (opts.retry > 0) opts.retry = opts.retry + 1;
617
727
  if (opts.timeout === undefined) opts.timeout = false;
618
728
  const response = await ky(url, opts);
619
729
  const body = await response.json();
@@ -639,15 +749,17 @@
639
749
  }
640
750
  };
641
751
 
642
- var browser = factory({
752
+ var lightweight = factory({
643
753
  MicrolinkError,
644
754
  urlHttp,
645
755
  got,
646
756
  flatten,
647
- VERSION: '0.10.33'
757
+ VERSION: '0.10.35'
648
758
  });
649
759
 
650
- return browser;
760
+ var lightweight$1 = /*@__PURE__*/getDefaultExportFromCjs(lightweight);
761
+
762
+ return lightweight$1;
651
763
 
652
764
  }));
653
765
  //# sourceMappingURL=mql.js.map