UNPKG

@naturalcycles/nodejs-lib

Version:
666 lines (665 loc) 29.8 kB
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 {};