mirror of
https://github.com/postmanlabs/openapi-to-postman.git
synced 2022-11-29 22:05:00 +03:00
added support for multifile
This commit is contained in:
82
index.js
82
index.js
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
79
lib/parse.js
79
lib/parse.js
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
1675
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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",
|
||||
|
||||
4
test/data/multiFile_with_one_root/definitions/User.yaml
Normal file
4
test/data/multiFile_with_one_root/definitions/User.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
2
test/data/multiFile_with_one_root/definitions/index.yaml
Normal file
2
test/data/multiFile_with_one_root/definitions/index.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
User:
|
||||
$ref: ./User.yaml
|
||||
7
test/data/multiFile_with_one_root/index.yaml
Normal file
7
test/data/multiFile_with_one_root/index.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
openapi: '3.0.0'
|
||||
info:
|
||||
$ref: ./info/index.yaml
|
||||
paths:
|
||||
$ref: ./paths/index.yaml
|
||||
definitions:
|
||||
$ref: ./definitions/index.yaml
|
||||
2
test/data/multiFile_with_one_root/info/index.yaml
Normal file
2
test/data/multiFile_with_one_root/info/index.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
version: 0.0.0
|
||||
title: Simple API
|
||||
6
test/data/multiFile_with_one_root/paths/bar.yaml
Normal file
6
test/data/multiFile_with_one_root/paths/bar.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
get:
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/User'
|
||||
4
test/data/multiFile_with_one_root/paths/foo.yaml
Normal file
4
test/data/multiFile_with_one_root/paths/foo.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
get:
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
4
test/data/multiFile_with_one_root/paths/index.yaml
Normal file
4
test/data/multiFile_with_one_root/paths/index.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
/foo:
|
||||
$ref: ./foo.yaml
|
||||
/bar:
|
||||
$ref: ./bar.yaml
|
||||
4
test/data/multiFile_with_two_root/definitions/User.yaml
Normal file
4
test/data/multiFile_with_two_root/definitions/User.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
2
test/data/multiFile_with_two_root/definitions/index.yaml
Normal file
2
test/data/multiFile_with_two_root/definitions/index.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
User:
|
||||
$ref: ./User.yaml
|
||||
7
test/data/multiFile_with_two_root/index.yaml
Normal file
7
test/data/multiFile_with_two_root/index.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
openapi: '3.0.0'
|
||||
info:
|
||||
$ref: ./info/index.yaml
|
||||
paths:
|
||||
$ref: ./paths/index.yaml
|
||||
definitions:
|
||||
$ref: ./definitions/index.yaml
|
||||
7
test/data/multiFile_with_two_root/index1.yaml
Normal file
7
test/data/multiFile_with_two_root/index1.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
openapi: '3.0.0'
|
||||
info:
|
||||
$ref: ./info/index1.yaml
|
||||
paths:
|
||||
$ref: ./paths/index.yaml
|
||||
definitions:
|
||||
$ref: ./definitions/index.yaml
|
||||
2
test/data/multiFile_with_two_root/info/index.yaml
Normal file
2
test/data/multiFile_with_two_root/info/index.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
version: 0.0.0
|
||||
title: Simple API
|
||||
2
test/data/multiFile_with_two_root/info/index1.yaml
Normal file
2
test/data/multiFile_with_two_root/info/index1.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
version: 0.0.0
|
||||
title: Simple API copy
|
||||
6
test/data/multiFile_with_two_root/paths/bar.yaml
Normal file
6
test/data/multiFile_with_two_root/paths/bar.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
get:
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/User'
|
||||
4
test/data/multiFile_with_two_root/paths/foo.yaml
Normal file
4
test/data/multiFile_with_two_root/paths/foo.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
get:
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
4
test/data/multiFile_with_two_root/paths/index.yaml
Normal file
4
test/data/multiFile_with_two_root/paths/index.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
/foo:
|
||||
$ref: ./foo.yaml
|
||||
/bar:
|
||||
$ref: ./bar.yaml
|
||||
@@ -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
54
test/unit/parse.test.js
Normal 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');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user