@microlink/mql 0.11.0-1 → 0.11.0-2

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.
@@ -1,29 +1,93 @@
1
- import require$$0 from 'url-http/lightweight';
2
- import { flattie as require$$1 } from 'flattie';
3
- import require$$3 from 'ky';
4
-
5
1
  function getDefaultExportFromCjs (x) {
6
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
2
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x.default : x
3
+ }
4
+
5
+ function getAugmentedNamespace (n) {
6
+ if (n.__esModule) return n
7
+ const f = n.default
8
+ if (typeof f === 'function') {
9
+ var a = function a () {
10
+ if (this instanceof a) {
11
+ return Reflect.construct(f, arguments, this.constructor)
12
+ }
13
+ return f.apply(this, arguments)
14
+ }
15
+ a.prototype = f.prototype
16
+ } else a = {}
17
+ Object.defineProperty(a, '__esModule', { value: true })
18
+ Object.keys(n).forEach(function (k) {
19
+ const d = Object.getOwnPropertyDescriptor(n, k)
20
+ Object.defineProperty(a, k, d.get
21
+ ? d
22
+ : {
23
+ enumerable: true,
24
+ get: function () {
25
+ return n[k]
26
+ }
27
+ })
28
+ })
29
+ return a
30
+ }
31
+
32
+ const REGEX_HTTP_PROTOCOL = /^https?:\/\//i
33
+
34
+ const lightweight = 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
+ }
42
+
43
+ const dist = {}
44
+
45
+ function iter (output, nullish, sep, val, key) {
46
+ let k; const 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)
59
+ }
60
+ }
61
+ }
62
+
63
+ function flattie (input, glue, toNull) {
64
+ const output = {}
65
+ if (typeof input === 'object') {
66
+ iter(output, !!toNull, glue || '.', input, '')
67
+ }
68
+ return output
7
69
  }
8
70
 
71
+ dist.flattie = flattie
72
+
9
73
  const ENDPOINT = {
10
74
  FREE: 'https://api.microlink.io/',
11
75
  PRO: 'https://pro.microlink.io/'
12
- };
76
+ }
13
77
 
14
- const isObject = input => input !== null && typeof input === 'object';
78
+ const isObject$1 = input => input !== null && typeof input === 'object'
15
79
 
16
80
  const isBuffer = input =>
17
81
  input != null &&
18
82
  input.constructor != null &&
19
83
  typeof input.constructor.isBuffer === 'function' &&
20
- input.constructor.isBuffer(input);
84
+ input.constructor.isBuffer(input)
21
85
 
22
86
  const parseBody = (input, error, url) => {
23
87
  try {
24
88
  return JSON.parse(input)
25
89
  } catch (_) {
26
- const message = input || error.message;
90
+ const message = input || error.message
27
91
 
28
92
  return {
29
93
  status: 'error',
@@ -34,12 +98,12 @@ const parseBody = (input, error, url) => {
34
98
  url
35
99
  }
36
100
  }
37
- };
101
+ }
38
102
 
39
103
  const factory$1 = ({ VERSION, MicrolinkError, urlHttp, got, flatten }) => {
40
104
  const assertUrl = (url = '') => {
41
105
  if (!urlHttp(url)) {
42
- const message = `The \`url\` as \`${url}\` is not valid. Ensure it has protocol (http or https) and hostname.`;
106
+ const message = `The \`url\` as \`${url}\` is not valid. Ensure it has protocol (http or https) and hostname.`
43
107
  throw new MicrolinkError({
44
108
  status: 'fail',
45
109
  data: { url: message },
@@ -49,37 +113,37 @@ const factory$1 = ({ VERSION, MicrolinkError, urlHttp, got, flatten }) => {
49
113
  url
50
114
  })
51
115
  }
52
- };
116
+ }
53
117
 
54
118
  const mapRules = rules => {
55
- if (!isObject(rules)) return
56
- const flatRules = flatten(rules);
119
+ if (!isObject$1(rules)) return
120
+ const flatRules = flatten(rules)
57
121
  return Object.keys(flatRules).reduce((acc, key) => {
58
- acc[`data.${key}`] = flatRules[key].toString();
122
+ acc[`data.${key}`] = flatRules[key].toString()
59
123
  return acc
60
124
  }, {})
61
- };
125
+ }
62
126
 
63
127
  const fetchFromApi = async (apiUrl, opts = {}) => {
64
128
  try {
65
- const response = await got(apiUrl, opts);
129
+ const response = await got(apiUrl, opts)
66
130
  return opts.responseType === 'buffer'
67
131
  ? { body: response.body, response }
68
132
  : { ...response.body, response }
69
133
  } catch (err) {
70
- const { response = {} } = err;
134
+ const { response = {} } = err
71
135
  const {
72
136
  statusCode,
73
137
  body: rawBody,
74
138
  headers = {},
75
139
  url: uri = apiUrl
76
- } = response;
77
- const isBodyBuffer = isBuffer(rawBody);
140
+ } = response
141
+ const isBodyBuffer = isBuffer(rawBody)
78
142
 
79
143
  const body =
80
- isObject(rawBody) && !isBodyBuffer
144
+ isObject$1(rawBody) && !isBodyBuffer
81
145
  ? rawBody
82
- : parseBody(isBodyBuffer ? rawBody.toString() : rawBody, err, uri);
146
+ : parseBody(isBodyBuffer ? rawBody.toString() : rawBody, err, uri)
83
147
 
84
148
  throw new MicrolinkError({
85
149
  ...body,
@@ -89,105 +153,621 @@ const factory$1 = ({ VERSION, MicrolinkError, urlHttp, got, flatten }) => {
89
153
  headers
90
154
  })
91
155
  }
92
- };
156
+ }
93
157
 
94
158
  const getApiUrl = (
95
159
  url,
96
160
  { data, apiKey, endpoint, retry, cache, ...opts } = {},
97
161
  { responseType = 'json', headers: gotHeaders, ...gotOpts } = {}
98
162
  ) => {
99
- const isPro = !!apiKey;
100
- const apiEndpoint = endpoint || ENDPOINT[isPro ? 'PRO' : 'FREE'];
163
+ const isPro = !!apiKey
164
+ const apiEndpoint = endpoint || ENDPOINT[isPro ? 'PRO' : 'FREE']
101
165
 
102
166
  const apiUrl = `${apiEndpoint}?${new URLSearchParams({
103
167
  url,
104
168
  ...mapRules(data),
105
169
  ...flatten(opts)
106
- }).toString()}`;
170
+ }).toString()}`
107
171
 
108
172
  const headers = isPro
109
173
  ? { ...gotHeaders, 'x-api-key': apiKey }
110
- : { ...gotHeaders };
174
+ : { ...gotHeaders }
111
175
  return [apiUrl, { ...gotOpts, responseType, cache, retry, headers }]
112
- };
176
+ }
113
177
 
114
178
  const createMql = defaultOpts => async (url, opts, gotOpts) => {
115
- assertUrl(url);
179
+ assertUrl(url)
116
180
  const [apiUrl, fetchOpts] = getApiUrl(url, opts, {
117
181
  ...defaultOpts,
118
182
  ...gotOpts
119
- });
183
+ })
120
184
  return fetchFromApi(apiUrl, fetchOpts)
121
- };
185
+ }
122
186
 
123
- const mql = createMql();
124
- mql.MicrolinkError = MicrolinkError;
125
- mql.getApiUrl = getApiUrl;
126
- mql.fetchFromApi = fetchFromApi;
127
- mql.mapRules = mapRules;
128
- mql.version = VERSION;
129
- mql.stream = got.stream;
130
- mql.buffer = createMql({ responseType: 'buffer' });
187
+ const mql = createMql()
188
+ mql.MicrolinkError = MicrolinkError
189
+ mql.getApiUrl = getApiUrl
190
+ mql.fetchFromApi = fetchFromApi
191
+ mql.mapRules = mapRules
192
+ mql.version = VERSION
193
+ mql.stream = got.stream
194
+ mql.buffer = createMql({ responseType: 'buffer' })
131
195
 
132
196
  return mql
133
- };
197
+ }
134
198
 
135
- var factory_1 = factory$1;
199
+ const factory_1 = factory$1
136
200
 
137
- const urlHttp = require$$0;
138
- const { flattie: flatten } = require$$1;
201
+ // eslint-lint-disable-next-line @typescript-eslint/naming-convention
202
+ class HTTPError extends Error {
203
+ constructor (response, request, options) {
204
+ const code = (response.status || response.status === 0) ? response.status : ''
205
+ const title = response.statusText || ''
206
+ const status = `${code} ${title}`.trim()
207
+ const reason = status ? `status code ${status}` : 'an unknown error'
208
+ super(`Request failed with ${reason}`)
209
+ Object.defineProperty(this, 'response', {
210
+ enumerable: true,
211
+ configurable: true,
212
+ writable: true,
213
+ value: void 0
214
+ })
215
+ Object.defineProperty(this, 'request', {
216
+ enumerable: true,
217
+ configurable: true,
218
+ writable: true,
219
+ value: void 0
220
+ })
221
+ Object.defineProperty(this, 'options', {
222
+ enumerable: true,
223
+ configurable: true,
224
+ writable: true,
225
+ value: void 0
226
+ })
227
+ this.name = 'HTTPError'
228
+ this.response = response
229
+ this.request = request
230
+ this.options = options
231
+ }
232
+ }
233
+
234
+ class TimeoutError extends Error {
235
+ constructor (request) {
236
+ super('Request timed out')
237
+ Object.defineProperty(this, 'request', {
238
+ enumerable: true,
239
+ configurable: true,
240
+ writable: true,
241
+ value: void 0
242
+ })
243
+ this.name = 'TimeoutError'
244
+ this.request = request
245
+ }
246
+ }
247
+
248
+ // eslint-disable-next-line @typescript-eslint/ban-types
249
+ const isObject = (value) => value !== null && typeof value === 'object'
250
+
251
+ const validateAndMerge = (...sources) => {
252
+ for (const source of sources) {
253
+ if ((!isObject(source) || Array.isArray(source)) && source !== undefined) {
254
+ throw new TypeError('The `options` argument must be an object')
255
+ }
256
+ }
257
+ return deepMerge({}, ...sources)
258
+ }
259
+ const mergeHeaders = (source1 = {}, source2 = {}) => {
260
+ const result = new globalThis.Headers(source1)
261
+ const isHeadersInstance = source2 instanceof globalThis.Headers
262
+ const source = new globalThis.Headers(source2)
263
+ for (const [key, value] of source.entries()) {
264
+ if ((isHeadersInstance && value === 'undefined') || value === undefined) {
265
+ result.delete(key)
266
+ } else {
267
+ result.set(key, value)
268
+ }
269
+ }
270
+ return result
271
+ }
272
+ // TODO: Make this strongly-typed (no `any`).
273
+ const deepMerge = (...sources) => {
274
+ let returnValue = {}
275
+ let headers = {}
276
+ for (const source of sources) {
277
+ if (Array.isArray(source)) {
278
+ if (!Array.isArray(returnValue)) {
279
+ returnValue = []
280
+ }
281
+ returnValue = [...returnValue, ...source]
282
+ } else if (isObject(source)) {
283
+ for (let [key, value] of Object.entries(source)) {
284
+ if (isObject(value) && key in returnValue) {
285
+ value = deepMerge(returnValue[key], value)
286
+ }
287
+ returnValue = { ...returnValue, [key]: value }
288
+ }
289
+ if (isObject(source.headers)) {
290
+ headers = mergeHeaders(headers, source.headers)
291
+ returnValue.headers = headers
292
+ }
293
+ }
294
+ }
295
+ return returnValue
296
+ }
139
297
 
140
- const factory = factory_1;
141
- const { default: ky } = require$$3;
298
+ const supportsRequestStreams = (() => {
299
+ let duplexAccessed = false
300
+ let hasContentType = false
301
+ const supportsReadableStream = typeof globalThis.ReadableStream === 'function'
302
+ const supportsRequest = typeof globalThis.Request === 'function'
303
+ if (supportsReadableStream && supportsRequest) {
304
+ hasContentType = new globalThis.Request('https://empty.invalid', {
305
+ body: new globalThis.ReadableStream(),
306
+ method: 'POST',
307
+ // @ts-expect-error - Types are outdated.
308
+ get duplex () {
309
+ duplexAccessed = true
310
+ return 'half'
311
+ }
312
+ }).headers.has('Content-Type')
313
+ }
314
+ return duplexAccessed && !hasContentType
315
+ })()
316
+ const supportsAbortController = typeof globalThis.AbortController === 'function'
317
+ const supportsResponseStreams = typeof globalThis.ReadableStream === 'function'
318
+ const supportsFormData = typeof globalThis.FormData === 'function'
319
+ const requestMethods = ['get', 'post', 'put', 'patch', 'head', 'delete']
320
+ const responseTypes = {
321
+ json: 'application/json',
322
+ text: 'text/*',
323
+ formData: 'multipart/form-data',
324
+ arrayBuffer: '*/*',
325
+ blob: '*/*'
326
+ }
327
+ // The maximum value of a 32bit int (see issue #117)
328
+ const maxSafeTimeout = 2147483647
329
+ const stop = Symbol('stop')
330
+
331
+ const normalizeRequestMethod = (input) => requestMethods.includes(input) ? input.toUpperCase() : input
332
+ const retryMethods = ['get', 'put', 'head', 'delete', 'options', 'trace']
333
+ const retryStatusCodes = [408, 413, 429, 500, 502, 503, 504]
334
+ const retryAfterStatusCodes = [413, 429, 503]
335
+ const defaultRetryOptions = {
336
+ limit: 2,
337
+ methods: retryMethods,
338
+ statusCodes: retryStatusCodes,
339
+ afterStatusCodes: retryAfterStatusCodes,
340
+ maxRetryAfter: Number.POSITIVE_INFINITY,
341
+ backoffLimit: Number.POSITIVE_INFINITY
342
+ }
343
+ const normalizeRetryOptions = (retry = {}) => {
344
+ if (typeof retry === 'number') {
345
+ return {
346
+ ...defaultRetryOptions,
347
+ limit: retry
348
+ }
349
+ }
350
+ if (retry.methods && !Array.isArray(retry.methods)) {
351
+ throw new Error('retry.methods must be an array')
352
+ }
353
+ if (retry.statusCodes && !Array.isArray(retry.statusCodes)) {
354
+ throw new Error('retry.statusCodes must be an array')
355
+ }
356
+ return {
357
+ ...defaultRetryOptions,
358
+ ...retry,
359
+ afterStatusCodes: retryAfterStatusCodes
360
+ }
361
+ }
362
+
363
+ // `Promise.race()` workaround (#91)
364
+ async function timeout (request, abortController, options) {
365
+ return new Promise((resolve, reject) => {
366
+ const timeoutId = setTimeout(() => {
367
+ if (abortController) {
368
+ abortController.abort()
369
+ }
370
+ reject(new TimeoutError(request))
371
+ }, options.timeout)
372
+ void options
373
+ .fetch(request)
374
+ .then(resolve)
375
+ .catch(reject)
376
+ .then(() => {
377
+ clearTimeout(timeoutId)
378
+ })
379
+ })
380
+ }
381
+
382
+ // https://github.com/sindresorhus/delay/tree/ab98ae8dfcb38e1593286c94d934e70d14a4e111
383
+ async function delay (ms, { signal }) {
384
+ return new Promise((resolve, reject) => {
385
+ if (signal) {
386
+ signal.throwIfAborted()
387
+ signal.addEventListener('abort', abortHandler, { once: true })
388
+ }
389
+ function abortHandler () {
390
+ clearTimeout(timeoutId)
391
+ reject(signal.reason)
392
+ }
393
+ const timeoutId = setTimeout(() => {
394
+ signal?.removeEventListener('abort', abortHandler)
395
+ resolve()
396
+ }, ms)
397
+ })
398
+ }
399
+
400
+ class Ky {
401
+ static create (input, options) {
402
+ const ky = new Ky(input, options)
403
+ const fn = async () => {
404
+ if (typeof ky._options.timeout === 'number' && ky._options.timeout > maxSafeTimeout) {
405
+ throw new RangeError(`The \`timeout\` option cannot be greater than ${maxSafeTimeout}`)
406
+ }
407
+ // Delay the fetch so that body method shortcuts can set the Accept header
408
+ await Promise.resolve()
409
+ let response = await ky._fetch()
410
+ for (const hook of ky._options.hooks.afterResponse) {
411
+ // eslint-disable-next-line no-await-in-loop
412
+ const modifiedResponse = await hook(ky.request, ky._options, ky._decorateResponse(response.clone()))
413
+ if (modifiedResponse instanceof globalThis.Response) {
414
+ response = modifiedResponse
415
+ }
416
+ }
417
+ ky._decorateResponse(response)
418
+ if (!response.ok && ky._options.throwHttpErrors) {
419
+ let error = new HTTPError(response, ky.request, ky._options)
420
+ for (const hook of ky._options.hooks.beforeError) {
421
+ // eslint-disable-next-line no-await-in-loop
422
+ error = await hook(error)
423
+ }
424
+ throw error
425
+ }
426
+ // If `onDownloadProgress` is passed, it uses the stream API internally
427
+ /* istanbul ignore next */
428
+ if (ky._options.onDownloadProgress) {
429
+ if (typeof ky._options.onDownloadProgress !== 'function') {
430
+ throw new TypeError('The `onDownloadProgress` option must be a function')
431
+ }
432
+ if (!supportsResponseStreams) {
433
+ throw new Error('Streams are not supported in your environment. `ReadableStream` is missing.')
434
+ }
435
+ return ky._stream(response.clone(), ky._options.onDownloadProgress)
436
+ }
437
+ return response
438
+ }
439
+ const isRetriableMethod = ky._options.retry.methods.includes(ky.request.method.toLowerCase())
440
+ const result = (isRetriableMethod ? ky._retry(fn) : fn())
441
+ for (const [type, mimeType] of Object.entries(responseTypes)) {
442
+ result[type] = async () => {
443
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
444
+ ky.request.headers.set('accept', ky.request.headers.get('accept') || mimeType)
445
+ const awaitedResult = await result
446
+ const response = awaitedResult.clone()
447
+ if (type === 'json') {
448
+ if (response.status === 204) {
449
+ return ''
450
+ }
451
+ const arrayBuffer = await response.clone().arrayBuffer()
452
+ const responseSize = arrayBuffer.byteLength
453
+ if (responseSize === 0) {
454
+ return ''
455
+ }
456
+ if (options.parseJson) {
457
+ return options.parseJson(await response.text())
458
+ }
459
+ }
460
+ return response[type]()
461
+ }
462
+ }
463
+ return result
464
+ }
465
+
466
+ // eslint-disable-next-line complexity
467
+ constructor (input, options = {}) {
468
+ Object.defineProperty(this, 'request', {
469
+ enumerable: true,
470
+ configurable: true,
471
+ writable: true,
472
+ value: void 0
473
+ })
474
+ Object.defineProperty(this, 'abortController', {
475
+ enumerable: true,
476
+ configurable: true,
477
+ writable: true,
478
+ value: void 0
479
+ })
480
+ Object.defineProperty(this, '_retryCount', {
481
+ enumerable: true,
482
+ configurable: true,
483
+ writable: true,
484
+ value: 0
485
+ })
486
+ Object.defineProperty(this, '_input', {
487
+ enumerable: true,
488
+ configurable: true,
489
+ writable: true,
490
+ value: void 0
491
+ })
492
+ Object.defineProperty(this, '_options', {
493
+ enumerable: true,
494
+ configurable: true,
495
+ writable: true,
496
+ value: void 0
497
+ })
498
+ this._input = input
499
+ this._options = {
500
+ // TODO: credentials can be removed when the spec change is implemented in all browsers. Context: https://www.chromestatus.com/feature/4539473312350208
501
+ credentials: this._input.credentials || 'same-origin',
502
+ ...options,
503
+ headers: mergeHeaders(this._input.headers, options.headers),
504
+ hooks: deepMerge({
505
+ beforeRequest: [],
506
+ beforeRetry: [],
507
+ beforeError: [],
508
+ afterResponse: []
509
+ }, options.hooks),
510
+ method: normalizeRequestMethod(options.method ?? this._input.method),
511
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
512
+ prefixUrl: String(options.prefixUrl || ''),
513
+ retry: normalizeRetryOptions(options.retry),
514
+ throwHttpErrors: options.throwHttpErrors !== false,
515
+ timeout: options.timeout ?? 10000,
516
+ fetch: options.fetch ?? globalThis.fetch.bind(globalThis)
517
+ }
518
+ if (typeof this._input !== 'string' && !(this._input instanceof URL || this._input instanceof globalThis.Request)) {
519
+ throw new TypeError('`input` must be a string, URL, or Request')
520
+ }
521
+ if (this._options.prefixUrl && typeof this._input === 'string') {
522
+ if (this._input.startsWith('/')) {
523
+ throw new Error('`input` must not begin with a slash when using `prefixUrl`')
524
+ }
525
+ if (!this._options.prefixUrl.endsWith('/')) {
526
+ this._options.prefixUrl += '/'
527
+ }
528
+ this._input = this._options.prefixUrl + this._input
529
+ }
530
+ if (supportsAbortController) {
531
+ this.abortController = new globalThis.AbortController()
532
+ if (this._options.signal) {
533
+ const originalSignal = this._options.signal
534
+ this._options.signal.addEventListener('abort', () => {
535
+ this.abortController.abort(originalSignal.reason)
536
+ })
537
+ }
538
+ this._options.signal = this.abortController.signal
539
+ }
540
+ if (supportsRequestStreams) {
541
+ // @ts-expect-error - Types are outdated.
542
+ this._options.duplex = 'half'
543
+ }
544
+ this.request = new globalThis.Request(this._input, this._options)
545
+ if (this._options.searchParams) {
546
+ // eslint-disable-next-line unicorn/prevent-abbreviations
547
+ const textSearchParams = typeof this._options.searchParams === 'string'
548
+ ? this._options.searchParams.replace(/^\?/, '')
549
+ : new URLSearchParams(this._options.searchParams).toString()
550
+ // eslint-disable-next-line unicorn/prevent-abbreviations
551
+ const searchParams = '?' + textSearchParams
552
+ const url = this.request.url.replace(/(?:\?.*?)?(?=#|$)/, searchParams)
553
+ // To provide correct form boundary, Content-Type header should be deleted each time when new Request instantiated from another one
554
+ if (((supportsFormData && this._options.body instanceof globalThis.FormData) ||
555
+ this._options.body instanceof URLSearchParams) && !(this._options.headers && this._options.headers['content-type'])) {
556
+ this.request.headers.delete('content-type')
557
+ }
558
+ // The spread of `this.request` is required as otherwise it misses the `duplex` option for some reason and throws.
559
+ this.request = new globalThis.Request(new globalThis.Request(url, { ...this.request }), this._options)
560
+ }
561
+ if (this._options.json !== undefined) {
562
+ this._options.body = JSON.stringify(this._options.json)
563
+ this.request.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json')
564
+ this.request = new globalThis.Request(this.request, { body: this._options.body })
565
+ }
566
+ }
567
+
568
+ _calculateRetryDelay (error) {
569
+ this._retryCount++
570
+ if (this._retryCount < this._options.retry.limit && !(error instanceof TimeoutError)) {
571
+ if (error instanceof HTTPError) {
572
+ if (!this._options.retry.statusCodes.includes(error.response.status)) {
573
+ return 0
574
+ }
575
+ const retryAfter = error.response.headers.get('Retry-After')
576
+ if (retryAfter && this._options.retry.afterStatusCodes.includes(error.response.status)) {
577
+ let after = Number(retryAfter)
578
+ if (Number.isNaN(after)) {
579
+ after = Date.parse(retryAfter) - Date.now()
580
+ } else {
581
+ after *= 1000
582
+ }
583
+ if (this._options.retry.maxRetryAfter !== undefined && after > this._options.retry.maxRetryAfter) {
584
+ return 0
585
+ }
586
+ return after
587
+ }
588
+ if (error.response.status === 413) {
589
+ return 0
590
+ }
591
+ }
592
+ const BACKOFF_FACTOR = 0.3
593
+ return Math.min(this._options.retry.backoffLimit, BACKOFF_FACTOR * (2 ** (this._retryCount - 1)) * 1000)
594
+ }
595
+ return 0
596
+ }
597
+
598
+ _decorateResponse (response) {
599
+ if (this._options.parseJson) {
600
+ response.json = async () => this._options.parseJson(await response.text())
601
+ }
602
+ return response
603
+ }
604
+
605
+ async _retry (fn) {
606
+ try {
607
+ return await fn()
608
+ } catch (error) {
609
+ const ms = Math.min(this._calculateRetryDelay(error), maxSafeTimeout)
610
+ if (ms !== 0 && this._retryCount > 0) {
611
+ await delay(ms, { signal: this._options.signal })
612
+ for (const hook of this._options.hooks.beforeRetry) {
613
+ // eslint-disable-next-line no-await-in-loop
614
+ const hookResult = await hook({
615
+ request: this.request,
616
+ options: this._options,
617
+ error,
618
+ retryCount: this._retryCount
619
+ })
620
+ // If `stop` is returned from the hook, the retry process is stopped
621
+ if (hookResult === stop) {
622
+ return
623
+ }
624
+ }
625
+ return this._retry(fn)
626
+ }
627
+ throw error
628
+ }
629
+ }
630
+
631
+ async _fetch () {
632
+ for (const hook of this._options.hooks.beforeRequest) {
633
+ // eslint-disable-next-line no-await-in-loop
634
+ const result = await hook(this.request, this._options)
635
+ if (result instanceof Request) {
636
+ this.request = result
637
+ break
638
+ }
639
+ if (result instanceof Response) {
640
+ return result
641
+ }
642
+ }
643
+ if (this._options.timeout === false) {
644
+ return this._options.fetch(this.request.clone())
645
+ }
646
+ return timeout(this.request.clone(), this.abortController, this._options)
647
+ }
648
+
649
+ /* istanbul ignore next */
650
+ _stream (response, onDownloadProgress) {
651
+ const totalBytes = Number(response.headers.get('content-length')) || 0
652
+ let transferredBytes = 0
653
+ if (response.status === 204) {
654
+ if (onDownloadProgress) {
655
+ onDownloadProgress({ percent: 1, totalBytes, transferredBytes }, new Uint8Array())
656
+ }
657
+ return new globalThis.Response(null, {
658
+ status: response.status,
659
+ statusText: response.statusText,
660
+ headers: response.headers
661
+ })
662
+ }
663
+ return new globalThis.Response(new globalThis.ReadableStream({
664
+ async start (controller) {
665
+ const reader = response.body.getReader()
666
+ if (onDownloadProgress) {
667
+ onDownloadProgress({ percent: 0, transferredBytes: 0, totalBytes }, new Uint8Array())
668
+ }
669
+ async function read () {
670
+ const { done, value } = await reader.read()
671
+ if (done) {
672
+ controller.close()
673
+ return
674
+ }
675
+ if (onDownloadProgress) {
676
+ transferredBytes += value.byteLength
677
+ const percent = totalBytes === 0 ? 0 : transferredBytes / totalBytes
678
+ onDownloadProgress({ percent, transferredBytes, totalBytes }, value)
679
+ }
680
+ controller.enqueue(value)
681
+ await read()
682
+ }
683
+ await read()
684
+ }
685
+ }), {
686
+ status: response.status,
687
+ statusText: response.statusText,
688
+ headers: response.headers
689
+ })
690
+ }
691
+ }
692
+
693
+ /*! MIT License © Sindre Sorhus */
694
+ const createInstance = (defaults) => {
695
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
696
+ const ky = (input, options) => Ky.create(input, validateAndMerge(defaults, options))
697
+ for (const method of requestMethods) {
698
+ // eslint-disable-next-line @typescript-eslint/promise-function-async
699
+ ky[method] = (input, options) => Ky.create(input, validateAndMerge(defaults, options, { method }))
700
+ }
701
+ ky.create = (newDefaults) => createInstance(validateAndMerge(newDefaults))
702
+ ky.extend = (newDefaults) => createInstance(validateAndMerge(defaults, newDefaults))
703
+ ky.stop = stop
704
+ return ky
705
+ }
706
+ const ky$1 = createInstance()
707
+
708
+ const distribution = /* #__PURE__ */Object.freeze({
709
+ __proto__: null,
710
+ HTTPError,
711
+ TimeoutError,
712
+ default: ky$1
713
+ })
714
+
715
+ const require$$3 = /* @__PURE__ */getAugmentedNamespace(distribution)
716
+
717
+ const urlHttp = lightweight
718
+ const { flattie: flatten } = dist
719
+
720
+ const factory = factory_1
721
+ const { default: ky } = require$$3
142
722
 
143
723
  class MicrolinkError extends Error {
144
724
  constructor (props) {
145
- super();
146
- this.name = 'MicrolinkError';
147
- Object.assign(this, props);
148
- this.description = this.message;
725
+ super()
726
+ this.name = 'MicrolinkError'
727
+ Object.assign(this, props)
728
+ this.description = this.message
149
729
  this.message = this.code
150
730
  ? `${this.code}, ${this.description}`
151
- : this.description;
731
+ : this.description
152
732
  }
153
733
  }
154
734
 
155
735
  const got = async (url, opts) => {
156
736
  try {
157
- if (opts.retry > 0) opts.retry = opts.retry + 1;
158
- if (opts.timeout === undefined) opts.timeout = false;
159
- const response = await ky(url, opts);
160
- const body = await response.json();
161
- const { headers, status: statusCode } = response;
737
+ if (opts.retry > 0) opts.retry = opts.retry + 1
738
+ if (opts.timeout === undefined) opts.timeout = false
739
+ const response = await ky(url, opts)
740
+ const body = await response.json()
741
+ const { headers, status: statusCode } = response
162
742
  return { url: response.url, body, headers, statusCode }
163
743
  } catch (err) {
164
744
  if (err.response) {
165
- const { response } = err;
745
+ const { response } = err
166
746
  err.response = {
167
747
  ...response,
168
748
  headers: Array.from(response.headers.entries()).reduce(
169
749
  (acc, [key, value]) => {
170
- acc[key] = value;
750
+ acc[key] = value
171
751
  return acc
172
752
  },
173
753
  {}
174
754
  ),
175
755
  statusCode: response.status,
176
756
  body: await response.text()
177
- };
757
+ }
178
758
  }
179
759
  throw err
180
760
  }
181
- };
761
+ }
182
762
 
183
- var lightweight_tpl = factory({
763
+ const lightweight_tpl = factory({
184
764
  MicrolinkError,
185
765
  urlHttp,
186
766
  got,
187
767
  flatten,
188
768
  VERSION: '0.11.0-1'
189
- });
769
+ })
190
770
 
191
- var lightweight_tpl$1 = /*@__PURE__*/getDefaultExportFromCjs(lightweight_tpl);
771
+ const lightweight_tpl$1 = /* @__PURE__ */getDefaultExportFromCjs(lightweight_tpl)
192
772
 
193
- export { lightweight_tpl$1 as default };
773
+ export { lightweight_tpl$1 as default }