Skip to content

Commit 850476e

Browse files
committed
Try and fix circular refrences
1 parent 29a1c74 commit 850476e

File tree

1 file changed

+93
-4
lines changed

1 file changed

+93
-4
lines changed

src/Convertor.js

Lines changed: 93 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,20 +94,40 @@ class Convertor {
9494
property
9595
) => {
9696
this.parseSchema(schema);
97+
9798
if (this.components.schemas) {
9899
Object.assign(this.components.schemas, { [name]: rootSchema });
99100
} else {
100101
Object.assign(this.components, { schemas: { [name]: rootSchema } });
101102
}
102103
};
103-
if (this.schema.title === "UserResponse")
104-
console.log(
105-
this.schema.properties.user.properties.classes.items.properties.subRows
106-
);
104+
105+
this.closeCircularReferences();
107106
traverse(this.schema, traversal);
108107
return this.components;
109108
}
110109

110+
closeCircularReferences() {
111+
const report = this.isCyclic(this.schema, true);
112+
113+
for (const reportDetail of report) {
114+
try {
115+
this.closingTheCircle(this.schema, reportDetail.duplicate, {});
116+
} catch (err) {
117+
console.error(err);
118+
throw err;
119+
}
120+
}
121+
}
122+
123+
closingTheCircle(obj, is, value) {
124+
if (typeof is == "string")
125+
return this.closingTheCircle(obj, is.split("."), value);
126+
else if (is.length == 1 && value !== undefined) return (obj[is[0]] = value);
127+
else if (is.length == 0) return obj;
128+
else return this.closingTheCircle(obj[is[0]], is.slice(1), value);
129+
}
130+
111131
parseSchema(schema) {
112132
this.convertConst(schema);
113133
this.convertArrays(schema);
@@ -487,6 +507,75 @@ class Convertor {
487507
}
488508
}
489509
}
510+
511+
isCyclic(x, bReturnReport) {
512+
var a_sKeys = [],
513+
a_oStack = [],
514+
wm_oSeenObjects = new WeakMap(), //# see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
515+
oReturnVal = {
516+
found: false,
517+
report: [],
518+
};
519+
//# Setup the recursive logic to locate any circular references while kicking off the initial call
520+
(function doIsCyclic(oTarget, sKey) {
521+
var a_sTargetKeys, sCurrentKey, i;
522+
523+
//# If we've seen this oTarget before, flip our .found to true
524+
if (wm_oSeenObjects.has(oTarget)) {
525+
oReturnVal.found = true;
526+
527+
//# If we are to bReturnReport, add the entries into our .report
528+
if (bReturnReport) {
529+
oReturnVal.report.push({
530+
instance: oTarget,
531+
source: a_sKeys.slice(0, a_oStack.indexOf(oTarget) + 1).join("."),
532+
duplicate: a_sKeys.join(".") + "." + sKey,
533+
});
534+
}
535+
}
536+
//# Else if oTarget is an instanceof Object, determine the a_sTargetKeys and .set our oTarget into the wm_oSeenObjects
537+
else if (oTarget instanceof Object) {
538+
a_sTargetKeys = Object.keys(oTarget);
539+
wm_oSeenObjects.set(oTarget /*, undefined*/);
540+
541+
//# If we are to bReturnReport, .push the current level's/call's items onto our stacks
542+
if (bReturnReport) {
543+
if (sKey) {
544+
a_sKeys.push(sKey);
545+
}
546+
a_oStack.push(oTarget);
547+
}
548+
549+
//# Traverse the a_sTargetKeys, pulling each into sCurrentKey as we go
550+
//# NOTE: If you want all properties, even non-enumerables, see Object.getOwnPropertyNames() so there is no need to call .hasOwnProperty (per: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys)
551+
for (i = 0; i < a_sTargetKeys.length; i++) {
552+
sCurrentKey = a_sTargetKeys[i];
553+
554+
//# If we've already .found a circular reference and we're not bReturnReport, fall from the loop
555+
if (oReturnVal.found && !bReturnReport) {
556+
break;
557+
}
558+
//# Else if the sCurrentKey is an instanceof Object, recurse to test
559+
else if (oTarget[sCurrentKey] instanceof Object) {
560+
doIsCyclic(oTarget[sCurrentKey], sCurrentKey);
561+
}
562+
}
563+
564+
//# .delete our oTarget into the wm_oSeenObjects
565+
wm_oSeenObjects.delete(oTarget);
566+
567+
//# If we are to bReturnReport, .pop the current level's/call's items off our stacks
568+
if (bReturnReport) {
569+
if (sKey) {
570+
a_sKeys.pop();
571+
}
572+
a_oStack.pop();
573+
}
574+
}
575+
})(x, ""); //# doIsCyclic
576+
577+
return bReturnReport ? oReturnVal.report : oReturnVal.found;
578+
}
490579
}
491580

492581
module.exports = Convertor;

0 commit comments

Comments
 (0)