UNPKG

@graphql-hive/gateway-testing

Version:
159 lines (154 loc) 4.95 kB
'use strict'; var subgraph = require('@apollo/subgraph'); var gatewayRuntime = require('@graphql-hive/gateway-runtime'); var fusionComposition = require('@graphql-mesh/fusion-composition'); var executorHttp = require('@graphql-tools/executor-http'); var graphql = require('graphql'); var graphqlYoga = require('graphql-yoga'); function getEnvStr(key, opts = {}) { const globalThat = opts.globalThis ?? globalThis; let variable = globalThat.process?.env?.[key] || // @ts-expect-error can exist in wrangler and maybe other runtimes globalThat.env?.[key] || // @ts-expect-error can exist in deno globalThat.Deno?.env?.get(key) || // @ts-expect-error could be globalThat[key]; if (variable != null) { variable += ""; } else { variable = void 0; } return variable?.trim(); } function getEnvBool(key, opts = {}) { return strToBool(getEnvStr(key, opts)); } function strToBool(str) { return ["1", "t", "true", "y", "yes", "on", "enabled"].includes( (str || "").toLowerCase() ); } function isDebug() { return getEnvBool("DEBUG"); } function createGatewayTester(config) { let runtime; if ("supergraph" in config) { runtime = gatewayRuntime.createGatewayRuntime({ maskedErrors: false, logging: isDebug(), ...config }); } else if ("subgraphs" in config) { let buildSubgraphs2 = function() { subgraphsRef.ref = (typeof subgraphsConfig === "function" ? subgraphsConfig() : subgraphsConfig).reduce( (acc, subgraph) => { const remoteSchema = buildRemoteSchema(subgraph); return { ...acc, [remoteSchema.name]: remoteSchema }; }, {} ); return Object.values(subgraphsRef.ref); }; const subgraphsConfig = config.subgraphs; const subgraphsRef = { ref: null }; runtime = gatewayRuntime.createGatewayRuntime({ maskedErrors: false, logging: isDebug(), ...config, supergraph: typeof config.subgraphs === "function" ? () => fusionComposition.getUnifiedGraphGracefully(buildSubgraphs2()) : fusionComposition.getUnifiedGraphGracefully(buildSubgraphs2()), plugins: (ctx) => [ { onFetch({ executionRequest, setFetchFn }) { const subgraphName = executionRequest?.subgraphName; if (!subgraphName) { return; } if (!subgraphsRef.ref) { throw new Error("Subgraphs are not built yet"); } const subgraph = subgraphsRef.ref[subgraphName]; if (!subgraph) { throw new Error(`Subgraph "${subgraphName}" not found`); } setFetchFn(subgraph.yoga.fetch); } }, ...config.plugins?.(ctx) || [] ] }); } else if ("proxy" in config) { const remoteSchema = buildRemoteSchema(config.proxy); runtime = gatewayRuntime.createGatewayRuntime({ maskedErrors: false, logging: isDebug(), ...config, proxy: { endpoint: remoteSchema.url, headers: config.proxy.headers }, plugins: (ctx) => [ gatewayRuntime.useCustomFetch((url, options, context, info) => { return remoteSchema.yoga.fetch( // @ts-expect-error TODO: url can be a string, not only an instance of URL url, options, context, info ); }), ...config.plugins?.(ctx) || [] ] }); } else { throw new Error("Unsupported gateway tester configuration"); } const runtimeExecute = executorHttp.buildHTTPExecutor({ endpoint: "http://gateway/graphql", fetch: runtime.fetch, headers: (execReq) => execReq?.rootValue.headers }); return { runtime, // @ts-expect-error native and whatwg-node fetch has conflicts fetch: runtime.fetch, async execute(args) { return runtimeExecute({ document: graphql.parse(args.query), variables: args.variables, operationName: args.operationName, extensions: args.extensions, rootValue: { headers: args.headers } }); }, [graphqlYoga.DisposableSymbols.asyncDispose]() { return runtime[graphqlYoga.DisposableSymbols.asyncDispose](); }, async dispose() { await runtime.dispose(); } }; } function buildRemoteSchema(config) { const schema = "typeDefs" in config.schema ? subgraph.buildSubgraphSchema([ { ...config.schema, typeDefs: graphql.parse(config.schema.typeDefs) } ]) : config.schema; const yoga = typeof config.yoga === "function" ? config.yoga?.(schema) : graphqlYoga.createYoga({ maskedErrors: false, logging: isDebug(), ...config.yoga, schema }); const host = config.host || config.name; const url = `http://${host}${yoga.graphqlEndpoint}`; return { name: config.name, url, schema, yoga }; } exports.createGatewayTester = createGatewayTester;