@graphql-hive/gateway-plugin-console-sdk
Version:
Hive Console + Hive Gateway
231 lines (230 loc) • 13.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createSupergraphSDLFetcher = exports.createServicesFetcher = exports.createSchemaFetcher = exports.atLeastOnceSampler = void 0;
exports.createHive = createHive;
exports.useHive = useHive;
const tslib_1 = require("tslib");
const graphql_1 = require("graphql");
const tiny_lru_1 = require("tiny-lru");
const core_1 = require("@graphql-hive/core");
const is_entity_request_js_1 = require("./is-entity-request.js");
const version_js_1 = require("./version.js");
var core_2 = require("@graphql-hive/core");
Object.defineProperty(exports, "atLeastOnceSampler", { enumerable: true, get: function () { return core_2.atLeastOnceSampler; } });
Object.defineProperty(exports, "createSchemaFetcher", { enumerable: true, get: function () { return core_2.createSchemaFetcher; } });
Object.defineProperty(exports, "createServicesFetcher", { enumerable: true, get: function () { return core_2.createServicesFetcher; } });
Object.defineProperty(exports, "createSupergraphSDLFetcher", { enumerable: true, get: function () { return core_2.createSupergraphSDLFetcher; } });
function createHive(clientOrOptions) {
return (0, core_1.createHive)(Object.assign(Object.assign({}, clientOrOptions), { agent: Object.assign({ name: 'hive-client-gateway-sdk', version: version_js_1.version }, clientOrOptions.agent) }));
}
function useHive(clientOrOptions) {
var _a, _b;
const hive = (0, core_1.isHiveClient)(clientOrOptions)
? clientOrOptions
: createHive(Object.assign(Object.assign({}, clientOrOptions), { agent: Object.assign({ name: 'hive-client-gateway-sdk' }, clientOrOptions.agent) }));
void hive.info();
const contextualCache = new WeakMap();
const statusMap = new WeakMap();
const fieldLevelMetricsEnabled = (0, core_1.isHiveClient)(clientOrOptions)
? false
: (typeof clientOrOptions.usage === 'object' &&
((_a = clientOrOptions.usage) === null || _a === void 0 ? void 0 : _a.fieldLevelMetricsEnabled)) ||
false;
const operationCache = fieldLevelMetricsEnabled
? (0, tiny_lru_1.lru)((0, core_1.isHiveClient)(clientOrOptions) ? 10000 : ((_b = clientOrOptions.cache) !== null && _b !== void 0 ? _b : 10000))
: null;
let latestSchema = null;
return {
onFetch({ executionRequest }) {
if (!executionRequest) {
return;
}
return function onFetchDone({ response }) {
statusMap.set(executionRequest, response.status);
};
},
onSubgraphExecute({ executionRequest, subgraphName, subgraph: subgraphSchema }) {
var _a, _b, _c;
if (!fieldLevelMetricsEnabled || !executionRequest.context) {
return;
}
const cache = contextualCache.get(executionRequest.context);
if (!cache) {
return;
}
const finishSubRequest = cache.collector.subrequest({
subgraph: subgraphName,
type: (0, is_entity_request_js_1.isEntityRequest)(executionRequest.document) ? 'ENTITY' : 'ROOT',
paths: ((_a = executionRequest.info) === null || _a === void 0 ? void 0 : _a.path)
? [(0, graphql_1.responsePathAsArray)(executionRequest.info.path).join('.')]
: (_c = (0, core_1.getDefinedRootType)(subgraphSchema, (_b = executionRequest.operationType) !== null && _b !== void 0 ? _b : graphql_1.OperationTypeNode.QUERY)) === null || _c === void 0 ? void 0 : _c.name,
});
return function onSubgraphExecuteDone({ result }) {
var _a;
if (!(0, core_1.isAsyncIterable)(result)) {
finishSubRequest({
status: (_a = statusMap.get(executionRequest)) !== null && _a !== void 0 ? _a : 200,
subgraphSchema,
result,
// The Rust query planner generates and caches this document up front.
// This depends on the operation and variables.
// So if we need to add typenames to the request, it needs to happen
// here also. E.g. `addHiveTypenames(executionRequest.document, subgraphSchema)`.
// But for the js gateway execution, this is redundant and an unnecessary expense.
document: executionRequest.document,
});
}
};
},
onSchemaChange({ schema }) {
hive.reportSchema({ schema });
latestSchema = schema;
operationCache === null || operationCache === void 0 ? void 0 : operationCache.clear();
},
onParams(context) {
if ((context.params.query || 'documentId' in context.params) && latestSchema) {
contextualCache.set(context.context, {
collector: hive.collectUsage(),
paramsArgs: context.params,
});
}
},
onExecute({ args, context, setExecuteFn, executeFn }) {
var _a;
const ctx = args.contextValue || context;
const cache = contextualCache.get(ctx);
if (!cache)
return;
cache.executionArgs = args;
if (fieldLevelMetricsEnabled && operationCache && latestSchema) {
// Validation must run against the client document. Add the metadata fields only
// to the document passed to execution and cache that transformed document.
const query = (_a = args.document.loc) === null || _a === void 0 ? void 0 : _a.source.body;
const cachedDocument = query ? operationCache.get(query) : undefined;
const modifiedDocument = cachedDocument === true
? args.document
: cachedDocument || (0, core_1.addHiveTypenames)(args.document, latestSchema);
if (query && cachedDocument === undefined) {
operationCache.set(query, args.document === modifiedDocument || modifiedDocument);
}
if (args.document !== modifiedDocument) {
setExecuteFn(executionArgs => executeFn(Object.assign(Object.assign({}, executionArgs), { document: modifiedDocument })));
}
cache.document = modifiedDocument;
}
return {
onExecuteDone({ result, args }) {
var _a, _b, _c;
if (!(0, core_1.isAsyncIterable)(result)) {
if (result.errors) {
const gatewayErrors = (_a = result.errors) === null || _a === void 0 ? void 0 : _a.filter(e => { var _a, _b;
/**
* DOWNSTREAM_SERVICE_ERROR is set by the executor to wrap subgraph errors. A serviceName is also
* used to indicate the source of the error. If either of these are found, then it's safe to assume
* the error was not thrown in the gateway.
*/
return ((_a = e.extensions) === null || _a === void 0 ? void 0 : _a.code) !== 'DOWNSTREAM_SERVICE_ERROR' && !((_b = e.extensions) === null || _b === void 0 ? void 0 : _b.serviceName); });
if (cache && (gatewayErrors === null || gatewayErrors === void 0 ? void 0 : gatewayErrors.length) > 0) {
cache.collector.trackGatewayErrors({ errors: gatewayErrors });
}
}
args.contextValue.waitUntil(cache.collector.finish(Object.assign(Object.assign({}, args), { document: (_c = (_b = cache.document) !== null && _b !== void 0 ? _b : ctx.document) !== null && _c !== void 0 ? _c : args.document }), result, cache.experimental__documentId));
return;
}
const errors = [];
return {
onNext({ result: iterResult }) {
if (iterResult.errors) {
errors.push(...iterResult.errors);
}
},
onEnd() {
var _a;
ctx.waitUntil(cache.collector.finish(Object.assign(Object.assign({}, args), { document: (_a = cache.document) !== null && _a !== void 0 ? _a : args.document }),
// how to pass in data here?
errors.length ? { errors } : {}, cache.experimental__documentId));
},
};
},
};
},
onSubscribe({ args, context }) {
const ctx = args.contextValue || context;
const record = contextualCache.get(ctx);
return {
onSubscribeResult() {
var _a, _b, _c;
const experimental__persistedDocumentHash = record === null || record === void 0 ? void 0 : record.experimental__documentId;
hive.collectSubscriptionUsage({
args: Object.assign(Object.assign({}, args), { document: (_c = (_a = record === null || record === void 0 ? void 0 : record.document) !== null && _a !== void 0 ? _a : (_b = record === null || record === void 0 ? void 0 : record.executionArgs) === null || _b === void 0 ? void 0 : _b.document) !== null && _c !== void 0 ? _c : args.document }),
experimental__persistedDocumentHash,
});
},
};
},
async onResultProcess({ serverContext, result, setResult }) {
const record = contextualCache.get(serverContext);
if (!record || Array.isArray(result) || (0, core_1.isAsyncIterable)(result) || record.executionArgs) {
if (fieldLevelMetricsEnabled) {
if ((0, core_1.isAsyncIterable)(result)) {
const modifyStream = function () {
return tslib_1.__asyncGenerator(this, arguments, function* () {
var _a, e_1, _b, _c;
try {
for (var _d = true, result_1 = tslib_1.__asyncValues(result), result_1_1; result_1_1 = yield tslib_1.__await(result_1.next()), _a = result_1_1.done, !_a; _d = true) {
_c = result_1_1.value;
_d = false;
const r = _c;
(0, core_1.hideInjectedTypenames)(r.data);
yield yield tslib_1.__await(r);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (!_d && !_a && (_b = result_1.return)) yield tslib_1.__await(_b.call(result_1));
}
finally { if (e_1) throw e_1.error; }
}
});
};
setResult(modifyStream());
}
else if (Array.isArray(result)) {
for (let r of result) {
(0, core_1.hideInjectedTypenames)(r.data);
}
}
else {
(0, core_1.hideInjectedTypenames)(result.data);
}
}
return;
}
if (record.paramsArgs.query && latestSchema) {
try {
let doc = record.document;
if (!doc) {
doc = (0, graphql_1.parse)(record.paramsArgs.query);
}
serverContext.waitUntil(record.collector.finish({
document: doc,
schema: latestSchema,
variableValues: record.paramsArgs.variables,
operationName: record.paramsArgs.operationName,
contextValue: serverContext,
}, result, record.experimental__documentId));
}
catch (err) {
// Fail silently if parse fails inside cached block handling
}
}
if (fieldLevelMetricsEnabled) {
(0, core_1.hideInjectedTypenames)(result.data);
}
},
onDispose() {
return hive.dispose();
},
};
}