import { Value } from '@convex-dev/common';

/**
 * Create the API type from the types of all of the modules.
 *
 * Input is an object mapping file paths to the type of each module.
 *
 * For internal use by Convex code generation.
 *
 * @public
 */
export declare type ApiFromModules<Modules extends Record<string, Record<string, any>>> = {
    queries: Expand<ConvertToClientFunctions<PickByValue<MergeAllExports<Modules>, {
        isQuery: true;
    }>>>;
    mutations: Expand<ConvertToClientFunctions<PickByValue<MergeAllExports<Modules>, {
        isMutation: true;
    }>>>;
};

/**
 * The configuration needed to construct a Convex client like the
 * {@link ConvexHttpClient} and {@link react.ConvexReactClient}.
 *
 * This configuration is automatically generated by `npx convex dev` and
 * `npx convex deploy`. You can find the generated version at
 * `convex/_generated/clientConfig.js`.
 *
 * @public
 */
export declare interface ClientConfiguration {
    /**
     * The URL of the Convex deployment.
     */
    address: string;
}

/**
 * Options for {@link InternalConvexClient}.
 *
 * @public
 */
export declare type ClientOptions = {
    /**
     * Whether to prompt the user that have unsaved changes pending
     * when navigating away or closing a web page with pending Convex mutations.
     * This is only possible when the `window` object exists, i.e. in a browser.
     * The default value is `true`.
     */
    unsavedChangesWarning?: boolean;
    /**
     * Specifies an alternate
     * [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
     * constructor to use for client communication with the Convex cloud.
     * The default behavior is to use `WebSocket` from the global environment.
     */
    webSocketConstructor?: typeof WebSocket;
};

/**
 * Converts a map of query and mutation types into their client form.
 *
 * This is done by:
 * - Unwrapping `Promise` if it's in the output.
 * - Switching functions that output `undefined` to `null`.
 *
 */
declare type ConvertToClientFunctions<FunctionsByName extends Record<string, any>> = {
    [Name in keyof FunctionsByName]: (...args: FunctionsByName[Name]["args"]) => UndefinedToNull<Awaited<FunctionsByName[Name]["output"]>>;
};

/**
 * A Convex client that runs queries and mutations over HTTP.
 *
 * This is appropriate for server-side code (like Netlify Lambdas) or non-reactive
 * webapps.
 *
 * If you're building a React app, consider using
 * {@link react.ConvexReactClient} instead.
 *
 *
 * @public
 */
export declare class ConvexHttpClient {
    private readonly address;
    private auth?;
    constructor(clientConfig: ClientConfiguration);
    /**
     * Obtain the {@link ConvexHttpClient}'s URL to its backend.
     *
     * @returns The URL to the Convex backend, including the client's API version.
     */
    backendUrl(): string;
    /**
     * Set the authentication token to be used for subsequent queries and mutations.
     *
     * Should be called whenever the token changes (i.e. due to expiration and refresh).
     *
     * @param value - JWT-encoded OpenID Connect identity token.
     */
    setAuth(value: string): void;
    /**
     * Clear the current authentication token if set.
     */
    clearAuth(): void;
    /**
     * Construct a new {@link Query}.
     *
     * @param name - The name of the query function.
     * @returns The {@link Query} object with that name.
     */
    query<F extends (...args: any[]) => Promise<any>>(name: string): Query<F>;
    /**
     * Construct a new {@link Mutation}.
     *
     * @param name - The name of the mutation function.
     * @returns The {@link Mutation} object with that name.
     */
    mutation<F extends (...args: any[]) => Promise<any>>(name: string): Mutation<F>;
}

/**
 * Common utilities for manipulating TypeScript types.
 * @module
 */
/**
 * Hack! This type causes TypeScript to simplify how it renders object types.
 *
 * It is functionally the identity for object types, but in practice it can
 * simplify expressions like `A & B`.
 */
declare type Expand<ObjectType extends Record<any, any>> = ObjectType extends Record<any, any> ? {
    [Key in keyof ObjectType]: ObjectType[Key];
} : never;

/**
 * Internal Codegen Type Helpers
 */
/**
 * Generate the fully-qualified query/mutation name of an export.
 *
 * This is `path/to/module:export` or `path/to/module` for the default export.
 */
declare type FunctionName<FilePath extends string, ExportName extends string> = ExportName extends "default" ? FilePath : `${FilePath}:${ExportName}`;

/**
 * Description of the Convex functions available to an application.
 *
 * This is a generic type that expresses the shape of API types created by
 * `npx convex codegen`. It's used to make the Convex clients type-safe.
 *
 * @public
 */
export declare type GenericAPI = {
    queries: Record<string, (...args: any[]) => any>;
    mutations: Record<string, (...args: any[]) => any>;
};

/**
 * Low-level client for directly integrating state management libraries
 * with Convex.
 *
 * Most developers should use higher level clients, like
 * the {@link ConvexHttpClient} or the React hook based {@link react.ConvexReactClient}.
 *
 * @public
 */
export declare class InternalConvexClient {
    private readonly state;
    private readonly mutationManager;
    private readonly webSocketManager;
    private remoteQuerySet;
    private readonly optimisticQueryResults;
    private readonly onTransition;
    private nextMutationId;
    private readonly sessionId;
    private connectionCount;
    /**
     * @param clientConfig - The generated client configuration for your project.
     * You can find this at `convex/_generated/clientConfig.js`.
     * @param onTransition - A callback receiving an array of query tokens
     * corresponding to query results that have changed.
     * @param options - See {@link ClientOptions} for a full description.
     */
    constructor(clientConfig: ClientConfiguration, onTransition: (updatedQueries: QueryToken[]) => void, options?: ClientOptions);
    /**
     * Compute the current query results based on the remoteQuerySet and the
     * current optimistic updates and call `onTransition` for all the changed
     * queries.
     *
     * @param completedMutations - A set of mutation IDs whose optimistic updates
     * are no longer needed.
     */
    private notifyOnQueryResultChanges;
    setAuth(value: string): void;
    /** @internal */
    setAdminAuth(value: string): void;
    clearAuth(): void;
    subscribe(udfPath: string, args: any[]): {
        queryToken: QueryToken;
        unsubscribe: () => void;
    };
    /**
     * A query result based only on the current, local state.
     *
     * The only way this will return a value is if we're already subscribed to the
     * query or its value has been set optimistically.
     */
    localQueryResult(udfPath: string, args: any[]): Value | undefined;
    mutate<Args extends any[]>(udfPath: string, args: Args, optimisticUpdate?: OptimisticUpdate<GenericAPI, Args> | null): Promise<any>;
    close(): Promise<void>;
}

/**
 * Name and merge together all of the exports in the `convex/` directory into
 * a flat object type.
 */
declare type MergeAllExports<Modules extends Record<string, Record<string, any>>> = UnionToIntersection<{
    [FilePath in keyof Modules]: NameModule<FilePath & string, Modules[FilePath]>;
}[keyof Modules]>;

/**
 * An interface to execute a Convex mutation function on the server.
 *
 * @public
 */
export declare interface Mutation<F extends (...args: any[]) => Promise<any>> {
    /**
     * Execute the mutation on the server, returning a `Promise` of its return value.
     *
     * @param args - Arguments for the mutation.
     * @returns The return value of the server-side function call.
     */
    (...args: Parameters<F>): Promise<Awaited<ReturnType<F>>>;
}

/**
 * The names of mutation functions in a Convex API.
 *
 * @public
 */
export declare type MutationNames<API extends GenericAPI> = keyof API["mutations"] & string;

/**
 * The type of a mutation function in a Convex API.
 *
 * @public
 */
export declare type NamedMutation<API extends GenericAPI, Name extends MutationNames<API>> = API["mutations"][Name];

/**
 * The type of a query function in a Convex API.
 *
 * @public
 */
export declare type NamedQuery<API extends GenericAPI, Name extends QueryNames<API>> = API["queries"][Name];

/**
 * Generate a type of this module where each export is renamed to its
 * fully-qualified {@link FunctionName}.
 */
declare type NameModule<FilePath extends string, Module extends Record<string, any>> = {
    [ExportName in keyof Module as FunctionName<FilePath, ExportName & string>]: Module[ExportName];
};

/**
 * A view of the query results currently in the Convex client for use within
 * optimistic updates.
 *
 * @public
 */
export declare interface OptimisticLocalStore<API extends GenericAPI = GenericAPI> {
    /**
     * Retrieve the result of a query from the client.
     *
     * Important: Query results should be treated as immutable!
     * Always make new copies of structures within query results to avoid
     * corrupting data within the client.
     *
     * @param name - The name of the query.
     * @param args - An array of the arguments for this query.
     * @returns The query result or `undefined` if the query is not currently
     * in the client.
     */
    getQuery<Name extends QueryNames<API>>(name: Name, args: Parameters<NamedQuery<API, Name>>): undefined | ReturnType<NamedQuery<API, Name>>;
    /**
     * Optimistically update the result of a query.
     *
     * This can either be a new value (perhaps derived from the old value from
     * {@link OptimisticLocalStore.getQuery}) or `undefined` to remove the query.
     * Removing a query is useful to create loading states while Convex recomputes
     * the query results.
     *
     * @param name - The name of the query.
     * @param args - An array of the arguments for this query.
     * @param value - The new value to set the query to or `undefined` to remove
     * it from the client.
     */
    setQuery<Name extends QueryNames<API>>(name: Name, args: Parameters<NamedQuery<API, Name>>, value: undefined | ReturnType<NamedQuery<API, Name>>): void;
}

/**
 * A temporary, local update to query results within this client.
 *
 * This update will always be executed when a mutation is synced to the Convex
 * server and rolled back when the mutation completes.
 *
 * Note that optimistic updates can be called multiple times! If the client
 * loads new data while the mutation is in progress, the update will be replayed
 * again.
 *
 * @param localQueryStore - An interface to read and edit local query results.
 * @param args - The arguments to the mutation.
 *
 * @public
 */
export declare type OptimisticUpdate<API extends GenericAPI, Arguments extends any[]> = (localQueryStore: OptimisticLocalStore<API>, ...args: Arguments) => void;

/**
 * From ObjectType, pick the properties that are assignable to T.
 */
declare type PickByValue<ObjectType, T> = Pick<ObjectType, {
    [Key in keyof ObjectType]: ObjectType[Key] extends T ? Key : never;
}[keyof ObjectType]>;

/**
 * An interface to execute a Convex query function on the server.
 *
 * @public
 */
export declare interface Query<F extends (...args: any[]) => Promise<any>> {
    /**
     * Execute the query on the server, returning a `Promise` of the return value.
     *
     * @param args - Arguments for the query.
     * @returns The result of the query.
     */
    (...args: Parameters<F>): Promise<Awaited<ReturnType<F>>>;
}

/**
 * Helper types for interacting with the overall API type
 */
/**
 * The names of query functions in a Convex API.
 *
 * @public
 */
export declare type QueryNames<API extends GenericAPI> = keyof API["queries"] & string;

/**
 * The result of running a query function on the server.
 *
 * If the function hit an exception it will have an `errorMessage`. Otherwise
 * it will produce a `Value`.
 *
 * @public
 */
export declare type QueryResult = {
    success: true;
    value: Value;
} | {
    success: false;
    errorMessage: string;
};

/**
 * A string representing the name and arguments of a query.
 *
 * This is used by the {@link InternalConvexClient}.
 *
 * @public
 */
export declare type QueryToken = string;

declare type UndefinedToNull<T> = T extends void ? null : T;

/**
 * Convert a union type like `A | B | C` into an intersection type like
 * `A & B & C`.
 */
declare type UnionToIntersection<UnionType> = (UnionType extends any ? (k: UnionType) => void : never) extends (k: infer I) => void ? I : never;

export { }
