object.js 2.3 KB

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