import { Types, PluginFunction } from '@graphql-codegen/plugin-helpers';
import { Source } from '@graphql-tools/utils';
import { OperationDefinitionNode, FragmentDefinitionNode, ExecutionArgs } from 'graphql';
import { IsNever, SetOptional } from 'type-fest';

type PresetConfig = {
    /**
     * Whether types should be imported or generated inline.
     */
    importTypes?: {
        /**
         * Name for the variable that contains the imported types.
         * @example 'StorefrontAPI'
         */
        namespace: string;
        /**
         * Module to import the types from.
         * @example '@shopify/hydrogen/storefront-api-types'
         */
        from: string;
    };
    /**
     * Whether to skip adding `__typename` to generated operation types.
     * @default true
     */
    skipTypenameInOperations?: boolean;
    /**
     * Override the default interface extension.
     * @example ({queryType}) => `declare module 'my-api' { interface Queries extends ${queryType} {} }`
     */
    interfaceExtension: (options: {
        queryType: string;
        mutationType: string;
    }) => string;
};
declare const preset: Types.OutputPreset<PresetConfig>;

type OperationOrFragment = {
    initialName: string;
    definition: OperationDefinitionNode | FragmentDefinitionNode;
};
type SourceWithOperations = {
    source: Source;
    operations: Array<OperationOrFragment>;
};
declare const plugin: PluginFunction<{
    sourcesWithOperations: Array<SourceWithOperations>;
    interfaceExtensionCode: string;
}>;

declare function processSources(sources: Array<Source>, buildName?: (node: OperationDefinitionNode | FragmentDefinitionNode) => string): SourceWithOperations[];

/**
 * This is a modified version of graphql-tag-pluck's default config.
 * https://github.com/ardatan/graphql-tools/issues/5127
 */
declare const pluckConfig: {
    /**
     * Hook to determine if a node is a gql template literal.
     * By default, graphql-tag-pluck only looks for leading comments or `gql` tag.
     */
    isGqlTemplateLiteral: (node: any, options: any) => boolean;
    /**
     * Instruct how to extract the gql template literal from the code.
     * By default, embedded expressions in template literals (e.g. ${foo})
     * are removed from the template string. This hook allows us to annotate
     * the template string with the required embedded expressions instead of
     * removing them. Later, we can use this information to reconstruct the
     * embedded expressions.
     */
    pluckStringFromFile: (code: string, { start, end, leadingComments }: any) => string;
};

/**
 * This file has utilities to create GraphQL clients
 * that consume the types generated by the preset.
 */

/**
 * A generic type for `variables` in GraphQL clients
 */
type GenericVariables = ExecutionArgs['variableValues'];
/**
 * Use this type to make parameters optional in GraphQL clients
 * when no variables need to be passed.
 */
type EmptyVariables = {
    [key: string]: never;
};
/**
 * GraphQL client's generic operation interface.
 */
interface CodegenOperations {
    [key: string]: any;
}
/**
 * Used as the return type for GraphQL clients. It picks
 * the return type from the generated operation types.
 * @example
 * graphqlQuery: (...) => Promise<ClientReturn<...>>
 * graphqlQuery: (...) => Promise<{data: ClientReturn<...>}>
 */
type ClientReturn<GeneratedOperations extends CodegenOperations, RawGqlString extends string, OverrideReturnType extends any = never> = IsNever<OverrideReturnType> extends true ? RawGqlString extends keyof GeneratedOperations ? GeneratedOperations[RawGqlString]['return'] : any : OverrideReturnType;
/**
 * Checks if the generated variables for an operation
 * are optional or required.
 */
type IsOptionalVariables<VariablesParam, OptionalVariableNames extends string = never, VariablesWithoutOptionals = Omit<VariablesParam, OptionalVariableNames>> = VariablesWithoutOptionals extends EmptyVariables ? true : GenericVariables extends VariablesParam ? true : Partial<VariablesWithoutOptionals> extends VariablesWithoutOptionals ? true : false;
/**
 * Used as the type for the GraphQL client's variables. It checks
 * the generated operation types to see if variables are optional.
 * @example
 * graphqlQuery: (query: string, param: ClientVariables<...>) => Promise<...>
 * Where `param` is required.
 */
type ClientVariables<GeneratedOperations extends CodegenOperations, RawGqlString extends string, OptionalVariableNames extends string = never, VariablesKey extends string = 'variables', GeneratedVariables = RawGqlString extends keyof GeneratedOperations ? SetOptional<GeneratedOperations[RawGqlString]['variables'], Extract<keyof GeneratedOperations[RawGqlString]['variables'], OptionalVariableNames>> : GenericVariables, VariablesWrapper = Record<VariablesKey, GeneratedVariables>> = IsOptionalVariables<GeneratedVariables, OptionalVariableNames> extends true ? Partial<VariablesWrapper> : VariablesWrapper;
/**
 * Similar to ClientVariables, but makes the whole wrapper optional:
 * @example
 * graphqlQuery: (query: string, ...params: ClientVariablesInRestParams<...>) => Promise<...>
 * Where the first item in `params` might be optional depending on the query.
 */
type ClientVariablesInRestParams<GeneratedOperations extends CodegenOperations, RawGqlString extends string, OtherParams extends Record<string, any> = {}, OptionalVariableNames extends string = never, ProcessedVariables = OtherParams & ClientVariables<GeneratedOperations, RawGqlString, OptionalVariableNames>> = Partial<OtherParams> extends OtherParams ? IsOptionalVariables<GeneratedOperations[RawGqlString]['variables'], OptionalVariableNames> extends true ? [
    ProcessedVariables?
] : [
    ProcessedVariables
] : [
    ProcessedVariables
];

export { type ClientReturn, type ClientVariables, type ClientVariablesInRestParams, type EmptyVariables, type GenericVariables, type IsOptionalVariables, type PresetConfig, pluckConfig, plugin, preset, processSources };
