Fix bugs and warnings from linter

This commit is contained in:
Vlad Barosan 2018-01-26 16:54:11 -08:00
Родитель 4459e377b6
Коммит ff7d81279e
17 изменённых файлов: 344 добавлений и 338 удалений

Просмотреть файл

@ -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 {

2
package-lock.json сгенерированный
Просмотреть файл

@ -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"
}
}
}