import type { PrimaryFieldType } from "../..";
import { s } from "bknd/utils";
import type { ExpressionBuilder, SelectQueryBuilder } from "kysely";
import type { Entity, EntityData, EntityManager } from "../entities";
import { type EntityRelationAnchor, type MutationInstructionResponse, RelationHelper } from "../relations";
import type { RepoQuery } from "../server/query";
import type { RelationType } from "./relation-types";
declare const directions: readonly ["source", "target"];
export type TDirection = (typeof directions)[number];
export type KyselyJsonFrom = any;
export type KyselyQueryBuilder = SelectQueryBuilder<any, any, any>;
export type BaseRelationConfig = s.Static<typeof EntityRelation.schema>;
export declare abstract class EntityRelation<Schema extends typeof EntityRelation.schema = typeof EntityRelation.schema> {
    config: s.Static<Schema>;
    source: EntityRelationAnchor;
    target: EntityRelationAnchor;
    directions: TDirection[];
    static schema: s.ObjectSchema<{
        readonly mappedBy: {
            default?: any;
            maxLength?: number | undefined;
            minLength?: number | undefined;
            pattern?: (string | RegExp) | undefined;
            format?: string | undefined;
            enum?: (readonly any[] | any[]) | undefined;
            const?: any;
        } & s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
        readonly inversedBy: {
            default?: any;
            maxLength?: number | undefined;
            minLength?: number | undefined;
            pattern?: (string | RegExp) | undefined;
            format?: string | undefined;
            enum?: (readonly any[] | any[]) | undefined;
            const?: any;
        } & s.Schema<s.ISchemaOptions, string | undefined, string | undefined>;
        readonly required: {
            default?: any;
            enum?: (readonly any[] | any[]) | undefined;
            const?: any;
        } & s.Schema<s.ISchemaOptions, boolean | undefined, boolean | undefined>;
    }, s.Merge<s.IObjectOptions & {
        additionalProperties: false;
    }>>;
    constructor(source: EntityRelationAnchor, target: EntityRelationAnchor, config?: Partial<s.Static<Schema>>);
    abstract initialize(em: EntityManager<any>): void;
    /**
     * Build the "with" part of the query.
     *
     * @param entity requesting entity, so target needs to be added
     * @param qb
     * @param jsonFrom
     */
    abstract buildWith(entity: Entity, reference: string): (eb: ExpressionBuilder<any, any>) => KyselyQueryBuilder;
    abstract buildJoin(entity: Entity, qb: KyselyQueryBuilder, reference: string): KyselyQueryBuilder;
    getReferenceQuery(entity: Entity, id: PrimaryFieldType, reference: string): Partial<RepoQuery>;
    /** @deprecated */
    helper(entity_name: string): RelationHelper;
    /**
     * Get the other side of the relation quickly
     * @param entity
     */
    other(entity: Entity | string): EntityRelationAnchor;
    self(entity: Entity | string): EntityRelationAnchor;
    ref(reference: string): EntityRelationAnchor;
    otherRef(reference: string): EntityRelationAnchor;
    visibleFrom(from: "source" | "target"): boolean;
    /**
     * Hydrate the relation. "entity" represents where the payload belongs to.
     * E.g. if entity is "categories", then value is the result of categories
     *
     * IMPORTANT: This method is called from EM, high potential of recursion!
     *
     * @param entity
     * @param value
     * @param em
     */
    hydrate(entity: Entity | string, value: EntityData[], em: EntityManager<any>): EntityData | EntityData[] | undefined;
    /**
     * Determines if the relation is listable for the given entity
     * If the given entity is the one with the local reference, then it's not listable
     * Only if there are multiple, which is generally the other side (except for 1:1)
     * @param entity
     */
    isListableFor(entity: Entity): boolean;
    abstract type(): RelationType;
    get required(): boolean;
    $set(em: EntityManager<any>, key: string, value: unknown): Promise<void | MutationInstructionResponse>;
    $create(em: EntityManager<any>, key: string, value: unknown): Promise<void | MutationInstructionResponse>;
    $attach(em: EntityManager<any>, key: string, value: unknown): Promise<void | MutationInstructionResponse>;
    $detach(em: EntityManager<any>, key: string, value: unknown): Promise<void | MutationInstructionResponse>;
    getName(): string;
    toJSON(): {
        type: RelationType;
        source: string;
        target: string;
        config: s.Static<Schema>;
    };
}
export {};
