import { type Schema } from "./schemas/schema.js"; import { SwitchConfig } from "./schemas/switch.js"; // A stripped-down interface that recursive validators use to call `parse`. export interface SchemaLike { readonly config: Record; parse(data: any, ctx?: any): any; safeParse(data: any, ctx?: any): Promise>; } // The simplified context object passed through the validation chain. export interface ValidationContext { /** The original, top-level data passed to `parse()`. */ rootData: any; /** The path from the root to the current value being validated. */ path: (string | number)[]; /** The value at the current path. */ value: any; /** The user-provided context object. */ ctx?: any; } export interface MessageProducerContext { label: string; value: any; path: (string | number)[]; args: any[]; dataType: string; ctx?: any; schema: Schema; } export type MessageProducer = (context: MessageProducerContext) => string; // The simplified function signature for a single preparation. export type PreparationFunction = ( value: T, args: Args, context: ValidationContext, schema: Schema ) => any | Promise; // The simplified function signature for a single transformation. export type TransformationFunction = ( value: T, args: Args, context: ValidationContext, schema: Schema ) => any | Promise; // The simplified function signature for a single validator. export type ValidatorFunction = ( value: T, args: Args, context: ValidationContext, schema: Schema ) => boolean | Promise; export type ValidatorDefinition = { validator: ValidatorFunction; message: MessageProducer; }; // A collection of preparations for a specific data type. export type PreparationCollection = { [preparationName: string]: PreparationFunction; }; // A collection of transformations for a specific data type. export type TransformationCollection = { [transformationName: string]: TransformationFunction; }; // A collection of validators for a specific data type. export type ValidatorCollection = { [validatorName: string]: ValidatorDefinition; }; export type Validator = { dataType: string; prepare?: PreparationCollection; transform?: TransformationCollection; validate?: ValidatorCollection & { identity: { validator: ( value: unknown, args: any[], context: ValidationContext, schema: Schema ) => boolean | Promise; message: MessageProducer; }; }; }; export function definePlugin( plugin: Validator ): Validator { return plugin; } // The main map of all data types to their validator collections. export type SchemaValidatorMap = { [dataType: string]: { identity: ValidatorFunction; [validatorName: string]: ValidatorFunction; }; }; export type ValidationIssue = { path: readonly (string | number)[]; message: string; }; export class ValidationError extends Error { public issues: ValidationIssue[]; constructor(issues: ValidationIssue[]) { super(issues[0]?.message || "Validation failed"); this.issues = issues; this.name = "ValidationError"; } } export type SafeParseSuccess = { status: "success"; data: T; }; export type SafeParseError = { status: "error"; error: ValidationError; }; export type SafeParseResult = SafeParseSuccess | SafeParseError; // A utility to force TS to expand a type in tooltips for better DX. export type Prettify = { [K in keyof T]: T[K] } & {}; // The keys of T that can be undefined export type UndefinedKeys = { [K in keyof T]: undefined extends T[K] ? K : never; }[keyof T]; // Make properties of T optional if their value can be undefined export type UndefinedToOptional = Prettify< { [K in Exclude>]: T[K] } & { [K in UndefinedKeys]?: T[K]; } >; export type CustomValidator = | (( value: TOutput, args: any[], context: ValidationContext, schema: any ) => any) | { validator: ( value: TOutput, args: any[], context: ValidationContext, schema: any ) => any; message?: string | MessageProducer; name?: string; }; // Creates a typed config object from a validator collection. export type ValidatorConfig = { optional?: boolean; nullable?: boolean; label?: string; messages?: Prettify< { [K in keyof Omit< VCollection, "identity" | "messages" | "preparations" | "transformations" >]?: string; } & { identity?: string; } >; prepare?: Record & { custom?: ((value: any) => any)[] }; validate?: Record & { custom?: CustomValidator | CustomValidator[]; }; transform?: Record & { custom?: ((value: any) => any)[] }; }; export type InferSchemaType> = T extends Schema< infer U, any > ? U : never; export type SObjectProperties = Record>; export type InferSObjectType

= Prettify< UndefinedToOptional<{ [K in keyof P]: InferSchemaType; }> >;