/* * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. * @generated-id: b65a1bd4c0e9 */ // Not needed if lax mode import * as z from "zod/v4"; import { isUnknown as isDiscriminatedUnionUnknown } from "./discriminatedUnion.js"; import { RFCDate } from "./rfcdate.js"; import { startCountingUnrecognized } from "./unrecognized.js"; interface Candidate { data: unknown; /** Total number of fields in the parsed data */ fieldCount: number; /** Number of fields which only matched due to lax parsing */ inexactCount: number; /** Number of fields which defaulted to zero values */ zeroDefaultCount: number; } /** * Smart union parser that tries all schemas and returns the best match * based on the number of populated fields. */ export function smartUnion< Options extends readonly [z.ZodType, z.ZodType, ...z.ZodType[]], >( options: Options, ): z.ZodType, z.input> { return z.unknown().transform((input, ctx) => { const candidates: Candidate[] = []; const errors: z.ZodIssue[][] = options.map(() => []); const parentUnrecognizedCtr = startCountingUnrecognized(); // Filter out invalid options for (const [i, option] of options.entries()) { const unrecognizedCtr = startCountingUnrecognized(); const result = option.safeParse(input); const inexactCount = unrecognizedCtr.end(); const zeroDefaultCount = 0; if (result.success) { candidates.push({ data: result.data, inexactCount, zeroDefaultCount, fieldCount: -1, // We'll count this later if needed }); continue; } errors[i]!.push(...result.error.issues); } // No valid options if (candidates.length === 0) { parentUnrecognizedCtr.end(0); ctx.addIssue({ input: input, code: "invalid_union", errors: errors }); return z.NEVER; } let best = candidates[0]!; // Find the best option for (const candidate of candidates) { // Minor optimization to avoid counting fields if there's only one candidate if (candidates.length > 1) { candidate.fieldCount = countFieldsRecursive(candidate.data); } best = better(candidate, best); } // The cost of this union should be the cost of the best candidate not all the candidates parentUnrecognizedCtr.end(best.inexactCount); return best.data; }) as any; } function better(a: Candidate, b: Candidate): Candidate { // First prefer exact matches over inexact ones const aIsExact = a.inexactCount === 0; const bIsExact = b.inexactCount === 0; if (aIsExact !== bIsExact) { return aIsExact ? a : b; } // Then compare field counts const actualFieldCountA = a.fieldCount - a.zeroDefaultCount; const actualFieldCountB = b.fieldCount - b.zeroDefaultCount; if (actualFieldCountA !== actualFieldCountB) { return actualFieldCountA > actualFieldCountB ? a : b; } return a.inexactCount < b.inexactCount ? a : b; } /** * Counts the number of fields in a parsed value recursively. * @param `parsed` assumed to *not* contain cycles * fieldCount: total number of fields found * inexactCount: number of primitive values that are not unrecognized enum values */ function countFieldsRecursive(parsed: unknown): number { let fieldCount = 0; const queue: unknown[] = [parsed]; let index = 0; while (index < queue.length) { const value = queue[index++]; if (value === undefined || isDiscriminatedUnionUnknown(value)) { continue; } // Check if it's a primitive value const type = typeof value; if ( value === null || type === "number" || type === "string" || type === "boolean" || type === "bigint" || value instanceof Date || value instanceof RFCDate ) { fieldCount++; continue; } // Handle arrays if (Array.isArray(value)) { queue.push(...value); continue; } // Handle objects if (type === "object") { queue.push(...Object.values(value)); } } return fieldCount; }