Fix bugs and warnings from linter
This commit is contained in:
Родитель
4459e377b6
Коммит
ff7d81279e
53
.jshintrc
53
.jshintrc
|
@ -1,29 +1,28 @@
|
|||
{
|
||||
"esversion": 6,
|
||||
"bitwise": true,
|
||||
"camelcase": true,
|
||||
"curly": false,
|
||||
"eqeqeq": false,
|
||||
"forin": true,
|
||||
"immed": true,
|
||||
"indent": 2,
|
||||
"latedef": true,
|
||||
"maxparams": false,
|
||||
"maxdepth": false,
|
||||
"maxstatements": false,
|
||||
"maxcomplexity": false,
|
||||
"newcap": true,
|
||||
"noarg": true,
|
||||
"node": true,
|
||||
"noempty": true,
|
||||
"nonew": true,
|
||||
"plusplus": false,
|
||||
"quotmark": "single",
|
||||
"regexp": true,
|
||||
"sub": true,
|
||||
"strict": false,
|
||||
"trailing": true,
|
||||
"undef": true,
|
||||
"unused": false,
|
||||
"shadow": true
|
||||
"esversion": 6,
|
||||
"bitwise": true,
|
||||
"camelcase": true,
|
||||
"curly": false,
|
||||
"eqeqeq": false,
|
||||
"forin": true,
|
||||
"immed": true,
|
||||
"indent": 2,
|
||||
"latedef": true,
|
||||
"maxparams": false,
|
||||
"maxdepth": false,
|
||||
"maxstatements": false,
|
||||
"maxcomplexity": false,
|
||||
"newcap": true,
|
||||
"noarg": true,
|
||||
"node": true,
|
||||
"noempty": true,
|
||||
"nonew": true,
|
||||
"plusplus": false,
|
||||
"regexp": true,
|
||||
"sub": true,
|
||||
"strict": false,
|
||||
"trailing": true,
|
||||
"undef": true,
|
||||
"unused": false,
|
||||
"shadow": true
|
||||
}
|
|
@ -18,7 +18,7 @@ exports = module.exports;
|
|||
|
||||
const extension = new extensionBase.AutoRestExtension();
|
||||
const modelValidatorPluginName = "model-validator";
|
||||
const modelValidationCategory = "ExampleModelViolation"
|
||||
const modelValidationCategory = "ExampleModelViolation";
|
||||
|
||||
function FormattedOutput(channel, details, code, text, source) {
|
||||
this.channel = channel;
|
||||
|
@ -29,23 +29,23 @@ function FormattedOutput(channel, details, code, text, source) {
|
|||
}
|
||||
|
||||
extension.Add(modelValidatorPluginName, autoRestApi => {
|
||||
return autoRestApi.ListInputs().then(function (swaggerFileNames) {
|
||||
return autoRestApi.ListInputs().then((swaggerFileNames) => {
|
||||
const promises = [];
|
||||
for (const swaggerFileName of swaggerFileNames) {
|
||||
promises.push(
|
||||
autoRestApi.ReadFile(swaggerFileName).then(function (swaggerFile) {
|
||||
autoRestApi.ReadFile(swaggerFileName).then((swaggerFile) => {
|
||||
const swagger = yaml.safeLoad(swaggerFile);
|
||||
return exports.openApiValidationExample(swagger, swaggerFileName).then(function (exampleValidationResults) {
|
||||
for (const result of exampleValidationResults) {
|
||||
autoRestApi.Message({ Channel: result.channel, Text: result.text, Details: result.details, Key: result.code, Source: result.source });
|
||||
}
|
||||
// console.error(JSON.stringify(exampleValidationResults, null, 2));
|
||||
})
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
return Promise.all(promises).then(_ => true)
|
||||
})
|
||||
return Promise.all(promises).then(_ => true);
|
||||
});
|
||||
});
|
||||
|
||||
exports.openApiValidationExample = function openApiValidationExample(swagger, swaggerFileName, options) {
|
||||
|
@ -57,10 +57,10 @@ exports.openApiValidationExample = function openApiValidationExample(swagger, sw
|
|||
//console.error(JSON.stringify(swagger, null, 2));
|
||||
return specVal.initialize().then(function () {
|
||||
specVal.validateOperations();
|
||||
Promise.resolve(specVal.specValidationResult).then(function (specValidationResult) {
|
||||
for (var op in specValidationResult.operations) {
|
||||
Promise.resolve(specVal.specValidationResult).then((specValidationResult) => {
|
||||
for (let op of utils.getKeys(specValidationResult.operations)) {
|
||||
const xmsExamplesNode = specValidationResult.operations[op]["x-ms-examples"];
|
||||
for (var scenario in xmsExamplesNode.scenarios) {
|
||||
for (let scenario of utils.getKeys(xmsExamplesNode.scenarios)) {
|
||||
// invalid? meaning that there's an issue found in the validation
|
||||
var scenarioItem = xmsExamplesNode.scenarios[scenario];
|
||||
if (scenarioItem.isValid === false) {
|
||||
|
@ -72,7 +72,7 @@ exports.openApiValidationExample = function openApiValidationExample(swagger, sw
|
|||
throw new Error("Model Validator: Path to x-ms-examples not found.");
|
||||
}
|
||||
//console.error(JSON.stringify(scenarioItem, null, 2));
|
||||
var result = new FormattedOutput("verbose", scenarioItem, scenario, [modelValidationCategory], "Model validator found issue (see details).", [{ document: swaggerFileName, Position: { path: xmsexPath } }])
|
||||
var result = new FormattedOutput("verbose", scenarioItem, scenario, [modelValidationCategory], "Model validator found issue (see details).", [{ document: swaggerFileName, Position: { path: xmsexPath } }]);
|
||||
formattedResult.push(result);
|
||||
|
||||
// request
|
||||
|
@ -84,9 +84,9 @@ exports.openApiValidationExample = function openApiValidationExample(swagger, sw
|
|||
throw new Error("Model Validator: Unexpected format.");
|
||||
}
|
||||
for (const innerError of innerErrors) {
|
||||
const path = ConvertIndicesFromStringToNumbers(innerError.path);
|
||||
const path = convertIndicesFromStringToNumbers(innerError.path);
|
||||
//console.error(JSON.stringify(error, null, 2));
|
||||
resultDetails = { type: "Error", code: error.code, message: error.message, id: error.id, validationCategory: modelValidationCategory, innerErrors: innerError };
|
||||
let resultDetails = { type: "Error", code: error.code, message: error.message, id: error.id, validationCategory: modelValidationCategory, innerErrors: innerError };
|
||||
result = new FormattedOutput("error", resultDetails, [error.code, error.id, modelValidationCategory],
|
||||
innerError.message + ". \nScenario: " + scenario + ". \nDetails: " + JSON.stringify(innerError.errors, null, 2) + "\nMore info: " + openAPIDocUrl + "#" + error.id.toLowerCase() + "-" + error.code.toLowerCase() + "\n",
|
||||
[{ document: swaggerFileName, Position: { path: path } }]);
|
||||
|
@ -95,7 +95,7 @@ exports.openApiValidationExample = function openApiValidationExample(swagger, sw
|
|||
}
|
||||
|
||||
// responses
|
||||
for (var responseCode in scenarioItem.responses) {
|
||||
for (let responseCode of utils.getKeys(scenarioItem.responses)) {
|
||||
const response = scenarioItem.responses[responseCode];
|
||||
if (response.isValid === false) {
|
||||
const error = response.error;
|
||||
|
@ -105,11 +105,11 @@ exports.openApiValidationExample = function openApiValidationExample(swagger, sw
|
|||
}
|
||||
for (const innerError of innerErrors) {
|
||||
//console.error(JSON.stringify(error, null, 2));
|
||||
resultDetails = { type: "Error", code: error.code, message: error.message, id: error.id, validationCategory: modelValidationCategory, innerErrors: innerError };
|
||||
let resultDetails = { type: "Error", code: error.code, message: error.message, id: error.id, validationCategory: modelValidationCategory, innerErrors: innerError };
|
||||
result = new FormattedOutput("error", resultDetails, [error.code, error.id, modelValidationCategory],
|
||||
innerError.message + ". \nScenario: " + scenario + ". \nDetails: " + JSON.stringify(innerError.errors, null, 2) + "\nMore info: " + openAPIDocUrl + "#" + error.id.toLowerCase() + "-" + error.code.toLowerCase() + "\n",
|
||||
[{ document: swaggerFileName, Position: { path: xmsexPath.slice(0, xmsexPath.length - 1).concat(["responses", responseCode]) } }
|
||||
])
|
||||
]);
|
||||
formattedResult.push(result);
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ exports.openApiValidationExample = function openApiValidationExample(swagger, sw
|
|||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
return formattedResult;
|
||||
}).catch(function (err) {
|
||||
console.error(err);
|
||||
|
@ -127,7 +127,7 @@ exports.openApiValidationExample = function openApiValidationExample(swagger, sw
|
|||
/**
|
||||
* Path comes with indices as strings in "inner errors", so converting those to actual numbers for path to work.
|
||||
*/
|
||||
function ConvertIndicesFromStringToNumbers(path) {
|
||||
function convertIndicesFromStringToNumbers(path) {
|
||||
const result = path.slice();
|
||||
for (let i = 1; i < result.length; ++i) {
|
||||
const num = parseInt(result[i]);
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
'use strict';
|
||||
const url = require('url'),
|
||||
uuid = require('uuid');
|
||||
uuid = require('uuid'),
|
||||
utils = require('../util/utils');
|
||||
|
||||
class HttpTemplate {
|
||||
|
||||
|
@ -27,7 +28,7 @@ class HttpTemplate {
|
|||
result += `\n${padding}-H 'Content-Length: ${JSON.stringify(this.request.body).length}' \\`;
|
||||
}
|
||||
if (this.request.headers) {
|
||||
let headers = Object.keys(this.request.headers);
|
||||
let headers = utils.getKeys(this.request.headers);
|
||||
|
||||
for (let i = 0; i < headers.length; i++) {
|
||||
let headerName = headers[i];
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
'use strict';
|
||||
const url = require('url'),
|
||||
HttpTemplate = require('./httpTemplate'),
|
||||
uuid = require('uuid');
|
||||
uuid = require('uuid'),
|
||||
utils = require('../util/utils');
|
||||
|
||||
class MarkdownHttpTemplate extends HttpTemplate {
|
||||
|
||||
|
@ -18,7 +19,7 @@ class MarkdownHttpTemplate extends HttpTemplate {
|
|||
result += `Content-Length: ${JSON.stringify(this.request.body).length}\n`;
|
||||
}
|
||||
if (this.request.headers) {
|
||||
let headers = Object.keys(this.request.headers);
|
||||
let headers = utils.getKeys(this.request.headers);
|
||||
|
||||
for (let i = 0; i < headers.length; i++) {
|
||||
let headerName = headers[i];
|
||||
|
@ -38,7 +39,7 @@ class MarkdownHttpTemplate extends HttpTemplate {
|
|||
}
|
||||
let gotContentType = false;
|
||||
if (response.headers) {
|
||||
let headers = Object.keys(response.headers);
|
||||
let headers = utils.getKeys(response.headers);
|
||||
for (let i = 0; i < headers.length; i++) {
|
||||
let headerName = headers[i];
|
||||
if (headerName.match(/^Content-Type$/ig) !== null) gotContentType = true;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
'use strict';
|
||||
const url = require('url'),
|
||||
utils = require('../util/utils'),
|
||||
HttpTemplate = require('./httpTemplate'),
|
||||
uuid = require('uuid');
|
||||
|
||||
|
@ -18,7 +19,7 @@ class YamlHttpTemplate extends HttpTemplate {
|
|||
result += ` Content-Length: ${JSON.stringify(this.request.body).length}\n`;
|
||||
}
|
||||
if (this.request.headers) {
|
||||
let headers = Object.keys(this.request.headers);
|
||||
let headers = utils.getKeys(this.request.headers);
|
||||
|
||||
for (let i = 0; i < headers.length; i++) {
|
||||
let headerName = headers[i];
|
||||
|
@ -38,7 +39,7 @@ class YamlHttpTemplate extends HttpTemplate {
|
|||
}
|
||||
let gotContentType = false;
|
||||
if (response.headers) {
|
||||
let headers = Object.keys(response.headers);
|
||||
let headers = utils.getKeys(response.headers);
|
||||
for (let i = 0; i < headers.length; i++) {
|
||||
let headerName = headers[i];
|
||||
if (headerName.match(/^Content-Type$/ig) !== null) gotContentType = true;
|
||||
|
|
|
@ -20,14 +20,14 @@ class UmlGenerator {
|
|||
/**
|
||||
* @constructor
|
||||
* Initializes a new instance of the UmlGenerator class.
|
||||
*
|
||||
*
|
||||
* @param {object} specInJson the parsed spec in json format
|
||||
*
|
||||
*
|
||||
* @return {object} An instance of the UmlGenerator class.
|
||||
*/
|
||||
constructor(specInJson, options) {
|
||||
if (specInJson === null || specInJson === undefined || typeof specInJson !== 'object') {
|
||||
throw new Error('specInJson is a required property of type object')
|
||||
throw new Error('specInJson is a required property of type object');
|
||||
}
|
||||
this.specInJson = specInJson;
|
||||
this.graphDefinition = '';
|
||||
|
@ -46,7 +46,7 @@ class UmlGenerator {
|
|||
generateAllOfGraph() {
|
||||
let spec = this.specInJson;
|
||||
let definitions = spec.definitions;
|
||||
for (let modelName in definitions) {
|
||||
for (let modelName of utils.getKeys(definitions)) {
|
||||
let model = definitions[modelName];
|
||||
if (model.allOf) {
|
||||
model.allOf.map((item) => {
|
||||
|
@ -64,12 +64,12 @@ class UmlGenerator {
|
|||
let spec = this.specInJson;
|
||||
let definitions = spec.definitions;
|
||||
let references = [];
|
||||
for (let modelName in definitions) {
|
||||
for (let modelName of utils.getKeys(definitions)) {
|
||||
let model = definitions[modelName];
|
||||
let modelProperties = model.properties;
|
||||
let props = '';
|
||||
if (modelProperties) {
|
||||
for (let propertyName in modelProperties) {
|
||||
for (let propertyName of utils.getKeys(modelProperties)) {
|
||||
let property = modelProperties[propertyName];
|
||||
let propertyType = this.getPropertyType(modelName, property, references);
|
||||
let discriminator = '';
|
||||
|
@ -95,7 +95,7 @@ class UmlGenerator {
|
|||
}
|
||||
|
||||
if (property.type === 'array') {
|
||||
let result = 'Array<'
|
||||
let result = 'Array<';
|
||||
if (property.items) {
|
||||
result += this.getPropertyType(modelName, property.items, references);
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ class UmlGenerator {
|
|||
}
|
||||
|
||||
if (property.type === 'object') {
|
||||
return 'Object'
|
||||
return 'Object';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
|
|
@ -18,12 +18,12 @@ var util = require('util'),
|
|||
/*
|
||||
* @class
|
||||
* It is responsible for executing an example against a live service.
|
||||
*/
|
||||
*/
|
||||
class ExecutionEngine {
|
||||
/*
|
||||
* @constructor
|
||||
* Initializes a new instance of the ExecutionEngine class.
|
||||
*
|
||||
*
|
||||
* @return {object} An instance of the ExecutionEngine class.
|
||||
*/
|
||||
constructor() {
|
||||
|
@ -40,7 +40,7 @@ class ExecutionEngine {
|
|||
}
|
||||
}
|
||||
return exampleParameters;
|
||||
};
|
||||
}
|
||||
|
||||
liveTest(specPath, operationId) {
|
||||
let self = this;
|
||||
|
@ -59,8 +59,7 @@ class ExecutionEngine {
|
|||
operation = validator.getOperationById(operationId);
|
||||
xmsExamples = operation[Constants.xmsExamples];
|
||||
if (xmsExamples) {
|
||||
for (let scenario in xmsExamples) {
|
||||
let xmsExample = xmsExamples[scenario];
|
||||
for (let xmsExample of utils.get(xmsExamples)) {
|
||||
let parameters = self.sanitizeParameters(xmsExample.parameters);
|
||||
let result = validator.validateRequest(operation, xmsExample.parameters);
|
||||
if (result.validationResult && result.validationResult.errors && result.validationResult.errors.length) {
|
||||
|
@ -75,17 +74,17 @@ class ExecutionEngine {
|
|||
if (req.body !== null && req.body !== undefined) {
|
||||
req.body = JSON.stringify(req.body);
|
||||
}
|
||||
msrestazure.loginWithServicePrincipalSecret(clientId, secret, domain, function (err, creds, subscriptions) {
|
||||
msrestazure.loginWithServicePrincipalSecret(clientId, secret, domain, (err, creds, subscriptions) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
let resourceClient = new ResourceManagementClient(creds, subscriptionId);
|
||||
let client = new msrestazure.AzureServiceClient(creds);
|
||||
self.createResourceGroup(resourceClient, location, resourceGroupName, function (err, resourceGroup) {
|
||||
self.createResourceGroup(resourceClient, location, resourceGroupName, (err, resourceGroup) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
client.sendRequest(req, function (err, result, request, response) {
|
||||
client.sendRequest(req, (err, result, request, response) => {
|
||||
log.info(request);
|
||||
log.info(response);
|
||||
if (err) {
|
||||
|
@ -117,7 +116,7 @@ class ExecutionEngine {
|
|||
|
||||
getResourceGroup(resourceClient, resourceGroupName, callback) {
|
||||
let self = this;
|
||||
log.info(`Searching ResourceGroup: ${resourceGroupName}.`)
|
||||
log.info(`Searching ResourceGroup: ${resourceGroupName}.`);
|
||||
resourceClient.resourceGroups.get(resourceGroupName, callback);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ exports.docCache = {};
|
|||
exports.clearCache = function clearCache() {
|
||||
exports.docCache = {};
|
||||
return;
|
||||
}
|
||||
};
|
||||
/*
|
||||
* Removes byte order marker. This catches EF BB BF (the UTF-8 BOM)
|
||||
* because the buffer-to-string conversion in `fs.readFile()`
|
||||
|
@ -50,7 +50,6 @@ exports.stripBOM = function stripBOM(content) {
|
|||
* @returns {object} jsonDoc - Parsed document in JSON format.
|
||||
*/
|
||||
exports.parseJson = function parseJson(specPath) {
|
||||
let result = null;
|
||||
if (!specPath || (specPath && typeof specPath.valueOf() !== 'string')) {
|
||||
let err = new Error('A (github) url or a local file path to the swagger spec is required and must be of type string.');
|
||||
return Promise.reject(err);
|
||||
|
@ -164,7 +163,7 @@ exports.makeRequest = function makeRequest(options) {
|
|||
res = exports.parseContent(options.url, responseBody);
|
||||
}
|
||||
} catch (error) {
|
||||
let msg = `An error occurred while parsing the file ${options.url}. The error is:\n ${util.inspect(error, { depth: null })}.`
|
||||
let msg = `An error occurred while parsing the file ${options.url}. The error is:\n ${util.inspect(error, { depth: null })}.`;
|
||||
let e = new Error(msg);
|
||||
reject(e);
|
||||
}
|
||||
|
@ -208,7 +207,7 @@ exports.generateRandomId = function generateRandomId(prefix, existingIds) {
|
|||
if (prefix && typeof prefix.valueOf() === 'string') {
|
||||
randomStr = prefix + randomStr;
|
||||
}
|
||||
if (!exsitingIds || !(randomStr in existingIds)) {
|
||||
if (!existingIds || !(randomStr in existingIds)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -319,7 +318,7 @@ exports.mergeObjects = function mergeObjects(source, target) {
|
|||
}
|
||||
});
|
||||
return target;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Merges source array into the target array
|
||||
|
@ -337,7 +336,7 @@ exports.mergeArrays = function mergeArrays(source, target) {
|
|||
target.push(lodash.cloneDeep(item));
|
||||
});
|
||||
return target;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Gets the object from the given doc based on the provided json reference pointer.
|
||||
|
@ -414,7 +413,7 @@ exports.getProvider = function getProvider(path) {
|
|||
let pathMatch;
|
||||
|
||||
// Loop over the paths to find the last matched provider namespace
|
||||
while ((pathMatch = providerRegEx.exec(path)) != null) {
|
||||
while ((pathMatch = providerRegEx.exec(path)) !== null) {
|
||||
result = pathMatch[1];
|
||||
}
|
||||
|
||||
|
@ -484,10 +483,10 @@ exports.removeDirSync = function removeDirSync(dir) {
|
|||
var current = dir + '/' + file;
|
||||
if (fs.statSync(current).isDirectory()) exports.removeDirSync(current);
|
||||
else fs.unlinkSync(current);
|
||||
})
|
||||
});
|
||||
fs.rmdirSync(dir);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Finds the first content-type that contains "/json". Only supported Content-Types are
|
||||
|
@ -525,16 +524,16 @@ exports.isPureObject = function isPureObject(model) {
|
|||
if (!model) {
|
||||
throw new Error(`model cannot be null or undefined and must be of type "object"`);
|
||||
}
|
||||
if (model.type && typeof model.type.valueOf() === 'string' && model.type === 'object' && model.properties && Object.keys(model.properties).length === 0) {
|
||||
if (model.type && typeof model.type.valueOf() === 'string' && model.type === 'object' && model.properties && exports.getKeys(model.properties).length === 0) {
|
||||
return true;
|
||||
} else if (!model.type && model.properties && Object.keys(model.properties).length === 0) {
|
||||
} else if (!model.type && model.properties && exports.getKeys(model.properties).length === 0) {
|
||||
return true;
|
||||
} else if (model.type && typeof model.type.valueOf() === 'string' && model.type === 'object' && !model.properties && !model.additionalProperties) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Relaxes/Transforms the given entities type from a specific JSON schema primitive type (http://json-schema.org/latest/json-schema-core.html#rfc.section.4.2)
|
||||
|
@ -568,8 +567,8 @@ exports.relaxModelLikeEntities = function relaxModelLikeEntities(model) {
|
|||
model = exports.relaxEntityType(model);
|
||||
if (model.properties) {
|
||||
let modelProperties = model.properties;
|
||||
for (let propName in modelProperties) {
|
||||
let isPropRequired = model.required ? model.required.some((p) => { return p == propName; }) : false
|
||||
for (let propName of exports.getKeys(modelProperties)) {
|
||||
let isPropRequired = model.required ? model.required.some((p) => { return p == propName; }) : false;
|
||||
if (modelProperties[propName].properties) {
|
||||
modelProperties[propName] = exports.relaxModelLikeEntities(modelProperties[propName]);
|
||||
} else {
|
||||
|
@ -578,7 +577,7 @@ exports.relaxModelLikeEntities = function relaxModelLikeEntities(model) {
|
|||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Relaxes the entity to be a oneOf: [the current type OR null type] if the condition is satisfied
|
||||
|
@ -595,7 +594,7 @@ exports.allowNullType = function allowNullType(entity, isPropRequired) {
|
|||
if (entity.items) {
|
||||
// if items object contains inline properties
|
||||
if (entity.items.properties) {
|
||||
entity.items = exports.allowNullableTypes(entity.items)
|
||||
entity.items = exports.allowNullableTypes(entity.items);
|
||||
} else {
|
||||
entity.items = exports.allowNullType(entity.items);
|
||||
}
|
||||
|
@ -612,11 +611,11 @@ exports.allowNullType = function allowNullType(entity, isPropRequired) {
|
|||
}
|
||||
|
||||
if (exports.shouldAcceptNullValue(entity['x-nullable'], isPropRequired)) {
|
||||
let savedEntity = entity
|
||||
let savedEntity = entity;
|
||||
// handling nullable parameters
|
||||
if (savedEntity.in) {
|
||||
entity.oneOf = [{ "type": entity.type }, { "type": "null" }];
|
||||
delete entity.type
|
||||
delete entity.type;
|
||||
} else {
|
||||
entity = {};
|
||||
entity.oneOf = [savedEntity, { "type": "null" }];
|
||||
|
@ -626,23 +625,23 @@ exports.allowNullType = function allowNullType(entity, isPropRequired) {
|
|||
|
||||
// if there's a $ref
|
||||
if (entity && entity["$ref"] && exports.shouldAcceptNullValue(entity['x-nullable'], isPropRequired)) {
|
||||
let savedEntity = entity
|
||||
let savedEntity = entity;
|
||||
entity = {};
|
||||
entity.oneOf = [savedEntity, { "type": "null" }];
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
};
|
||||
|
||||
/** logic table to determine when to use oneOf to accept null values
|
||||
* required \ x-nullable | True | False | Undefined
|
||||
* ===============================================================
|
||||
* Yes | convert to oneOf[] | |
|
||||
* Yes | convert to oneOf[] | |
|
||||
* No | convert to oneOf[] | | convert to oneOf[]
|
||||
*/
|
||||
exports.shouldAcceptNullValue = function shouldAcceptNullValue(xnullable, isPropRequired) {
|
||||
let isPropNullable = xnullable && typeof xnullable === 'boolean';
|
||||
return (isPropNullable === undefined && !isPropRequired) || isPropNullable;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Relaxes/Transforms model definition to allow null values
|
||||
*/
|
||||
|
@ -650,7 +649,7 @@ exports.allowNullableTypes = function allowNullableTypes(model) {
|
|||
// process additionalProperties if present
|
||||
if (model && typeof model.additionalProperties === 'object') {
|
||||
if (model.additionalProperties.properties || model.additionalProperties.additionalProperties) {
|
||||
model.additionalProperties = exports.allowNullableTypes(model.additionalProperties)
|
||||
model.additionalProperties = exports.allowNullableTypes(model.additionalProperties);
|
||||
} else {
|
||||
// there shouldn't be more properties nesting at this point
|
||||
model.additionalProperties = exports.allowNullType(model.additionalProperties);
|
||||
|
@ -664,7 +663,7 @@ exports.allowNullableTypes = function allowNullableTypes(model) {
|
|||
if (modelProperties[propName].properties || modelProperties[propName].additionalProperties) {
|
||||
modelProperties[propName] = exports.allowNullableTypes(modelProperties[propName]);
|
||||
}
|
||||
modelProperties[propName] = exports.allowNullType(modelProperties[propName], isPropRequired)
|
||||
modelProperties[propName] = exports.allowNullType(modelProperties[propName], isPropRequired);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -674,7 +673,7 @@ exports.allowNullableTypes = function allowNullableTypes(model) {
|
|||
// if items object contains additional properties
|
||||
if (model.items.additionalProperties && typeof model.items.additionalProperties === 'object') {
|
||||
if (model.items.additionalProperties.properties || model.items.additionalProperties.additionalProperties) {
|
||||
model.items.additionalProperties = exports.allowNullableTypes(model.items.additionalProperties)
|
||||
model.items.additionalProperties = exports.allowNullableTypes(model.items.additionalProperties);
|
||||
} else {
|
||||
// there shouldn't be more properties nesting at this point
|
||||
model.items.additionalProperties = exports.allowNullType(model.items.additionalProperties);
|
||||
|
@ -682,7 +681,7 @@ exports.allowNullableTypes = function allowNullableTypes(model) {
|
|||
}
|
||||
// if items object contains inline properties
|
||||
if (model.items.properties) {
|
||||
model.items = exports.allowNullableTypes(model.items)
|
||||
model.items = exports.allowNullableTypes(model.items);
|
||||
}
|
||||
else {
|
||||
model.items = exports.allowNullType(model.items);
|
||||
|
@ -691,17 +690,17 @@ exports.allowNullableTypes = function allowNullableTypes(model) {
|
|||
}
|
||||
// if we have a top level "object" with x-nullable set, we need to relax the model at that level
|
||||
else if (model.type == "object" && model['x-nullable']) {
|
||||
model = exports.allowNullType(model)
|
||||
model = exports.allowNullType(model);
|
||||
}
|
||||
}
|
||||
|
||||
// if model is a parameter (contains "in" property") we want to relax the parameter
|
||||
if (model && model.in && model['x-nullable']) {
|
||||
model = exports.allowNullType(model, model["required"])
|
||||
model = exports.allowNullType(model, model["required"]);
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Relaxes/Transforms parameter definition to allow null values for non-path parameters
|
||||
|
@ -712,11 +711,11 @@ exports.allowNullableParams = function allowNullableParams(parameter) {
|
|||
}
|
||||
else {
|
||||
if (parameter["in"] && parameter["in"] !== "path") {
|
||||
parameter = exports.allowNullType(parameter, parameter["required"])
|
||||
parameter = exports.allowNullType(parameter, parameter["required"]);
|
||||
}
|
||||
}
|
||||
return parameter;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
@ -728,4 +727,29 @@ exports.allowNullableParams = function allowNullableParams(parameter) {
|
|||
exports.sanitizeFileName = function sanitizeFileName(str) {
|
||||
let result = str ? str.replace(/[{}\[\]'";\(\)#@~`!%&\^\$\+=,\/\\?<>\|\*:]/ig, '').replace(/(\s+)/ig, '_') : str;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the values of an object or returns an empty Array if the object is not defined.
|
||||
* The check is necessary because Object.values does not coerce parameters to object type.
|
||||
* @param {*} obj
|
||||
*/
|
||||
exports.getValues = function getValues(obj) {
|
||||
if (obj === undefined || obj === null) {
|
||||
return [];
|
||||
}
|
||||
return Object.values(obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the keys of an object or returns an empty Array if the object is not defined.
|
||||
.* The check is necessary because Object.keys does not coerce parameters to object type.
|
||||
* @param {*} obj
|
||||
*/
|
||||
exports.getKeys = function getKeys(obj) {
|
||||
if (obj === undefined || obj === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Object.keys(obj);
|
||||
};
|
|
@ -29,7 +29,7 @@ exports.serialize = function seralize() {
|
|||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
exports.constructErrors = function constructErrors(validationError, specPath, providerNamespace) {
|
||||
if (!validationError) {
|
||||
|
@ -69,13 +69,14 @@ exports.sanitizeWarnings = function sanitizeWarnings(warnings) {
|
|||
throw new Error('validationError cannot be null or undefined.');
|
||||
}
|
||||
let result = [];
|
||||
warnings.forEach(function(warning) {
|
||||
warnings.forEach(function (warning) {
|
||||
if (warning.code && warning.code !== 'EXTRA_REFERENCE_PROPERTIES' && warning.code !== 'UNUSED_DEFINITION') {
|
||||
result.push(warning);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
exports.mapper = {
|
||||
'SWAGGER_SCHEMA_VALIDATION_ERROR': 'M6000',
|
||||
'INVALID_PARAMETER_COMBINATION': 'M6001',
|
||||
|
@ -84,9 +85,7 @@ exports.mapper = {
|
|||
'DUPLICATE_OPERATIONID': 'M6004',
|
||||
'MISSING_PATH_PARAMETER_DEFINITION': 'M6005',
|
||||
'EMPTY_PATH_PARAMETER_DECLARATION': 'M6006',
|
||||
'MISSING_PATH_PARAMETER_DEFINITION': 'M6007',
|
||||
'EQUIVALENT_PATH': 'M6008',
|
||||
'DUPLICATE_PARAMETER': 'M6009',
|
||||
'UNRESOLVABLE_REFERENCE': 'M6010',
|
||||
'INVALID_TYPE': 'M6011',
|
||||
'CIRCULAR_INHERITANCE': 'M6012',
|
||||
|
|
|
@ -10,9 +10,7 @@ var fs = require('fs'),
|
|||
ResourceManagementClient = require('azure-arm-resource').ResourceManagementClient,
|
||||
log = require('./util/logging'),
|
||||
utils = require('./util/utils'),
|
||||
Constants = require('./util/constants'),
|
||||
path = require('path'),
|
||||
util = require('util'),
|
||||
SpecValidator = require('./validators/specValidator'),
|
||||
WireFormatGenerator = require('./wireFormatGenerator'),
|
||||
XMsExampleExtractor = require('./xMsExampleExtractor'),
|
||||
|
@ -93,7 +91,7 @@ exports.validateCompositeSpec = function validateCompositeSpec(compositeSpecPath
|
|||
options.consoleLogLevel = log.consoleLogLevel;
|
||||
options.logFilepath = log.filepath;
|
||||
let promiseFactories = docs.map(function (doc) {
|
||||
return function () { return exports.validateSpec(doc, options) };
|
||||
return function () { return exports.validateSpec(doc, options); };
|
||||
});
|
||||
return utils.executePromisesSequentially(promiseFactories);
|
||||
}).catch(function (err) {
|
||||
|
@ -128,7 +126,7 @@ exports.validateExamplesInCompositeSpec = function validateExamplesInCompositeSp
|
|||
options.consoleLogLevel = log.consoleLogLevel;
|
||||
options.logFilepath = log.filepath;
|
||||
let promiseFactories = docs.map(function (doc) {
|
||||
return function () { return exports.validateExamples(doc, options); }
|
||||
return function () { return exports.validateExamples(doc, options); };
|
||||
});
|
||||
return utils.executePromisesSequentially(promiseFactories);
|
||||
}).catch(function (err) {
|
||||
|
@ -153,7 +151,7 @@ exports.resolveSpec = function resolveSpec(specPath, outputDir, options) {
|
|||
}
|
||||
let outputFilepath = `${path.join(outputDir, specFileName)}`;
|
||||
fs.writeFileSync(`${path.join(outputDir, specFileName)}`, resolvedSwagger, { encoding: 'utf8' });
|
||||
console.log(`Saved the resolved spec at "${outputFilepath}".`)
|
||||
console.log(`Saved the resolved spec at "${outputFilepath}".`);
|
||||
return Promise.resolve();
|
||||
}).catch((err) => {
|
||||
log.error(err);
|
||||
|
@ -165,11 +163,11 @@ exports.resolveCompositeSpec = function resolveCompositeSpec(specPath, outputDir
|
|||
if (!options) options = {};
|
||||
log.consoleLogLevel = options.consoleLogLevel || log.consoleLogLevel;
|
||||
log.filepath = options.logFilepath || log.filepath;
|
||||
return exports.getDocumentsFromCompositeSwagger(compositeSpecPath).then(function (docs) {
|
||||
return exports.getDocumentsFromCompositeSwagger(specPath).then(function (docs) {
|
||||
options.consoleLogLevel = log.consoleLogLevel;
|
||||
options.logFilepath = log.filepath;
|
||||
let promiseFactories = docs.map(function (doc) {
|
||||
return function () { return exports.resolveSpec(doc, outputDir, options); }
|
||||
return function () { return exports.resolveSpec(doc, outputDir, options); };
|
||||
});
|
||||
return utils.executePromisesSequentially(promiseFactories);
|
||||
}).catch(function (err) {
|
||||
|
@ -202,7 +200,7 @@ exports.generateWireFormatInCompositeSpec = function generateWireFormatInComposi
|
|||
options.consoleLogLevel = log.consoleLogLevel;
|
||||
options.logFilepath = log.filepath;
|
||||
let promiseFactories = docs.map(function (doc) {
|
||||
return function () { return exports.generateWireFormat(doc, outDir, emitYaml, null, options); }
|
||||
return function () { return exports.generateWireFormat(doc, outDir, emitYaml, null, options); };
|
||||
});
|
||||
return utils.executePromisesSequentially(promiseFactories);
|
||||
}).catch(function (err) {
|
||||
|
|
|
@ -183,7 +183,7 @@ class LiveValidator {
|
|||
log.debug(`Unable to initialize "${swaggerPath}" file from SpecValidator. Error: ${err}`);
|
||||
log.warn(`Unable to initialize "${swaggerPath}" file from SpecValidator. We are ignoring this swagger file and continuing to build cache for other valid specs.`);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return utils.executePromisesSequentially(promiseFactories).then(() => {
|
||||
|
@ -427,7 +427,7 @@ class LiveValidator {
|
|||
log.debug(reqResult);
|
||||
} catch (reqValidationError) {
|
||||
let msg = `An error occurred while validating the live request for operation "${operation.operationId}". ` +
|
||||
`The error is:\n ${util.inspect(requestValidationError, { depth: null })}`;
|
||||
`The error is:\n ${util.inspect(reqValidationError, { depth: null })}`;
|
||||
let err = new models.LiveValidationError(Constants.ErrorCodes.RequestValidationError.name, msg);
|
||||
validationResult.requestValidationResult.errors = [err];
|
||||
}
|
||||
|
@ -439,7 +439,7 @@ class LiveValidator {
|
|||
log.debug(resResult);
|
||||
} catch (resValidationError) {
|
||||
let msg = `An error occurred while validating the live response for operation "${operation.operationId}". ` +
|
||||
`The error is:\n ${util.inspect(responseValidationError, { depth: null })}`;
|
||||
`The error is:\n ${util.inspect(resValidationError, { depth: null })}`;
|
||||
let err = new models.LiveValidationError(Constants.ErrorCodes.ResponseValidationError.name, msg);
|
||||
validationResult.responseValidationResult.errors = [err];
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
var util = require('util'),
|
||||
_ = require('lodash'),
|
||||
var _ = require('lodash'),
|
||||
path = require('path'),
|
||||
JsonRefs = require('json-refs'),
|
||||
utils = require('../util/utils'),
|
||||
|
@ -15,8 +14,8 @@ var util = require('util'),
|
|||
|
||||
/**
|
||||
* @class
|
||||
* Resolves the swagger spec by unifying x-ms-paths, resolving relative file references if any,
|
||||
* resolving the allof is present in any model definition and then setting additionalProperties
|
||||
* Resolves the swagger spec by unifying x-ms-paths, resolving relative file references if any,
|
||||
* resolving the allof is present in any model definition and then setting additionalProperties
|
||||
* to false if it is not previously set to true or an object in that definition.
|
||||
*/
|
||||
class SpecResolver {
|
||||
|
@ -24,39 +23,39 @@ class SpecResolver {
|
|||
/**
|
||||
* @constructor
|
||||
* Initializes a new instance of the SpecResolver class.
|
||||
*
|
||||
*
|
||||
* @param {string} specPath the (remote|local) swagger spec path
|
||||
*
|
||||
*
|
||||
* @param {object} specInJson the parsed spec in json format
|
||||
*
|
||||
*
|
||||
* @param {object} [options] The options object
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldResolveRelativePaths] Should relative pathes be resolved? Default: true
|
||||
*
|
||||
* @param {object} [options.shouldResolveXmsExamples] Should x-ms-examples be resolved? Default: true.
|
||||
*
|
||||
* @param {object} [options.shouldResolveXmsExamples] Should x-ms-examples be resolved? Default: true.
|
||||
* If options.shouldResolveRelativePaths is false then this option will also be false implicitly and cannot be overridden.
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldResolveAllOf] Should allOf references be resolved? Default: true
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldResolveDiscriminator] Should discriminator be resolved? Default: true
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldSetAdditionalPropertiesFalse] Should additionalProperties be set to false? Default: true
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldResolvePureObjects] Should pure objects be resolved? Default: true
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldResolveParameterizedHost] Should x-ms-parameterized-host be resolved? Default: true
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldResolveNullableTypes] Should we allow null values to match any type? Default: true
|
||||
*
|
||||
*
|
||||
* @return {object} An instance of the SpecResolver class.
|
||||
*/
|
||||
constructor(specPath, specInJson, options) {
|
||||
if (specPath === null || specPath === undefined || typeof specPath.valueOf() !== 'string' || !specPath.trim().length) {
|
||||
throw new Error('specPath is a required property of type string and it cannot be an empty string.')
|
||||
throw new Error('specPath is a required property of type string and it cannot be an empty string.');
|
||||
}
|
||||
|
||||
if (specInJson === null || specInJson === undefined || typeof specInJson !== 'object') {
|
||||
throw new Error('specInJson is a required property of type object')
|
||||
throw new Error('specInJson is a required property of type object');
|
||||
}
|
||||
this.specInJson = specInJson;
|
||||
this.specPath = specPath;
|
||||
|
@ -98,7 +97,7 @@ class SpecResolver {
|
|||
}
|
||||
|
||||
/**
|
||||
* Merges the x-ms-paths object into the paths object in swagger spec. The method assumes that the
|
||||
* Merges the x-ms-paths object into the paths object in swagger spec. The method assumes that the
|
||||
* paths present in "x-ms-paths" and "paths" are unique. Hence it does a simple union.
|
||||
*/
|
||||
unifyXmsPaths() {
|
||||
|
@ -106,8 +105,8 @@ class SpecResolver {
|
|||
//unify x-ms-paths into paths
|
||||
let xmsPaths = self.specInJson['x-ms-paths'];
|
||||
let paths = self.specInJson.paths;
|
||||
if (xmsPaths && xmsPaths instanceof Object && Object.keys(xmsPaths).length > 0) {
|
||||
for (let property in xmsPaths) {
|
||||
if (xmsPaths && xmsPaths instanceof Object && utils.getKeys(xmsPaths).length > 0) {
|
||||
for (const property of utils.getKeys(xmsPaths)) {
|
||||
paths[property] = xmsPaths[property];
|
||||
}
|
||||
self.specInJson.paths = utils.mergeObjects(xmsPaths, paths);
|
||||
|
@ -116,8 +115,8 @@ class SpecResolver {
|
|||
}
|
||||
|
||||
/**
|
||||
* Resolves the swagger spec by unifying x-ms-paths, resolving relative file references if any,
|
||||
* resolving the allof is present in any model definition and then setting additionalProperties
|
||||
* Resolves the swagger spec by unifying x-ms-paths, resolving relative file references if any,
|
||||
* resolving the allof is present in any model definition and then setting additionalProperties
|
||||
* to false if it is not previously set to true or an object in that definition.
|
||||
*/
|
||||
resolve() {
|
||||
|
@ -184,14 +183,14 @@ class SpecResolver {
|
|||
|
||||
/**
|
||||
* Resolves the references to relative paths in the provided object.
|
||||
*
|
||||
*
|
||||
* @param {object} [doc] the json doc that contains relative references. Default: self.specInJson (current swagger spec).
|
||||
*
|
||||
* @param {string} [docPath] the absolute (local|remote) path of the doc Default: self.specPath (current swagger spec path).
|
||||
*
|
||||
* @param {string} [filterType] the type of paths to filter. By default the method will resolve 'relative' and 'remote' references.
|
||||
*
|
||||
* @param {string} [docPath] the absolute (local|remote) path of the doc Default: self.specPath (current swagger spec path).
|
||||
*
|
||||
* @param {string} [filterType] the type of paths to filter. By default the method will resolve 'relative' and 'remote' references.
|
||||
* If provided the value should be 'all'. This indicates that 'local' references should also be resolved apart from the default ones.
|
||||
*
|
||||
*
|
||||
* @return {object} doc fully resolved json document
|
||||
*/
|
||||
resolveRelativePaths(doc, docPath, filterType) {
|
||||
|
@ -217,7 +216,7 @@ class SpecResolver {
|
|||
}
|
||||
|
||||
let allRefsRemoteRelative = JsonRefs.findRefs(doc, options);
|
||||
let promiseFactories = Object.keys(allRefsRemoteRelative).map(function (refName) {
|
||||
let promiseFactories = utils.getKeys(allRefsRemoteRelative).map(function (refName) {
|
||||
let refDetails = allRefsRemoteRelative[refName];
|
||||
return function () { return self.resolveRelativeReference(refName, refDetails, doc, docPath); };
|
||||
});
|
||||
|
@ -229,17 +228,17 @@ class SpecResolver {
|
|||
}
|
||||
|
||||
/**
|
||||
* Resolves the relative reference in the provided object. If the object to be resolved contains
|
||||
* Resolves the relative reference in the provided object. If the object to be resolved contains
|
||||
* more relative references then this method will call resolveRelativePaths
|
||||
*
|
||||
*
|
||||
* @param {string} refName the reference name/location that has a relative reference
|
||||
*
|
||||
*
|
||||
* @param {object} refDetails the value or the object that the refName points at
|
||||
*
|
||||
*
|
||||
* @param {object} doc the doc in which the refName exists
|
||||
*
|
||||
*
|
||||
* @param {string} docPath the absolute (local|remote) path of the doc
|
||||
*
|
||||
*
|
||||
* @return undefined the modified object
|
||||
*/
|
||||
resolveRelativeReference(refName, refDetails, doc, docPath) {
|
||||
|
@ -267,14 +266,14 @@ class SpecResolver {
|
|||
let docDir = path.dirname(docPath);
|
||||
|
||||
if (parsedReference.filePath) {
|
||||
//assuming that everything in the spec is relative to it, let us join the spec directory
|
||||
//assuming that everything in the spec is relative to it, let us join the spec directory
|
||||
//and the file path in reference.
|
||||
docPath = utils.joinPath(docDir, parsedReference.filePath);
|
||||
}
|
||||
|
||||
return utils.parseJson(docPath).then(function (result) {
|
||||
if (!parsedReference.localReference) {
|
||||
//Since there is no local reference we will replace the key in the object with the parsed
|
||||
//Since there is no local reference we will replace the key in the object with the parsed
|
||||
//json (relative) file it is refering to.
|
||||
let regex = /.*x-ms-examples.*/ig;
|
||||
if (self.options.shouldResolveXmsExamples || (!self.options.shouldResolveXmsExamples && slicedRefName.match(regex) === null)) {
|
||||
|
@ -289,7 +288,7 @@ class SpecResolver {
|
|||
let slicedLocalReferenceValue = parsedReference.localReference.value.slice(1);
|
||||
let referencedObj = self.visitedEntities[slicedLocalReferenceValue];
|
||||
if (!referencedObj) {
|
||||
//We get the definition/parameter from the relative file and then add it (make it local)
|
||||
//We get the definition/parameter from the relative file and then add it (make it local)
|
||||
//to the doc (i.e. self.specInJson) being processed.
|
||||
referencedObj = utils.getObject(result, slicedLocalReferenceValue);
|
||||
utils.setObject(self.specInJson, slicedLocalReferenceValue, referencedObj);
|
||||
|
@ -297,14 +296,14 @@ class SpecResolver {
|
|||
return self.resolveRelativePaths(referencedObj, docPath, 'all').then(() => {
|
||||
//After resolving a model definition, if there are models that have an allOf on that model definition
|
||||
//It may be possible that those models are not being referenced anywhere. Hence, we must ensure
|
||||
//that they are consumed as well. Example model "CopyActivity" in file
|
||||
//that they are consumed as well. Example model "CopyActivity" in file
|
||||
//arm-datafactory/2017-03-01-preview/swagger/entityTypes/Pipeline.json is having an allOf on model
|
||||
//"Activity". Spec "datafactory.json" has references to "Activity" in Pipeline.json but there are no
|
||||
//"Activity". Spec "datafactory.json" has references to "Activity" in Pipeline.json but there are no
|
||||
//references to "CopyActivity". The following code, ensures that we do not forget such models while
|
||||
//resolving relative swaggers.
|
||||
if (result && result.definitions) {
|
||||
let unresolvedDefinitions = [];
|
||||
for (let defName in result.definitions) {
|
||||
for (const defName of utils.getKeys(result.definitions)) {
|
||||
unresolvedDefinitions.push(() => {
|
||||
if (result.definitions[defName].allOf) {
|
||||
let matchFound = result.definitions[defName].allOf.some((item) => {
|
||||
|
@ -339,7 +338,7 @@ class SpecResolver {
|
|||
let self = this;
|
||||
let spec = self.specInJson;
|
||||
let definitions = spec.definitions;
|
||||
let modelNames = Object.keys(definitions);
|
||||
let modelNames = utils.getKeys(definitions);
|
||||
modelNames.map(function (modelName) {
|
||||
let model = definitions[modelName];
|
||||
let modelRef = '/definitions/' + modelName;
|
||||
|
@ -389,11 +388,11 @@ class SpecResolver {
|
|||
|
||||
/**
|
||||
* Merges the properties of the parent model into the child model.
|
||||
*
|
||||
*
|
||||
* @param {object} parent object to be merged. Example: "Resource".
|
||||
*
|
||||
*
|
||||
* @param {object} child object to be merged. Example: "Storage".
|
||||
*
|
||||
*
|
||||
* @return {object} returns the merged child oject
|
||||
*/
|
||||
mergeParentAllOfInChild(parent, child) {
|
||||
|
@ -404,7 +403,7 @@ class SpecResolver {
|
|||
if (!child || (child && typeof child !== 'object')) {
|
||||
throw new Error(`child must be of type "object".`);
|
||||
}
|
||||
//merge the parent (Resource) model's properties into the properties
|
||||
//merge the parent (Resource) model's properties into the properties
|
||||
//of the child (StorageAccount) model.
|
||||
if (!parent.properties) parent.properties = {};
|
||||
if (!child.properties) child.properties = {};
|
||||
|
@ -430,7 +429,7 @@ class SpecResolver {
|
|||
let self = this;
|
||||
let spec = self.specInJson;
|
||||
let definitions = spec.definitions;
|
||||
let modelNames = Object.keys(definitions);
|
||||
let modelNames = utils.getKeys(definitions);
|
||||
modelNames.map(function (modelName) {
|
||||
if (definitions[modelName].allOf) {
|
||||
delete definitions[modelName].allOf;
|
||||
|
@ -441,10 +440,10 @@ class SpecResolver {
|
|||
|
||||
/*
|
||||
* Sets additionalProperties of the given modelNames to false.
|
||||
*
|
||||
*
|
||||
* @param {array} [modelNames] An array of strings that specifies the modelNames to be processed.
|
||||
* Default: All the modelnames from the definitions section in the swagger spec.
|
||||
*
|
||||
*
|
||||
* @param {boolean} [force] A boolean value that indicates whether to ignore the additionalProperties
|
||||
* set to true or an object and forcefully set it to false. Default: false.
|
||||
*/
|
||||
|
@ -454,12 +453,12 @@ class SpecResolver {
|
|||
let definitions = spec.definitions;
|
||||
|
||||
if (!modelNames) {
|
||||
modelNames = Object.keys(definitions);
|
||||
modelNames = utils.getKeys(definitions);
|
||||
}
|
||||
modelNames.forEach(function iterator(modelName) {
|
||||
let model = definitions[modelName];
|
||||
if (model) {
|
||||
if (force || (!model.additionalProperties && (!(!model.properties || (model.properties && Object.keys(model.properties).length === 0))))) {
|
||||
if (force || (!model.additionalProperties && (!(!model.properties || (model.properties && utils.getKeys(model.properties).length === 0))))) {
|
||||
model.additionalProperties = false;
|
||||
}
|
||||
}
|
||||
|
@ -470,13 +469,13 @@ class SpecResolver {
|
|||
/**
|
||||
* Resolves the parameters provided in 'x-ms-parameterized-host'
|
||||
* extension by adding those parameters as local parameters to every operation.
|
||||
*
|
||||
*
|
||||
* ModelValidation:
|
||||
* This step should only be performed for model validation as we need to
|
||||
* make sure that the examples contain correct values for parameters
|
||||
* defined in 'x-ms-parameterized-host'.hostTemplate. Moreover, they are a
|
||||
* make sure that the examples contain correct values for parameters
|
||||
* defined in 'x-ms-parameterized-host'.hostTemplate. Moreover, they are a
|
||||
* part of the baseUrl.
|
||||
*
|
||||
*
|
||||
* SemanticValidation:
|
||||
* This step should not be performed for semantic validation, othwerise there will
|
||||
* be a mismatch between the number of path parameters provided in the operation
|
||||
|
@ -489,10 +488,8 @@ class SpecResolver {
|
|||
let hostParameters = parameterizedHost ? parameterizedHost.parameters : null;
|
||||
if (parameterizedHost && hostParameters) {
|
||||
let paths = spec.paths;
|
||||
for (let path in paths) {
|
||||
let verbs = paths[path];
|
||||
for (let verb in verbs) {
|
||||
let operation = verbs[verb];
|
||||
for (let verbs of utils.getValues(paths)) {
|
||||
for (let operation of utils.getValues(verbs)) {
|
||||
let operationParameters = operation.parameters;
|
||||
if (!operationParameters) operationParameters = [];
|
||||
// merge host parameters into parameters for that operation.
|
||||
|
@ -506,7 +503,7 @@ class SpecResolver {
|
|||
|
||||
/**
|
||||
* Resolves entities (parameters, definitions, model properties, etc.) in the spec that are true ojects.
|
||||
* i.e `"type": "object"` and `"properties": {}` or `"properties"` is absent or the entity has
|
||||
* i.e `"type": "object"` and `"properties": {}` or `"properties"` is absent or the entity has
|
||||
* "additionalProperties": { "type": "object" }.
|
||||
*/
|
||||
resolvePureObjects() {
|
||||
|
@ -515,16 +512,13 @@ class SpecResolver {
|
|||
let definitions = spec.definitions;
|
||||
|
||||
//scan definitions and properties of every model in definitions
|
||||
for (let defName in definitions) {
|
||||
let model = definitions[defName];
|
||||
for (let model of utils.getValues(definitions)) {
|
||||
utils.relaxModelLikeEntities(model);
|
||||
}
|
||||
|
||||
//scan every operation
|
||||
for (let path in spec.paths) {
|
||||
let pathObj = spec.paths[path];
|
||||
for (let verb in pathObj) {
|
||||
let operation = pathObj[verb];
|
||||
for (let pathObj of utils.getValues(spec.paths)) {
|
||||
for (let operation of utils.getValues(pathObj)) {
|
||||
//scan every parameter in the operation
|
||||
let consumes = _.isUndefined(operation.consumes) ?
|
||||
_.isUndefined(spec.consumes) ?
|
||||
|
@ -555,8 +549,7 @@ class SpecResolver {
|
|||
}
|
||||
//scan every response in the operation
|
||||
if (operation.responses) {
|
||||
for (let statusCode in operation.responses) {
|
||||
let response = operation.responses[statusCode];
|
||||
for (let response of utils.getValues(operation.responses)) {
|
||||
if (response.schema && !octetStream(produces)) {
|
||||
response.schema = utils.relaxModelLikeEntities(response.schema);
|
||||
}
|
||||
|
@ -575,7 +568,7 @@ class SpecResolver {
|
|||
}
|
||||
}
|
||||
//scan global parameters
|
||||
for (let param in spec.parameters) {
|
||||
for (let param of utils.getKeys(spec.parameters)) {
|
||||
if (spec.parameters[param].in && spec.parameters[param].in === 'body' && spec.parameters[param].schema) {
|
||||
spec.parameters[param].schema = utils.relaxModelLikeEntities(spec.parameters[param].schema);
|
||||
}
|
||||
|
@ -593,7 +586,7 @@ class SpecResolver {
|
|||
* "Tiger" are children (having "allof": [ { "$ref": "#/definitions/Animal" } ] on) of "Animal" in the swagger spec.
|
||||
*
|
||||
* - This method will replace all the locations in the swagger spec that have a reference to the
|
||||
* parent model "Animal" ("$ref": "#/definitions/Animal") except the allOf reference with a oneOf reference
|
||||
* parent model "Animal" ("$ref": "#/definitions/Animal") except the allOf reference with a oneOf reference
|
||||
* "oneOf": [ { "$ref": "#/definitions/Animal" }, { "$ref": "#/definitions/Cat" }, { "$ref": "#/definitions/Dog" }, { "$ref": "#/definitions/Tiger" } ]
|
||||
*
|
||||
* - It will also add a constant value (name of that animal on the wire or the value provided by "x-ms-discriminator-value")
|
||||
|
@ -605,14 +598,13 @@ class SpecResolver {
|
|||
let self = this;
|
||||
let spec = self.specInJson;
|
||||
let definitions = spec.definitions;
|
||||
let modelNames = Object.keys(definitions);
|
||||
let modelNames = utils.getKeys(definitions);
|
||||
let subTreeMap = new Map();
|
||||
let references = JsonRefs.findRefs(spec);
|
||||
|
||||
modelNames.map((modelName) => {
|
||||
if (definitions[modelName].discriminator) {
|
||||
let modelReference = `#/definitions/${modelName}`;
|
||||
let rootNode = subTreeMap.get(modelName)
|
||||
let rootNode = subTreeMap.get(modelName);
|
||||
if (!rootNode) {
|
||||
rootNode = self.createPolymorphicTree(modelName, definitions[modelName].discriminator, subTreeMap);
|
||||
}
|
||||
|
@ -626,42 +618,37 @@ class SpecResolver {
|
|||
/**
|
||||
* Resolves all properties in models or responses that have a "type" defined, so that if the property
|
||||
* is marked with "x-nullable", we'd honor it: we'd relax the type to include "null" if value is true, we won't if value is false.
|
||||
* If the property does not have the "x-nullable" extension, then if not required, we'll relax the type to include "null"; if required we won't.
|
||||
* If the property does not have the "x-nullable" extension, then if not required, we'll relax the type to include "null"; if required we won't.
|
||||
* The way we're relaxing the type is to have the model be a "oneOf" array with one value being the original content of the model and the second value "type": "null".
|
||||
*/
|
||||
resolveNullableTypes() {
|
||||
let self = this;
|
||||
let spec = self.specInJson;
|
||||
let definitions = spec.definitions;
|
||||
let modelNames = Object.keys(definitions);
|
||||
let references = JsonRefs.findRefs(spec);
|
||||
|
||||
//scan definitions and properties of every model in definitions
|
||||
for (let defName in definitions) {
|
||||
for (let defName of utils.getKeys(definitions)) {
|
||||
let model = definitions[defName];
|
||||
definitions[defName] = utils.allowNullableTypes(model);
|
||||
}
|
||||
//scan every operation response
|
||||
for (let path in spec.paths) {
|
||||
let pathObj = spec.paths[path];
|
||||
for (let pathObj of utils.getValues(spec.paths)) {
|
||||
//need to handle paramaters at this level
|
||||
if (pathObj.parameters) {
|
||||
for (let parameter in pathObj.parameters) {
|
||||
for (let parameter of utils.getValues(pathObj.parameters)) {
|
||||
pathObj.parameters[parameter] = utils.allowNullableParams(pathObj.parameters[parameter]);
|
||||
}
|
||||
}
|
||||
for (let verb in pathObj) {
|
||||
let operation = pathObj[verb];
|
||||
for (let operation of utils.getValues(pathObj)) {
|
||||
// need to account for parameters, except for path parameters
|
||||
if (operation.parameters) {
|
||||
for (let parameter in operation.parameters) {
|
||||
for (let parameter of utils.getKeys(operation.parameters)) {
|
||||
operation.parameters[parameter] = utils.allowNullableParams(operation.parameters[parameter]);
|
||||
}
|
||||
}
|
||||
// going through responses
|
||||
if (operation.responses) {
|
||||
for (let statusCode in operation.responses) {
|
||||
let response = operation.responses[statusCode];
|
||||
for (let response of utils.getValues(operation.responses)) {
|
||||
if (response.schema) {
|
||||
response.schema = utils.allowNullableTypes(response.schema);
|
||||
}
|
||||
|
@ -671,7 +658,7 @@ class SpecResolver {
|
|||
}
|
||||
|
||||
// scan parameter definitions
|
||||
for (let parameter in spec.parameters) {
|
||||
for (let parameter of utils.getKeys(spec.parameters)) {
|
||||
spec.parameters[parameter] = utils.allowNullableParams(spec.parameters[parameter]);
|
||||
}
|
||||
|
||||
|
@ -680,15 +667,14 @@ class SpecResolver {
|
|||
|
||||
/**
|
||||
* Updates the reference to a parent node with a oneOf array containing a reference to the parent and all its children.
|
||||
*
|
||||
*
|
||||
* @param {Map<string, PolymorphicTree>} subTreeMap - A map containing a reference to a node in the PolymorhicTree.
|
||||
* @param {object} references - This object is the output of findRefs function from "json-refs" library. Please refer
|
||||
* @param {object} references - This object is the output of findRefs function from "json-refs" library. Please refer
|
||||
* to the documentation of json-refs over [here](https://github.com/whitlockjc/json-refs/blob/master/docs/API.md#jsonrefsunresolvedrefdetails--object)
|
||||
* for detailed structure of the object.
|
||||
*/
|
||||
updateReferencesWithOneOf(subTreeMap, references) {
|
||||
let spec = this.specInJson;
|
||||
let definitions = spec.definitions;
|
||||
|
||||
for (const node of subTreeMap.values()) {
|
||||
// Have to process all the non-leaf nodes only
|
||||
|
@ -725,15 +711,15 @@ class SpecResolver {
|
|||
*/
|
||||
createPolymorphicTree(name, discriminator, subTreeMap) {
|
||||
if (name === null || name === undefined || typeof name.valueOf() !== 'string' || !name.trim().length) {
|
||||
throw new Error('name is a required property of type string and it cannot be an empty string.')
|
||||
throw new Error('name is a required property of type string and it cannot be an empty string.');
|
||||
}
|
||||
|
||||
if (discriminator === null || discriminator === undefined || typeof discriminator.valueOf() !== 'string' || !discriminator.trim().length) {
|
||||
throw new Error('discriminator is a required property of type string and it cannot be an empty string.')
|
||||
throw new Error('discriminator is a required property of type string and it cannot be an empty string.');
|
||||
}
|
||||
|
||||
if (subTreeMap === null || subTreeMap === undefined || !(subTreeMap instanceof Map)) {
|
||||
throw new Error('subTreeMap is a required property of type Map.')
|
||||
throw new Error('subTreeMap is a required property of type Map.');
|
||||
}
|
||||
|
||||
let rootNode = new PolymorphicTree(name);
|
||||
|
@ -745,7 +731,7 @@ class SpecResolver {
|
|||
if (definitions[name]['x-ms-discriminator-value']) {
|
||||
val = definitions[name]['x-ms-discriminator-value'];
|
||||
}
|
||||
// Ensure that the property marked as a discriminator has only one value in the enum constraint for that model and it
|
||||
// Ensure that the property marked as a discriminator has only one value in the enum constraint for that model and it
|
||||
// should be the one that is the model name or the value indicated by x-ms-discriminator-value. This will make the discriminator
|
||||
// property a constant (in json schema terms).
|
||||
if (definitions[name].properties[discriminator]['$ref']) {
|
||||
|
@ -753,7 +739,7 @@ class SpecResolver {
|
|||
}
|
||||
// We will set "type" to "string". It is safe to assume that properties marked as "discriminator" will be of type "string"
|
||||
// as it needs to refer to a model definition name. Model name would be a key in the definitions object/dictionary in the
|
||||
// swagger spec. keys would always be a string in a JSON object/dictionary.
|
||||
// swagger spec. keys would always be a string in a JSON object/dictionary.
|
||||
if (!definitions[name].properties[discriminator].type) {
|
||||
definitions[name].properties[discriminator].type = 'string';
|
||||
}
|
||||
|
@ -778,12 +764,12 @@ class SpecResolver {
|
|||
*/
|
||||
findChildren(name) {
|
||||
if (name === null || name === undefined || typeof name.valueOf() !== 'string' || !name.trim().length) {
|
||||
throw new Error('name is a required property of type string and it cannot be an empty string.')
|
||||
throw new Error('name is a required property of type string and it cannot be an empty string.');
|
||||
}
|
||||
let definitions = this.specInJson.definitions;
|
||||
let reference = `#/definitions/${name}`;
|
||||
let result = new Set();
|
||||
for (let definitionName of Object.keys(definitions)) {
|
||||
for (let definitionName of utils.getKeys(definitions)) {
|
||||
let definition = definitions[definitionName];
|
||||
if (definition && definition.allOf) {
|
||||
definition.allOf.forEach((item) => {
|
||||
|
@ -830,11 +816,11 @@ class PolymorphicTree {
|
|||
*/
|
||||
constructor(name, children) {
|
||||
if (name === null || name === undefined || typeof name.valueOf() !== 'string' || !name.trim().length) {
|
||||
throw new Error('name is a required property of type string and it cannot be an empty string.')
|
||||
throw new Error('name is a required property of type string and it cannot be an empty string.');
|
||||
}
|
||||
|
||||
if (children !== null && children !== undefined && !children instanceof Map) {
|
||||
throw new Error('children is an optional property of type Map<string, PolymorphicTree>.')
|
||||
if (children !== null && children !== undefined && !(children instanceof Map)) {
|
||||
throw new Error('children is an optional property of type Map<string, PolymorphicTree>.');
|
||||
}
|
||||
this.name = name;
|
||||
this.children = children || new Map();
|
||||
|
@ -848,7 +834,7 @@ class PolymorphicTree {
|
|||
*/
|
||||
addChildByName(childName) {
|
||||
if (childName === null || childName === undefined || typeof childName.valueOf() === 'string' || !childName.trim().length) {
|
||||
throw new Error('childName is a required parameter of type string.')
|
||||
throw new Error('childName is a required parameter of type string.');
|
||||
}
|
||||
let child;
|
||||
if (!this.children.has(childName)) {
|
||||
|
@ -868,7 +854,7 @@ class PolymorphicTree {
|
|||
*/
|
||||
addChildByObject(childObj) {
|
||||
if (childObj === null || childObj === undefined || !(childObj instanceof PolymorphicTree)) {
|
||||
throw new Error('childObj is a required parameter of type PolymorphicTree.')
|
||||
throw new Error('childObj is a required parameter of type PolymorphicTree.');
|
||||
}
|
||||
|
||||
if (!this.children.has(childObj.name)) {
|
||||
|
|
|
@ -19,40 +19,40 @@ var util = require('util'),
|
|||
|
||||
/*
|
||||
* @class
|
||||
* Performs sematic and data validation of the given swagger spec.
|
||||
* Performs semantic and data validation of the given swagger spec.
|
||||
*/
|
||||
class SpecValidator {
|
||||
|
||||
/*
|
||||
* @constructor
|
||||
* Initializes a new instance of the SpecValidator class.
|
||||
*
|
||||
*
|
||||
* @param {string} specPath the (remote|local) swagger spec path
|
||||
*
|
||||
*
|
||||
* @param {object} [specInJson] the parsed spec in json format
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldResolveRelativePaths] Should relative pathes be resolved? Default: true
|
||||
*
|
||||
* @param {object} [options.shouldResolveXmsExamples] Should x-ms-examples be resolved? Default: true.
|
||||
*
|
||||
* @param {object} [options.shouldResolveXmsExamples] Should x-ms-examples be resolved? Default: true.
|
||||
* If options.shouldResolveRelativePaths is false then this option will also be false implicitly and cannot be overridden.
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldResolveAllOf] Should allOf references be resolved? Default: true
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldResolveDiscriminator] Should discriminator be resolved? Default: true
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldSetAdditionalPropertiesFalse] Should additionalProperties be set to false? Default: true
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldResolvePureObjects] Should pure objects be resolved? Default: true
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldResolveParameterizedHost] Should 'x-ms-parameterized-host' be resolved? Default: true
|
||||
*
|
||||
*
|
||||
* @param {object} [options.shouldResolveNullableTypes] Should we allow null values to match any type? Default: true
|
||||
*
|
||||
*
|
||||
* @return {object} An instance of the SpecValidator class.
|
||||
*/
|
||||
constructor(specPath, specInJson, options) {
|
||||
if (specPath === null || specPath === undefined || typeof specPath.valueOf() !== 'string' || !specPath.trim().length) {
|
||||
throw new Error('specPath is a required parameter of type string and it cannot be an empty string.')
|
||||
throw new Error('specPath is a required parameter of type string and it cannot be an empty string.');
|
||||
}
|
||||
//If the spec path is a url starting with https://github then let us auto convert it to an https://raw.githubusercontent url.
|
||||
if (specPath.startsWith('https://github')) {
|
||||
|
@ -129,7 +129,7 @@ class SpecValidator {
|
|||
let re = /^(.*)\/providers\/(\w+\.\w+)\/(.*)$/ig;
|
||||
if (this.specInJson) {
|
||||
if (this.specInJson.paths) {
|
||||
let paths = Object.keys(this.specInJson.paths);
|
||||
let paths = utils.getKeys(this.specInJson.paths);
|
||||
if (paths) {
|
||||
for (let i = 0; i < paths.length; i++) {
|
||||
let res = re.exec(paths[i]);
|
||||
|
@ -146,7 +146,7 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Updates the validityStatus of the internal specValidationResult based on the provided value.
|
||||
*
|
||||
*
|
||||
* @param {boolean} value A truthy or a falsy value.
|
||||
*/
|
||||
updateValidityStatus(value) {
|
||||
|
@ -160,15 +160,15 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Constructs the Error object and updates the validityStatus unless indicated to not update the status.
|
||||
*
|
||||
*
|
||||
* @param {string} code The Error code that uniquely idenitifies the error.
|
||||
*
|
||||
*
|
||||
* @param {string} message The message that provides more information about the error.
|
||||
*
|
||||
*
|
||||
* @param {array} [innerErrors] An array of Error objects that specify inner details.
|
||||
*
|
||||
*
|
||||
* @param {boolean} [skipValidityStatusUpdate] When specified a truthy value it will skip updating the validity status.
|
||||
*
|
||||
*
|
||||
* @return {object} err Return the constructed Error object.
|
||||
*/
|
||||
constructErrorObject(code, message, innerErrors, skipValidityStatusUpdate) {
|
||||
|
@ -176,7 +176,7 @@ class SpecValidator {
|
|||
code: code.name,
|
||||
id: code.id,
|
||||
message: message,
|
||||
}
|
||||
};
|
||||
if (innerErrors) {
|
||||
err.innerErrors = innerErrors;
|
||||
}
|
||||
|
@ -191,10 +191,10 @@ class SpecValidator {
|
|||
self.specValidationResult.validateSpec = {};
|
||||
self.specValidationResult.validateSpec.isValid = true;
|
||||
self.specValidationResult.validateSpec.errors = [];
|
||||
self.specValidationResult.validateSpec.warnings = []
|
||||
self.specValidationResult.validateSpec.warnings = [];
|
||||
if (!self.swaggerApi) {
|
||||
let msg = `Please call "specValidator.initialize()" before calling this method, so that swaggerApi is populated.`;
|
||||
let e = self.constructErrorObject(ErrorCodes.InitializationError, msg)
|
||||
let e = self.constructErrorObject(ErrorCodes.InitializationError, msg);
|
||||
self.specValidationResult.initialize = e;
|
||||
self.specValidationResult.validateSpec.isValid = false;
|
||||
log.error(`${ErrorCodes.InitializationError.name}: ${msg}`);
|
||||
|
@ -212,7 +212,7 @@ class SpecValidator {
|
|||
self.updateValidityStatus();
|
||||
log.error(e);
|
||||
} else {
|
||||
self.specValidationResult.validateSpec.result = `The spec ${self.specPath} is sematically valid.`
|
||||
self.specValidationResult.validateSpec.result = `The spec ${self.specPath} is sematically valid.`;
|
||||
}
|
||||
if (validationResult.warnings && validationResult.warnings.length > 0) {
|
||||
let warnings = ValidationResponse.sanitizeWarnings(validationResult.warnings);
|
||||
|
@ -240,9 +240,9 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Gets the operation object by operationId specified in the swagger spec.
|
||||
*
|
||||
*
|
||||
* @param {string} id - The operation id.
|
||||
*
|
||||
*
|
||||
* @return {object} operation - The operation object.
|
||||
*/
|
||||
getOperationById(id) {
|
||||
|
@ -261,9 +261,9 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Gets the x-ms-examples object for an operation if specified in the swagger spec.
|
||||
*
|
||||
*
|
||||
* @param {string|object} idOrObj - The operation id or the operation object.
|
||||
*
|
||||
*
|
||||
* @return {object} xmsExample - The xmsExample object.
|
||||
*/
|
||||
getXmsExamples(idOrObj) {
|
||||
|
@ -272,7 +272,7 @@ class SpecValidator {
|
|||
}
|
||||
let operation = {};
|
||||
if (typeof idOrObj.valueOf() === 'string') {
|
||||
operation = self.getOperationById(id);
|
||||
operation = this.getOperationById(idOrObj);
|
||||
} else {
|
||||
operation = idOrObj;
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ class SpecValidator {
|
|||
}
|
||||
if (exampleType === Constants.exampleInSpec) {
|
||||
if (!operationResult[exampleType] ||
|
||||
(operationResult[exampleType] && !Object.keys(operationResult[exampleType]).length)) {
|
||||
(operationResult[exampleType] && !utils.getKeys(operationResult[exampleType]).length)) {
|
||||
operationResult[exampleType] = initialResult;
|
||||
}
|
||||
}
|
||||
|
@ -405,14 +405,14 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Cosntructs the validation result for an operation.
|
||||
*
|
||||
*
|
||||
* @param {object} operation - The operation object.
|
||||
*
|
||||
* @param {object} result - The validation result that needs to be added to the uber
|
||||
*
|
||||
* @param {object} result - The validation result that needs to be added to the uber
|
||||
* validationResult object for the entire spec.
|
||||
*
|
||||
*
|
||||
* @param {string} exampleType A string specifying the type of example. "x-ms-example", "example-in-spec".
|
||||
*
|
||||
*
|
||||
* @return {object} xmsExample - The xmsExample object.
|
||||
*/
|
||||
constructOperationResult(operation, result, exampleType) {
|
||||
|
@ -423,13 +423,13 @@ class SpecValidator {
|
|||
}
|
||||
if (exampleType === Constants.xmsExamples) {
|
||||
if (result.scenarios) {
|
||||
for (let scenario in result.scenarios) {
|
||||
for (let scenario of utils.getKeys(result.scenarios)) {
|
||||
//requestValidation
|
||||
let requestValidationErrors = result.scenarios[scenario].requestValidation.validationResult.errors;
|
||||
let requestValidationWarnings = result.scenarios[scenario].requestValidation.validationResult.warnings;
|
||||
this.constructRequestResultWrapper(operationId, requestValidationErrors, requestValidationWarnings, exampleType, scenario);
|
||||
//responseValidation
|
||||
for (let responseStatusCode in result.scenarios[scenario].responseValidation) {
|
||||
for (let responseStatusCode of utils.getKeys(result.scenarios[scenario].responseValidation)) {
|
||||
let responseValidationErrors = result.scenarios[scenario].responseValidation[responseStatusCode].errors;
|
||||
let responseValidationWarnings = result.scenarios[scenario].responseValidation[responseStatusCode].warnings;
|
||||
this.constructResponseResultWrapper(operationId, responseStatusCode, responseValidationErrors, responseValidationWarnings, exampleType, scenario);
|
||||
|
@ -437,15 +437,15 @@ class SpecValidator {
|
|||
}
|
||||
}
|
||||
} else if (exampleType === Constants.exampleInSpec) {
|
||||
if (result.requestValidation && Object.keys(result.requestValidation).length) {
|
||||
if (result.requestValidation && utils.getKeys(result.requestValidation).length) {
|
||||
//requestValidation
|
||||
let requestValidationErrors = result.requestValidation.validationResult.errors;
|
||||
let requestValidationWarnings = result.requestValidation.validationResult.warnings;
|
||||
this.constructRequestResultWrapper(operationId, requestValidationErrors, requestValidationWarnings, exampleType);
|
||||
}
|
||||
if (result.responseValidation && Object.keys(result.responseValidation).length) {
|
||||
if (result.responseValidation && utils.getKeys(result.responseValidation).length) {
|
||||
//responseValidation
|
||||
for (let responseStatusCode in result.responseValidation) {
|
||||
for (let responseStatusCode of utils.getKeys(result.responseValidation)) {
|
||||
let responseValidationErrors = result.responseValidation[responseStatusCode].errors;
|
||||
let responseValidationWarnings = result.responseValidation[responseStatusCode].warnings;
|
||||
this.constructResponseResultWrapper(operationId, responseStatusCode, responseValidationErrors, responseValidationWarnings, exampleType);
|
||||
|
@ -457,7 +457,7 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Validates the given operation.
|
||||
*
|
||||
*
|
||||
* @param {object} operation - The operation object.
|
||||
*/
|
||||
validateOperation(operation) {
|
||||
|
@ -468,8 +468,8 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Validates the given operationIds or all the operations in the spec.
|
||||
*
|
||||
* @param {string} [operationIds] - A comma sparated string specifying the operations to be validated.
|
||||
*
|
||||
* @param {string} [operationIds] - A comma sparated string specifying the operations to be validated.
|
||||
* If not specified then the entire spec is validated.
|
||||
*/
|
||||
validateOperations(operationIds) {
|
||||
|
@ -497,7 +497,7 @@ class SpecValidator {
|
|||
self.specValidationResult.operations[operation.operationId][Constants.xmsExamples] = {};
|
||||
self.specValidationResult.operations[operation.operationId][Constants.exampleInSpec] = {};
|
||||
self.validateOperation(operation);
|
||||
if (Object.keys(self.specValidationResult.operations[operation.operationId][Constants.exampleInSpec]).length === 0) {
|
||||
if (utils.getKeys(self.specValidationResult.operations[operation.operationId][Constants.exampleInSpec]).length === 0) {
|
||||
delete self.specValidationResult.operations[operation.operationId][Constants.exampleInSpec];
|
||||
}
|
||||
}
|
||||
|
@ -505,7 +505,7 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Validates the x-ms-examples object for an operation if specified in the swagger spec.
|
||||
*
|
||||
*
|
||||
* @param {object} operation - The operation object.
|
||||
*/
|
||||
validateXmsExamples(operation) {
|
||||
|
@ -517,7 +517,7 @@ class SpecValidator {
|
|||
let result = { scenarios: {} };
|
||||
let resultScenarios = result.scenarios;
|
||||
if (xmsExamples) {
|
||||
for (let scenario in xmsExamples) {
|
||||
for (let scenario of Object.keys(xmsExamples)) {
|
||||
let xmsExample = xmsExamples[scenario];
|
||||
resultScenarios[scenario] = {};
|
||||
resultScenarios[scenario].requestValidation = self.validateRequest(operation, xmsExample.parameters);
|
||||
|
@ -533,7 +533,7 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Validates the example provided in the spec for the given operation if specified in the spec.
|
||||
*
|
||||
*
|
||||
* @param {object} operation - The operation object.
|
||||
*/
|
||||
validateExample(operation) {
|
||||
|
@ -550,11 +550,11 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Validates the request for an operation.
|
||||
*
|
||||
*
|
||||
* @param {object} operation - The operation object.
|
||||
*
|
||||
*
|
||||
* @param {object} exampleParameterValues - The example parameter values.
|
||||
*
|
||||
*
|
||||
* @return {object} result - The validation result.
|
||||
*/
|
||||
validateRequest(operation, exampleParameterValues) {
|
||||
|
@ -706,7 +706,7 @@ class SpecValidator {
|
|||
validationResult['errors'] = [];
|
||||
if (!foundIssues) {
|
||||
try {
|
||||
request = new HttpRequest()
|
||||
request = new HttpRequest();
|
||||
request = request.prepare(options);
|
||||
// set formData in the way sway expects it.
|
||||
if (formDataFiles) {
|
||||
|
@ -730,11 +730,11 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Validates the response for an operation.
|
||||
*
|
||||
*
|
||||
* @param {object} operationOrResponse - The operation or the response object.
|
||||
*
|
||||
*
|
||||
* @param {object} responseWrapper - The example responseWrapper.
|
||||
*
|
||||
*
|
||||
* @return {object} result - The validation result.
|
||||
*/
|
||||
validateResponse(operationOrResponse, responseWrapper) {
|
||||
|
@ -752,9 +752,9 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Validates the example (request) for an operation if specified in the swagger spec.
|
||||
*
|
||||
*
|
||||
* @param {object} operation - The operation object.
|
||||
*
|
||||
*
|
||||
* @return {object} result - The validation result.
|
||||
*/
|
||||
validateExampleRequest(operation) {
|
||||
|
@ -764,7 +764,7 @@ class SpecValidator {
|
|||
}
|
||||
let parameters = operation.getParameters();
|
||||
//as per swagger specification https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#fixed-fields-13
|
||||
//example can only be provided in a schema and schema can only be provided for a body parameter. Hence, if the body
|
||||
//example can only be provided in a schema and schema can only be provided for a body parameter. Hence, if the body
|
||||
//parameter schema has an example, then we will populate sample values for other parameters and create a request object.
|
||||
//This request object will be used to validate the body parameter example. Otherwise, we will skip it.
|
||||
let bodyParam = parameters.find(function (item) {
|
||||
|
@ -790,11 +790,11 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Validates the responses given in x-ms-examples object for an operation.
|
||||
*
|
||||
*
|
||||
* @param {object} operation - The operation object.
|
||||
*
|
||||
*
|
||||
* @param {object} exampleResponseValue - The example response value.
|
||||
*
|
||||
*
|
||||
* @return {object} result - The validation result.
|
||||
*/
|
||||
validateXmsExampleResponses(operation, exampleResponseValue) {
|
||||
|
@ -847,7 +847,7 @@ class SpecValidator {
|
|||
let validationResult = self.validateResponse(operation, exampleResponse);
|
||||
result[exampleResponseStatusCode] = validationResult;
|
||||
}
|
||||
let responseWithoutXmsExamples = Object.keys(responsesInSwagger).filter(function (statusCode) {
|
||||
let responseWithoutXmsExamples = utils.getKeys(responsesInSwagger).filter(function (statusCode) {
|
||||
if (statusCode !== 'default') {
|
||||
//let intStatusCode = parseInt(statusCode);
|
||||
//if (!isNaN(intStatusCode) && intStatusCode < 400) {
|
||||
|
@ -870,9 +870,9 @@ class SpecValidator {
|
|||
|
||||
/*
|
||||
* Validates the example responses for a given operation.
|
||||
*
|
||||
*
|
||||
* @param {object} operation - The operation object.
|
||||
*
|
||||
*
|
||||
* @return {object} result - The validation result.
|
||||
*/
|
||||
validateExampleResponses(operation) {
|
||||
|
@ -885,7 +885,7 @@ class SpecValidator {
|
|||
for (let i = 0; i < responses.length; i++) {
|
||||
let response = responses[i];
|
||||
if (response.examples) {
|
||||
for (let mimeType in response.examples) {
|
||||
for (let mimeType of Object.keys(response.examples)) {
|
||||
let exampleResponseBody = response.examples[mimeType];
|
||||
let exampleResponseHeaders = { 'content-type': mimeType };
|
||||
let exampleResponse = new ResponseWrapper(response.statusCode, exampleResponseBody, exampleResponseHeaders);
|
||||
|
|
|
@ -22,7 +22,7 @@ const ErrorCodes = Constants.ErrorCodes;
|
|||
class WireFormatGenerator {
|
||||
constructor(specPath, specInJson, wireFormatDir, emitYaml) {
|
||||
if (specPath === null || specPath === undefined || typeof specPath.valueOf() !== 'string' || !specPath.trim().length) {
|
||||
throw new Error('specPath is a required parameter of type string and it cannot be an empty string.')
|
||||
throw new Error('specPath is a required parameter of type string and it cannot be an empty string.');
|
||||
}
|
||||
//If the spec path is a url starting with https://github then let us auto convert it to an https://raw.githubusercontent url.
|
||||
if (specPath.startsWith('https://github')) {
|
||||
|
@ -44,7 +44,7 @@ class WireFormatGenerator {
|
|||
this.swaggerApi = null;
|
||||
this.options = {
|
||||
shouldResolveRelativePaths: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
initialize() {
|
||||
|
@ -60,7 +60,7 @@ class WireFormatGenerator {
|
|||
shouldResolveAllOf: false,
|
||||
shouldSetAdditionalPropertiesFalse: false,
|
||||
shouldResolvePureObjects: false
|
||||
}
|
||||
};
|
||||
self.specResolver = new SpecResolver(self.specPath, self.specInJson, options);
|
||||
return self.specResolver.resolve();
|
||||
}).then(() => {
|
||||
|
@ -85,7 +85,7 @@ class WireFormatGenerator {
|
|||
|
||||
/*
|
||||
* Updates the validityStatus of the internal specValidationResult based on the provided value.
|
||||
*
|
||||
*
|
||||
* @param {boolean} value A truthy or a falsy value.
|
||||
*/
|
||||
updateValidityStatus(value) {
|
||||
|
@ -99,22 +99,22 @@ class WireFormatGenerator {
|
|||
|
||||
/*
|
||||
* Constructs the Error object and updates the validityStatus unless indicated to not update the status.
|
||||
*
|
||||
*
|
||||
* @param {string} code The Error code that uniquely idenitifies the error.
|
||||
*
|
||||
*
|
||||
* @param {string} message The message that provides more information about the error.
|
||||
*
|
||||
*
|
||||
* @param {array} [innerErrors] An array of Error objects that specify inner details.
|
||||
*
|
||||
*
|
||||
* @param {boolean} [skipValidityStatusUpdate] When specified a truthy value it will skip updating the validity status.
|
||||
*
|
||||
*
|
||||
* @return {object} err Return the constructed Error object.
|
||||
*/
|
||||
constructErrorObject(code, message, innerErrors, skipValidityStatusUpdate) {
|
||||
let err = {
|
||||
code: code,
|
||||
message: message,
|
||||
}
|
||||
};
|
||||
if (innerErrors) {
|
||||
err.innerErrors = innerErrors;
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ class WireFormatGenerator {
|
|||
};
|
||||
|
||||
let allRefsRemoteRelative = JsonRefs.findRefs(self.specInJson, options);
|
||||
let promiseFactories = Object.keys(allRefsRemoteRelative).map(function (refName) {
|
||||
let promiseFactories = utils.getKeys(allRefsRemoteRelative).map(function (refName) {
|
||||
let refDetails = allRefsRemoteRelative[refName];
|
||||
return function () { return self.resolveRelativeReference(refName, refDetails, self.specInJson, self.specPath); };
|
||||
});
|
||||
|
@ -168,14 +168,14 @@ class WireFormatGenerator {
|
|||
let docDir = path.dirname(docPath);
|
||||
|
||||
if (parsedReference.filePath) {
|
||||
//assuming that everything in the spec is relative to it, let us join the spec directory
|
||||
//assuming that everything in the spec is relative to it, let us join the spec directory
|
||||
//and the file path in reference.
|
||||
docPath = utils.joinPath(docDir, parsedReference.filePath);
|
||||
}
|
||||
|
||||
return utils.parseJson(docPath).then((result) => {
|
||||
if (!parsedReference.localReference) {
|
||||
//Since there is no local reference we will replace the key in the object with the parsed
|
||||
//Since there is no local reference we will replace the key in the object with the parsed
|
||||
//json (relative) file it is refering to.
|
||||
let regex = /.*x-ms-examples.*/ig;
|
||||
if (slicedRefName.match(regex) !== null) {
|
||||
|
@ -192,8 +192,8 @@ class WireFormatGenerator {
|
|||
|
||||
/*
|
||||
* Generates wireformat for the given operationIds or all the operations in the spec.
|
||||
*
|
||||
* @param {string} [operationIds] - A comma sparated string specifying the operations for
|
||||
*
|
||||
* @param {string} [operationIds] - A comma sparated string specifying the operations for
|
||||
* which the wire format needs to be generated. If not specified then the entire spec is processed.
|
||||
*/
|
||||
processOperations(operationIds) {
|
||||
|
@ -223,7 +223,7 @@ class WireFormatGenerator {
|
|||
|
||||
/*
|
||||
* Generates wireformat for the given operation.
|
||||
*
|
||||
*
|
||||
* @param {object} operation - The operation object.
|
||||
*/
|
||||
processOperation(operation) {
|
||||
|
@ -235,7 +235,7 @@ class WireFormatGenerator {
|
|||
|
||||
/*
|
||||
* Process the x-ms-examples object for an operation if specified in the swagger spec.
|
||||
*
|
||||
*
|
||||
* @param {object} operation - The operation object.
|
||||
*/
|
||||
processXmsExamples(operation) {
|
||||
|
@ -245,8 +245,8 @@ class WireFormatGenerator {
|
|||
}
|
||||
let xmsExamples = operation[Constants.xmsExamples];
|
||||
if (xmsExamples) {
|
||||
for (let scenario in xmsExamples) {
|
||||
//If we do not see the value property then we assume that the swagger spec had x-ms-examples references resolved.
|
||||
for (let scenario of utils.getKeys(xmsExamples)) {
|
||||
//If we do not see the value property then we assume that the swagger spec had x-ms-examples references resolved.
|
||||
//Then we do not need to access the value property. At the same time the file name for wire-format will be the sanitized scenario name.
|
||||
let xmsExample = xmsExamples[scenario].value || xmsExamples[scenario];
|
||||
let sampleRequest = self.processRequest(operation, xmsExample.parameters);
|
||||
|
@ -265,11 +265,11 @@ class WireFormatGenerator {
|
|||
|
||||
/*
|
||||
* Processes the request for an operation to generate in wire format.
|
||||
*
|
||||
*
|
||||
* @param {object} operation - The operation object.
|
||||
*
|
||||
*
|
||||
* @param {object} exampleParameterValues - The example parameter values.
|
||||
*
|
||||
*
|
||||
* @return {object} result - The validation result.
|
||||
*/
|
||||
processRequest(operation, exampleParameterValues) {
|
||||
|
@ -336,11 +336,11 @@ class WireFormatGenerator {
|
|||
|
||||
/*
|
||||
* Validates the responses given in x-ms-examples object for an operation.
|
||||
*
|
||||
*
|
||||
* @param {object} operation - The operation object.
|
||||
*
|
||||
*
|
||||
* @param {object} exampleResponseValue - The example response value.
|
||||
*
|
||||
*
|
||||
* @return {object} result - The validation result.
|
||||
*/
|
||||
processXmsExampleResponses(operation, exampleResponseValue) {
|
||||
|
@ -364,7 +364,7 @@ class WireFormatGenerator {
|
|||
result.standard = { finalResponse: undefined };
|
||||
}
|
||||
|
||||
for (let exampleResponseStatusCode in exampleResponseValue) {
|
||||
for (let exampleResponseStatusCode of utils.getKeys(exampleResponseValue)) {
|
||||
let response = operation.getResponse(exampleResponseStatusCode);
|
||||
if (response) {
|
||||
let exampleResponseHeaders = exampleResponseValue[exampleResponseStatusCode]['headers'] || {};
|
||||
|
|
|
@ -17,24 +17,24 @@ class xMsExampleExtractor {
|
|||
/**
|
||||
* @constructor
|
||||
* Initializes a new instance of the xMsExampleExtractor class.
|
||||
*
|
||||
*
|
||||
* @param {string} specPath the swagger spec path
|
||||
*
|
||||
*
|
||||
* @param {object} recordings the folder for recordings
|
||||
*
|
||||
*
|
||||
* @param {object} [options] The options object
|
||||
*
|
||||
*
|
||||
* @param {object} [options.matchApiVersion] Only generate examples if api-version matches. Default: false
|
||||
*
|
||||
*
|
||||
* @param {object} [options.output] Output folder for the generated examples.
|
||||
*/
|
||||
constructor(specPath, recordings, options) {
|
||||
if (specPath === null || specPath === undefined || typeof specPath.valueOf() !== 'string' || !specPath.trim().length) {
|
||||
throw new Error('specPath is a required property of type string and it cannot be an empty string.')
|
||||
throw new Error('specPath is a required property of type string and it cannot be an empty string.');
|
||||
}
|
||||
|
||||
if (recordings === null || recordings === undefined || typeof recordings.valueOf() !== 'string' || !recordings.trim().length) {
|
||||
throw new Error('recordings is a required property of type string and it cannot be an empty string.')
|
||||
throw new Error('recordings is a required property of type string and it cannot be an empty string.');
|
||||
}
|
||||
|
||||
this.specPath = specPath;
|
||||
|
@ -70,7 +70,7 @@ class xMsExampleExtractor {
|
|||
let outputExamples = self.options.output + "/examples/";
|
||||
let relativeExamplesPath = "../examples/";
|
||||
let specName = self.specPath.split("/");
|
||||
let outputSwagger = self.options.output + "/swagger/" + specName[specName.length - 1].split(".")[0] + ".json"
|
||||
let outputSwagger = self.options.output + "/swagger/" + specName[specName.length - 1].split(".")[0] + ".json";
|
||||
|
||||
var swaggerObject = require(self.specPath);
|
||||
var SwaggerParser = require('swagger-parser');
|
||||
|
@ -84,8 +84,7 @@ class xMsExampleExtractor {
|
|||
var example = {};
|
||||
|
||||
parser.parse(swaggerObject).then(function (api) {
|
||||
for (var recordingFile in recordingFiles) {
|
||||
let recordingFileName = recordingFiles[recordingFile];
|
||||
for (let recordingFileName of utils.getValues(recordingFiles)) {
|
||||
log.debug(`Processing recording file: ${recordingFileName}`);
|
||||
|
||||
try {
|
||||
|
@ -93,20 +92,19 @@ class xMsExampleExtractor {
|
|||
let paths = api.paths;
|
||||
let pathIndex = 0;
|
||||
var pathParams = {};
|
||||
for (var path in paths) {
|
||||
for (let path in paths) {
|
||||
pathIndex++;
|
||||
let searchResult = path.match(/\/{\w*\}/g);
|
||||
let pathParts = path.split('/');
|
||||
let pathToMatch = path;
|
||||
pathParams = {};
|
||||
for (var sr in searchResult) {
|
||||
let match = searchResult[sr];
|
||||
for (let match of utils.getValues(searchResult)) {
|
||||
let splitRegEx = /[{}]/;
|
||||
let pathParam = match.split(splitRegEx)[1];
|
||||
|
||||
for (var part in pathParts) {
|
||||
for (let part of utils.getKeys(pathParts)) {
|
||||
let pathPart = "/" + pathParts[part];
|
||||
if (pathPart.localeCompare(match) == 0) {
|
||||
if (pathPart.localeCompare(match) === 0) {
|
||||
pathParams[pathParam] = part;
|
||||
}
|
||||
}
|
||||
|
@ -119,12 +117,12 @@ class xMsExampleExtractor {
|
|||
var entries = recording.Entries;
|
||||
let entryIndex = 0;
|
||||
let queryParams = {};
|
||||
for (var entry in entries) {
|
||||
for (let entry of utils.getKeys(entries)) {
|
||||
entryIndex++;
|
||||
let recordingPath = JSON.stringify(entries[entry]["RequestUri"]);
|
||||
let recordingPathQueryParams = recordingPath.split('?')[1].slice(0, -1);
|
||||
let queryParamsArray = recordingPathQueryParams.split('&');
|
||||
for (var part in queryParamsArray) {
|
||||
for (let part of utils.getKeys(queryParamsArray)) {
|
||||
let queryParam = queryParamsArray[part].split('=');
|
||||
queryParams[queryParam[0]] = queryParam[1];
|
||||
}
|
||||
|
@ -134,12 +132,12 @@ class xMsExampleExtractor {
|
|||
recordingPath = recordingPath.replace(/\?.*/, '');
|
||||
let recordingPathParts = recordingPath.split('/');
|
||||
let match = recordingPath.match(newPathToMatch);
|
||||
if (match != null) {
|
||||
if (match !== null) {
|
||||
log.silly("path: " + path);
|
||||
log.silly("recording path: " + recordingPath);
|
||||
|
||||
var pathParamsValues = {};
|
||||
for (var p in pathParams) {
|
||||
for (let p of utils.getKeys(pathParams)) {
|
||||
let index = pathParams[p];
|
||||
pathParamsValues[p] = recordingPathParts[index];
|
||||
}
|
||||
|
@ -167,20 +165,20 @@ class xMsExampleExtractor {
|
|||
example["parameters"] = {};
|
||||
example["responses"] = {};
|
||||
let params = infoFromOperation["parameters"];
|
||||
for (var param in pathParamsValues) {
|
||||
for (let param of utils.getKeys(pathParamsValues)) {
|
||||
example['parameters'][param] = pathParamsValues[param];
|
||||
}
|
||||
for (var param in queryParams) {
|
||||
for (let param of utils.getKeys(queryParams)) {
|
||||
example['parameters'][param] = queryParams[param];
|
||||
}
|
||||
for (var param in infoFromOperation["parameters"]) {
|
||||
for (let param of utils.getKeys(infoFromOperation["parameters"])) {
|
||||
if (params[param]["in"] == "body") {
|
||||
let bodyParamName = params[param]["name"];
|
||||
let bodyParamValue = entries[entry]["RequestBody"];
|
||||
let bodyParamExample = {};
|
||||
bodyParamExample[bodyParamName] = bodyParamValue;
|
||||
|
||||
if (bodyParamValue != "") {
|
||||
if (bodyParamValue !== "") {
|
||||
example['parameters'][bodyParamName] = JSON.parse(bodyParamValue);
|
||||
}
|
||||
else {
|
||||
|
@ -193,7 +191,7 @@ class xMsExampleExtractor {
|
|||
let statusCodeFromRecording = entries[entry]["StatusCode"];
|
||||
let responseBody = entries[entry]["ResponseBody"];
|
||||
example['responses'][statusCodeFromRecording] = {};
|
||||
if (responseBody != "") {
|
||||
if (responseBody !== "") {
|
||||
example['responses'][statusCodeFromRecording]['body'] = JSON.parse(responseBody);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -2391,7 +2391,7 @@
|
|||
"tunnel": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.5.tgz",
|
||||
"integrity": "sha512-gj5sdqherx4VZKMcBA4vewER7zdK25Td+z1npBqpbDys4eJrLx+SlYjJvq1bDXs2irkuJM5pf8ktaEQVipkrbA=="
|
||||
"integrity": "sha1-0VMiVHSe02Yg/NEBCGVJWh+p0K4="
|
||||
},
|
||||
"tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
|
|
|
@ -51,8 +51,8 @@
|
|||
"oav": "./cli.js"
|
||||
},
|
||||
"scripts": {
|
||||
"jshint": "jshint index.js --reporter=jslint",
|
||||
"test": "npm -s run-script jshint && mocha -t 100000",
|
||||
"jshint": "jshint lib --reporter=jslint",
|
||||
"test": "mocha -t 100000",
|
||||
"start": "node ./lib/autorestPlugin/pluginHost.js"
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче