added support for multifile

This commit is contained in:
Dhroov7
2019-12-04 13:26:41 +05:30
parent 7a2ad3da39
commit 7e963b0ba2
24 changed files with 1957 additions and 75 deletions

View File

@@ -1,7 +1,17 @@
var converter = require('./lib/convert.js'),
validate = require('./lib/validate.js'),
parse = require('./lib/parse.js'),
async = require('async'),
loader = require('speccy/lib/loader'),
_ = require('lodash'),
fs = require('fs');
// options for speccy loader
const loaderOptions = {
resolve: true, // Resolve external references
jsonSchema: true // Treat $ref like JSON Schema and convert to OpenAPI Schema Objects
};
module.exports = {
convert: function(input, options, cb) {
if (input.type === 'string' || input.type === 'json') {
@@ -19,10 +29,82 @@ module.exports = {
return converter.convert(data, options, cb);
});
}
else if (input.type === 'folder') {
let filesPathArray = input.data,
convertedSpecs = [],
rootFiles = parse.getRootFiles(filesPathArray);
async.each(rootFiles, (rootFile, callback) => {
loader
// will merge all the files in the folder
.loadSpec(rootFile, loaderOptions)
.then((spec) => {
converter.convert(spec, options, (err, result) => {
if (err) {
return callback(null, {
result: false,
reason: err
});
}
// eslint-disable-next-line no-else-return
else {
convertedSpecs.push(result);
return callback(null);
}
});
})
.catch((err) => {
return callback(null, {
result: false,
reason: err
});
});
}, (err) => {
if (err) {
return cb(null, {
result: false,
reason: _.toString(err.reason)
});
}
var conversionResult = false,
convertedCollections = [],
reasonForFail;
_.forEach(convertedSpecs, (convertedSpec) => {
if (convertedSpec.result) {
conversionResult = convertedSpec.result;
convertedCollections.push(convertedSpec.output[0]);
}
else {
conversionResult = convertedSpec.result;
reasonForFail = convertedSpec.reason;
}
});
if (conversionResult) {
return cb(null, {
result: true,
output: convertedCollections
});
}
// eslint-disable-next-line no-else-return
else {
return cb(null, {
result: false,
reason: reasonForFail
});
}
});
}
// eslint-disable-next-line no-else-return
else {
return cb(null, {
result: false,
reason: 'input type:' + input.type + ' is not valid'
});
}
},
validate: function(input) {

View File

@@ -187,7 +187,6 @@ var sdk = require('postman-collection'),
// Adds items from the trie into the collection
this.generateCollection(specWrapper);
return callback(null, {
result: true,
output: [{
@@ -262,7 +261,9 @@ var sdk = require('postman-collection'),
module.exports = {
convert: function(json, options, callback) {
try {
converter.convert(json, options, callback);
converter.convert(json, options, (err, result) => {
callback(null, result);
});
}
catch (e) {
if (e instanceof OpenApiErr) {
@@ -274,7 +275,10 @@ module.exports = {
}
else {
// Unhandled exception, rethrow
callback(e);
callback(null, {
result: false,
reason: e.message
});
}
}
},

View File

@@ -1,4 +1,5 @@
var yaml = require('js-yaml');
var yaml = require('js-yaml'),
fs = require('fs');
module.exports = {
@@ -20,9 +21,9 @@ module.exports = {
}
},
validateRoot: function(spec) {
validateSpec: function(spec) {
// Checking for the all the required properties in the specificatio
// Checking for the all the required properties in the specification
if (!spec.hasOwnProperty('openapi')) {
return {
result: false,
@@ -43,6 +44,7 @@ module.exports = {
reason: 'Specification must contain an Info Object for the meta-data of the API'
};
}
if (!spec.info.hasOwnProperty('title')) {
return {
result: false,
@@ -56,6 +58,36 @@ module.exports = {
reason: 'Specification must contain a semantic version number of the API in the Info Object'
};
}
// Valid specification
return {
result: true,
openapi: spec
};
},
validateRoot: function(spec) {
// Checking for the all the required properties needed in a root file
if (!spec.hasOwnProperty('openapi')) {
return {
result: false,
reason: 'Specification must contain a semantic version number of the OAS specification'
};
}
if (!spec.paths) {
return {
result: false,
reason: 'Specification must contain Paths Object for the available operational paths'
};
}
if (!spec.hasOwnProperty('info')) {
return {
result: false,
reason: 'Specification must contain an Info Object for the meta-data of the API'
};
}
// Valid specification
@@ -63,5 +95,46 @@ module.exports = {
result: true,
openapi: spec
};
},
getOasObject: function(file) {
let oasObj = file;
if (typeof file === 'string') {
try {
oasObj = JSON.parse(file);
}
catch (jsonEx) {
// Not direct JSON. Could be YAML
try {
oasObj = yaml.safeLoad(file);
}
catch (yamlEx) {
// Not JSON or YAML
return {
result: false,
reason: 'The input must be valid JSON or YAML'
};
}
// valid YAML
}
}
return oasObj;
},
getRootFiles: function(filesPathArray) {
let rootFilesArray = [];
filesPathArray.forEach((filePath) => {
let file = fs.readFileSync(filePath.fileName, 'utf8'),
oasObject = this.getOasObject(file);
if (this.validateRoot(oasObject).result) {
rootFilesArray.push(filePath.fileName);
}
});
return rootFilesArray;
}
};

View File

@@ -229,7 +229,7 @@ module.exports = {
// spec is a valid JSON object at this point
// Validate the root level object for semantics
rootValidation = parse.validateRoot(openApiObj);
rootValidation = parse.validateSpec(openApiObj);
if (!rootValidation.result) {
return {
result: false,

1675
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -116,10 +116,12 @@
"openapi2postmanv2": "./bin/openapi2postmanv2.js"
},
"dependencies": {
"async": "3.1.0",
"commander": "2.3.0",
"js-yaml": "3.13.1",
"lodash": "4.17.13",
"postman-collection": "3.5.1"
"postman-collection": "3.5.1",
"speccy": "0.11.0"
},
"author": "Postman Labs <help@getpostman.com>",
"license": "Apache-2.0",

View File

@@ -0,0 +1,4 @@
type: object
properties:
name:
type: string

View File

@@ -0,0 +1,2 @@
User:
$ref: ./User.yaml

View File

@@ -0,0 +1,7 @@
openapi: '3.0.0'
info:
$ref: ./info/index.yaml
paths:
$ref: ./paths/index.yaml
definitions:
$ref: ./definitions/index.yaml

View File

@@ -0,0 +1,2 @@
version: 0.0.0
title: Simple API

View File

@@ -0,0 +1,6 @@
get:
responses:
200:
description: OK
schema:
$ref: '#/definitions/User'

View File

@@ -0,0 +1,4 @@
get:
responses:
200:
description: OK

View File

@@ -0,0 +1,4 @@
/foo:
$ref: ./foo.yaml
/bar:
$ref: ./bar.yaml

View File

@@ -0,0 +1,4 @@
type: object
properties:
name:
type: string

View File

@@ -0,0 +1,2 @@
User:
$ref: ./User.yaml

View File

@@ -0,0 +1,7 @@
openapi: '3.0.0'
info:
$ref: ./info/index.yaml
paths:
$ref: ./paths/index.yaml
definitions:
$ref: ./definitions/index.yaml

View File

@@ -0,0 +1,7 @@
openapi: '3.0.0'
info:
$ref: ./info/index1.yaml
paths:
$ref: ./paths/index.yaml
definitions:
$ref: ./definitions/index.yaml

View File

@@ -0,0 +1,2 @@
version: 0.0.0
title: Simple API

View File

@@ -0,0 +1,2 @@
version: 0.0.0
title: Simple API copy

View File

@@ -0,0 +1,6 @@
get:
responses:
200:
description: OK
schema:
$ref: '#/definitions/User'

View File

@@ -0,0 +1,4 @@
get:
responses:
200:
description: OK

View File

@@ -0,0 +1,4 @@
/foo:
$ref: ./foo.yaml
/bar:
$ref: ./bar.yaml

View File

@@ -245,6 +245,57 @@ describe('CONVERT FUNCTION TESTS ', function() {
done();
});
});
it('Should create collection from folder having only one root file', function(done) {
let folderPath = path.join(__dirname, '../data/multiFile_with_one_root'),
array = [
{ fileName: folderPath + '/index.yaml' },
{ fileName: folderPath + '/definitions/index.yaml' },
{ fileName: folderPath + '/definitions/User.yaml' },
{ fileName: folderPath + '/info/index.yaml' },
{ fileName: folderPath + '/paths/index.yaml' },
{ fileName: folderPath + '/paths/foo.yaml' },
{ fileName: folderPath + '/paths/bar.yaml' }
];
Converter.convert({ type: 'folder', data: array }, {}, (err, result) => {
expect(result.result).to.equal(true);
expect(result.output.length).to.equal(1);
expect(result.output[0].type).to.have.equal('collection');
expect(result.output[0].data).to.have.property('info');
expect(result.output[0].data).to.have.property('item');
done();
});
});
it('Should create collection from folder having more than one root file', function(done) {
let folderPath = path.join(__dirname, '../data/multiFile_with_two_root'),
array = [
{ fileName: folderPath + '/index.yaml' },
{ fileName: folderPath + '/index1.yaml' },
{ fileName: folderPath + '/definitions/index.yaml' },
{ fileName: folderPath + '/definitions/User.yaml' },
{ fileName: folderPath + '/info/index.yaml' },
{ fileName: folderPath + '/info/index1.yaml' },
{ fileName: folderPath + '/paths/index.yaml' },
{ fileName: folderPath + '/paths/foo.yaml' },
{ fileName: folderPath + '/paths/bar.yaml' }
];
Converter.convert({ type: 'folder', data: array }, {}, (err, result) => {
expect(result.result).to.equal(true);
expect(result.output.length).to.equal(2);
// first collection
expect(result.output[0].type).to.have.equal('collection');
expect(result.output[0].data).to.have.property('info');
expect(result.output[0].data).to.have.property('item');
expect(result.output[0].data.info.name).to.equal('Simple API');
// second collection
expect(result.output[1].type).to.have.equal('collection');
expect(result.output[1].data).to.have.property('info');
expect(result.output[1].data).to.have.property('item');
expect(result.output[1].data.info.name).to.equal('Simple API copy');
done();
});
});
});
describe('for invalid requestNameSource option', function() {
var pathPrefix = VALID_OPENAPI_PATH + '/test1.json',

54
test/unit/parse.test.js Normal file
View File

@@ -0,0 +1,54 @@
var expect = require('chai').expect,
path = require('path'),
fs = require('fs'),
parse = require('../../lib/parse');
describe('Parse function tests', function() {
describe('getRootFiles function', function() {
it('Should return an array with only one root file path', function() {
let folderPath = path.join(__dirname, '../data/multiFile_with_one_root'),
array = [
{ fileName: folderPath + '/index.yaml' },
{ fileName: folderPath + '/definitions/index.yaml' },
{ fileName: folderPath + '/definitions/User.yaml' },
{ fileName: folderPath + '/info/index.yaml' },
{ fileName: folderPath + '/paths/index.yaml' },
{ fileName: folderPath + '/paths/foo.yaml' },
{ fileName: folderPath + '/paths/bar.yaml' }
],
result = parse.getRootFiles(array);
expect(result.length).to.equal(1);
expect(result[0]).to.equal('/Users/dhroovgupta/Postman/projects/openapi-to-postman' +
'/test/data/multiFile_with_one_root/index.yaml');
});
});
describe('validateRoot function', function() {
it('Should return an object with result true', function() {
let oas = {
'openapi': '3.0.0',
'info': {
'title': 'sample title',
'version': '1.2.4'
},
'paths': {
'/': {}
}
},
result = parse.validateRoot(oas);
expect(result.result).to.equal(true);
});
});
describe('getOasObject function', function() {
it('Should return a valid oas object from a yaml file', function() {
let filePath = '/Users/dhroovgupta/Postman/projects/openapi-to-postman' +
'/test/data/multiFile_with_one_root/index.yaml',
file = fs.readFileSync(filePath, 'utf8'),
result = parse.getOasObject(file);
expect(result.openapi).to.equal('3.0.0');
});
});
});