(schema, args)
| 309 | * @returns {z.ZodSchema} Closest schema matching the input arguments. |
| 310 | */ |
| 311 | const findClosestSchema = function (schema, args) { |
| 312 | if (!(schema instanceof z.ZodUnion)) { |
| 313 | return schema; |
| 314 | } |
| 315 | |
| 316 | // Helper function that scores how close the input arguments are to a schema. |
| 317 | // Lower score means closer match. |
| 318 | const scoreSchema = schema => { |
| 319 | let score = Infinity; |
| 320 | if (!(schema instanceof z.ZodTuple)) { |
| 321 | console.warn('Schema below is not a tuple: '); |
| 322 | printZodSchema(schema); |
| 323 | return score; |
| 324 | } |
| 325 | |
| 326 | const numArgs = args.length; |
| 327 | const schemaItems = schema.def.items; |
| 328 | const numSchemaItems = schemaItems.length; |
| 329 | const numRequiredSchemaItems = schemaItems |
| 330 | .filter(item => !item.isOptional()) |
| 331 | .length; |
| 332 | |
| 333 | if (numArgs >= numRequiredSchemaItems && numArgs <= numSchemaItems) { |
| 334 | score = 0; |
| 335 | } |
| 336 | // Here, give more weight to mismatch in number of arguments. |
| 337 | // |
| 338 | // For example, color() can either take [Number, Number?] or |
| 339 | // [Number, Number, Number, Number?] as list of parameters. |
| 340 | // If the user passed in 3 arguments, [10, undefined, undefined], it's |
| 341 | // more than likely that they intended to pass in 3 arguments, but the |
| 342 | // last two arguments are invalid. |
| 343 | // |
| 344 | // If there's no bias towards matching the number of arguments, the error |
| 345 | // message will show that we're expecting at most 2 arguments, but more |
| 346 | // are received. |
| 347 | else { |
| 348 | score = Math.abs( |
| 349 | numArgs < numRequiredSchemaItems ? |
| 350 | numRequiredSchemaItems - numArgs : |
| 351 | numArgs - numSchemaItems |
| 352 | ) * 4; |
| 353 | } |
| 354 | |
| 355 | for (let i = 0; i < Math.min(schemaItems.length, args.length); i++) { |
| 356 | const paramSchema = schemaItems[i]; |
| 357 | const arg = args[i]; |
| 358 | |
| 359 | if (!paramSchema.safeParse(arg).success) score++; |
| 360 | } |
| 361 | |
| 362 | return score; |
| 363 | }; |
| 364 | |
| 365 | // Default to the first schema, so that we are guaranteed to return a result. |
| 366 | let closestSchema = schema.def.options[0]; |
| 367 | // We want to return the schema with the lowest score. |
| 368 | let bestScore = Infinity; |
no test coverage detected