import { Attachment } from '@taylordb/shared';
import { AbstractLinkColumn, AnyDB, QueryNode, RootQueryNode, SelectionQueryNode } from './@types/internal-types.js';
import { LinkColumnNames, NonLinkColumnNames } from './@types/query-builder.js';
import { InferDataType, ResolveSelection, ResolveWithObject, ResolveWithPlain } from './@types/type-helpers.js';
import { AggregationQueryBuilder } from './aggregation-query-builder.js';
import { AnyQueryBuilder, AreAllBuildersSubscribable, BatchQueryBuilder } from './batch-query-builder.js';
import { DeleteQueryBuilder } from './delete-query-builder.js';
import { Executor } from './executor.js';
import { InsertQueryBuilder } from './insert-query-builder.js';
import { UpdateQueryBuilder } from './update-query-builder.js';
import { FilterableQueryBuilder } from './where-query-builder.js';
/**
 * The main query builder class for constructing and executing select queries.
 * @template DB - The database type.
 * @template TableName - The name of the table to query.
 * @template Selection - The type of the selected fields.
 * @template LinkName - The name of the link field if this is a subquery.
 */
export declare class QueryBuilder<DB extends AnyDB, TableName extends keyof DB, Selection = object, LinkName = null> extends FilterableQueryBuilder<DB, TableName> {
    _node: QueryNode;
    constructor(node: QueryNode, executor: Executor);
    /**
     * Counts the number of records that match the query.
     * @returns A promise that resolves with the total number of records.
     *
     * @example
     * ```typescript
     * const totalUsers = await qb
     *  .selectFrom('users')
     *  .where('age', '>', 30)
     *  .count();
     * ```
     */
    count(): Promise<number>;
    /**
     * Selects a set of fields from the table.
     * @param fields - An array of field names to select.
     * @returns A new `QueryBuilder` instance with the specified fields selected.
     *
     * @example
     * ```typescript
     * const users = await qb
     *   .selectFrom('users')
     *   .select(['id', 'name'])
     *   .execute();
     * ```
     */
    select<const TFields extends readonly NonLinkColumnNames<DB[TableName]>[]>(fields: TFields): QueryBuilder<DB, TableName, ResolveSelection<DB, TableName, TFields, Selection>>;
    /**
     * Selects all fields from the table.
     * @returns A new `QueryBuilder` instance with all fields selected.
     *
     * @example
     * ```typescript
     * const users = await qb
     *   .selectFrom('users')
     *   .selectAll()
     *   .execute();
     * ```
     */
    selectAll(): QueryBuilder<DB, TableName, Selection & {
        [K in keyof DB[TableName]]: InferDataType<DB[TableName][K]>;
    }>;
    /**
     * Includes related records from a linked table.
     * This method has two overloads:
     * 1. Pass an array of link field names to include all fields from the related records.
     * 2. Pass an object to specify subqueries for each link field.
     *
     * @param relations - The relations to include.
     * @returns A new `QueryBuilder` instance with the specified relations included.
     *
     * @example
     * ```typescript
     * const usersWithPosts = await qb
     *   .selectFrom('users')
     *   .select(['id', 'name'])
     *   .with(['posts']) // Assuming 'posts' is a link field on the 'users' table
     *   .execute();
     * ```
     *
     * @example
     * ```typescript
     * const usersWithPublishedPosts = await qb
     *   .selectFrom('users')
     *   .select(['id', 'name'])
     *   .with({
     *     posts: (qb) => qb.select(['title', 'content']).where('isPublished', '=', true),
     *   })
     *   .execute();
     * ```
     */
    with<const TArg extends (LinkColumnNames<DB[TableName]> & string) | readonly (LinkColumnNames<DB[TableName]> & string)[]>(relations: TArg): QueryBuilder<DB, TableName, ResolveWithPlain<DB, TableName, TArg, Selection>>;
    with<const TArg extends {
        [K in LinkColumnNames<DB[TableName]>]?: (qb: QueryBuilder<DB, DB[TableName][K] extends AbstractLinkColumn ? DB[TableName][K]['linkedTo'] : never, object, K>) => QueryBuilder<DB, any, any, any>;
    }>(relations: TArg): QueryBuilder<DB, TableName, ResolveWithObject<TArg, Selection>>;
    /**
     * Sets the maximum number of records to return.
     * @param count - The maximum number of records.
     * @returns A new `QueryBuilder` instance with the limit applied.
     *
     * @example
     * ```typescript
     * const users = await qb
     *   .selectFrom('users')
     *   .select(['id', 'name'])
     *   .limit(10)
     *   .execute();
     * ```
     */
    limit(count: number): QueryBuilder<DB, TableName, Selection, LinkName>;
    /**
     * Sets the number of records to skip.
     * @param count - The number of records to skip.
     * @returns A new `QueryBuilder` instance with the offset applied.
     *
     * @example
     * ```typescript
     * const users = await qb
     *   .selectFrom('users')
     *   .select(['id', 'name'])
     *   .offset(10)
     *   .execute();
     * ```
     */
    offset(count: number): QueryBuilder<DB, TableName, Selection, LinkName>;
    /**
     * Paginates the results.
     * @param page - The page number to retrieve.
     * @param limit - The number of records per page.
     * @returns A new `QueryBuilder` instance with pagination applied.
     *
     * @example
     * ```typescript
     * const users = await qb
     *   .selectFrom('users')
     *   .select(['id', 'name'])
     *   .paginate(2, 25) // Retrieves page 2 with 25 records per page
     *   .execute();
     * ```
     */
    paginate(page: number, limit: number): QueryBuilder<DB, TableName, Selection, LinkName>;
    /**
     * Sorts the results by a specified field.
     * @param field - The field to sort by.
     * @param direction - The sort direction ('asc' or 'desc').
     * @returns A new `QueryBuilder` instance with the sorting applied.
     *
     * @example
     * ```typescript
     * const users = await qb
     *   .selectFrom('users')
     *   .select(['id', 'name'])
     *   .orderBy('name', 'asc')
     *   .execute();
     * ```
     */
    orderBy(field: keyof DB[TableName], direction?: 'asc' | 'desc'): QueryBuilder<DB, TableName, Selection, LinkName>;
    /**
     * Executes the select query.
     * @returns A promise that resolves with an array of the selected records.
     *
     * @example
     * ```typescript
     * const users = await qb
     *   .selectFrom('users')
     *   .select(['id', 'name'])
     *   .execute();
     * ```
     */
    execute(): Promise<Selection[]>;
    /**
     * Executes the select query and returns the first result.
     * @returns A promise that resolves with the first record, or `null` if no records were found.
     *
     * @example
     * ```typescript
     * const user = await qb
     *   .selectFrom('users')
     *   .where('id', '=', 1)
     *   .select(['id', 'name'])
     *   .executeTakeFirst();
     * ```
     */
    executeTakeFirst(): Promise<Selection | null>;
    /**
     * Transforms the response by converting attachment objects to absolute URL strings.
     * @private
     */
    private _transformResponse;
    /**
     * Checks if an object looks like an attachment object.
     * @private
     */
    private _isAttachmentObject;
    subscribe(callback: (result: Selection[]) => void): Promise<{
        unsubscribe: () => Promise<void>;
    }>;
    compile(): {
        query: string;
        variables: Record<string, any>;
    };
    _prepareMetadata(): any;
    isSelectionQueryNode(node: QueryNode): node is SelectionQueryNode;
    isRootQueryNode(node: QueryNode): node is RootQueryNode;
}
/**
 * The root query builder class that provides entry points for all query types.
 */
export declare class BaseRootQueryBuilder<DB extends AnyDB> {
    protected _executor: Executor;
    constructor(executor: Executor);
    /**
     * Creates a new select query builder for the specified table.
     * @param from - The name of the table to select from.
     * @returns A new `QueryBuilder` instance.
     *
     * @example
     * ```typescript
     * const qb = createQueryBuilder<MyDatabase>({ ... });
     * const userQuery = qb.selectFrom('users');
     * ```
     */
    selectFrom<TableName extends keyof Omit<DB, 'selectTable' | 'attachmentTable' | 'collaboratorsTable'> & string>(from: TableName): QueryBuilder<DB, TableName>;
    /**
     * Creates a new insert query builder for the specified table.
     * @param into - The name of the table to insert into.
     * @returns A new `InsertQueryBuilder` instance.
     *
     * @example
     * ```typescript
     * const qb = createQueryBuilder<MyDatabase>({ ... });
     * const insertQuery = qb.insertInto('users');
     * ```
     */
    insertInto<TableName extends keyof Omit<DB, 'selectTable' | 'attachmentTable' | 'collaboratorsTable'> & string>(into: TableName): InsertQueryBuilder<DB, TableName>;
    /**
     * Creates a new update query builder for the specified table.
     * @param tableName - The name of the table to update.
     * @returns A new `UpdateQueryBuilder` instance.
     *
     * @example
     * ```typescript
     * const qb = createQueryBuilder<MyDatabase>({ ... });
     * const updateQuery = qb.update('users');
     * ```
     */
    update<TableName extends keyof Omit<DB, 'selectTable' | 'attachmentTable' | 'collaboratorsTable'> & string>(tableName: TableName): UpdateQueryBuilder<DB, TableName>;
    /**
     * Creates a new delete query builder for the specified table.
     * @param tableName - The name of the table to delete from.
     * @returns A new `DeleteQueryBuilder` instance.
     *
     * @example
     * ```typescript
     * const qb = createQueryBuilder<MyDatabase>({ ... });
     * const deleteQuery = qb.deleteFrom('users');
     * ```
     */
    deleteFrom<TableName extends keyof Omit<DB, 'selectTable' | 'attachmentTable' | 'collaboratorsTable'> & string>(tableName: TableName): DeleteQueryBuilder<DB, TableName>;
    /**
     * Creates a new batch query builder.
     * @param builders - An array of query builders to execute in a batch.
     * @returns A new `BatchQueryBuilder` instance.
     *
     * @example
     * ```typescript
     * const qb = createQueryBuilder<MyDatabase>({ ... });
     * const batchQuery = qb.batch([
     *   qb.selectFrom('users').select(['id', 'name']),
     *   qb.insertInto('users').values({ name: 'New User' }),
     * ]);
     * const [users, newUser] = await batchQuery.execute();
     * ```
     */
    batch<const TBuilders extends readonly AnyQueryBuilder[]>(builders: TBuilders): AreAllBuildersSubscribable<TBuilders> extends true ? BatchQueryBuilder<TBuilders> : Omit<BatchQueryBuilder<TBuilders>, 'subscribe'>;
    /**
     * Creates a new aggregation query builder for the specified table.
     * @param tableName - The name of the table to aggregate from.
     * @returns A new `AggregationQueryBuilder` instance.
     *
     * @example
     * ```typescript
     * const qb = createQueryBuilder<MyDatabase>({ ... });
     * const aggregateQuery = qb.aggregateFrom('users');
     * ```
     */
    aggregateFrom<TableName extends keyof Omit<DB, 'selectTable' | 'attachmentTable' | 'collaboratorsTable'> & string>(tableName: TableName): AggregationQueryBuilder<DB, TableName>;
    uploadAttachments(files: {
        file: Blob;
        name: string;
    }[]): Promise<Attachment[]>;
}
export declare class RootQueryBuilder<DB extends AnyDB> extends BaseRootQueryBuilder<DB> {
    constructor(executor: Executor);
    transaction<T>(callback: (qb: BaseRootQueryBuilder<DB>) => Promise<T>): Promise<T>;
}
export declare function createQueryBuilder<DB extends AnyDB>(config: {
    baseUrl: string;
    baseId: string;
    apiKey: string;
}): RootQueryBuilder<DB>;
