@graphql-hive/core 0.16.0 → 0.17.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.
@@ -4,16 +4,12 @@ exports.createAgent = createAgent;
4
4
  const tslib_1 = require("tslib");
5
5
  const circuit_js_1 = tslib_1.__importDefault(require("../circuit-breaker/circuit.js"));
6
6
  const version_js_1 = require("../version.js");
7
+ const circuit_breaker_js_1 = require("./circuit-breaker.js");
7
8
  const http_client_js_1 = require("./http-client.js");
8
9
  const utils_js_1 = require("./utils.js");
9
- const defaultCircuitBreakerConfiguration = {
10
- errorThresholdPercentage: 50,
11
- volumeThreshold: 10,
12
- resetTimeout: 30000,
13
- };
14
10
  function createAgent(pluginOptions, { data, body, headers = () => ({}), }) {
15
11
  const options = Object.assign(Object.assign({ timeout: 30000, enabled: true, minTimeout: 200, maxRetries: 3, sendInterval: 10000, maxSize: 25, name: 'hive-client', version: version_js_1.version }, pluginOptions), { circuitBreaker: pluginOptions.circuitBreaker == null || pluginOptions.circuitBreaker === true
16
- ? defaultCircuitBreakerConfiguration
12
+ ? circuit_breaker_js_1.defaultCircuitBreakerConfiguration
17
13
  : pluginOptions.circuitBreaker === false
18
14
  ? null
19
15
  : pluginOptions.circuitBreaker });
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCDNArtifactFetcher = createCDNArtifactFetcher;
4
+ const tslib_1 = require("tslib");
5
+ const circuit_js_1 = tslib_1.__importDefault(require("../circuit-breaker/circuit.js"));
6
+ const version_js_1 = require("../version.js");
7
+ const circuit_breaker_js_1 = require("./circuit-breaker.js");
8
+ const http_client_js_1 = require("./http-client.js");
9
+ const utils_js_1 = require("./utils.js");
10
+ function isRequestOk(response) {
11
+ return response.status === 304 || response.ok;
12
+ }
13
+ /**
14
+ * Create a handler for fetching a CDN artifact with built-in cache and circuit breaker.
15
+ * It is intended for polling supergraph, schema sdl or services.
16
+ */
17
+ function createCDNArtifactFetcher(args) {
18
+ var _a, _b;
19
+ const logger = (0, utils_js_1.chooseLogger)(args.logger);
20
+ let cacheETag = null;
21
+ let cached = null;
22
+ const clientInfo = (_a = args.client) !== null && _a !== void 0 ? _a : { name: 'hive-client', version: version_js_1.version };
23
+ const circuitBreakerConfig = (_b = args.circuitBreaker) !== null && _b !== void 0 ? _b : circuit_breaker_js_1.defaultCircuitBreakerConfiguration;
24
+ const endpoints = Array.isArray(args.endpoint) ? args.endpoint : [args.endpoint];
25
+ function runFetch(circuitBreaker, endpoint) {
26
+ var _a;
27
+ const signal = circuitBreaker.getSignal();
28
+ const headers = {
29
+ 'X-Hive-CDN-Key': args.accessKey,
30
+ 'User-Agent': `${clientInfo.name}/${clientInfo.version}`,
31
+ };
32
+ if (cacheETag) {
33
+ headers['If-None-Match'] = cacheETag;
34
+ }
35
+ return http_client_js_1.http.get(endpoint, {
36
+ headers,
37
+ isRequestOk,
38
+ retry: (_a = args.retry) !== null && _a !== void 0 ? _a : {
39
+ retries: 10,
40
+ maxTimeout: 200,
41
+ minTimeout: 1,
42
+ },
43
+ timeout: args.timeout,
44
+ logger,
45
+ fetchImplementation: args.fetch,
46
+ signal,
47
+ });
48
+ }
49
+ const circuitBreakers = endpoints.map(endpoint => {
50
+ const circuitBreaker = new circuit_js_1.default(async function fire() {
51
+ return await runFetch(circuitBreaker, endpoint);
52
+ }, Object.assign(Object.assign({}, circuitBreakerConfig), { timeout: false, autoRenewAbortController: true }));
53
+ return circuitBreaker;
54
+ });
55
+ async function attempt(breaker) {
56
+ var _a;
57
+ const response = await breaker.fire();
58
+ if (response.status === 304) {
59
+ if (cached !== null) {
60
+ return cached;
61
+ }
62
+ throw new Error('Unexpected 304 with no cache');
63
+ }
64
+ const contents = await response.text();
65
+ const result = {
66
+ hash: await (0, utils_js_1.createHash)('SHA-256').update(contents).digest('base64'),
67
+ contents,
68
+ schemaVersionId: (_a = response.headers.get('x-hive-schema-version-id')) !== null && _a !== void 0 ? _a : null,
69
+ };
70
+ const etag = response.headers.get('etag');
71
+ if (etag) {
72
+ cached = result;
73
+ cacheETag = etag;
74
+ }
75
+ return result;
76
+ }
77
+ return {
78
+ async fetch() {
79
+ for (const [index, breaker] of circuitBreakers.entries()) {
80
+ try {
81
+ return await attempt(breaker);
82
+ }
83
+ catch (error) {
84
+ logger.debug({ error });
85
+ if (index === circuitBreakers.length - 1) {
86
+ if (cached) {
87
+ return cached;
88
+ }
89
+ }
90
+ }
91
+ }
92
+ throw new Error('Could not retrieve artifact.');
93
+ },
94
+ dispose() {
95
+ circuitBreakers.forEach(breaker => breaker.shutdown());
96
+ },
97
+ };
98
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultCircuitBreakerConfiguration = void 0;
4
+ exports.defaultCircuitBreakerConfiguration = {
5
+ errorThresholdPercentage: 50,
6
+ volumeThreshold: 10,
7
+ resetTimeout: 30000,
8
+ };
@@ -36,6 +36,9 @@ function createHive(options) {
36
36
  logger });
37
37
  const usage = (0, usage_js_1.createUsage)(mergedOptions);
38
38
  const schemaReporter = (0, reporting_js_1.createReporting)(mergedOptions);
39
+ const persistedDocuments = options.experimental__persistedDocuments
40
+ ? (0, persisted_documents_js_1.createPersistedDocuments)(Object.assign(Object.assign({}, options.experimental__persistedDocuments), { logger, fetch: options.experimental__persistedDocuments.fetch }))
41
+ : null;
39
42
  function reportSchema({ schema }) {
40
43
  schemaReporter.report({ schema });
41
44
  }
@@ -46,7 +49,7 @@ function createHive(options) {
46
49
  return usage.collectRequest(...args);
47
50
  }
48
51
  async function dispose() {
49
- await Promise.all([schemaReporter.dispose(), usage.dispose()]);
52
+ await Promise.all([schemaReporter.dispose(), usage.dispose(), persistedDocuments === null || persistedDocuments === void 0 ? void 0 : persistedDocuments.dispose()]);
50
53
  }
51
54
  const isOrganizationAccessToken = !(0, utils_js_1.isLegacyAccessToken)((_b = options.token) !== null && _b !== void 0 ? _b : '');
52
55
  // enabledOnly when `printTokenInfo` is `true` or `debug` is true and `printTokenInfo` is not `false`
@@ -189,9 +192,7 @@ function createHive(options) {
189
192
  collectSubscriptionUsage: usage.collectSubscription,
190
193
  createInstrumentedSubscribe,
191
194
  createInstrumentedExecute,
192
- experimental__persistedDocuments: options.experimental__persistedDocuments
193
- ? (0, persisted_documents_js_1.createPersistedDocuments)(Object.assign(Object.assign({}, options.experimental__persistedDocuments), { logger, fetch: options.experimental__persistedDocuments.fetch }))
194
- : null,
195
+ experimental__persistedDocuments: persistedDocuments,
195
196
  };
196
197
  }
197
198
  exports.hiveClientSymbol = Symbol('hive-client');
@@ -3,7 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createPersistedDocuments = createPersistedDocuments;
4
4
  const tslib_1 = require("tslib");
5
5
  const tiny_lru_1 = tslib_1.__importDefault(require("tiny-lru"));
6
+ const circuit_js_1 = tslib_1.__importDefault(require("../circuit-breaker/circuit.js"));
7
+ const circuit_breaker_js_1 = require("./circuit-breaker.js");
6
8
  const http_client_js_1 = require("./http-client.js");
9
+ function isRequestOk(response) {
10
+ return response.status === 200 || response.status === 404;
11
+ }
7
12
  function createPersistedDocuments(config) {
8
13
  var _a;
9
14
  const persistedDocumentsCache = (0, tiny_lru_1.default)((_a = config.cache) !== null && _a !== void 0 ? _a : 10000);
@@ -20,42 +25,77 @@ function createPersistedDocuments(config) {
20
25
  }
21
26
  /** if there is already a in-flight request for a document, we re-use it. */
22
27
  const fetchCache = new Map();
23
- /** Batch load a persisted documents */
24
- function loadPersistedDocument(documentId) {
25
- const document = persistedDocumentsCache.get(documentId);
26
- if (document) {
27
- return document;
28
- }
29
- const cdnDocumentId = documentId.replaceAll('~', '/');
30
- const url = config.cdn.endpoint + '/apps/' + cdnDocumentId;
31
- let promise = fetchCache.get(url);
32
- if (!promise) {
33
- promise = http_client_js_1.http
34
- .get(url, {
28
+ const endpoints = Array.isArray(config.cdn.endpoint)
29
+ ? config.cdn.endpoint
30
+ : [config.cdn.endpoint];
31
+ const circuitBreakers = endpoints.map(endpoint => {
32
+ var _a;
33
+ const circuitBreaker = new circuit_js_1.default(async function doFetch(cdnDocumentId) {
34
+ const signal = circuitBreaker.getSignal();
35
+ return await http_client_js_1.http
36
+ .get(endpoint + '/apps/' + cdnDocumentId, {
35
37
  headers: {
36
38
  'X-Hive-CDN-Key': config.cdn.accessToken,
37
39
  },
38
40
  logger: config.logger,
39
- isRequestOk: response => response.status === 200 || response.status === 404,
41
+ isRequestOk,
40
42
  fetchImplementation: config.fetch,
43
+ signal,
44
+ retry: config.retry,
41
45
  })
42
46
  .then(async (response) => {
43
47
  if (response.status !== 200) {
44
48
  return null;
45
49
  }
46
50
  const text = await response.text();
47
- persistedDocumentsCache.set(documentId, text);
48
51
  return text;
49
- })
50
- .finally(() => {
51
- fetchCache.delete(url);
52
52
  });
53
- fetchCache.set(url, promise);
53
+ }, Object.assign(Object.assign({}, ((_a = config.circuitBreaker) !== null && _a !== void 0 ? _a : circuit_breaker_js_1.defaultCircuitBreakerConfiguration)), { timeout: false, autoRenewAbortController: true }));
54
+ return circuitBreaker;
55
+ });
56
+ /** Batch load a persisted documents */
57
+ function loadPersistedDocument(documentId) {
58
+ const document = persistedDocumentsCache.get(documentId);
59
+ if (document) {
60
+ return document;
61
+ }
62
+ let promise = fetchCache.get(documentId);
63
+ if (promise) {
64
+ return promise;
54
65
  }
66
+ promise = Promise.resolve()
67
+ .then(async () => {
68
+ const cdnDocumentId = documentId.replaceAll('~', '/');
69
+ let lastError = null;
70
+ for (const breaker of circuitBreakers) {
71
+ try {
72
+ return await breaker.fire(cdnDocumentId);
73
+ }
74
+ catch (error) {
75
+ config.logger.debug({ error });
76
+ lastError = error;
77
+ }
78
+ }
79
+ if (lastError) {
80
+ config.logger.error({ error: lastError });
81
+ }
82
+ throw new Error('Failed to look up persisted operation.');
83
+ })
84
+ .then(result => {
85
+ persistedDocumentsCache.set(documentId, result);
86
+ return result;
87
+ })
88
+ .finally(() => {
89
+ fetchCache.delete(documentId);
90
+ });
91
+ fetchCache.set(documentId, promise);
55
92
  return promise;
56
93
  }
57
94
  return {
58
95
  allowArbitraryDocuments,
59
96
  resolve: loadPersistedDocument,
97
+ dispose() {
98
+ circuitBreakers.map(breaker => breaker.shutdown());
99
+ },
60
100
  };
61
101
  }
@@ -4,6 +4,9 @@ exports.createSupergraphSDLFetcher = createSupergraphSDLFetcher;
4
4
  const version_js_1 = require("../version.js");
5
5
  const http_client_js_1 = require("./http-client.js");
6
6
  const utils_js_1 = require("./utils.js");
7
+ /**
8
+ * @deprecated Please use {createCDNArtifactFetcher} instead.
9
+ */
7
10
  function createSupergraphSDLFetcher(options) {
8
11
  let cacheETag = null;
9
12
  let cached = null;
package/cjs/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createSupergraphSDLFetcher = exports.URL = exports.http = exports.joinUrl = exports.createHash = exports.isAsyncIterable = exports.isHiveClient = exports.atLeastOnceSampler = exports.autoDisposeSymbol = exports.createHive = exports.createServicesFetcher = exports.createSchemaFetcher = exports.collectSchemaCoordinates = void 0;
3
+ exports.createCDNArtifactFetcher = exports.createSupergraphSDLFetcher = exports.URL = exports.http = exports.joinUrl = exports.createHash = exports.isAsyncIterable = exports.isHiveClient = exports.atLeastOnceSampler = exports.autoDisposeSymbol = exports.createHive = exports.createServicesFetcher = exports.createSchemaFetcher = exports.collectSchemaCoordinates = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  tslib_1.__exportStar(require("./normalize/operation.js"), exports);
6
6
  var collect_schema_coordinates_js_1 = require("./client/collect-schema-coordinates.js");
@@ -23,3 +23,5 @@ Object.defineProperty(exports, "http", { enumerable: true, get: function () { re
23
23
  Object.defineProperty(exports, "URL", { enumerable: true, get: function () { return http_client_js_1.URL; } });
24
24
  var supergraph_js_1 = require("./client/supergraph.js");
25
25
  Object.defineProperty(exports, "createSupergraphSDLFetcher", { enumerable: true, get: function () { return supergraph_js_1.createSupergraphSDLFetcher; } });
26
+ var cdn_artifact_fetcher_js_1 = require("./client/cdn-artifact-fetcher.js");
27
+ Object.defineProperty(exports, "createCDNArtifactFetcher", { enumerable: true, get: function () { return cdn_artifact_fetcher_js_1.createCDNArtifactFetcher; } });
package/cjs/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.version = void 0;
4
- exports.version = '0.16.0';
4
+ exports.version = '0.17.0';
@@ -1,12 +1,8 @@
1
1
  import CircuitBreaker from '../circuit-breaker/circuit.js';
2
2
  import { version } from '../version.js';
3
+ import { defaultCircuitBreakerConfiguration, } from './circuit-breaker.js';
3
4
  import { http } from './http-client.js';
4
5
  import { chooseLogger } from './utils.js';
5
- const defaultCircuitBreakerConfiguration = {
6
- errorThresholdPercentage: 50,
7
- volumeThreshold: 10,
8
- resetTimeout: 30000,
9
- };
10
6
  export function createAgent(pluginOptions, { data, body, headers = () => ({}), }) {
11
7
  const options = Object.assign(Object.assign({ timeout: 30000, enabled: true, minTimeout: 200, maxRetries: 3, sendInterval: 10000, maxSize: 25, name: 'hive-client', version }, pluginOptions), { circuitBreaker: pluginOptions.circuitBreaker == null || pluginOptions.circuitBreaker === true
12
8
  ? defaultCircuitBreakerConfiguration
@@ -0,0 +1,94 @@
1
+ import CircuitBreaker from '../circuit-breaker/circuit.js';
2
+ import { version } from '../version.js';
3
+ import { defaultCircuitBreakerConfiguration, } from './circuit-breaker.js';
4
+ import { http } from './http-client.js';
5
+ import { chooseLogger, createHash } from './utils.js';
6
+ function isRequestOk(response) {
7
+ return response.status === 304 || response.ok;
8
+ }
9
+ /**
10
+ * Create a handler for fetching a CDN artifact with built-in cache and circuit breaker.
11
+ * It is intended for polling supergraph, schema sdl or services.
12
+ */
13
+ export function createCDNArtifactFetcher(args) {
14
+ var _a, _b;
15
+ const logger = chooseLogger(args.logger);
16
+ let cacheETag = null;
17
+ let cached = null;
18
+ const clientInfo = (_a = args.client) !== null && _a !== void 0 ? _a : { name: 'hive-client', version };
19
+ const circuitBreakerConfig = (_b = args.circuitBreaker) !== null && _b !== void 0 ? _b : defaultCircuitBreakerConfiguration;
20
+ const endpoints = Array.isArray(args.endpoint) ? args.endpoint : [args.endpoint];
21
+ function runFetch(circuitBreaker, endpoint) {
22
+ var _a;
23
+ const signal = circuitBreaker.getSignal();
24
+ const headers = {
25
+ 'X-Hive-CDN-Key': args.accessKey,
26
+ 'User-Agent': `${clientInfo.name}/${clientInfo.version}`,
27
+ };
28
+ if (cacheETag) {
29
+ headers['If-None-Match'] = cacheETag;
30
+ }
31
+ return http.get(endpoint, {
32
+ headers,
33
+ isRequestOk,
34
+ retry: (_a = args.retry) !== null && _a !== void 0 ? _a : {
35
+ retries: 10,
36
+ maxTimeout: 200,
37
+ minTimeout: 1,
38
+ },
39
+ timeout: args.timeout,
40
+ logger,
41
+ fetchImplementation: args.fetch,
42
+ signal,
43
+ });
44
+ }
45
+ const circuitBreakers = endpoints.map(endpoint => {
46
+ const circuitBreaker = new CircuitBreaker(async function fire() {
47
+ return await runFetch(circuitBreaker, endpoint);
48
+ }, Object.assign(Object.assign({}, circuitBreakerConfig), { timeout: false, autoRenewAbortController: true }));
49
+ return circuitBreaker;
50
+ });
51
+ async function attempt(breaker) {
52
+ var _a;
53
+ const response = await breaker.fire();
54
+ if (response.status === 304) {
55
+ if (cached !== null) {
56
+ return cached;
57
+ }
58
+ throw new Error('Unexpected 304 with no cache');
59
+ }
60
+ const contents = await response.text();
61
+ const result = {
62
+ hash: await createHash('SHA-256').update(contents).digest('base64'),
63
+ contents,
64
+ schemaVersionId: (_a = response.headers.get('x-hive-schema-version-id')) !== null && _a !== void 0 ? _a : null,
65
+ };
66
+ const etag = response.headers.get('etag');
67
+ if (etag) {
68
+ cached = result;
69
+ cacheETag = etag;
70
+ }
71
+ return result;
72
+ }
73
+ return {
74
+ async fetch() {
75
+ for (const [index, breaker] of circuitBreakers.entries()) {
76
+ try {
77
+ return await attempt(breaker);
78
+ }
79
+ catch (error) {
80
+ logger.debug({ error });
81
+ if (index === circuitBreakers.length - 1) {
82
+ if (cached) {
83
+ return cached;
84
+ }
85
+ }
86
+ }
87
+ }
88
+ throw new Error('Could not retrieve artifact.');
89
+ },
90
+ dispose() {
91
+ circuitBreakers.forEach(breaker => breaker.shutdown());
92
+ },
93
+ };
94
+ }
@@ -0,0 +1,5 @@
1
+ export const defaultCircuitBreakerConfiguration = {
2
+ errorThresholdPercentage: 50,
3
+ volumeThreshold: 10,
4
+ resetTimeout: 30000,
5
+ };
@@ -32,6 +32,9 @@ export function createHive(options) {
32
32
  logger });
33
33
  const usage = createUsage(mergedOptions);
34
34
  const schemaReporter = createReporting(mergedOptions);
35
+ const persistedDocuments = options.experimental__persistedDocuments
36
+ ? createPersistedDocuments(Object.assign(Object.assign({}, options.experimental__persistedDocuments), { logger, fetch: options.experimental__persistedDocuments.fetch }))
37
+ : null;
35
38
  function reportSchema({ schema }) {
36
39
  schemaReporter.report({ schema });
37
40
  }
@@ -42,7 +45,7 @@ export function createHive(options) {
42
45
  return usage.collectRequest(...args);
43
46
  }
44
47
  async function dispose() {
45
- await Promise.all([schemaReporter.dispose(), usage.dispose()]);
48
+ await Promise.all([schemaReporter.dispose(), usage.dispose(), persistedDocuments === null || persistedDocuments === void 0 ? void 0 : persistedDocuments.dispose()]);
46
49
  }
47
50
  const isOrganizationAccessToken = !isLegacyAccessToken((_b = options.token) !== null && _b !== void 0 ? _b : '');
48
51
  // enabledOnly when `printTokenInfo` is `true` or `debug` is true and `printTokenInfo` is not `false`
@@ -185,9 +188,7 @@ export function createHive(options) {
185
188
  collectSubscriptionUsage: usage.collectSubscription,
186
189
  createInstrumentedSubscribe,
187
190
  createInstrumentedExecute,
188
- experimental__persistedDocuments: options.experimental__persistedDocuments
189
- ? createPersistedDocuments(Object.assign(Object.assign({}, options.experimental__persistedDocuments), { logger, fetch: options.experimental__persistedDocuments.fetch }))
190
- : null,
191
+ experimental__persistedDocuments: persistedDocuments,
191
192
  };
192
193
  }
193
194
  export const hiveClientSymbol = Symbol('hive-client');
@@ -1,5 +1,10 @@
1
1
  import LRU from 'tiny-lru';
2
+ import CircuitBreaker from '../circuit-breaker/circuit.js';
3
+ import { defaultCircuitBreakerConfiguration } from './circuit-breaker.js';
2
4
  import { http } from './http-client.js';
5
+ function isRequestOk(response) {
6
+ return response.status === 200 || response.status === 404;
7
+ }
3
8
  export function createPersistedDocuments(config) {
4
9
  var _a;
5
10
  const persistedDocumentsCache = LRU((_a = config.cache) !== null && _a !== void 0 ? _a : 10000);
@@ -16,42 +21,77 @@ export function createPersistedDocuments(config) {
16
21
  }
17
22
  /** if there is already a in-flight request for a document, we re-use it. */
18
23
  const fetchCache = new Map();
19
- /** Batch load a persisted documents */
20
- function loadPersistedDocument(documentId) {
21
- const document = persistedDocumentsCache.get(documentId);
22
- if (document) {
23
- return document;
24
- }
25
- const cdnDocumentId = documentId.replaceAll('~', '/');
26
- const url = config.cdn.endpoint + '/apps/' + cdnDocumentId;
27
- let promise = fetchCache.get(url);
28
- if (!promise) {
29
- promise = http
30
- .get(url, {
24
+ const endpoints = Array.isArray(config.cdn.endpoint)
25
+ ? config.cdn.endpoint
26
+ : [config.cdn.endpoint];
27
+ const circuitBreakers = endpoints.map(endpoint => {
28
+ var _a;
29
+ const circuitBreaker = new CircuitBreaker(async function doFetch(cdnDocumentId) {
30
+ const signal = circuitBreaker.getSignal();
31
+ return await http
32
+ .get(endpoint + '/apps/' + cdnDocumentId, {
31
33
  headers: {
32
34
  'X-Hive-CDN-Key': config.cdn.accessToken,
33
35
  },
34
36
  logger: config.logger,
35
- isRequestOk: response => response.status === 200 || response.status === 404,
37
+ isRequestOk,
36
38
  fetchImplementation: config.fetch,
39
+ signal,
40
+ retry: config.retry,
37
41
  })
38
42
  .then(async (response) => {
39
43
  if (response.status !== 200) {
40
44
  return null;
41
45
  }
42
46
  const text = await response.text();
43
- persistedDocumentsCache.set(documentId, text);
44
47
  return text;
45
- })
46
- .finally(() => {
47
- fetchCache.delete(url);
48
48
  });
49
- fetchCache.set(url, promise);
49
+ }, Object.assign(Object.assign({}, ((_a = config.circuitBreaker) !== null && _a !== void 0 ? _a : defaultCircuitBreakerConfiguration)), { timeout: false, autoRenewAbortController: true }));
50
+ return circuitBreaker;
51
+ });
52
+ /** Batch load a persisted documents */
53
+ function loadPersistedDocument(documentId) {
54
+ const document = persistedDocumentsCache.get(documentId);
55
+ if (document) {
56
+ return document;
57
+ }
58
+ let promise = fetchCache.get(documentId);
59
+ if (promise) {
60
+ return promise;
50
61
  }
62
+ promise = Promise.resolve()
63
+ .then(async () => {
64
+ const cdnDocumentId = documentId.replaceAll('~', '/');
65
+ let lastError = null;
66
+ for (const breaker of circuitBreakers) {
67
+ try {
68
+ return await breaker.fire(cdnDocumentId);
69
+ }
70
+ catch (error) {
71
+ config.logger.debug({ error });
72
+ lastError = error;
73
+ }
74
+ }
75
+ if (lastError) {
76
+ config.logger.error({ error: lastError });
77
+ }
78
+ throw new Error('Failed to look up persisted operation.');
79
+ })
80
+ .then(result => {
81
+ persistedDocumentsCache.set(documentId, result);
82
+ return result;
83
+ })
84
+ .finally(() => {
85
+ fetchCache.delete(documentId);
86
+ });
87
+ fetchCache.set(documentId, promise);
51
88
  return promise;
52
89
  }
53
90
  return {
54
91
  allowArbitraryDocuments,
55
92
  resolve: loadPersistedDocument,
93
+ dispose() {
94
+ circuitBreakers.map(breaker => breaker.shutdown());
95
+ },
56
96
  };
57
97
  }
@@ -1,6 +1,9 @@
1
1
  import { version } from '../version.js';
2
2
  import { http } from './http-client.js';
3
3
  import { createHash, joinUrl } from './utils.js';
4
+ /**
5
+ * @deprecated Please use {createCDNArtifactFetcher} instead.
6
+ */
4
7
  export function createSupergraphSDLFetcher(options) {
5
8
  let cacheETag = null;
6
9
  let cached = null;
package/esm/index.js CHANGED
@@ -6,3 +6,4 @@ export { atLeastOnceSampler } from './client/samplers.js';
6
6
  export { isHiveClient, isAsyncIterable, createHash, joinUrl } from './client/utils.js';
7
7
  export { http, URL } from './client/http-client.js';
8
8
  export { createSupergraphSDLFetcher } from './client/supergraph.js';
9
+ export { createCDNArtifactFetcher, } from './client/cdn-artifact-fetcher.js';
package/esm/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '0.16.0';
1
+ export const version = '0.17.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphql-hive/core",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
6
  "graphql": "^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
@@ -1,22 +1,6 @@
1
+ import { CircuitBreakerConfiguration } from './circuit-breaker.cjs';
1
2
  import type { LegacyLogger } from './types.cjs';
2
3
  type ReadOnlyResponse = Pick<Response, 'status' | 'text' | 'json' | 'statusText'>;
3
- export type AgentCircuitBreakerConfiguration = {
4
- /**
5
- * Percentage after what the circuit breaker should kick in.
6
- * Default: 50
7
- */
8
- errorThresholdPercentage: number;
9
- /**
10
- * Count of requests before starting evaluating.
11
- * Default: 5
12
- */
13
- volumeThreshold: number;
14
- /**
15
- * After what time the circuit breaker is attempting to retry sending requests in milliseconds
16
- * Default: 30_000
17
- */
18
- resetTimeout: number;
19
- };
20
4
  export interface AgentOptions {
21
5
  enabled?: boolean;
22
6
  name?: string;
@@ -63,7 +47,7 @@ export interface AgentOptions {
63
47
  * false -> Disable
64
48
  * object -> use custom configuration see {AgentCircuitBreakerConfiguration}
65
49
  */
66
- circuitBreaker?: boolean | AgentCircuitBreakerConfiguration;
50
+ circuitBreaker?: boolean | CircuitBreakerConfiguration;
67
51
  /**
68
52
  * WHATWG Compatible fetch implementation
69
53
  * used by the agent to send reports
@@ -1,22 +1,6 @@
1
+ import { CircuitBreakerConfiguration } from './circuit-breaker.js';
1
2
  import type { LegacyLogger } from './types.js';
2
3
  type ReadOnlyResponse = Pick<Response, 'status' | 'text' | 'json' | 'statusText'>;
3
- export type AgentCircuitBreakerConfiguration = {
4
- /**
5
- * Percentage after what the circuit breaker should kick in.
6
- * Default: 50
7
- */
8
- errorThresholdPercentage: number;
9
- /**
10
- * Count of requests before starting evaluating.
11
- * Default: 5
12
- */
13
- volumeThreshold: number;
14
- /**
15
- * After what time the circuit breaker is attempting to retry sending requests in milliseconds
16
- * Default: 30_000
17
- */
18
- resetTimeout: number;
19
- };
20
4
  export interface AgentOptions {
21
5
  enabled?: boolean;
22
6
  name?: string;
@@ -63,7 +47,7 @@ export interface AgentOptions {
63
47
  * false -> Disable
64
48
  * object -> use custom configuration see {AgentCircuitBreakerConfiguration}
65
49
  */
66
- circuitBreaker?: boolean | AgentCircuitBreakerConfiguration;
50
+ circuitBreaker?: boolean | CircuitBreakerConfiguration;
67
51
  /**
68
52
  * WHATWG Compatible fetch implementation
69
53
  * used by the agent to send reports
@@ -0,0 +1,63 @@
1
+ import { Logger } from '@graphql-hive/logger';
2
+ import { CircuitBreakerConfiguration } from './circuit-breaker.cjs';
3
+ import { HttpCallConfig } from './http-client.cjs';
4
+ type CreateCDNArtifactFetcherArgs = {
5
+ /**
6
+ * The endpoint that should be fetched.
7
+ *
8
+ * It is possible to provide an endpoint list. The first endpoint will be treated as the primary source.
9
+ * The secondary endpoint will be used in case the first endpoint fails to respond.
10
+ *
11
+ * Example:
12
+ *
13
+ * ```
14
+ * [
15
+ * "https://cdn.graphql-hive.com/artifacts/v1/9fb37bc4-e520-4019-843a-0c8698c25688/supergraph",
16
+ * "https://cdn-mirror.graphql-hive.com/artifacts/v1/9fb37bc4-e520-4019-843a-0c8698c25688/supergraph"
17
+ * ]
18
+ * ```
19
+ */
20
+ endpoint: string | [string, string];
21
+ /**
22
+ * The access key that is used for authenticating on the endpoints (via the `X-Hive-CDN-Key` header).
23
+ */
24
+ accessKey: string;
25
+ logger?: Logger;
26
+ circuitBreaker?: CircuitBreakerConfiguration;
27
+ /**
28
+ * Custom fetch implementation used for calling the endpoint.
29
+ */
30
+ fetch?: typeof fetch;
31
+ /** Amount of retries per endpoint lookup attempt */
32
+ retry?: HttpCallConfig['retry'];
33
+ /** Timeout per retry for endpoint lookup */
34
+ timeout?: HttpCallConfig['timeout'];
35
+ /**
36
+ * Optional client meta configuration.
37
+ **/
38
+ client?: {
39
+ name: string;
40
+ version: string;
41
+ };
42
+ };
43
+ type CDNFetchResult = {
44
+ /** Text contents of the artifact */
45
+ contents: string;
46
+ /** SHA-256 Hash */
47
+ hash: string;
48
+ /** Schema Version ID as on Hive Console (optional) */
49
+ schemaVersionId: null | string;
50
+ };
51
+ export type CDNArtifactFetcher = {
52
+ /** Call the CDN and retrieve the lastest artifact version. */
53
+ fetch(): Promise<CDNFetchResult>;
54
+ /** Dispose the fetcher and cleanup existing timers (e.g. used for circuit breaker) */
55
+ dispose(): void;
56
+ };
57
+ /**
58
+ * Create a handler for fetching a CDN artifact with built-in cache and circuit breaker.
59
+ * It is intended for polling supergraph, schema sdl or services.
60
+ */
61
+ export declare function createCDNArtifactFetcher(args: CreateCDNArtifactFetcherArgs): CDNArtifactFetcher;
62
+ export {};
63
+ //# sourceMappingURL=cdn-artifact-fetcher.d.ts.map
@@ -0,0 +1,63 @@
1
+ import { Logger } from '@graphql-hive/logger';
2
+ import { CircuitBreakerConfiguration } from './circuit-breaker.js';
3
+ import { HttpCallConfig } from './http-client.js';
4
+ type CreateCDNArtifactFetcherArgs = {
5
+ /**
6
+ * The endpoint that should be fetched.
7
+ *
8
+ * It is possible to provide an endpoint list. The first endpoint will be treated as the primary source.
9
+ * The secondary endpoint will be used in case the first endpoint fails to respond.
10
+ *
11
+ * Example:
12
+ *
13
+ * ```
14
+ * [
15
+ * "https://cdn.graphql-hive.com/artifacts/v1/9fb37bc4-e520-4019-843a-0c8698c25688/supergraph",
16
+ * "https://cdn-mirror.graphql-hive.com/artifacts/v1/9fb37bc4-e520-4019-843a-0c8698c25688/supergraph"
17
+ * ]
18
+ * ```
19
+ */
20
+ endpoint: string | [string, string];
21
+ /**
22
+ * The access key that is used for authenticating on the endpoints (via the `X-Hive-CDN-Key` header).
23
+ */
24
+ accessKey: string;
25
+ logger?: Logger;
26
+ circuitBreaker?: CircuitBreakerConfiguration;
27
+ /**
28
+ * Custom fetch implementation used for calling the endpoint.
29
+ */
30
+ fetch?: typeof fetch;
31
+ /** Amount of retries per endpoint lookup attempt */
32
+ retry?: HttpCallConfig['retry'];
33
+ /** Timeout per retry for endpoint lookup */
34
+ timeout?: HttpCallConfig['timeout'];
35
+ /**
36
+ * Optional client meta configuration.
37
+ **/
38
+ client?: {
39
+ name: string;
40
+ version: string;
41
+ };
42
+ };
43
+ type CDNFetchResult = {
44
+ /** Text contents of the artifact */
45
+ contents: string;
46
+ /** SHA-256 Hash */
47
+ hash: string;
48
+ /** Schema Version ID as on Hive Console (optional) */
49
+ schemaVersionId: null | string;
50
+ };
51
+ export type CDNArtifactFetcher = {
52
+ /** Call the CDN and retrieve the lastest artifact version. */
53
+ fetch(): Promise<CDNFetchResult>;
54
+ /** Dispose the fetcher and cleanup existing timers (e.g. used for circuit breaker) */
55
+ dispose(): void;
56
+ };
57
+ /**
58
+ * Create a handler for fetching a CDN artifact with built-in cache and circuit breaker.
59
+ * It is intended for polling supergraph, schema sdl or services.
60
+ */
61
+ export declare function createCDNArtifactFetcher(args: CreateCDNArtifactFetcherArgs): CDNArtifactFetcher;
62
+ export {};
63
+ //# sourceMappingURL=cdn-artifact-fetcher.d.ts.map
@@ -0,0 +1,19 @@
1
+ export type CircuitBreakerConfiguration = {
2
+ /**
3
+ * Percentage after what the circuit breaker should kick in.
4
+ * Default: 50
5
+ */
6
+ errorThresholdPercentage: number;
7
+ /**
8
+ * Count of requests before starting evaluating.
9
+ * Default: 5
10
+ */
11
+ volumeThreshold: number;
12
+ /**
13
+ * After what time the circuit breaker is attempting to retry sending requests in milliseconds
14
+ * Default: 30_000
15
+ */
16
+ resetTimeout: number;
17
+ };
18
+ export declare const defaultCircuitBreakerConfiguration: CircuitBreakerConfiguration;
19
+ //# sourceMappingURL=circuit-breaker.d.ts.map
@@ -0,0 +1,19 @@
1
+ export type CircuitBreakerConfiguration = {
2
+ /**
3
+ * Percentage after what the circuit breaker should kick in.
4
+ * Default: 50
5
+ */
6
+ errorThresholdPercentage: number;
7
+ /**
8
+ * Count of requests before starting evaluating.
9
+ * Default: 5
10
+ */
11
+ volumeThreshold: number;
12
+ /**
13
+ * After what time the circuit breaker is attempting to retry sending requests in milliseconds
14
+ * Default: 30_000
15
+ */
16
+ resetTimeout: number;
17
+ };
18
+ export declare const defaultCircuitBreakerConfiguration: CircuitBreakerConfiguration;
19
+ //# sourceMappingURL=circuit-breaker.d.ts.map
@@ -1,7 +1,7 @@
1
1
  import asyncRetry from 'async-retry';
2
2
  import { fetch, URL } from '@whatwg-node/fetch';
3
3
  import type { LegacyLogger } from './types';
4
- interface SharedConfig {
4
+ export interface HttpCallConfig {
5
5
  headers: Record<string, string>;
6
6
  /**
7
7
  * timeout in milliseconds (for each single fetch call)
@@ -27,9 +27,9 @@ interface SharedConfig {
27
27
  * Return a string that contains the reason on why the request should be retried.
28
28
  */
29
29
  type ResponseAssertFunction = (response: Response) => boolean;
30
- type RetryOptions = Parameters<typeof asyncRetry>[1];
31
- declare function get(endpoint: string, config: SharedConfig): Promise<Response>;
32
- declare function post(endpoint: string, data: string | Buffer, config: SharedConfig): Promise<Response>;
30
+ export type RetryOptions = Parameters<typeof asyncRetry>[1];
31
+ declare function get(endpoint: string, config: HttpCallConfig): Promise<Response>;
32
+ declare function post(endpoint: string, data: string | Buffer, config: HttpCallConfig): Promise<Response>;
33
33
  export declare const http: {
34
34
  get: typeof get;
35
35
  post: typeof post;
@@ -1,7 +1,7 @@
1
1
  import asyncRetry from 'async-retry';
2
2
  import { fetch, URL } from '@whatwg-node/fetch';
3
3
  import type { LegacyLogger } from './types';
4
- interface SharedConfig {
4
+ export interface HttpCallConfig {
5
5
  headers: Record<string, string>;
6
6
  /**
7
7
  * timeout in milliseconds (for each single fetch call)
@@ -27,9 +27,9 @@ interface SharedConfig {
27
27
  * Return a string that contains the reason on why the request should be retried.
28
28
  */
29
29
  type ResponseAssertFunction = (response: Response) => boolean;
30
- type RetryOptions = Parameters<typeof asyncRetry>[1];
31
- declare function get(endpoint: string, config: SharedConfig): Promise<Response>;
32
- declare function post(endpoint: string, data: string | Buffer, config: SharedConfig): Promise<Response>;
30
+ export type RetryOptions = Parameters<typeof asyncRetry>[1];
31
+ declare function get(endpoint: string, config: HttpCallConfig): Promise<Response>;
32
+ declare function post(endpoint: string, data: string | Buffer, config: HttpCallConfig): Promise<Response>;
33
33
  export declare const http: {
34
34
  get: typeof get;
35
35
  post: typeof post;
@@ -1,17 +1,22 @@
1
1
  import type { PromiseOrValue } from 'graphql/jsutils/PromiseOrValue.cjs';
2
2
  import { Logger } from '@graphql-hive/logger';
3
+ import { HttpCallConfig } from './http-client.cjs';
3
4
  import type { PersistedDocumentsConfiguration } from './types';
4
5
  type HeadersObject = {
5
6
  get(name: string): string | null;
6
7
  };
7
- export declare function createPersistedDocuments(config: PersistedDocumentsConfiguration & {
8
- logger: Logger;
9
- fetch?: typeof fetch;
10
- }): null | {
8
+ type PersistedDocuments = {
11
9
  resolve(documentId: string): PromiseOrValue<string | null>;
12
10
  allowArbitraryDocuments(context: {
13
11
  headers?: HeadersObject;
14
12
  }): PromiseOrValue<boolean>;
13
+ dispose: () => void;
15
14
  };
15
+ export declare function createPersistedDocuments(config: PersistedDocumentsConfiguration & {
16
+ logger: Logger;
17
+ fetch?: typeof fetch;
18
+ retry?: HttpCallConfig['retry'];
19
+ timeout?: HttpCallConfig['retry'];
20
+ }): PersistedDocuments;
16
21
  export {};
17
22
  //# sourceMappingURL=persisted-documents.d.ts.map
@@ -1,17 +1,22 @@
1
1
  import type { PromiseOrValue } from 'graphql/jsutils/PromiseOrValue.js';
2
2
  import { Logger } from '@graphql-hive/logger';
3
+ import { HttpCallConfig } from './http-client.js';
3
4
  import type { PersistedDocumentsConfiguration } from './types';
4
5
  type HeadersObject = {
5
6
  get(name: string): string | null;
6
7
  };
7
- export declare function createPersistedDocuments(config: PersistedDocumentsConfiguration & {
8
- logger: Logger;
9
- fetch?: typeof fetch;
10
- }): null | {
8
+ type PersistedDocuments = {
11
9
  resolve(documentId: string): PromiseOrValue<string | null>;
12
10
  allowArbitraryDocuments(context: {
13
11
  headers?: HeadersObject;
14
12
  }): PromiseOrValue<boolean>;
13
+ dispose: () => void;
15
14
  };
15
+ export declare function createPersistedDocuments(config: PersistedDocumentsConfiguration & {
16
+ logger: Logger;
17
+ fetch?: typeof fetch;
18
+ retry?: HttpCallConfig['retry'];
19
+ timeout?: HttpCallConfig['retry'];
20
+ }): PersistedDocuments;
16
21
  export {};
17
22
  //# sourceMappingURL=persisted-documents.d.ts.map
@@ -1,5 +1,8 @@
1
1
  import { Logger } from '@graphql-hive/logger';
2
2
  import type { LegacyLogger } from './types.cjs';
3
+ /**
4
+ * @deprecated Please use {createCDNArtifactFetcher} instead of createSupergraphSDLFetcher.
5
+ */
3
6
  export interface SupergraphSDLFetcherOptions {
4
7
  endpoint: string;
5
8
  key: string;
@@ -8,6 +11,9 @@ export interface SupergraphSDLFetcherOptions {
8
11
  name?: string;
9
12
  version?: string;
10
13
  }
14
+ /**
15
+ * @deprecated Please use {createCDNArtifactFetcher} instead.
16
+ */
11
17
  export declare function createSupergraphSDLFetcher(options: SupergraphSDLFetcherOptions): () => Promise<{
12
18
  id: string;
13
19
  supergraphSdl: string;
@@ -1,5 +1,8 @@
1
1
  import { Logger } from '@graphql-hive/logger';
2
2
  import type { LegacyLogger } from './types.js';
3
+ /**
4
+ * @deprecated Please use {createCDNArtifactFetcher} instead of createSupergraphSDLFetcher.
5
+ */
3
6
  export interface SupergraphSDLFetcherOptions {
4
7
  endpoint: string;
5
8
  key: string;
@@ -8,6 +11,9 @@ export interface SupergraphSDLFetcherOptions {
8
11
  name?: string;
9
12
  version?: string;
10
13
  }
14
+ /**
15
+ * @deprecated Please use {createCDNArtifactFetcher} instead.
16
+ */
11
17
  export declare function createSupergraphSDLFetcher(options: SupergraphSDLFetcherOptions): () => Promise<{
12
18
  id: string;
13
19
  supergraphSdl: string;
@@ -2,6 +2,7 @@ import type { ExecutionArgs } from 'graphql';
2
2
  import type { PromiseOrValue } from 'graphql/jsutils/PromiseOrValue.cjs';
3
3
  import { LogLevel as HiveLoggerLevel, Logger } from '@graphql-hive/logger';
4
4
  import type { AgentOptions } from './agent.cjs';
5
+ import { CircuitBreakerConfiguration } from './circuit-breaker.cjs';
5
6
  import type { autoDisposeSymbol, hiveClientSymbol } from './client.cjs';
6
7
  import type { SchemaReporter } from './reporting.cjs';
7
8
  type HeadersObject = {
@@ -277,10 +278,20 @@ export type PersistedDocumentsConfiguration = {
277
278
  **/
278
279
  cdn: {
279
280
  /**
280
- * CDN endpoint
281
- * @example https://cdn.graphql-hive.com/artifacts/v1/5d80a1c2-2532-419c-8bb5-75bb04ea1112
281
+ * CDN endpoint(s) for looking up persisted documents.
282
+ *
283
+ * It is possible to provide an endpoint list. The first endpoint will be treated as the primary source.
284
+ * The secondary endpoint will be used in case the first endpoint fails to respond.
285
+ *
286
+ * @example
287
+ * ```
288
+ * [
289
+ * "https://cdn.graphql-hive.com/artifacts/v1/9fb37bc4-e520-4019-843a-0c8698c25688",
290
+ * "https://cdn-mirror.graphql-hive.com/artifacts/v1/9fb37bc4-e520-4019-843a-0c8698c25688"
291
+ * ]
292
+ * ```
282
293
  */
283
- endpoint: string;
294
+ endpoint: string | [string, string];
284
295
  /**
285
296
  * CDN access token
286
297
  * @example hv2ZjUxNGUzN2MtNjVhNS0=
@@ -303,6 +314,8 @@ export type PersistedDocumentsConfiguration = {
303
314
  * used for doing HTTP requests.
304
315
  */
305
316
  fetch?: typeof fetch;
317
+ /** Configuration for the circuit breaker. */
318
+ circuitBreaker?: CircuitBreakerConfiguration;
306
319
  };
307
320
  export type AllowArbitraryDocumentsFunction = (context: {
308
321
  /** an object for accessing the request headers. */
@@ -2,6 +2,7 @@ import type { ExecutionArgs } from 'graphql';
2
2
  import type { PromiseOrValue } from 'graphql/jsutils/PromiseOrValue.js';
3
3
  import { LogLevel as HiveLoggerLevel, Logger } from '@graphql-hive/logger';
4
4
  import type { AgentOptions } from './agent.js';
5
+ import { CircuitBreakerConfiguration } from './circuit-breaker.js';
5
6
  import type { autoDisposeSymbol, hiveClientSymbol } from './client.js';
6
7
  import type { SchemaReporter } from './reporting.js';
7
8
  type HeadersObject = {
@@ -277,10 +278,20 @@ export type PersistedDocumentsConfiguration = {
277
278
  **/
278
279
  cdn: {
279
280
  /**
280
- * CDN endpoint
281
- * @example https://cdn.graphql-hive.com/artifacts/v1/5d80a1c2-2532-419c-8bb5-75bb04ea1112
281
+ * CDN endpoint(s) for looking up persisted documents.
282
+ *
283
+ * It is possible to provide an endpoint list. The first endpoint will be treated as the primary source.
284
+ * The secondary endpoint will be used in case the first endpoint fails to respond.
285
+ *
286
+ * @example
287
+ * ```
288
+ * [
289
+ * "https://cdn.graphql-hive.com/artifacts/v1/9fb37bc4-e520-4019-843a-0c8698c25688",
290
+ * "https://cdn-mirror.graphql-hive.com/artifacts/v1/9fb37bc4-e520-4019-843a-0c8698c25688"
291
+ * ]
292
+ * ```
282
293
  */
283
- endpoint: string;
294
+ endpoint: string | [string, string];
284
295
  /**
285
296
  * CDN access token
286
297
  * @example hv2ZjUxNGUzN2MtNjVhNS0=
@@ -303,6 +314,8 @@ export type PersistedDocumentsConfiguration = {
303
314
  * used for doing HTTP requests.
304
315
  */
305
316
  fetch?: typeof fetch;
317
+ /** Configuration for the circuit breaker. */
318
+ circuitBreaker?: CircuitBreakerConfiguration;
306
319
  };
307
320
  export type AllowArbitraryDocumentsFunction = (context: {
308
321
  /** an object for accessing the request headers. */
@@ -8,4 +8,6 @@ export { isHiveClient, isAsyncIterable, createHash, joinUrl } from './client/uti
8
8
  export { http, URL } from './client/http-client.cjs';
9
9
  export { createSupergraphSDLFetcher } from './client/supergraph.cjs';
10
10
  export type { SupergraphSDLFetcherOptions } from './client/supergraph.cjs';
11
+ export { createCDNArtifactFetcher, type CDNArtifactFetcher, } from './client/cdn-artifact-fetcher.cjs';
12
+ export type { CircuitBreakerConfiguration } from './client/circuit-breaker.cjs';
11
13
  //# sourceMappingURL=index.d.ts.map
@@ -8,4 +8,6 @@ export { isHiveClient, isAsyncIterable, createHash, joinUrl } from './client/uti
8
8
  export { http, URL } from './client/http-client.js';
9
9
  export { createSupergraphSDLFetcher } from './client/supergraph.js';
10
10
  export type { SupergraphSDLFetcherOptions } from './client/supergraph.js';
11
+ export { createCDNArtifactFetcher, type CDNArtifactFetcher, } from './client/cdn-artifact-fetcher.js';
12
+ export type { CircuitBreakerConfiguration } from './client/circuit-breaker.js';
11
13
  //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1,2 @@
1
- export declare const version = "0.16.0";
1
+ export declare const version = "0.17.0";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,2 +1,2 @@
1
- export declare const version = "0.16.0";
1
+ export declare const version = "0.17.0";
2
2
  //# sourceMappingURL=version.d.ts.map