@microlink/mql 0.13.6 → 0.13.8
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 +1 -1
- package/lightweight/index.js +129 -153
- package/lightweight/index.umd.js +129 -153
- package/package.json +9 -9
- package/src/factory.js +9 -2
- package/src/node.js +0 -1
package/README.md
CHANGED
|
@@ -10,4 +10,4 @@
|
|
|
10
10
|
**microlink** © [Microlink](https://microlink.io), Released under the [MIT](https://github.com/microlinkhq/sdk/blob/master/LICENSE.md) License.<br>
|
|
11
11
|
Authored and maintained by Kiko Beats with help from [contributors](https://github.com/microlinkhq/sdk/contributors).
|
|
12
12
|
|
|
13
|
-
> [microlink.io](https://microlink.io) · GitHub [@MicrolinkHQ](https://github.com/microlinkhq) ·
|
|
13
|
+
> [microlink.io](https://microlink.io) · GitHub [@MicrolinkHQ](https://github.com/microlinkhq) · X [@microlinkhq](https://x.com/microlinkhq)
|
package/lightweight/index.js
CHANGED
|
@@ -27,18 +27,7 @@ function getAugmentedNamespace(n) {
|
|
|
27
27
|
return a;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
var lightweight$
|
|
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
|
|
|
@@ -70,32 +59,16 @@ function flattie(input, glue, toNull) {
|
|
|
70
59
|
|
|
71
60
|
dist.flattie = flattie;
|
|
72
61
|
|
|
73
|
-
// eslint-lint-disable-next-line @typescript-eslint/naming-convention
|
|
74
62
|
class HTTPError extends Error {
|
|
63
|
+
response;
|
|
64
|
+
request;
|
|
65
|
+
options;
|
|
75
66
|
constructor(response, request, options) {
|
|
76
67
|
const code = (response.status || response.status === 0) ? response.status : '';
|
|
77
68
|
const title = response.statusText || '';
|
|
78
69
|
const status = `${code} ${title}`.trim();
|
|
79
70
|
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
|
-
});
|
|
71
|
+
super(`Request failed with ${reason}: ${request.method} ${request.url}`);
|
|
99
72
|
this.name = 'HTTPError';
|
|
100
73
|
this.response = response;
|
|
101
74
|
this.request = request;
|
|
@@ -104,14 +77,9 @@ class HTTPError extends Error {
|
|
|
104
77
|
}
|
|
105
78
|
|
|
106
79
|
class TimeoutError extends Error {
|
|
80
|
+
request;
|
|
107
81
|
constructor(request) {
|
|
108
|
-
super(
|
|
109
|
-
Object.defineProperty(this, "request", {
|
|
110
|
-
enumerable: true,
|
|
111
|
-
configurable: true,
|
|
112
|
-
writable: true,
|
|
113
|
-
value: void 0
|
|
114
|
-
});
|
|
82
|
+
super(`Request timed out: ${request.method} ${request.url}`);
|
|
115
83
|
this.name = 'TimeoutError';
|
|
116
84
|
this.request = request;
|
|
117
85
|
}
|
|
@@ -142,10 +110,22 @@ const mergeHeaders = (source1 = {}, source2 = {}) => {
|
|
|
142
110
|
}
|
|
143
111
|
return result;
|
|
144
112
|
};
|
|
113
|
+
function newHookValue(original, incoming, property) {
|
|
114
|
+
return (Object.hasOwn(incoming, property) && incoming[property] === undefined)
|
|
115
|
+
? []
|
|
116
|
+
: deepMerge(original[property] ?? [], incoming[property] ?? []);
|
|
117
|
+
}
|
|
118
|
+
const mergeHooks = (original = {}, incoming = {}) => ({
|
|
119
|
+
beforeRequest: newHookValue(original, incoming, 'beforeRequest'),
|
|
120
|
+
beforeRetry: newHookValue(original, incoming, 'beforeRetry'),
|
|
121
|
+
afterResponse: newHookValue(original, incoming, 'afterResponse'),
|
|
122
|
+
beforeError: newHookValue(original, incoming, 'beforeError'),
|
|
123
|
+
});
|
|
145
124
|
// TODO: Make this strongly-typed (no `any`).
|
|
146
125
|
const deepMerge = (...sources) => {
|
|
147
126
|
let returnValue = {};
|
|
148
127
|
let headers = {};
|
|
128
|
+
let hooks = {};
|
|
149
129
|
for (const source of sources) {
|
|
150
130
|
if (Array.isArray(source)) {
|
|
151
131
|
if (!Array.isArray(returnValue)) {
|
|
@@ -160,6 +140,10 @@ const deepMerge = (...sources) => {
|
|
|
160
140
|
}
|
|
161
141
|
returnValue = { ...returnValue, [key]: value };
|
|
162
142
|
}
|
|
143
|
+
if (isObject$1(source.hooks)) {
|
|
144
|
+
hooks = mergeHooks(hooks, source.hooks);
|
|
145
|
+
returnValue.hooks = hooks;
|
|
146
|
+
}
|
|
163
147
|
if (isObject$1(source.headers)) {
|
|
164
148
|
headers = mergeHeaders(headers, source.headers);
|
|
165
149
|
returnValue.headers = headers;
|
|
@@ -175,15 +159,24 @@ const supportsRequestStreams = (() => {
|
|
|
175
159
|
const supportsReadableStream = typeof globalThis.ReadableStream === 'function';
|
|
176
160
|
const supportsRequest = typeof globalThis.Request === 'function';
|
|
177
161
|
if (supportsReadableStream && supportsRequest) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
162
|
+
try {
|
|
163
|
+
hasContentType = new globalThis.Request('https://empty.invalid', {
|
|
164
|
+
body: new globalThis.ReadableStream(),
|
|
165
|
+
method: 'POST',
|
|
166
|
+
// @ts-expect-error - Types are outdated.
|
|
167
|
+
get duplex() {
|
|
168
|
+
duplexAccessed = true;
|
|
169
|
+
return 'half';
|
|
170
|
+
},
|
|
171
|
+
}).headers.has('Content-Type');
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
// QQBrowser on iOS throws "unsupported BodyInit type" error (see issue #581)
|
|
175
|
+
if (error instanceof Error && error.message === 'unsupported BodyInit type') {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
throw error;
|
|
179
|
+
}
|
|
187
180
|
}
|
|
188
181
|
return duplexAccessed && !hasContentType;
|
|
189
182
|
})();
|
|
@@ -204,6 +197,7 @@ const stop = Symbol('stop');
|
|
|
204
197
|
const kyOptionKeys = {
|
|
205
198
|
json: true,
|
|
206
199
|
parseJson: true,
|
|
200
|
+
stringifyJson: true,
|
|
207
201
|
searchParams: true,
|
|
208
202
|
prefixUrl: true,
|
|
209
203
|
retry: true,
|
|
@@ -261,7 +255,6 @@ const normalizeRetryOptions = (retry = {}) => {
|
|
|
261
255
|
return {
|
|
262
256
|
...defaultRetryOptions,
|
|
263
257
|
...retry,
|
|
264
|
-
afterStatusCodes: retryAfterStatusCodes,
|
|
265
258
|
};
|
|
266
259
|
};
|
|
267
260
|
|
|
@@ -377,47 +370,18 @@ class Ky {
|
|
|
377
370
|
}
|
|
378
371
|
return result;
|
|
379
372
|
}
|
|
373
|
+
request;
|
|
374
|
+
abortController;
|
|
375
|
+
_retryCount = 0;
|
|
376
|
+
_input;
|
|
377
|
+
_options;
|
|
380
378
|
// eslint-disable-next-line complexity
|
|
381
379
|
constructor(input, options = {}) {
|
|
382
|
-
Object.defineProperty(this, "request", {
|
|
383
|
-
enumerable: true,
|
|
384
|
-
configurable: true,
|
|
385
|
-
writable: true,
|
|
386
|
-
value: void 0
|
|
387
|
-
});
|
|
388
|
-
Object.defineProperty(this, "abortController", {
|
|
389
|
-
enumerable: true,
|
|
390
|
-
configurable: true,
|
|
391
|
-
writable: true,
|
|
392
|
-
value: void 0
|
|
393
|
-
});
|
|
394
|
-
Object.defineProperty(this, "_retryCount", {
|
|
395
|
-
enumerable: true,
|
|
396
|
-
configurable: true,
|
|
397
|
-
writable: true,
|
|
398
|
-
value: 0
|
|
399
|
-
});
|
|
400
|
-
Object.defineProperty(this, "_input", {
|
|
401
|
-
enumerable: true,
|
|
402
|
-
configurable: true,
|
|
403
|
-
writable: true,
|
|
404
|
-
value: void 0
|
|
405
|
-
});
|
|
406
|
-
Object.defineProperty(this, "_options", {
|
|
407
|
-
enumerable: true,
|
|
408
|
-
configurable: true,
|
|
409
|
-
writable: true,
|
|
410
|
-
value: void 0
|
|
411
|
-
});
|
|
412
380
|
this._input = input;
|
|
413
|
-
const credentials = this._input instanceof Request && 'credentials' in Request.prototype
|
|
414
|
-
? this._input.credentials
|
|
415
|
-
: undefined;
|
|
416
381
|
this._options = {
|
|
417
|
-
...(credentials && { credentials }), // For exactOptionalPropertyTypes
|
|
418
382
|
...options,
|
|
419
383
|
headers: mergeHeaders(this._input.headers, options.headers),
|
|
420
|
-
hooks:
|
|
384
|
+
hooks: mergeHooks({
|
|
421
385
|
beforeRequest: [],
|
|
422
386
|
beforeRetry: [],
|
|
423
387
|
beforeError: [],
|
|
@@ -445,18 +409,20 @@ class Ky {
|
|
|
445
409
|
}
|
|
446
410
|
if (supportsAbortController) {
|
|
447
411
|
this.abortController = new globalThis.AbortController();
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
this.
|
|
451
|
-
|
|
452
|
-
});
|
|
453
|
-
}
|
|
412
|
+
const originalSignal = this._options.signal ?? this._input.signal;
|
|
413
|
+
originalSignal?.addEventListener('abort', () => {
|
|
414
|
+
this.abortController.abort(originalSignal.reason);
|
|
415
|
+
});
|
|
454
416
|
this._options.signal = this.abortController.signal;
|
|
455
417
|
}
|
|
456
418
|
if (supportsRequestStreams) {
|
|
457
419
|
// @ts-expect-error - Types are outdated.
|
|
458
420
|
this._options.duplex = 'half';
|
|
459
421
|
}
|
|
422
|
+
if (this._options.json !== undefined) {
|
|
423
|
+
this._options.body = this._options.stringifyJson?.(this._options.json) ?? JSON.stringify(this._options.json);
|
|
424
|
+
this._options.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json');
|
|
425
|
+
}
|
|
460
426
|
this.request = new globalThis.Request(this._input, this._options);
|
|
461
427
|
if (this._options.searchParams) {
|
|
462
428
|
// eslint-disable-next-line unicorn/prevent-abbreviations
|
|
@@ -474,41 +440,38 @@ class Ky {
|
|
|
474
440
|
// The spread of `this.request` is required as otherwise it misses the `duplex` option for some reason and throws.
|
|
475
441
|
this.request = new globalThis.Request(new globalThis.Request(url, { ...this.request }), this._options);
|
|
476
442
|
}
|
|
477
|
-
if (this._options.json !== undefined) {
|
|
478
|
-
this._options.body = JSON.stringify(this._options.json);
|
|
479
|
-
this.request.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json');
|
|
480
|
-
this.request = new globalThis.Request(this.request, { body: this._options.body });
|
|
481
|
-
}
|
|
482
443
|
}
|
|
483
444
|
_calculateRetryDelay(error) {
|
|
484
445
|
this._retryCount++;
|
|
485
|
-
if (this._retryCount
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
return 0;
|
|
501
|
-
}
|
|
502
|
-
return after;
|
|
446
|
+
if (this._retryCount > this._options.retry.limit || error instanceof TimeoutError) {
|
|
447
|
+
throw error;
|
|
448
|
+
}
|
|
449
|
+
if (error instanceof HTTPError) {
|
|
450
|
+
if (!this._options.retry.statusCodes.includes(error.response.status)) {
|
|
451
|
+
throw error;
|
|
452
|
+
}
|
|
453
|
+
const retryAfter = error.response.headers.get('Retry-After')
|
|
454
|
+
?? error.response.headers.get('RateLimit-Reset')
|
|
455
|
+
?? error.response.headers.get('X-RateLimit-Reset') // GitHub
|
|
456
|
+
?? error.response.headers.get('X-Rate-Limit-Reset'); // Twitter
|
|
457
|
+
if (retryAfter && this._options.retry.afterStatusCodes.includes(error.response.status)) {
|
|
458
|
+
let after = Number(retryAfter) * 1000;
|
|
459
|
+
if (Number.isNaN(after)) {
|
|
460
|
+
after = Date.parse(retryAfter) - Date.now();
|
|
503
461
|
}
|
|
504
|
-
if (
|
|
505
|
-
|
|
462
|
+
else if (after >= Date.parse('2024-01-01')) {
|
|
463
|
+
// A large number is treated as a timestamp (fixed threshold protects against clock skew)
|
|
464
|
+
after -= Date.now();
|
|
506
465
|
}
|
|
466
|
+
const max = this._options.retry.maxRetryAfter ?? after;
|
|
467
|
+
return after < max ? after : max;
|
|
468
|
+
}
|
|
469
|
+
if (error.response.status === 413) {
|
|
470
|
+
throw error;
|
|
507
471
|
}
|
|
508
|
-
const retryDelay = this._options.retry.delay(this._retryCount);
|
|
509
|
-
return Math.min(this._options.retry.backoffLimit, retryDelay);
|
|
510
472
|
}
|
|
511
|
-
|
|
473
|
+
const retryDelay = this._options.retry.delay(this._retryCount);
|
|
474
|
+
return Math.min(this._options.retry.backoffLimit, retryDelay);
|
|
512
475
|
}
|
|
513
476
|
_decorateResponse(response) {
|
|
514
477
|
if (this._options.parseJson) {
|
|
@@ -522,24 +485,24 @@ class Ky {
|
|
|
522
485
|
}
|
|
523
486
|
catch (error) {
|
|
524
487
|
const ms = Math.min(this._calculateRetryDelay(error), maxSafeTimeout);
|
|
525
|
-
if (
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
488
|
+
if (this._retryCount < 1) {
|
|
489
|
+
throw error;
|
|
490
|
+
}
|
|
491
|
+
await delay(ms, { signal: this._options.signal });
|
|
492
|
+
for (const hook of this._options.hooks.beforeRetry) {
|
|
493
|
+
// eslint-disable-next-line no-await-in-loop
|
|
494
|
+
const hookResult = await hook({
|
|
495
|
+
request: this.request,
|
|
496
|
+
options: this._options,
|
|
497
|
+
error: error,
|
|
498
|
+
retryCount: this._retryCount,
|
|
499
|
+
});
|
|
500
|
+
// If `stop` is returned from the hook, the retry process is stopped
|
|
501
|
+
if (hookResult === stop) {
|
|
502
|
+
return;
|
|
539
503
|
}
|
|
540
|
-
return this._retry(function_);
|
|
541
504
|
}
|
|
542
|
-
|
|
505
|
+
return this._retry(function_);
|
|
543
506
|
}
|
|
544
507
|
}
|
|
545
508
|
async _fetch() {
|
|
@@ -555,10 +518,13 @@ class Ky {
|
|
|
555
518
|
}
|
|
556
519
|
}
|
|
557
520
|
const nonRequestOptions = findUnknownOptions(this.request, this._options);
|
|
521
|
+
// Cloning is done here to prepare in advance for retries
|
|
522
|
+
const mainRequest = this.request;
|
|
523
|
+
this.request = mainRequest.clone();
|
|
558
524
|
if (this._options.timeout === false) {
|
|
559
|
-
return this._options.fetch(
|
|
525
|
+
return this._options.fetch(mainRequest, nonRequestOptions);
|
|
560
526
|
}
|
|
561
|
-
return timeout(
|
|
527
|
+
return timeout(mainRequest, nonRequestOptions, this.abortController, this._options);
|
|
562
528
|
}
|
|
563
529
|
/* istanbul ignore next */
|
|
564
530
|
_stream(response, onDownloadProgress) {
|
|
@@ -613,7 +579,12 @@ const createInstance = (defaults) => {
|
|
|
613
579
|
ky[method] = (input, options) => Ky.create(input, validateAndMerge(defaults, options, { method }));
|
|
614
580
|
}
|
|
615
581
|
ky.create = (newDefaults) => createInstance(validateAndMerge(newDefaults));
|
|
616
|
-
ky.extend = (newDefaults) =>
|
|
582
|
+
ky.extend = (newDefaults) => {
|
|
583
|
+
if (typeof newDefaults === 'function') {
|
|
584
|
+
newDefaults = newDefaults(defaults ?? {});
|
|
585
|
+
}
|
|
586
|
+
return createInstance(validateAndMerge(defaults, newDefaults));
|
|
587
|
+
};
|
|
617
588
|
ky.stop = stop;
|
|
618
589
|
return ky;
|
|
619
590
|
};
|
|
@@ -626,7 +597,7 @@ var distribution = /*#__PURE__*/Object.freeze({
|
|
|
626
597
|
default: ky$1
|
|
627
598
|
});
|
|
628
599
|
|
|
629
|
-
var require$$
|
|
600
|
+
var require$$1 = /*@__PURE__*/getAugmentedNamespace(distribution);
|
|
630
601
|
|
|
631
602
|
const ENDPOINT = {
|
|
632
603
|
FREE: 'https://api.microlink.io/',
|
|
@@ -658,15 +629,22 @@ const parseBody = (input, error, url) => {
|
|
|
658
629
|
}
|
|
659
630
|
};
|
|
660
631
|
|
|
632
|
+
const isURL = url => {
|
|
633
|
+
try {
|
|
634
|
+
return /^https?:\/\//i.test(new URL(url).href)
|
|
635
|
+
} catch (_) {
|
|
636
|
+
return false
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
|
|
661
640
|
const factory$1 = streamResponseType => ({
|
|
662
641
|
VERSION,
|
|
663
642
|
MicrolinkError,
|
|
664
|
-
urlHttp,
|
|
665
643
|
got,
|
|
666
644
|
flatten
|
|
667
645
|
}) => {
|
|
668
646
|
const assertUrl = (url = '') => {
|
|
669
|
-
if (!
|
|
647
|
+
if (!isURL(url)) {
|
|
670
648
|
const message = `The \`url\` as \`${url}\` is not valid. Ensure it has protocol (http or https) and hostname.`;
|
|
671
649
|
throw new MicrolinkError({
|
|
672
650
|
status: 'fail',
|
|
@@ -766,9 +744,8 @@ const factory$1 = streamResponseType => ({
|
|
|
766
744
|
|
|
767
745
|
var factory_1 = factory$1;
|
|
768
746
|
|
|
769
|
-
const urlHttp = lightweight$1;
|
|
770
747
|
const { flattie: flatten } = dist;
|
|
771
|
-
const { default: ky } = require$$
|
|
748
|
+
const { default: ky } = require$$1;
|
|
772
749
|
|
|
773
750
|
const factory = factory_1('arrayBuffer');
|
|
774
751
|
|
|
@@ -815,22 +792,21 @@ got.stream = (...args) => ky(...args).then(res => res.body);
|
|
|
815
792
|
|
|
816
793
|
const mql = factory({
|
|
817
794
|
MicrolinkError,
|
|
818
|
-
urlHttp,
|
|
819
795
|
got,
|
|
820
796
|
flatten,
|
|
821
|
-
VERSION: '0.13.
|
|
797
|
+
VERSION: '0.13.8'
|
|
822
798
|
});
|
|
823
799
|
|
|
824
|
-
lightweight$
|
|
825
|
-
var arrayBuffer = lightweight$
|
|
826
|
-
var extend = lightweight$
|
|
827
|
-
var fetchFromApi = lightweight$
|
|
828
|
-
var getApiUrl = lightweight$
|
|
829
|
-
var mapRules = lightweight$
|
|
830
|
-
var MicrolinkError_1 = lightweight$
|
|
831
|
-
var version = lightweight$
|
|
800
|
+
lightweight$1.exports = mql;
|
|
801
|
+
var arrayBuffer = lightweight$1.exports.arrayBuffer = mql.extend({ responseType: 'arrayBuffer' });
|
|
802
|
+
var extend = lightweight$1.exports.extend = mql.extend;
|
|
803
|
+
var fetchFromApi = lightweight$1.exports.fetchFromApi = mql.fetchFromApi;
|
|
804
|
+
var getApiUrl = lightweight$1.exports.getApiUrl = mql.getApiUrl;
|
|
805
|
+
var mapRules = lightweight$1.exports.mapRules = mql.mapRules;
|
|
806
|
+
var MicrolinkError_1 = lightweight$1.exports.MicrolinkError = mql.MicrolinkError;
|
|
807
|
+
var version = lightweight$1.exports.version = mql.version;
|
|
832
808
|
|
|
833
|
-
var lightweightExports = lightweight$
|
|
809
|
+
var lightweightExports = lightweight$1.exports;
|
|
834
810
|
var lightweight = /*@__PURE__*/getDefaultExportFromCjs(lightweightExports);
|
|
835
811
|
|
|
836
812
|
export { MicrolinkError_1 as MicrolinkError, arrayBuffer, lightweight as default, extend, fetchFromApi, getApiUrl, mapRules, version };
|
package/lightweight/index.umd.js
CHANGED
|
@@ -33,18 +33,7 @@
|
|
|
33
33
|
return a;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
var lightweight$
|
|
37
|
-
|
|
38
|
-
const REGEX_HTTP_PROTOCOL = /^https?:\/\//i;
|
|
39
|
-
|
|
40
|
-
var lightweight$1 = url => {
|
|
41
|
-
try {
|
|
42
|
-
const { href } = new URL(url);
|
|
43
|
-
return REGEX_HTTP_PROTOCOL.test(href) && href
|
|
44
|
-
} catch (err) {
|
|
45
|
-
return false
|
|
46
|
-
}
|
|
47
|
-
};
|
|
36
|
+
var lightweight$1 = {exports: {}};
|
|
48
37
|
|
|
49
38
|
var dist = {};
|
|
50
39
|
|
|
@@ -76,32 +65,16 @@
|
|
|
76
65
|
|
|
77
66
|
dist.flattie = flattie;
|
|
78
67
|
|
|
79
|
-
// eslint-lint-disable-next-line @typescript-eslint/naming-convention
|
|
80
68
|
class HTTPError extends Error {
|
|
69
|
+
response;
|
|
70
|
+
request;
|
|
71
|
+
options;
|
|
81
72
|
constructor(response, request, options) {
|
|
82
73
|
const code = (response.status || response.status === 0) ? response.status : '';
|
|
83
74
|
const title = response.statusText || '';
|
|
84
75
|
const status = `${code} ${title}`.trim();
|
|
85
76
|
const reason = status ? `status code ${status}` : 'an unknown error';
|
|
86
|
-
super(`Request failed with ${reason}`);
|
|
87
|
-
Object.defineProperty(this, "response", {
|
|
88
|
-
enumerable: true,
|
|
89
|
-
configurable: true,
|
|
90
|
-
writable: true,
|
|
91
|
-
value: void 0
|
|
92
|
-
});
|
|
93
|
-
Object.defineProperty(this, "request", {
|
|
94
|
-
enumerable: true,
|
|
95
|
-
configurable: true,
|
|
96
|
-
writable: true,
|
|
97
|
-
value: void 0
|
|
98
|
-
});
|
|
99
|
-
Object.defineProperty(this, "options", {
|
|
100
|
-
enumerable: true,
|
|
101
|
-
configurable: true,
|
|
102
|
-
writable: true,
|
|
103
|
-
value: void 0
|
|
104
|
-
});
|
|
77
|
+
super(`Request failed with ${reason}: ${request.method} ${request.url}`);
|
|
105
78
|
this.name = 'HTTPError';
|
|
106
79
|
this.response = response;
|
|
107
80
|
this.request = request;
|
|
@@ -110,14 +83,9 @@
|
|
|
110
83
|
}
|
|
111
84
|
|
|
112
85
|
class TimeoutError extends Error {
|
|
86
|
+
request;
|
|
113
87
|
constructor(request) {
|
|
114
|
-
super(
|
|
115
|
-
Object.defineProperty(this, "request", {
|
|
116
|
-
enumerable: true,
|
|
117
|
-
configurable: true,
|
|
118
|
-
writable: true,
|
|
119
|
-
value: void 0
|
|
120
|
-
});
|
|
88
|
+
super(`Request timed out: ${request.method} ${request.url}`);
|
|
121
89
|
this.name = 'TimeoutError';
|
|
122
90
|
this.request = request;
|
|
123
91
|
}
|
|
@@ -148,10 +116,22 @@
|
|
|
148
116
|
}
|
|
149
117
|
return result;
|
|
150
118
|
};
|
|
119
|
+
function newHookValue(original, incoming, property) {
|
|
120
|
+
return (Object.hasOwn(incoming, property) && incoming[property] === undefined)
|
|
121
|
+
? []
|
|
122
|
+
: deepMerge(original[property] ?? [], incoming[property] ?? []);
|
|
123
|
+
}
|
|
124
|
+
const mergeHooks = (original = {}, incoming = {}) => ({
|
|
125
|
+
beforeRequest: newHookValue(original, incoming, 'beforeRequest'),
|
|
126
|
+
beforeRetry: newHookValue(original, incoming, 'beforeRetry'),
|
|
127
|
+
afterResponse: newHookValue(original, incoming, 'afterResponse'),
|
|
128
|
+
beforeError: newHookValue(original, incoming, 'beforeError'),
|
|
129
|
+
});
|
|
151
130
|
// TODO: Make this strongly-typed (no `any`).
|
|
152
131
|
const deepMerge = (...sources) => {
|
|
153
132
|
let returnValue = {};
|
|
154
133
|
let headers = {};
|
|
134
|
+
let hooks = {};
|
|
155
135
|
for (const source of sources) {
|
|
156
136
|
if (Array.isArray(source)) {
|
|
157
137
|
if (!Array.isArray(returnValue)) {
|
|
@@ -166,6 +146,10 @@
|
|
|
166
146
|
}
|
|
167
147
|
returnValue = { ...returnValue, [key]: value };
|
|
168
148
|
}
|
|
149
|
+
if (isObject$1(source.hooks)) {
|
|
150
|
+
hooks = mergeHooks(hooks, source.hooks);
|
|
151
|
+
returnValue.hooks = hooks;
|
|
152
|
+
}
|
|
169
153
|
if (isObject$1(source.headers)) {
|
|
170
154
|
headers = mergeHeaders(headers, source.headers);
|
|
171
155
|
returnValue.headers = headers;
|
|
@@ -181,15 +165,24 @@
|
|
|
181
165
|
const supportsReadableStream = typeof globalThis.ReadableStream === 'function';
|
|
182
166
|
const supportsRequest = typeof globalThis.Request === 'function';
|
|
183
167
|
if (supportsReadableStream && supportsRequest) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
168
|
+
try {
|
|
169
|
+
hasContentType = new globalThis.Request('https://empty.invalid', {
|
|
170
|
+
body: new globalThis.ReadableStream(),
|
|
171
|
+
method: 'POST',
|
|
172
|
+
// @ts-expect-error - Types are outdated.
|
|
173
|
+
get duplex() {
|
|
174
|
+
duplexAccessed = true;
|
|
175
|
+
return 'half';
|
|
176
|
+
},
|
|
177
|
+
}).headers.has('Content-Type');
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
// QQBrowser on iOS throws "unsupported BodyInit type" error (see issue #581)
|
|
181
|
+
if (error instanceof Error && error.message === 'unsupported BodyInit type') {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
193
186
|
}
|
|
194
187
|
return duplexAccessed && !hasContentType;
|
|
195
188
|
})();
|
|
@@ -210,6 +203,7 @@
|
|
|
210
203
|
const kyOptionKeys = {
|
|
211
204
|
json: true,
|
|
212
205
|
parseJson: true,
|
|
206
|
+
stringifyJson: true,
|
|
213
207
|
searchParams: true,
|
|
214
208
|
prefixUrl: true,
|
|
215
209
|
retry: true,
|
|
@@ -267,7 +261,6 @@
|
|
|
267
261
|
return {
|
|
268
262
|
...defaultRetryOptions,
|
|
269
263
|
...retry,
|
|
270
|
-
afterStatusCodes: retryAfterStatusCodes,
|
|
271
264
|
};
|
|
272
265
|
};
|
|
273
266
|
|
|
@@ -383,47 +376,18 @@
|
|
|
383
376
|
}
|
|
384
377
|
return result;
|
|
385
378
|
}
|
|
379
|
+
request;
|
|
380
|
+
abortController;
|
|
381
|
+
_retryCount = 0;
|
|
382
|
+
_input;
|
|
383
|
+
_options;
|
|
386
384
|
// eslint-disable-next-line complexity
|
|
387
385
|
constructor(input, options = {}) {
|
|
388
|
-
Object.defineProperty(this, "request", {
|
|
389
|
-
enumerable: true,
|
|
390
|
-
configurable: true,
|
|
391
|
-
writable: true,
|
|
392
|
-
value: void 0
|
|
393
|
-
});
|
|
394
|
-
Object.defineProperty(this, "abortController", {
|
|
395
|
-
enumerable: true,
|
|
396
|
-
configurable: true,
|
|
397
|
-
writable: true,
|
|
398
|
-
value: void 0
|
|
399
|
-
});
|
|
400
|
-
Object.defineProperty(this, "_retryCount", {
|
|
401
|
-
enumerable: true,
|
|
402
|
-
configurable: true,
|
|
403
|
-
writable: true,
|
|
404
|
-
value: 0
|
|
405
|
-
});
|
|
406
|
-
Object.defineProperty(this, "_input", {
|
|
407
|
-
enumerable: true,
|
|
408
|
-
configurable: true,
|
|
409
|
-
writable: true,
|
|
410
|
-
value: void 0
|
|
411
|
-
});
|
|
412
|
-
Object.defineProperty(this, "_options", {
|
|
413
|
-
enumerable: true,
|
|
414
|
-
configurable: true,
|
|
415
|
-
writable: true,
|
|
416
|
-
value: void 0
|
|
417
|
-
});
|
|
418
386
|
this._input = input;
|
|
419
|
-
const credentials = this._input instanceof Request && 'credentials' in Request.prototype
|
|
420
|
-
? this._input.credentials
|
|
421
|
-
: undefined;
|
|
422
387
|
this._options = {
|
|
423
|
-
...(credentials && { credentials }), // For exactOptionalPropertyTypes
|
|
424
388
|
...options,
|
|
425
389
|
headers: mergeHeaders(this._input.headers, options.headers),
|
|
426
|
-
hooks:
|
|
390
|
+
hooks: mergeHooks({
|
|
427
391
|
beforeRequest: [],
|
|
428
392
|
beforeRetry: [],
|
|
429
393
|
beforeError: [],
|
|
@@ -451,18 +415,20 @@
|
|
|
451
415
|
}
|
|
452
416
|
if (supportsAbortController) {
|
|
453
417
|
this.abortController = new globalThis.AbortController();
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
this.
|
|
457
|
-
|
|
458
|
-
});
|
|
459
|
-
}
|
|
418
|
+
const originalSignal = this._options.signal ?? this._input.signal;
|
|
419
|
+
originalSignal?.addEventListener('abort', () => {
|
|
420
|
+
this.abortController.abort(originalSignal.reason);
|
|
421
|
+
});
|
|
460
422
|
this._options.signal = this.abortController.signal;
|
|
461
423
|
}
|
|
462
424
|
if (supportsRequestStreams) {
|
|
463
425
|
// @ts-expect-error - Types are outdated.
|
|
464
426
|
this._options.duplex = 'half';
|
|
465
427
|
}
|
|
428
|
+
if (this._options.json !== undefined) {
|
|
429
|
+
this._options.body = this._options.stringifyJson?.(this._options.json) ?? JSON.stringify(this._options.json);
|
|
430
|
+
this._options.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json');
|
|
431
|
+
}
|
|
466
432
|
this.request = new globalThis.Request(this._input, this._options);
|
|
467
433
|
if (this._options.searchParams) {
|
|
468
434
|
// eslint-disable-next-line unicorn/prevent-abbreviations
|
|
@@ -480,41 +446,38 @@
|
|
|
480
446
|
// The spread of `this.request` is required as otherwise it misses the `duplex` option for some reason and throws.
|
|
481
447
|
this.request = new globalThis.Request(new globalThis.Request(url, { ...this.request }), this._options);
|
|
482
448
|
}
|
|
483
|
-
if (this._options.json !== undefined) {
|
|
484
|
-
this._options.body = JSON.stringify(this._options.json);
|
|
485
|
-
this.request.headers.set('content-type', this._options.headers.get('content-type') ?? 'application/json');
|
|
486
|
-
this.request = new globalThis.Request(this.request, { body: this._options.body });
|
|
487
|
-
}
|
|
488
449
|
}
|
|
489
450
|
_calculateRetryDelay(error) {
|
|
490
451
|
this._retryCount++;
|
|
491
|
-
if (this._retryCount
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
return 0;
|
|
507
|
-
}
|
|
508
|
-
return after;
|
|
452
|
+
if (this._retryCount > this._options.retry.limit || error instanceof TimeoutError) {
|
|
453
|
+
throw error;
|
|
454
|
+
}
|
|
455
|
+
if (error instanceof HTTPError) {
|
|
456
|
+
if (!this._options.retry.statusCodes.includes(error.response.status)) {
|
|
457
|
+
throw error;
|
|
458
|
+
}
|
|
459
|
+
const retryAfter = error.response.headers.get('Retry-After')
|
|
460
|
+
?? error.response.headers.get('RateLimit-Reset')
|
|
461
|
+
?? error.response.headers.get('X-RateLimit-Reset') // GitHub
|
|
462
|
+
?? error.response.headers.get('X-Rate-Limit-Reset'); // Twitter
|
|
463
|
+
if (retryAfter && this._options.retry.afterStatusCodes.includes(error.response.status)) {
|
|
464
|
+
let after = Number(retryAfter) * 1000;
|
|
465
|
+
if (Number.isNaN(after)) {
|
|
466
|
+
after = Date.parse(retryAfter) - Date.now();
|
|
509
467
|
}
|
|
510
|
-
if (
|
|
511
|
-
|
|
468
|
+
else if (after >= Date.parse('2024-01-01')) {
|
|
469
|
+
// A large number is treated as a timestamp (fixed threshold protects against clock skew)
|
|
470
|
+
after -= Date.now();
|
|
512
471
|
}
|
|
472
|
+
const max = this._options.retry.maxRetryAfter ?? after;
|
|
473
|
+
return after < max ? after : max;
|
|
474
|
+
}
|
|
475
|
+
if (error.response.status === 413) {
|
|
476
|
+
throw error;
|
|
513
477
|
}
|
|
514
|
-
const retryDelay = this._options.retry.delay(this._retryCount);
|
|
515
|
-
return Math.min(this._options.retry.backoffLimit, retryDelay);
|
|
516
478
|
}
|
|
517
|
-
|
|
479
|
+
const retryDelay = this._options.retry.delay(this._retryCount);
|
|
480
|
+
return Math.min(this._options.retry.backoffLimit, retryDelay);
|
|
518
481
|
}
|
|
519
482
|
_decorateResponse(response) {
|
|
520
483
|
if (this._options.parseJson) {
|
|
@@ -528,24 +491,24 @@
|
|
|
528
491
|
}
|
|
529
492
|
catch (error) {
|
|
530
493
|
const ms = Math.min(this._calculateRetryDelay(error), maxSafeTimeout);
|
|
531
|
-
if (
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
494
|
+
if (this._retryCount < 1) {
|
|
495
|
+
throw error;
|
|
496
|
+
}
|
|
497
|
+
await delay(ms, { signal: this._options.signal });
|
|
498
|
+
for (const hook of this._options.hooks.beforeRetry) {
|
|
499
|
+
// eslint-disable-next-line no-await-in-loop
|
|
500
|
+
const hookResult = await hook({
|
|
501
|
+
request: this.request,
|
|
502
|
+
options: this._options,
|
|
503
|
+
error: error,
|
|
504
|
+
retryCount: this._retryCount,
|
|
505
|
+
});
|
|
506
|
+
// If `stop` is returned from the hook, the retry process is stopped
|
|
507
|
+
if (hookResult === stop) {
|
|
508
|
+
return;
|
|
545
509
|
}
|
|
546
|
-
return this._retry(function_);
|
|
547
510
|
}
|
|
548
|
-
|
|
511
|
+
return this._retry(function_);
|
|
549
512
|
}
|
|
550
513
|
}
|
|
551
514
|
async _fetch() {
|
|
@@ -561,10 +524,13 @@
|
|
|
561
524
|
}
|
|
562
525
|
}
|
|
563
526
|
const nonRequestOptions = findUnknownOptions(this.request, this._options);
|
|
527
|
+
// Cloning is done here to prepare in advance for retries
|
|
528
|
+
const mainRequest = this.request;
|
|
529
|
+
this.request = mainRequest.clone();
|
|
564
530
|
if (this._options.timeout === false) {
|
|
565
|
-
return this._options.fetch(
|
|
531
|
+
return this._options.fetch(mainRequest, nonRequestOptions);
|
|
566
532
|
}
|
|
567
|
-
return timeout(
|
|
533
|
+
return timeout(mainRequest, nonRequestOptions, this.abortController, this._options);
|
|
568
534
|
}
|
|
569
535
|
/* istanbul ignore next */
|
|
570
536
|
_stream(response, onDownloadProgress) {
|
|
@@ -619,7 +585,12 @@
|
|
|
619
585
|
ky[method] = (input, options) => Ky.create(input, validateAndMerge(defaults, options, { method }));
|
|
620
586
|
}
|
|
621
587
|
ky.create = (newDefaults) => createInstance(validateAndMerge(newDefaults));
|
|
622
|
-
ky.extend = (newDefaults) =>
|
|
588
|
+
ky.extend = (newDefaults) => {
|
|
589
|
+
if (typeof newDefaults === 'function') {
|
|
590
|
+
newDefaults = newDefaults(defaults ?? {});
|
|
591
|
+
}
|
|
592
|
+
return createInstance(validateAndMerge(defaults, newDefaults));
|
|
593
|
+
};
|
|
623
594
|
ky.stop = stop;
|
|
624
595
|
return ky;
|
|
625
596
|
};
|
|
@@ -632,7 +603,7 @@
|
|
|
632
603
|
default: ky$1
|
|
633
604
|
});
|
|
634
605
|
|
|
635
|
-
var require$$
|
|
606
|
+
var require$$1 = /*@__PURE__*/getAugmentedNamespace(distribution);
|
|
636
607
|
|
|
637
608
|
const ENDPOINT = {
|
|
638
609
|
FREE: 'https://api.microlink.io/',
|
|
@@ -664,15 +635,22 @@
|
|
|
664
635
|
}
|
|
665
636
|
};
|
|
666
637
|
|
|
638
|
+
const isURL = url => {
|
|
639
|
+
try {
|
|
640
|
+
return /^https?:\/\//i.test(new URL(url).href)
|
|
641
|
+
} catch (_) {
|
|
642
|
+
return false
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
|
|
667
646
|
const factory$1 = streamResponseType => ({
|
|
668
647
|
VERSION,
|
|
669
648
|
MicrolinkError,
|
|
670
|
-
urlHttp,
|
|
671
649
|
got,
|
|
672
650
|
flatten
|
|
673
651
|
}) => {
|
|
674
652
|
const assertUrl = (url = '') => {
|
|
675
|
-
if (!
|
|
653
|
+
if (!isURL(url)) {
|
|
676
654
|
const message = `The \`url\` as \`${url}\` is not valid. Ensure it has protocol (http or https) and hostname.`;
|
|
677
655
|
throw new MicrolinkError({
|
|
678
656
|
status: 'fail',
|
|
@@ -772,9 +750,8 @@
|
|
|
772
750
|
|
|
773
751
|
var factory_1 = factory$1;
|
|
774
752
|
|
|
775
|
-
const urlHttp = lightweight$1;
|
|
776
753
|
const { flattie: flatten } = dist;
|
|
777
|
-
const { default: ky } = require$$
|
|
754
|
+
const { default: ky } = require$$1;
|
|
778
755
|
|
|
779
756
|
const factory = factory_1('arrayBuffer');
|
|
780
757
|
|
|
@@ -821,22 +798,21 @@
|
|
|
821
798
|
|
|
822
799
|
const mql = factory({
|
|
823
800
|
MicrolinkError,
|
|
824
|
-
urlHttp,
|
|
825
801
|
got,
|
|
826
802
|
flatten,
|
|
827
|
-
VERSION: '0.13.
|
|
803
|
+
VERSION: '0.13.8'
|
|
828
804
|
});
|
|
829
805
|
|
|
830
|
-
lightweight$
|
|
831
|
-
var arrayBuffer = lightweight$
|
|
832
|
-
var extend = lightweight$
|
|
833
|
-
var fetchFromApi = lightweight$
|
|
834
|
-
var getApiUrl = lightweight$
|
|
835
|
-
var mapRules = lightweight$
|
|
836
|
-
var MicrolinkError_1 = lightweight$
|
|
837
|
-
var version = lightweight$
|
|
806
|
+
lightweight$1.exports = mql;
|
|
807
|
+
var arrayBuffer = lightweight$1.exports.arrayBuffer = mql.extend({ responseType: 'arrayBuffer' });
|
|
808
|
+
var extend = lightweight$1.exports.extend = mql.extend;
|
|
809
|
+
var fetchFromApi = lightweight$1.exports.fetchFromApi = mql.fetchFromApi;
|
|
810
|
+
var getApiUrl = lightweight$1.exports.getApiUrl = mql.getApiUrl;
|
|
811
|
+
var mapRules = lightweight$1.exports.mapRules = mql.mapRules;
|
|
812
|
+
var MicrolinkError_1 = lightweight$1.exports.MicrolinkError = mql.MicrolinkError;
|
|
813
|
+
var version = lightweight$1.exports.version = mql.version;
|
|
838
814
|
|
|
839
|
-
var lightweightExports = lightweight$
|
|
815
|
+
var lightweightExports = lightweight$1.exports;
|
|
840
816
|
var lightweight = /*@__PURE__*/getDefaultExportFromCjs(lightweightExports);
|
|
841
817
|
|
|
842
818
|
exports.MicrolinkError = MicrolinkError_1;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@microlink/mql",
|
|
3
3
|
"description": "Microlink Query Language. The official HTTP client to interact with Microlink API for Node.js, browsers & Deno.",
|
|
4
4
|
"homepage": "https://microlink.io/mql",
|
|
5
|
-
"version": "0.13.
|
|
5
|
+
"version": "0.13.8",
|
|
6
6
|
"types": "lightweight/index.d.ts",
|
|
7
7
|
"exports": {
|
|
8
8
|
"require": "./src/node.js",
|
|
@@ -48,14 +48,13 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"flattie": "~1.1.0",
|
|
50
50
|
"got": "~11.8.6",
|
|
51
|
-
"url-http": "~1.2.0",
|
|
52
51
|
"whoops": "~4.1.7"
|
|
53
52
|
},
|
|
54
53
|
"devDependencies": {
|
|
55
54
|
"@commitlint/cli": "latest",
|
|
56
55
|
"@commitlint/config-conventional": "latest",
|
|
57
56
|
"@ksmithut/prettier-standard": "latest",
|
|
58
|
-
"@rollup/plugin-commonjs": "
|
|
57
|
+
"@rollup/plugin-commonjs": "26",
|
|
59
58
|
"@rollup/plugin-node-resolve": "latest",
|
|
60
59
|
"@rollup/plugin-replace": "latest",
|
|
61
60
|
"@rollup/plugin-terser": "latest",
|
|
@@ -67,7 +66,6 @@
|
|
|
67
66
|
"github-generate-release": "latest",
|
|
68
67
|
"ky": "latest",
|
|
69
68
|
"nano-staged": "latest",
|
|
70
|
-
"npm-check-updates": "latest",
|
|
71
69
|
"prettier-standard": "latest",
|
|
72
70
|
"rollup": "latest",
|
|
73
71
|
"rollup-plugin-filesize": "latest",
|
|
@@ -98,14 +96,11 @@
|
|
|
98
96
|
"postrelease": "npm run release:tags && npm run release:github && (ci-publish || npm publish --access=public)",
|
|
99
97
|
"prebuild": "npm run clean:build",
|
|
100
98
|
"prepublishOnly": "npm run build",
|
|
101
|
-
"prerelease": "npm run update:check",
|
|
102
99
|
"pretest": "npm run lint && npm run build",
|
|
103
100
|
"release": "standard-version -a",
|
|
104
101
|
"release:github": "github-generate-release",
|
|
105
102
|
"release:tags": "git push --follow-tags origin HEAD:master",
|
|
106
|
-
"test": "c8 ava --verbose"
|
|
107
|
-
"update": "ncu -u",
|
|
108
|
-
"update:check": "ncu -- --error-level 2"
|
|
103
|
+
"test": "c8 ava --verbose"
|
|
109
104
|
},
|
|
110
105
|
"license": "MIT",
|
|
111
106
|
"ava": {
|
|
@@ -118,7 +113,12 @@
|
|
|
118
113
|
"commitlint": {
|
|
119
114
|
"extends": [
|
|
120
115
|
"@commitlint/config-conventional"
|
|
121
|
-
]
|
|
116
|
+
],
|
|
117
|
+
"rules": {
|
|
118
|
+
"body-max-line-length": [
|
|
119
|
+
0
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
122
|
},
|
|
123
123
|
"nano-staged": {
|
|
124
124
|
"*.js": [
|
package/src/factory.js
CHANGED
|
@@ -28,15 +28,22 @@ const parseBody = (input, error, url) => {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
const isURL = url => {
|
|
32
|
+
try {
|
|
33
|
+
return /^https?:\/\//i.test(new URL(url).href)
|
|
34
|
+
} catch (_) {
|
|
35
|
+
return false
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
const factory = streamResponseType => ({
|
|
32
40
|
VERSION,
|
|
33
41
|
MicrolinkError,
|
|
34
|
-
urlHttp,
|
|
35
42
|
got,
|
|
36
43
|
flatten
|
|
37
44
|
}) => {
|
|
38
45
|
const assertUrl = (url = '') => {
|
|
39
|
-
if (!
|
|
46
|
+
if (!isURL(url)) {
|
|
40
47
|
const message = `The \`url\` as \`${url}\` is not valid. Ensure it has protocol (http or https) and hostname.`
|
|
41
48
|
throw new MicrolinkError({
|
|
42
49
|
status: 'fail',
|
package/src/node.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const mql = require('./factory')('buffer')({
|
|
2
2
|
MicrolinkError: require('whoops')('MicrolinkError'),
|
|
3
|
-
urlHttp: require('url-http/lightweight'),
|
|
4
3
|
got: require('got').extend({ headers: { 'user-agent': undefined } }),
|
|
5
4
|
flatten: require('flattie').flattie,
|
|
6
5
|
VERSION: require('../package.json').version
|