diff --git a/lib/parse.js b/lib/parse.js index 8c395052..3542ecc4 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -147,9 +147,93 @@ module.exports = { throw new Error(e.message); } }); + + // there can be only one root file and the root file should not be referenced by any other file. + if (rootFilesArray.length > 1) { + let fileRefPathObj = {}; + + rootFilesArray.forEach((file) => { + fileRefPathObj[file] = 0; + + let obj, + oasObject, + refFilePaths; + // Use files map if present to read files. + if (!_.isEmpty(files)) { + obj = files[path.resolve(file)]; + } + else if (allowReadingFS) { + obj = fs.readFileSync(file, 'utf8'); + } + + obj = this.getOasObject(obj); + + if (obj.result) { + oasObject = obj.oasObject; + } + + refFilePaths = this.getRefFilePaths(oasObject, file); + refFilePaths.forEach((refFilePath) => { + if (refFilePath in fileRefPathObj) { + fileRefPathObj[refFilePath] += 1; + } + }); + }); + + // Get the root files + rootFilesArray = Object.keys(fileRefPathObj).filter((file) => { + if (fileRefPathObj[file] === 0) { + return file; + } + }); + } return rootFilesArray; }, + /** Given an OAS object and a file path, returns the file paths of the referenced files + * @param {Object} oasObject OAS object + * @param {String} filePath file path + * @return {Array} refFilePaths + * */ + getRefFilePaths: function (oasObject, filePath) { + let refFilePaths = []; + if (oasObject.hasOwnProperty('$ref')) { + refFilePaths.push(path.resolve(path.dirname(filePath), oasObject.$ref)); + } + else { + let refFilePathsArray = []; + this.getRefFilePathsHelper(oasObject, filePath, refFilePathsArray); + refFilePaths = refFilePathsArray; + } + return refFilePaths; + }, + + /** Helper function for getRefFilePaths + * @param {Object} oasObject OAS object + * @param {String} filePath file path + * @param {Array} refFilePathsArray array to store file paths + * @return {Array} refFilePaths + * */ + getRefFilePathsHelper: function (oasObject, filePath, refFilePathsArray) { + let refFilePaths = []; + if (oasObject.hasOwnProperty('$ref')) { + if (!oasObject.$ref.startsWith('#') && !oasObject.$ref.startsWith('http')) { + let resolvedFilePath = path.resolve(path.dirname(filePath), oasObject.$ref.split('#')[0]); + if (resolvedFilePath !== filePath) { + refFilePaths.push(resolvedFilePath); + } + } + } + else { + Object.keys(oasObject).forEach((key) => { + if (typeof oasObject[key] === 'object') { + this.getRefFilePathsHelper(oasObject[key], filePath, refFilePathsArray); + } + }); + } + refFilePathsArray.push(...refFilePaths); + }, + /** * Resolve file references and generate single OAS Object *