object.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import { ZodOptional } from "zod";
  2. import { parseDef } from "../parseDef.js";
  3. export function parseObjectDef(def, refs) {
  4. const forceOptionalIntoNullable = refs.target === "openAi";
  5. const result = {
  6. type: "object",
  7. properties: {},
  8. };
  9. const required = [];
  10. const shape = def.shape();
  11. for (const propName in shape) {
  12. let propDef = shape[propName];
  13. if (propDef === undefined || propDef._def === undefined) {
  14. continue;
  15. }
  16. let propOptional = safeIsOptional(propDef);
  17. if (propOptional && forceOptionalIntoNullable) {
  18. if (propDef instanceof ZodOptional) {
  19. propDef = propDef._def.innerType;
  20. }
  21. if (!propDef.isNullable()) {
  22. propDef = propDef.nullable();
  23. }
  24. propOptional = false;
  25. }
  26. const parsedDef = parseDef(propDef._def, {
  27. ...refs,
  28. currentPath: [...refs.currentPath, "properties", propName],
  29. propertyPath: [...refs.currentPath, "properties", propName],
  30. });
  31. if (parsedDef === undefined) {
  32. continue;
  33. }
  34. result.properties[propName] = parsedDef;
  35. if (!propOptional) {
  36. required.push(propName);
  37. }
  38. }
  39. if (required.length) {
  40. result.required = required;
  41. }
  42. const additionalProperties = decideAdditionalProperties(def, refs);
  43. if (additionalProperties !== undefined) {
  44. result.additionalProperties = additionalProperties;
  45. }
  46. return result;
  47. }
  48. function decideAdditionalProperties(def, refs) {
  49. if (def.catchall._def.typeName !== "ZodNever") {
  50. return parseDef(def.catchall._def, {
  51. ...refs,
  52. currentPath: [...refs.currentPath, "additionalProperties"],
  53. });
  54. }
  55. switch (def.unknownKeys) {
  56. case "passthrough":
  57. return refs.allowedAdditionalProperties;
  58. case "strict":
  59. return refs.rejectedAdditionalProperties;
  60. case "strip":
  61. return refs.removeAdditionalStrategy === "strict"
  62. ? refs.allowedAdditionalProperties
  63. : refs.rejectedAdditionalProperties;
  64. }
  65. }
  66. function safeIsOptional(schema) {
  67. try {
  68. return schema.isOptional();
  69. }
  70. catch {
  71. return true;
  72. }
  73. }