UNPKG

@graphql-hive/router-runtime

Version:
2,035 lines • 64.9 kB
'use strict';

var fusionRuntime = require('@graphql-mesh/fusion-runtime');
var transportCommon = require('@graphql-mesh/transport-common');
var executorCommon = require('@graphql-tools/executor-common');
var federation = require('@graphql-tools/federation');
var promiseHelpers = require('@whatwg-node/promise-helpers');
var graphql = require('graphql');
var core = require('@envelop/core');
var executor = require('@graphql-tools/executor');
var utils = require('@graphql-tools/utils');
var utils$1 = require('@graphql-mesh/utils');
var delegate = require('@graphql-tools/delegate');

const queryPlanForExecutionRequestContext = /* @__PURE__ */ new WeakMap();
function getLazyValue(factory) {
  let _value;
  return function() {
    if (_value == null) {
      _value = factory();
    }
    return _value;
  };
}
function getLazyFactory(factory) {
  let _value;
  return function(...args) {
    if (!_value) {
      _value = factory();
    }
    return _value(...args);
  };
}
function onSubgraphExecuteWithTransforms(subgraphName, executionRequest, onSubgraphExecute, getSubschema) {
  const subschema = getSubschema(subgraphName);
  if (subschema.transforms?.length) {
    const transforms = subschema.transforms;
    const transformationContext = /* @__PURE__ */ Object.create(null);
    const delegationContext = void 0;
    for (const transform of transforms) {
      if (transform.transformRequest) {
        executionRequest = transform.transformRequest(
          executionRequest,
          delegationContext,
          transformationContext
        );
      }
    }
    return handleMaybePromiseMaybeAsyncIterable(
      () => onSubgraphExecute(subgraphName, executionRequest),
      (executionResult) => {
        for (const transform of transforms.toReversed()) {
          if (transform.transformResult) {
            executionResult = transform.transformResult(
              executionResult,
              delegationContext,
              transformationContext
            );
          }
        }
        return executionResult;
      }
    );
  }
  return onSubgraphExecute(subgraphName, executionRequest);
}
function handleMaybePromiseMaybeAsyncIterable(executor, mapper, errorMapper) {
  return promiseHelpers.handleMaybePromise(
    executor,
    (result$) => {
      if (utils.isAsyncIterable(result$)) {
        return promiseHelpers.mapAsyncIterator(result$, mapper, errorMapper);
      }
      return mapper(result$);
    },
    errorMapper
  );
}

function isEntityRepresentation(obj) {
  return obj?.__typename != null;
}
function executeQueryPlan({
  queryPlan,
  executionRequest,
  onSubgraphExecute,
  supergraphSchema
}) {
  const node = queryPlan.node;
  if (!node) {
    throw new Error("Query plan has no root node.");
  }
  const executionContext = createQueryPlanExecutionContext({
    supergraphSchema,
    executionRequest,
    onSubgraphExecute
  });
  return handleMaybePromiseMaybeAsyncIterable(
    () => executePlanNode(node, executionContext),
    () => {
      const executionResult = {};
      if (Object.keys(executionContext.data).length > 0) {
        executionResult.data = projectDataByOperation(executionContext);
      }
      if (executionContext.errors.length > 0) {
        executionResult.errors = executionContext.errors;
      }
      return executionResult;
    }
  );
}
const globalEmpty = {};
function createQueryPlanExecutionContext({
  supergraphSchema,
  executionRequest,
  onSubgraphExecute
}) {
  const fragments = executor.getFragmentsFromDocument(executionRequest.document);
  const operation = utils.getOperationASTFromRequest(executionRequest);
  let variableValues = executionRequest.variables;
  if (operation.variableDefinitions) {
    const variableValuesResult = executor.getVariableValues(
      supergraphSchema,
      operation.variableDefinitions,
      variableValues || globalEmpty
    );
    if (variableValuesResult.errors?.length) {
      if (variableValuesResult.errors.length === 1) {
        throw variableValuesResult.errors[0];
      }
      if (variableValuesResult.errors.length > 1) {
        throw new AggregateError(
          variableValuesResult.errors,
          "Variable parsing error"
        );
      }
    }
    if (variableValuesResult.coerced) {
      variableValues = variableValuesResult.coerced;
    }
  }
  return {
    supergraphSchema,
    operation,
    fragments,
    variableValues,
    data: {},
    errors: [],
    onSubgraphExecute,
    executionRequest
  };
}
function normalizeFlattenNodePath(path) {
  const normalized = [];
  for (const segment of path) {
    if (segment === "@") {
      normalized.push({ kind: "List" });
      continue;
    } else if ("Field" in segment) {
      normalized.push({ kind: "Field", name: segment.Field });
    } else if ("TypeCondition" in segment) {
      normalized.push({ kind: "Cast", typeCondition: segment.TypeCondition });
    } else {
      throw new Error(
        `Unsupported flatten path segment received from query planner: ${JSON.stringify(segment)}`
      );
    }
  }
  return normalized;
}
function collectFlattenEntities(source, pathSegments, supergraphSchema) {
  const entities = [];
  const activePath = [];
  traverseFlattenPath(
    source,
    pathSegments,
    supergraphSchema,
    activePath,
    (value, path) => {
      if (Array.isArray(value)) {
        for (let index = 0; index < value.length; index++) {
          const item = value[index];
          if (item && typeof item === "object") {
            path.push(index);
            entities.push({
              entity: item,
              path: path.slice()
            });
            path.pop();
          }
        }
        return;
      }
      if (value && typeof value === "object") {
        entities.push({
          entity: value,
          path: path.slice()
        });
      }
    }
  );
  return entities;
}
function traverseFlattenPath(current, remainingPath, supergraphSchema, path, callback) {
  if (current == null) {
    return;
  }
  const [segment, ...rest] = remainingPath;
  if (!segment) {
    callback(current, path);
    return;
  }
  switch (segment.kind) {
    case "Field": {
      if (Array.isArray(current)) {
        for (const item of current) {
          traverseFlattenPath(
            item,
            remainingPath,
            supergraphSchema,
            path,
            callback
          );
        }
        return;
      }
      if (typeof current === "object") {
        path.push(segment.name);
        const next = current[segment.name];
        traverseFlattenPath(next, rest, supergraphSchema, path, callback);
        path.pop();
      }
      return;
    }
    case "List": {
      if (Array.isArray(current)) {
        for (let index = 0; index < current.length; index++) {
          path.push(index);
          traverseFlattenPath(
            current[index],
            rest,
            supergraphSchema,
            path,
            callback
          );
          path.pop();
        }
      }
      return;
    }
    case "Cast": {
      if (Array.isArray(current)) {
        for (const item of current) {
          traverseFlattenPath(
            item,
            remainingPath,
            supergraphSchema,
            path,
            callback
          );
        }
        return;
      }
      if (typeof current === "object") {
        const value = current;
        const candidateTypenames = typeof value.__typename === "string" ? [value.__typename] : segment.typeCondition;
        if (candidateTypenames.some(
          (typeName) => entitySatisfiesTypeCondition(
            supergraphSchema,
            typeName,
            segment.typeCondition
          )
        )) {
          traverseFlattenPath(current, rest, supergraphSchema, path, callback);
        }
      }
    }
  }
}
function prepareFlattenContext(flattenNode, executionContext) {
  if (!flattenNode.node || flattenNode.node.kind !== "Fetch") {
    return null;
  }
  const fetchNode = flattenNode.node;
  const requires = fetchNode.requires;
  if (!requires || requires.length === 0) {
    return null;
  }
  const pathSegments = normalizeFlattenNodePath(flattenNode.path);
  const entityLocations = collectFlattenEntities(
    executionContext.data,
    pathSegments,
    executionContext.supergraphSchema
  );
  if (entityLocations.length === 0) {
    return null;
  }
  const entityRefs = [];
  const entityPaths = [];
  const representationOrder = [];
  const dedupedRepresentations = [];
  const representationKeyToIndex = /* @__PURE__ */ new Map();
  for (const location of entityLocations) {
    const entityRef = location.entity;
    if (!isEntityRepresentation(entityRef)) {
      continue;
    }
    let representation = projectRequires(
      requires,
      entityRef,
      executionContext.supergraphSchema
    );
    if (!representation || Array.isArray(representation)) {
      continue;
    }
    representation.__typename ??= entityRef.__typename;
    if (fetchNode.inputRewrites?.length) {
      representation = applyInputRewrites(
        representation,
        fetchNode.inputRewrites,
        executionContext.supergraphSchema
      );
    }
    const dedupeKey = stableStringify(representation);
    let dedupIndex = representationKeyToIndex.get(dedupeKey);
    if (dedupIndex === void 0) {
      dedupIndex = dedupedRepresentations.length;
      representationKeyToIndex.set(dedupeKey, dedupIndex);
      dedupedRepresentations.push(representation);
    }
    entityRefs.push(entityRef);
    entityPaths.push(location.path);
    representationOrder.push(dedupIndex);
  }
  if (dedupedRepresentations.length === 0) {
    return null;
  }
  const errorPath = pathSegments.filter(
    (segment) => segment.kind === "Field"
  ).map((segment) => segment.name);
  return {
    entityRefs,
    dedupedRepresentations,
    entityPaths,
    representationOrder,
    errorPath: errorPath.length ? errorPath : void 0
  };
}
function prepareBatchFetchContext(batchFetchNode, executionContext) {
  const byAlias = /* @__PURE__ */ new Map();
  const representationsByVariableName = /* @__PURE__ */ new Map();
  for (const alias of batchFetchNode.entityBatch.aliases) {
    const requires = alias.requires;
    if (!requires || requires.length === 0) {
      continue;
    }
    const pathStates = [];
    const entityPathsByRepresentationIndex = /* @__PURE__ */ new Map();
    const representationsVariableName = alias.representationsVariableName;
    let variableBatchState = representationsByVariableName.get(
      representationsVariableName
    );
    if (!variableBatchState) {
      variableBatchState = {
        representations: [],
        identityToEntityIndex: /* @__PURE__ */ new Map()
      };
      representationsByVariableName.set(
        representationsVariableName,
        variableBatchState
      );
    }
    for (const path of alias.paths) {
      const normalizedPath = normalizeFlattenNodePath(path);
      const entityLocations = collectFlattenEntities(
        executionContext.data,
        normalizedPath,
        executionContext.supergraphSchema
      );
      const entityRefs = [];
      const entityPaths = [];
      const representationIndexByTarget = [];
      for (const location of entityLocations) {
        const entityRef = location.entity;
        if (!isEntityRepresentation(entityRef)) {
          continue;
        }
        let representation = projectRequires(
          requires,
          entityRef,
          executionContext.supergraphSchema
        );
        if (!representation || Array.isArray(representation)) {
          continue;
        }
        representation.__typename ??= entityRef.__typename;
        if (alias.inputRewrites?.length) {
          representation = applyInputRewrites(
            representation,
            alias.inputRewrites,
            executionContext.supergraphSchema
          );
        }
        const identity = stableStringify(representation);
        let dedupIndex = variableBatchState.identityToEntityIndex.get(identity);
        if (dedupIndex == null) {
          dedupIndex = variableBatchState.representations.length;
          variableBatchState.identityToEntityIndex.set(identity, dedupIndex);
          variableBatchState.representations.push(representation);
        }
        entityRefs.push(entityRef);
        entityPaths.push(location.path);
        representationIndexByTarget.push(dedupIndex);
        const pathsForRepresentation = entityPathsByRepresentationIndex.get(dedupIndex) ?? [];
        pathsForRepresentation.push(location.path);
        entityPathsByRepresentationIndex.set(
          dedupIndex,
          pathsForRepresentation
        );
      }
      pathStates.push({
        entityRefs,
        entityPaths,
        representationIndexByTarget
      });
    }
    byAlias.set(alias.alias, {
      alias: alias.alias,
      pathStates,
      entityPathsByRepresentationIndex,
      outputRewrites: alias.outputRewrites
    });
  }
  const hasRepresentations = Array.from(
    representationsByVariableName.values()
  ).some((state) => state.representations.length > 0);
  if (!hasRepresentations) {
    return null;
  }
  return {
    byAlias,
    representationsByVariableName
  };
}
function buildBatchFetchVariables(batchContext, selectedVariables) {
  let variablesForFetch;
  if (selectedVariables) {
    variablesForFetch = { ...selectedVariables };
  }
  for (const [
    variableName,
    state
  ] of batchContext.representationsByVariableName.entries()) {
    const targetVariables = variablesForFetch ?? /* @__PURE__ */ Object.create(null);
    if (!variablesForFetch) {
      variablesForFetch = targetVariables;
    }
    targetVariables[variableName] = state.representations;
  }
  return variablesForFetch;
}
function applyBatchAliasEntities(returnedEntities, aliasContext) {
  for (const pathContext of aliasContext.pathStates) {
    const { entityRefs, representationIndexByTarget } = pathContext;
    for (let index = 0; index < entityRefs.length; index++) {
      const target = entityRefs[index];
      const dedupIndex = representationIndexByTarget[index];
      if (dedupIndex == null) {
        continue;
      }
      const entity = returnedEntities[dedupIndex];
      if (!target || !entity) {
        continue;
      }
      Object.assign(target, utils.mergeDeep([target, entity], false, true, true));
    }
  }
}
function normalizeBatchFetchErrors(errors, batchContext) {
  if (!errors.length) {
    return [];
  }
  const relocated = [];
  for (const error of errors) {
    const errorPath = error.path;
    if (!errorPath || errorPath.length === 0) {
      relocated.push(error);
      continue;
    }
    const aliasName = errorPath[0];
    if (typeof aliasName !== "string") {
      relocated.push(error);
      continue;
    }
    const aliasContext = batchContext.byAlias.get(aliasName);
    if (!aliasContext) {
      relocated.push(error);
      continue;
    }
    const entityIndex = errorPath[1];
    if (typeof entityIndex !== "number") {
      relocated.push(error);
      continue;
    }
    const mappedPaths = aliasContext.entityPathsByRepresentationIndex.get(entityIndex);
    if (!mappedPaths?.length) {
      relocated.push(error);
      continue;
    }
    const tail = errorPath.slice(2);
    for (const mappedPath of mappedPaths) {
      relocated.push(utils.relocatedError(error, [...mappedPath, ...tail]));
    }
  }
  return relocated;
}
function executeBatchFetchPlanNode(batchFetchNode, executionContext, batchContext) {
  const selectedVariables = selectFetchVariables(
    executionContext.variableValues,
    batchFetchNode.variableUsages
  );
  const variablesForFetch = buildBatchFetchVariables(
    batchContext,
    selectedVariables
  );
  return handleMaybePromiseMaybeAsyncIterable(
    () => executionContext.onSubgraphExecute(batchFetchNode.serviceName, {
      document: getDocumentNodeOfFetchingNode(batchFetchNode),
      variables: variablesForFetch,
      operationType: batchFetchNode.operationKind ?? executionContext.operation.operation,
      operationName: batchFetchNode.operationName,
      extensions: executionContext.executionRequest.extensions,
      rootValue: executionContext.executionRequest.rootValue,
      context: executionContext.executionRequest.context,
      subgraphName: batchFetchNode.serviceName,
      info: executionContext.executionRequest.info,
      signal: executionContext.executionRequest.signal
    }),
    (fetchResult) => {
      if (fetchResult.errors?.length) {
        executionContext.errors.push(
          ...normalizeBatchFetchErrors(fetchResult.errors, batchContext)
        );
      }
      const responseData = fetchResult.data;
      if (!responseData || typeof responseData !== "object") {
        return;
      }
      for (const [aliasName, aliasContext] of batchContext.byAlias.entries()) {
        let aliasData = responseData[aliasName];
        if (!aliasData) {
          continue;
        }
        if (aliasContext.outputRewrites?.length) {
          aliasData = applyOutputRewrites(
            aliasData,
            aliasContext.outputRewrites,
            executionContext.supergraphSchema
          );
        }
        if (Array.isArray(aliasData)) {
          applyBatchAliasEntities(
            aliasData,
            aliasContext
          );
        }
      }
      return;
    },
    (error) => handleSubgraphExecutionError(
      error,
      executionContext,
      batchFetchNode.serviceName
    )
  );
}
function executeFetchPlanNode(fetchNode, executionContext, state) {
  const flattenState = state?.flatten;
  let representationTargets = flattenState?.entityRefs ?? state?.representations;
  let preparedRepresentations;
  if (flattenState) {
    if (!flattenState.dedupedRepresentations.length) {
      return;
    }
    preparedRepresentations = flattenState.dedupedRepresentations;
  } else if (representationTargets?.length) {
    const requires = fetchNode.requires;
    if (requires && representationTargets.length) {
      representationTargets = representationTargets.filter(
        (entity) => requires.some(
          (requiresNode) => entity && entitySatisfiesTypeCondition(
            executionContext.supergraphSchema,
            entity.__typename,
            requiresNode.kind === "InlineFragment" ? requiresNode.typeCondition : void 0
          )
        )
      );
    }
    if (!representationTargets || representationTargets.length === 0) {
      return;
    }
    const nextTargets = [];
    const payloads = [];
    for (const entity of representationTargets) {
      let projection = fetchNode.requires ? projectRequires(
        fetchNode.requires,
        entity,
        executionContext.supergraphSchema
      ) : entity;
      if (!projection || Array.isArray(projection)) {
        continue;
      }
      projection.__typename ??= entity.__typename;
      if (fetchNode.inputRewrites?.length) {
        projection = applyInputRewrites(
          projection,
          fetchNode.inputRewrites,
          executionContext.supergraphSchema
        );
      }
      payloads.push(projection);
      nextTargets.push(entity);
    }
    if (!payloads.length) {
      return;
    }
    representationTargets = nextTargets;
    preparedRepresentations = payloads;
  }
  const selectedVariables = selectFetchVariables(
    executionContext.variableValues,
    fetchNode.variableUsages
  );
  let variablesForFetch;
  if (preparedRepresentations?.length) {
    variablesForFetch = {
      representations: preparedRepresentations
    };
  }
  if (selectedVariables) {
    variablesForFetch = variablesForFetch ? { ...selectedVariables, ...variablesForFetch } : { ...selectedVariables };
  }
  const defaultErrorPath = state?.errorPath ?? state?.flatten?.errorPath ?? getDefaultErrorPath(fetchNode);
  return handleMaybePromiseMaybeAsyncIterable(
    () => executionContext.onSubgraphExecute(fetchNode.serviceName, {
      document: getDocumentNodeOfFetchingNode(fetchNode),
      variables: variablesForFetch,
      operationType: fetchNode.operationKind ?? executionContext.operation.operation,
      operationName: fetchNode.operationName,
      extensions: executionContext.executionRequest.extensions,
      rootValue: executionContext.executionRequest.rootValue,
      context: executionContext.executionRequest.context,
      subgraphName: fetchNode.serviceName,
      info: executionContext.executionRequest.info,
      signal: executionContext.executionRequest.signal
    }),
    (fetchResult) => {
      if (fetchResult.errors?.length) {
        const normalizedErrors = normalizeFetchErrors(fetchResult.errors, {
          fetchNode,
          state,
          defaultPath: defaultErrorPath
        });
        if (normalizedErrors.length) {
          executionContext.errors.push(...normalizedErrors);
        }
      }
      const responseData = fetchNode.outputRewrites ? applyOutputRewrites(
        fetchResult.data,
        fetchNode.outputRewrites,
        executionContext.supergraphSchema
      ) : fetchResult.data;
      if (!responseData) {
        return;
      }
      if (flattenState && flattenState.entityRefs.length) {
        const returnedEntities = responseData._entities;
        if (Array.isArray(returnedEntities)) {
          mergeFlattenEntities(returnedEntities, flattenState);
        }
        return;
      }
      if (representationTargets?.length && responseData._entities) {
        const returnedEntities = responseData._entities;
        for (let index = 0; index < returnedEntities.length; index++) {
          const entity = returnedEntities[index];
          const target = representationTargets[index];
          if (target && entity) {
            Object.assign(
              target,
              utils.mergeDeep([target, entity], false, true, true)
            );
          }
        }
        return;
      }
      if (executionContext.operation.operation === "subscription") {
        executionContext.data = responseData;
      } else {
        Object.assign(
          executionContext.data,
          utils.mergeDeep([executionContext.data, responseData], false, true, true)
        );
      }
      return;
    },
    (error) => handleSubgraphExecutionError(
      error,
      executionContext,
      fetchNode.serviceName,
      defaultErrorPath
    )
  );
}
function handleSubgraphExecutionError(error, executionContext, serviceName, path) {
  let graphQLError;
  if (error instanceof graphql.GraphQLError) {
    graphQLError = error;
  } else {
    graphQLError = utils.createGraphQLError(error.message, {
      originalError: error,
      extensions: {
        code: "DOWNSTREAM_SERVICE_ERROR",
        serviceName
      },
      path
    });
  }
  executionContext.errors.push(graphQLError);
}
function selectFetchVariables(variableValues, variableUsages) {
  if (!variableValues || !variableUsages || variableUsages.length === 0) {
    return void 0;
  }
  const selected = /* @__PURE__ */ Object.create(null);
  let hasValue = false;
  for (const variableName of variableUsages) {
    if (Object.prototype.hasOwnProperty.call(variableValues, variableName)) {
      selected[variableName] = variableValues[variableName];
      hasValue = true;
    }
  }
  return hasValue ? selected : void 0;
}
function normalizeFetchErrors(errors, options) {
  if (!errors.length) {
    return [];
  }
  const { fetchNode, state } = options;
  const flattenState = state?.flatten;
  const fallbackPath = options.defaultPath ?? getDefaultErrorPath(fetchNode);
  if (!flattenState) {
    return errors.map(
      (error) => error.path || !fallbackPath ? error : utils.relocatedError(error, fallbackPath)
    );
  }
  const entityPathMap = buildFlattenEntityPathMap(flattenState);
  const relocated = [];
  for (const error of errors) {
    const errorPath = error.path;
    if (errorPath) {
      const entityIndexPosition = errorPath.indexOf("_entities");
      if (entityIndexPosition !== -1) {
        const dedupIndex = errorPath[entityIndexPosition + 1];
        if (typeof dedupIndex === "number") {
          const mappedPaths = entityPathMap.get(dedupIndex);
          if (mappedPaths && mappedPaths.length) {
            const tail = errorPath.slice(entityIndexPosition + 2);
            for (const mappedPath of mappedPaths) {
              relocated.push(utils.relocatedError(error, [...mappedPath, ...tail]));
            }
            continue;
          }
        }
      }
    }
    if (fallbackPath) {
      relocated.push(utils.relocatedError(error, fallbackPath));
    } else {
      relocated.push(error);
    }
  }
  return relocated;
}
function buildFlattenEntityPathMap(flattenState) {
  const map = /* @__PURE__ */ new Map();
  flattenState.representationOrder.forEach((dedupIndex, index) => {
    const existing = map.get(dedupIndex);
    if (existing) {
      existing.push(flattenState.entityPaths[index]);
    } else {
      map.set(dedupIndex, [flattenState.entityPaths[index]]);
    }
  });
  return map;
}
function mergeFlattenEntities(returnedEntities, flattenState) {
  const { entityRefs, representationOrder } = flattenState;
  for (let index = 0; index < entityRefs.length; index++) {
    const target = entityRefs[index];
    const dedupIndex = representationOrder[index];
    const entity = returnedEntities[dedupIndex];
    if (!target || !entity) {
      continue;
    }
    Object.assign(target, utils.mergeDeep([target, entity], false, true, true));
  }
}
function applyInputRewrites(representation, rewrites, supergraphSchema) {
  let current = representation;
  for (const rewrite of rewrites) {
    const normalizedRewrite = normalizeRewrite(rewrite);
    if (!normalizedRewrite) {
      continue;
    }
    switch (normalizedRewrite.kind) {
      case "ValueSetter":
        current = applyValueSetter(
          current,
          normalizedRewrite.path,
          normalizedRewrite.setValueTo,
          supergraphSchema
        );
        break;
      case "KeyRenamer":
        applyKeyRenamer(
          current,
          normalizedRewrite.path,
          normalizedRewrite.renameKeyTo,
          supergraphSchema
        );
        break;
    }
  }
  return current;
}
function applyOutputRewrites(data, rewrites, supergraphSchema) {
  let current = data;
  if (!current) {
    return current;
  }
  for (const rewrite of rewrites) {
    const normalizedRewrite = normalizeRewrite(rewrite);
    if (!normalizedRewrite) {
      continue;
    }
    switch (normalizedRewrite.kind) {
      case "KeyRenamer":
        applyKeyRenamer(
          current,
          normalizedRewrite.path,
          normalizedRewrite.renameKeyTo,
          supergraphSchema
        );
        break;
      case "ValueSetter":
        current = applyValueSetter(
          current,
          normalizedRewrite.path,
          normalizedRewrite.setValueTo,
          supergraphSchema
        );
        break;
    }
  }
  return current;
}
const getDocumentNodeOfFetchingNode = utils.memoize1(
  function getDocumentNodeOfFetchNode(fetchingNode) {
    const doc = graphql.parse(fetchingNode.operation, { noLocation: true });
    core.documentStringMap.set(doc, fetchingNode.operation);
    return doc;
  }
);
const getDefaultErrorPath = utils.memoize1(function getDefaultErrorPath2(fetchNode) {
  const document = getDocumentNodeOfFetchingNode(fetchNode);
  const operationAst = utils.getOperationASTFromDocument(
    document,
    fetchNode.operationName
  );
  if (!operationAst) {
    return [];
  }
  const rootSelection = operationAst.selectionSet.selections.find(
    (selection) => selection.kind === graphql.Kind.FIELD
  );
  if (!rootSelection) {
    return [];
  }
  const responseKey = rootSelection.alias?.value ?? rootSelection.name.value;
  return responseKey ? [responseKey] : [];
});
function stableStringify(value) {
  if (value == null) {
    return "null";
  }
  if (value === true) {
    return "true";
  }
  if (value === false) {
    return "false";
  }
  const type = typeof value;
  if (type === "number") {
    return value.toString();
  }
  if (type === "bigint") {
    return value.toString();
  }
  if (type === "string") {
    return JSON.stringify(value);
  }
  if (Array.isArray(value)) {
    return `[${value.map((item) => stableStringify(item)).join(",")}]`;
  }
  if (type === "object") {
    const entries = Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(
      ([key, entryValue]) => `${stableStringify(key)}:${stableStringify(entryValue)}`
    );
    return `{${entries.join(",")}}`;
  }
  return "null";
}
function executePlanNode(planNode, executionContext, state) {
  switch (planNode.kind) {
    case "Sequence": {
      let pending = null;
      let nextState = state;
      for (const node of planNode.nodes) {
        const currentState = nextState;
        nextState = void 0;
        pending = handleMaybePromiseMaybeAsyncIterable(
          () => pending,
          () => executePlanNode(node, executionContext, currentState)
        );
      }
      return pending;
    }
    case "Parallel": {
      const promises = [];
      planNode.nodes.forEach((node, index) => {
        const maybePromise = executePlanNode(
          node,
          executionContext,
          index === 0 ? state : void 0
        );
        if (promiseHelpers.isPromise(maybePromise)) {
          promises.push(maybePromise);
        }
      });
      if (promises.length === 1) {
        return promises[0];
      }
      if (promises.length === 0) {
        return;
      }
      return Promise.all(promises);
    }
    case "Flatten": {
      const flattenContext = prepareFlattenContext(planNode, executionContext);
      if (!flattenContext) {
        return;
      }
      const errorPath = flattenContext.errorPath && flattenContext.errorPath.length ? [...flattenContext.errorPath] : void 0;
      return executePlanNode(planNode.node, executionContext, {
        representations: flattenContext.entityRefs,
        errorPath,
        flatten: flattenContext
      });
    }
    case "Fetch": {
      return executeFetchPlanNode(planNode, executionContext, state);
    }
    case "BatchFetch": {
      const batchContext = prepareBatchFetchContext(planNode, executionContext);
      if (!batchContext) {
        return;
      }
      return executeBatchFetchPlanNode(
        planNode,
        executionContext,
        batchContext
      );
    }
    case "Condition": {
      const conditionValue = executionContext.variableValues?.[planNode.condition];
      if (conditionValue === true) {
        if (planNode.ifClause) {
          return executePlanNode(planNode.ifClause, executionContext);
        }
      } else if (planNode.elseClause) {
        return executePlanNode(planNode.elseClause, executionContext);
      }
      break;
    }
    case "Subscription": {
      return executeFetchPlanNode(planNode.primary, executionContext);
    }
    default:
      throw new Error(`Invalid plan node: ${JSON.stringify(planNode)}`);
  }
}
function normalizeRewrite(rewrite) {
  if ("kind" in rewrite && rewrite.kind === "ValueSetter") {
    return {
      ...rewrite,
      path: normalizeRewritePath(rewrite.path)
    };
  }
  if ("ValueSetter" in rewrite) {
    return {
      kind: "ValueSetter",
      path: normalizeRewritePath(rewrite.ValueSetter?.path),
      setValueTo: rewrite.ValueSetter?.setValueTo
    };
  }
  if ("KeyRenamer" in rewrite) {
    return {
      kind: "KeyRenamer",
      path: normalizeRewritePath(rewrite.KeyRenamer?.path),
      renameKeyTo: rewrite.KeyRenamer?.renameKeyTo
    };
  }
  throw new Error(`Unsupported fetch node rewrite: ${JSON.stringify(rewrite)}`);
}
function normalizeRewritePath(path) {
  const normalized = [];
  for (const segment of path) {
    if ("TypenameEquals" in segment) {
      normalized.push(`... on ${segment.TypenameEquals}`);
    } else if ("Key" in segment) {
      normalized.push(segment.Key);
    } else {
      throw new Error(
        `Unsupported fetch node path segment: ${JSON.stringify(segment)}`
      );
    }
  }
  return normalized;
}
function applyKeyRenamer(entityRepresentation, path, renameKeyTo, supergraphSchema) {
  const keyProp = path[0];
  if (!keyProp) {
    throw new Error("Invalid key prop");
  }
  const nextPath = path.slice(1);
  if (keyProp.startsWith("... on")) {
    const typeCondition = keyProp.split("... on ")[1];
    if (isEntityRepresentation(entityRepresentation) && typeCondition && !entitySatisfiesTypeCondition(
      supergraphSchema,
      entityRepresentation.__typename,
      typeCondition
    )) {
      return;
    }
    return applyKeyRenamer(
      entityRepresentation,
      nextPath,
      renameKeyTo,
      supergraphSchema
    );
  }
  if (path.length === 1) {
    entityRepresentation[renameKeyTo] = entityRepresentation[keyProp];
    delete entityRepresentation[keyProp];
    return;
  }
  const nextData = entityRepresentation[keyProp];
  if (nextData == null) {
    return;
  }
  if (Array.isArray(nextData)) {
    return nextData.map(
      (item) => applyKeyRenamer(item, nextPath, renameKeyTo, supergraphSchema)
    );
  }
  return applyKeyRenamer(nextData, nextPath, renameKeyTo, supergraphSchema);
}
function applyValueSetter(data, path, setValueTo, supergraphSchema) {
  if (Array.isArray(data)) {
    return data.map(
      (item) => applyValueSetter(item, path, setValueTo, supergraphSchema)
    );
  }
  const keyProp = path[0];
  if (!keyProp) {
    return setValueTo;
  }
  const nextPath = path.slice(1);
  if (keyProp.startsWith("... on")) {
    const typeCondition = keyProp.split("... on ")[1];
    if (!typeCondition) {
      throw new Error("Invalid type condition");
    }
    if (isEntityRepresentation(data) && !entitySatisfiesTypeCondition(
      supergraphSchema,
      data.__typename,
      typeCondition
    )) {
      return data;
    }
    return applyValueSetter(data, nextPath, setValueTo, supergraphSchema);
  }
  if (path.length === 1) {
    const existingValue = data[keyProp];
    if (existingValue === setValueTo) {
      return data;
    }
    return {
      ...data,
      [keyProp]: setValueTo
    };
  }
  const nextData = data[keyProp];
  if (nextData == null) {
    return data;
  }
  return {
    ...data,
    [keyProp]: applyValueSetter(
      nextData,
      nextPath,
      setValueTo,
      supergraphSchema
    )
  };
}
function entitySatisfiesTypeCondition(supergraphSchema, typeNameInEntity, typeConditionInInlineFragment) {
  if (!typeConditionInInlineFragment) {
    return false;
  }
  const normalizedTypeConditions = Array.isArray(typeConditionInInlineFragment) ? typeConditionInInlineFragment : [typeConditionInInlineFragment];
  if (normalizedTypeConditions.includes(typeNameInEntity)) {
    return true;
  }
  const entityType = supergraphSchema.getType(typeNameInEntity);
  if (!graphql.isObjectType(entityType)) {
    return false;
  }
  for (const typeCondition of normalizedTypeConditions) {
    const conditionType = supergraphSchema.getType(typeCondition);
    if (graphql.isAbstractType(conditionType) && supergraphSchema.isSubType(conditionType, entityType)) {
      return true;
    }
  }
  return false;
}
function projectSelectionSet(data, selectionSet, type, executionContext) {
  if (data == null) {
    return data;
  }
  if (Array.isArray(data)) {
    return data.map(
      (item) => projectSelectionSet(item, selectionSet, type, executionContext)
    );
  }
  const parentType = isEntityRepresentation(data) ? executionContext.supergraphSchema.getType(data.__typename) : type;
  if (!graphql.isObjectType(parentType) && !graphql.isInterfaceType(parentType)) {
    return null;
  }
  if (graphql.isObjectType(parentType)) {
    const inaccessibleDirective = parentType.astNode?.directives?.find(
      (directive) => directive.name.value === "inaccessible"
    );
    if (inaccessibleDirective) {
      return null;
    }
  }
  const result = {};
  selectionLoop: for (const selection of selectionSet.selections) {
    if (selection.directives?.length) {
      for (const directiveNode of selection.directives) {
        const ifArg = directiveNode.arguments?.find(
          (arg) => arg.name.value === "if"
        );
        if (directiveNode.name.value === "skip") {
          if (ifArg) {
            const ifValueNode = ifArg.value;
            if (ifValueNode.kind === graphql.Kind.VARIABLE) {
              const variableName = ifValueNode.name.value;
              if (executionContext.variableValues?.[variableName]) {
                continue selectionLoop;
              }
            } else if (ifValueNode.kind === graphql.Kind.BOOLEAN) {
              if (ifValueNode.value) {
                continue selectionLoop;
              }
            }
          } else {
            continue selectionLoop;
          }
        }
        if (directiveNode.name.value === "include") {
          if (ifArg) {
            const ifValueNode = ifArg.value;
            if (ifValueNode.kind === graphql.Kind.VARIABLE) {
              const variableName = ifValueNode.name.value;
              if (!executionContext.variableValues?.[variableName]) {
                continue selectionLoop;
              }
            } else if (ifValueNode.kind === graphql.Kind.BOOLEAN) {
              if (!ifValueNode.value) {
                continue selectionLoop;
              }
            }
          } else {
            continue selectionLoop;
          }
        }
      }
    }
    if (selection.kind === "Field") {
      const field = selection.name.value === "__typename" ? graphql.TypeNameMetaFieldDef : parentType.getFields()[selection.name.value];
      if (!field) {
        throw new Error(
          `Field not found: ${selection.name.value} on ${parentType.name}`
        );
      }
      const fieldType = graphql.getNamedType(field.type);
      const responseKey = selection.alias?.value || selection.name.value;
      let projectedValue = selection.selectionSet ? projectSelectionSet(
        data[responseKey],
        selection.selectionSet,
        fieldType,
        executionContext
      ) : data[responseKey];
      if (projectedValue !== void 0) {
        if (graphql.isEnumType(fieldType)) {
          let projectEnumValue2 = function(value) {
            if (Array.isArray(value)) {
              return value.map((item) => projectEnumValue2(item));
            }
            const enumValue = enumType.getValue(value);
            if (enumValue == null) {
              return null;
            } else if (utils.getDirective(
              executionContext.supergraphSchema,
              enumValue,
              "inaccessible"
            )?.length) {
              return null;
            }
            return value;
          };
          const enumType = fieldType;
          projectedValue = projectEnumValue2(projectedValue);
        }
        if (result[responseKey] == null) {
          result[responseKey] = projectedValue;
        } else if (typeof result[responseKey] === "object" && projectedValue != null) {
          result[responseKey] = Object.assign(
            result[responseKey],
            utils.mergeDeep([result[responseKey], projectedValue])
          );
        } else {
          result[responseKey] = projectedValue;
        }
      } else if (field.name === "__typename") {
        result[responseKey] = type.name;
      } else if (graphql.isNonNullType(field.type)) {
        return null;
      } else {
        result[responseKey] = null;
      }
    } else if (selection.kind === "InlineFragment") {
      const typeCondition = selection.typeCondition?.name.value;
      if (isEntityRepresentation(data)) {
        if (typeCondition && !entitySatisfiesTypeCondition(
          executionContext.supergraphSchema,
          data.__typename,
          typeCondition
        )) {
          continue;
        }
        const typeByTypename = executionContext.supergraphSchema.getType(
          data.__typename
        );
        if (!graphql.isOutputType(typeByTypename)) {
          throw new Error("Invalid type");
        }
        const projectedValue = projectSelectionSet(
          data,
          selection.selectionSet,
          typeByTypename,
          executionContext
        );
        if (projectedValue != null) {
          Object.assign(
            result,
            utils.mergeDeep([result, projectedValue], false, true, true)
          );
        }
      } else {
        if (typeCondition && !entitySatisfiesTypeCondition(
          executionContext.supergraphSchema,
          parentType.name,
          typeCondition
        )) {
          continue;
        }
        const projectedValue = projectSelectionSet(
          data,
          selection.selectionSet,
          typeCondition ? executionContext.supergraphSchema.getType(typeCondition) : parentType,
          executionContext
        );
        if (projectedValue != null) {
          Object.assign(
            result,
            utils.mergeDeep([result, projectedValue], false, true, true)
          );
        }
      }
    } else if (selection.kind === "FragmentSpread") {
      const fragment = executionContext.fragments[selection.name.value];
      if (!fragment) {
        throw new Error(`Fragment "${selection.name.value}" not found`);
      }
      const typeCondition = fragment.typeCondition?.name.value;
      if (isEntityRepresentation(data) && typeCondition && !entitySatisfiesTypeCondition(
        executionContext.supergraphSchema,
        data.__typename,
        typeCondition
      )) {
        continue;
      }
      const typeByTypename = executionContext.supergraphSchema.getType(
        data.__typename || typeCondition
      );
      if (!graphql.isOutputType(typeByTypename)) {
        throw new Error("Invalid type");
      }
      const projectedValue = projectSelectionSet(
        data,
        fragment.selectionSet,
        typeByTypename,
        executionContext
      );
      if (projectedValue != null) {
        Object.assign(
          result,
          utils.mergeDeep([result, projectedValue], false, true, true)
        );
      }
    }
  }
  return result;
}
function projectDataByOperation(executionContext) {
  const rootType = executionContext.supergraphSchema.getRootType(
    executionContext.operation.operation
  );
  if (!rootType) {
    throw new Error("Root type not found");
  }
  return projectSelectionSet(
    executionContext.data,
    executionContext.operation.selectionSet,
    rootType,
    executionContext
  );
}
function projectRequires(requiresSelections, entity, supergraphSchema) {
  if (!entity) {
    return entity;
  }
  if (Array.isArray(entity)) {
    return entity.map(
      (item) => projectRequires(requiresSelections, item, supergraphSchema)
    );
  }
  const result = {};
  for (const requiresSelection of requiresSelections) {
    switch (requiresSelection.kind) {
      case "Field": {
        const fieldName = requiresSelection.name;
        const responseKey = requiresSelection.alias ?? fieldName;
        let original = entity[fieldName];
        if (original === void 0) {
          original = entity[responseKey];
        }
        const projectedValue = requiresSelection.selections ? projectRequires(
          requiresSelection.selections,
          original,
          supergraphSchema
        ) : original;
        if (projectedValue != null) {
          result[responseKey] = projectedValue;
        }
        break;
      }
      case "InlineFragment":
        if (entitySatisfiesTypeCondition(
          supergraphSchema,
          entity.__typename,
          requiresSelection.typeCondition
        )) {
          const projected = projectRequires(
            requiresSelection.selections,
            entity,
            supergraphSchema
          );
          if (projected) {
            Object.assign(
              result,
              utils.mergeDeep([result, projected], false, true, true)
            );
          }
        }
        break;
    }
  }
  if (Object.keys(result).length === 1 && result.__typename || Object.keys(result).length === 0) {
    return null;
  }
  return result;
}

const REPRESENTATIONS_VAR_DEF = Object.freeze({
  kind: graphql.Kind.VARIABLE_DEFINITION,
  variable: {
    kind: graphql.Kind.VARIABLE,
    name: {
      kind: graphql.Kind.NAME,
      value: "representations"
    }
  },
  type: {
    kind: graphql.Kind.NON_NULL_TYPE,
    type: {
      kind: graphql.Kind.LIST_TYPE,
      type: {
        kind: graphql.Kind.NON_NULL_TYPE,
        type: {
          kind: graphql.Kind.NAMED_TYPE,
          name: {
            kind: graphql.Kind.NAME,
            value: "_Any"
          }
        }
      }
    }
  }
});
function getEntityResolutionMap(supergraphSchema) {
  const entityResolutionMap = /* @__PURE__ */ new Map();
  const realSubgraphNames = /* @__PURE__ */ new Map();
  const joinGraph = supergraphSchema.getType("join__Graph");
  if (graphql.isEnumType(joinGraph)) {
    for (const value of joinGraph.getValues()) {
      const valueDirectives = utils.getDirectiveExtensions(value, supergraphSchema);
      const graphName = valueDirectives?.["join__graph"]?.[0]?.["name"];
      if (graphName) {
        realSubgraphNames.set(value.name, graphName);
      }
    }
  }
  for (const typeName in supergraphSchema.getTypeMap()) {
    const type = supergraphSchema.getType(typeName);
    if (type) {
      const directives = utils.getDirectiveExtensions(type, supergraphSchema);
      const joinTypeDirective = directives?.["join__type"];
      if (joinTypeDirective) {
        for (const joinTypeDirectiveArgs of joinTypeDirective) {
          const subgraphName = joinTypeDirectiveArgs["graph"];
          const keySelectionSetStr = joinTypeDirectiveArgs["key"];
          const resolvable = joinTypeDirectiveArgs["resolvable"] !== false;
          if (subgraphName && keySelectionSetStr && resolvable) {
            const realSubgraphName = realSubgraphNames.get(subgraphName) || subgraphName;
            entityResolutionMap.set(typeName, {
              [realSubgraphName]: utils.parseSelectionSet(
                `{ ${keySelectionSetStr} }`
              )
            });
          }
        }
      }
    }
  }
  return entityResolutionMap;
}
function getPubsubOperationRootFields(schema, entityResolutionMap) {
  const pubsubOperationFields = /* @__PURE__ */ new Map();
  const subscriptionType = schema.getSubscriptionType();
  if (subscriptionType) {
    const subscriptionFields = subscriptionType.getFields();
    for (const fieldName in subscriptionFields) {
      const fieldDef = subscriptionFields[fieldName];
      if (fieldDef) {
        const pubsubOperations = utils.getDirectiveInExtensions(
          fieldDef,
          "pubsubOperation"
        );
        if (pubsubOperations) {
          for (const operationDef of pubsubOperations) {
            const returnType = graphql.getNamedType(fieldDef.type);
            const entityResolution = entityResolutionMap.has(returnType.name);
            pubsubOperationFields.set(fieldDef.name, {
              pubsubTopic: operationDef["pubsubTopic"],
              filterBy: operationDef["filterBy"],
              result: operationDef["result"],
              entityTypeName: entityResolution ? returnType.name : void 0
            });
          }
        }
      }
    }
  }
  return pubsubOperationFields;
}
function resolvePubsubOperationRootField(opts, responseKey, resolverOpts) {
  const pubsubOperationResolver = utils$1.getResolverForPubSubOperation(
    opts,
    (payload) => ({
      data: {
        [responseKey]: payload
      }
    })
  );
  return handleMaybePromiseMaybeAsyncIterable(
    () => pubsubOperationResolver.subscribe(
      resolverOpts.root,
      resolverOpts.args,
      resolverOpts.context,
      void 0
    ),
    (root) => pubsubOperationResolver.resolve(
      root,
      // @ts-expect-error in case the resolve takes in more args, doesnt hurt to keep passing them
      resolverOpts.args,
      resolverOpts.context,
      void 0
    )
  );
}
const getSubscriptionInformationFromDocument = utils.memoize2(
  function getSubscriptionInformationFromDocument2(supergraphSchema, document) {
    const typeInfo = delegate.getTypeInfo(supergraphSchema);
    let responseKey;
    let fieldName;
    let selectionSet;
    let argNodes;
    let variableDefinitions;
    graphql.visit(
      document,
      graphql.visitWithTypeInfo(typeInfo, {
        OperationDefinition(node) {
          variableDefinitions = node.variableDefinitions;
        },
        Field(node) {
          const parentType = typeInfo.getParentType();
          if (parentType === supergraphSchema.getSubscriptionType()) {
            responseKey = node.alias?.value || node.name.value;
            fieldName = node.name.value;
            selectionSet = node.selectionSet;
            argNodes = node.arguments;
            return graphql.BREAK;
          }
          return node;
        }
      })
    );
    return {
      responseKey,
      fieldName,
      selectionSet,
      argNodes,
      variableDefinitions
    };
  }
);
function getArgsFromArgumentNodes(argNodes, variables) {
  const args = {};
  if (argNodes) {
    for (const argNode of argNodes) {
      const argName = argNode.name.value;
      const argValueNode = argNode.value;
      args[argName] = graphql.valueFromASTUntyped(argValueNode, variables);
    }
  }
  return args;
}
function resolvePubsubOperationResult(executionRequest, executionResult, pubsubOperationMetadata, responseKey, executeSubgraph, variableDefinitions, selectionSet) {
  if (pubsubOperationMetadata.entityTypeName && selectionSet && executionResult.data?.[responseKey] != null) {
    const representations = utils.asArray(
      executionResult.data[responseKey]
    ).filter(Boolean);
    if (representations.length) {
      for (const representation of representations) {
        representation.__typename ||= pubsubOperationMetadata.entityTypeName;
      }
      const varDefs = [...variableDefinitions || []];
      varDefs.push(REPRESENTATIONS_VAR_DEF);
      const entityResolutionDocument = {
        kind: graphql.Kind.DOCUMENT,
        definitions: [
          {
            kind: graphql.Kind.OPERATION_DEFINITION,
            operation: "query",
            name: executionRequest.operationName ? {
              kind: graphql.Kind.NAME,
              value: executionRequest.operationName
            } : void 0,
            variableDefinitions: varDefs,
            selectionSet: {
              kind: graphql.Kind.SELECTION_SET,
              selections: [
                {
                  kind: graphql.Kind.FIELD,
                  name: {
                    kind: graphql.Kind.NAME,
                    value: "_entities"
                  },
                  arguments: [
                    {
                      kind: graphql.Kind.ARGUMENT,
                      name: {
                        kind: graphql.Kind.NAME,
                        value: "representations"
                      },
                      value: {
                        kind: graphql.Kind.VARIABLE,
                        name: {
                          kind: graphql.Kind.NAME,
                          value: "representations"
                        }
                      }
                    }
                  ],
                  selectionSet: {
                    kind: graphql.Kind.SELECTION_SET,
                    selections: [
                      {
                        kind: graphql.Kind.FIELD,
                        name: {
                          kind: graphql.Kind.NAME,
                          value: "__typename"
                        }
                      },
                      {
                        kind: graphql.Kind.INLINE_FRAGMENT,
                        typeCondition: {
                          kind: graphql.Kind.NAMED_TYPE,
                          name: {
                            kind: graphql.Kind.NAME,
                            value: pubsubOperationMetadata.entityTypeName
                          }
                        },
                        selectionSet
                      }
                    ]
                  }
                }
              ]
            }
          }
        ]
      };
      return handleMaybePromiseMaybeAsyncIterable(
        () => executeSubgraph({
          ...executionRequest,
          document: entityResolutionDocument,
          variables: {
            ...executionRequest.variables,
            representations
          }
        }),
        (entitiesResult) => {
          if (entitiesResult?.data?._entities?.length) {
            const entities = utils.asArray(entitiesResult.data._entities);
            for (let i = 0; i < entities.length; i++) {
              const entity = entities[i];
              const representation = representations[i];
              if (entity != null && representation != null) {
                Object.assign(
                  representation,
                  utils.mergeDeep([entity, representation], false, true, true)
                );
              }
            }
          }
          if (entitiesResult?.errors?.length) {
            executionResult.errors ||= [];
            executionResult.errors.push(...entitiesResult.errors);
          }
          return executionResult;
        }
      );
    }
  }
  return executionResult;
}
function handlePubsubOperationField(supergraphSchema, executionRequest, pubsubOperationMetadataMap, executeSubgraph) {
  if (executionRequest.operationType === "subscription" && pubsubOperationMetadataMap.size > 0) {
    const {
      responseKey,
      fieldName,
      selectionSet,
      argNodes,
      variableDefinitions
    } = getSubscriptionInformationFromDocument(
      supergraphSchema,
      executionRequest.document
    );
    if (responseKey && fieldName) {
      const pubsubOperationMetadata = pubsubOperationMetadataMap.get(fieldName);
      if (pubsubOperationMetadata) {
        const args = getArgsFromArgumentNodes(
          argNodes,
          executionRequest.variables
        );
        return handleMaybePromiseMaybeAsyncIterable(
          () => resolvePubsubOperationRootField(
            pubsubOperationMetadata,
            responseKey,
            {
              root: executionRequest.rootValue,
              args,
              context: executionRequest.context
            }
          ),
          (executionResult) => resolvePubsubOperationResult(
            executionRequest,
            executionResult,
            pubsubOperationMetadata,
            responseKey,
            executeSubgraph,
            variableDefinitions,
            selectionSet
          )
        );
      }
    }
  }
  return executeSubgraph(executionRequest);
}
function getPubsubPublishMetadata(schema, entityResolutionMap) {
  const pubsubPublishMetadataMap = /* @__PURE__ */ new Map();
  for (const typeName in schema.getTypeMap()) {
    const type = schema.getType(typeName);
    if (type != null && "getFields" in type) {
      const fields = type.getFields();
      for (const fieldName in fields) {
        const fieldDef = fields[fieldName];
        if (fieldDef) {
          const pubsubPublishes = utils.getDirectiveInExtensions(
            fieldDef,
            "pubsubPublish"
          );
          if (pubsubPublishes) {
            for (const { pubsubTopic } of pubsubPublishes) {
              let typeMap = pubsubPublishMetadataMap.get(typeName);
              if (!typeMap) {
                typeMap = /* @__PURE__ */ new Map();
                pubsubPublishMetadataMap.set(typeName, typeMap);
              }
              const returnType = graphql.getNamedType(fieldDef.type);
              const returnTypeName = returnType.name;
              const entityInfo = entityResolutionMap.get(returnTypeName);
              typeMap.set(fieldName, { pubsubTopic, entityInfo });
            }
          }
        }
      }
    }
  }
  return pubsubPublishMetadataMap;
}
function addEntityResolutionFieldsForPubsubPublish(schema, executionRequest, subgraphName, metadata) {
  if (executionRequest.operationType === "mutation" && metadata.size > 0) {
    const typeInfo = delegate.getTypeInfo(schema);
    let changed = false;
    const document = graphql.visit(
      executionRequest.document,
      graphql.visitWithTypeInfo(typeInfo, {
        [graphql.Kind.FIELD](node) {
          const parentType = typeInfo.getParentType();
          const fieldDef = typeInfo.getFieldDef();
          if (parentType && fieldDef) {
            const typeMetadata = metadata.get(parentType.name);
            const fieldMetadata = typeMetadata?.get(fieldDef.name);
            const entitySelectionSet = fieldMetadata?.entityInfo?.[subgraphName];
            if (entitySelectionSet) {
              changed = true;
              return {
                ...node,
                selectionSet: {
                  kind: graphql.Kind.SELECTION_SET,
                  selections: [
                    ...node.selectionSet?.selections || [],
                    ...entitySelectionSet.selections
                  ]
                }
              };
            }
          }
          return node;
        }
      })
    );
    if (changed) {
      return {
        ...executionRequest,
        document
      };
    }
  }
  return executionRequest;
}
const getPubsubPublishVisitor = utils.memoize2(function getPubsubPublishFields(metadata, pubsub) {
  if (!metadata.size) {
    return false;
  }
  const pubsubPublishVisitor = {};
  for (const [typeName, fieldsMap] of metadata) {
    const typeVisitor = pubsubPublishVisitor[typeName] ||= {};
    for (const [fieldName, { pubsubTopic }] of fieldsMap) {
      typeVisitor[fieldName] = (value) => {
        const maybePromise = pubsub.publish(pubsubTopic, value);
        if (maybePromise && typeof maybePromise.catch === "function") {
          maybePromise.catch(() => {
          });
        }
        return value;
      };
    }
  }
  return pubsubPublishVisitor;
});
function handleResultWithPubSubPublish(schema, metadata, request, result) {
  if (request.operationType === "mutation" && result.data != null && request.context?.pubsub != null) {
    const pubsubPublishVisitor = getPubsubPublishVisitor(
      metadata,
      request.context.pubsub
    );
    if (pubsubPublishVisitor) {
      return utils.visitResult(result, request, schema, pubsubPublishVisitor);
    }
  }
  return result;
}

async function unifiedGraphHandler(opts) {
  const getSubschema = getLazyFactory(
    () => getHandledFederationSupergraph().getSubschema
  );
  const getHandledFederationSupergraph = getLazyValue(
    () => fusionRuntime.handleFederationSupergraph(opts)
  );
  const moduleName = "@graphql-hive/router-query-planner";
  const { QueryPlanner } = await import(moduleName);
  const supergraphSdl = opts.getUnifiedGraphSDL();
  const queryPlanner = new QueryPlanner(supergraphSdl);
  function getActivePercentLabels(percentageValue) {
    const activePercentLabels = /* @__PURE__ */ new Set();
    for (const percentage of queryPlanner.overridePercentages) {
      if (percentageValue > percentage) {
        activePercentLabels.add(`percent(${percentage})`);
      }
    }
    return activePercentLabels;
  }
  const entityResolutionMap = getEntityResolutionMap(opts.unifiedGraph);
  const pubsubOperationMetadataMap = getPubsubOperationRootFields(
    opts.unifiedGraph,
    entityResolutionMap
  );
  const pubsubPublishMetadataMap = getPubsubPublishMetadata(
    opts.unifiedGraph,
    entityResolutionMap
  );
  const supergraphSchema = federation.filterInternalFieldsAndTypes(opts.unifiedGraph);
  const defaultExecutor = getLazyFactory(
    () => transportCommon.createDefaultExecutor(supergraphSchema)
  );
  function calculateCacheKeyForDocument(activeLabels, percentageValue, operationName) {
    let cacheKey = operationName || "";
    for (const label of activeLabels) {
      cacheKey += `|${label}`;
    }
    const activePercentLabels = getActivePercentLabels(percentageValue);
    for (const label of activePercentLabels) {
      cacheKey += `|${label}`;
    }
    return cacheKey;
  }
  const documentOperationPlanCache = /* @__PURE__ */ new WeakMap();
  function planDocument(executionRequest) {
    let operationCache = documentOperationPlanCache.get(
      executionRequest.document
    );
    const activeLabels = /* @__PURE__ */ new Set();
    for (const label of queryPlanner.overrideLabels) {
      if (opts.handleProgressiveOverride?.(label, executionRequest.context)) {
        activeLabels.add(label);
      }
    }
    const rng = federation.getRngFromEnv() || Math.random();
    const percentageValue = rng * 100;
    const cacheKey = calculateCacheKeyForDocument(
      activeLabels,
      percentageValue,
      executionRequest.operationName
    );
    if (operationCache) {
      const plan2 = operationCache.get(cacheKey);
      if (plan2) {
        return plan2;
      }
    } else {
      operationCache = /* @__PURE__ */ new Map();
      documentOperationPlanCache.set(executionRequest.document, operationCache);
    }
    const plan = promiseHelpers.handleMaybePromise(
      () => queryPlanner.planAsync(
        executorCommon.defaultPrintFn(executionRequest.document),
        executionRequest.operationName,
        activeLabels,
        percentageValue,
        executionRequest.signal
      ),
      (queryPlan) => {
        operationCache.set(cacheKey, queryPlan);
        return queryPlan;
      }
    );
    operationCache.set(cacheKey, plan);
    return plan;
  }
  return {
    unifiedGraph: supergraphSchema,
    getSubgraphSchema(subgraphName) {
      return getSubschema(subgraphName).schema;
    },
    executor(executionRequest) {
      if (isIntrospection(executionRequest.document)) {
        return defaultExecutor(executionRequest);
      }
      return promiseHelpers.handleMaybePromise(
        () => planDocument(executionRequest),
        (queryPlan) => {
          queryPlanForExecutionRequestContext.set(
            // setter like getter
            executionRequest.context || executionRequest.document,
            queryPlan
          );
          return executeQueryPlan({
            supergraphSchema,
            executionRequest,
            onSubgraphExecute: (subgraphName, executionRequest2) => handlePubsubOperationField(
              supergraphSchema,
              addEntityResolutionFieldsForPubsubPublish(
                supergraphSchema,
                executionRequest2,
                subgraphName,
                pubsubPublishMetadataMap
              ),
              pubsubOperationMetadataMap,
              (executionRequest3) => handleMaybePromiseMaybeAsyncIterable(
                () => onSubgraphExecuteWithTransforms(
                  subgraphName,
                  executionRequest3,
                  opts.onSubgraphExecute,
                  getSubschema
                ),
                (executionResult) => handleResultWithPubSubPublish(
                  supergraphSchema,
                  pubsubPublishMetadataMap,
                  executionRequest3,
                  executionResult
                )
              )
            ),
            queryPlan
          });
        }
      );
    },
    overrideLabels: queryPlanner.overrideLabels
  };
}
function isIntrospection(document) {
  let onlyQueryTypenameFields = false;
  let containsIntrospectionField = false;
  graphql.visit(document, {
    OperationDefinition(node) {
      for (const sel of node.selectionSet.selections) {
        if (sel.kind !== "Field") return graphql.BREAK;
        if (sel.name.value === "__schema" || sel.name.value === "__type") {
          containsIntrospectionField = true;
          return graphql.BREAK;
        }
        if (sel.name.value === "__typename") {
          onlyQueryTypenameFields = true;
        } else {
          onlyQueryTypenameFields = false;
          return graphql.BREAK;
        }
      }
      return;
    }
  });
  return containsIntrospectionField || onlyQueryTypenameFields;
}

function useQueryPlan(opts = {}) {
  const { expose, onQueryPlan } = opts;
  return {
    onExecute({ context, args }) {
      return {
        onExecuteDone({ result, setResult }) {
          const queryPlan = queryPlanForExecutionRequestContext.get(
            // getter like setter
            context || args.document
          );
          onQueryPlan?.(queryPlan);
          const shouldExpose = typeof expose === "function" ? expose(context.request) : expose;
          if (shouldExpose && !utils.isAsyncIterable(result)) {
            setResult({
              ...result,
              extensions: {
                ...result.extensions,
                queryPlan
              }
            });
          }
        }
      };
    }
  };
}

exports.unifiedGraphHandler = unifiedGraphHandler;
exports.useQueryPlan = useQueryPlan;