import { StandardSchemaV1 } from '@standard-schema/spec';

interface SchemQlAdapter<T = unknown> {
    queryFirst: QueryFn<T | undefined>;
    queryFirstOrThrow: QueryFn<T>;
    queryAll: QueryFn<T[]>;
    queryIterate: IterativeQueryFn<T>;
}
type QueryFn<TQueryResult, TParams extends Record<string, any> | undefined = Record<string, any> | undefined> = (sql: string) => (params?: TParams) => TQueryResult | Promise<TQueryResult>;
type IterativeQueryFn<TQueryResult, TParams extends Record<string, any> | undefined = Record<string, any> | undefined> = (sql: string) => (params?: TParams) => GeneratorFn<TQueryResult> | AsyncGeneratorFn<TQueryResult>;
type ArrayElement<T> = T extends (infer U)[] ? U : T;
type GeneratorFn<T> = () => Generator<T, void, unknown>;
type AsyncGeneratorFn<T> = () => AsyncGenerator<T, void, unknown>;
type TableNames<DB> = Extract<keyof DB, string>;
type ColumnNames<DB, T extends TableNames<DB>> = Extract<keyof DB[T], string>;
type TableColumnSelection<DB> = {
    [T in TableNames<DB>]?: ColumnNames<DB, T>[];
};
type ValidTableColumnCombinations<DB> = {
    [T in TableNames<DB>]: `${T}.${ColumnNames<DB, T>}` | `${T}.${ColumnNames<DB, T>}-`;
}[TableNames<DB>];
type JsonPathForObjectArrow<T, P extends string = ''> = T extends Record<string, any> ? {
    [K in keyof T & string]: `${P}->${K}` | `${P}->${K}-` | `${P}->>${K}` | `${P}->>${K}-` | (NonNullable<T[K]> extends Record<string, any> ? `${P}->${K}${JsonPathForObjectArrow<NonNullable<T[K]>, ''>}` : never);
}[keyof T & string] : '';
type JsonPathForObjectDot<T, P extends string = ''> = T extends Record<string, any> ? {
    [K in keyof T & string]: `${P}.${K}` | (NonNullable<T[K]> extends Record<string, any> ? `${P}.${K}${JsonPathForObjectDot<NonNullable<T[K]>, ''>}` : never);
}[keyof T & string] : '';
type JsonPathCombinations<DB, T extends TableNames<DB>> = {
    [K in ColumnNames<DB, T>]: DB[T][K] extends object ? JsonPathForObjectArrow<ArrayElement<DB[T][K]>, `${T}.${K} `> | JsonPathForObjectDot<ArrayElement<DB[T][K]>, `${T}.${K} $`> : never;
}[ColumnNames<DB, T>];
type ValidJsonPathCombinations<DB> = {
    [T in TableNames<DB>]: JsonPathCombinations<DB, T>;
}[TableNames<DB>];
type SqlTemplateValue<TResultSchema, TParams, DB> = TableColumnSelection<DB> | `@${TableNames<DB>}` | `@${TableNames<DB>}.*` | `@${ValidTableColumnCombinations<DB>}` | `@${ValidJsonPathCombinations<DB>}` | `$${keyof ArrayElement<Exclude<TResultSchema, undefined>> & string}` | `:${keyof TParams & string}` | `§${string}`;
type SqlTemplateValues<TResultSchema, TParams, DB> = SqlTemplateValue<TResultSchema, TParams, DB>[];
type SqlOrBuilderFn<TResultSchema extends StandardSchemaV1 | undefined, TParams extends Record<string, any>, DB> = string | ((s: SchemQlSqlHelper<TResultSchema, TParams, DB>) => string);
type SchemQlSqlHelper<TResultSchema extends StandardSchemaV1 | undefined, TParams extends Record<string, any>, DB> = {
    sql: <T extends SqlTemplateValues<TResultSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TResultSchema> : unknown, TParams, DB>>(strings: TemplateStringsArray, ...values: T) => string;
    sqlCond: (condition: boolean, ifTrue: string | number, ifFalse?: string | number) => `§${string}`;
    sqlRaw: (raw: string | number) => `§${string}`;
};
type SchemQlOptions = {
    adapter: SchemQlAdapter;
    /** @deprecated Use `stringifyObjectParams` instead */
    shouldStringifyObjectParams?: boolean;
    stringifyObjectParams?: boolean;
    quoteSqlIdentifiers?: boolean;
};
type IsIterativeExecution<TParams> = TParams extends any[] ? true : TParams extends AsyncGeneratorFn<any> ? true : TParams extends GeneratorFn<any> ? true : false;
type ParamsType<T> = T extends AsyncGeneratorFn<infer P> ? P : T extends GeneratorFn<infer P> ? P : T extends Array<infer P> ? P : T;
type SimpleQueryExecutorResult<TQueryResult, TResultSchema extends StandardSchemaV1 | undefined> = TResultSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TResultSchema> : TQueryResult;
type QueryExecutor<DB> = <TQueryResult = unknown, TParams extends QueryExecutorParams = QueryExecutorParams, TParamsSchema extends StandardSchemaV1 | undefined = undefined, TResultSchema extends StandardSchemaV1 | undefined = undefined>(options: {
    params?: QueryExecutorOptionsParams<TParams, TParamsSchema>;
    paramsSchema?: TParamsSchema;
    resultSchema?: TResultSchema;
}) => (sqlOrBuilderFn: SqlOrBuilderFn<TResultSchema, ParamsType<TParams>, DB>) => Promise<QueryExecutorResult<TQueryResult, TParams, TResultSchema>>;
type QueryExecutorParams = Record<string, any> | Record<string, any>[] | GeneratorFn<Record<string, any>> | AsyncGeneratorFn<Record<string, any>>;
type QueryExecutorOptionsParams<TParams, TParamsSchema extends StandardSchemaV1 | undefined> = TParams extends AsyncGeneratorFn<infer P> ? AsyncGeneratorFn<P> : TParams extends GeneratorFn<infer P> ? GeneratorFn<P> : TParams extends Array<infer P> ? P[] : TParamsSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TParamsSchema> : TParams;
type QueryExecutorResult<TQueryResult, TParams, TResultSchema extends StandardSchemaV1 | undefined> = IsIterativeExecution<TParams> extends true ? AsyncGenerator<SimpleQueryExecutorResult<TQueryResult, TResultSchema>, void, unknown> : SimpleQueryExecutorResult<TQueryResult, TResultSchema>;
type IterativeQueryExecutor<DB> = <TQueryResult = unknown, TParams extends Record<string, any> = Record<string, any>, TParamsSchema extends StandardSchemaV1 | undefined = undefined, TResultSchema extends StandardSchemaV1 | undefined = undefined>(options: {
    params?: TParamsSchema extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<TParamsSchema> : TParams;
    paramsSchema?: TParamsSchema;
    resultSchema?: TResultSchema;
}) => (sqlOrBuilderFn: SqlOrBuilderFn<TResultSchema, TParams, DB>) => Promise<AsyncGenerator<SimpleQueryExecutorResult<TQueryResult, TResultSchema>, void, unknown>>;
declare class SchemQl<DB> {
    private readonly options;
    first: QueryExecutor<DB>;
    firstOrThrow: QueryExecutor<DB>;
    all: QueryExecutor<DB>;
    iterate: IterativeQueryExecutor<DB>;
    constructor(options: SchemQlOptions);
    private createQueryExecutor;
    private createIterativeExecutor;
    private validateAndStringifyParams;
    private createSqlHelper;
    private processLiteralExpressions;
    private processLiteralExpression;
}

export { type SchemQlAdapter as S, SchemQl as a };
