UNPKG

@graphql-hive/gateway-runtime

Version:
2,879 lines • 101 kB
import { useDisableIntrospection } from '@envelop/disable-introspection';
import { useGenericAuth } from '@envelop/generic-auth';
import { createSchemaFetcher, createSupergraphSDLFetcher } from '@graphql-hive/core';
import { millisecondsToStr, getOnSubgraphExecute, subgraphNameByExecutionRequest, UnifiedGraphManager, restoreExtraDirectives, getTransportEntryMapUsingFusionAndFederationDirectives, getStitchingDirectivesTransformerForSubschema, handleFederationSubschema, handleResolveToDirectives } from '@graphql-mesh/fusion-runtime';
export { getExecutorForUnifiedGraph, getSdkRequesterForUnifiedGraph } from '@graphql-mesh/fusion-runtime';
import { useHmacUpstreamSignature } from '@graphql-mesh/hmac-upstream-signature';
export * from '@graphql-mesh/hmac-upstream-signature';
import useMeshResponseCache from '@graphql-mesh/plugin-response-cache';
import { DefaultLogger, LogLevel, isUrl, readFileOrUrl, defaultImportFn, requestIdByRequest, getHeadersObj, wrapFetchWithHooks, isDisposable, dispose, getInContextSDK, pathExists } from '@graphql-mesh/utils';
export { DefaultLogger, LogLevel } from '@graphql-mesh/utils';
import { batchDelegateToSchema } from '@graphql-tools/batch-delegate';
import { getTypeInfo, EMPTY_OBJECT, delegateToSchema } from '@graphql-tools/delegate';
import { defaultPrintFn as defaultPrintFn$1 } from '@graphql-tools/executor-common';
import { getDirectiveExtensions, memoize1, isValidPath, pathToArray, memoize3, getDirective, createGraphQLError, isAsyncIterable, mapAsyncIterator, createDeferred, isPromise, isDocumentNode, asArray, printSchemaWithDirectives, parseSelectionSet, mergeDeep } from '@graphql-tools/utils';
import { wrapSchema, schemaFromExecutor } from '@graphql-tools/wrap';
import { useCSRFPrevention } from '@graphql-yoga/plugin-csrf-prevention';
import { useDeferStream } from '@graphql-yoga/plugin-defer-stream';
import { usePersistedOperations } from '@graphql-yoga/plugin-persisted-operations';
import { AsyncDisposableStack } from '@whatwg-node/disposablestack';
export * from '@whatwg-node/disposablestack';
import { handleMaybePromise, iterateAsync } from '@whatwg-node/promise-helpers';
import { useCookies } from '@whatwg-node/server-plugin-cookies';
import { print, visit, visitWithTypeInfo, getArgumentValues, getNamedType, isIntrospectionType, isListType, isCompositeType, getOperationAST, isSchema, parse, buildASTSchema, buildSchema } from 'graphql';
import { isAsyncIterable as isAsyncIterable$1, useReadinessCheck, useExecutionCancellation, createYoga, chain, mergeSchemas } from 'graphql-yoga';
import { process as process$1, path, fs } from '@graphql-mesh/cross-helpers';
import { DEFAULT_UPLINKS, fetchSupergraphSdlFromManagedFederation } from '@graphql-tools/federation';
import { JSONLogger } from '@graphql-hive/logger-json';
export { JSONLogger } from '@graphql-hive/logger-json';
import { useApolloUsageReport } from '@graphql-yoga/plugin-apollo-usage-report';
import { useHive } from '@graphql-hive/yoga';
import { useContentEncoding as useContentEncoding$1 } from '@whatwg-node/server';
import { defaultPrintFn } from '@graphql-mesh/transport-common';
import { abortSignalAny } from '@graphql-hive/signal';
import { isOriginalGraphQLError } from '@envelop/core';

function checkIfDataSatisfiesSelectionSet(selectionSet, data) {
  if (Array.isArray(data)) {
    return data.every(
      (item) => checkIfDataSatisfiesSelectionSet(selectionSet, item)
    );
  }
  for (const selection of selectionSet.selections) {
    if (selection.kind === "Field") {
      const field = selection;
      const responseKey = field.alias?.value || field.name.value;
      if (data[responseKey] != null) {
        if (field.selectionSet) {
          if (!checkIfDataSatisfiesSelectionSet(
            field.selectionSet,
            data[field.name.value]
          )) {
            return false;
          }
        }
      } else {
        return false;
      }
    } else if (selection.kind === "InlineFragment") {
      const inlineFragment = selection;
      if (!checkIfDataSatisfiesSelectionSet(inlineFragment.selectionSet, data)) {
        return false;
      }
    }
  }
  return true;
}
const defaultQueryText = (
  /* GraphQL */
  `
  # Welcome to GraphiQL
  # GraphiQL is an in-browser tool for writing, validating,
  # and testing GraphQL queries.
  #
  # Type queries into this side of the screen, and you will
  # see intelligent typeaheads aware of the current GraphQL
  # type schema and live syntax and validation errors
  # highlighted within the text.
  #
  # GraphQL queries typically start with a "{" character.
  # Lines that start with a # are ignored.
  #
  # An example GraphQL query might look like:
  #
  #     {
  #       field(arg: "value") {
  #         subField
  #       }
  #     }
  #
`
);
function delayInMs(ms, signal) {
  return new Promise((resolve, reject) => {
    globalThis.setTimeout(resolve, ms);
  });
}
const getExecuteFnFromExecutor = memoize1(
  function getExecuteFnFromExecutor2(executor) {
    return function executeFn(args) {
      return executor({
        document: args.document,
        variables: args.variableValues,
        operationName: args.operationName ?? void 0,
        rootValue: args.rootValue,
        context: args.contextValue,
        signal: args.signal
      });
    };
  }
);
function wrapCacheWithHooks({
  cache,
  onCacheGet,
  onCacheSet,
  onCacheDelete
}) {
  return new Proxy(cache, {
    get(target, prop, receiver) {
      switch (prop) {
        case "get": {
          if (onCacheGet.length === 0) {
            break;
          }
          return function cacheGet(key) {
            const onCacheGetResults = [];
            return handleMaybePromise(
              () => iterateAsync(
                onCacheGet,
                (onCacheGet2) => onCacheGet2({
                  key,
                  cache
                }),
                onCacheGetResults
              ),
              () => handleMaybePromise(
                () => target.get(key),
                (value) => value == null ? handleMaybePromise(
                  () => iterateAsync(
                    onCacheGetResults,
                    (onCacheGetResult) => onCacheGetResult?.onCacheMiss?.()
                  ),
                  () => value
                ) : handleMaybePromise(
                  () => iterateAsync(
                    onCacheGetResults,
                    (onCacheGetResult) => onCacheGetResult?.onCacheHit?.({ value })
                  ),
                  () => value
                ),
                (error) => handleMaybePromise(
                  () => iterateAsync(
                    onCacheGetResults,
                    (onCacheGetResult) => onCacheGetResult?.onCacheGetError?.({ error })
                  ),
                  () => {
                    throw error;
                  }
                )
              )
            );
          };
        }
        case "set": {
          if (onCacheSet.length === 0) {
            break;
          }
          return function cacheSet(key, value, opts) {
            const onCacheSetResults = [];
            return handleMaybePromise(
              () => iterateAsync(
                onCacheSet,
                (onCacheSet2) => onCacheSet2({
                  key,
                  value,
                  ttl: opts?.ttl,
                  cache
                }),
                onCacheSetResults
              ),
              () => handleMaybePromise(
                () => target.set(key, value, opts),
                (result) => handleMaybePromise(
                  () => iterateAsync(
                    onCacheSetResults,
                    (onCacheSetResult) => onCacheSetResult?.onCacheSetDone?.()
                  ),
                  () => result
                ),
                (err) => handleMaybePromise(
                  () => iterateAsync(
                    onCacheSetResults,
                    (onCacheSetResult) => onCacheSetResult?.onCacheSetError?.({ error: err })
                  ),
                  () => {
                    throw err;
                  }
                )
              )
            );
          };
        }
        case "delete": {
          if (onCacheDelete.length === 0) {
            break;
          }
          return function cacheDelete(key) {
            const onCacheDeleteResults = [];
            return handleMaybePromise(
              () => iterateAsync(
                onCacheDelete,
                (onCacheDelete2) => onCacheDelete2({
                  key,
                  cache
                })
              ),
              () => handleMaybePromise(
                () => target.delete(key),
                (result) => handleMaybePromise(
                  () => iterateAsync(
                    onCacheDeleteResults,
                    (onCacheDeleteResult) => onCacheDeleteResult?.onCacheDeleteDone?.()
                  ),
                  () => result
                )
              ),
              (err) => handleMaybePromise(
                () => iterateAsync(
                  onCacheDeleteResults,
                  (onCacheDeleteResult) => onCacheDeleteResult?.onCacheDeleteError?.({ error: err })
                ),
                () => {
                  throw err;
                }
              )
            );
          };
        }
      }
      return Reflect.get(target, prop, receiver);
    }
  });
}
function urlMatches(url, specUrl) {
  {
    return url === specUrl;
  }
}
function normalizeDirectiveName(directiveName) {
  if (directiveName.startsWith("@")) {
    return directiveName.slice(1);
  }
  return directiveName;
}
function getDirectiveNameForFederationDirective({
  schema,
  directiveName,
  specUrl
}) {
  const directivesOnSchemaDef = getDirectiveExtensions(schema, schema);
  const normalizedDirectiveName = normalizeDirectiveName(directiveName);
  if (directivesOnSchemaDef?.["link"]) {
    const linkDirectives = directivesOnSchemaDef["link"];
    for (const linkDirective of linkDirectives) {
      if (urlMatches(linkDirective.url, specUrl)) {
        const imports = linkDirective.import;
        if (imports) {
          for (const importDirective of imports) {
            if (typeof importDirective === "string") {
              const normalizedImportDirective = normalizeDirectiveName(importDirective);
              if (normalizedImportDirective === normalizedDirectiveName) {
                return normalizedImportDirective;
              }
            } else {
              const normalizedImportDirective = normalizeDirectiveName(
                importDirective.name
              );
              if (normalizedImportDirective === normalizedDirectiveName) {
                const normalizedAlias = normalizeDirectiveName(
                  importDirective.as
                );
                return normalizedAlias;
              }
            }
          }
        }
      }
    }
  }
  return normalizedDirectiveName;
}

const defaultLoadedPlacePrefix = "GraphOS Managed Federation";
function decideMaxRetries({
  graphosOpts,
  pollingInterval,
  minDelaySeconds,
  uplinks,
  initialSchemaExists
}) {
  let maxRetries = graphosOpts.maxRetries || Math.max(3, uplinks.length);
  if (initialSchemaExists && pollingInterval && pollingInterval <= minDelaySeconds * 1e3) {
    maxRetries = 1;
  }
  return maxRetries;
}
function createGraphOSFetcher({
  graphosOpts,
  configContext,
  pollingInterval
}) {
  let lastSeenId;
  let lastSupergraphSdl;
  let nextFetchTime;
  const uplinksParam = graphosOpts.upLink || process$1.env["APOLLO_SCHEMA_CONFIG_DELIVERY_ENDPOINT"];
  const uplinks = uplinksParam?.split(",").map((uplink) => uplink.trim()) || DEFAULT_UPLINKS;
  const graphosLogger = configContext.logger.child({ source: "GraphOS" });
  graphosLogger.info("Using GraphOS with uplinks ", ...uplinks);
  let supergraphLoadedPlace = defaultLoadedPlacePrefix;
  if (graphosOpts.graphRef) {
    supergraphLoadedPlace += ` <br>${graphosOpts.graphRef}`;
  }
  let minDelaySeconds = 10;
  const uplinksToUse = [];
  return {
    supergraphLoadedPlace,
    unifiedGraphFetcher(transportContext) {
      const maxRetries = decideMaxRetries({
        graphosOpts,
        pollingInterval,
        minDelaySeconds,
        uplinks,
        initialSchemaExists: !!lastSupergraphSdl
      });
      let retries = maxRetries;
      function fetchSupergraphWithDelay() {
        if (nextFetchTime) {
          const currentTime = Date.now();
          if (nextFetchTime >= currentTime) {
            const delay = nextFetchTime - currentTime;
            graphosLogger.info(
              `Fetching supergraph with delay: ${millisecondsToStr(delay)}`
            );
            nextFetchTime = 0;
            return delayInMs(delay).then(fetchSupergraph);
          }
        }
        return fetchSupergraph();
      }
      function fetchSupergraph() {
        if (uplinksToUse.length === 0) {
          uplinksToUse.push(...uplinks);
        }
        retries--;
        const uplinkToUse = uplinksToUse.pop();
        const attemptMetadata = {
          uplink: uplinkToUse || "none"
        };
        if (maxRetries > 1) {
          attemptMetadata["attempt"] = `${maxRetries - retries}/${maxRetries}`;
        }
        const attemptLogger = graphosLogger.child(attemptMetadata);
        attemptLogger.debug(`Fetching supergraph`);
        return handleMaybePromise(
          () => fetchSupergraphSdlFromManagedFederation({
            graphRef: graphosOpts.graphRef,
            apiKey: graphosOpts.apiKey,
            upLink: uplinkToUse,
            lastSeenId,
            fetch: transportContext.fetch || configContext.fetch,
            loggerByMessageLevel: {
              ERROR(message) {
                attemptLogger.error(message);
              },
              INFO(message) {
                attemptLogger.info(message);
              },
              WARN(message) {
                attemptLogger.warn(message);
              }
            }
          }),
          (result) => {
            if (result.minDelaySeconds) {
              minDelaySeconds = result.minDelaySeconds;
              attemptLogger.debug(`Setting min delay to ${minDelaySeconds}s`);
            }
            nextFetchTime = Date.now() + minDelaySeconds * 1e3;
            if ("error" in result && result.error) {
              attemptLogger.error(result.error.code, result.error.message);
            }
            if ("id" in result) {
              if (lastSeenId === result.id) {
                attemptLogger.debug("Supergraph is unchanged");
                return lastSupergraphSdl;
              }
              lastSeenId = result.id;
            }
            if ("supergraphSdl" in result && result.supergraphSdl) {
              attemptLogger.debug(
                `Fetched the new supergraph ${lastSeenId ? `with id ${lastSeenId}` : ""}`
              );
              lastSupergraphSdl = result.supergraphSdl;
            }
            if (!lastSupergraphSdl) {
              if (retries > 0) {
                return fetchSupergraphWithDelay();
              }
              throw new Error(
                `Failed to fetch supergraph SDL from '${uplinkToUse}': [${JSON.stringify(result)}]`
              );
            }
            return lastSupergraphSdl;
          },
          (err) => {
            nextFetchTime = Date.now() + minDelaySeconds * 1e3;
            if (retries > 0) {
              attemptLogger.error(err);
              return fetchSupergraphWithDelay();
            }
            if (lastSupergraphSdl) {
              attemptLogger.error(err);
              return lastSupergraphSdl;
            }
            if (err?.name === "TimeoutError") {
              throw new Error(`HTTP request to '${uplinkToUse}' timed out`);
            }
            throw err;
          }
        );
      }
      return fetchSupergraphWithDelay();
    }
  };
}

function getDefaultLogger(opts) {
  const logFormat = process$1.env["LOG_FORMAT"] || globalThis.LOG_FORMAT;
  if (logFormat) {
    if (logFormat.toLowerCase() === "json") {
      return new JSONLogger(opts);
    } else if (logFormat.toLowerCase() === "pretty") {
      return new DefaultLogger(opts?.name, opts?.level);
    }
  }
  const nodeEnv = process$1.env["NODE_ENV"] || globalThis.NODE_ENV;
  if (nodeEnv === "production") {
    return new JSONLogger(opts);
  }
  return new DefaultLogger(opts?.name, opts?.level);
}
function handleLoggingConfig(loggingConfig, existingLogger) {
  if (typeof loggingConfig === "object") {
    return loggingConfig;
  }
  if (typeof loggingConfig === "boolean") {
    if (!loggingConfig) {
      if (existingLogger && "logLevel" in existingLogger) {
        existingLogger.logLevel = LogLevel.silent;
        return existingLogger;
      }
      return getDefaultLogger({
        name: existingLogger?.name,
        level: LogLevel.silent
      });
    }
  }
  if (typeof loggingConfig === "number") {
    if (existingLogger && "logLevel" in existingLogger) {
      existingLogger.logLevel = loggingConfig;
      return existingLogger;
    }
    return getDefaultLogger({
      name: existingLogger?.name,
      level: loggingConfig
    });
  }
  if (typeof loggingConfig === "string") {
    if (existingLogger && "logLevel" in existingLogger) {
      existingLogger.logLevel = LogLevel[loggingConfig];
      return existingLogger;
    }
    return getDefaultLogger({
      name: existingLogger?.name,
      level: LogLevel[loggingConfig]
    });
  }
  return existingLogger || getDefaultLogger();
}

function getProxyExecutor({
  config,
  configContext,
  getSchema,
  onSubgraphExecuteHooks,
  transportExecutorStack,
  instrumentation
}) {
  const fakeTransportEntryMap = {};
  let subgraphName = "upstream";
  const onSubgraphExecute = getOnSubgraphExecute({
    onSubgraphExecuteHooks,
    transportEntryMap: new Proxy(fakeTransportEntryMap, {
      get(fakeTransportEntryMap2, subgraphNameProp) {
        if (!fakeTransportEntryMap2[subgraphNameProp]) {
          subgraphName = subgraphNameProp;
          fakeTransportEntryMap2[subgraphNameProp] = {
            kind: "http",
            subgraph: subgraphName.toString(),
            location: config.proxy?.endpoint,
            headers: config.proxy?.headers,
            options: config.proxy
          };
        }
        return fakeTransportEntryMap2[subgraphNameProp];
      }
    }),
    transportContext: configContext,
    getSubgraphSchema: getSchema,
    transportExecutorStack,
    transports: config.transports,
    instrumentation
  });
  return function proxyExecutor(executionRequest) {
    return onSubgraphExecute(subgraphName, executionRequest);
  };
}

function useHiveConsole({
  enabled,
  token,
  ...options
}) {
  const agent = {
    name: "hive-gateway",
    logger: options.logger,
    ...options.agent
  };
  let usage = void 0;
  if (options.usage && typeof options.usage === "object") {
    usage = {
      ...options.usage,
      clientInfo: typeof options.usage.clientInfo === "object" ? () => (
        // @ts-expect-error clientInfo will be an object
        options.usage.clientInfo
      ) : options.usage.clientInfo
    };
  } else {
    usage = options.usage;
  }
  if (enabled && !token) {
    throw new Error("Hive plugin is enabled but the token is not provided");
  }
  return useHive({
    debug: ["1", "y", "yes", "t", "true"].includes(
      String(process$1.env["DEBUG"])
    ),
    ...options,
    enabled: !!enabled,
    token,
    agent,
    usage
  });
}

function getReportingPlugin(config, configContext) {
  if (config.reporting?.type === "hive") {
    const { target, ...reporting } = config.reporting;
    let usage = reporting.usage;
    if (usage === false) ; else {
      usage = {
        target,
        ...typeof usage === "object" ? { ...usage } : {}
      };
    }
    return {
      name: "Hive",
      plugin: useHiveConsole({
        logger: configContext.logger.child({ reporting: "Hive" }),
        enabled: true,
        ...reporting,
        ...usage ? { usage } : {},
        ...config.persistedDocuments && "type" in config.persistedDocuments && config.persistedDocuments?.type === "hive" ? {
          experimental__persistedDocuments: {
            cdn: {
              endpoint: config.persistedDocuments.endpoint,
              accessToken: config.persistedDocuments.token
            },
            allowArbitraryDocuments: !!config.persistedDocuments.allowArbitraryDocuments
          }
        } : {}
      })
    };
  } else if (config.reporting?.type === "graphos" || !config.reporting && "supergraph" in config && typeof config.supergraph === "object" && "type" in config.supergraph && config.supergraph.type === "graphos") {
    if ("supergraph" in config && typeof config.supergraph === "object" && "type" in config.supergraph && config.supergraph.type === "graphos") {
      if (!config.reporting) {
        config.reporting = {
          type: "graphos",
          apiKey: config.supergraph.apiKey,
          graphRef: config.supergraph.graphRef
        };
      } else {
        config.reporting.apiKey ||= config.supergraph.apiKey;
        config.reporting.graphRef ||= config.supergraph.graphRef;
      }
    }
    return {
      name: "GraphOS",
      // @ts-expect-error - TODO: Fix types
      plugin: useApolloUsageReport({
        agentVersion: `hive-gateway@${globalThis.__VERSION__}`,
        ...config.reporting
      })
    };
  }
  return {
    plugin: {}
  };
}

function handleUnifiedGraphConfig(config, configContext) {
  return handleMaybePromise(
    () => typeof config === "function" ? config(configContext) : config,
    (schema) => handleUnifiedGraphSchema(schema, configContext)
  );
}
function handleUnifiedGraphSchema(unifiedGraphSchema, configContext) {
  if (typeof unifiedGraphSchema === "string" && (isValidPath(unifiedGraphSchema) || isUrl(unifiedGraphSchema))) {
    return readFileOrUrl(unifiedGraphSchema, {
      fetch: configContext.fetch,
      cwd: configContext.cwd,
      logger: configContext.logger,
      allowUnknownExtensions: true,
      importFn: defaultImportFn
    });
  }
  return unifiedGraphSchema;
}

var landingPageHtml = `<!doctype html><html lang=en><head><meta charset=utf-8><title>Welcome to __PRODUCT_NAME__</title><link rel=apple-touch-icon sizes=180x180 href=https://the-guild.dev/apple-touch-icon.png><link rel=icon type=image/png sizes=32x32 href=https://the-guild.dev/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=https://the-guild.dev/favicon-16x16.png><link rel=icon type=image/png sizes=16x16 href=https://the-guild.dev/favicon-16x16.png><link rel="shorcut icon" type=image/x-icon href=https://the-guild.dev/favicon.ico><link rel=stylesheet href=https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/default.min.css><script src=https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js><\/script><script src=https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/languages/typescript.min.js><\/script><script>hljs.highlightAll()<\/script><style>*{box-sizing:border-box}body,html{padding:20px;margin:0;background-color:#000;color:#fff;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol'}a{color:#add8e6}code{background-color:#d3d3d3;color:#000;padding:2px;border-radius:4px;font-family:monospace}table{border:2px solid #d3d3d3;border-radius:4px;border-spacing:0}th{text-align:left;color:#d3d3d3;border-bottom:4px solid #d3d3d3}td,th{padding:6px 8px}td{overflow-wrap:anywhere}pre{max-width:100%}.hero{display:flex;flex-direction:column;align-items:center}.hero .logo{font-size:2rem;display:flex;align-items:center;gap:10px}.hero .logo svg{height:50px}.hero .logo h1{margin:0}.hero .description{color:gray}.hero .links{text-align:center}.status{position:relative;margin:50px auto;display:flex;flex-direction:column;max-width:800px}.status h2,.status p{margin:0}.status .var{display:flex;flex-direction:column;align-items:flex-start}.status .var label{font-size:small}.four-oh-four{position:relative;display:flex;flex-direction:column;align-items:center;background-color:#2f2f2f;border-radius:4px;margin:0 auto;padding:10px;max-width:800px;border:1px solid gray;opacity:.4;transition:opacity .3s ease-in-out}.four-oh-four:hover{opacity:1}.four-oh-four p{text-align:center}</style></head><body id=body><main><section class=hero><div class=logo><!-- will be an <svg> --> __PRODUCT_LOGO__<h1>__PRODUCT_NAME__</h1></div><p class=description>__PRODUCT_DESCRIPTION__</p><div class=links><a href=__PRODUCT_LINK__ class=docs>\u{1F4DA} Read the Documentation</a><br><a href=__GRAPHIQL_LINK__ class=graphiql>\u{1F5C3}\uFE0F Visit GraphiQL</a></div></section><section class=status>__SUBGRAPH_HTML__</section><section class=four-oh-four><h2>\u2139\uFE0F Not the Page You Expected To See?</h2><p>This page is shown be default whenever a 404 is hit.<br>You can disable this by behavior via the <code>landingPage</code> option.</p><pre><code class=language-typescript>import { defineConfig } from '__PRODUCT_PACKAGE_NAME__';

export const gatewayConfig = defineConfig({
  landingPage: false,
});
</code></pre><p>If you expected <u>this</u> page to be the GraphQL route, you need to configure Hive Gateway.<br>Currently, the GraphQL route is configured to be on <a href=__GRAPHIQL_LINK__ class=graphiql>__GRAPHIQL_LINK__</a>.</p><pre><code class=language-typescript>import { defineConfig } from '__PRODUCT_PACKAGE_NAME__';

export const gatewayConfig = defineConfig({
  graphqlEndpoint: '__REQUEST_PATH__',
});
</code></pre></section></main></body></html>`;

function useCacheDebug(opts) {
  return {
    onCacheGet({ key }) {
      return {
        onCacheGetError({ error }) {
          const cacheGetErrorLogger = opts.logger.child("cache-get-error");
          cacheGetErrorLogger.error({ key, error });
        },
        onCacheHit({ value }) {
          const cacheHitLogger = opts.logger.child("cache-hit");
          cacheHitLogger.debug({ key, value });
        },
        onCacheMiss() {
          const cacheMissLogger = opts.logger.child("cache-miss");
          cacheMissLogger.debug({ key });
        }
      };
    },
    onCacheSet({ key, value, ttl }) {
      return {
        onCacheSetError({ error }) {
          const cacheSetErrorLogger = opts.logger.child("cache-set-error");
          cacheSetErrorLogger.error({ key, value, ttl, error });
        },
        onCacheSetDone() {
          const cacheSetDoneLogger = opts.logger.child("cache-set-done");
          cacheSetDoneLogger.debug({ key, value, ttl });
        }
      };
    },
    onCacheDelete({ key }) {
      return {
        onCacheDeleteError({ error }) {
          const cacheDeleteErrorLogger = opts.logger.child("cache-delete-error");
          cacheDeleteErrorLogger.error({ key, error });
        },
        onCacheDeleteDone() {
          const cacheDeleteDoneLogger = opts.logger.child("cache-delete-done");
          cacheDeleteDoneLogger.debug({ key });
        }
      };
    }
  };
}

function useContentEncoding({
  subgraphs
} = {}) {
  if (!subgraphs?.length) {
    return useContentEncoding$1();
  }
  const compressionAlgorithm = "gzip";
  let fetchAPI;
  const execReqWithContentEncoding = /* @__PURE__ */ new WeakSet();
  return {
    onYogaInit({ yoga }) {
      fetchAPI = yoga.fetchAPI;
    },
    onPluginInit({ addPlugin }) {
      addPlugin(
        // @ts-expect-error - Plugin types do not match
        useContentEncoding$1()
      );
    },
    onSubgraphExecute({ subgraphName, executionRequest }) {
      if (subgraphs.includes(subgraphName) || subgraphs.includes("*")) {
        execReqWithContentEncoding.add(executionRequest);
      }
    },
    onFetch({ executionRequest, options, setOptions }) {
      if (options.body && !options.headers?.["Content-Encoding"] && executionRequest && execReqWithContentEncoding.has(executionRequest) && fetchAPI.CompressionStream) {
        const compressionStream = new fetchAPI.CompressionStream(
          compressionAlgorithm
        );
        let bodyStream;
        if (options.body instanceof fetchAPI.ReadableStream) {
          bodyStream = options.body;
        } else {
          bodyStream = new fetchAPI.Response(options.body).body;
        }
        setOptions({
          ...options,
          headers: {
            "Accept-Encoding": "gzip, deflate",
            ...options.headers,
            "Content-Encoding": compressionAlgorithm
          },
          body: bodyStream.pipeThrough(compressionStream)
        });
      }
    }
  };
}

function useCustomAgent(agentFactory) {
  return {
    onFetch(payload) {
      const agent = agentFactory(payload);
      if (agent != null) {
        payload.setOptions({
          ...payload.options,
          // @ts-expect-error - `agent` is there
          agent
        });
      }
    }
  };
}

function useDelegationPlanDebug(opts) {
  let fetchAPI;
  const stageExecuteLogById = /* @__PURE__ */ new WeakMap();
  return {
    onYogaInit({ yoga }) {
      fetchAPI = yoga.fetchAPI;
    },
    onDelegationPlan({
      typeName,
      variables,
      fragments,
      fieldNodes,
      info,
      logger = opts.logger
    }) {
      const planId = fetchAPI.crypto.randomUUID();
      const planLogger = logger.child({ planId, typeName });
      const delegationPlanStartLogger = planLogger.child(
        "delegation-plan-start"
      );
      delegationPlanStartLogger.debug(() => {
        const logObj = {};
        if (variables && Object.keys(variables).length) {
          logObj["variables"] = variables;
        }
        if (fragments && Object.keys(fragments).length) {
          logObj["fragments"] = Object.fromEntries(
            Object.entries(fragments).map(([name, fragment]) => [
              name,
              print(fragment)
            ])
          );
        }
        if (fieldNodes && fieldNodes.length) {
          logObj["fieldNodes"] = fieldNodes.map(
            (fieldNode) => print(fieldNode)
          );
        }
        if (info?.path) {
          logObj["path"] = pathToArray(info.path).join(" | ");
        }
        return logObj;
      });
      return ({ delegationPlan }) => {
        const delegationPlanDoneLogger = logger.child("delegation-plan-done");
        delegationPlanDoneLogger.debug(
          () => delegationPlan.map((plan) => {
            const planObj = {};
            for (const [subschema, selectionSet] of plan) {
              if (subschema.name) {
                planObj[subschema.name] = print(selectionSet);
              }
            }
            return planObj;
          })
        );
      };
    },
    onDelegationStageExecute({
      object,
      info,
      context,
      subgraph,
      selectionSet,
      key,
      typeName,
      logger = opts.logger
    }) {
      let contextLog = stageExecuteLogById.get(context);
      if (!contextLog) {
        contextLog = /* @__PURE__ */ new Set();
        stageExecuteLogById.set(context, contextLog);
      }
      const log = {
        key: JSON.stringify(key),
        object: JSON.stringify(object),
        selectionSet: print(selectionSet)
      };
      const logStr = JSON.stringify(log);
      if (contextLog.has(logStr)) {
        return;
      }
      contextLog.add(logStr);
      const logMeta = {
        stageId: fetchAPI.crypto.randomUUID(),
        subgraph,
        typeName
      };
      const delegationStageLogger = logger.child(logMeta);
      delegationStageLogger.debug("delegation-plan-start", () => {
        return {
          ...log,
          path: pathToArray(info.path).join(" | ")
        };
      });
      return ({ result }) => {
        const delegationStageExecuteDoneLogger = logger.child(
          "delegation-stage-execute-done"
        );
        delegationStageExecuteDoneLogger.debug(() => result);
      };
    }
  };
}

function getDepthOfListType(type) {
  let depth = 0;
  while (isListType(type)) {
    depth++;
    type = type.ofType;
  }
  return depth;
}
const getCostListSizeDirectiveNames = memoize1(
  function getCostListSizeDirectiveNames2(schema) {
    const costDirectiveName = getDirectiveNameForFederationDirective({
      schema,
      directiveName: "cost",
      specUrl: "https://specs.apollo.dev/cost/v0.1"
    });
    const listSizeDirectiveName = getDirectiveNameForFederationDirective({
      schema,
      directiveName: "listSize",
      specUrl: "https://specs.apollo.dev/cost/v0.1"
    });
    return {
      cost: costDirectiveName,
      listSize: listSizeDirectiveName
    };
  }
);
function createCalculateCost({
  listSize,
  operationTypeCost,
  typeCost,
  fieldCost
}) {
  return memoize3(function calculateCost(schema, document, variables) {
    const { cost: costDirectiveName, listSize: listSizeDirectiveName } = getCostListSizeDirectiveNames(schema);
    let cost = 0;
    const factorQueue = [];
    function timesFactor(c) {
      for (const f of factorQueue) {
        c *= f;
      }
      return c;
    }
    const fieldFactorMap = /* @__PURE__ */ new Map();
    const typeInfo = getTypeInfo(schema);
    visit(
      document,
      visitWithTypeInfo(typeInfo, {
        OperationTypeDefinition(node) {
          cost += operationTypeCost(node.operation) || 0;
        },
        Field: {
          enter(node) {
            let currentFieldCost = 0;
            const field = typeInfo.getFieldDef();
            if (field) {
              const fieldAnnotations = getDirectiveExtensions(field, schema);
              const factoryResult = fieldCost?.(node, typeInfo);
              if (factoryResult) {
                currentFieldCost += factoryResult;
              } else if (fieldAnnotations?.[costDirectiveName]) {
                for (const costAnnotation of fieldAnnotations[costDirectiveName]) {
                  if (costAnnotation?.weight) {
                    const weight = Number(costAnnotation.weight);
                    if (weight && !isNaN(weight)) {
                      currentFieldCost += weight;
                    }
                  }
                }
              }
              const returnType = typeInfo.getType();
              let factor = 1;
              const sizedFieldFactor = fieldFactorMap.get(node.name.value);
              if (sizedFieldFactor) {
                factor = sizedFieldFactor;
                fieldFactorMap.delete(field.name);
              } else if (fieldAnnotations?.[listSizeDirectiveName]) {
                for (const listSizeAnnotation of fieldAnnotations[listSizeDirectiveName]) {
                  if (listSizeAnnotation) {
                    if ("slicingArguments" in listSizeAnnotation) {
                      const slicingArguments = listSizeAnnotation.slicingArguments;
                      const argValues = getArgumentValues(
                        field,
                        node,
                        variables
                      );
                      let factorSet = false;
                      let slicingArgumentFactor = 1;
                      for (const slicingArgument of slicingArguments) {
                        const value = argValues[slicingArgument];
                        const numValue = Number(value);
                        if (numValue && !isNaN(numValue)) {
                          slicingArgumentFactor = Math.max(
                            slicingArgumentFactor,
                            numValue
                          );
                          if (factorSet && listSizeAnnotation.requireOneSlicingArgument !== false) {
                            throw createGraphQLError(
                              `Only one slicing argument is allowed on field "${field.name}"; found multiple slicing arguments "${slicingArguments.join(", ")}"`,
                              {
                                extensions: {
                                  code: "COST_QUERY_PARSE_FAILURE"
                                }
                              }
                            );
                          }
                          factorSet = true;
                        }
                      }
                      if (listSizeAnnotation.sizedFields?.length) {
                        for (const sizedField of listSizeAnnotation.sizedFields) {
                          fieldFactorMap.set(sizedField, slicingArgumentFactor);
                        }
                      } else {
                        factor = slicingArgumentFactor;
                      }
                    } else if ("assumedSize" in listSizeAnnotation) {
                      const assumedSizeVal = listSizeAnnotation.assumedSize;
                      const numValue = Number(assumedSizeVal);
                      if (numValue && !isNaN(numValue)) {
                        factor = numValue;
                      }
                    }
                  }
                }
              } else if (listSize && returnType) {
                const depth = getDepthOfListType(returnType);
                if (depth > 0) {
                  factor = listSize * depth;
                }
              }
              factorQueue.push(factor);
              if (returnType) {
                const namedReturnType = getNamedType(returnType);
                if (isIntrospectionType(namedReturnType)) {
                  return;
                }
                const namedReturnTypeAnnotations = getDirectiveExtensions(
                  namedReturnType,
                  schema
                );
                if (namedReturnTypeAnnotations?.[costDirectiveName]) {
                  for (const costAnnotation of namedReturnTypeAnnotations[costDirectiveName]) {
                    if (costAnnotation?.weight) {
                      const weight = Number(costAnnotation?.weight);
                      if (weight && !isNaN(weight)) {
                        currentFieldCost += weight;
                      }
                    }
                  }
                } else {
                  currentFieldCost += typeCost(namedReturnType);
                }
              }
              if (currentFieldCost) {
                cost += timesFactor(currentFieldCost);
              }
            }
          },
          leave() {
            factorQueue.pop();
          }
        },
        Directive() {
          const directive = typeInfo.getDirective();
          if (directive) {
            const directiveCostAnnotations = getDirective(
              schema,
              directive,
              "cost"
            );
            if (directiveCostAnnotations) {
              for (const costAnnotation of directiveCostAnnotations) {
                if (costAnnotation["weight"]) {
                  const weight = Number(costAnnotation["weight"]);
                  if (weight && !isNaN(weight)) {
                    cost += timesFactor(weight);
                  }
                }
              }
            }
          }
        },
        Argument() {
          const argument = typeInfo.getArgument();
          if (argument) {
            const argumentCostAnnotations = getDirective(
              schema,
              argument,
              "cost"
            );
            if (argumentCostAnnotations) {
              for (const costAnnotation of argumentCostAnnotations) {
                if (costAnnotation["weight"]) {
                  const weight = Number(costAnnotation["weight"]);
                  if (weight && !isNaN(weight)) {
                    cost += timesFactor(weight);
                  }
                }
              }
            }
          }
        }
      })
    );
    return cost;
  });
}

function useDemandControl({
  listSize = 0,
  maxCost,
  includeExtensionMetadata = process$1.env["NODE_ENV"] === "development",
  operationTypeCost = (operationType) => operationType === "mutation" ? 10 : 0,
  fieldCost,
  typeCost = (type) => isCompositeType(type) ? 1 : 0
}) {
  const calculateCost = createCalculateCost({
    listSize,
    operationTypeCost,
    fieldCost,
    typeCost
  });
  const costByContextMap = /* @__PURE__ */ new WeakMap();
  return {
    onSubgraphExecute({ subgraph, executionRequest, logger }) {
      const demandControlLogger = logger?.child("demand-control");
      let costByContext = executionRequest.context ? costByContextMap.get(executionRequest.context) || 0 : 0;
      const operationCost = calculateCost(
        subgraph,
        executionRequest.document,
        executionRequest.variables || EMPTY_OBJECT
      );
      costByContext += operationCost;
      if (executionRequest.context) {
        costByContextMap.set(executionRequest.context, costByContext);
      }
      demandControlLogger?.debug({
        operationCost,
        totalCost: costByContext
      });
      if (maxCost != null && costByContext > maxCost) {
        throw createGraphQLError(
          `Operation estimated cost ${costByContext} exceeded configured maximum ${maxCost}`,
          {
            extensions: {
              code: "COST_ESTIMATED_TOO_EXPENSIVE",
              cost: {
                estimated: costByContext,
                max: maxCost
              }
            }
          }
        );
      }
    },
    onExecutionResult({ result, setResult, context }) {
      if (includeExtensionMetadata) {
        const costByContext = costByContextMap.get(context) || 0;
        if (isAsyncIterable(result)) {
          setResult(
            mapAsyncIterator(result, (value) => ({
              ...value,
              extensions: {
                ...value.extensions || {},
                cost: {
                  estimated: costByContext,
                  max: maxCost
                }
              }
            }))
          );
        } else {
          setResult({
            ...result || {},
            extensions: {
              ...result?.extensions || {},
              cost: {
                estimated: costByContext,
                max: maxCost
              }
            }
          });
        }
      }
    }
  };
}

function useFetchDebug(opts) {
  let fetchAPI;
  return {
    onYogaInit({ yoga }) {
      fetchAPI = yoga.fetchAPI;
    },
    onFetch({ url, options, logger = opts.logger }) {
      const fetchId = fetchAPI.crypto.randomUUID();
      const fetchLogger = logger.child({
        fetchId
      });
      const httpFetchRequestLogger = fetchLogger.child("http-fetch-request");
      httpFetchRequestLogger.debug(() => ({
        url,
        ...options || {},
        body: options?.body,
        headers: options?.headers,
        signal: options?.signal?.aborted ? options?.signal?.reason : false
      }));
      const start = performance.now();
      return function onFetchDone({ response }) {
        const httpFetchResponseLogger = fetchLogger.child(
          "http-fetch-response"
        );
        httpFetchResponseLogger.debug(() => ({
          status: response.status,
          headers: Object.fromEntries(response.headers.entries()),
          duration: performance.now() - start
        }));
      };
    }
  };
}

function usePropagateHeaders(opts) {
  const resHeadersByRequest = /* @__PURE__ */ new WeakMap();
  return {
    onFetch({ executionRequest, context, options, setOptions }) {
      const request = context?.request || executionRequest?.context?.request;
      if (request) {
        const subgraphName = executionRequest && subgraphNameByExecutionRequest.get(executionRequest);
        return handleMaybePromise(
          () => handleMaybePromise(
            () => opts.fromClientToSubgraphs?.({
              request,
              subgraphName
            }),
            (propagatingHeaders) => {
              const headers = options.headers || {};
              for (const key in propagatingHeaders) {
                const value = propagatingHeaders[key];
                if (value != null && headers[key] == null) {
                  headers[key] = value;
                }
              }
              setOptions({
                ...options,
                headers
              });
            }
          ),
          () => {
            if (opts.fromSubgraphsToClient) {
              return function onFetchDone({ response }) {
                return handleMaybePromise(
                  () => opts.fromSubgraphsToClient?.({
                    response,
                    subgraphName
                  }),
                  (headers) => {
                    if (headers && request) {
                      let existingHeaders = resHeadersByRequest.get(request);
                      if (!existingHeaders) {
                        existingHeaders = {};
                        resHeadersByRequest.set(request, existingHeaders);
                      }
                      for (const key in headers) {
                        const value = headers[key];
                        if (value != null) {
                          const headerAsArray = Array.isArray(value) ? value : [value];
                          if (existingHeaders[key]) {
                            existingHeaders[key].push(...headerAsArray);
                          } else {
                            existingHeaders[key] = headerAsArray;
                          }
                        }
                      }
                    }
                  }
                );
              };
            }
          }
        );
      }
    },
    onResponse({ response, request }) {
      const headers = resHeadersByRequest.get(request);
      if (headers) {
        for (const key in headers) {
          const value = headers[key];
          if (value) {
            for (const v of value) {
              response.headers.append(key, v);
            }
          }
        }
      }
    }
  };
}

const defaultGenerateRequestId = ({
  fetchAPI = globalThis
}) => fetchAPI.crypto.randomUUID();
const defaultRequestIdHeader = "x-request-id";
function useRequestId(opts) {
  const headerName = opts?.headerName || defaultRequestIdHeader;
  const generateRequestId = opts?.generateRequestId || defaultGenerateRequestId;
  return {
    onRequest({ request, fetchAPI, serverContext }) {
      const requestId = request.headers.get(headerName) || generateRequestId({
        request,
        fetchAPI,
        // @ts-expect-error - Server context is not typed
        context: serverContext
      });
      requestIdByRequest.set(request, requestId);
    },
    onContextBuilding({ context }) {
      if (context?.request) {
        const requestId = requestIdByRequest.get(context.request);
        if (requestId && context.logger) {
          context.logger = context.logger.child({ requestId });
        }
      }
    },
    onFetch({ context, options, setOptions }) {
      if (context?.request) {
        const requestId = requestIdByRequest.get(context.request);
        if (requestId) {
          setOptions({
            ...options || {},
            headers: {
              ...options.headers || {},
              [headerName]: requestId
            }
          });
        }
      }
    },
    onResponse({ request, response }) {
      const requestId = requestIdByRequest.get(request);
      if (requestId) {
        response.headers.set(headerName, requestId);
      }
    }
  };
}

function useRetryOnSchemaReload({
  logger
}) {
  const execHandlerByContext = /* @__PURE__ */ new WeakMap();
  function handleOnExecute(args) {
    if (args.contextValue) {
      const operation = getOperationAST(args.document, args.operationName);
      if (operation?.operation !== "query") {
        execHandlerByContext.delete(args.contextValue);
      }
    }
  }
  function handleExecutionResult({
    context,
    result,
    setResult,
    request
  }) {
    const execHandler = execHandlerByContext.get(context);
    if (execHandler && result?.errors?.some((e) => e.extensions?.["code"] === "SCHEMA_RELOAD")) {
      let requestLogger = logger;
      const requestId = requestIdByRequest.get(request);
      if (requestId) {
        requestLogger = logger.child({ requestId });
      }
      requestLogger.info(
        "The operation has been aborted after the supergraph schema reloaded, retrying the operation..."
      );
      if (execHandler) {
        return handleMaybePromise(
          execHandler,
          (newResult) => setResult(newResult)
        );
      }
    }
  }
  return {
    onParams({ request, params, context, paramsHandler }) {
      execHandlerByContext.set(
        context,
        () => paramsHandler({
          request,
          params,
          context
        })
      );
    },
    onExecute({ args }) {
      handleOnExecute(args);
    },
    onSubscribe({ args }) {
      handleOnExecute(args);
    },
    onExecutionResult({ request, context, result, setResult }) {
      if (isAsyncIterable$1(result)) {
        return;
      }
      return handleExecutionResult({ context, result, setResult, request });
    },
    onResultProcess({ result, setResult, serverContext, request }) {
      if (isAsyncIterable$1(result) || Array.isArray(result)) {
        return;
      }
      return handleExecutionResult({
        context: serverContext,
        result,
        setResult,
        request
      });
    }
  };
}

function useSubgraphErrorPlugin({
  errorCode = "DOWNSTREAM_SERVICE_ERROR",
  subgraphNameProp = "serviceName"
} = {}) {
  function extendError(error, subgraphName) {
    const errorExtensions = error.extensions ||= {};
    if (errorCode) {
      errorExtensions.code ||= errorCode;
    }
    if (subgraphNameProp) {
      errorExtensions[subgraphNameProp] ||= subgraphName;
    }
  }
  return {
    onSubgraphExecute({ subgraphName }) {
      return function({ result }) {
        if (isAsyncIterable(result)) {
          return {
            onNext({ result: result2 }) {
              if (result2.errors) {
                for (const error of result2.errors) {
                  extendError(error, subgraphName);
                }
              }
            }
          };
        }
        if (result.errors) {
          for (const error of result.errors) {
            extendError(error, subgraphName);
          }
        }
        return;
      };
    }
  };
}

function useSubgraphExecuteDebug(opts) {
  let fetchAPI;
  return {
    onYogaInit({ yoga }) {
      fetchAPI = yoga.fetchAPI;
    },
    onSubgraphExecute({ executionRequest, logger = opts.logger }) {
      const subgraphExecuteHookLogger = logger.child({
        subgraphExecuteId: fetchAPI.crypto.randomUUID()
      });
      const subgraphExecuteStartLogger = subgraphExecuteHookLogger.child(
        "subgraph-execute-start"
      );
      subgraphExecuteStartLogger.debug(() => {
        const logData = {};
        if (executionRequest.document) {
          logData["query"] = defaultPrintFn(executionRequest.document);
        }
        if (executionRequest.variables && Object.keys(executionRequest.variables).length) {
          logData["variables"] = executionRequest.variables;
        }
        return logData;
      });
      const start = performance.now();
      return function onSubgraphExecuteDone({ result }) {
        const subgraphExecuteEndLogger = subgraphExecuteHookLogger.child(
          "subgraph-execute-end"
        );
        if (isAsyncIterable$1(result)) {
          return {
            onNext({ result: result2 }) {
              const subgraphExecuteNextLogger = subgraphExecuteHookLogger.child(
                "subgraph-execute-next"
              );
              subgraphExecuteNextLogger.debug(result2);
            },
            onEnd() {
              subgraphExecuteEndLogger.debug(() => ({
                duration: performance.now() - start
              }));
            }
          };
        }
        subgraphExecuteEndLogger.debug(result);
        return void 0;
      };
    }
  };
}

function useUpstreamCancel() {
  return {
    onFetch({ context, options, executionRequest, info }) {
      const signals = [];
      if (context?.request?.signal) {
        signals.push(context.request.signal);
      }
      const execRequestSignal = executionRequest?.signal || executionRequest?.info?.signal;
      if (execRequestSignal) {
        signals.push(execRequestSignal);
      }
      const signalInInfo = info?.signal;
      if (signalInInfo) {
        signals.push(signalInInfo);
      }
      if (options.signal) {
        signals.push(options.signal);
      }
      options.signal = abortSignalAny(signals);
    },
    onSubgraphExecute({ executionRequest }) {
      const signals = [];
      if (executionRequest.info?.signal) {
        signals.push(executionRequest.info.signal);
      }
      if (executionRequest.context?.request?.signal) {
        signals.push(executionRequest.context.request.signal);
      }
      if (executionRequest.signal) {
        signals.push(executionRequest.signal);
      }
      executionRequest.signal = abortSignalAny(signals);
    }
  };
}

function useUpstreamRetry(opts) {
  const timeouts = /* @__PURE__ */ new Set();
  const retryOptions = typeof opts === "function" ? opts : () => opts;
  const executionRequestResponseMap = /* @__PURE__ */ new WeakMap();
  return {
    onSubgraphExecute({
      subgraphName,
      executionRequest,
      executor,
      setExecutor
    }) {
      const optsForReq = retryOptions({ subgraphName, executionRequest });
      if (optsForReq) {
        const {
          maxRetries,
          retryDelay = 1e3,
          retryDelayFactor = 1.25,
          shouldRetry = ({ response, executionResult }) => {
            if (response) {
              if (response.status >= 500 || response.status === 429 || response.headers.get("Retry-After")) {
                return true;
              }
            }
            if (!executionResult || !isAsyncIterable(executionResult) && executionResult.errors?.length && executionResult.errors.some((e) => !isOriginalGraphQLError(e))) {
              return true;
            }
            return false;
          }
        } = optsForReq;
        if (maxRetries > 0) {
          setExecutor(function(executionRequest2) {
            let attemptsLeft = maxRetries + 1;
            let executionResult;
            let currRetryDelay = retryDelay;
            function retry() {
              try {
                if (attemptsLeft <= 0) {
                  return executionResult;
                }
                const requestTime = Date.now();
                attemptsLeft--;
                return handleMaybePromise(
                  () => executor(executionRequest2),
                  (currRes) => {
                    executionResult = currRes;
                    let retryAfterSecondsFromHeader;
                    const response = executionRequestResponseMap.get(executionRequest2);
                    executionRequestResponseMap.delete(executionRequest2);
                    const retryAfterHeader = response?.headers.get("Retry-After");
                    if (retryAfterHeader) {
                      retryAfterSecondsFromHeader = parseInt(retryAfterHeader) * 1e3;
                      if (isNaN(retryAfterSecondsFromHeader)) {
                        const dateTime = new Date(retryAfterHeader).getTime();
                        if (!isNaN(dateTime)) {
                          retryAfterSecondsFromHeader = dateTime - requestTime;
                        }
                      }
                    }
                    currRetryDelay = retryAfterSecondsFromHeader || currRetryDelay * retryDelayFactor;
                    if (shouldRetry({
                      executionRequest: executionRequest2,
                      executionResult,
                      response
                    })) {
                      return new Promise((resolve) => {
                        const timeout = setTimeout(() => {
                          timeouts.delete(timeout);
                          resolve(retry());
                        }, currRetryDelay);
                        timeouts.add(timeout);
                      });
                    }
                    return executionResult;
                  },
                  (e) => {
                    if (attemptsLeft <= 0) {
                      throw e;
                    }
                    return retry();
                  }
                );
              } catch (e) {
                if (attemptsLeft <= 0) {
                  throw e;
                }
                return retry();
              }
            }
            return retry();
          });
        }
      }
    },
    onFetch({ info, executionRequest }) {
      executionRequest ||= info?.rootValue?.executionRequest;
      if (executionRequest) {
        return function onFetchDone({ response }) {
          executionRequestResponseMap.set(executionRequest, response);
        };
      }
      return void 0;
    },
    onDispose() {
      for (const timeout of timeouts) {
        clearTimeout(timeout);
        timeouts.delete(timeout);
      }
    }
  };
}

function useUpstreamTimeout(opts) {
  const timeoutFactory = typeof opts === "function" ? opts : () => opts;
  const timeoutSignalsByExecutionRequest = /* @__PURE__ */ new WeakMap();
  const errorExtensionsByExecRequest = /* @__PURE__ */ new WeakMap();
  return {
    onSubgraphExecute({
      subgraphName,
      executionRequest,
      executor,
      setExecutor
    }) {
      const timeout = timeoutFactory({ subgraphName, executionRequest });
      if (timeout) {
        setExecutor(function timeoutExecutor(executionRequest2) {
          let timeoutSignal = timeoutSignalsByExecutionRequest.get(executionRequest2);
          if (!timeoutSignal) {
            timeoutSignal = AbortSignal.timeout(timeout);
            timeoutSignalsByExecutionRequest.set(
              executionRequest2,
              timeoutSignal
            );
          }
          const signals = [];
          signals.push(timeoutSignal);
          if (executionRequest2.signal) {
            signals.push(executionRequest2.signal);
          }
          const timeoutDeferred = createDeferred();
          function rejectDeferred() {
            timeoutDeferred.reject(timeoutSignal?.reason);
          }
          timeoutSignal.addEventListener("abort", rejectDeferred, {
            once: true
          });
          const combinedSignal = abortSignalAny(signals);
          const res$ = executor({
            ...executionRequest2,
            signal: combinedSignal
          });
          if (!isPromise(res$)) {
            return res$;
          }
          return Promise.race([timeoutDeferred.promise, res$]).then((result) => {
            if (isAsyncIterable(result)) {
              return {
                [Symbol.asyncIterator]() {
                  const iterator = result[Symbol.asyncIterator]();
                  if (iterator.return) {
                    timeoutSignal.addEventListener(
                      "abort",
                      () => {
                        iterator.return?.(timeoutSignal.reason);
                      },
                      {
                        once: true
                      }
                    );
                  }
                  return iterator;
                }
              };
            }
            return result;
          }).catch((e) => {
            if (e === timeoutSignal.reason) {
              const upstreamErrorExtensions = errorExtensionsByExecRequest.get(executionRequest2);
              throw createGraphQLError(e.message, {
                extensions: {
                  ...upstreamErrorExtensions,
                  code: "TIMEOUT_ERROR",
                  http: {
                    status: 504
                  }
                }
              });
            }
            throw e;
          }).finally(() => {
            timeoutDeferred.resolve(void 0);
            timeoutSignal.removeEventListener("abort", rejectDeferred);
            errorExtensionsByExecRequest.delete(executionRequest2);
            timeoutSignalsByExecutionRequest.delete(executionRequest2);
          });
        });
      }
      return void 0;
    },
    onFetch({ url, executionRequest, options, setOptions }) {
      const subgraphName = executionRequest && subgraphNameByExecutionRequest.get(executionRequest);
      if (!executionRequest || !timeoutSignalsByExecutionRequest.has(executionRequest)) {
        const timeout = timeoutFactory({ subgraphName, executionRequest });
        if (timeout) {
          let timeoutSignal;
          if (executionRequest) {
            timeoutSignal = timeoutSignalsByExecutionRequest.get(executionRequest);
            if (!timeoutSignal) {
              timeoutSignal = AbortSignal.timeout(timeout);
              timeoutSignalsByExecutionRequest.set(
                executionRequest,
                timeoutSignal
              );
            }
          } else {
            timeoutSignal = AbortSignal.timeout(timeout);
          }
          const signals = [];
          signals.push(timeoutSignal);
          if (options.signal) {
            signals.push(options.signal);
          }
          setOptions({
            ...options,
            signal: abortSignalAny(signals)
          });
        }
      }
      if (executionRequest) {
        const upstreamErrorExtensions = {
          serviceName: subgraphName,
          request: {
            url,
            method: options.method,
            body: options.body
          }
        };
        errorExtensionsByExecRequest.set(
          executionRequest,
          upstreamErrorExtensions
        );
        return function onFetchDone({ response }) {
          timeoutSignalsByExecutionRequest.delete(executionRequest);
          upstreamErrorExtensions.response = {
            status: response.status,
            statusText: response.statusText,
            headers: getHeadersObj(response.headers)
          };
        };
      }
      return void 0;
    }
  };
}

function useWebhooks({
  pubsub,
  logger
}) {
  if (!pubsub) {
    throw new Error(`You must provide a pubsub instance to webhooks feature!
    Example:
      import { PubSub } from '@graphql-hive/gateway'
      export const gatewayConfig = defineConfig({
        pubsub: new PubSub(),
        webhooks: true,
      })
    See documentation: https://the-guild.dev/docs/mesh/pubsub`);
  }
  return {
    onRequest({ request, url, endResponse, fetchAPI }) {
      const eventNames = pubsub.getEventNames();
      if (eventNames.length === 0) {
        return;
      }
      const requestMethod = request.method.toLowerCase();
      const pathname = url.pathname;
      const expectedEventName = `webhook:${requestMethod}:${pathname}`;
      for (const eventName of eventNames) {
        if (eventName === expectedEventName) {
          logger?.debug(() => `Received webhook request for ${pathname}`);
          return handleMaybePromise(
            () => request.text(),
            function handleWebhookPayload(webhookPayload) {
              logger?.debug(
                () => `Emitted webhook request for ${pathname}: ${webhookPayload}`
              );
              webhookPayload = request.headers.get("content-type") === "application/json" ? JSON.parse(webhookPayload) : webhookPayload;
              pubsub.publish(eventName, webhookPayload);
              return endResponse(
                new fetchAPI.Response(null, {
                  status: 204,
                  statusText: "OK"
                })
              );
            }
          );
        }
      }
    }
  };
}

const defaultProductLogo = (
  /* HTML */
  `<svg
  viewBox="0 0 52 53"
  fill="currentColor"
  class="size-7 text-green-1000"
>
  <defs>
    <path
      id="hive-gateway-path"
      d="m25 .524872-7.7758.000001V13.6981c0 2.2382-1.8128 4.051-4.0509 4.051H0l7.2e-7 7.7758H8.48411c1.06096 0 2.07849-.4215 2.82859-1.1718l12.5159-12.5176C24.5786 11.0854 25 10.068 25 9.00727V.524872Zm2 0 7.7758.000001V13.6981c0 2.2382 1.8128 4.051 4.0509 4.051H52v7.7758h-8.4841c-1.061 0-2.0785-.4215-2.8286-1.1718L28.1714 11.8355C27.4214 11.0854 27 10.068 27 9.00727V.524872ZM25 52.5249h-7.7758V39.3516c0-2.2381-1.8128-4.0509-4.0509-4.0509H0l7.2e-7-7.7758H8.48411c1.06096 0 2.07849.4215 2.82859 1.1717l12.5159 12.5176c.75.7502 1.1714 1.7675 1.1714 2.8283v8.4824Zm2 0h7.7758V39.3516c0-2.2381 1.8128-4.0509 4.0509-4.0509H52v-7.7758h-8.4841c-1.061 0-2.0785.4215-2.8286 1.1717L28.1714 41.2142c-.75.7502-1.1714 1.7675-1.1714 2.8283v8.4824Zm2.8369-29.837H22.163v7.6739h7.6739v-7.6739Z"
    ></path>
    <clipPath id="hive-gateway-clip-path">
      <use href="#hive-gateway-path"></use>
    </clipPath>
  </defs>
  <use href="#hive-gateway-path" clip-path="url(#hive-gateway-clip-path)"></use>
</svg>`
);

function createGatewayRuntime(config) {
  let fetchAPI = config.fetchAPI;
  const logger = handleLoggingConfig(config.logging);
  let instrumentation;
  const onFetchHooks = [];
  const onCacheGetHooks = [];
  const onCacheSetHooks = [];
  const onCacheDeleteHooks = [];
  const wrappedFetchFn = wrapFetchWithHooks(
    onFetchHooks,
    () => instrumentation,
    logger
  );
  const wrappedCache = config.cache ? wrapCacheWithHooks({
    cache: config.cache,
    onCacheGet: onCacheGetHooks,
    onCacheSet: onCacheSetHooks,
    onCacheDelete: onCacheDeleteHooks
  }) : void 0;
  const pubsub = config.pubsub;
  const configContext = {
    fetch: wrappedFetchFn,
    logger,
    cwd: config.cwd || (typeof process !== "undefined" ? process.cwd() : ""),
    cache: wrappedCache,
    pubsub
  };
  let unifiedGraphPlugin;
  const readinessCheckEndpoint = config.readinessCheckEndpoint || "/readiness";
  const onSubgraphExecuteHooks = [];
  const onDelegateHooks = [];
  const onDelegationPlanHooks = [];
  const onDelegationStageExecuteHooks = [];
  let unifiedGraph;
  let schemaInvalidator;
  let getSchema = () => unifiedGraph;
  let contextBuilder;
  let readinessChecker;
  let getExecutor;
  let replaceSchema = (newSchema) => {
    unifiedGraph = newSchema;
  };
  const { name: reportingTarget, plugin: registryPlugin } = getReportingPlugin(
    config,
    configContext
  );
  let persistedDocumentsPlugin = {};
  if (config.reporting?.type !== "hive" && config.persistedDocuments && "type" in config.persistedDocuments && config.persistedDocuments?.type === "hive") {
    persistedDocumentsPlugin = useHiveConsole({
      ...configContext,
      enabled: false,
      // disables only usage reporting
      logger: configContext.logger.child({
        plugin: "Hive Persisted Documents"
      }),
      experimental__persistedDocuments: {
        cdn: {
          endpoint: config.persistedDocuments.endpoint,
          accessToken: config.persistedDocuments.token
        },
        allowArbitraryDocuments: !!config.persistedDocuments.allowArbitraryDocuments
      }
    });
  } else if (config.persistedDocuments && "getPersistedOperation" in config.persistedDocuments) {
    persistedDocumentsPlugin = usePersistedOperations({
      ...configContext,
      ...config.persistedDocuments
    });
  }
  let subgraphInformationHTMLRenderer = () => "";
  if ("proxy" in config) {
    let continuePolling2 = function() {
      if (currentTimeout) {
        clearTimeout(currentTimeout);
      }
      if (pollingInterval) {
        currentTimeout = setTimeout(schemaFetcher, pollingInterval);
      }
    }, pausePolling2 = function() {
      if (currentTimeout) {
        clearTimeout(currentTimeout);
      }
    };
    const transportExecutorStack = new AsyncDisposableStack();
    const proxyExecutor = getProxyExecutor({
      config,
      configContext,
      getSchema() {
        return unifiedGraph;
      },
      onSubgraphExecuteHooks,
      transportExecutorStack,
      instrumentation: () => instrumentation
    });
    getExecutor = () => proxyExecutor;
    let currentTimeout;
    const pollingInterval = config.pollingInterval;
    let initialFetch$;
    let schemaFetcher;
    if (config.schema && typeof config.schema === "object" && "type" in config.schema) {
      const { endpoint, key } = config.schema;
      const fetcher = createSchemaFetcher({
        endpoint,
        key,
        logger: configContext.logger.child({ source: "Hive CDN" })
      });
      schemaFetcher = function fetchSchemaFromCDN() {
        pausePolling2();
        initialFetch$ = handleMaybePromise(fetcher, ({ sdl }) => {
          {
            unifiedGraph = buildSchema(sdl, {
              assumeValid: true,
              assumeValidSDL: true
            });
          }
          continuePolling2();
          return true;
        });
        return initialFetch$;
      };
    } else if (config.schema) {
      if (!isDynamicUnifiedGraphSchema(config.schema)) {
        delete config.pollingInterval;
      }
      schemaFetcher = function fetchSchema() {
        pausePolling2();
        initialFetch$ = handleMaybePromise(
          () => handleUnifiedGraphConfig(
            // @ts-expect-error TODO: what's up with type narrowing
            config.schema,
            configContext
          ),
          (schema) => {
            if (isSchema(schema)) {
              unifiedGraph = schema;
            } else if (isDocumentNode(schema)) {
              unifiedGraph = buildASTSchema(schema, {
                assumeValid: true,
                assumeValidSDL: true
              });
            } else {
              unifiedGraph = buildSchema(schema, {
                noLocation: true,
                assumeValid: true,
                assumeValidSDL: true
              });
            }
            continuePolling2();
            return true;
          }
        );
        return initialFetch$;
      };
    } else {
      schemaFetcher = function fetchSchemaWithExecutor() {
        pausePolling2();
        return handleMaybePromise(
          () => schemaFromExecutor(proxyExecutor, configContext, {
            assumeValid: true
          }),
          (schema) => {
            unifiedGraph = schema;
            continuePolling2();
            return true;
          },
          (err) => {
            configContext.logger.warn(`Failed to introspect schema`, err);
            return true;
          }
        );
      };
    }
    getSchema = () => {
      if (unifiedGraph != null) {
        return unifiedGraph;
      }
      if (initialFetch$ != null) {
        return handleMaybePromise(
          () => initialFetch$,
          () => unifiedGraph
        );
      }
      return handleMaybePromise(schemaFetcher, () => unifiedGraph);
    };
    const shouldSkipValidation = "skipValidation" in config ? config.skipValidation : false;
    const executorPlugin = {
      onValidate({ params, setResult }) {
        if (shouldSkipValidation || !params.schema) {
          setResult([]);
        }
      },
      onDispose() {
        pausePolling2();
        return transportExecutorStack.disposeAsync();
      }
    };
    unifiedGraphPlugin = executorPlugin;
    readinessChecker = () => handleMaybePromise(
      () => proxyExecutor({
        document: parse(`query ReadinessCheck { __typename }`)
      }),
      (res) => !isAsyncIterable$1(res) && !!res.data?.__typename
    );
    schemaInvalidator = () => {
      unifiedGraph = void 0;
      initialFetch$ = schemaFetcher();
    };
    subgraphInformationHTMLRenderer = () => {
      const endpoint = config.proxy.endpoint;
      const htmlParts = [];
      htmlParts.push(`<h2>Proxy Mode</h2>`);
      if (config.schema) {
        if (typeof config.schema === "object" && "type" in config.schema) {
          htmlParts.push(
            `<p>From ${config.schema.type === "hive" ? "Hive" : "Unknown"} CDN</p>`
          );
        } else if (isValidPath(config.schema) || isUrl(String(config.schema))) {
          if (isUrl(String(config.schema))) {
            htmlParts.push(
              `<p>From <a href="${config.schema}">${config.schema}</p>`
            );
          } else {
            htmlParts.push(`<p>From <code>${config.schema}</code></p>`);
          }
        } else {
          htmlParts.push(`<p>Using GraphQL Schema in Config</p>`);
        }
      }
      htmlParts.push("<br>");
      htmlParts.push(
        `<div class="var">
          <label for="endpoint">Endpoint</label>
          <code id="endpoint">${endpoint}</code>
        </div>`
      );
      if (reportingTarget) {
        htmlParts.push(
          `<br><p>Usage Reporting Sent to <u>${reportingTarget}</u></p>`
        );
      }
      return htmlParts.join("");
    };
  } else if ("subgraph" in config) {
    let getSubschemaConfig2 = function() {
      if (getSubschemaConfig$ == null) {
        getSubschemaConfig$ = handleMaybePromise(
          () => handleUnifiedGraphConfig(subgraphInConfig, configContext),
          (newUnifiedGraph) => {
            if (isSchema(newUnifiedGraph)) {
              unifiedGraph = newUnifiedGraph;
            } else if (isDocumentNode(newUnifiedGraph)) {
              unifiedGraph = buildASTSchema(newUnifiedGraph, {
                assumeValid: true,
                assumeValidSDL: true
              });
            } else {
              unifiedGraph = buildSchema(newUnifiedGraph, {
                noLocation: true,
                assumeValid: true,
                assumeValidSDL: true
              });
            }
            unifiedGraph = restoreExtraDirectives(unifiedGraph);
            subschemaConfig = {
              name: getDirectiveExtensions(unifiedGraph)?.["transport"]?.[0]?.["subgraph"],
              schema: unifiedGraph
            };
            const transportEntryMap = getTransportEntryMapUsingFusionAndFederationDirectives(
              unifiedGraph,
              config.transportEntries
            );
            const additionalTypeDefs = [];
            const stitchingDirectivesTransformer = getStitchingDirectivesTransformerForSubschema();
            const onSubgraphExecute = getOnSubgraphExecute({
              onSubgraphExecuteHooks,
              ...config.transports ? { transports: config.transports } : {},
              transportContext: configContext,
              transportEntryMap,
              getSubgraphSchema() {
                return unifiedGraph;
              },
              transportExecutorStack,
              instrumentation: () => instrumentation
            });
            subschemaConfig = handleFederationSubschema({
              subschemaConfig,
              additionalTypeDefs,
              stitchingDirectivesTransformer,
              onSubgraphExecute
            });
            unifiedGraph = wrapSchema(subschemaConfig);
            const entities = Object.keys(subschemaConfig.merge || {});
            let entitiesDef = "union _Entity";
            if (entities.length) {
              entitiesDef += ` = ${entities.join(" | ")}`;
            }
            const additionalResolvers = asArray(
              "additionalResolvers" in config ? config.additionalResolvers : []
            ).filter((r) => r != null);
            const queryTypeName = unifiedGraph.getQueryType()?.name || "Query";
            const finalTypeDefs = handleResolveToDirectives(
              parse(
                /* GraphQL */
                `
                type ${queryTypeName} {
                  ${entities.length ? "_entities(representations: [_Any!]!): [_Entity]!" : ""}
                  _service: _Service!
                }

                scalar _Any
                ${entities.length ? entitiesDef : ""}
                type _Service {
                  sdl: String
                }
              `
              ),
              additionalTypeDefs,
              additionalResolvers
            );
            additionalResolvers.push({
              [queryTypeName]: {
                _service() {
                  return {
                    sdl() {
                      if (isSchema(newUnifiedGraph)) {
                        return printSchemaWithDirectives(newUnifiedGraph);
                      }
                      if (isDocumentNode(newUnifiedGraph)) {
                        return defaultPrintFn$1(newUnifiedGraph);
                      }
                      return newUnifiedGraph;
                    }
                  };
                }
              }
            });
            if (entities.length) {
              additionalResolvers.push({
                [queryTypeName]: {
                  _entities(_root, args, context, info) {
                    if (Array.isArray(args.representations)) {
                      return args.representations.map((representation) => {
                        const typeName = representation.__typename;
                        const mergeConfig = subschemaConfig.merge?.[typeName];
                        const entryPoints = mergeConfig?.entryPoints || [
                          mergeConfig
                        ];
                        const satisfiedEntryPoint = entryPoints.find(
                          (entryPoint) => {
                            if (entryPoint?.selectionSet) {
                              const selectionSet = parseSelectionSet(
                                entryPoint.selectionSet,
                                {
                                  noLocation: true
                                }
                              );
                              return checkIfDataSatisfiesSelectionSet(
                                selectionSet,
                                representation
                              );
                            }
                            return true;
                          }
                        );
                        if (satisfiedEntryPoint) {
                          if (satisfiedEntryPoint.key) {
                            return handleMaybePromise(
                              () => batchDelegateToSchema({
                                schema: subschemaConfig,
                                ...satisfiedEntryPoint.fieldName ? {
                                  fieldName: satisfiedEntryPoint.fieldName
                                } : {},
                                key: satisfiedEntryPoint.key(representation),
                                ...satisfiedEntryPoint.argsFromKeys ? {
                                  argsFromKeys: satisfiedEntryPoint.argsFromKeys
                                } : {},
                                ...satisfiedEntryPoint.valuesFromResults ? {
                                  valuesFromResults: satisfiedEntryPoint.valuesFromResults
                                } : {},
                                context,
                                info
                              }),
                              (res) => mergeDeep([representation, res])
                            );
                          }
                          if (satisfiedEntryPoint.args) {
                            return handleMaybePromise(
                              () => delegateToSchema({
                                schema: subschemaConfig,
                                ...satisfiedEntryPoint.fieldName ? {
                                  fieldName: satisfiedEntryPoint.fieldName
                                } : {},
                                args: satisfiedEntryPoint.args(
                                  representation
                                ),
                                context,
                                info
                              }),
                              (res) => mergeDeep([representation, res])
                            );
                          }
                        }
                        return representation;
                      });
                    }
                    return [];
                  }
                }
              });
            }
            unifiedGraph = mergeSchemas({
              assumeValid: true,
              assumeValidSDL: true,
              schemas: [unifiedGraph],
              typeDefs: finalTypeDefs,
              resolvers: additionalResolvers
            });
            contextBuilder = (base) => (
              // @ts-expect-error - Typings are wrong in legacy Mesh
              Object.assign(
                // @ts-expect-error - Typings are wrong in legacy Mesh
                base,
                getInContextSDK(
                  unifiedGraph,
                  // @ts-expect-error - Typings are wrong in legacy Mesh
                  [subschemaConfig],
                  configContext.logger,
                  onDelegateHooks
                )
              )
            );
            return true;
          }
        );
      }
      return getSubschemaConfig$;
    };
    const subgraphInConfig = config.subgraph;
    let getSubschemaConfig$;
    let subschemaConfig;
    const transportExecutorStack = new AsyncDisposableStack();
    getSchema = () => handleMaybePromise(getSubschemaConfig2, () => unifiedGraph);
    schemaInvalidator = () => {
      getSubschemaConfig$ = void 0;
    };
    unifiedGraphPlugin = {
      onDispose() {
        return transportExecutorStack.disposeAsync();
      }
    };
  } else {
    let unifiedGraphFetcher;
    let supergraphLoadedPlace;
    if (typeof config.supergraph === "object" && "type" in config.supergraph) {
      if (config.supergraph.type === "hive") {
        const { endpoint, key } = config.supergraph;
        supergraphLoadedPlace = "Hive CDN <br>" + endpoint;
        const fetcher = createSupergraphSDLFetcher({
          endpoint,
          key,
          logger: configContext.logger.child({ source: "Hive CDN" }),
          // @ts-expect-error - MeshFetch is not compatible with `typeof fetch`
          fetchImplementation: configContext.fetch
        });
        unifiedGraphFetcher = () => fetcher().then(({ supergraphSdl }) => supergraphSdl);
      } else if (config.supergraph.type === "graphos") {
        const graphosFetcherContainer = createGraphOSFetcher({
          graphosOpts: config.supergraph,
          configContext,
          pollingInterval: config.pollingInterval
        });
        unifiedGraphFetcher = graphosFetcherContainer.unifiedGraphFetcher;
        supergraphLoadedPlace = graphosFetcherContainer.supergraphLoadedPlace;
      } else {
        unifiedGraphFetcher = () => {
          throw new Error(
            `Unknown supergraph configuration: ${config.supergraph}`
          );
        };
      }
    } else {
      if (!isDynamicUnifiedGraphSchema(config.supergraph)) {
        logger.debug(`Disabling polling for static supergraph`);
        delete config.pollingInterval;
      } else if (!config.pollingInterval) {
        logger.debug(
          `Polling interval not set for supergraph, if you want to get updates of supergraph, we recommend setting a polling interval`
        );
      }
      unifiedGraphFetcher = () => handleUnifiedGraphConfig(
        // @ts-expect-error TODO: what's up with type narrowing
        config.supergraph,
        configContext
      );
      if (typeof config.supergraph === "function") {
        const fnName = config.supergraph.name || "";
        supergraphLoadedPlace = `a custom loader ${fnName}`;
      } else if (typeof config.supergraph === "string") {
        supergraphLoadedPlace = config.supergraph;
      }
    }
    const unifiedGraphManager = new UnifiedGraphManager({
      getUnifiedGraph: unifiedGraphFetcher,
      onUnifiedGraphChange(newUnifiedGraph) {
        unifiedGraph = newUnifiedGraph;
        replaceSchema(newUnifiedGraph);
      },
      transports: config.transports,
      transportEntryAdditions: config.transportEntries,
      pollingInterval: config.pollingInterval,
      transportContext: configContext,
      onDelegateHooks,
      onSubgraphExecuteHooks,
      onDelegationPlanHooks,
      onDelegationStageExecuteHooks,
      additionalTypeDefs: config.additionalTypeDefs,
      additionalResolvers: config.additionalResolvers,
      instrumentation: () => instrumentation,
      batch: config.__experimental__batchDelegation
    });
    getSchema = () => unifiedGraphManager.getUnifiedGraph();
    readinessChecker = () => {
      const logger2 = configContext.logger.child("readiness");
      logger2.debug(`checking`);
      return handleMaybePromise(
        () => unifiedGraphManager.getUnifiedGraph(),
        (schema) => {
          if (!schema) {
            logger2.debug(
              `failed because supergraph has not been loaded yet or failed to load`
            );
            return false;
          }
          logger2.debug("passed");
          return true;
        },
        (err) => {
          logger2.error(
            `failed due to errors on loading supergraph:
${err.stack || err.message}`
          );
          return false;
        }
      );
    };
    schemaInvalidator = () => unifiedGraphManager.invalidateUnifiedGraph();
    contextBuilder = (base) => unifiedGraphManager.getContext(base);
    getExecutor = () => unifiedGraphManager.getExecutor();
    unifiedGraphPlugin = {
      onDispose() {
        return dispose(unifiedGraphManager);
      }
    };
    subgraphInformationHTMLRenderer = () => handleMaybePromise(
      () => handleMaybePromise(
        () => unifiedGraphManager.getTransportEntryMap(),
        (transportEntryMap) => ({
          transportEntryMap,
          loadError: void 0,
          loaded: true
        }),
        (loadError) => ({
          transportEntryMap: {},
          loadError,
          loaded: false
        })
      ),
      ({ transportEntryMap, loaded, loadError }) => {
        const htmlParts = [];
        htmlParts.push(`<h2>Supergraph Status</h2>`);
        const sourceHtmlPart = supergraphLoadedPlace ? `<div class="var">
                <label for="source">Source</label>
                <code id="source">${supergraphLoadedPlace}</code>
              </div>` : "";
        if (loaded) {
          htmlParts.push(`<p>\u2705 Loaded</p><br>`);
          htmlParts.push(sourceHtmlPart);
          if (reportingTarget) {
            htmlParts.push(
              `<br><p>Usage Reporting Sent to <u>${reportingTarget}</u></p>`
            );
          }
          htmlParts.push(`<br>`);
          htmlParts.push(`<table>`);
          htmlParts.push(
            `<tr><th>Subgraph</th><th>Transport</th><th>Location</th></tr>`
          );
          for (const subgraphName in transportEntryMap) {
            const transportEntry = transportEntryMap[subgraphName];
            htmlParts.push(`<tr>`);
            htmlParts.push(`<td>${subgraphName}</td>`);
            htmlParts.push(`<td>${transportEntry.kind}</td>`);
            if (transportEntry.location && isUrl(transportEntry.location)) {
              htmlParts.push(
                `<td><a href="${transportEntry.location}">${transportEntry.location}</a></td>`
              );
            } else {
              htmlParts.push(
                `<td><code>${transportEntry.location}</code></td>`
              );
            }
            htmlParts.push(`</tr>`);
          }
          htmlParts.push(`</table>`);
        } else if (loadError) {
          htmlParts.push(`<p>\u274C Failed</p><br>`);
          htmlParts.push(sourceHtmlPart);
          htmlParts.push(`<br>`);
          htmlParts.push(
            `<pre><code>${loadError instanceof Error ? loadError.stack : JSON.stringify(loadError, null, "  ")}</code></pre>`
          );
        } else {
          htmlParts.push(`<p>\u26A0\uFE0F Unknown</p><br>`);
          htmlParts.push(sourceHtmlPart);
        }
        return htmlParts.join("");
      }
    );
  }
  const readinessCheckPlugin = useReadinessCheck({
    endpoint: readinessCheckEndpoint,
    // @ts-expect-error PromiseLike is not compatible with Promise
    check: readinessChecker
  });
  const defaultGatewayPlugin = {
    onFetch({ setFetchFn }) {
      if (fetchAPI?.fetch) {
        setFetchFn(fetchAPI.fetch);
      }
    },
    onRequestParse() {
      return handleMaybePromise(getSchema, (schema) => {
        replaceSchema(schema);
      });
    },
    onPluginInit({ plugins, setSchema }) {
      replaceSchema = setSchema;
      onFetchHooks.splice(0, onFetchHooks.length);
      onSubgraphExecuteHooks.splice(0, onSubgraphExecuteHooks.length);
      onDelegateHooks.splice(0, onDelegateHooks.length);
      for (const plugin of plugins) {
        if (plugin.instrumentation) {
          instrumentation = instrumentation ? chain(instrumentation, plugin.instrumentation) : plugin.instrumentation;
        }
        if (plugin.onFetch) {
          onFetchHooks.push(plugin.onFetch);
        }
        if (plugin.onSubgraphExecute) {
          onSubgraphExecuteHooks.push(plugin.onSubgraphExecute);
        }
        if (plugin.onDelegate) {
          onDelegateHooks.push(plugin.onDelegate);
        }
        if (plugin.onDelegationPlan) {
          onDelegationPlanHooks.push(plugin.onDelegationPlan);
        }
        if (plugin.onDelegationStageExecute) {
          onDelegationStageExecuteHooks.push(plugin.onDelegationStageExecute);
        }
        if (plugin.onCacheGet) {
          onCacheGetHooks.push(plugin.onCacheGet);
        }
        if (plugin.onCacheSet) {
          onCacheSetHooks.push(plugin.onCacheSet);
        }
        if (plugin.onCacheDelete) {
          onCacheDeleteHooks.push(plugin.onCacheDelete);
        }
      }
    }
  };
  if (getExecutor) {
    const onExecute = ({
      setExecuteFn
    }) => handleMaybePromise(
      () => getExecutor?.(),
      (executor) => {
        if (executor) {
          const executeFn = getExecuteFnFromExecutor(executor);
          setExecuteFn(executeFn);
        }
      }
    );
    const onSubscribe = ({
      setSubscribeFn
    }) => handleMaybePromise(
      () => getExecutor?.(),
      (executor) => {
        if (executor) {
          const subscribeFn = getExecuteFnFromExecutor(executor);
          setSubscribeFn(subscribeFn);
        }
      }
    );
    defaultGatewayPlugin.onExecute = onExecute;
    defaultGatewayPlugin.onSubscribe = onSubscribe;
  }
  const productName = config.productName || "Hive Gateway";
  const productDescription = config.productDescription || "Federated GraphQL Gateway";
  const productPackageName = config.productPackageName || "@graphql-hive/gateway";
  const productLogo = config.productLogo || defaultProductLogo;
  const productLink = config.productLink || "https://the-guild.dev/graphql/hive/docs/gateway";
  let graphiqlOptionsOrFactory;
  if (config.graphiql == null || config.graphiql === true) {
    graphiqlOptionsOrFactory = {
      title: productName,
      defaultQuery: defaultQueryText
    };
  } else if (config.graphiql === false) {
    graphiqlOptionsOrFactory = false;
  } else if (typeof config.graphiql === "object") {
    graphiqlOptionsOrFactory = {
      title: productName,
      defaultQuery: defaultQueryText,
      ...config.graphiql
    };
  } else if (typeof config.graphiql === "function") {
    const userGraphiqlFactory = config.graphiql;
    graphiqlOptionsOrFactory = function graphiqlOptionsFactoryForMesh(...args) {
      return handleMaybePromise(
        () => userGraphiqlFactory(...args),
        (resolvedOpts) => {
          if (resolvedOpts === false) {
            return false;
          }
          if (resolvedOpts === true) {
            return {
              title: productName,
              defaultQuery: defaultQueryText
            };
          }
          return {
            title: productName,
            defaultQuery: defaultQueryText,
            ...resolvedOpts
          };
        }
      );
    };
  }
  let landingPageRenderer;
  if (config.landingPage == null || config.landingPage === true) {
    landingPageRenderer = (opts) => handleMaybePromise(
      subgraphInformationHTMLRenderer,
      (subgraphHtml) => new opts.fetchAPI.Response(
        landingPageHtml.replace(/__GRAPHIQL_LINK__/g, opts.graphqlEndpoint).replace(/__REQUEST_PATH__/g, opts.url.pathname).replace(/__SUBGRAPH_HTML__/g, subgraphHtml).replaceAll(/__PRODUCT_NAME__/g, productName).replaceAll(/__PRODUCT_DESCRIPTION__/g, productDescription).replaceAll(/__PRODUCT_PACKAGE_NAME__/g, productPackageName).replace(/__PRODUCT_LINK__/, productLink).replace(/__PRODUCT_LOGO__/g, productLogo),
        {
          status: 200,
          statusText: "OK",
          headers: {
            "Content-Type": "text/html"
          }
        }
      )
    );
  } else if (typeof config.landingPage === "function") {
    landingPageRenderer = config.landingPage;
  } else if (config.landingPage === false) {
    landingPageRenderer = false;
  }
  const basePlugins = [
    defaultGatewayPlugin,
    unifiedGraphPlugin,
    readinessCheckPlugin,
    registryPlugin,
    persistedDocumentsPlugin,
    useRetryOnSchemaReload({ logger })
  ];
  if (config.subgraphErrors !== false) {
    basePlugins.push(
      useSubgraphErrorPlugin(
        typeof config.subgraphErrors === "object" ? config.subgraphErrors : void 0
      )
    );
  }
  if (config.requestId !== false) {
    const reqIdPlugin = useRequestId(
      typeof config.requestId === "object" ? config.requestId : void 0
    );
    basePlugins.push(reqIdPlugin);
  }
  if (isDisposable(wrappedCache)) {
    const cacheDisposePlugin = {
      onDispose() {
        return dispose(wrappedCache);
      }
    };
    basePlugins.push(cacheDisposePlugin);
  }
  if (isDisposable(pubsub)) {
    const cacheDisposePlugin = {
      onDispose() {
        return dispose(pubsub);
      }
    };
    basePlugins.push(cacheDisposePlugin);
  }
  const extraPlugins = [];
  if (config.webhooks) {
    extraPlugins.push(useWebhooks(configContext));
  }
  if (config.responseCaching) {
    extraPlugins.push(
      // @ts-expect-error TODO: what's up with type narrowing
      useMeshResponseCache({
        ...configContext,
        ...config.responseCaching
      })
    );
  }
  if (config.contentEncoding) {
    extraPlugins.push(
      useContentEncoding(
        typeof config.contentEncoding === "object" ? config.contentEncoding : {}
      )
    );
  }
  if (config.deferStream) {
    extraPlugins.push(useDeferStream());
  }
  if (config.executionCancellation) {
    extraPlugins.push(useExecutionCancellation());
  }
  if (config.upstreamCancellation) {
    extraPlugins.push(useUpstreamCancel());
  }
  if (config.disableIntrospection) {
    extraPlugins.push(
      useDisableIntrospection(
        // @ts-expect-error - Should be fixed in the envelop plugin
        typeof config.disableIntrospection === "object" ? config.disableIntrospection : {}
      )
    );
  }
  if (config.csrfPrevention) {
    extraPlugins.push(
      useCSRFPrevention(
        typeof config.csrfPrevention === "object" ? config.csrfPrevention : {}
      )
    );
  }
  if (config.customAgent) {
    extraPlugins.push(useCustomAgent(config.customAgent));
  }
  if (config.genericAuth) {
    extraPlugins.push(useGenericAuth(config.genericAuth));
  }
  if (config.hmacSignature) {
    extraPlugins.push(useHmacUpstreamSignature(config.hmacSignature));
  }
  if (config.propagateHeaders) {
    extraPlugins.push(usePropagateHeaders(config.propagateHeaders));
  }
  if (config.upstreamTimeout) {
    extraPlugins.push(useUpstreamTimeout(config.upstreamTimeout));
  }
  if (config.upstreamRetry) {
    extraPlugins.push(useUpstreamRetry(config.upstreamRetry));
  }
  if (config.demandControl) {
    extraPlugins.push(useDemandControl(config.demandControl));
  }
  if (config.cookies) {
    extraPlugins.push(useCookies());
  }
  let isDebug = false;
  if ("level" in logger) {
    if (logger.level === "debug" || logger.level === LogLevel.debug) {
      isDebug = true;
    }
  } else {
    logger.debug(() => {
      isDebug = true;
      return "Debug mode enabled";
    });
  }
  if (isDebug) {
    extraPlugins.push(
      useSubgraphExecuteDebug(configContext),
      useFetchDebug(configContext),
      useDelegationPlanDebug(configContext),
      useCacheDebug(configContext)
    );
  }
  const yoga = createYoga({
    // @ts-expect-error Types???
    schema: unifiedGraph,
    // @ts-expect-error MeshFetch is not compatible with YogaFetch
    fetchAPI: config.fetchAPI,
    logging: logger,
    plugins: [
      ...basePlugins,
      ...extraPlugins,
      ...config.plugins?.(configContext) || []
    ],
    context({ request, params, req, connectionParams }) {
      let headers = (
        // Maybe Node-like environment
        req?.headers ? getHeadersObj(req.headers) : (
          // Fetch environment
          request?.headers ? getHeadersObj(request.headers) : (
            // Unknown environment
            {}
          )
        )
      );
      if (connectionParams) {
        headers = { ...headers, ...connectionParams };
      }
      const baseContext = {
        ...configContext,
        request,
        params,
        headers,
        connectionParams: headers
      };
      if (contextBuilder) {
        return contextBuilder(baseContext);
      }
      return baseContext;
    },
    cors: config.cors,
    graphiql: graphiqlOptionsOrFactory,
    renderGraphiQL: config.renderGraphiQL,
    batching: config.batching,
    graphqlEndpoint: config.graphqlEndpoint,
    maskedErrors: config.maskedErrors,
    healthCheckEndpoint: config.healthCheckEndpoint || "/healthcheck",
    landingPage: landingPageRenderer,
    disposeOnProcessTerminate: true
  });
  fetchAPI ||= yoga.fetchAPI;
  Object.defineProperties(yoga, {
    version: {
      get() {
        return globalThis.__VERSION__;
      }
    },
    invalidateUnifiedGraph: {
      value: schemaInvalidator,
      configurable: true
    },
    getSchema: {
      value: getSchema,
      configurable: true
    }
  });
  return yoga;
}
function isDynamicUnifiedGraphSchema(schema) {
  if (isSchema(schema)) {
    return false;
  }
  if (isDocumentNode(schema)) {
    return false;
  }
  if (typeof schema === "string") {
    if (isUrl(schema)) {
      return true;
    }
    if (isValidPath(schema)) {
      return false;
    }
    try {
      parse(schema);
      return false;
    } catch (e) {
    }
  }
  return true;
}

function useCustomFetch(fetch) {
  return {
    onFetch({ setFetchFn }) {
      setFetchFn(fetch);
    }
  };
}

const useStaticFiles = ({
  baseDir,
  staticFiles = "public"
}) => {
  return {
    onRequest({ request, url, endResponse, fetchAPI }) {
      if (request.method === "GET") {
        let relativePath = url.pathname;
        if (relativePath === "/" || !relativePath) {
          relativePath = "index.html";
        }
        const absoluteStaticFilesPath = path.join(baseDir, staticFiles);
        const absolutePath = path.join(absoluteStaticFilesPath, relativePath);
        if (absolutePath.startsWith(absoluteStaticFilesPath)) {
          return pathExists(absolutePath).then((exists) => {
            if (exists) {
              const readStream = fs.createReadStream(absolutePath);
              endResponse(
                new fetchAPI.Response(readStream, {
                  status: 200
                })
              );
            }
          });
        }
      }
    }
  };
};

function getGraphQLWSOptions(gwRuntime, onContext) {
  return {
    execute: (args) => args.rootValue.execute(args),
    subscribe: (args) => args.rootValue.subscribe(args),
    onSubscribe: async (ctx, idOrMessage, payloadOrUndefined) => {
      let payload;
      if (typeof idOrMessage === "string") {
        payload = payloadOrUndefined;
      } else {
        payload = idOrMessage.payload;
      }
      const { schema, execute: execute2, subscribe: subscribe2, contextFactory, parse, validate } = gwRuntime.getEnveloped({
        connectionParams: ctx.connectionParams,
        waitUntil: gwRuntime.waitUntil,
        ...await onContext(ctx)
      });
      const args = {
        schema: schema || await gwRuntime.getSchema(),
        operationName: payload.operationName,
        document: parse(payload.query),
        variableValues: payload.variables,
        contextValue: await contextFactory(),
        rootValue: {
          execute: execute2,
          subscribe: subscribe2
        }
      };
      if (args.schema) {
        const errors = validate(args.schema, args.document);
        if (errors.length) return errors;
      }
      return args;
    }
  };
}

export { createGatewayRuntime, getDefaultLogger, getGraphQLWSOptions, getProxyExecutor, handleLoggingConfig, useCustomFetch, usePropagateHeaders, useStaticFiles, useUpstreamRetry, useUpstreamTimeout };