import { BaseSchema, MaybeValid, Schema, SchemaOptions, SchemaType, ValidationError } from "../../Schema"; import { MaybePromise } from "../../utils/MaybePromise"; import { maybeSkipValidation } from "../../utils/maybeSkipValidation"; import { getSchemaUtils } from "../schema-utils"; import { inferParsedUnidiscriminatedUnionSchema, inferRawUnidiscriminatedUnionSchema } from "./types"; export function undiscriminatedUnion, ...Schema[]]>( schemas: Schemas ): Schema, inferParsedUnidiscriminatedUnionSchema> { const baseSchema: BaseSchema< inferRawUnidiscriminatedUnionSchema, inferParsedUnidiscriminatedUnionSchema > = { parse: async (raw, opts) => { return validateAndTransformUndiscriminatedUnion>( (schema, opts) => schema.parse(raw, opts), schemas, opts ); }, json: async (parsed, opts) => { return validateAndTransformUndiscriminatedUnion>( (schema, opts) => schema.json(parsed, opts), schemas, opts ); }, getType: () => SchemaType.UNDISCRIMINATED_UNION, }; return { ...maybeSkipValidation(baseSchema), ...getSchemaUtils(baseSchema), }; } async function validateAndTransformUndiscriminatedUnion( transform: (schema: Schema, opts: SchemaOptions) => MaybePromise>, schemas: Schema[], opts: SchemaOptions | undefined ): Promise> { const errors: ValidationError[] = []; for (const [index, schema] of schemas.entries()) { const transformed = await transform(schema, { ...opts, skipValidation: false }); if (transformed.ok) { return transformed; } else { for (const error of transformed.errors) { errors.push({ path: error.path, message: `[Variant ${index}] ${error.message}`, }); } } } return { ok: false, errors, }; }