@graphql-hive/nestjs
Version:
1,010 lines (975 loc) • 29.6 kB
JavaScript
import { createLoggerFromLogging, PubSub, getCacheInstanceFromConfig, getBuiltinPluginsFromConfig, createGatewayRuntime, getGraphQLWSOptions } from '@graphql-hive/gateway';
import { asArray } from '@graphql-tools/utils';
import { Injectable, Logger as Logger$1 } from '@nestjs/common';
import { AbstractGraphQLDriver, GqlSubscriptionService } from '@nestjs/graphql';
import { handleMaybePromise } from '@whatwg-node/promise-helpers';
import { lexicographicSortSchema } from 'graphql';
const DisposableSymbols = {
get asyncDispose() {
return Symbol.asyncDispose || Symbol.for('asyncDispose');
},
};
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var fastSafeStringify = stringify;
stringify.default = stringify;
stringify.stable = deterministicStringify;
stringify.stableStringify = deterministicStringify;
var LIMIT_REPLACE_NODE = '[...]';
var CIRCULAR_REPLACE_NODE = '[Circular]';
var arr = [];
var replacerStack = [];
function defaultOptions () {
return {
depthLimit: Number.MAX_SAFE_INTEGER,
edgesLimit: Number.MAX_SAFE_INTEGER
}
}
// Regular stringify
function stringify (obj, replacer, spacer, options) {
if (typeof options === 'undefined') {
options = defaultOptions();
}
decirc(obj, '', 0, [], undefined, 0, options);
var res;
try {
if (replacerStack.length === 0) {
res = JSON.stringify(obj, replacer, spacer);
} else {
res = JSON.stringify(obj, replaceGetterValues(replacer), spacer);
}
} catch (_) {
return JSON.stringify('[unable to serialize, circular reference is too complex to analyze]')
} finally {
while (arr.length !== 0) {
var part = arr.pop();
if (part.length === 4) {
Object.defineProperty(part[0], part[1], part[3]);
} else {
part[0][part[1]] = part[2];
}
}
}
return res
}
function setReplace (replace, val, k, parent) {
var propertyDescriptor = Object.getOwnPropertyDescriptor(parent, k);
if (propertyDescriptor.get !== undefined) {
if (propertyDescriptor.configurable) {
Object.defineProperty(parent, k, { value: replace });
arr.push([parent, k, val, propertyDescriptor]);
} else {
replacerStack.push([val, k, replace]);
}
} else {
parent[k] = replace;
arr.push([parent, k, val]);
}
}
function decirc (val, k, edgeIndex, stack, parent, depth, options) {
depth += 1;
var i;
if (typeof val === 'object' && val !== null) {
for (i = 0; i < stack.length; i++) {
if (stack[i] === val) {
setReplace(CIRCULAR_REPLACE_NODE, val, k, parent);
return
}
}
if (
typeof options.depthLimit !== 'undefined' &&
depth > options.depthLimit
) {
setReplace(LIMIT_REPLACE_NODE, val, k, parent);
return
}
if (
typeof options.edgesLimit !== 'undefined' &&
edgeIndex + 1 > options.edgesLimit
) {
setReplace(LIMIT_REPLACE_NODE, val, k, parent);
return
}
stack.push(val);
// Optimize for Arrays. Big arrays could kill the performance otherwise!
if (Array.isArray(val)) {
for (i = 0; i < val.length; i++) {
decirc(val[i], i, i, stack, val, depth, options);
}
} else {
var keys = Object.keys(val);
for (i = 0; i < keys.length; i++) {
var key = keys[i];
decirc(val[key], key, i, stack, val, depth, options);
}
}
stack.pop();
}
}
// Stable-stringify
function compareFunction (a, b) {
if (a < b) {
return -1
}
if (a > b) {
return 1
}
return 0
}
function deterministicStringify (obj, replacer, spacer, options) {
if (typeof options === 'undefined') {
options = defaultOptions();
}
var tmp = deterministicDecirc(obj, '', 0, [], undefined, 0, options) || obj;
var res;
try {
if (replacerStack.length === 0) {
res = JSON.stringify(tmp, replacer, spacer);
} else {
res = JSON.stringify(tmp, replaceGetterValues(replacer), spacer);
}
} catch (_) {
return JSON.stringify('[unable to serialize, circular reference is too complex to analyze]')
} finally {
// Ensure that we restore the object as it was.
while (arr.length !== 0) {
var part = arr.pop();
if (part.length === 4) {
Object.defineProperty(part[0], part[1], part[3]);
} else {
part[0][part[1]] = part[2];
}
}
}
return res
}
function deterministicDecirc (val, k, edgeIndex, stack, parent, depth, options) {
depth += 1;
var i;
if (typeof val === 'object' && val !== null) {
for (i = 0; i < stack.length; i++) {
if (stack[i] === val) {
setReplace(CIRCULAR_REPLACE_NODE, val, k, parent);
return
}
}
try {
if (typeof val.toJSON === 'function') {
return
}
} catch (_) {
return
}
if (
typeof options.depthLimit !== 'undefined' &&
depth > options.depthLimit
) {
setReplace(LIMIT_REPLACE_NODE, val, k, parent);
return
}
if (
typeof options.edgesLimit !== 'undefined' &&
edgeIndex + 1 > options.edgesLimit
) {
setReplace(LIMIT_REPLACE_NODE, val, k, parent);
return
}
stack.push(val);
// Optimize for Arrays. Big arrays could kill the performance otherwise!
if (Array.isArray(val)) {
for (i = 0; i < val.length; i++) {
deterministicDecirc(val[i], i, i, stack, val, depth, options);
}
} else {
// Create a temporary object in the required way
var tmp = {};
var keys = Object.keys(val).sort(compareFunction);
for (i = 0; i < keys.length; i++) {
var key = keys[i];
deterministicDecirc(val[key], key, i, stack, val, depth, options);
tmp[key] = val[key];
}
if (typeof parent !== 'undefined') {
arr.push([parent, k, val]);
parent[k] = tmp;
} else {
return tmp
}
}
stack.pop();
}
}
// wraps replacer function to handle values we couldn't replace
// and mark them as replaced value
function replaceGetterValues (replacer) {
replacer =
typeof replacer !== 'undefined'
? replacer
: function (k, v) {
return v
};
return function (key, val) {
if (replacerStack.length > 0) {
for (var i = 0; i < replacerStack.length; i++) {
var part = replacerStack[i];
if (part[1] === key && part[0] === val) {
val = part[2];
replacerStack.splice(i, 1);
break
}
}
}
return replacer.call(this, key, val)
}
}
var fastSafeStringify$1 = /*@__PURE__*/getDefaultExportFromCjs(fastSafeStringify);
function tryStringify (o) {
try { return JSON.stringify(o) } catch(e) { return '"[Circular]"' }
}
var quickFormatUnescaped = format;
function format(f, args, opts) {
var ss = (opts && opts.stringify) || tryStringify;
var offset = 1;
if (typeof f === 'object' && f !== null) {
var len = args.length + offset;
if (len === 1) return f
var objects = new Array(len);
objects[0] = ss(f);
for (var index = 1; index < len; index++) {
objects[index] = ss(args[index]);
}
return objects.join(' ')
}
if (typeof f !== 'string') {
return f
}
var argLen = args.length;
if (argLen === 0) return f
var str = '';
var a = 1 - offset;
var lastPos = -1;
var flen = (f && f.length) || 0;
for (var i = 0; i < flen;) {
if (f.charCodeAt(i) === 37 && i + 1 < flen) {
lastPos = lastPos > -1 ? lastPos : 0;
switch (f.charCodeAt(i + 1)) {
case 100: // 'd'
case 102: // 'f'
if (a >= argLen)
break
if (args[a] == null) break
if (lastPos < i)
str += f.slice(lastPos, i);
str += Number(args[a]);
lastPos = i + 2;
i++;
break
case 105: // 'i'
if (a >= argLen)
break
if (args[a] == null) break
if (lastPos < i)
str += f.slice(lastPos, i);
str += Math.floor(Number(args[a]));
lastPos = i + 2;
i++;
break
case 79: // 'O'
case 111: // 'o'
case 106: // 'j'
if (a >= argLen)
break
if (args[a] === undefined) break
if (lastPos < i)
str += f.slice(lastPos, i);
var type = typeof args[a];
if (type === 'string') {
str += '\'' + args[a] + '\'';
lastPos = i + 2;
i++;
break
}
if (type === 'function') {
str += args[a].name || '<anonymous>';
lastPos = i + 2;
i++;
break
}
str += ss(args[a]);
lastPos = i + 2;
i++;
break
case 115: // 's'
if (a >= argLen)
break
if (lastPos < i)
str += f.slice(lastPos, i);
str += String(args[a]);
lastPos = i + 2;
i++;
break
case 37: // '%'
if (lastPos < i)
str += f.slice(lastPos, i);
str += '%';
lastPos = i + 2;
i++;
a--;
break
}
++a;
}
++i;
}
if (lastPos === -1)
return f
else if (lastPos < flen) {
str += f.slice(lastPos);
}
return str
}
var format$1 = /*@__PURE__*/getDefaultExportFromCjs(quickFormatUnescaped);
const logLevel = {
trace: 0,
debug: 1,
info: 2,
warn: 3,
error: 4
};
function shouldLog(setLevel, loggingLevel) {
setLevel = typeof setLevel === "function" ? setLevel() : setLevel;
return setLevel !== false && // logging is not disabled
logLevel[setLevel] <= logLevel[loggingLevel];
}
function logLevelToString(level) {
switch (level) {
case "trace":
return "TRC";
case "debug":
return "DBG";
case "info":
return "INF";
case "warn":
return "WRN";
case "error":
return "ERR";
default:
throw new Error(`Unknown log level "${level}"`);
}
}
function isPromise(val) {
const obj = Object(val);
return typeof obj.then === "function" && typeof obj.catch === "function" && typeof obj.finally === "function";
}
function parseAttrs(attrs, functionUnwrapDepth = 0) {
if (functionUnwrapDepth > 3) {
throw new Error("Too much recursion while unwrapping function attributes");
}
if (!attrs) {
return void 0;
}
if (typeof attrs === "function") {
return parseAttrs(attrs(), functionUnwrapDepth + 1);
}
if (Array.isArray(attrs)) {
return attrs.map((val) => unwrapAttrVal(val));
}
if (isPlainObject(attrs)) {
const unwrapped = {};
for (const key of Object.keys(attrs)) {
const val = attrs[key];
unwrapped[key] = unwrapAttrVal(val);
}
return unwrapped;
}
return objectifyClass(attrs);
}
function unwrapAttrVal(attr, visited = /* @__PURE__ */ new WeakSet()) {
if (!attr) {
return attr;
}
if (isPrimitive(attr)) {
return attr;
}
if (typeof attr === "function") {
return `[Function: ${attr.name || "(anonymous)"}]`;
}
if (visited.has(attr)) {
return "[Circular]";
}
visited.add(attr);
if (Array.isArray(attr)) {
return attr.map((val) => unwrapAttrVal(val));
}
if (isPlainObject(attr)) {
const unwrapped = {};
for (const key of Object.keys(attr)) {
const val = attr[key];
unwrapped[key] = unwrapAttrVal(val, visited);
}
return unwrapped;
}
return objectifyClass(attr);
}
function isPrimitive(val) {
return val !== Object(val);
}
const nodejsCustomInspectSy = Symbol.for("nodejs.util.inspect.custom");
function objectifyClass(val) {
if (
// simply empty
!val || // Object.create(null)
Object(val).__proto__ == null
) {
return {};
}
if (typeof val === "object" && "toJSON" in val && typeof val.toJSON === "function") {
return val.toJSON();
}
if (typeof val === "object" && nodejsCustomInspectSy in val && typeof val[nodejsCustomInspectSy] === "function") {
return {
[nodejsCustomInspectSy.toString()]: unwrapAttrVal(
val[nodejsCustomInspectSy](Infinity, {})
),
class: val.constructor.name
};
}
const props = {};
for (const propName of Object.getOwnPropertyNames(val)) {
props[propName] = unwrapAttrVal(val[propName]);
}
for (const protoPropName of Object.getOwnPropertyNames(
Object.getPrototypeOf(val)
)) {
const propVal = val[protoPropName];
if (typeof propVal === "function") {
continue;
}
props[protoPropName] = unwrapAttrVal(propVal);
}
return {
...props,
class: val.constructor.name
};
}
function getEnv(key) {
return globalThis.process?.env?.[key] || // @ts-expect-error can exist in wrangler and maybe other runtimes
globalThis.env?.[key] || // @ts-expect-error can exist in deno
globalThis.Deno?.env?.get(key) || // @ts-expect-error could be
globalThis[key];
}
function truthyEnv(key) {
return ["1", "t", "true", "y", "yes"].includes(
getEnv(key)?.toLowerCase() || ""
);
}
function shallowMergeAttributes(target, source) {
switch (true) {
case (Array.isArray(source) && Array.isArray(target)):
return [...target, ...source];
case Array.isArray(source):
return target ? [target, ...source] : source;
case Array.isArray(target):
return source ? [...target, source] : target;
case !!(target || source):
return { ...target, ...source };
default:
return void 0;
}
}
function isPlainObject(val) {
return Object(val).constructor === Object && Object.getPrototypeOf(val) === Object.prototype;
}
function jsonStringify(val, pretty) {
return fastSafeStringify$1(val, void 0, pretty ? 2 : void 0);
}
const asciMap = {
timestamp: "\x1B[90m",
// bright black
trace: "\x1B[36m",
// cyan
debug: "\x1B[90m",
// bright black
info: "\x1B[32m",
// green
warn: "\x1B[33m",
// yellow
error: "\x1B[41;39m",
// red; white
message: "\x1B[1m",
// bold
key: "\x1B[35m",
// magenta
reset: "\x1B[0m"
// reset
};
class ConsoleLogWriter {
#console;
#noColor;
#noTimestamp;
constructor(opts = {}) {
const {
console = globalThis.console,
// no color if we're running in browser-like (edge) environments
noColor = typeof process === "undefined" || // or no color if https://no-color.org/
truthyEnv("NO_COLOR"),
noTimestamp = false
} = opts;
this.#console = console;
this.#noColor = noColor;
this.#noTimestamp = noTimestamp;
}
color(style, text) {
if (!text) {
return text;
}
if (this.#noColor) {
return text;
}
return asciMap[style] + text + asciMap.reset;
}
write(level, attrs, msg) {
this.#console[level === "trace" ? "debug" : level](
[
!this.#noTimestamp && this.color("timestamp", (/* @__PURE__ */ new Date()).toISOString()),
this.color(level, logLevelToString(level)),
this.color("message", msg),
attrs && this.stringifyAttrs(attrs)
].filter(Boolean).join(" ")
);
}
stringifyAttrs(attrs) {
let log = "\n";
for (const line of jsonStringify(attrs, true).split("\n")) {
if (line === "{" || line === "}" || line === "[" || line === "]") {
continue;
}
let formattedLine = line;
formattedLine = formattedLine.replace(
/"([^"]+)":/,
this.color("key", "$1:")
);
let indentationSize = line.match(/^\s*/)?.[0]?.length || 0;
if (indentationSize) indentationSize++;
formattedLine = formattedLine.replaceAll(
/\\n/g,
"\n" + [...Array(indentationSize)].join(" ")
);
formattedLine = formattedLine.replace(/,$/, "");
formattedLine = formattedLine.replace(
/(\[|\{|\]|\})$/,
this.color("key", "$1")
);
log += formattedLine + "\n";
}
log = log.slice(0, -1);
return log;
}
}
class JSONLogWriter {
write(level, attrs, msg) {
console.log(
jsonStringify(
{
...attrs,
level,
...msg ? { msg } : {},
timestamp: (/* @__PURE__ */ new Date()).toISOString()
},
truthyEnv("LOG_JSON_PRETTY")
)
);
}
}
class Logger {
#level;
#prefix;
#attrs;
#writers;
#pendingWrites;
constructor(opts = {}) {
let logLevelEnv = getEnv("LOG_LEVEL");
if (logLevelEnv && !(logLevelEnv in logLevel)) {
throw new Error(
`Invalid LOG_LEVEL environment variable "${logLevelEnv}". Must be one of: ${[...Object.keys(logLevel), "false"].join(", ")}`
);
}
this.#level = opts.level ?? logLevelEnv ?? (truthyEnv("DEBUG") ? "debug" : "info");
this.#prefix = opts.prefix;
this.#attrs = opts.attrs;
this.#writers = opts.writers ?? (truthyEnv("LOG_JSON") ? [new JSONLogWriter()] : [new ConsoleLogWriter()]);
}
/** The prefix that's prepended to each log message. */
get prefix() {
return this.#prefix;
}
/**
* The attributes that are added to each log. If the log itself contains
* attributes with keys existing in {@link attrs}, the log's attributes will
* override.
*/
get attrs() {
return this.#attrs;
}
/** The current {@link LogLevel} of the logger. You can change the level using the {@link setLevel} method. */
get level() {
return typeof this.#level === "function" ? this.#level() : this.#level;
}
/**
* Sets the new {@link LogLevel} of the logger. All subsequent logs, and {@link child child loggers} whose
* level did not change, will respect the new level.
*/
setLevel(level) {
this.#level = level;
}
write(level, attrs, msg) {
for (const w of this.#writers) {
const write$ = w.write(level, attrs, msg);
if (isPromise(write$)) {
this.#pendingWrites ??= /* @__PURE__ */ new Set();
this.#pendingWrites.add(write$);
write$.then(() => {
this.#pendingWrites.delete(write$);
}).catch((e) => {
console.error("Failed to write async log", e);
});
}
}
}
flush() {
if (this.#pendingWrites?.size) {
const errs = [];
return Promise.allSettled(
Array.from(this.#pendingWrites).map(
(w) => w.catch((err) => errs.push(err))
)
).then(() => {
this.#pendingWrites.clear();
if (errs.length) {
throw new AggregateError(
errs,
`Failed to flush ${errs.length} writes`
);
}
});
}
return;
}
async [DisposableSymbols.asyncDispose]() {
return this.flush();
}
child(prefixOrAttrs, prefix) {
if (typeof prefixOrAttrs === "string") {
return new Logger({
level: () => this.level,
// inherits the parent level (yet can be changed on child only when using setLevel)
prefix: (this.#prefix || "") + prefixOrAttrs,
attrs: this.#attrs,
writers: this.#writers
});
}
return new Logger({
level: () => this.level,
// inherits the parent level (yet can be changed on child only when using setLevel)
prefix: (this.#prefix || "") + (prefix || "") || void 0,
attrs: shallowMergeAttributes(this.#attrs, prefixOrAttrs),
writers: this.#writers
});
}
log(level, maybeAttrsOrMsg, ...rest) {
if (!shouldLog(this.#level, level)) {
return;
}
let msg;
let attrs;
if (typeof maybeAttrsOrMsg === "string") {
msg = maybeAttrsOrMsg;
} else if (maybeAttrsOrMsg) {
attrs = maybeAttrsOrMsg;
if (typeof rest[0] === "string") {
msg = rest.shift();
}
}
if (this.#prefix) {
msg = `${this.#prefix}${msg || ""}`.trim();
}
attrs = shallowMergeAttributes(parseAttrs(this.#attrs), parseAttrs(attrs));
msg = msg && rest.length ? format$1(msg, rest, { stringify: fastSafeStringify$1 }) : msg;
this.write(level, attrs, msg);
if (truthyEnv("LOG_TRACE_LOGS")) {
console.trace("\u{1F446}");
}
}
trace(...args) {
this.log(
"trace",
...args
);
}
debug(...args) {
this.log(
"debug",
...args
);
}
info(...args) {
this.log(
"info",
...args
);
}
warn(...args) {
this.log(
"warn",
...args
);
}
error(...args) {
this.log(
"error",
...args
);
}
}
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
var __typeError = (msg) => {
throw TypeError(msg);
};
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
var __runInitializers = (array, flags, self, value) => {
for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) fns[i].call(self) ;
return value;
};
var __decorateElement = (array, flags, name, decorators, target, extra) => {
var it, done, ctx, k = flags & 7, p = false;
var j = 0;
var extraInitializers = array[j] || (array[j] = []);
var desc = k && ((target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(target , name));
__name(target, name);
for (var i = decorators.length - 1; i >= 0; i--) {
ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
it = (0, decorators[i])(target, ctx), done._ = 1;
__expectFn(it) && (target = it);
}
return __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
};
var _HiveGatewayDriver_decorators, _init, _a;
_HiveGatewayDriver_decorators = [Injectable()];
class HiveGatewayDriver extends (_a = AbstractGraphQLDriver) {
_gatewayRuntime;
_subscriptionService;
async ensureGatewayRuntime({
typeDefs,
resolvers,
logging,
...options
}) {
if (this._gatewayRuntime) {
return this._gatewayRuntime;
}
const additionalTypeDefs = [];
if (typeDefs) {
additionalTypeDefs.push(typeDefs);
}
const additionalResolvers = [];
if (resolvers) {
additionalResolvers.push(...asArray(resolvers));
}
let log;
if (logging != null) {
log = createLoggerFromLogging(logging);
} else {
const nestLog = new Logger$1("Hive Gateway");
log = new Logger({
writers: [
{
write(level, attrs, msg) {
switch (level) {
case "trace":
nestLog.verbose(msg, attrs);
break;
case "info":
nestLog.log(msg, attrs);
break;
default:
nestLog[level](msg, attrs);
}
}
}
]
});
}
const configCtx = {
log,
cwd: process.cwd(),
pubsub: options.pubsub || new PubSub()
};
const cache = await getCacheInstanceFromConfig(options, configCtx);
const builtinPlugins = await getBuiltinPluginsFromConfig(options, {
...configCtx,
cache
});
this._gatewayRuntime = createGatewayRuntime({
...options,
logging: configCtx.log,
cache,
graphqlEndpoint: options.path,
additionalTypeDefs,
additionalResolvers,
disableIntrospection: options.introspection === false ? { disableIf: () => options.introspection || false } : void 0,
...options.context || options.transformSchema || options.sortSchema ? {
plugins: (ctx) => {
const existingPlugins = options.plugins?.(ctx) || [];
if (options.context) {
const contextPlugin = {
onContextBuilding: ({ context, extendContext }) => handleMaybePromise(
() => typeof options.context === "function" ? options.context(context) : options.context,
extendContext
)
};
existingPlugins.push(contextPlugin);
}
if (options.transformSchema) {
const schemaTransformPlugin = {
onSchemaChange({ schema, replaceSchema }) {
return handleMaybePromise(
() => options.transformSchema(schema),
replaceSchema
);
}
};
existingPlugins.push(schemaTransformPlugin);
}
if (options.sortSchema) {
const schemaSortPlugin = {
onSchemaChange({ schema, replaceSchema }) {
replaceSchema(lexicographicSortSchema(schema));
}
};
existingPlugins.push(schemaSortPlugin);
}
return [...builtinPlugins, ...existingPlugins];
}
} : {}
});
return this._gatewayRuntime;
}
async start(options) {
const gatewayRuntime = await this.ensureGatewayRuntime(options);
const platformName = this.httpAdapterHost.httpAdapter.getType();
if (platformName === "express") {
this.registerExpress();
} else if (platformName === "fastify") {
this.registerFastify();
} else {
throw new Error(`No support for current HttpAdapter: ${platformName}`);
}
if (options.installSubscriptionHandlers || options.subscriptions) {
const subscriptionsOptions = options.subscriptions || { "graphql-ws": {} };
if (subscriptionsOptions["graphql-ws"]) {
const gwOptions = getGraphQLWSOptions(
gatewayRuntime,
(ctx) => ({
req: ctx.extra?.request,
socket: ctx.extra?.socket
})
);
subscriptionsOptions["graphql-ws"] = {
...gwOptions,
...typeof subscriptionsOptions["graphql-ws"] === "object" ? subscriptionsOptions["graphql-ws"] : {}
};
}
if (subscriptionsOptions["subscriptions-transport-ws"]) {
subscriptionsOptions["subscriptions-transport-ws"] = typeof subscriptionsOptions["subscriptions-transport-ws"] === "object" ? subscriptionsOptions["subscriptions-transport-ws"] : {};
subscriptionsOptions["subscriptions-transport-ws"].onOperation = async (_msg, params, ws) => {
const {
schema,
execute,
subscribe,
contextFactory,
parse,
validate
} = gatewayRuntime.getEnveloped({
...params.context,
req: (
// @ts-expect-error upgradeReq does exist but is untyped
ws.upgradeReq
),
socket: ws,
params
});
const args = {
schema,
operationName: params.operationName,
document: typeof params.query === "string" ? parse(params.query) : params.query,
variables: params.variables,
context: await contextFactory(),
rootValue: { execute, subscribe }
};
const errors = validate(args.schema, args.document);
if (errors.length) return errors;
return args;
};
}
this._subscriptionService = new GqlSubscriptionService(
{
schema: await gatewayRuntime.getSchema(),
path: options.path,
// @ts-expect-error - We know that execute and subscribe are defined
execute: (args) => args.rootValue.execute(args),
// @ts-expect-error - We know that execute and subscribe are defined
subscribe: (args) => args.rootValue.subscribe(args),
...subscriptionsOptions
},
this.httpAdapterHost.httpAdapter?.getHttpServer()
);
}
}
async stop() {
await Promise.all([
this._subscriptionService?.stop(),
this._gatewayRuntime?.dispose()
]);
}
async generateSchema(options) {
const gatewayRuntime = await this.ensureGatewayRuntime(options);
return gatewayRuntime.getSchema();
}
registerExpress() {
if (!this._gatewayRuntime) {
throw new Error("Hive Gateway is not initialized");
}
this.httpAdapterHost.httpAdapter.use(this._gatewayRuntime);
}
registerFastify() {
this.httpAdapterHost.httpAdapter.getInstance().all("*", async (req, reply) => {
if (!this._gatewayRuntime) {
throw new Error("Hive Gateway is not initialized");
}
const response = await this._gatewayRuntime.handleNodeRequestAndResponse(req, reply, {
req,
reply
});
response.headers.forEach((value, key) => {
reply.header(key, value);
});
reply.status(response.status);
reply.send(response.body);
return reply;
});
}
}
_init = __decoratorStart(_a);
HiveGatewayDriver = __decorateElement(_init, 0, "HiveGatewayDriver", _HiveGatewayDriver_decorators, HiveGatewayDriver);
__runInitializers(_init, 1, HiveGatewayDriver);
export { HiveGatewayDriver };