parseDef.js 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import { ignoreOverride } from "./Options.js";
  2. import { selectParser } from "./selectParser.js";
  3. export function parseDef(def, refs, forceResolution = false) {
  4. const seenItem = refs.seen.get(def);
  5. if (refs.override) {
  6. const overrideResult = refs.override?.(def, refs, seenItem, forceResolution);
  7. if (overrideResult !== ignoreOverride) {
  8. return overrideResult;
  9. }
  10. }
  11. if (seenItem && !forceResolution) {
  12. const seenSchema = get$ref(seenItem, refs);
  13. if (seenSchema !== undefined) {
  14. return seenSchema;
  15. }
  16. }
  17. const newItem = { def, path: refs.currentPath, jsonSchema: undefined };
  18. refs.seen.set(def, newItem);
  19. const jsonSchemaOrGetter = selectParser(def, def.typeName, refs);
  20. // If the return was a function, then the inner definition needs to be extracted before a call to parseDef (recursive)
  21. const jsonSchema = typeof jsonSchemaOrGetter === "function"
  22. ? parseDef(jsonSchemaOrGetter(), refs)
  23. : jsonSchemaOrGetter;
  24. if (jsonSchema) {
  25. addMeta(def, refs, jsonSchema);
  26. }
  27. if (refs.postProcess) {
  28. const postProcessResult = refs.postProcess(jsonSchema, def, refs);
  29. newItem.jsonSchema = jsonSchema;
  30. return postProcessResult;
  31. }
  32. newItem.jsonSchema = jsonSchema;
  33. return jsonSchema;
  34. }
  35. const get$ref = (item, refs) => {
  36. switch (refs.$refStrategy) {
  37. case "root":
  38. return { $ref: item.path.join("/") };
  39. case "relative":
  40. return { $ref: getRelativePath(refs.currentPath, item.path) };
  41. case "none":
  42. case "seen": {
  43. if (item.path.length < refs.currentPath.length &&
  44. item.path.every((value, index) => refs.currentPath[index] === value)) {
  45. console.warn(`Recursive reference detected at ${refs.currentPath.join("/")}! Defaulting to any`);
  46. return {};
  47. }
  48. return refs.$refStrategy === "seen" ? {} : undefined;
  49. }
  50. }
  51. };
  52. const getRelativePath = (pathA, pathB) => {
  53. let i = 0;
  54. for (; i < pathA.length && i < pathB.length; i++) {
  55. if (pathA[i] !== pathB[i])
  56. break;
  57. }
  58. return [(pathA.length - i).toString(), ...pathB.slice(i)].join("/");
  59. };
  60. const addMeta = (def, refs, jsonSchema) => {
  61. if (def.description) {
  62. jsonSchema.description = def.description;
  63. if (refs.markdownDescription) {
  64. jsonSchema.markdownDescription = def.description;
  65. }
  66. }
  67. return jsonSchema;
  68. };