import { StandardJSONSchemaV1 } from "../standard-schema/types.mjs"; import { JsonSchemaResult, JsonSchemaTarget } from "../standard-schema/json-schema.mjs"; import { ContextualSchemaRule, SchemaRule, SchemaRuleOptions, ValidationAttributesList } from "../types/rule-types.mjs"; import { SchemaContext } from "../types/context-types.mjs"; import { ValidationResult } from "../types/result-types.mjs"; import { ContextualizedMutator, Mutator } from "../types/mutator-types.mjs"; import { ContextualizedTransformer, SimpleTransformerCallback, TransformerCallback } from "../types/data-transformer-types.mjs"; //#region ../@warlock.js/seal/src/validators/base-validator.d.ts /** * Base validator class - foundation for all validators */ declare class BaseValidator { rules: ContextualSchemaRule[]; mutators: ContextualizedMutator[]; protected defaultValue: any | (() => any); protected description?: string; protected shouldOmit: boolean; protected isNullable: boolean; protected isMutable: boolean; /** * Catch state — when `hasCatch` is true and validation fails, `catchValue` * (or its callback result) substitutes for the failed value, and the public * result reports `isValid: true` with no errors. * * See `.catch()` for semantics and the v1 scope (leaf-only). */ protected catchValue: any | ((errors: ValidationResult["errors"], originalInput: any) => any | Promise); protected hasCatch: boolean; /** * Whether the field is optional. * - false (default): field is required unless a requiredRule governs the condition. * - true: field can be absent or empty — set by calling .optional(). * * Also used as a TypeScript literal brand via the optional() return type. */ isOptional: boolean; /** * The single required-condition rule for this field. * - null: field uses strict default (always required when not optional). * - set: the rule governs when the field is required (e.g., requiredIf). * * Stored separately from rules[] and prepended at validate() time. */ requiredRule: ContextualSchemaRule | null; /** * Pipeline to transform the mutated/original data before returning it */ protected dataTransformers: ContextualizedTransformer[]; /** * Attributes text to be replaced on translations * If the value is an object, it will be used as the attributes list for the rule * If the value is a string, it will be used as the attributes list for the rule */ protected attributesText: ValidationAttributesList; /** * Attributed that will be always using the attribute translator */ protected translatedAttributes: Record; /** * Mark the validator as mutable */ get mutable(): this; /** * Mark the validator as immutable */ get immutable(): this; /** * Get the instance to apply changes to. * By default (immutable), returns a clone so the original is unchanged. * When `.mutable` is set, returns `this` to mutate in place. */ protected get instance(): this; /** * Get the default value * Supports lazy evaluation via callbacks */ getDefaultValue(): any; /** * Allow null as a valid value. * * Brands the return type with `{ isNullable: true }` so `Infer<>` widens * the inferred output to include `| null`. */ nullable(): this & { isNullable: true; }; /** * Explicitly disallow null values after calling nullable. * * Brands the return type with `{ isNullable: false }` to cancel any prior * `.nullable()` at the type level. */ notNullable(): this & { isNullable: false; }; /** * Add transformer with optional options * * @param transform - The transformer callback function * @param options - Optional options to pass to the transformer * * @example * ```ts * // Without options * v.date().addTransformer(data => data.toISOString()) * * // With options * v.date().addTransformer( * (data, { options }) => dayjs(data).format(options.format), * { format: 'YYYY-MM-DD' } * ) * ``` */ addTransformer(transform: TransformerCallback, options?: any): this; /** * Add transformer with optional options * * @param transform - The transformer callback function * @param options - Optional options to pass to the transformer * * @example * ```ts * // Without options * v.date().addTransformer(data => data.toISOString()) * * // With options * v.date().addTransformer( * (data, { options }) => dayjs(data).format(options.format), * { format: 'YYYY-MM-DD' } * ) * ``` */ addMutableTransformer(transform: TransformerCallback, options?: any): void; /** * Transform the output value - simple one-time transformation * * @param callback - Simple callback receiving data and context * * @example * ```ts * // Simple transformation * v.string().outputAs(data => data.toUpperCase()) * * // With context * v.string().outputAs((data, context) => { * console.log(`Transforming ${context.path}`); * return data.toLowerCase(); * }) * ``` */ outputAs(callback: SimpleTransformerCallback): this; /** * Transform output to JSON string * * Works with any validator type (string, number, date, object, array, etc.) * * @param indent - Optional indentation for pretty printing (default: 0 for compact) * * @example * ```ts * // Compact JSON * v.object({ name: v.string() }).toJSON() * // Output: '{"name":"John"}' * * // Pretty-printed JSON * v.array(v.object({...})).toJSON(2) * // Output: * // [ * // { * // "name": "John" * // } * // ] * * // Works with any type * v.string().toJSON() // '"hello"' * v.number().toJSON() // '42' * v.date().toJSON() // '"2024-10-26T00:00:00.000Z"' * ``` * * @category Transformer */ toJSON(indent?: number): this; /** * Start data transformation pipeline * Context is passed at runtime, not stored */ startTransformationPipeline(data: any, context: SchemaContext): Promise; /** * Set attributes text to be replaced on translations * If the value is an object, it will be used as the attributes list for the rule * If the value is a string, it will be used as the attributes list for the rule * * @example * v.string().attributes({ * name: "Name", * email: "Email", * }); * // Example 2: Add custom attributes for matches * v.string().matches("confirmPassword").attributes({ * matches: { * confirmPassword: "Confirm Password", * }, * }); */ attributes(attributes: Record>): this; /** * Define a lazy getter property for each attribute in the given object and use the config attribute translator */ transAttributes(attributes: Record): this; /** * Add description to the validator */ describe(description: string): this; /** * Check if this validator can handle the given value's type * Override this in specific validators to enable type-based routing in union validators * * Default: returns true (validator will attempt to validate any type) * * @param value - The value to check * @returns True if this validator can handle this type * * @example * ```ts * // StringValidator * public matchesType(value: any): boolean { * return typeof value === 'string'; * } * * // Custom FileValidator * public matchesType(value: any): boolean { * return value instanceof UploadedFile; * } * ``` */ matchesType(_value: any): boolean; /** * Create a copy of this validator with the same configuration * Copies all rules, mutators, transformers, default values, and settings * * @returns A new validator instance with copied configuration * * @example * ```ts * // Create reusable validator templates * const baseString = v.string().required().trim().min(3); * const emailField = baseString.clone().email(); * const usernameField = baseString.clone().alphanumeric().max(20); * * // Works with all validators * const positiveInt = v.int().positive().required(); * const ageField = positiveInt.clone().min(18).max(120); * ``` */ clone(): this; /** * @deprecated This method is no longer needed and does nothing. * Empty values are now automatically skipped for validation rules by default. * Only presence validators (required, present, etc.) will check empty values. * You can safely remove this call from your code. */ ignoreEmptyValue(_ignoreEmptyValue?: boolean): this; /** * Omit this field from the validated data output * * Field will still be validated but not included in the final result. * Useful for confirmation fields, captcha, terms acceptance, etc. * * @example * ```ts * v.object({ * password: v.string().required(), * confirmPassword: v.string().required().sameAs("password").omit(), * acceptTerms: v.boolean().required().omit(), * }); * // Output: { password: "..." } * // confirmPassword and acceptTerms validated but omitted * ``` */ omit(): this; /** * @alias omit */ exclude(): this; /** * Check if this field should be omitted from the output */ isOmitted(): boolean; /** * Add rule to the validator */ addRule(rule: SchemaRule, errorMessage?: string, options?: T): this; /** * Set the required-condition rule for this field. * * Unlike addRule(), this does NOT push to rules[]. The rule is stored in the * dedicated `requiredRule` slot and is prepended to the validation pipeline * at runtime. Only one required rule can be active per field — this replaces * any previously set required rule. * * Also marks the field as not optional (isOptional = false). * * @example * ```ts * // Used internally by required(), requiredIf(), requiredWith(), etc. * BaseValidator.prototype.required = function(msg) { * return this.setRequiredRule(requiredRule, msg); * }; * ``` */ setRequiredRule(rule: SchemaRule, errorMessage?: string, options?: T): this; /** * Add mutable rule */ addMutableRule(rule: SchemaRule, errorMessage?: string, options?: T): ContextualSchemaRule; /** * Create new rule */ protected createRule(rule: SchemaRule, errorMessage?: string, options?: T): ContextualSchemaRule; /** * Use a custom or pre-built validation rule * * @param rule - The validation rule to apply * @param options - Rule options including errorMessage and any rule-specific options * * @example * ```ts * import { hexColorRule } from "@warlock.js/seal"; * * v.string().useRule(hexColorRule, { errorMessage: "Invalid color" }); * ``` * * @example * ```ts * // With rule options * v.string().useRule(myCustomRule, { * customOption: true, * errorMessage: "Custom validation failed" * }); * ``` */ useRule(rule: SchemaRule, options?: T & { errorMessage?: string; }): this; /** * Define custom rule */ refine(callback: (value: any, context: SchemaContext) => Promise | string | undefined): this; /** * Add mutator to the validator */ addMutator(mutator: Mutator, options?: any): this; /** * Add mutable mutator */ addMutableMutator(mutator: Mutator, options?: any): void; /** * Set default value for the field. The default is used when the input is * absent (`undefined`); it then flows through the rule pipeline. * * Brands the return type with `{ hasDefault: true }` so `Infer<>` treats * the field as guaranteed-present even when chained with `.optional()`. */ default(value: any): this & { hasDefault: true; }; /** * Fallback to a value when validation fails. * * Complementary to `.default()`: `.default(x)` fires when input is **absent**, * `.catch(y)` fires when input is **present but invalid**. Combine them when * you want both behaviours: `.optional().default(x).catch(y)`. * * The fallback can be a value or a callback `(errors, originalInput) => fallback`. * The callback variant is the only side-channel for the swallowed errors — * use it to log/alert before the fallback substitutes. * * Brands the return type with `{ hasCatch: true }` so `Infer<>` treats the * field as guaranteed-present (the catch ensures a value will always exist). * * **Scope (v1).** Catch is honoured for **leaf validators** (string, number, * boolean, date, …) and for fields inside containers. It is a **no-op on * container validators themselves** (`v.object`, `v.array`, `v.record`, * `v.tuple`, `v.discriminatedUnion`) — those use their own iteration logic * that bypasses the catch hook in `BaseValidator.validate()`. * * @example * ```ts * v.int().min(0).catch(3) // bad number → 3 * v.string().in(["us", "eu"]).catch("us") // unknown enum → "us" * v.string().catch((errors, input) => { * console.warn(`bad user value: ${JSON.stringify(input)}`, errors); * return "anonymous"; * }) * ``` */ catch(fallback: any | ((errors: ValidationResult["errors"], originalInput: any) => any | Promise)): this & { hasCatch: true; }; /** * Mutate the data */ mutate(data: any, context: SchemaContext): Promise; /** * Set the label for the validator that will be matching the :input attribute */ label(label: string): this; /** * Validate the data */ validate(data: any, context: SchemaContext): Promise; /** * Set rule attributes list */ protected setRuleAttributesList(rule: ContextualSchemaRule): void; /** * Standard Schema V1 compliance. * * Allows this validator to be used with any Standard Schema-aware library * (OpenAI structured outputs, LangGraph, TanStack Form, Conform, Valibot adapters, etc.) * without extra adapters. * * Delegates to the `validate()` factory so all `configureSeal()` options * (translations, firstErrorOnly) are picked up automatically at call time. * * Includes Standard JSON Schema support via `jsonSchema.input()` / `jsonSchema.output()`. * * ## How Standard Schema libraries consume this * * You pass the **schema object itself** to the library — they internally read * `schema["~standard"]`. Do NOT pass `schema["~standard"]` directly. * * @example * ```ts * const schema = v.object({ name: v.string().required() }); * * // TanStack Form — pass schema, library reads ["~standard"] internally * const form = useForm({ validators: { onChange: schema } }); * * // Conform (Remix) — same pattern * const [form] = useForm({ onValidate({ formData }) { * return parseWithStandardSchema(formData, { schema }); * }}); * * // Direct validation (lower level — most apps don't need this) * const result = await schema["~standard"].validate({ name: "Hasan" }); * // → { value: { name: "Hasan" } } on success * // → { issues: [{ message: "...", path: [{ key: "name" }] }] } on failure * * // JSON Schema for OpenAI / LangChain tool calling * const parameters = schema["~standard"].jsonSchema.input({ target: "openai-strict" }); * // → { type: "object", properties: {...}, required: [...], additionalProperties: false } * ``` * * @note Cross-field rules (sameAs, requiredIf, requiredWith) rely on sibling values * available in the full validation context. When called on a standalone scalar validator, * sibling data is absent and those rules will not evaluate correctly. * Always call on the parent ObjectValidator for full-payload validation. */ get ["~standard"](): StandardJSONSchemaV1.Props; /** * Generate a JSON Schema representation of this validator. * * Supports targets: `"draft-2020-12"` (default), `"draft-07"`, `"openapi-3.0"`. * * Subclasses override this to describe their specific constraints. * The base implementation returns `{}` (permissive — accepts anything), * which is correct for validators with no representable JSON Schema constraints. * * @note Rules that cannot be expressed in JSON Schema are silently omitted: * - Cross-field rules: sameAs, requiredIf, requiredWith, requiredWithout * - Custom callbacks: refine() * - Framework-specific runtime rules (core/cascade plugins) * These rules still run normally at validation time — only absent from JSON Schema. * * @example * ```ts * v.string().min(3).max(50).toJsonSchema("draft-2020-12") * // → { type: "string", minLength: 3, maxLength: 50 } * * v.object({ name: v.string().required(), age: v.int().optional() }) * .toJsonSchema("draft-07") * // → { type: "object", properties: { name: { type: "string" }, age: { type: "integer" } }, required: ["name"] } * ``` */ toJsonSchema(_target?: JsonSchemaTarget): JsonSchemaResult; } //#endregion export { BaseValidator }; //# sourceMappingURL=base-validator.d.mts.map