import { FieldNode, SelectionSetNode, GraphQLSchema, GraphQLNamedType, GraphQLFieldConfig, GraphQLObjectType, GraphQLInterfaceType, GraphQLInputFieldConfig, GraphQLInputObjectType, GraphQLEnumValueConfig, GraphQLEnumType, GraphQLOutputType, SelectionNode, FragmentDefinitionNode } from 'graphql';
import { SubschemaConfig, Subschema, MergedTypeResolverOptions, MergedTypeResolver } from '@graphql-tools/delegate';
import { IExecutableSchemaDefinition } from '@graphql-tools/schema';
import { TypeSource, Maybe, ExecutionRequest } from '@graphql-tools/utils';

interface MergeTypeCandidate<TContext = Record<string, any>> {
    type: GraphQLNamedType;
    subschema?: GraphQLSchema | SubschemaConfig<any, any, any, TContext>;
    transformedSubschema?: Subschema<any, any, any, TContext>;
}
interface MergeFieldConfigCandidate<TContext = Record<string, any>> {
    fieldConfig: GraphQLFieldConfig<any, TContext>;
    fieldName: string;
    type: GraphQLObjectType | GraphQLInterfaceType;
    subschema?: GraphQLSchema | SubschemaConfig<any, any, any, TContext>;
    transformedSubschema?: Subschema<any, any, any, TContext>;
}
interface MergeInputFieldConfigCandidate<TContext = Record<string, any>> {
    inputFieldConfig: GraphQLInputFieldConfig;
    fieldName: string;
    type: GraphQLInputObjectType;
    subschema?: GraphQLSchema | SubschemaConfig<any, any, any, TContext>;
    transformedSubschema?: Subschema<any, any, any, TContext>;
}
interface MergeEnumValueConfigCandidate<TContext = Record<string, any>> {
    enumValueConfig: GraphQLEnumValueConfig;
    enumValue: string;
    type: GraphQLEnumType;
    subschema?: GraphQLSchema | SubschemaConfig<any, any, any, TContext>;
    transformedSubschema?: Subschema<any, any, any, TContext>;
}
type MergeTypeFilter<TContext = Record<string, any>> = (mergeTypeCandidates: Array<MergeTypeCandidate<TContext>>, typeName: string) => boolean;
interface IStitchSchemasOptions<TContext = Record<string, any>> extends Omit<IExecutableSchemaDefinition<TContext>, 'typeDefs'> {
    subschemas?: Array<GraphQLSchema | SubschemaConfig<any, any, any, TContext>>;
    typeDefs?: TypeSource;
    types?: Array<GraphQLNamedType>;
    onTypeConflict?: OnTypeConflict<TContext>;
    mergeDirectives?: boolean | undefined;
    mergeTypes?: boolean | Array<string> | MergeTypeFilter<TContext>;
    typeMergingOptions?: TypeMergingOptions<TContext>;
    subschemaConfigTransforms?: Array<SubschemaConfigTransform<TContext>>;
}
type SubschemaConfigTransform<TContext = Record<string, any>> = (subschemaConfig: SubschemaConfig<any, any, any, TContext>) => SubschemaConfig<any, any, any, TContext> | Array<SubschemaConfig<any, any, any, TContext>>;
interface TypeMergingOptions<TContext = Record<string, any>> {
    validationSettings?: ValidationSettings;
    validationScopes?: Record<string, ValidationSettings>;
    typeCandidateMerger?: (candidates: Array<MergeTypeCandidate<TContext>>) => MergeTypeCandidate<TContext>;
    typeDescriptionsMerger?: (candidates: Array<MergeTypeCandidate<TContext>>) => Maybe<string>;
    fieldConfigMerger?: (candidates: Array<MergeFieldConfigCandidate<TContext>>) => GraphQLFieldConfig<any, TContext>;
    inputFieldConfigMerger?: (candidates: Array<MergeInputFieldConfigCandidate<TContext>>) => GraphQLInputFieldConfig;
    enumValueConfigMerger?: (candidates: Array<MergeEnumValueConfigCandidate<TContext>>) => GraphQLEnumValueConfig;
    useNonNullableFieldOnConflict?: boolean;
}
declare enum ValidationLevel {
    Error = "error",
    Warn = "warn",
    Off = "off"
}
interface ValidationSettings {
    validationLevel?: ValidationLevel;
    strictNullComparison?: boolean;
    proxiableScalars?: Record<string, Array<string>>;
}
type OnTypeConflict<TContext = Record<string, any>> = (left: GraphQLNamedType, right: GraphQLNamedType, info?: {
    left: {
        subschema?: GraphQLSchema | SubschemaConfig<any, any, any, TContext>;
        transformedSubschema?: Subschema<any, any, any, TContext>;
    };
    right: {
        subschema?: GraphQLSchema | SubschemaConfig<any, any, any, TContext>;
        transformedSubschema?: Subschema<any, any, any, TContext>;
    };
}) => GraphQLNamedType;
declare module '@graphql-tools/utils' {
    interface IFieldResolverOptions<TSource = any, TContext = any, TArgs = any> {
        selectionSet?: string | ((node: FieldNode) => SelectionSetNode);
    }
}

declare function stitchSchemas<TContext extends Record<string, any> = Record<string, any>>({ subschemas, types, typeDefs, onTypeConflict, mergeDirectives, mergeTypes, typeMergingOptions, subschemaConfigTransforms, resolvers, inheritResolversFromInterfaces, resolverValidationOptions, updateResolversInPlace, schemaExtensions, ...rest }: IStitchSchemasOptions<TContext>): GraphQLSchema;

declare function createMergedTypeResolver<TContext extends Record<string, any> = any>(mergedTypeResolverOptions: MergedTypeResolverOptions, mergedType?: GraphQLOutputType | string): MergedTypeResolver<TContext> | undefined;

declare const forwardArgsToSelectionSet: (selectionSet: string, mapping?: Record<string, string[]>) => (field: FieldNode) => SelectionSetNode;

declare function isolateComputedFieldsTransformer(subschemaConfig: SubschemaConfig): Array<SubschemaConfig>;

declare function splitMergedTypeEntryPointsTransformer(subschemaConfig: SubschemaConfig): Array<SubschemaConfig>;

declare function handleRelaySubschemas(subschemas: SubschemaConfig[], getTypeNameFromId?: (id: string) => string): SubschemaConfig<any, any, any, Record<string, any>>[];

/**
 * Creates an executor that uses the schema created by stitching together multiple subschemas.
 * Not ready for production
 * Breaking changes can be introduced in the meanwhile
 *
 * @experimental
 *
 */
declare function createStitchingExecutor(stitchedSchema: GraphQLSchema): (executorRequest: ExecutionRequest) => Promise<{
    data: Record<string, any>;
}>;

declare function getDefaultFieldConfigMerger(useNonNullableFieldOnConflict?: boolean): <TContext = Record<string, any>>(candidates: Array<MergeFieldConfigCandidate<TContext>>) => GraphQLFieldConfig<any, TContext, any>;

declare const calculateSelectionScore: (selections: readonly SelectionNode[], fragments: Record<string, FragmentDefinitionNode>) => number;

export { type IStitchSchemasOptions, type MergeEnumValueConfigCandidate, type MergeFieldConfigCandidate, type MergeInputFieldConfigCandidate, type MergeTypeCandidate, type MergeTypeFilter, type OnTypeConflict, type SubschemaConfigTransform, type TypeMergingOptions, ValidationLevel, type ValidationSettings, calculateSelectionScore, createMergedTypeResolver, createStitchingExecutor, forwardArgsToSelectionSet, getDefaultFieldConfigMerger, handleRelaySubschemas, isolateComputedFieldsTransformer, splitMergedTypeEntryPointsTransformer, stitchSchemas };
