import * as server_with_kill from 'server-with-kill';
import express from 'express';

type ScenarioWithOptionalProperties = {
    name?: string;
    description?: string;
    context?: Context;
    mocks: Mock[];
    extend?: string;
    group?: string;
};
type Scenario = ScenarioWithOptionalProperties | Mock[];
type Groups = Record<string, string>;
type ApiScenario = {
    id: string;
    name: string;
    description: null | string;
    selected: boolean;
    group: null | string;
};
type ScenarioMap = Record<string, Scenario>;
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
type ResponseFunction<TInput, TResponse> = (input: TInput & {
    updateContext: UpdateContext;
    context: Context;
}) => TResponse | Promise<TResponse>;
type MockResponse<TInput, TResponse> = TResponse | ResponseFunction<TInput, TResponse>;
type HttpResponse = Record<string, unknown> | string | null;
type ResponseProps<TInput, TResponse> = {
    response?: MockResponse<TInput, {
        data?: TResponse;
        status?: number;
        headers?: Record<string, string>;
        delay?: number;
    }>;
};
type HttpMock = {
    path: string | RegExp;
    method: HttpMethod;
} & ResponseProps<{
    query: Record<string, string | Array<string>>;
    body: Record<string, unknown>;
    params: Record<string, string>;
    headers: Record<string, string>;
}, HttpResponse>;
type GraphQlResponse = {
    data?: null | Record<string, unknown>;
    errors?: Array<unknown>;
};
type Operation = {
    type: 'query' | 'mutation';
    name: string;
} & ResponseProps<{
    variables: Record<string, unknown>;
    headers: Record<string, string>;
}, GraphQlResponse>;
type GraphQlMock = {
    path: string;
    method: 'GRAPHQL';
    operations: Array<Operation>;
};
type Mock = HttpMock | GraphQlMock;
type Options = {
    port?: number;
    uiPath?: string;
    selectScenarioPath?: string;
    scenariosPath?: string;
    groupsPath?: string;
    cookieMode?: boolean;
    parallelContextSize?: number;
};
type Context = Record<string, unknown>;
type PartialContext = Context | ((context: Context) => Context);
type UpdateContext = (partialContext: PartialContext) => Context;

declare function run({ scenarios, options, groups, }: {
    scenarios: ScenarioMap;
    options?: Options;
    groups?: Groups;
}): server_with_kill.ServerWithKill;

declare function createExpressApp({ scenarios: externalScenarioMap, options, groups, }: {
    scenarios: ScenarioMap;
    options?: Omit<Options, 'port'>;
    groups?: Groups;
}): ReturnType<typeof express>;

export { ApiScenario, GraphQlMock, HttpMock, Mock, Operation, Options, Scenario, createExpressApp, run };
