Preparing oav to plugin to autorest and adding id to error codes for consistency and documentation
This commit is contained in:
Родитель
c7a21320d3
Коммит
c6192a24b5
|
@ -0,0 +1,204 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const vscode_jsonrpc_1 = require("vscode-jsonrpc");
|
||||
const linq = require('linq');
|
||||
const jsonPath = require('jsonpath');
|
||||
const yaml = require("./yaml.js");
|
||||
const utils = require("../util/utils");
|
||||
const validator = require("../validate");
|
||||
const log = require('../util/logging');
|
||||
const SpecValidator = require('../validators/specValidator')
|
||||
|
||||
const openAPIDocUrl = "https://github.com/Azure/oav";
|
||||
|
||||
exports = module.exports;
|
||||
|
||||
class OpenApiValidationExample {
|
||||
Process(sessionId, initiator) {
|
||||
return initiator.ListInputs(sessionId).then(function (swaggerFileNames) {
|
||||
const promises = [];
|
||||
for (const swaggerFileName of swaggerFileNames) {
|
||||
promises.push(
|
||||
initiator.ReadFile(sessionId, swaggerFileName).then(function (swaggerFile) {
|
||||
const swagger = yaml.Parse(swaggerFile);
|
||||
return exports.openApiValidationExample(swagger, swaggerFileName).then(function (exampleValidationResults) {
|
||||
for (const result of exampleValidationResults) {
|
||||
initiator.Message(sessionId, { 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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
OpenApiValidationExample.Name = "model-validator";
|
||||
|
||||
function FormattedOutput(channel, details, code, text, source) {
|
||||
this.channel = channel;
|
||||
this.details = details;
|
||||
this.code = code;
|
||||
this.text = text;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
exports.openApiValidationExample = function openApiValidationExample(swagger, swaggerFileName) {
|
||||
var formattedResult = [];
|
||||
let specVal = new SpecValidator("swagger.json", swagger, { "consoleLogLevel": "off" });
|
||||
//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) {
|
||||
const xmsExamplesNode = specValidationResult.operations[op]["x-ms-examples"];
|
||||
for (var scenario in xmsExamplesNode.scenarios) {
|
||||
// invalid? meaning that there's an issue found in the validation
|
||||
var scenarioItem = xmsExamplesNode.scenarios[scenario];
|
||||
if (scenarioItem.isValid === false) {
|
||||
// get path to x-ms-examples in swagger
|
||||
const xmsexPath = linq.from(jsonPath.nodes(swagger, `$.paths[*][?(@.operationId==='${op}')]["x-ms-examples"]`))
|
||||
.select(x => x.path)
|
||||
.firstOrDefault();
|
||||
if (!xmsexPath) {
|
||||
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, ["ExampleModelViolation"], "Model validator found issue (see details).", [{ document: swaggerFileName, Position: { path: xmsexPath } }])
|
||||
formattedResult.push(result);
|
||||
|
||||
// request
|
||||
const request = scenarioItem.request;
|
||||
if (request.isValid === false) {
|
||||
const error = request.error;
|
||||
const innerErrors = error.innerErrors;
|
||||
if (!innerErrors || !innerErrors.length) {
|
||||
throw new Error("Model Validator: Unexpected format.");
|
||||
}
|
||||
for (const innerError of innerErrors) {
|
||||
const path = ConvertIndicesFromStringToNumbers(innerError.path);
|
||||
//console.error(JSON.stringify(error, null, 2));
|
||||
result = new FormattedOutput("error", error, [error.code, error.id, "ExampleModelViolation"],
|
||||
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 } }]);
|
||||
formattedResult.push(result);
|
||||
}
|
||||
}
|
||||
|
||||
// responses
|
||||
for (var responseCode in scenarioItem.responses) {
|
||||
const response = scenarioItem.responses[responseCode];
|
||||
if (response.isValid === false) {
|
||||
const error = response.error;
|
||||
const innerErrors = error.innerErrors;
|
||||
if (!innerErrors || !innerErrors.length) {
|
||||
throw new Error("Model Validator: Unexpected format.");
|
||||
}
|
||||
for (const innerError of innerErrors) {
|
||||
//console.error(JSON.stringify(error, null, 2));
|
||||
result = new FormattedOutput("error", error, [error.code, error.id, "ExampleModelViolation"],
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return formattedResult;
|
||||
}).catch(function (err) {
|
||||
console.error(err);
|
||||
return Promise.reject(err);
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Path comes with indices as strings in "inner errors", so converting those to actual numbers for path to work.
|
||||
*/
|
||||
function ConvertIndicesFromStringToNumbers(path) {
|
||||
const result = path.slice();
|
||||
for (let i = 1; i < result.length; ++i) {
|
||||
const num = parseInt(result[i]);
|
||||
if (!isNaN(num) && result[i - 1] === "parameters") {
|
||||
result[i] = num;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class PluginHost {
|
||||
constructor(initiator) {
|
||||
this.initiator = initiator;
|
||||
}
|
||||
|
||||
GetPluginNames() {
|
||||
return [/*OpenApiValidationSemantic.Name, */ OpenApiValidationExample.Name];
|
||||
}
|
||||
|
||||
Process(pluginName, sessionId) {
|
||||
switch (pluginName) {
|
||||
// case OpenApiValidationSemantic.Name:
|
||||
// return new OpenApiValidationSemantic().Process(sessionId, this.initiator);
|
||||
case OpenApiValidationExample.Name:
|
||||
return new OpenApiValidationExample().Process(sessionId, this.initiator);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var IAutoRestPluginInitiator_Types;
|
||||
(function (IAutoRestPluginInitiator_Types) {
|
||||
IAutoRestPluginInitiator_Types.ReadFile = new vscode_jsonrpc_1.RequestType2("ReadFile");
|
||||
IAutoRestPluginInitiator_Types.GetValue = new vscode_jsonrpc_1.RequestType2("GetValue");
|
||||
IAutoRestPluginInitiator_Types.ListInputs = new vscode_jsonrpc_1.RequestType1("ListInputs");
|
||||
IAutoRestPluginInitiator_Types.WriteFile = new vscode_jsonrpc_1.NotificationType4("WriteFile");
|
||||
IAutoRestPluginInitiator_Types.Message = new vscode_jsonrpc_1.NotificationType4("Message");
|
||||
})(IAutoRestPluginInitiator_Types = exports.IAutoRestPluginInitiator_Types || (exports.IAutoRestPluginInitiator_Types = {}));
|
||||
|
||||
var IAutoRestPluginTarget_Types;
|
||||
(function (IAutoRestPluginTarget_Types) {
|
||||
IAutoRestPluginTarget_Types.GetPluginNames = new vscode_jsonrpc_1.RequestType0("GetPluginNames");
|
||||
IAutoRestPluginTarget_Types.Process = new vscode_jsonrpc_1.RequestType2("Process");
|
||||
})(IAutoRestPluginTarget_Types = exports.IAutoRestPluginTarget_Types || (exports.IAutoRestPluginTarget_Types = {}));
|
||||
|
||||
function main() {
|
||||
// connection setup
|
||||
const channel = vscode_jsonrpc_1.createMessageConnection(process.stdin, process.stdout, {
|
||||
error(message) { console.error(message); },
|
||||
info(message) { console.info(message); },
|
||||
log(message) { console.log(message); },
|
||||
warn(message) { console.warn(message); }
|
||||
});
|
||||
const initiator = {
|
||||
ReadFile(sessionId, filename) {
|
||||
return channel.sendRequest(IAutoRestPluginInitiator_Types.ReadFile, sessionId, filename);
|
||||
},
|
||||
GetValue(sessionId, key) {
|
||||
return channel.sendRequest(IAutoRestPluginInitiator_Types.GetValue, sessionId, key);
|
||||
},
|
||||
ListInputs(sessionId) {
|
||||
return channel.sendRequest(IAutoRestPluginInitiator_Types.ListInputs, sessionId);
|
||||
},
|
||||
WriteFile(sessionId, filename, content, sourceMap) {
|
||||
channel.sendNotification(IAutoRestPluginInitiator_Types.WriteFile, sessionId, filename, content, sourceMap);
|
||||
},
|
||||
Message(sessionId, message, path, sourceFile) {
|
||||
channel.sendNotification(IAutoRestPluginInitiator_Types.Message, sessionId, message, path, sourceFile);
|
||||
}
|
||||
};
|
||||
const target = new PluginHost(initiator);
|
||||
channel.onRequest(IAutoRestPluginTarget_Types.GetPluginNames, target.GetPluginNames.bind(target));
|
||||
channel.onRequest(IAutoRestPluginTarget_Types.Process, target.Process.bind(target));
|
||||
// activate
|
||||
channel.listen();
|
||||
}
|
||||
|
||||
main();
|
|
@ -0,0 +1,38 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
function NewEmptyObject() {
|
||||
let keys = [];
|
||||
return new Proxy({}, {
|
||||
get(target, key) {
|
||||
return target[key];
|
||||
},
|
||||
has(target, key) {
|
||||
return keys.indexOf(key) !== -1;
|
||||
},
|
||||
set(target, key, value) {
|
||||
if (keys.indexOf(key) === -1) {
|
||||
keys.push(key);
|
||||
}
|
||||
target[key] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty(target, key) {
|
||||
if (keys.indexOf(key) !== -1) {
|
||||
keys = keys.filter(x => x !== key);
|
||||
}
|
||||
delete target[key];
|
||||
return true;
|
||||
},
|
||||
ownKeys(target) {
|
||||
return keys;
|
||||
},
|
||||
enumerate(target) {
|
||||
return keys;
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.NewEmptyObject = NewEmptyObject;
|
|
@ -0,0 +1,177 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const yamlAst = require("yaml-ast-parser");
|
||||
const stable_object_1 = require("./stable-object");
|
||||
/**
|
||||
* reexport required elements
|
||||
*/
|
||||
var yaml_ast_parser_1 = require("yaml-ast-parser");
|
||||
exports.newScalar = yaml_ast_parser_1.newScalar;
|
||||
exports.Kind = yamlAst.Kind;
|
||||
exports.CreateYAMLMapping = yamlAst.newMapping;
|
||||
exports.CreateYAMLScalar = yamlAst.newScalar;
|
||||
/**
|
||||
* Parsing
|
||||
*/
|
||||
function ParseToAst(rawYaml) {
|
||||
return yamlAst.safeLoad(rawYaml, null);
|
||||
}
|
||||
exports.ParseToAst = ParseToAst;
|
||||
function* Descendants(yamlAstNode, currentPath = [], deferResolvingMappings = false) {
|
||||
const todos = [{ path: currentPath, node: yamlAstNode }];
|
||||
let todo;
|
||||
while (todo = todos.pop()) {
|
||||
// report self
|
||||
yield todo;
|
||||
// traverse
|
||||
if (todo.node) {
|
||||
switch (todo.node.kind) {
|
||||
case exports.Kind.MAPPING:
|
||||
{
|
||||
let astSub = todo.node;
|
||||
if (deferResolvingMappings) {
|
||||
todos.push({ node: astSub.value, path: todo.path });
|
||||
}
|
||||
else {
|
||||
todos.push({ node: astSub.value, path: todo.path.concat([astSub.key.value]) });
|
||||
}
|
||||
}
|
||||
break;
|
||||
case exports.Kind.MAP:
|
||||
if (deferResolvingMappings) {
|
||||
for (let mapping of todo.node.mappings) {
|
||||
todos.push({ node: mapping, path: todo.path.concat([mapping.key.value]) });
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let mapping of todo.node.mappings) {
|
||||
todos.push({ node: mapping, path: todo.path });
|
||||
}
|
||||
}
|
||||
break;
|
||||
case exports.Kind.SEQ:
|
||||
{
|
||||
let astSub = todo.node;
|
||||
for (let i = 0; i < astSub.items.length; ++i) {
|
||||
todos.push({ node: astSub.items[i], path: todo.path.concat([i]) });
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.Descendants = Descendants;
|
||||
function ResolveAnchorRef(yamlAstRoot, anchorRef) {
|
||||
for (let yamlAstNode of Descendants(yamlAstRoot)) {
|
||||
if (yamlAstNode.node.anchorId === anchorRef) {
|
||||
return yamlAstNode;
|
||||
}
|
||||
}
|
||||
throw new Error(`Anchor '${anchorRef}' not found`);
|
||||
}
|
||||
exports.ResolveAnchorRef = ResolveAnchorRef;
|
||||
/**
|
||||
* Populates yamlNode.valueFunc with a function that creates a *mutable* object (i.e. no caching of the reference or such)
|
||||
*/
|
||||
function ParseNodeInternal(yamlRootNode, yamlNode, onError) {
|
||||
if (yamlNode.errors.length > 0) {
|
||||
for (const error of yamlNode.errors) {
|
||||
onError(`Syntax error: ${error.reason}`, error.mark.position);
|
||||
}
|
||||
return yamlNode.valueFunc = () => null;
|
||||
}
|
||||
if (yamlNode.valueFunc) {
|
||||
return yamlNode.valueFunc;
|
||||
}
|
||||
switch (yamlNode.kind) {
|
||||
case exports.Kind.SCALAR: {
|
||||
const yamlNodeScalar = yamlNode;
|
||||
return yamlNode.valueFunc = yamlNodeScalar.valueObject !== undefined
|
||||
? () => yamlNodeScalar.valueObject
|
||||
: () => yamlNodeScalar.value;
|
||||
}
|
||||
case exports.Kind.MAPPING:
|
||||
onError("Syntax error: Encountered bare mapping.", yamlNode.startPosition);
|
||||
return yamlNode.valueFunc = () => null;
|
||||
case exports.Kind.MAP: {
|
||||
const yamlNodeMapping = yamlNode;
|
||||
return yamlNode.valueFunc = () => {
|
||||
const result = stable_object_1.NewEmptyObject();
|
||||
for (const mapping of yamlNodeMapping.mappings) {
|
||||
if (mapping.key.kind !== exports.Kind.SCALAR) {
|
||||
onError("Syntax error: Only scalar keys are allowed as mapping keys.", mapping.key.startPosition);
|
||||
}
|
||||
else if (mapping.value === null) {
|
||||
onError("Syntax error: No mapping value found.", mapping.key.endPosition);
|
||||
}
|
||||
else {
|
||||
result[mapping.key.value] = ParseNodeInternal(yamlRootNode, mapping.value, onError)();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
case exports.Kind.SEQ: {
|
||||
const yamlNodeSequence = yamlNode;
|
||||
return yamlNode.valueFunc = () => yamlNodeSequence.items.map(item => ParseNodeInternal(yamlRootNode, item, onError)());
|
||||
}
|
||||
case exports.Kind.ANCHOR_REF: {
|
||||
const yamlNodeRef = yamlNode;
|
||||
return ResolveAnchorRef(yamlRootNode, yamlNodeRef.referencesAnchor).node.valueFunc;
|
||||
}
|
||||
case exports.Kind.INCLUDE_REF:
|
||||
onError("Syntax error: INCLUDE_REF not implemented.", yamlNode.startPosition);
|
||||
return yamlNode.valueFunc = () => null;
|
||||
default:
|
||||
throw new Error("Unknown YAML node kind.");
|
||||
}
|
||||
}
|
||||
function ParseNode(yamlNode, onError = message => { throw new Error(message); }) {
|
||||
ParseNodeInternal(yamlNode, yamlNode, onError);
|
||||
return yamlNode.valueFunc();
|
||||
}
|
||||
exports.ParseNode = ParseNode;
|
||||
function CloneAst(ast) {
|
||||
if (ast.kind === exports.Kind.MAPPING) {
|
||||
const astMapping = ast;
|
||||
return exports.CreateYAMLMapping(CloneAst(astMapping.key), CloneAst(astMapping.value));
|
||||
}
|
||||
return ParseToAst(StringifyAst(ast));
|
||||
}
|
||||
exports.CloneAst = CloneAst;
|
||||
function StringifyAst(ast) {
|
||||
return FastStringify(ParseNode(ast));
|
||||
}
|
||||
exports.StringifyAst = StringifyAst;
|
||||
function Clone(object) {
|
||||
return Parse(FastStringify(object));
|
||||
}
|
||||
exports.Clone = Clone;
|
||||
function ToAst(object) {
|
||||
return ParseToAst(FastStringify(object));
|
||||
}
|
||||
exports.ToAst = ToAst;
|
||||
function Parse(rawYaml, onError = message => { throw new Error(message); }) {
|
||||
const node = ParseToAst(rawYaml);
|
||||
const result = ParseNode(node, onError);
|
||||
return result;
|
||||
}
|
||||
exports.Parse = Parse;
|
||||
function Stringify(object) {
|
||||
return "---\n" + yamlAst.safeDump(object, { skipInvalid: true });
|
||||
}
|
||||
exports.Stringify = Stringify;
|
||||
function FastStringify(obj) {
|
||||
try {
|
||||
return JSON.stringify(obj, null, 1);
|
||||
}
|
||||
catch (e) {
|
||||
return Stringify(obj);
|
||||
}
|
||||
}
|
||||
exports.FastStringify = FastStringify;
|
|
@ -12,35 +12,35 @@ var Constants = {
|
|||
Errors: 'Errors',
|
||||
Warnings: 'Warnings',
|
||||
ErrorCodes: {
|
||||
InternalError: 'INTERNAL_ERROR',
|
||||
InitializationError: 'INITIALIZATION_ERROR',
|
||||
ResolveSpecError: 'RESOLVE_SPEC_ERROR',
|
||||
RefNotFoundError: 'REF_NOTFOUND_ERROR',
|
||||
JsonParsingError: 'JSON_PARSING_ERROR',
|
||||
RequiredParameterExampleNotFound: 'REQUIRED_PARAMETER_EXAMPLE_NOT_FOUND',
|
||||
ErrorInPreparingRequest: 'ERROR_IN_PREPARING_REQUEST',
|
||||
XmsExampleNotFoundError: 'X-MS-EXAMPLE_NOTFOUND_ERROR',
|
||||
ResponseValidationError: 'RESPONSE_VALIDATION_ERROR',
|
||||
RequestValidationError: 'REQUEST_VALIDATION_ERROR',
|
||||
ResponseBodyValidationError: 'RESPONSE_BODY_VALIDATION_ERROR',
|
||||
ResponseStatusCodeNotInExample: 'RESPONSE_STATUS_CODE_NOT_IN_EXAMPLE',
|
||||
ResponseStatusCodeNotInSpec: 'RESPONSE_STATUS_CODE_NOT_IN_SPEC',
|
||||
ResponseSchemaNotInSpec: 'RESPONSE_SCHEMA_NOT_IN_SPEC',
|
||||
RequiredParameterNotInExampleError: 'REQUIRED_PARAMETER_NOT_IN_EXAMPLE_ERROR',
|
||||
BodyParameterValidationError: 'BODY_PARAMETER_VALIDATION_ERROR',
|
||||
TypeValidationError: 'TYPE_VALIDATION_ERROR',
|
||||
ConstraintValidationError: 'CONSTRAINT_VALIDATION_ERROR',
|
||||
StatuscodeNotInExampleError: 'STATUS_CODE_NOT_IN_EXAMPLE_ERROR',
|
||||
SemanticValidationError: 'SEMANTIC_VALIDATION_ERROR',
|
||||
MultipleOperationsFound: 'MULTIPLE_OPERATIONS_FOUND',
|
||||
NoOperationFound: 'NO_OPERATION_FOUND',
|
||||
IncorrectInput: 'INCORRECT_INPUT',
|
||||
PotentialOperationSearchError: 'POTENTIAL_OPERATION_SEARCH_ERROR',
|
||||
PathNotFoundInRequestUrl: "PATH_NOT_FOUND_IN_REQUEST_URL",
|
||||
OperationNotFoundInCache: "OPERATION_NOT_FOUND_IN_CACHE",
|
||||
OperationNotFoundInCacheWithVerb: "OPERATION_NOT_FOUND_IN_CACHE_WITH_VERB", // Implies we found correct api-version + provider in cache
|
||||
OperationNotFoundInCacheWithApi: "OPERATION_NOT_FOUND_IN_CACHE_WITH_API", // Implies we found correct provider in cache
|
||||
OperationNotFoundInCacheWithProvider: "OPERATION_NOT_FOUND_IN_CACHE_WITH_PROVIDER" // Implies we never found correct provider in cache
|
||||
InternalError: { name: 'INTERNAL_ERROR', id: 'OAV100' },
|
||||
InitializationError: { name: 'INITIALIZATION_ERROR', id: 'OAV101' },
|
||||
ResolveSpecError: { name: 'RESOLVE_SPEC_ERROR', id: 'OAV102' },
|
||||
RefNotFoundError: { name: 'REF_NOTFOUND_ERROR', id: 'OAV103' },
|
||||
JsonParsingError: { name: 'JSON_PARSING_ERROR', id: 'OAV104' },
|
||||
RequiredParameterExampleNotFound: { name: 'REQUIRED_PARAMETER_EXAMPLE_NOT_FOUND', id: 'OAV105' },
|
||||
ErrorInPreparingRequest: { name: 'ERROR_IN_PREPARING_REQUEST', id: 'OAV106' },
|
||||
XmsExampleNotFoundError: { name: 'X-MS-EXAMPLE_NOTFOUND_ERROR', id: 'OAV107' },
|
||||
ResponseValidationError: { name: 'RESPONSE_VALIDATION_ERROR', id: 'OAV108' },
|
||||
RequestValidationError: { name: 'REQUEST_VALIDATION_ERROR', id: 'OAV109' },
|
||||
ResponseBodyValidationError: { name: 'RESPONSE_BODY_VALIDATION_ERROR', id: 'OAV110' },
|
||||
ResponseStatusCodeNotInExample: { name: 'RESPONSE_STATUS_CODE_NOT_IN_EXAMPLE', id: 'OAV111' },
|
||||
ResponseStatusCodeNotInSpec: { name: 'RESPONSE_STATUS_CODE_NOT_IN_SPEC', id: 'OAV112' },
|
||||
ResponseSchemaNotInSpec: { nam: 'RESPONSE_SCHEMA_NOT_IN_SPEC', id: 'OAV113' },
|
||||
RequiredParameterNotInExampleError: { name: 'REQUIRED_PARAMETER_NOT_IN_EXAMPLE_ERROR', id: 'OAV114' },
|
||||
BodyParameterValidationError: { name: 'BODY_PARAMETER_VALIDATION_ERROR', id: 'OAV115' },
|
||||
TypeValidationError: { name: 'TYPE_VALIDATION_ERROR', id: 'OAV116' },
|
||||
ConstraintValidationError: { name: 'CONSTRAINT_VALIDATION_ERROR', id: 'OAV117' },
|
||||
StatuscodeNotInExampleError: { name: 'STATUS_CODE_NOT_IN_EXAMPLE_ERROR', id: 'OAV118' },
|
||||
SemanticValidationError: { name: 'SEMANTIC_VALIDATION_ERROR', id: 'OAV119' },
|
||||
MultipleOperationsFound: { name: 'MULTIPLE_OPERATIONS_FOUND', id: 'OAV120' },
|
||||
NoOperationFound: { name: 'NO_OPERATION_FOUND', id: 'OAV121' },
|
||||
IncorrectInput: { name: 'INCORRECT_INPUT', id: 'OAV122' },
|
||||
PotentialOperationSearchError: { name: 'POTENTIAL_OPERATION_SEARCH_ERROR', id: 'OAV123' },
|
||||
PathNotFoundInRequestUrl: { name: "PATH_NOT_FOUND_IN_REQUEST_URL", id: 'OAV124' },
|
||||
OperationNotFoundInCache: { name: "OPERATION_NOT_FOUND_IN_CACHE", id: 'OAV125' },
|
||||
OperationNotFoundInCacheWithVerb: { name: "OPERATION_NOT_FOUND_IN_CACHE_WITH_VERB", id: 'OAV126' }, // Implies we found correct api-version + provider in cache
|
||||
OperationNotFoundInCacheWithApi: { name: "OPERATION_NOT_FOUND_IN_CACHE_WITH_API", id: 'OAV127' }, // Implies we found correct provider in cache
|
||||
OperationNotFoundInCacheWithProvider: { name: "OPERATION_NOT_FOUND_IN_CACHE_WITH_PROVIDER", id: 'OAV128' } // Implies we never found correct provider in cache
|
||||
},
|
||||
EnvironmentVariables: {
|
||||
ClientId: 'CLIENT_ID',
|
||||
|
|
|
@ -133,7 +133,8 @@ class SpecResolver {
|
|||
}).catch(function (err) {
|
||||
let e = {
|
||||
message: `An Error occurred while resolving relative references and allOf in model definitions in the swagger spec: "${self.specPath}".`,
|
||||
code: ErrorCodes.ResolveSpecError,
|
||||
code: ErrorCodes.ResolveSpecError.name,
|
||||
id: ErrorCodes.ResolveSpecError.id,
|
||||
innerErrors: [err]
|
||||
};
|
||||
log.error(err);
|
||||
|
|
|
@ -87,26 +87,47 @@ class SpecValidator {
|
|||
if (self.options.shouldResolveRelativePaths) {
|
||||
utils.clearCache();
|
||||
}
|
||||
return utils.parseJson(self.specPath).then(function (result) {
|
||||
self.specInJson = result;
|
||||
if (self.specInJson === null) {
|
||||
return utils.parseJson(self.specPath).then(function (result) {
|
||||
self.specInJson = result;
|
||||
self.specResolver = new SpecResolver(self.specPath, self.specInJson, self.options);
|
||||
return self.specResolver.resolve();
|
||||
}).then(function () {
|
||||
let options = {};
|
||||
options.definition = self.specInJson;
|
||||
options.jsonRefs = {};
|
||||
options.jsonRefs.relativeBase = self.specDir;
|
||||
return Sway.create(options);
|
||||
}).then(function (api) {
|
||||
self.swaggerApi = api;
|
||||
return Promise.resolve(api);
|
||||
}).catch(function (err) {
|
||||
let e = self.constructErrorObject(ErrorCodes.ResolveSpecError, err.message, [err]);
|
||||
self.specValidationResult.resolveSpec = e;
|
||||
log.error(`${ErrorCodes.ResolveSpecError.name}: ${err.message}.`);
|
||||
log.error(err.stack);
|
||||
return Promise.reject(e);
|
||||
});
|
||||
}
|
||||
else {
|
||||
self.specResolver = new SpecResolver(self.specPath, self.specInJson, self.options);
|
||||
return self.specResolver.resolve();
|
||||
}).then(function () {
|
||||
let options = {};
|
||||
options.definition = self.specInJson;
|
||||
options.jsonRefs = {};
|
||||
options.jsonRefs.relativeBase = self.specDir;
|
||||
return Sway.create(options);
|
||||
}).then(function (api) {
|
||||
self.swaggerApi = api;
|
||||
return Promise.resolve(api);
|
||||
}).catch(function (err) {
|
||||
let e = self.constructErrorObject(ErrorCodes.ResolveSpecError, err.message, [err]);
|
||||
self.specValidationResult.resolveSpec = e;
|
||||
log.error(`${ErrorCodes.ResolveSpecError}: ${err.message}.`);
|
||||
log.error(err.stack);
|
||||
return Promise.reject(e);
|
||||
});
|
||||
return self.specResolver.resolve().then(function () {
|
||||
let options = {};
|
||||
options.definition = self.specInJson;
|
||||
options.jsonRefs = {};
|
||||
options.jsonRefs.relativeBase = self.specDir;
|
||||
return Sway.create(options);
|
||||
}).then(function (api) {
|
||||
self.swaggerApi = api;
|
||||
return Promise.resolve(api);
|
||||
}).catch(function (err) {
|
||||
let e = self.constructErrorObject(ErrorCodes.ResolveSpecError, err.message, [err]);
|
||||
self.specValidationResult.resolveSpec = e;
|
||||
log.error(`${ErrorCodes.ResolveSpecError.name}: ${err.message}.`);
|
||||
log.error(err.stack);
|
||||
return Promise.reject(e);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getProviderNamespace() {
|
||||
|
@ -158,7 +179,8 @@ class SpecValidator {
|
|||
*/
|
||||
constructErrorObject(code, message, innerErrors, skipValidityStatusUpdate) {
|
||||
let err = {
|
||||
code: code,
|
||||
code: code.name,
|
||||
id: code.id,
|
||||
message: message,
|
||||
}
|
||||
if (innerErrors) {
|
||||
|
@ -181,7 +203,7 @@ class SpecValidator {
|
|||
let e = self.constructErrorObject(ErrorCodes.InitializationError, msg)
|
||||
self.specValidationResult.initialize = e;
|
||||
self.specValidationResult.validateSpec.isValid = false;
|
||||
log.error(`${ErrorCodes.InitializationError}: ${msg}`);
|
||||
log.error(`${ErrorCodes.InitializationError.name}: ${msg}`);
|
||||
return Promise.reject(e);
|
||||
}
|
||||
try {
|
||||
|
@ -211,7 +233,8 @@ class SpecValidator {
|
|||
return Promise.resolve(validationResult);
|
||||
} catch (err) {
|
||||
let msg = `An Internal Error occurred in validating the spec "${self.specPath}". \t${err.message}.`;
|
||||
err.code = ErrorCodes.InternalError;
|
||||
err.code = ErrorCodes.InternalError.name;
|
||||
err.id = ErrorCodes.InternalError.id;
|
||||
err.message = msg;
|
||||
self.specValidationResult.validateSpec.isValid = false;
|
||||
self.specValidationResult.validateSpec.error = err;
|
||||
|
|
|
@ -77,7 +77,7 @@ class WireFormatGenerator {
|
|||
}).catch((err) => {
|
||||
let e = self.constructErrorObject(ErrorCodes.ResolveSpecError, err.message, [err]);
|
||||
//self.specValidationResult.resolveSpec = e;
|
||||
log.error(`${ErrorCodes.ResolveSpecError}: ${err.message}.`);
|
||||
log.error(`${ErrorCodes.ResolveSpecError.name}: ${err.message}.`);
|
||||
log.error(err.stack);
|
||||
return Promise.reject(e);
|
||||
});
|
||||
|
|
|
@ -23,7 +23,11 @@
|
|||
"uuid": "^3.0.1",
|
||||
"recursive-readdir": "^2.1.0",
|
||||
"swagger-parser": "^3.4.1",
|
||||
"swagger-tools": "^0.10.1"
|
||||
"swagger-tools": "^0.10.1",
|
||||
"linq":"^3.0.8",
|
||||
"jsonpath": "^0.2.11",
|
||||
"vscode-jsonrpc": "^3.2.0",
|
||||
"yaml-ast-parser": "https://github.com/olydis/yaml-ast-parser/releases/download/0.0.34/yaml-ast-parser-0.0.34.tgz"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jshint": "2.9.4",
|
||||
|
|
Загрузка…
Ссылка в новой задаче