@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.
- package/cjs/client/agent.js +2 -6
- package/cjs/client/cdn-artifact-fetcher.js +98 -0
- package/cjs/client/circuit-breaker.js +8 -0
- package/cjs/client/client.js +5 -4
- package/cjs/client/persisted-documents.js +58 -18
- package/cjs/client/supergraph.js +3 -0
- package/cjs/index.js +3 -1
- package/cjs/version.js +1 -1
- package/esm/client/agent.js +1 -5
- package/esm/client/cdn-artifact-fetcher.js +94 -0
- package/esm/client/circuit-breaker.js +5 -0
- package/esm/client/client.js +5 -4
- package/esm/client/persisted-documents.js +58 -18
- package/esm/client/supergraph.js +3 -0
- package/esm/index.js +1 -0
- package/esm/version.js +1 -1
- package/package.json +1 -1
- package/typings/client/agent.d.cts +2 -18
- package/typings/client/agent.d.ts +2 -18
- package/typings/client/cdn-artifact-fetcher.d.cts +63 -0
- package/typings/client/cdn-artifact-fetcher.d.ts +63 -0
- package/typings/client/circuit-breaker.d.cts +19 -0
- package/typings/client/circuit-breaker.d.ts +19 -0
- package/typings/client/http-client.d.cts +4 -4
- package/typings/client/http-client.d.ts +4 -4
- package/typings/client/persisted-documents.d.cts +9 -4
- package/typings/client/persisted-documents.d.ts +9 -4
- package/typings/client/supergraph.d.cts +6 -0
- package/typings/client/supergraph.d.ts +6 -0
- package/typings/client/types.d.cts +16 -3
- package/typings/client/types.d.ts +16 -3
- package/typings/index.d.cts +2 -0
- package/typings/index.d.ts +2 -0
- package/typings/version.d.cts +1 -1
- package/typings/version.d.ts +1 -1
package/cjs/client/agent.js
CHANGED
|
@@ -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
|
+
}
|
package/cjs/client/client.js
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
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
|
-
|
|
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
|
}
|
package/cjs/client/supergraph.js
CHANGED
|
@@ -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
package/esm/client/agent.js
CHANGED
|
@@ -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
|
+
}
|
package/esm/client/client.js
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
|
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
|
-
|
|
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
|
}
|
package/esm/client/supergraph.js
CHANGED
|
@@ -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.
|
|
1
|
+
export const version = '0.17.0';
|
package/package.json
CHANGED
|
@@ -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 |
|
|
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 |
|
|
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
|
|
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:
|
|
32
|
-
declare function post(endpoint: string, data: string | Buffer, config:
|
|
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
|
|
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:
|
|
32
|
-
declare function post(endpoint: string, data: string | Buffer, config:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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. */
|
package/typings/index.d.cts
CHANGED
|
@@ -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
|
package/typings/index.d.ts
CHANGED
|
@@ -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
|
package/typings/version.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "0.
|
|
1
|
+
export declare const version = "0.17.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/typings/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "0.
|
|
1
|
+
export declare const version = "0.17.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|