zodToJsonSchema.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import { parseDef } from "./parseDef.js";
  2. import { getRefs } from "./Refs.js";
  3. const zodToJsonSchema = (schema, options) => {
  4. const refs = getRefs(options);
  5. const definitions = typeof options === "object" && options.definitions
  6. ? Object.entries(options.definitions).reduce((acc, [name, schema]) => ({
  7. ...acc,
  8. [name]: parseDef(schema._def, {
  9. ...refs,
  10. currentPath: [...refs.basePath, refs.definitionPath, name],
  11. }, true) ?? {},
  12. }), {})
  13. : undefined;
  14. const name = typeof options === "string"
  15. ? options
  16. : options?.nameStrategy === "title"
  17. ? undefined
  18. : options?.name;
  19. const main = parseDef(schema._def, name === undefined
  20. ? refs
  21. : {
  22. ...refs,
  23. currentPath: [...refs.basePath, refs.definitionPath, name],
  24. }, false) ?? {};
  25. const title = typeof options === "object" &&
  26. options.name !== undefined &&
  27. options.nameStrategy === "title"
  28. ? options.name
  29. : undefined;
  30. if (title !== undefined) {
  31. main.title = title;
  32. }
  33. const combined = name === undefined
  34. ? definitions
  35. ? {
  36. ...main,
  37. [refs.definitionPath]: definitions,
  38. }
  39. : main
  40. : {
  41. $ref: [
  42. ...(refs.$refStrategy === "relative" ? [] : refs.basePath),
  43. refs.definitionPath,
  44. name,
  45. ].join("/"),
  46. [refs.definitionPath]: {
  47. ...definitions,
  48. [name]: main,
  49. },
  50. };
  51. if (refs.target === "jsonSchema7") {
  52. combined.$schema = "http://json-schema.org/draft-07/schema#";
  53. }
  54. else if (refs.target === "jsonSchema2019-09" || refs.target === "openAi") {
  55. combined.$schema = "https://json-schema.org/draft/2019-09/schema#";
  56. }
  57. if (refs.target === "openAi" &&
  58. ("anyOf" in combined ||
  59. "oneOf" in combined ||
  60. "allOf" in combined ||
  61. ("type" in combined && Array.isArray(combined.type)))) {
  62. console.warn("Warning: OpenAI may not support schemas with unions as roots! Try wrapping it in an object property.");
  63. }
  64. return combined;
  65. };
  66. export { zodToJsonSchema };