Skip to content

Commit

Permalink
fix: bundle original spec to account for multi-file API definitions (#…
Browse files Browse the repository at this point in the history
…252)

We do some validations on the "resolved spec" or the full API definition with all of its
references resolved into one large document. This takes multi-file specs into account and
resolves all references, even to other files. However, some validations are performed only
on the original spec as it provides some benefits, such as gathering all schemas without
worrying about duplicates. The problem with our current approach is that, if the spec is
split into multiple files, we only validate the entry file and none of the others.

This adds a quick step to "bundle" all of the files together into one "file" that only has
internal references. This way, the unresolved "js spec" will represent the entire definition.
  • Loading branch information
dpopp07 committed Mar 9, 2021
1 parent 23098b7 commit f241c8b
Showing 1 changed file with 12 additions and 3 deletions.
15 changes: 12 additions & 3 deletions src/cli-validator/utils/buildSwaggerObject.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@ const schemas = {
module.exports = async function(input) {
// initialize an object to be passed through all the validators
const swagger = {};
const parser = new RefParser();

// in case of multi-file specifications, bundle the spec into one file with
// only internal refs. use this for the spec string and the js spec
const bundledSpec = await parser.bundle(copyObject(input));

// formatting the JSON string with indentations is necessary for the
// validations that use it with regular expressions (e.g. refs.js)
const indentationSpaces = 2;
swagger.specStr = JSON.stringify(input, null, indentationSpaces);
swagger.specStr = JSON.stringify(bundledSpec, null, indentationSpaces);

// deep copy input to a jsSpec by parsing the spec string.
// just setting it equal to 'input' and then calling 'dereference'
Expand All @@ -35,10 +40,9 @@ module.exports = async function(input) {

// dereference() resolves all references. it esentially returns the resolvedSpec,
// but without the $$ref tags (which are not used in the validations)
const parser = new RefParser();
parser.dereference.circular = false;
// passes the parser a copy of the spec to keep the original spec intact
swagger.resolvedSpec = await parser.dereference(JSON.parse(swagger.specStr));
swagger.resolvedSpec = await parser.dereference(copyObject(input));
swagger.circular = parser.$refs.circular;

const version = getVersion(swagger.jsSpec);
Expand All @@ -53,3 +57,8 @@ module.exports = async function(input) {

return swagger;
};

// copy an object such that changes to the copy won't affect the original
function copyObject(obj) {
return JSON.parse(JSON.stringify(obj));
}

0 comments on commit f241c8b

Please sign in to comment.