/**
 *
 * handler
 *
 */
import { ExecutionArgs, GraphQLSchema, validate as graphqlValidate } from 'graphql';
import { ExecutionResult, ExecutionPatchResult, RequestParams } from './common';
/**
 * The incoming request headers the implementing server should provide.
 *
 * @category Server
 */
export interface RequestHeaders {
    get: (key: string) => string | null | undefined;
}
/**
 * Server agnostic request interface containing the raw request
 * which is server dependant.
 *
 * @category Server
 */
export interface Request<Raw = unknown, Context = unknown> {
    readonly method: string;
    readonly url: string;
    readonly headers: RequestHeaders;
    /**
     * Parsed request body or a parser function.
     *
     * If the provided function throws, the error message "Unparsable JSON body" will
     * be in the erroneous response.
     */
    readonly body: string | Record<PropertyKey, unknown> | null | (() => string | Record<PropertyKey, unknown> | null | Promise<string | Record<PropertyKey, unknown> | null>);
    /**
     * The raw request itself from the implementing server.
     */
    readonly raw: Raw;
    /**
     * Context value about the incoming request, you're free to pass any information here.
     *
     * Intentionally not readonly because you're free to mutate it whenever you want.
     */
    context: Context;
}
/**
 * The response headers that get returned from graphql-sse.
 *
 * @category Server
 */
export type ResponseHeaders = {
    accept?: string;
    allow?: string;
    'content-type'?: string;
} & Record<string, string>;
/**
 * Server agnostic response body returned from `graphql-sse` needing
 * to be coerced to the server implementation in use.
 *
 * When the body is a string, it is NOT a GraphQL response.
 *
 * @category Server
 */
export type ResponseBody = string | AsyncGenerator<string, void, undefined>;
/**
 * Server agnostic response options (ex. status and headers) returned from
 * `graphql-sse` needing to be coerced to the server implementation in use.
 *
 * @category Server
 */
export interface ResponseInit {
    readonly status: number;
    readonly statusText: string;
    readonly headers?: ResponseHeaders;
}
/**
 * Server agnostic response returned from `graphql-sse` containing the
 * body and init options needing to be coerced to the server implementation in use.
 *
 * @category Server
 */
export type Response = readonly [body: ResponseBody | null, init: ResponseInit];
/**
 * A concrete GraphQL execution context value type.
 *
 * Mainly used because TypeScript collapses unions
 * with `any` or `unknown` to `any` or `unknown`. So,
 * we use a custom type to allow definitions such as
 * the `context` server option.
 *
 * @category Server
 */
export type OperationContext = Record<PropertyKey, unknown> | symbol | number | string | boolean | undefined | null;
/** @category Server */
export type OperationArgs<Context extends OperationContext = undefined> = ExecutionArgs & {
    contextValue: Context;
};
/** @category Server */
export type OperationResult = Promise<AsyncGenerator<ExecutionResult | ExecutionPatchResult> | AsyncIterable<ExecutionResult | ExecutionPatchResult> | ExecutionResult> | AsyncGenerator<ExecutionResult | ExecutionPatchResult> | AsyncIterable<ExecutionResult | ExecutionPatchResult> | ExecutionResult;
/** @category Server */
export interface HandlerOptions<RequestRaw = unknown, RequestContext = unknown, Context extends OperationContext = undefined> {
    /**
     * A custom GraphQL validate function allowing you to apply your
     * own validation rules.
     */
    validate?: typeof graphqlValidate;
    /**
     * Is the `execute` function from GraphQL which is
     * used to execute the query and mutation operations.
     */
    execute?: (args: OperationArgs<Context>) => OperationResult;
    /**
     * Is the `subscribe` function from GraphQL which is
     * used to execute the subscription operation.
     */
    subscribe?: (args: OperationArgs<Context>) => OperationResult;
    /**
     * The GraphQL schema on which the operations will
     * be executed and validated against.
     *
     * If a function is provided, it will be called on every
     * subscription request allowing you to manipulate schema
     * dynamically.
     *
     * If the schema is left undefined, you're trusted to
     * provide one in the returned `ExecutionArgs` from the
     * `onSubscribe` callback.
     */
    schema?: GraphQLSchema | ((req: Request<RequestRaw, RequestContext>, args: Pick<OperationArgs<Context>, 'contextValue' | 'operationName' | 'document' | 'variableValues'>) => Promise<GraphQLSchema> | GraphQLSchema);
    /**
     * Authenticate the client. Returning a string indicates that the client
     * is authenticated and the request is ready to be processed.
     *
     * A distinct token of type string must be supplied to enable the "single connection mode".
     *
     * Providing `null` as the token will completely disable the "single connection mode"
     * and all incoming requests will always use the "distinct connection mode".
     *
     * @default 'req.headers["x-graphql-event-stream-token"] || req.url.searchParams["token"] || generateRandomUUID()' // https://gist.github.com/jed/982883
     */
    authenticate?: (req: Request<RequestRaw, RequestContext>) => Promise<Response | string | undefined | null> | Response | string | undefined | null;
    /**
     * Called when a new event stream is connecting BEFORE it is accepted.
     * By accepted, its meant the server processed the request and responded
     * with a 200 (OK), alongside flushing the necessary event stream headers.
     */
    onConnect?: (req: Request<RequestRaw, RequestContext>) => Promise<Response | null | undefined | void> | Response | null | undefined | void;
    /**
     * A value which is provided to every resolver and holds
     * important contextual information like the currently
     * logged in user, or access to a database.
     *
     * Note that the context function is invoked on each operation only once.
     * Meaning, for subscriptions, only at the point of initialising the subscription;
     * not on every subscription event emission. Read more about the context lifecycle
     * in subscriptions here: https://github.com/graphql/graphql-js/issues/894.
     *
     * If you don't provide the context context field, but have a context - you're trusted to
     * provide one in `onSubscribe`.
     */
    context?: Context | ((req: Request<RequestRaw, RequestContext>, params: RequestParams) => Promise<Context> | Context);
    /**
     * The subscribe callback executed right after processing the request
     * before proceeding with the GraphQL operation execution.
     *
     * If you return `ExecutionArgs` from the callback, it will be used instead of
     * trying to build one internally. In this case, you are responsible for providing
     * a ready set of arguments which will be directly plugged in the operation execution.
     *
     * Omitting the fields `contextValue` from the returned `ExecutionArgs` will use the
     * provided `context` option, if available.
     *
     * If you want to respond to the client with a custom status or body,
     * you should do so using the provided `res` argument which will stop
     * further execution.
     *
     * Useful for preparing the execution arguments following a custom logic. A typical
     * use-case is persisted queries. You can identify the query from the request parameters
     * and supply the appropriate GraphQL operation execution arguments.
     */
    onSubscribe?: (req: Request<RequestRaw, RequestContext>, params: RequestParams) => Promise<Response | OperationResult | OperationArgs<Context> | void> | Response | OperationResult | OperationArgs<Context> | void;
    /**
     * Executed after the operation call resolves. For streaming
     * operations, triggering this callback does not necessarily
     * mean that there is already a result available - it means
     * that the subscription process for the stream has resolved
     * and that the client is now subscribed.
     *
     * The `OperationResult` argument is the result of operation
     * execution. It can be an iterator or already a value.
     *
     * If you want the single result and the events from a streaming
     * operation, use the `onNext` callback.
     *
     * If `onSubscribe` returns an `OperationResult`, this hook
     * will NOT be called.
     */
    onOperation?: (ctx: Context, req: Request<RequestRaw, RequestContext>, args: ExecutionArgs, result: OperationResult) => Promise<OperationResult | void> | OperationResult | void;
    /**
     * Executed after an operation has emitted a result right before
     * that result has been sent to the client.
     *
     * Results from both single value and streaming operations will
     * invoke this callback.
     *
     * Use this callback if you want to format the execution result
     * before it reaches the client.
     *
     * @param req - Always the request that contains the GraphQL operation.
     */
    onNext?: (ctx: Context, req: Request<RequestRaw, RequestContext>, result: ExecutionResult | ExecutionPatchResult) => Promise<ExecutionResult | ExecutionPatchResult | void> | ExecutionResult | ExecutionPatchResult | void;
    /**
     * The complete callback is executed after the operation
     * has completed and the client has been notified.
     *
     * Since the library makes sure to complete streaming
     * operations even after an abrupt closure, this callback
     * will always be called.
     *
     * @param req - Always the request that contains the GraphQL operation.
     */
    onComplete?: (ctx: Context, req: Request<RequestRaw, RequestContext>) => Promise<void> | void;
}
/**
 * The ready-to-use handler. Simply plug it in your favourite fetch-enabled HTTP
 * framework and enjoy.
 *
 * Errors thrown from **any** of the provided options or callbacks (or even due to
 * library misuse or potential bugs) will reject the handler's promise. They are
 * considered internal errors and you should take care of them accordingly.
 *
 * @category Server
 */
export type Handler<RequestRaw = unknown, RequestContext = unknown> = (req: Request<RequestRaw, RequestContext>) => Promise<Response>;
/**
 * Makes a Protocol compliant HTTP GraphQL server handler. The handler can
 * be used with your favourite server library.
 *
 * Read more about the Protocol in the PROTOCOL.md documentation file.
 *
 * @category Server
 */
export declare function createHandler<RequestRaw = unknown, RequestContext = unknown, Context extends OperationContext = undefined>(options: HandlerOptions<RequestRaw, RequestContext, Context>): Handler<RequestRaw, RequestContext>;
export declare function isExecutionResult(val: unknown): val is ExecutionResult;
