@microlink/mql 0.13.5 → 0.13.7

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.
@@ -27,75 +27,55 @@ function getAugmentedNamespace(n) {
27
27
  return a;
28
28
  }
29
29
 
30
- var lightweight$2 = {exports: {}};
31
-
32
- const REGEX_HTTP_PROTOCOL = /^https?:\/\//i;
33
-
34
- var lightweight$1 = url => {
35
- try {
36
- const { href } = new URL(url);
37
- return REGEX_HTTP_PROTOCOL.test(href) && href
38
- } catch (err) {
39
- return false
40
- }
41
- };
30
+ var lightweight$1 = {exports: {}};
42
31
 
43
32
  var dist = {};
44
33
 
45
- function iter(output, nullish, sep, val, key) {
46
- var k, pfx = key ? (key + sep) : key;
47
-
48
- if (val == null) {
49
- if (nullish) output[key] = val;
50
- } else if (typeof val != 'object') {
51
- output[key] = val;
52
- } else if (Array.isArray(val)) {
53
- for (k=0; k < val.length; k++) {
54
- iter(output, nullish, sep, val[k], pfx + k);
55
- }
56
- } else {
57
- for (k in val) {
58
- iter(output, nullish, sep, val[k], pfx + k);
34
+ var hasRequiredDist;
35
+
36
+ function requireDist () {
37
+ if (hasRequiredDist) return dist;
38
+ hasRequiredDist = 1;
39
+ function iter(output, nullish, sep, val, key) {
40
+ var k, pfx = key ? (key + sep) : key;
41
+
42
+ if (val == null) {
43
+ if (nullish) output[key] = val;
44
+ } else if (typeof val != 'object') {
45
+ output[key] = val;
46
+ } else if (Array.isArray(val)) {
47
+ for (k=0; k < val.length; k++) {
48
+ iter(output, nullish, sep, val[k], pfx + k);
49
+ }
50
+ } else {
51
+ for (k in val) {
52
+ iter(output, nullish, sep, val[k], pfx + k);
53
+ }
59
54
  }
60
55
  }
61
- }
62
56
 
63
- function flattie(input, glue, toNull) {
64
- var output = {};
65
- if (typeof input == 'object') {
66
- iter(output, !!toNull, glue || '.', input, '');
57
+ function flattie(input, glue, toNull) {
58
+ var output = {};
59
+ if (typeof input == 'object') {
60
+ iter(output, !!toNull, glue || '.', input, '');
61
+ }
62
+ return output;
67
63
  }
68
- return output;
69
- }
70
64
 
71
- dist.flattie = flattie;
65
+ dist.flattie = flattie;
66
+ return dist;
67
+ }
72
68
 
73
- // eslint-lint-disable-next-line @typescript-eslint/naming-convention
74
69
  class HTTPError extends Error {
70
+ response;
71
+ request;
72
+ options;
75
73
  constructor(response, request, options) {
76
74
  const code = (response.status || response.status === 0) ? response.status : '';
77
75
  const title = response.statusText || '';
78
76
  const status = `${code} ${title}`.trim();
79
77
  const reason = status ? `status code ${status}` : 'an unknown error';
80
- super(`Request failed with ${reason}`);
81
- Object.defineProperty(this, "response", {
82
- enumerable: true,
83
- configurable: true,
84
- writable: true,
85
- value: void 0
86
- });
87
- Object.defineProperty(this, "request", {
88
- enumerable: true,
89
- configurable: true,
90
- writable: true,
91
- value: void 0
92
- });
93
- Object.defineProperty(this, "options", {
94
- enumerable: true,
95
- configurable: true,
96
- writable: true,
97
- value: void 0
98
- });
78
+ super(`Request failed with ${reason}: ${request.method} ${request.url}`);
99
79
  this.name = 'HTTPError';
100
80
  this.response = response;
101
81
  this.request = request;
@@ -104,25 +84,20 @@ class HTTPError extends Error {
104
84
  }
105
85
 
106
86
  class TimeoutError extends Error {
87
+ request;
107
88
  constructor(request) {
108
- super('Request timed out');
109
- Object.defineProperty(this, "request", {
110
- enumerable: true,
111
- configurable: true,
112
- writable: true,
113
- value: void 0
114
- });
89
+ super(`Request timed out: ${request.method} ${request.url}`);
115
90
  this.name = 'TimeoutError';
116
91
  this.request = request;
117
92
  }
118
93
  }
119
94
 
120
95
  // eslint-disable-next-line @typescript-eslint/ban-types
121
- const isObject$1 = (value) => value !== null && typeof value === 'object';
96
+ const isObject = (value) => value !== null && typeof value === 'object';
122
97
 
123
98
  const validateAndMerge = (...sources) => {
124
99
  for (const source of sources) {
125
- if ((!isObject$1(source) || Array.isArray(source)) && source !== undefined) {
100
+ if ((!isObject(source) || Array.isArray(source)) && source !== undefined) {
126
101
  throw new TypeError('The `options` argument must be an object');
127
102
  }
128
103
  }
@@ -142,10 +117,22 @@ const mergeHeaders = (source1 = {}, source2 = {}) => {
142
117
  }
143
118
  return result;
144
119
  };
120
+ function newHookValue(original, incoming, property) {
121
+ return (Object.hasOwn(incoming, property) && incoming[property] === undefined)
122
+ ? []
123
+ : deepMerge(original[property] ?? [], incoming[property] ?? []);
124
+ }
125
+ const mergeHooks = (original = {}, incoming = {}) => ({
126
+ beforeRequest: newHookValue(original, incoming, 'beforeRequest'),
127
+ beforeRetry: newHookValue(original, incoming, 'beforeRetry'),
128
+ afterResponse: newHookValue(original, incoming, 'afterResponse'),
129
+ beforeError: newHookValue(original, incoming, 'beforeError'),
130
+ });
145
131
  // TODO: Make this strongly-typed (no `any`).
146
132
  const deepMerge = (...sources) => {
147
133
  let returnValue = {};
148
134
  let headers = {};
135
+ let hooks = {};
149
136
  for (const source of sources) {
150
137
  if (Array.isArray(source)) {
151
138
  if (!Array.isArray(returnValue)) {
@@ -153,14 +140,18 @@ const deepMerge = (...sources) => {
153
140
  }
154
141
  returnValue = [...returnValue, ...source];
155
142
  }
156
- else if (isObject$1(source)) {
143
+ else if (isObject(source)) {
157
144
  for (let [key, value] of Object.entries(source)) {
158
- if (isObject$1(value) && key in returnValue) {
145
+ if (isObject(value) && key in returnValue) {
159
146
  value = deepMerge(returnValue[key], value);
160
147
  }
161
148
  returnValue = { ...returnValue, [key]: value };
162
149
  }
163
- if (isObject$1(source.headers)) {
150
+ if (isObject(source.hooks)) {
151
+ hooks = mergeHooks(hooks, source.hooks);
152
+ returnValue.hooks = hooks;
153
+ }
154
+ if (isObject(source.headers)) {
164
155
  headers = mergeHeaders(headers, source.headers);
165
156
  returnValue.headers = headers;
166
157
  }
@@ -175,15 +166,24 @@ const supportsRequestStreams = (() => {
175
166
  const supportsReadableStream = typeof globalThis.ReadableStream === 'function';
176
167
  const supportsRequest = typeof globalThis.Request === 'function';
177
168
  if (supportsReadableStream && supportsRequest) {
178
- hasContentType = new globalThis.Request('https://empty.invalid', {
179
- body: new globalThis.ReadableStream(),
180
- method: 'POST',
181
- // @ts-expect-error - Types are outdated.
182
- get duplex() {
183
- duplexAccessed = true;
184
- return 'half';
185
- },
186
- }).headers.has('Content-Type');
169
+ try {
170
+ hasContentType = new globalThis.Request('https://empty.invalid', {
171
+ body: new globalThis.ReadableStream(),
172
+ method: 'POST',
173
+ // @ts-expect-error - Types are outdated.
174
+ get duplex() {
175
+ duplexAccessed = true;
176
+ return 'half';
177
+ },
178
+ }).headers.has('Content-Type');
179
+ }
180
+ catch (error) {
181
+ // QQBrowser on iOS throws "unsupported BodyInit type" error (see issue #581)
182
+ if (error instanceof Error && error.message === 'unsupported BodyInit type') {
183
+ return false;
184
+ }
185
+ throw error;
186
+ }
187
187
  }
188
188
  return duplexAccessed && !hasContentType;
189
189
  })();
@@ -199,11 +199,12 @@ const responseTypes = {
199
199
  blob: '*/*',
200
200
  };
201
201
  // The maximum value of a 32bit int (see issue #117)
202
- const maxSafeTimeout = 2147483647;
202
+ const maxSafeTimeout = 2_147_483_647;
203
203
  const stop = Symbol('stop');
204
204
  const kyOptionKeys = {
205
205
  json: true,
206
206
  parseJson: true,
207
+ stringifyJson: true,
207
208
  searchParams: true,
208
209
  prefixUrl: true,
209
210
  retry: true,
@@ -229,6 +230,7 @@ const requestOptionsRegistry = {
229
230
  window: true,
230
231
  dispatcher: true,
231
232
  duplex: true,
233
+ priority: true,
232
234
  };
233
235
 
234
236
  const normalizeRequestMethod = (input) => requestMethods.includes(input) ? input.toUpperCase() : input;
@@ -260,7 +262,6 @@ const normalizeRetryOptions = (retry = {}) => {
260
262
  return {
261
263
  ...defaultRetryOptions,
262
264
  ...retry,
263
- afterStatusCodes: retryAfterStatusCodes,
264
265
  };
265
266
  };
266
267
 
@@ -376,45 +377,18 @@ class Ky {
376
377
  }
377
378
  return result;
378
379
  }
380
+ request;
381
+ abortController;
382
+ _retryCount = 0;
383
+ _input;
384
+ _options;
379
385
  // eslint-disable-next-line complexity
380
386
  constructor(input, options = {}) {
381
- Object.defineProperty(this, "request", {
382
- enumerable: true,
383
- configurable: true,
384
- writable: true,
385
- value: void 0
386
- });
387
- Object.defineProperty(this, "abortController", {
388
- enumerable: true,
389
- configurable: true,
390
- writable: true,
391
- value: void 0
392
- });
393
- Object.defineProperty(this, "_retryCount", {
394
- enumerable: true,
395
- configurable: true,
396
- writable: true,
397
- value: 0
398
- });
399
- Object.defineProperty(this, "_input", {
400
- enumerable: true,
401
- configurable: true,
402
- writable: true,
403
- value: void 0
404
- });
405
- Object.defineProperty(this, "_options", {
406
- enumerable: true,
407
- configurable: true,
408
- writable: true,
409
- value: void 0
410
- });
411
387
  this._input = input;
412
- const isCredentialsSupported = 'credentials' in Request.prototype;
413
388
  this._options = {
414
- credentials: isCredentialsSupported ? this._input.credentials : undefined,
415
389
  ...options,
416
390
  headers: mergeHeaders(this._input.headers, options.headers),
417
- hooks: deepMerge({
391
+ hooks: mergeHooks({
418
392
  beforeRequest: [],
419
393
  beforeRetry: [],
420
394
  beforeError: [],
@@ -425,7 +399,7 @@ class Ky {
425
399
  prefixUrl: String(options.prefixUrl || ''),
426
400
  retry: normalizeRetryOptions(options.retry),
427
401
  throwHttpErrors: options.throwHttpErrors !== false,
428
- timeout: options.timeout ?? 10000,
402
+ timeout: options.timeout ?? 10_000,
429
403
  fetch: options.fetch ?? globalThis.fetch.bind(globalThis),
430
404
  };
431
405
  if (typeof this._input !== 'string' && !(this._input instanceof URL || this._input instanceof globalThis.Request)) {
@@ -442,18 +416,20 @@ class Ky {
442
416
  }
443
417
  if (supportsAbortController) {
444
418
  this.abortController = new globalThis.AbortController();
445
- if (this._options.signal) {
446
- const originalSignal = this._options.signal;
447
- this._options.signal.addEventListener('abort', () => {
448
- this.abortController.abort(originalSignal.reason);
449
- });
450
- }
419
+ const originalSignal = this._options.signal ?? this._input.signal;
420
+ originalSignal?.addEventListener('abort', () => {
421
+ this.abortController.abort(originalSignal.reason);
422
+ });
451
423
  this._options.signal = this.abortController.signal;
452
424
  }
453
425
  if (supportsRequestStreams) {
454
426
  // @ts-expect-error - Types are outdated.
455
427
  this._options.duplex = 'half';
456
428
  }
429
+ if (this._options.json !== undefined) {
430
+ this._options.body = this._options.stringifyJson?.(this._options.json) ?? JSON.stringify(this._options.json);
431
+ this._options.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json');
432
+ }
457
433
  this.request = new globalThis.Request(this._input, this._options);
458
434
  if (this._options.searchParams) {
459
435
  // eslint-disable-next-line unicorn/prevent-abbreviations
@@ -471,41 +447,38 @@ class Ky {
471
447
  // The spread of `this.request` is required as otherwise it misses the `duplex` option for some reason and throws.
472
448
  this.request = new globalThis.Request(new globalThis.Request(url, { ...this.request }), this._options);
473
449
  }
474
- if (this._options.json !== undefined) {
475
- this._options.body = JSON.stringify(this._options.json);
476
- this.request.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json');
477
- this.request = new globalThis.Request(this.request, { body: this._options.body });
478
- }
479
450
  }
480
451
  _calculateRetryDelay(error) {
481
452
  this._retryCount++;
482
- if (this._retryCount <= this._options.retry.limit && !(error instanceof TimeoutError)) {
483
- if (error instanceof HTTPError) {
484
- if (!this._options.retry.statusCodes.includes(error.response.status)) {
485
- return 0;
486
- }
487
- const retryAfter = error.response.headers.get('Retry-After');
488
- if (retryAfter && this._options.retry.afterStatusCodes.includes(error.response.status)) {
489
- let after = Number(retryAfter);
490
- if (Number.isNaN(after)) {
491
- after = Date.parse(retryAfter) - Date.now();
492
- }
493
- else {
494
- after *= 1000;
495
- }
496
- if (this._options.retry.maxRetryAfter !== undefined && after > this._options.retry.maxRetryAfter) {
497
- return 0;
498
- }
499
- return after;
453
+ if (this._retryCount > this._options.retry.limit || error instanceof TimeoutError) {
454
+ throw error;
455
+ }
456
+ if (error instanceof HTTPError) {
457
+ if (!this._options.retry.statusCodes.includes(error.response.status)) {
458
+ throw error;
459
+ }
460
+ const retryAfter = error.response.headers.get('Retry-After')
461
+ ?? error.response.headers.get('RateLimit-Reset')
462
+ ?? error.response.headers.get('X-RateLimit-Reset') // GitHub
463
+ ?? error.response.headers.get('X-Rate-Limit-Reset'); // Twitter
464
+ if (retryAfter && this._options.retry.afterStatusCodes.includes(error.response.status)) {
465
+ let after = Number(retryAfter) * 1000;
466
+ if (Number.isNaN(after)) {
467
+ after = Date.parse(retryAfter) - Date.now();
500
468
  }
501
- if (error.response.status === 413) {
502
- return 0;
469
+ else if (after >= Date.parse('2024-01-01')) {
470
+ // A large number is treated as a timestamp (fixed threshold protects against clock skew)
471
+ after -= Date.now();
503
472
  }
473
+ const max = this._options.retry.maxRetryAfter ?? after;
474
+ return after < max ? after : max;
475
+ }
476
+ if (error.response.status === 413) {
477
+ throw error;
504
478
  }
505
- const retryDelay = this._options.retry.delay(this._retryCount);
506
- return Math.min(this._options.retry.backoffLimit, retryDelay);
507
479
  }
508
- return 0;
480
+ const retryDelay = this._options.retry.delay(this._retryCount);
481
+ return Math.min(this._options.retry.backoffLimit, retryDelay);
509
482
  }
510
483
  _decorateResponse(response) {
511
484
  if (this._options.parseJson) {
@@ -519,24 +492,24 @@ class Ky {
519
492
  }
520
493
  catch (error) {
521
494
  const ms = Math.min(this._calculateRetryDelay(error), maxSafeTimeout);
522
- if (ms !== 0 && this._retryCount > 0) {
523
- await delay(ms, { signal: this._options.signal });
524
- for (const hook of this._options.hooks.beforeRetry) {
525
- // eslint-disable-next-line no-await-in-loop
526
- const hookResult = await hook({
527
- request: this.request,
528
- options: this._options,
529
- error: error,
530
- retryCount: this._retryCount,
531
- });
532
- // If `stop` is returned from the hook, the retry process is stopped
533
- if (hookResult === stop) {
534
- return;
535
- }
495
+ if (this._retryCount < 1) {
496
+ throw error;
497
+ }
498
+ await delay(ms, { signal: this._options.signal });
499
+ for (const hook of this._options.hooks.beforeRetry) {
500
+ // eslint-disable-next-line no-await-in-loop
501
+ const hookResult = await hook({
502
+ request: this.request,
503
+ options: this._options,
504
+ error: error,
505
+ retryCount: this._retryCount,
506
+ });
507
+ // If `stop` is returned from the hook, the retry process is stopped
508
+ if (hookResult === stop) {
509
+ return;
536
510
  }
537
- return this._retry(function_);
538
511
  }
539
- throw error;
512
+ return this._retry(function_);
540
513
  }
541
514
  }
542
515
  async _fetch() {
@@ -552,10 +525,13 @@ class Ky {
552
525
  }
553
526
  }
554
527
  const nonRequestOptions = findUnknownOptions(this.request, this._options);
528
+ // Cloning is done here to prepare in advance for retries
529
+ const mainRequest = this.request;
530
+ this.request = mainRequest.clone();
555
531
  if (this._options.timeout === false) {
556
- return this._options.fetch(this.request.clone(), nonRequestOptions);
532
+ return this._options.fetch(mainRequest, nonRequestOptions);
557
533
  }
558
- return timeout(this.request.clone(), nonRequestOptions, this.abortController, this._options);
534
+ return timeout(mainRequest, nonRequestOptions, this.abortController, this._options);
559
535
  }
560
536
  /* istanbul ignore next */
561
537
  _stream(response, onDownloadProgress) {
@@ -610,224 +586,250 @@ const createInstance = (defaults) => {
610
586
  ky[method] = (input, options) => Ky.create(input, validateAndMerge(defaults, options, { method }));
611
587
  }
612
588
  ky.create = (newDefaults) => createInstance(validateAndMerge(newDefaults));
613
- ky.extend = (newDefaults) => createInstance(validateAndMerge(defaults, newDefaults));
589
+ ky.extend = (newDefaults) => {
590
+ if (typeof newDefaults === 'function') {
591
+ newDefaults = newDefaults(defaults ?? {});
592
+ }
593
+ return createInstance(validateAndMerge(defaults, newDefaults));
594
+ };
614
595
  ky.stop = stop;
615
596
  return ky;
616
597
  };
617
- const ky$1 = createInstance();
598
+ const ky = createInstance();
618
599
 
619
600
  var distribution = /*#__PURE__*/Object.freeze({
620
601
  __proto__: null,
621
602
  HTTPError: HTTPError,
622
603
  TimeoutError: TimeoutError,
623
- default: ky$1
604
+ default: ky
624
605
  });
625
606
 
626
- var require$$2 = /*@__PURE__*/getAugmentedNamespace(distribution);
627
-
628
- const ENDPOINT = {
629
- FREE: 'https://api.microlink.io/',
630
- PRO: 'https://pro.microlink.io/'
631
- };
632
-
633
- const isObject = input => input !== null && typeof input === 'object';
634
-
635
- const isBuffer = input =>
636
- input != null &&
637
- input.constructor != null &&
638
- typeof input.constructor.isBuffer === 'function' &&
639
- input.constructor.isBuffer(input);
607
+ var require$$1 = /*@__PURE__*/getAugmentedNamespace(distribution);
608
+
609
+ var factory_1;
610
+ var hasRequiredFactory;
611
+
612
+ function requireFactory () {
613
+ if (hasRequiredFactory) return factory_1;
614
+ hasRequiredFactory = 1;
615
+ const ENDPOINT = {
616
+ FREE: 'https://api.microlink.io/',
617
+ PRO: 'https://pro.microlink.io/'
618
+ };
619
+
620
+ const isObject = input => input !== null && typeof input === 'object';
621
+
622
+ const isBuffer = input =>
623
+ input != null &&
624
+ input.constructor != null &&
625
+ typeof input.constructor.isBuffer === 'function' &&
626
+ input.constructor.isBuffer(input);
627
+
628
+ const parseBody = (input, error, url) => {
629
+ try {
630
+ return JSON.parse(input)
631
+ } catch (_) {
632
+ const message = input || error.message;
633
+
634
+ return {
635
+ status: 'error',
636
+ data: { url: message },
637
+ more: 'https://microlink.io/efatalclient',
638
+ code: 'EFATALCLIENT',
639
+ message,
640
+ url
641
+ }
642
+ }
643
+ };
644
+
645
+ const isURL = url => {
646
+ try {
647
+ return /^https?:\/\//i.test(new URL(url).href)
648
+ } catch (_) {
649
+ return false
650
+ }
651
+ };
652
+
653
+ const factory = streamResponseType => ({
654
+ VERSION,
655
+ MicrolinkError,
656
+ got,
657
+ flatten
658
+ }) => {
659
+ const assertUrl = (url = '') => {
660
+ if (!isURL(url)) {
661
+ const message = `The \`url\` as \`${url}\` is not valid. Ensure it has protocol (http or https) and hostname.`;
662
+ throw new MicrolinkError({
663
+ status: 'fail',
664
+ data: { url: message },
665
+ more: 'https://microlink.io/einvalurlclient',
666
+ code: 'EINVALURLCLIENT',
667
+ message,
668
+ url
669
+ })
670
+ }
671
+ };
672
+
673
+ const mapRules = rules => {
674
+ if (!isObject(rules)) return
675
+ const flatRules = flatten(rules);
676
+ return Object.keys(flatRules).reduce((acc, key) => {
677
+ acc[`data.${key}`] = flatRules[key].toString();
678
+ return acc
679
+ }, {})
680
+ };
681
+
682
+ const fetchFromApi = async (apiUrl, opts = {}) => {
683
+ try {
684
+ const response = await got(apiUrl, opts);
685
+ return opts.responseType === streamResponseType
686
+ ? response
687
+ : { ...response.body, response }
688
+ } catch (error) {
689
+ const { response = {} } = error;
690
+ const {
691
+ statusCode,
692
+ body: rawBody,
693
+ headers = {},
694
+ url: uri = apiUrl
695
+ } = response;
696
+ const isBodyBuffer = isBuffer(rawBody);
697
+
698
+ const body =
699
+ isObject(rawBody) && !isBodyBuffer
700
+ ? rawBody
701
+ : parseBody(isBodyBuffer ? rawBody.toString() : rawBody, error, uri);
702
+
703
+ throw new MicrolinkError({
704
+ ...body,
705
+ message: body.message,
706
+ url: uri,
707
+ statusCode,
708
+ headers
709
+ })
710
+ }
711
+ };
712
+
713
+ const getApiUrl = (
714
+ url,
715
+ { data, apiKey, endpoint, retry, cache, ...opts } = {},
716
+ { responseType = 'json', headers: gotHeaders, ...gotOpts } = {}
717
+ ) => {
718
+ const isPro = !!apiKey;
719
+ const apiEndpoint = endpoint || ENDPOINT[isPro ? 'PRO' : 'FREE'];
720
+
721
+ const apiUrl = `${apiEndpoint}?${new URLSearchParams({
722
+ url,
723
+ ...mapRules(data),
724
+ ...flatten(opts)
725
+ }).toString()}`;
726
+
727
+ const headers = isPro
728
+ ? { ...gotHeaders, 'x-api-key': apiKey }
729
+ : { ...gotHeaders };
730
+
731
+ if (opts.stream) {
732
+ responseType = streamResponseType;
733
+ }
734
+ return [apiUrl, { ...gotOpts, responseType, cache, retry, headers }]
735
+ };
736
+
737
+ const createMql = defaultOpts => async (url, opts, gotOpts) => {
738
+ assertUrl(url);
739
+ const [apiUrl, fetchOpts] = getApiUrl(url, opts, {
740
+ ...defaultOpts,
741
+ ...gotOpts
742
+ });
743
+ return fetchFromApi(apiUrl, fetchOpts)
744
+ };
745
+
746
+ const mql = createMql();
747
+ mql.extend = createMql;
748
+ mql.MicrolinkError = MicrolinkError;
749
+ mql.getApiUrl = getApiUrl;
750
+ mql.fetchFromApi = fetchFromApi;
751
+ mql.mapRules = mapRules;
752
+ mql.version = VERSION;
753
+ mql.stream = got.stream;
754
+
755
+ return mql
756
+ };
757
+
758
+ factory_1 = factory;
759
+ return factory_1;
760
+ }
640
761
 
641
- const parseBody = (input, error, url) => {
642
- try {
643
- return JSON.parse(input)
644
- } catch (_) {
645
- const message = input || error.message;
762
+ var hasRequiredLightweight;
646
763
 
647
- return {
648
- status: 'error',
649
- data: { url: message },
650
- more: 'https://microlink.io/efatalclient',
651
- code: 'EFATALCLIENT',
652
- message,
653
- url
654
- }
655
- }
656
- };
764
+ function requireLightweight () {
765
+ if (hasRequiredLightweight) return lightweight$1.exports;
766
+ hasRequiredLightweight = 1;
657
767
 
658
- const factory$1 = streamResponseType => ({
659
- VERSION,
660
- MicrolinkError,
661
- urlHttp,
662
- got,
663
- flatten
664
- }) => {
665
- const assertUrl = (url = '') => {
666
- if (!urlHttp(url)) {
667
- const message = `The \`url\` as \`${url}\` is not valid. Ensure it has protocol (http or https) and hostname.`;
668
- throw new MicrolinkError({
669
- status: 'fail',
670
- data: { url: message },
671
- more: 'https://microlink.io/einvalurlclient',
672
- code: 'EINVALURLCLIENT',
673
- message,
674
- url
675
- })
676
- }
677
- };
678
-
679
- const mapRules = rules => {
680
- if (!isObject(rules)) return
681
- const flatRules = flatten(rules);
682
- return Object.keys(flatRules).reduce((acc, key) => {
683
- acc[`data.${key}`] = flatRules[key].toString();
684
- return acc
685
- }, {})
686
- };
687
-
688
- const fetchFromApi = async (apiUrl, opts = {}) => {
689
- try {
690
- const response = await got(apiUrl, opts);
691
- return opts.responseType === streamResponseType
692
- ? response
693
- : { ...response.body, response }
694
- } catch (error) {
695
- const { response = {} } = error;
696
- const {
697
- statusCode,
698
- body: rawBody,
699
- headers = {},
700
- url: uri = apiUrl
701
- } = response;
702
- const isBodyBuffer = isBuffer(rawBody);
703
-
704
- const body =
705
- isObject(rawBody) && !isBodyBuffer
706
- ? rawBody
707
- : parseBody(isBodyBuffer ? rawBody.toString() : rawBody, error, uri);
708
-
709
- throw new MicrolinkError({
710
- ...body,
711
- message: body.message,
712
- url: uri,
713
- statusCode,
714
- headers
715
- })
716
- }
717
- };
718
-
719
- const getApiUrl = (
720
- url,
721
- { data, apiKey, endpoint, retry, cache, ...opts } = {},
722
- { responseType = 'json', headers: gotHeaders, ...gotOpts } = {}
723
- ) => {
724
- const isPro = !!apiKey;
725
- const apiEndpoint = endpoint || ENDPOINT[isPro ? 'PRO' : 'FREE'];
726
-
727
- const apiUrl = `${apiEndpoint}?${new URLSearchParams({
728
- url,
729
- ...mapRules(data),
730
- ...flatten(opts)
731
- }).toString()}`;
732
-
733
- const headers = isPro
734
- ? { ...gotHeaders, 'x-api-key': apiKey }
735
- : { ...gotHeaders };
736
-
737
- if (opts.stream) {
738
- responseType = streamResponseType;
739
- }
740
- return [apiUrl, { ...gotOpts, responseType, cache, retry, headers }]
741
- };
742
-
743
- const createMql = defaultOpts => async (url, opts, gotOpts) => {
744
- assertUrl(url);
745
- const [apiUrl, fetchOpts] = getApiUrl(url, opts, {
746
- ...defaultOpts,
747
- ...gotOpts
748
- });
749
- return fetchFromApi(apiUrl, fetchOpts)
750
- };
751
-
752
- const mql = createMql();
753
- mql.extend = createMql;
754
- mql.MicrolinkError = MicrolinkError;
755
- mql.getApiUrl = getApiUrl;
756
- mql.fetchFromApi = fetchFromApi;
757
- mql.mapRules = mapRules;
758
- mql.version = VERSION;
759
- mql.stream = got.stream;
760
-
761
- return mql
762
- };
768
+ const { flattie: flatten } = requireDist();
769
+ const { default: ky } = require$$1;
763
770
 
764
- var factory_1 = factory$1;
771
+ const factory = requireFactory()('arrayBuffer');
765
772
 
766
- const urlHttp = lightweight$1;
767
- const { flattie: flatten } = dist;
768
- const { default: ky } = require$$2;
773
+ class MicrolinkError extends Error {
774
+ constructor (props) {
775
+ super();
776
+ this.name = 'MicrolinkError';
777
+ Object.assign(this, props);
778
+ this.description = this.message;
779
+ this.message = this.code
780
+ ? `${this.code}, ${this.description}`
781
+ : this.description;
782
+ }
783
+ }
769
784
 
770
- const factory = factory_1('arrayBuffer');
785
+ const got = async (url, { responseType, ...opts }) => {
786
+ try {
787
+ if (opts.timeout === undefined) opts.timeout = false;
788
+ const response = await ky(url, opts);
789
+ const body = await response[responseType]();
790
+ const { headers, status: statusCode } = response;
791
+ return { url: response.url, body, headers, statusCode }
792
+ } catch (error) {
793
+ if (error.response) {
794
+ const { response } = error;
795
+ error.response = {
796
+ ...response,
797
+ headers: Array.from(response.headers.entries()).reduce(
798
+ (acc, [key, value]) => {
799
+ acc[key] = value;
800
+ return acc
801
+ },
802
+ {}
803
+ ),
804
+ statusCode: response.status,
805
+ body: await response.text()
806
+ };
807
+ }
808
+ throw error
809
+ }
810
+ };
811
+
812
+ got.stream = (...args) => ky(...args).then(res => res.body);
813
+
814
+ const mql = factory({
815
+ MicrolinkError,
816
+ got,
817
+ flatten,
818
+ VERSION: '0.13.7'
819
+ });
771
820
 
772
- class MicrolinkError extends Error {
773
- constructor (props) {
774
- super();
775
- this.name = 'MicrolinkError';
776
- Object.assign(this, props);
777
- this.description = this.message;
778
- this.message = this.code
779
- ? `${this.code}, ${this.description}`
780
- : this.description;
781
- }
821
+ lightweight$1.exports = mql;
822
+ lightweight$1.exports.arrayBuffer = mql.extend({ responseType: 'arrayBuffer' });
823
+ lightweight$1.exports.extend = mql.extend;
824
+ lightweight$1.exports.fetchFromApi = mql.fetchFromApi;
825
+ lightweight$1.exports.getApiUrl = mql.getApiUrl;
826
+ lightweight$1.exports.mapRules = mql.mapRules;
827
+ lightweight$1.exports.MicrolinkError = mql.MicrolinkError;
828
+ lightweight$1.exports.version = mql.version;
829
+ return lightweight$1.exports;
782
830
  }
783
831
 
784
- const got = async (url, { responseType, ...opts }) => {
785
- try {
786
- if (opts.timeout === undefined) opts.timeout = false;
787
- const response = await ky(url, opts);
788
- const body = await response[responseType]();
789
- const { headers, status: statusCode } = response;
790
- return { url: response.url, body, headers, statusCode }
791
- } catch (error) {
792
- if (error.response) {
793
- const { response } = error;
794
- error.response = {
795
- ...response,
796
- headers: Array.from(response.headers.entries()).reduce(
797
- (acc, [key, value]) => {
798
- acc[key] = value;
799
- return acc
800
- },
801
- {}
802
- ),
803
- statusCode: response.status,
804
- body: await response.text()
805
- };
806
- }
807
- throw error
808
- }
809
- };
810
-
811
- got.stream = (...args) => ky(...args).then(res => res.body);
812
-
813
- const mql = factory({
814
- MicrolinkError,
815
- urlHttp,
816
- got,
817
- flatten,
818
- VERSION: '0.13.5'
819
- });
820
-
821
- lightweight$2.exports = mql;
822
- var arrayBuffer = lightweight$2.exports.arrayBuffer = mql.extend({ responseType: 'arrayBuffer' });
823
- var extend = lightweight$2.exports.extend = mql.extend;
824
- var fetchFromApi = lightweight$2.exports.fetchFromApi = mql.fetchFromApi;
825
- var getApiUrl = lightweight$2.exports.getApiUrl = mql.getApiUrl;
826
- var mapRules = lightweight$2.exports.mapRules = mql.mapRules;
827
- var MicrolinkError_1 = lightweight$2.exports.MicrolinkError = mql.MicrolinkError;
828
- var version = lightweight$2.exports.version = mql.version;
829
-
830
- var lightweightExports = lightweight$2.exports;
832
+ var lightweightExports = requireLightweight();
831
833
  var lightweight = /*@__PURE__*/getDefaultExportFromCjs(lightweightExports);
832
834
 
833
- export { MicrolinkError_1 as MicrolinkError, arrayBuffer, lightweight as default, extend, fetchFromApi, getApiUrl, mapRules, version };
835
+ export { lightweight as default };