import { JsonSchemaResult, JsonSchemaTarget } from "../standard-schema/json-schema.mjs"; import { Schema } from "../types/schema-types.mjs"; import { SchemaContext } from "../types/context-types.mjs"; import { ValidationResult } from "../types/result-types.mjs"; import { InferInputObjectShape, InferOutputObjectShape } from "../types/inference-types.mjs"; import { BaseValidator } from "./base-validator.mjs"; //#region ../@warlock.js/seal/src/validators/object-validator.d.ts /** * Object validator class with generic schema type for proper type inference. * * Threads two distinct inferred shapes into `BaseValidator`'s `TInput`/`TOutput`: * * - `TInput` = `InferInputObjectShape` — what `~standard.validate()` * accepts (caller's pre-validation payload; defaults/catches make * keys optional) * - `TOutput` = `InferOutputObjectShape` — what `~standard.validate()` * returns on success (post-default, post-catch shape; guaranteed * keys are required) * * Both helpers are used directly (not the full `Infer.*` walker) to avoid a * recursive class-base evaluation that would otherwise occur when the * brand-aware widening tries to inspect the class type. */ declare class ObjectValidator extends BaseValidator, InferOutputObjectShape> { schema: TSchema; protected shouldAllowUnknown: boolean; protected allowedKeys: string[]; protected hasUnknownKeyRule: boolean; constructor(schema: TSchema, errorMessage?: string); /** * Check if value is an object type (plain object, not array or date) */ matchesType(value: any): boolean; /** Strip unknown keys from the data */ stripUnknown(): this; /** Add list of allowed keys that could be in the data but not necessarily validated */ allow(...keys: string[]): this; /** Trim values of the object properties */ trim(recursive?: boolean): this; /** Whether to allow unknown properties * Please note it will allow only unknown direct children keys, not nested children keys */ allowUnknown(allow?: boolean): this; /** * Create a copy of this object validator with the same configuration * Copies schema, rules, mutators, transformers, and object-specific settings * * @returns A new ObjectValidator instance with copied configuration * * @example * ```ts * const baseUser = v.object({ name: v.string() }).allowUnknown(); * const userCopy = baseUser.clone(); * // userCopy has the same schema and allowUnknown setting * ``` */ clone(keys?: string[]): this; /** * Extend this schema with additional fields * Clones the current validator and adds new fields to the schema * **Keeps original configuration** (allowUnknown, stripUnknown, etc.) * * If an ObjectValidator is provided, only its schema is used - its configuration is ignored. * This is useful for creating reusable field collections that can be added to different schemas. * * @param schemaOrValidator - Plain schema object or ObjectValidator to extend with * @returns A new ObjectValidator with merged schema and original configuration * * @example * ```ts * // Extend with plain schema * const baseUser = v.object({ * name: v.string().required(), * email: v.string().email().required() * }).allowUnknown(); * * const adminUser = baseUser.extend({ * role: v.string().in(['admin', 'superadmin']).required() * }); * // adminUser has: name, email, role * // adminUser keeps: allowUnknown() from base ✅ * * // Extend with ObjectValidator (only schema is used) * const auditFields = v.object({ * createdAt: v.date().required(), * updatedAt: v.date().required() * }).stripUnknown(); // This config is ignored! * * const fullUser = baseUser.extend(auditFields); * // fullUser has: name, email, createdAt, updatedAt * // fullUser keeps: allowUnknown() from base (NOT stripUnknown from auditFields) ✅ * * // Chain multiple extends * const complexSchema = baseUser * .extend(auditFields) * .extend({ metadata: v.object({}) }); * ``` */ extend(schemaOrValidator: TExtension | ObjectValidator): ObjectValidator; /** * Merge with another ObjectValidator * Clones current validator, merges schemas, and **overrides configuration** with other validator's config * * Unlike extend(), merge() combines both schemas AND configurations. * The other validator's configuration (allowUnknown, stripUnknown, etc.) takes precedence. * * @param validator - Another ObjectValidator to merge with * @returns A new ObjectValidator with merged schema and configuration * * @example * ```ts * const baseUser = v.object({ * name: v.string().required() * }).allowUnknown(); * * const timestamps = v.object({ * createdAt: v.date().required(), * updatedAt: v.date().required() * }).stripUnknown(); * * const merged = baseUser.merge(timestamps); * // merged has: name, createdAt, updatedAt * // merged config: stripUnknown() from timestamps (overrides allowUnknown) ✅ * * // Chain multiple merges * const full = baseUser.merge(timestamps).merge(softDeleteSchema); * ``` */ merge(validator: ObjectValidator): ObjectValidator; /** * Create a new schema with only the specified fields * Clones the current validator and keeps only the selected fields * **Preserves all configuration** (allowUnknown, stripUnknown, etc.) * * @param keys - Field names to keep in the schema * @returns A new ObjectValidator with only the picked fields * * @example * ```ts * const fullUser = v.object({ * id: v.int().required(), * name: v.string().required(), * email: v.string().email().required(), * password: v.string().required(), * role: v.string() * }).allowUnknown(); * * // For login - only need email and password * const loginSchema = fullUser.pick('email', 'password'); * // loginSchema has: { email, password } * // loginSchema keeps: allowUnknown() ✅ * * // For public profile * const publicSchema = fullUser.pick('id', 'name', 'role'); * // publicSchema has: { id, name, role } * ``` */ pick(...keys: K[]): ObjectValidator>; /** * Mark all or the given schema fields as optional */ partial(...keys: K[]): this; /** * Make the all or the given fields as required */ requiredFields(...keys: K[]): this; /** * Create a new schema excluding the specified fields * Clones the current validator and removes the specified fields * **Preserves all configuration** (allowUnknown, stripUnknown, etc.) * * @param keys - Field names to exclude from the schema * @returns A new ObjectValidator without the excluded fields * * @example * ```ts * const fullUser = v.object({ * id: v.int().required(), * name: v.string().required(), * email: v.string().email().required(), * password: v.string().required(), * role: v.string() * }).allowUnknown(); * * // For updates - exclude id * const updateSchema = fullUser.without('id'); * // updateSchema has: { name, email, password, role } * // updateSchema keeps: allowUnknown() ✅ * * // For public API - exclude sensitive fields * const publicSchema = fullUser.without('password', 'role'); * // publicSchema has: { id, name, email } * * // Combine with other methods * const patchSchema = fullUser.without('id', 'password'); * // patchSchema has: { name, email, role } * ``` */ without(...keys: K[]): ObjectValidator>; /** Mutate the data */ mutate(data: any, context: SchemaContext): any; /** Validate the data */ validate(data: any, context?: SchemaContext): Promise; /** * Check if a validator is a computed or managed field * ManagedValidator extends ComputedValidator, so instanceof catches both */ private isComputedValidator; /** * Get all computed/managed fields from the schema */ private getComputedFields; /** * @inheritdoc * * Recursively generates JSON Schema for all input fields in the schema. * Computed/managed fields are skipped — they have no input representation. * * **Standard targets** (`draft-2020-12`, `draft-07`, `openapi-3.0`): * - Fields marked `.optional()` are excluded from `required`. * * **`openai-strict` target** (OpenAI Structured Outputs): * - ALL fields appear in `required` — OpenAI rejects schemas with optional fields. * - Optional fields are instead expressed as nullable types: * `{ type: ["string", "null"] }` so the model can output `null` for them. * - Recursively applies `openai-strict` to all nested objects. * * @example * ```ts * v.object({ * name: v.string().required(), * age: v.int().optional(), * }).toJsonSchema("draft-2020-12") * // → { type: "object", * // properties: { name: { type: "string" }, age: { type: "integer" } }, * // required: ["name"], additionalProperties: false } * * v.object({ * name: v.string().required(), * age: v.int().optional(), * }).toJsonSchema("openai-strict") * // → { type: "object", * // properties: { name: { type: "string" }, age: { type: ["integer", "null"] } }, * // required: ["name", "age"], ← all fields * // additionalProperties: false } * ``` */ toJsonSchema(target?: JsonSchemaTarget): JsonSchemaResult; } //#endregion export { ObjectValidator }; //# sourceMappingURL=object-validator.d.mts.map