import type { ValidationFunction, ValidationFunctionResult } from '@naturalcycles/js-lib';
import type { Set2 } from '@naturalcycles/js-lib/object';
import type { AnyObject, BaseDBEntity, IANATimezone, Inclusiveness, IsoDate, IsoDateTime, IsoMonth, NumberEnum, StringEnum, StringMap, UnixTimestamp, UnixTimestampMillis } from '@naturalcycles/js-lib/types';
import type { StandardJSONSchemaV1, StandardSchemaV1 } from '@standard-schema/spec';
import type { Ajv } from 'ajv';
import { AjvValidationError } from './ajvValidationError.js';
export declare const j: {
    /**
     * Matches literally any value - equivalent to TypeScript's `any` type.
     * Use sparingly, as it bypasses type validation entirely.
     */
    any(): JBuilder<any, false>;
    string(): JString<string, false>;
    number(): JNumber<number, false>;
    boolean(): JBoolean<boolean, false>;
    object: typeof object & {
        dbEntity: typeof objectDbEntity;
        infer: typeof objectInfer;
        any(): JObject<AnyObject, false>;
        stringMap<S extends JSchema<any, any>>(schema: S): JObject<StringMap<SchemaOut<S>>>;
        /**
         * @experimental Look around, maybe you find a rule that is better for your use-case.
         *
         * For Record<K, V> type of validations.
         * ```ts
         * const schema = j.object
         *  .record(
         *    j
         *      .string()
         *      .regex(/^\d{3,4}$/)
         *      .branded<B>(),
         *    j.number().nullable(),
         *  )
         *  .isOfType<Record<B, number | null>>()
         * ```
         *
         * When the keys of the Record are values from an Enum, prefer `j.object.withEnumKeys`!
         *
         * Non-matching keys will be stripped from the object, i.e. they will not cause an error.
         *
         * Caveat: This rule first validates values of every properties of the object, and only then validates the keys.
         * A consequence of that is that the validation will throw when there is an unexpected property with a value not matching the value schema.
         */
        record: typeof record;
        /**
         * For Record<ENUM, V> type of validations.
         *
         * When the keys of the Record are values from an Enum,
         * this helper is more performant and behaves in a more conventional manner than `j.object.record` would.
         *
         *
         */
        withEnumKeys: typeof withEnumKeys;
        withRegexKeys: typeof withRegexKeys;
        /**
         * Validates that the value is an instance of the given class/constructor.
         *
         * ```ts
         * j.object.instanceOf(Date) // typed as Date
         * j.object.instanceOf(Date).optional() // typed as Date | undefined
         * ```
         */
        instanceOf<T>(ctor: new (...args: any[]) => T): JBuilder<T, false>;
    };
    array<OUT, Opt>(itemSchema: JSchema<OUT, Opt>): JArray<OUT, Opt>;
    tuple<const S extends JSchema<any, any>[]>(items: S): JTuple<S>;
    set<OUT_1, Opt_1>(itemSchema: JSchema<OUT_1, Opt_1>): JSet2Builder<OUT_1, Opt_1>;
    buffer(): JBuilder<Buffer, false>;
    enum<const T extends readonly (string | number | boolean | null)[] | StringEnum | NumberEnum>(input: T, opt?: JsonBuilderRuleOpt): JEnum<T extends readonly (infer U)[] ? U : T extends StringEnum ? T[keyof T] : T extends NumberEnum ? T[keyof T] : never>;
    /**
     * Use only with primitive values, otherwise this function will throw to avoid bugs.
     * To validate objects, use `anyOfBy`.
     *
     * Our Ajv is configured to strip unexpected properties from objects,
     * and since Ajv is mutating the input, this means that it cannot
     * properly validate the same data over multiple schemas.
     *
     * Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
     * Use `oneOf` when schemas are mutually exclusive.
     */
    oneOf<B extends readonly JSchema<any, boolean>[]>(items: [...B]): JBuilder<BuilderOutUnion<B>, false>;
    /**
     * Use only with primitive values, otherwise this function will throw to avoid bugs.
     * To validate objects, use `anyOfBy` or `anyOfThese`.
     *
     * Our Ajv is configured to strip unexpected properties from objects,
     * and since Ajv is mutating the input, this means that it cannot
     * properly validate the same data over multiple schemas.
     *
     * Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
     * Use `oneOf` when schemas are mutually exclusive.
     */
    anyOf<B_1 extends readonly JSchema<any, boolean>[]>(items: [...B_1]): JBuilder<BuilderOutUnion<B_1>, false>;
    /**
     * Pick validation schema for an object based on the value of a specific property.
     *
     * ```
     * const schemaMap = {
     *   true: successSchema,
     *   false: errorSchema
     * }
     *
     * const schema = j.anyOfBy('success', schemaMap)
     * ```
     */
    anyOfBy<D extends Record<PropertyKey, JSchema<any, any>>>(propertyName: string, schemaDictionary: D): JBuilder<AnyOfByOut<D>, false>;
    /**
     * Custom version of `anyOf` which - in contrast to the original function - does not mutate the input.
     * This comes with a performance penalty, so do not use it where performance matters.
     *
     * ```
     * const schema = j.anyOfThese([successSchema, errorSchema])
     * ```
     */
    anyOfThese<B_2 extends readonly JSchema<any, boolean>[]>(items: [...B_2]): JBuilder<BuilderOutUnion<B_2>, false>;
    and(): {
        silentBob: () => never;
    };
    literal<const V extends string | number | boolean | null>(v: V): JEnum<V, false>;
    /**
     * Create a JSchema from a plain JsonSchema object.
     * Useful when the schema is loaded from a JSON file or generated externally.
     *
     * Optionally accepts a custom Ajv instance and/or inputName for error messages.
     */
    fromSchema<OUT_2>(schema: JsonSchema<OUT_2>, cfg?: {
        ajv?: Ajv;
        inputName?: string;
    }): JSchema<OUT_2, false>;
};
export declare const HIDDEN_AJV_SCHEMA: unique symbol;
export type WithCachedAjvSchema<Base, OUT> = Base & {
    [HIDDEN_AJV_SCHEMA]: AjvSchema<OUT>;
};
export declare class JSchema<OUT, Opt> implements StandardSchemaV1<unknown, OUT>, StandardJSONSchemaV1<unknown, OUT> {
    protected [HIDDEN_AJV_SCHEMA]: AjvSchema<any> | undefined;
    protected schema: JsonSchema;
    private _cfg?;
    constructor(schema: JsonSchema, cfg?: {
        ajv?: Ajv;
        inputName?: string;
    });
    private _builtSchema?;
    private _compiledFns?;
    private _getBuiltSchema;
    private _getCompiled;
    getSchema(): JsonSchema;
    /**
     * @deprecated
     * The usage of this function is discouraged as it defeats the purpose of having type-safe validation.
     */
    castAs<T>(): JSchema<T, Opt>;
    /**
     * A helper function that takes a type parameter and compares it with the type inferred from the schema.
     *
     * When the type inferred from the schema differs from the passed-in type,
     * the schema becomes unusable, by turning its type into `never`.
     */
    isOfType<ExpectedType>(): ExactMatch<ExpectedType, OUT> extends true ? this : never;
    /**
     * Produces a "clean schema object" without methods.
     * Same as if it would be JSON.stringified.
     */
    build(): JsonSchema<OUT>;
    clone(): this;
    cloneAndUpdateSchema(schema: Partial<JsonSchema>): this;
    get ['~standard'](): StandardSchemaV1.Props<unknown, OUT> & StandardJSONSchemaV1.Props<unknown, OUT>;
    validate(input: unknown, opt?: AjvValidationOptions): OUT;
    isValid(input: unknown, opt?: AjvValidationOptions): boolean;
    getValidationResult(input: unknown, opt?: AjvValidationOptions): ValidationFunctionResult<OUT, AjvValidationError>;
    getValidationFunction(opt?: AjvValidationOptions): ValidationFunction<OUT, AjvValidationError>;
    /**
     * Specify a function to be called after the normal validation is finished.
     *
     * This function will receive the validated, type-safe data, and you can use it
     * to do further validations, e.g. conditional validations based on certain property values,
     * or to do data modifications either by mutating the input or returning a new value.
     *
     * If you throw an error from this function, it will show up as an error in the validation.
     */
    postValidation<OUT2 = OUT>(fn: PostValidatonFn<OUT, OUT2>): JSchema<OUT2, Opt>;
    /**
     * @experimental
     */
    out: OUT;
    opt: Opt;
    /** Forces OUT to be invariant (prevents covariant subtype matching in object property constraints). */
    protected _invariantOut: (x: OUT) => void;
}
export declare class JBuilder<OUT, Opt> extends JSchema<OUT, Opt> {
    protected setErrorMessage(ruleName: string, errorMessage: string | undefined): void;
    /**
     * @deprecated
     * The usage of this function is discouraged as it defeats the purpose of having type-safe validation.
     */
    castAs<T>(): JBuilder<T, Opt>;
    $schema($schema: string): this;
    $schemaDraft7(): this;
    $id($id: string): this;
    title(title: string): this;
    description(description: string): this;
    deprecated(deprecated?: boolean): this;
    type(type: string): this;
    default(v: any): this;
    instanceof(of: string): this;
    /**
     * @param optionalValues List of values that should be considered/converted as `undefined`.
     *
     * This `optionalValues` feature only works when the current schema is nested in an object or array schema,
     * due to how mutability works in Ajv.
     *
     * Make sure this `optional()` call is at the end of your call chain.
     *
     * When `null` is included in optionalValues, the return type becomes `JSchema`
     * (no further chaining allowed) because the schema is wrapped in an anyOf structure.
     */
    optional<T extends readonly (string | number | boolean | null)[] | undefined = undefined>(optionalValues?: T): T extends readonly (string | number | boolean | null)[] ? JSchema<OUT | undefined, true> : JBuilder<OUT | undefined, true>;
    nullable(): JBuilder<OUT | null, Opt>;
    /**
     * Locks the given schema chain and no other modification can be done to it.
     */
    final(): JSchema<OUT, Opt>;
    /**
     *
     * @param validator A validator function that returns an error message or undefined.
     *
     * You may add multiple custom validators and they will be executed in the order you added them.
     */
    custom<OUT2 = OUT>(validator: CustomValidatorFn): JBuilder<OUT2, Opt>;
    /**
     *
     * @param converter A converter function that returns a new value.
     *
     * You may add multiple converters and they will be executed in the order you added them,
     * each converter receiving the result from the previous one.
     *
     * This feature only works when the current schema is nested in an object or array schema,
     * due to how mutability works in Ajv.
     */
    convert<OUT2>(converter: CustomConverterFn<OUT2>): JBuilder<OUT2, Opt>;
}
export declare class JString<OUT extends string | undefined = string, Opt extends boolean = false> extends JBuilder<OUT, Opt> {
    constructor();
    regex(pattern: RegExp, opt?: JsonBuilderRuleOpt): this;
    pattern(pattern: string, opt?: JsonBuilderRuleOpt): this;
    minLength(minLength: number): this;
    maxLength(maxLength: number): this;
    length(exactLength: number): this;
    length(minLength: number, maxLength: number): this;
    email(opt?: Partial<JsonSchemaStringEmailOptions>): this;
    trim(): this;
    toLowerCase(): this;
    toUpperCase(): this;
    truncate(toLength: number): this;
    branded<B extends string>(): JString<B, Opt>;
    /**
     * Validates that the input is a fully-specified YYYY-MM-DD formatted valid IsoDate value.
     *
     * All previous expectations in the schema chain are dropped - including `.optional()` -
     * because this call effectively starts a new schema chain.
     */
    isoDate(): JIsoDate;
    isoDateTime(): JString<IsoDateTime, Opt>;
    isoMonth(): JBuilder<IsoMonth, false>;
    /**
     * Validates the string format to be JWT.
     * Expects the JWT to be signed!
     */
    jwt(): this;
    url(): this;
    ipv4(): this;
    ipv6(): this;
    slug(): this;
    semVer(): this;
    languageTag(): this;
    countryCode(): this;
    currency(): this;
    /**
     * Validates that the input is a valid IANATimzone value.
     *
     * All previous expectations in the schema chain are dropped - including `.optional()` -
     * because this call effectively starts a new schema chain as an `enum` validation.
     */
    ianaTimezone(): JEnum<IANATimezone, false>;
    base64Url(): this;
    uuid(): this;
}
export interface JsonSchemaStringEmailOptions {
    checkTLD: boolean;
}
export declare class JIsoDate<Opt extends boolean = false> extends JBuilder<IsoDate, Opt> {
    constructor();
    before(date: string): this;
    sameOrBefore(date: string): this;
    after(date: string): this;
    sameOrAfter(date: string): this;
    between(fromDate: string, toDate: string, incl: Inclusiveness): this;
}
export interface JsonSchemaIsoDateOptions {
    before?: string;
    sameOrBefore?: string;
    after?: string;
    sameOrAfter?: string;
}
export interface JsonSchemaIsoMonthOptions {
}
export declare class JNumber<OUT extends number | undefined = number, Opt extends boolean = false> extends JBuilder<OUT, Opt> {
    constructor();
    integer(): this;
    branded<B extends number>(): JNumber<B, Opt>;
    multipleOf(multipleOf: number): this;
    min(minimum: number): this;
    exclusiveMin(exclusiveMinimum: number): this;
    max(maximum: number): this;
    exclusiveMax(exclusiveMaximum: number): this;
    lessThan(value: number): this;
    lessThanOrEqual(value: number): this;
    moreThan(value: number): this;
    moreThanOrEqual(value: number): this;
    equal(value: number): this;
    range(minimum: number, maximum: number, incl: Inclusiveness): this;
    int32(): this;
    int64(): this;
    float(): this;
    double(): this;
    unixTimestamp(): JNumber<UnixTimestamp, Opt>;
    unixTimestamp2000(): JNumber<UnixTimestamp, Opt>;
    unixTimestampMillis(): JNumber<UnixTimestampMillis, Opt>;
    unixTimestamp2000Millis(): JNumber<UnixTimestampMillis, Opt>;
    utcOffset(): this;
    utcOffsetHour(): this;
    /**
     * Specify the precision of the floating point numbers by the number of digits after the ".".
     * Excess digits will be cut-off when the current schema is nested in an object or array schema,
     * due to how mutability works in Ajv.
     */
    precision(numberOfDigits: number): this;
}
export declare class JBoolean<OUT extends boolean | undefined = boolean, Opt extends boolean = false> extends JBuilder<OUT, Opt> {
    constructor();
}
export declare class JObject<OUT extends AnyObject, Opt extends boolean = false> extends JBuilder<OUT, Opt> {
    constructor(props?: AnyObject, opt?: JObjectOpts);
    /**
     * When set, the validation will not strip away properties that are not specified explicitly in the schema.
     */
    allowAdditionalProperties(): this;
    extend<P extends Record<string, JSchema<any, any>>>(props: P): JObject<Expand<Override<OUT, {
        [K in keyof P as P[K] extends JSchema<any, infer IsOpt> ? IsOpt extends true ? never : K : never]: P[K] extends JSchema<infer OUT2, any> ? OUT2 : never;
    } & {
        [K in keyof P as P[K] extends JSchema<any, infer IsOpt> ? IsOpt extends true ? K : never : never]?: P[K] extends JSchema<infer OUT2, any> ? OUT2 : never;
    }>>, false>;
    /**
     * Concatenates another schema to the current schema.
     *
     * It expects you to use `isOfType<T>()` in the chain,
     * otherwise the validation will throw. This is to ensure
     * that the schemas you concatenated match the intended final type.
     */
    concat<OUT2 extends AnyObject>(other: JObject<OUT2, any>): JObject<OUT & OUT2, false>;
    /**
     * Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
     */
    dbEntity(): JObject<Expand<Override<OUT, {
        id: string;
        created: JNumber<UnixTimestamp, false>;
        updated: JNumber<UnixTimestamp, false>;
    } & {}>>, false>;
    minProperties(minProperties: number): this;
    maxProperties(maxProperties: number): this;
    exclusiveProperties(propNames: readonly (keyof OUT & string)[]): this;
}
interface JObjectOpts {
    hasIsOfTypeCheck?: false;
    patternProperties?: StringMap<JsonSchema<any>>;
    keySchema?: JsonSchema;
}
export declare class JObjectInfer<PROPS extends Record<string, JSchema<any, any>>, Opt extends boolean = false> extends JBuilder<Expand<{
    [K in keyof PROPS as PROPS[K] extends JSchema<any, infer IsOpt> ? IsOpt extends true ? never : K : never]: PROPS[K] extends JSchema<infer OUT, any> ? OUT : never;
} & {
    [K in keyof PROPS as PROPS[K] extends JSchema<any, infer IsOpt> ? IsOpt extends true ? K : never : never]?: PROPS[K] extends JSchema<infer OUT, any> ? OUT : never;
}>, Opt> {
    constructor(props?: PROPS);
    /**
     * When set, the validation will not strip away properties that are not specified explicitly in the schema.
     */
    allowAdditionalProperties(): this;
    extend<NEW_PROPS extends Record<string, JSchema<any, any>>>(props: NEW_PROPS): JObjectInfer<{
        [K in keyof PROPS | keyof NEW_PROPS]: K extends keyof NEW_PROPS ? NEW_PROPS[K] : K extends keyof PROPS ? PROPS[K] : never;
    }, Opt>;
    /**
     * Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
     */
    dbEntity(): JObjectInfer<{ [K in "created" | "id" | "updated" | keyof PROPS]: K extends "created" | "id" | "updated" ? {
        id: JString<string, false>;
        created: JNumber<UnixTimestamp, false>;
        updated: JNumber<UnixTimestamp, false>;
    }[K] : K extends keyof PROPS ? PROPS[K] : never; }, Opt>;
}
export declare class JArray<OUT, Opt> extends JBuilder<OUT[], Opt> {
    constructor(itemsSchema: JSchema<OUT, Opt>);
    minLength(minItems: number): this;
    maxLength(maxItems: number): this;
    length(exactLength: number): this;
    length(minItems: number, maxItems: number): this;
    exactLength(length: number): this;
    unique(): this;
}
declare class JSet2Builder<OUT, Opt> extends JBuilder<Set2<OUT>, Opt> {
    constructor(itemsSchema: JSchema<OUT, Opt>);
    min(minItems: number): this;
    max(maxItems: number): this;
}
export declare class JEnum<OUT extends string | number | boolean | null, Opt extends boolean = false> extends JBuilder<OUT, Opt> {
    constructor(enumValues: readonly OUT[], baseType: EnumBaseType, opt?: JsonBuilderRuleOpt);
    branded<B extends OUT>(): JEnum<B, Opt>;
}
export declare class JTuple<ITEMS extends JSchema<any, any>[]> extends JBuilder<TupleOut<ITEMS>, false> {
    constructor(items: ITEMS);
}
declare function object(props: AnyObject): never;
declare function object<OUT extends AnyObject>(props: [keyof OUT] extends [never] ? Record<string, never> : {
    [K in keyof Required<OUT>]-?: JSchema<OUT[K], any>;
}): [keyof OUT] extends [never] ? never : JObject<OUT, false>;
declare function objectInfer<P extends Record<string, JSchema<any, any>>>(props: P): JObjectInfer<P, false>;
declare function objectDbEntity(props: AnyObject): never;
declare function objectDbEntity<OUT extends BaseDBEntity, EXTRA_KEYS extends Exclude<keyof OUT, keyof BaseDBEntity> = Exclude<keyof OUT, keyof BaseDBEntity>>(props: {
    [K in EXTRA_KEYS]-?: BuilderFor<OUT[K]>;
} & (ExactMatch<OUT['id'], BaseDBEntity['id']> extends true ? {
    id?: BuilderFor<BaseDBEntity['id']>;
} : {
    id: BuilderFor<OUT['id']>;
}) & (ExactMatch<OUT['created'], BaseDBEntity['created']> extends true ? {
    created?: BuilderFor<BaseDBEntity['created']>;
} : {
    created: BuilderFor<OUT['created']>;
}) & (ExactMatch<OUT['updated'], BaseDBEntity['updated']> extends true ? {
    updated?: BuilderFor<BaseDBEntity['updated']>;
} : {
    updated: BuilderFor<OUT['updated']>;
})): JObject<OUT, false>;
declare function record<KS extends JSchema<any, any>, VS extends JSchema<any, any>, Opt extends boolean = SchemaOpt<VS>>(keySchema: KS, valueSchema: VS): SchemaOut<KS> extends string ? JObject<Opt extends true ? Partial<Record<SchemaOut<KS>, SchemaOut<VS>>> : Record<SchemaOut<KS>, SchemaOut<VS>>, false> : never;
declare function withRegexKeys<S extends JSchema<any, any>>(keyRegex: RegExp | string, schema: S): JObject<StringMap<SchemaOut<S>>, false>;
/**
 * Builds the object schema with the indicated `keys` and uses the `schema` for their validation.
 */
declare function withEnumKeys<const T extends readonly (string | number)[] | StringEnum | NumberEnum, S extends JSchema<any, any>, K extends string | number = EnumKeyUnion<T>, Opt extends boolean = SchemaOpt<S>>(keys: T, schema: S): JObject<Opt extends true ? {
    [P in K]?: SchemaOut<S>;
} : {
    [P in K]: SchemaOut<S>;
}, false>;
/**
 * On creation - compiles ajv validation function.
 * Provides convenient methods, error reporting, etc.
 */
export declare class AjvSchema<OUT> {
    schema: JsonSchema<OUT>;
    private constructor();
    /**
     * Shortcut for AjvSchema.create(schema, { lazy: true })
     */
    static createLazy<OUT>(schema: SchemaHandledByAjv<OUT>, cfg?: Partial<AjvSchemaCfg>): AjvSchema<OUT>;
    /**
     * Conveniently allows to pass either JsonSchema or JSchema builder, or existing AjvSchema.
     * If it's already an AjvSchema - it'll just return it without any processing.
     * If it's a Builder - will call `build` before proceeding.
     * Otherwise - will construct AjvSchema instance ready to be used.
     */
    static create<OUT>(schema: SchemaHandledByAjv<OUT>, cfg?: Partial<AjvSchemaCfg>): AjvSchema<OUT>;
    /**
     * Creates a minimal AjvSchema wrapper from a pre-compiled validate function.
     * Used internally by JSchema to cache a compatible AjvSchema instance.
     */
    static _wrap<OUT>(schema: JsonSchema<OUT>, compiledFn: any): AjvSchema<OUT>;
    static isSchemaWithCachedAjvSchema<Base, OUT>(schema: Base): schema is WithCachedAjvSchema<Base, OUT>;
    static cacheAjvSchema<Base extends AnyObject, OUT>(schema: Base, ajvSchema: AjvSchema<OUT>): WithCachedAjvSchema<Base, OUT>;
    static requireCachedAjvSchema<Base, OUT>(schema: WithCachedAjvSchema<Base, OUT>): AjvSchema<OUT>;
    readonly cfg: AjvSchemaCfg;
    private _compiledFn;
    private _getValidateFn;
    /**
     * It returns the original object just for convenience.
     */
    validate(input: unknown, opt?: AjvValidationOptions): OUT;
    isValid(input: unknown, opt?: AjvValidationOptions): boolean;
    getValidationResult(input: unknown, opt?: AjvValidationOptions): ValidationFunctionResult<OUT, AjvValidationError>;
    getValidationFunction(): ValidationFunction<OUT, AjvValidationError>;
    private static requireValidJsonSchema;
}
type EnumBaseType = 'string' | 'number' | 'other';
export interface AjvValidationOptions {
    /**
     * Custom Ajv instance to use for this validation.
     * Overrides the default Ajv or any Ajv set at construction time.
     * Compiled functions are cached per Ajv instance.
     */
    ajv?: Ajv;
    /**
     * Defaults to true,
     * because that's how AJV works by default,
     * and what gives it performance advantage.
     * (Because we have found that deep-clone is surprisingly slow,
     * nearly as slow as Joi validation).
     *
     * If set to true - AJV will mutate the input in case it needs to apply transformations
     * (strip unknown properties, convert types, etc).
     *
     * If false - it will deep-clone (using JSON.stringify+parse) the input to prevent its mutation.
     * Will return the cloned/mutated object.
     * Please note that JSON.stringify+parse has side-effects,
     * e.g it will transform Buffer into a weird object.
     */
    mutateInput?: boolean;
    inputName?: string;
    inputId?: string;
    /**
     * Function that returns "original input".
     * What is original input?
     * It's an input in its original non-mutated form.
     * Why is it needed?
     * Because we mutates the Input here. And after its been mutated - we no longer
     * can include it "how it was" in an error message. So, for that reason we'll use
     * `getOriginalInput()`, if it's provided.
     */
    getOriginalInput?: () => unknown;
}
export interface AjvSchemaCfg {
    /**
     * Pass Ajv instance, otherwise Ajv will be created with
     * AjvSchema default (not the same as Ajv defaults) parameters
     */
    ajv: Ajv;
    inputName?: string;
    /**
     * If true - schema will be compiled on-demand (lazily).
     * Default: false.
     */
    lazy?: boolean;
}
export type SchemaHandledByAjv<OUT> = JSchema<OUT, any> | JsonSchema<OUT> | AjvSchema<OUT>;
export interface JsonSchema<OUT = unknown> {
    readonly out?: OUT;
    $schema?: string;
    $id?: string;
    title?: string;
    description?: string;
    deprecated?: boolean;
    readOnly?: boolean;
    writeOnly?: boolean;
    type?: string | string[];
    items?: JsonSchema;
    prefixItems?: JsonSchema[];
    properties?: {
        [K in keyof OUT]: JsonSchema<OUT[K]>;
    };
    patternProperties?: StringMap<JsonSchema<any>>;
    required?: string[];
    additionalProperties?: boolean;
    minProperties?: number;
    maxProperties?: number;
    default?: OUT;
    if?: JsonSchema;
    then?: JsonSchema;
    else?: JsonSchema;
    anyOf?: JsonSchema[];
    oneOf?: JsonSchema[];
    /**
     * This is a temporary "intermediate AST" field that is used inside the parser.
     * In the final schema this field will NOT be present.
     */
    optionalField?: true;
    pattern?: string;
    minLength?: number;
    maxLength?: number;
    format?: string;
    contentMediaType?: string;
    contentEncoding?: string;
    multipleOf?: number;
    minimum?: number;
    exclusiveMinimum?: number;
    maximum?: number;
    exclusiveMaximum?: number;
    minItems?: number;
    maxItems?: number;
    uniqueItems?: boolean;
    enum?: any;
    hasIsOfTypeCheck?: boolean;
    email?: JsonSchemaStringEmailOptions;
    Set2?: JsonSchema;
    Buffer?: true;
    IsoDate?: JsonSchemaIsoDateOptions;
    IsoDateTime?: true;
    IsoMonth?: JsonSchemaIsoMonthOptions;
    instanceof?: string | string[];
    transform?: {
        trim?: true;
        toLowerCase?: true;
        toUpperCase?: true;
        truncate?: number;
    };
    errorMessages?: StringMap<string>;
    optionalValues?: (string | number | boolean | null)[];
    keySchema?: JsonSchema;
    isUndefined?: true;
    minProperties2?: number;
    exclusiveProperties?: (readonly string[])[];
    anyOfBy?: {
        propertyName: string;
        schemaDictionary: Record<string, JsonSchema>;
    };
    anyOfThese?: JsonSchema[];
    precision?: number;
    customValidations?: CustomValidatorFn[];
    customConversions?: CustomConverterFn<any>[];
    postValidation?: PostValidatonFn<any, OUT>;
}
export type PostValidatonFn<OUT, OUT2> = (v: OUT) => OUT2;
export type CustomValidatorFn = (v: any) => string | undefined;
export type CustomConverterFn<OUT> = (v: any) => OUT;
type Expand<T> = {
    [K in keyof T]: T[K];
};
type StripIndexSignatureDeep<T> = T extends readonly unknown[] ? T : T extends Record<string, any> ? {
    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: StripIndexSignatureDeep<T[K]>;
} : T;
type RelaxIndexSignature<T> = T extends readonly unknown[] ? T : T extends AnyObject ? {
    [K in keyof T]: RelaxIndexSignature<T[K]>;
} : T;
type Override<T, U> = Omit<T, keyof U> & U;
declare const allowExtraKeysSymbol: unique symbol;
type HasAllowExtraKeys<T> = T extends {
    readonly [allowExtraKeysSymbol]?: true;
} ? true : false;
type IsAny<T> = 0 extends 1 & T ? true : false;
type IsAssignableRelaxed<A, B> = IsAny<RelaxIndexSignature<A>> extends true ? true : [RelaxIndexSignature<A>] extends [B] ? true : false;
type ExactMatchBase<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => (T extends B ? 1 : 2) ? (<T>() => T extends B ? 1 : 2) extends <T>() => (T extends A ? 1 : 2) ? true : false : false;
type ExactMatch<A, B> = HasAllowExtraKeys<B> extends true ? IsAssignableRelaxed<B, A> : ExactMatchBase<Expand<A>, Expand<B>> extends true ? true : ExactMatchBase<Expand<StripIndexSignatureDeep<A>>, Expand<StripIndexSignatureDeep<B>>> extends true ? true : ExactMatchBase<keyof Expand<A>, keyof Expand<B>> extends true ? [Expand<A>] extends [Expand<B>] ? [Expand<B>] extends [Expand<A>] ? true : false : false : false;
type BuilderOutUnion<B extends readonly JSchema<any, any>[]> = {
    [K in keyof B]: B[K] extends JSchema<infer O, any> ? O : never;
}[number];
type AnyOfByOut<D extends Record<PropertyKey, JSchema<any, any>>> = {
    [K in keyof D]: D[K] extends JSchema<infer O, any> ? O : never;
}[keyof D];
type BuilderFor<T> = JSchema<T, any>;
export interface JsonBuilderRuleOpt {
    /**
     * Text of error message to return when the validation fails for the given rule:
     *
     * `{ msg: "is not a valid Oompa-loompa" } => "Object.property is not a valid Oompa-loompa"`
     */
    msg?: string;
    /**
     * A friendly name for what we are validating, that will be used in error messages:
     *
     * `{ name: "Oompa-loompa" } => "Object.property is not a valid Oompa-loompa"`
     */
    name?: string;
}
type EnumKeyUnion<T> = T extends readonly (infer U)[] ? `${U & (string | number)}` : T extends StringEnum | NumberEnum ? `${T[keyof T] & (string | number)}` : never;
type SchemaOut<S> = S extends JSchema<infer OUT, any> ? OUT : never;
type SchemaOpt<S> = S extends JSchema<any, infer Opt> ? (Opt extends true ? true : false) : false;
type TupleOut<T extends readonly JSchema<any, any>[]> = {
    [K in keyof T]: T[K] extends JSchema<infer O, any> ? O : never;
};
export {};
