@graphql-tools/url-loader 7.7.2 → 7.8.0-alpha-4faabc4b.0
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/index.d.ts +13 -0
- package/index.js +58 -7
- package/index.mjs +58 -7
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export declare type SyncImportFn = (moduleName: string) => any;
|
|
|
14
14
|
declare type HeadersConfig = Record<string, string>;
|
|
15
15
|
interface ExecutionExtensions {
|
|
16
16
|
headers?: HeadersConfig;
|
|
17
|
+
endpoint?: string;
|
|
17
18
|
}
|
|
18
19
|
export declare enum SubscriptionProtocol {
|
|
19
20
|
WS = "WS",
|
|
@@ -80,6 +81,18 @@ export interface LoadFromUrlOptions extends BaseLoaderOptions, Partial<Introspec
|
|
|
80
81
|
* Additional options to pass to the graphql-sse client.
|
|
81
82
|
*/
|
|
82
83
|
graphqlSseOptions?: Omit<GraphQLSSEClientOptions, 'url' | 'headers' | 'fetchFn' | 'abortControllerImpl'>;
|
|
84
|
+
/**
|
|
85
|
+
* Retry attempts
|
|
86
|
+
*/
|
|
87
|
+
retry?: number;
|
|
88
|
+
/**
|
|
89
|
+
* Timeout in milliseconds
|
|
90
|
+
*/
|
|
91
|
+
timeout?: number;
|
|
92
|
+
/**
|
|
93
|
+
* Request Credentials
|
|
94
|
+
*/
|
|
95
|
+
credentials?: RequestCredentials;
|
|
83
96
|
}
|
|
84
97
|
/**
|
|
85
98
|
* This loader loads a schema from a URL. The loaded schema is a fully-executable,
|
package/index.js
CHANGED
|
@@ -406,14 +406,14 @@ class UrlLoader {
|
|
|
406
406
|
const finalUrl = urlObj.toString().replace(dummyHostname, '');
|
|
407
407
|
return finalUrl;
|
|
408
408
|
}
|
|
409
|
-
buildHTTPExecutor(
|
|
409
|
+
buildHTTPExecutor(initialEndpoint, fetch, options) {
|
|
410
410
|
const defaultMethod = this.getDefaultMethodFromOptions(options === null || options === void 0 ? void 0 : options.method, 'POST');
|
|
411
|
-
const HTTP_URL = switchProtocols(
|
|
411
|
+
const HTTP_URL = switchProtocols(initialEndpoint, {
|
|
412
412
|
wss: 'https',
|
|
413
413
|
ws: 'http',
|
|
414
414
|
});
|
|
415
415
|
const executor = (request) => {
|
|
416
|
-
var _a;
|
|
416
|
+
var _a, _b;
|
|
417
417
|
const controller = new crossUndiciFetch.AbortController();
|
|
418
418
|
let method = defaultMethod;
|
|
419
419
|
if (options === null || options === void 0 ? void 0 : options.useGETForQueries) {
|
|
@@ -423,7 +423,8 @@ class UrlLoader {
|
|
|
423
423
|
method = 'GET';
|
|
424
424
|
}
|
|
425
425
|
}
|
|
426
|
-
const
|
|
426
|
+
const endpoint = ((_a = request.extensions) === null || _a === void 0 ? void 0 : _a.endpoint) || initialEndpoint;
|
|
427
|
+
const headers = Object.assign({}, options === null || options === void 0 ? void 0 : options.headers, ((_b = request.extensions) === null || _b === void 0 ? void 0 : _b.headers) || {});
|
|
427
428
|
const acceptedProtocols = [`application/json`];
|
|
428
429
|
if (method === 'GET' && (options === null || options === void 0 ? void 0 : options.subscriptionsProtocol) === exports.SubscriptionProtocol.SSE) {
|
|
429
430
|
acceptedProtocols.push('text/event-stream');
|
|
@@ -439,6 +440,15 @@ class UrlLoader {
|
|
|
439
440
|
operationName: request.operationName,
|
|
440
441
|
extensions: request.extensions,
|
|
441
442
|
};
|
|
443
|
+
let timeoutId;
|
|
444
|
+
if (options === null || options === void 0 ? void 0 : options.timeout) {
|
|
445
|
+
timeoutId = setTimeout(() => {
|
|
446
|
+
if (!controller.signal.aborted) {
|
|
447
|
+
controller.abort();
|
|
448
|
+
}
|
|
449
|
+
}, options.timeout);
|
|
450
|
+
}
|
|
451
|
+
const credentials = (options === null || options === void 0 ? void 0 : options.credentials) || 'include';
|
|
442
452
|
return new valueOrPromise.ValueOrPromise(() => {
|
|
443
453
|
switch (method) {
|
|
444
454
|
case 'GET':
|
|
@@ -448,7 +458,7 @@ class UrlLoader {
|
|
|
448
458
|
});
|
|
449
459
|
return fetch(finalUrl, {
|
|
450
460
|
method: 'GET',
|
|
451
|
-
credentials
|
|
461
|
+
credentials,
|
|
452
462
|
headers: {
|
|
453
463
|
accept,
|
|
454
464
|
...headers,
|
|
@@ -460,7 +470,7 @@ class UrlLoader {
|
|
|
460
470
|
return new valueOrPromise.ValueOrPromise(() => this.createFormDataFromVariables(requestBody))
|
|
461
471
|
.then(form => fetch(HTTP_URL, {
|
|
462
472
|
method: 'POST',
|
|
463
|
-
credentials
|
|
473
|
+
credentials,
|
|
464
474
|
body: form,
|
|
465
475
|
headers: {
|
|
466
476
|
accept,
|
|
@@ -473,7 +483,7 @@ class UrlLoader {
|
|
|
473
483
|
else {
|
|
474
484
|
return fetch(HTTP_URL, {
|
|
475
485
|
method: 'POST',
|
|
476
|
-
credentials
|
|
486
|
+
credentials,
|
|
477
487
|
body: JSON.stringify(requestBody),
|
|
478
488
|
headers: {
|
|
479
489
|
accept,
|
|
@@ -486,6 +496,13 @@ class UrlLoader {
|
|
|
486
496
|
}
|
|
487
497
|
})
|
|
488
498
|
.then((fetchResult) => {
|
|
499
|
+
if (timeoutId != null) {
|
|
500
|
+
clearTimeout(timeoutId);
|
|
501
|
+
}
|
|
502
|
+
// Retry should respect HTTP Errors
|
|
503
|
+
if ((options === null || options === void 0 ? void 0 : options.retry) != null && !fetchResult.status.toString().startsWith('2')) {
|
|
504
|
+
throw new Error(fetchResult.statusText || `HTTP Error: ${fetchResult.status}`);
|
|
505
|
+
}
|
|
489
506
|
const contentType = fetchResult.headers.get('content-type');
|
|
490
507
|
if (contentType === null || contentType === void 0 ? void 0 : contentType.includes('text/event-stream')) {
|
|
491
508
|
return handleEventStreamResponse(fetchResult).then(resultStream => addCancelToResponseStream(resultStream, controller));
|
|
@@ -497,6 +514,40 @@ class UrlLoader {
|
|
|
497
514
|
})
|
|
498
515
|
.resolve();
|
|
499
516
|
};
|
|
517
|
+
if ((options === null || options === void 0 ? void 0 : options.retry) != null) {
|
|
518
|
+
return function retryExecutor(request) {
|
|
519
|
+
let result;
|
|
520
|
+
let error;
|
|
521
|
+
let attempt = 0;
|
|
522
|
+
function retryAttempt() {
|
|
523
|
+
attempt++;
|
|
524
|
+
if (attempt > options.retry) {
|
|
525
|
+
if (result != null) {
|
|
526
|
+
return result;
|
|
527
|
+
}
|
|
528
|
+
if (error != null) {
|
|
529
|
+
throw error;
|
|
530
|
+
}
|
|
531
|
+
throw new Error('No result');
|
|
532
|
+
}
|
|
533
|
+
return new valueOrPromise.ValueOrPromise(() => executor(request))
|
|
534
|
+
.then(res => {
|
|
535
|
+
var _a;
|
|
536
|
+
result = res;
|
|
537
|
+
if ((_a = result === null || result === void 0 ? void 0 : result.errors) === null || _a === void 0 ? void 0 : _a.length) {
|
|
538
|
+
return retryAttempt();
|
|
539
|
+
}
|
|
540
|
+
return result;
|
|
541
|
+
})
|
|
542
|
+
.catch((e) => {
|
|
543
|
+
error = e;
|
|
544
|
+
return retryAttempt();
|
|
545
|
+
})
|
|
546
|
+
.resolve();
|
|
547
|
+
}
|
|
548
|
+
return retryAttempt();
|
|
549
|
+
};
|
|
550
|
+
}
|
|
500
551
|
return executor;
|
|
501
552
|
}
|
|
502
553
|
buildWSExecutor(subscriptionsEndpoint, webSocketImpl, connectionParams) {
|
package/index.mjs
CHANGED
|
@@ -382,14 +382,14 @@ class UrlLoader {
|
|
|
382
382
|
const finalUrl = urlObj.toString().replace(dummyHostname, '');
|
|
383
383
|
return finalUrl;
|
|
384
384
|
}
|
|
385
|
-
buildHTTPExecutor(
|
|
385
|
+
buildHTTPExecutor(initialEndpoint, fetch, options) {
|
|
386
386
|
const defaultMethod = this.getDefaultMethodFromOptions(options === null || options === void 0 ? void 0 : options.method, 'POST');
|
|
387
|
-
const HTTP_URL = switchProtocols(
|
|
387
|
+
const HTTP_URL = switchProtocols(initialEndpoint, {
|
|
388
388
|
wss: 'https',
|
|
389
389
|
ws: 'http',
|
|
390
390
|
});
|
|
391
391
|
const executor = (request) => {
|
|
392
|
-
var _a;
|
|
392
|
+
var _a, _b;
|
|
393
393
|
const controller = new AbortController();
|
|
394
394
|
let method = defaultMethod;
|
|
395
395
|
if (options === null || options === void 0 ? void 0 : options.useGETForQueries) {
|
|
@@ -399,7 +399,8 @@ class UrlLoader {
|
|
|
399
399
|
method = 'GET';
|
|
400
400
|
}
|
|
401
401
|
}
|
|
402
|
-
const
|
|
402
|
+
const endpoint = ((_a = request.extensions) === null || _a === void 0 ? void 0 : _a.endpoint) || initialEndpoint;
|
|
403
|
+
const headers = Object.assign({}, options === null || options === void 0 ? void 0 : options.headers, ((_b = request.extensions) === null || _b === void 0 ? void 0 : _b.headers) || {});
|
|
403
404
|
const acceptedProtocols = [`application/json`];
|
|
404
405
|
if (method === 'GET' && (options === null || options === void 0 ? void 0 : options.subscriptionsProtocol) === SubscriptionProtocol.SSE) {
|
|
405
406
|
acceptedProtocols.push('text/event-stream');
|
|
@@ -415,6 +416,15 @@ class UrlLoader {
|
|
|
415
416
|
operationName: request.operationName,
|
|
416
417
|
extensions: request.extensions,
|
|
417
418
|
};
|
|
419
|
+
let timeoutId;
|
|
420
|
+
if (options === null || options === void 0 ? void 0 : options.timeout) {
|
|
421
|
+
timeoutId = setTimeout(() => {
|
|
422
|
+
if (!controller.signal.aborted) {
|
|
423
|
+
controller.abort();
|
|
424
|
+
}
|
|
425
|
+
}, options.timeout);
|
|
426
|
+
}
|
|
427
|
+
const credentials = (options === null || options === void 0 ? void 0 : options.credentials) || 'include';
|
|
418
428
|
return new ValueOrPromise(() => {
|
|
419
429
|
switch (method) {
|
|
420
430
|
case 'GET':
|
|
@@ -424,7 +434,7 @@ class UrlLoader {
|
|
|
424
434
|
});
|
|
425
435
|
return fetch(finalUrl, {
|
|
426
436
|
method: 'GET',
|
|
427
|
-
credentials
|
|
437
|
+
credentials,
|
|
428
438
|
headers: {
|
|
429
439
|
accept,
|
|
430
440
|
...headers,
|
|
@@ -436,7 +446,7 @@ class UrlLoader {
|
|
|
436
446
|
return new ValueOrPromise(() => this.createFormDataFromVariables(requestBody))
|
|
437
447
|
.then(form => fetch(HTTP_URL, {
|
|
438
448
|
method: 'POST',
|
|
439
|
-
credentials
|
|
449
|
+
credentials,
|
|
440
450
|
body: form,
|
|
441
451
|
headers: {
|
|
442
452
|
accept,
|
|
@@ -449,7 +459,7 @@ class UrlLoader {
|
|
|
449
459
|
else {
|
|
450
460
|
return fetch(HTTP_URL, {
|
|
451
461
|
method: 'POST',
|
|
452
|
-
credentials
|
|
462
|
+
credentials,
|
|
453
463
|
body: JSON.stringify(requestBody),
|
|
454
464
|
headers: {
|
|
455
465
|
accept,
|
|
@@ -462,6 +472,13 @@ class UrlLoader {
|
|
|
462
472
|
}
|
|
463
473
|
})
|
|
464
474
|
.then((fetchResult) => {
|
|
475
|
+
if (timeoutId != null) {
|
|
476
|
+
clearTimeout(timeoutId);
|
|
477
|
+
}
|
|
478
|
+
// Retry should respect HTTP Errors
|
|
479
|
+
if ((options === null || options === void 0 ? void 0 : options.retry) != null && !fetchResult.status.toString().startsWith('2')) {
|
|
480
|
+
throw new Error(fetchResult.statusText || `HTTP Error: ${fetchResult.status}`);
|
|
481
|
+
}
|
|
465
482
|
const contentType = fetchResult.headers.get('content-type');
|
|
466
483
|
if (contentType === null || contentType === void 0 ? void 0 : contentType.includes('text/event-stream')) {
|
|
467
484
|
return handleEventStreamResponse(fetchResult).then(resultStream => addCancelToResponseStream(resultStream, controller));
|
|
@@ -473,6 +490,40 @@ class UrlLoader {
|
|
|
473
490
|
})
|
|
474
491
|
.resolve();
|
|
475
492
|
};
|
|
493
|
+
if ((options === null || options === void 0 ? void 0 : options.retry) != null) {
|
|
494
|
+
return function retryExecutor(request) {
|
|
495
|
+
let result;
|
|
496
|
+
let error;
|
|
497
|
+
let attempt = 0;
|
|
498
|
+
function retryAttempt() {
|
|
499
|
+
attempt++;
|
|
500
|
+
if (attempt > options.retry) {
|
|
501
|
+
if (result != null) {
|
|
502
|
+
return result;
|
|
503
|
+
}
|
|
504
|
+
if (error != null) {
|
|
505
|
+
throw error;
|
|
506
|
+
}
|
|
507
|
+
throw new Error('No result');
|
|
508
|
+
}
|
|
509
|
+
return new ValueOrPromise(() => executor(request))
|
|
510
|
+
.then(res => {
|
|
511
|
+
var _a;
|
|
512
|
+
result = res;
|
|
513
|
+
if ((_a = result === null || result === void 0 ? void 0 : result.errors) === null || _a === void 0 ? void 0 : _a.length) {
|
|
514
|
+
return retryAttempt();
|
|
515
|
+
}
|
|
516
|
+
return result;
|
|
517
|
+
})
|
|
518
|
+
.catch((e) => {
|
|
519
|
+
error = e;
|
|
520
|
+
return retryAttempt();
|
|
521
|
+
})
|
|
522
|
+
.resolve();
|
|
523
|
+
}
|
|
524
|
+
return retryAttempt();
|
|
525
|
+
};
|
|
526
|
+
}
|
|
476
527
|
return executor;
|
|
477
528
|
}
|
|
478
529
|
buildWSExecutor(subscriptionsEndpoint, webSocketImpl, connectionParams) {
|