@graphql-tools/url-loader 7.7.2 → 7.8.0-alpha-696c179a.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 +9 -0
- package/index.js +54 -4
- package/index.mjs +54 -4
- 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,14 @@ 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;
|
|
83
92
|
}
|
|
84
93
|
/**
|
|
85
94
|
* 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,14 @@ 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
|
+
}
|
|
442
451
|
return new valueOrPromise.ValueOrPromise(() => {
|
|
443
452
|
switch (method) {
|
|
444
453
|
case 'GET':
|
|
@@ -486,6 +495,13 @@ class UrlLoader {
|
|
|
486
495
|
}
|
|
487
496
|
})
|
|
488
497
|
.then((fetchResult) => {
|
|
498
|
+
if (timeoutId != null) {
|
|
499
|
+
clearTimeout(timeoutId);
|
|
500
|
+
}
|
|
501
|
+
// Retry should respect HTTP Errors
|
|
502
|
+
if ((options === null || options === void 0 ? void 0 : options.retry) != null && !fetchResult.status.toString().startsWith('2')) {
|
|
503
|
+
throw new Error(fetchResult.statusText || `HTTP Error: ${fetchResult.status}`);
|
|
504
|
+
}
|
|
489
505
|
const contentType = fetchResult.headers.get('content-type');
|
|
490
506
|
if (contentType === null || contentType === void 0 ? void 0 : contentType.includes('text/event-stream')) {
|
|
491
507
|
return handleEventStreamResponse(fetchResult).then(resultStream => addCancelToResponseStream(resultStream, controller));
|
|
@@ -497,6 +513,40 @@ class UrlLoader {
|
|
|
497
513
|
})
|
|
498
514
|
.resolve();
|
|
499
515
|
};
|
|
516
|
+
if ((options === null || options === void 0 ? void 0 : options.retry) != null) {
|
|
517
|
+
return function retryExecutor(request) {
|
|
518
|
+
let result;
|
|
519
|
+
let error;
|
|
520
|
+
let attempt = 0;
|
|
521
|
+
function retryAttempt() {
|
|
522
|
+
attempt++;
|
|
523
|
+
if (attempt > options.retry) {
|
|
524
|
+
if (result != null) {
|
|
525
|
+
return result;
|
|
526
|
+
}
|
|
527
|
+
if (error != null) {
|
|
528
|
+
throw error;
|
|
529
|
+
}
|
|
530
|
+
throw new Error('No result');
|
|
531
|
+
}
|
|
532
|
+
return new valueOrPromise.ValueOrPromise(() => executor(request))
|
|
533
|
+
.then(res => {
|
|
534
|
+
var _a;
|
|
535
|
+
result = res;
|
|
536
|
+
if ((_a = result === null || result === void 0 ? void 0 : result.errors) === null || _a === void 0 ? void 0 : _a.length) {
|
|
537
|
+
return retryAttempt();
|
|
538
|
+
}
|
|
539
|
+
return result;
|
|
540
|
+
})
|
|
541
|
+
.catch((e) => {
|
|
542
|
+
error = e;
|
|
543
|
+
return retryAttempt();
|
|
544
|
+
})
|
|
545
|
+
.resolve();
|
|
546
|
+
}
|
|
547
|
+
return retryAttempt();
|
|
548
|
+
};
|
|
549
|
+
}
|
|
500
550
|
return executor;
|
|
501
551
|
}
|
|
502
552
|
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,14 @@ 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
|
+
}
|
|
418
427
|
return new ValueOrPromise(() => {
|
|
419
428
|
switch (method) {
|
|
420
429
|
case 'GET':
|
|
@@ -462,6 +471,13 @@ class UrlLoader {
|
|
|
462
471
|
}
|
|
463
472
|
})
|
|
464
473
|
.then((fetchResult) => {
|
|
474
|
+
if (timeoutId != null) {
|
|
475
|
+
clearTimeout(timeoutId);
|
|
476
|
+
}
|
|
477
|
+
// Retry should respect HTTP Errors
|
|
478
|
+
if ((options === null || options === void 0 ? void 0 : options.retry) != null && !fetchResult.status.toString().startsWith('2')) {
|
|
479
|
+
throw new Error(fetchResult.statusText || `HTTP Error: ${fetchResult.status}`);
|
|
480
|
+
}
|
|
465
481
|
const contentType = fetchResult.headers.get('content-type');
|
|
466
482
|
if (contentType === null || contentType === void 0 ? void 0 : contentType.includes('text/event-stream')) {
|
|
467
483
|
return handleEventStreamResponse(fetchResult).then(resultStream => addCancelToResponseStream(resultStream, controller));
|
|
@@ -473,6 +489,40 @@ class UrlLoader {
|
|
|
473
489
|
})
|
|
474
490
|
.resolve();
|
|
475
491
|
};
|
|
492
|
+
if ((options === null || options === void 0 ? void 0 : options.retry) != null) {
|
|
493
|
+
return function retryExecutor(request) {
|
|
494
|
+
let result;
|
|
495
|
+
let error;
|
|
496
|
+
let attempt = 0;
|
|
497
|
+
function retryAttempt() {
|
|
498
|
+
attempt++;
|
|
499
|
+
if (attempt > options.retry) {
|
|
500
|
+
if (result != null) {
|
|
501
|
+
return result;
|
|
502
|
+
}
|
|
503
|
+
if (error != null) {
|
|
504
|
+
throw error;
|
|
505
|
+
}
|
|
506
|
+
throw new Error('No result');
|
|
507
|
+
}
|
|
508
|
+
return new ValueOrPromise(() => executor(request))
|
|
509
|
+
.then(res => {
|
|
510
|
+
var _a;
|
|
511
|
+
result = res;
|
|
512
|
+
if ((_a = result === null || result === void 0 ? void 0 : result.errors) === null || _a === void 0 ? void 0 : _a.length) {
|
|
513
|
+
return retryAttempt();
|
|
514
|
+
}
|
|
515
|
+
return result;
|
|
516
|
+
})
|
|
517
|
+
.catch((e) => {
|
|
518
|
+
error = e;
|
|
519
|
+
return retryAttempt();
|
|
520
|
+
})
|
|
521
|
+
.resolve();
|
|
522
|
+
}
|
|
523
|
+
return retryAttempt();
|
|
524
|
+
};
|
|
525
|
+
}
|
|
476
526
|
return executor;
|
|
477
527
|
}
|
|
478
528
|
buildWSExecutor(subscriptionsEndpoint, webSocketImpl, connectionParams) {
|