import type { EmptyObject } from 'type-fest';
import type { ObjectModel } from './core';
import { type AnyObject, type DefaultValueProvider, type Model, type ModelMetadata } from './model.js';
export type ModelBuilderPropertyOptions = Readonly<{
    meta?: ModelMetadata;
}>;
declare const $model: unique symbol;
export type Flags = {
    named: boolean;
    selfRefKeys: keyof any;
};
export declare class CoreModelBuilder<V, EX extends AnyObject = EmptyObject, F extends Flags = {
    named: false;
    selfRefKeys: never;
}> {
    protected readonly [$model]: Model<V, EX>;
    constructor(base: Model, defaultValueProvider?: (model: Model<V, EX>) => V);
    meta(value: ModelMetadata): this;
    define<DK extends symbol, DV>(key: DK, value: TypedPropertyDescriptor<DV>): CoreModelBuilder<V, EX & Readonly<Record<DK, DV>>, F>;
    defaultValueProvider(defaultValueProvider: DefaultValueProvider<V, EX>): this;
    name(name: string): CoreModelBuilder<V, EX, {
        named: true;
        selfRefKeys: F['selfRefKeys'];
    }>;
    build(this: F['named'] extends true ? this : never): Model<V, EX>;
}
export declare class ObjectModelBuilder<V extends AnyObject, CV extends AnyObject = EmptyObject, EX extends AnyObject = EmptyObject, F extends Flags = {
    named: false;
    selfRefKeys: never;
}> extends CoreModelBuilder<V, EX, F> {
    constructor(base: Model);
    object<NV extends AnyObject>(this: F['named'] extends false ? this : never, name: string): ObjectModelBuilder<NV & V, CV, EX, {
        named: true;
        selfRefKeys: F['selfRefKeys'];
    }>;
    ['define']: <DK extends symbol, DV>(key: DK, value: TypedPropertyDescriptor<DV>) => ObjectModelBuilder<V, CV, EX & Readonly<Record<DK, DV>>, F>;
    ['meta']: (value: ModelMetadata) => this;
    property<PK extends string & keyof V, EXK extends AnyObject = EmptyObject>(key: PK, model: Model<V[PK], EXK> | ((model: Model<V, EX & Readonly<Record<PK, Model<V[PK], EXK>>>>) => Model<V[PK], EXK>), options?: ModelBuilderPropertyOptions): Extract<V[PK], V> extends never ? ObjectModelBuilder<V, CV & Readonly<Record<PK, V[PK]>>, EX & Readonly<Record<PK, Model<V[PK], EXK>>>, F> : ObjectModelBuilder<V, CV & Readonly<Record<PK, V[PK]>>, EX, {
        named: F['named'];
        selfRefKeys: F['selfRefKeys'] | PK;
    }>;
    build: (this: F['named'] extends true ? (CV extends V ? this : never) : never) => ObjectModel<V, EX, F['selfRefKeys']>;
}
export {};
