@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 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(endpoint, fetch, options) {
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(endpoint, {
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 headers = Object.assign({}, options === null || options === void 0 ? void 0 : options.headers, ((_a = request.extensions) === null || _a === void 0 ? void 0 : _a.headers) || {});
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(endpoint, fetch, options) {
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(endpoint, {
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 headers = Object.assign({}, options === null || options === void 0 ? void 0 : options.headers, ((_a = request.extensions) === null || _a === void 0 ? void 0 : _a.headers) || {});
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-tools/url-loader",
3
- "version": "7.7.2",
3
+ "version": "7.8.0-alpha-696c179a.0",
4
4
  "description": "A set of utils for faster development of GraphQL tools",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {