зеркало из https://github.com/Azure/autorest.git
Feature: Move schema validator to ajv and ajv-errors for custom messages (#3936)
This commit is contained in:
Родитель
4246d1aba6
Коммит
dcb1684cb2
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@autorest/common",
|
||||
"comment": "Add `trackWarning` functionality to logger",
|
||||
"type": "patch"
|
||||
}
|
||||
],
|
||||
"packageName": "@autorest/common",
|
||||
"email": "tiguerin@microsoft.com"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@autorest/core",
|
||||
"comment": "Update swagger schema validator to use new system(`ajv` & `ajv-errors`) providing more relevant information",
|
||||
"type": "patch"
|
||||
}
|
||||
],
|
||||
"packageName": "@autorest/core",
|
||||
"email": "tiguerin@microsoft.com"
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@autorest/schemas",
|
||||
"comment": "Update schemas to jsonschema draft-07.",
|
||||
"type": "minor"
|
||||
},
|
||||
{
|
||||
"packageName": "@autorest/schemas",
|
||||
"comment": "Update schemas to use if else instead of oneof to provide more helpful validation.",
|
||||
"type": "minor"
|
||||
}
|
||||
],
|
||||
"packageName": "@autorest/schemas",
|
||||
"email": "tiguerin@microsoft.com"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"changes": [
|
||||
{
|
||||
"packageName": "@autorest/test-utils",
|
||||
"comment": "Add new util to create DataHandle",
|
||||
"type": "minor"
|
||||
}
|
||||
],
|
||||
"packageName": "@autorest/test-utils",
|
||||
"email": "tiguerin@microsoft.com"
|
||||
}
|
|
@ -48,6 +48,9 @@ dependencies:
|
|||
'@types/yargs': 15.0.13
|
||||
'@typescript-eslint/eslint-plugin': 4.14.2_e5f964fa93e839b7a7927397f6cb9cb1
|
||||
'@typescript-eslint/parser': 4.14.2_eslint@7.19.0+typescript@4.1.3
|
||||
ajv: 7.1.1
|
||||
ajv-errors: 2.0.0_ajv@7.1.1
|
||||
ajv-formats: 1.5.1
|
||||
body-parser: 1.19.0
|
||||
chalk: 4.1.0
|
||||
command-exists: 1.2.9
|
||||
|
@ -107,7 +110,6 @@ dependencies:
|
|||
yaml-ast-parser: 0.0.43
|
||||
yargs: 16.2.0
|
||||
yarn: 1.22.10
|
||||
z-schema: 5.0.0
|
||||
lockfileVersion: 5.2
|
||||
packages:
|
||||
/@azure-tools/async-io/3.0.253:
|
||||
|
@ -1479,6 +1481,20 @@ packages:
|
|||
node: '>= 4.0.0'
|
||||
resolution:
|
||||
integrity: sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==
|
||||
/ajv-errors/2.0.0_ajv@7.1.1:
|
||||
dependencies:
|
||||
ajv: 7.1.1
|
||||
dev: false
|
||||
peerDependencies:
|
||||
ajv: ^7.0.0
|
||||
resolution:
|
||||
integrity: sha512-Qi+I07e2Kc7Tgza7cZMvROyWuWmandN0BLbAiQUGLAMN/IfwIyg5kjg1qz/+q7p+uJ/x3THplnuGmihg/+WnXg==
|
||||
/ajv-formats/1.5.1:
|
||||
dependencies:
|
||||
ajv: 7.1.1
|
||||
dev: false
|
||||
resolution:
|
||||
integrity: sha512-s1RBVF4HZd2UjGkb6t6uWoXjf6o7j7dXPQIL7vprcIT/67bTD6+5ocsU0UKShS2qWxueGDWuGfKHfOxHWrlTQg==
|
||||
/ajv-keywords/3.5.2_ajv@6.12.6:
|
||||
dependencies:
|
||||
ajv: 6.12.6
|
||||
|
@ -1505,6 +1521,15 @@ packages:
|
|||
dev: false
|
||||
resolution:
|
||||
integrity: sha512-xzzzaqgEQfmuhbhAoqjJ8T/1okb6gAzXn/eQRNpAN1AEUoHJTNF9xCDRTtf/s3SKldtZfa+RJeTs+BQq+eZ/sw==
|
||||
/ajv/7.1.1:
|
||||
dependencies:
|
||||
fast-deep-equal: 3.1.3
|
||||
json-schema-traverse: 1.0.0
|
||||
require-from-string: 2.0.2
|
||||
uri-js: 4.4.1
|
||||
dev: false
|
||||
resolution:
|
||||
integrity: sha512-ga/aqDYnUy/o7vbsRTFhhTsNeXiYb5JWDIcRIeZfwRNCefwjNTVYCGdGSUrEmiu3yDK3vFvNbgJxvrQW4JXrYQ==
|
||||
/align-text/0.1.4:
|
||||
dependencies:
|
||||
kind-of: 3.2.2
|
||||
|
@ -9958,7 +9983,7 @@ packages:
|
|||
ts-node: '*'
|
||||
webpack-cli: '*'
|
||||
resolution:
|
||||
integrity: sha512-zn1e426O60et7E7+UyeBq6Rey9550paWPTGAUk+pTr+YpjckVIoKRoSqSIfoFhwf9Y5PblAe9bKTj4d8SEDuEA==
|
||||
integrity: sha512-QfELcsPUqDpOSGfMho2oSGzcGCt89Da8V5LpSXRqN2y8UZRg6Z4bjoT3DXPUAvbGDqppR6ydCJlrLW4WIWKtMg==
|
||||
tarball: file:projects/autorest.tgz
|
||||
version: 0.0.0
|
||||
file:projects/codegen.tgz_prettier@2.2.1+ts-node@9.1.1:
|
||||
|
@ -10072,7 +10097,7 @@ packages:
|
|||
peerDependencies:
|
||||
prettier: '*'
|
||||
resolution:
|
||||
integrity: sha512-ICQYsvvinkuAM42zp7jOoB+n+w3xqxTYbonvjNu3PoBGJuVTPNbAZ5I5kx65XvtVg3N4POEhAsS0iEuwabmV8w==
|
||||
integrity: sha512-Jo2B0ovccrO54g8I6Slhpz/incztxEnm/r52st+81Fd8/C+02q5sDEUMO84uM9RHNDH79vq+BYZn1PsXz5k45Q==
|
||||
tarball: file:projects/compare.tgz
|
||||
version: 0.0.0
|
||||
file:projects/configuration.tgz_prettier@2.2.1+ts-node@9.1.1:
|
||||
|
@ -10100,7 +10125,7 @@ packages:
|
|||
prettier: '*'
|
||||
ts-node: '*'
|
||||
resolution:
|
||||
integrity: sha512-/618yDQpSPf7x6bJkMyiKhltfS8j/YBjBxXydeDAnwYF1nN7I1kKLTJteCBRrZKiK5tLJFDuWm16x9PB85r+oA==
|
||||
integrity: sha512-LKUi6Mrflh5w0+U/PWjn1jtU7bE2jLqvND53aQf/hWMJmVmBcDFqXNS1vL2GUXNXjg/nWHsVG+Acu9agQwrPJg==
|
||||
tarball: file:projects/configuration.tgz
|
||||
version: 0.0.0
|
||||
file:projects/core.tgz_ts-node@9.1.1:
|
||||
|
@ -10120,6 +10145,9 @@ packages:
|
|||
'@types/webpack': 4.41.26
|
||||
'@typescript-eslint/eslint-plugin': 4.14.2_e5f964fa93e839b7a7927397f6cb9cb1
|
||||
'@typescript-eslint/parser': 4.14.2_eslint@7.19.0+typescript@4.1.3
|
||||
ajv: 7.1.1
|
||||
ajv-errors: 2.0.0_ajv@7.1.1
|
||||
ajv-formats: 1.5.1
|
||||
commonmark: 0.27.0
|
||||
compare-versions: 3.6.0
|
||||
copy-webpack-plugin: 7.0.0_webpack@5.18.0
|
||||
|
@ -10156,7 +10184,7 @@ packages:
|
|||
peerDependencies:
|
||||
ts-node: '*'
|
||||
resolution:
|
||||
integrity: sha512-QR7EBmyjKQCJfEkVZ/SgNyOPjgrtWDRW8nkJTexjXt6u++T17G2JSJ7l0v9+LDypazQ6Cebpq3lmQVUHcqrBMw==
|
||||
integrity: sha512-UKacK+vMh/BPaGatzLaMSPbd0qt4LCnnoEScLtb7jpHBvnVRZMVhH4bj6pjsUOUcIx4Kuxsh0fmjJkw4Nmmbsg==
|
||||
tarball: file:projects/core.tgz
|
||||
version: 0.0.0
|
||||
file:projects/datastore.tgz_prettier@2.2.1+ts-node@9.1.1:
|
||||
|
@ -10440,11 +10468,12 @@ packages:
|
|||
peerDependencies:
|
||||
prettier: '*'
|
||||
resolution:
|
||||
integrity: sha512-Nr/rOhVjZc0golARSPIQKP6Po09CdqVmXJF9NEfypoN2dthsy31ki4ls1D1YB0aHFwonpZLLTnDuFhUQ5GBiVA==
|
||||
integrity: sha512-dsmOlrJ7onRNMwAoVVwpacSEJbkLWYEEogGtNVi5aHh6VkhAFpyZKzJlrpOZ4UWasiCCFHr3w2tBzqVAMnox2A==
|
||||
tarball: file:projects/test-public-packages.tgz
|
||||
version: 0.0.0
|
||||
file:projects/test-utils.tgz_prettier@2.2.1+ts-node@9.1.1:
|
||||
dependencies:
|
||||
'@azure-tools/tasks': 3.0.253
|
||||
'@types/jest': 26.0.20
|
||||
eslint: 7.19.0
|
||||
eslint-plugin-prettier: 3.2.0_eslint@7.19.0+prettier@2.2.1
|
||||
|
@ -10460,7 +10489,7 @@ packages:
|
|||
prettier: '*'
|
||||
ts-node: '*'
|
||||
resolution:
|
||||
integrity: sha512-8nMXR/fQrY7cWzKlnWAWLNAPsCqTy218Yq76aUySEg/K65B+nGDBNIZewWlUh3Dy4q/xEwC+EN8tG9/SSwQ9EA==
|
||||
integrity: sha512-avGo/LW8WilQ37XPpPHqyRVtrS6FS4Oxm2NnkvMKV6v3UA8sQMMLH4QglVnyVpZDP8ULsCZwWrc7kVe+iYlZKA==
|
||||
tarball: file:projects/test-utils.tgz
|
||||
version: 0.0.0
|
||||
registry: ''
|
||||
|
@ -10514,6 +10543,9 @@ specifiers:
|
|||
'@types/yargs': ~15.0.12
|
||||
'@typescript-eslint/eslint-plugin': ^4.12.0
|
||||
'@typescript-eslint/parser': ^4.12.0
|
||||
ajv: ^7.1.1
|
||||
ajv-errors: ^2.0.0
|
||||
ajv-formats: ^1.5.1
|
||||
body-parser: ^1.19.0
|
||||
chalk: ^4.1.0
|
||||
command-exists: ~1.2.9
|
||||
|
@ -10573,4 +10605,3 @@ specifiers:
|
|||
yaml-ast-parser: 0.0.43
|
||||
yargs: ~16.2.0
|
||||
yarn: 1.22.10
|
||||
z-schema: ^5.0.0
|
||||
|
|
|
@ -63,6 +63,9 @@
|
|||
"@types/webpack": "~4.41.26",
|
||||
"@typescript-eslint/eslint-plugin": "^4.12.0",
|
||||
"@typescript-eslint/parser": "^4.12.0",
|
||||
"ajv": "^7.1.1",
|
||||
"ajv-errors": "^2.0.0",
|
||||
"ajv-formats": "^1.5.1",
|
||||
"commonmark": "^0.27.0",
|
||||
"compare-versions": "^3.4.0",
|
||||
"copy-webpack-plugin": "^7.0.0",
|
||||
|
@ -89,7 +92,6 @@
|
|||
"webpack-cli": "~4.4.0",
|
||||
"webpack-node-externals": "~2.5.2",
|
||||
"webpack": "~5.18.0",
|
||||
"yaml-ast-parser": "0.0.43",
|
||||
"z-schema": "^5.0.0"
|
||||
"yaml-ast-parser": "0.0.43"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import {
|
|||
arrayOf,
|
||||
extendAutorestConfiguration,
|
||||
} from "@autorest/configuration";
|
||||
import { AutorestError, AutorestLogger } from "@autorest/common";
|
||||
import { AutorestError, AutorestLogger, AutorestWarning } from "@autorest/common";
|
||||
import { Message } from "../message";
|
||||
import { AutorestCoreLogger } from "./logger";
|
||||
|
||||
|
@ -60,6 +60,10 @@ export class AutorestContext implements AutorestLogger {
|
|||
this.logger.trackError(error);
|
||||
}
|
||||
|
||||
public trackWarning(error: AutorestWarning) {
|
||||
this.logger.trackWarning(error);
|
||||
}
|
||||
|
||||
public Message(m: Message) {
|
||||
void this.logger.message(m);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Channel, Message, Range, SourceLocation } from "../message";
|
||||
import { BlameTree, stringify, Stringify, TryDecodeEnhancedPositionFromName } from "@azure-tools/datastore";
|
||||
import { AutorestError } from "@autorest/common";
|
||||
import { AutorestError, AutorestWarning } from "@autorest/common";
|
||||
import { AutorestConfiguration } from "@autorest/configuration";
|
||||
import { From } from "linq-es2015";
|
||||
import { Suppressor } from "../pipeline/suppression";
|
||||
|
@ -34,11 +34,21 @@ export class AutorestCoreLogger {
|
|||
});
|
||||
}
|
||||
|
||||
public trackWarning(error: AutorestWarning) {
|
||||
void this.message({
|
||||
Channel: Channel.Warning,
|
||||
Text: error.message,
|
||||
Source: error.source?.map((x) => ({ document: x.document, Position: x.position })),
|
||||
Details: error.details,
|
||||
});
|
||||
}
|
||||
|
||||
public trackError(error: AutorestError) {
|
||||
void this.message({
|
||||
Channel: Channel.Error,
|
||||
Text: error.message,
|
||||
Source: error.source?.map((x) => ({ document: x.document, Position: x.position })),
|
||||
Details: error.details,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ import {
|
|||
import { createTreeShakerPlugin } from "./plugins/tree-shaker/tree-shaker";
|
||||
import { createApiVersionParameterHandlerPlugin } from "./plugins/version-param-handler";
|
||||
import { createJsonToYamlPlugin, createYamlToJsonPlugin } from "./plugins/yaml-and-json";
|
||||
import { createOpenApiSchemaValidatorPlugin, createSwaggerSchemaValidatorPlugin } from "./schema-validation";
|
||||
import { createOpenApiSchemaValidatorPlugin, createSwaggerSchemaValidatorPlugin } from "./plugins/schema-validation";
|
||||
import { createHash } from "crypto";
|
||||
import { isCached, readCache, writeCache } from "./pipeline-cache";
|
||||
import { values } from "@azure-tools/linq";
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export * from "./schema-validation-plugins";
|
|
@ -0,0 +1,146 @@
|
|||
import { CompilePosition, DataHandle, JsonPath, parseJsonPointer } from "@azure-tools/datastore";
|
||||
import Ajv, { AnySchemaObject, ErrorObject } from "ajv";
|
||||
import ajvErrors from "ajv-errors";
|
||||
import { Position } from "source-map";
|
||||
|
||||
export interface ValidationError extends ErrorObject {
|
||||
path: JsonPath;
|
||||
}
|
||||
|
||||
export interface PositionedValidationError extends ValidationError {
|
||||
position: Position;
|
||||
}
|
||||
|
||||
export abstract class JsonSchemaValidator {
|
||||
protected ajv: Ajv;
|
||||
|
||||
public constructor() {
|
||||
this.ajv = new Ajv({ allErrors: true, strict: false });
|
||||
ajvErrors(this.ajv, {});
|
||||
}
|
||||
|
||||
public abstract get schema(): AnySchemaObject;
|
||||
|
||||
public validate(spec: unknown): ValidationError[] {
|
||||
const validate = this.ajv.compile(this.schema);
|
||||
const valid = validate(spec);
|
||||
if (valid || !validate.errors) {
|
||||
return [];
|
||||
} else {
|
||||
return condenseErrors(validate.errors).map((x) => ({ ...x, path: parseJsonPointer(x.dataPath) }));
|
||||
}
|
||||
}
|
||||
|
||||
public async validateFile(file: DataHandle): Promise<PositionedValidationError[]> {
|
||||
const spec = await file.ReadObject();
|
||||
const errors = this.validate(spec);
|
||||
const mappedErrors = errors.map((x) => extendWithPosition(x, file));
|
||||
return Promise.all(mappedErrors);
|
||||
}
|
||||
}
|
||||
|
||||
async function extendWithPosition(error: ValidationError, file: DataHandle): Promise<PositionedValidationError> {
|
||||
return {
|
||||
...error,
|
||||
position: await CompilePosition({ path: error.path }, file),
|
||||
};
|
||||
}
|
||||
|
||||
const IGNORE_ERROR = new Set(["if"]);
|
||||
export function condenseErrors(errors: ErrorObject[]): ErrorObject[] {
|
||||
const tree: any = {};
|
||||
|
||||
function countFor(dataPath: string, message: string) {
|
||||
return tree[dataPath][message].length;
|
||||
}
|
||||
|
||||
for (const err of errors.filter((x) => !IGNORE_ERROR.has(x.keyword))) {
|
||||
const { dataPath, message } = err;
|
||||
if (!message) {
|
||||
continue;
|
||||
}
|
||||
if (tree[dataPath] && tree[dataPath][message]) {
|
||||
tree[dataPath][message].push(err);
|
||||
} else if (tree[dataPath]) {
|
||||
tree[dataPath][message] = [err];
|
||||
} else {
|
||||
tree[dataPath] = {
|
||||
[message]: [err],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const dataPaths = Object.keys(tree);
|
||||
|
||||
return dataPaths.reduce((res: ValidationError[], path) => {
|
||||
const messages = Object.keys(tree[path]);
|
||||
|
||||
const mostFrequentMessageNames = messages.reduce(
|
||||
(obj, msg) => {
|
||||
const count = countFor(path, msg);
|
||||
|
||||
if (count > obj.max) {
|
||||
return {
|
||||
messages: [msg],
|
||||
max: count,
|
||||
};
|
||||
} else if (count === obj.max) {
|
||||
obj.messages.push(msg);
|
||||
return obj;
|
||||
} else {
|
||||
return obj;
|
||||
}
|
||||
},
|
||||
{ max: 0, messages: [] as string[] },
|
||||
).messages;
|
||||
|
||||
const mostFrequentMessages = mostFrequentMessageNames.map((name) => tree[path][name]);
|
||||
|
||||
const condensedErrors = mostFrequentMessages.map((messages) => {
|
||||
return messages.reduce((prev: any, err: ValidationError) => {
|
||||
const obj = Object.assign({}, prev, {
|
||||
params: mergeParams(prev.params, err.params),
|
||||
});
|
||||
|
||||
if (!prev.params && !err.params) {
|
||||
delete obj.params;
|
||||
}
|
||||
return obj;
|
||||
});
|
||||
});
|
||||
|
||||
return res.concat(condensedErrors);
|
||||
}, []);
|
||||
}
|
||||
|
||||
function mergeParams(objA: any = {}, objB: any = {}) {
|
||||
if (!objA && !objB) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const res: any = {};
|
||||
|
||||
for (const k of Object.keys(objA)) {
|
||||
res[k] = arrayify(objA[k]);
|
||||
}
|
||||
|
||||
for (const k of Object.keys(objB)) {
|
||||
if (res[k]) {
|
||||
res[k] = res[k].concat(arrayify(objB[k]));
|
||||
} else {
|
||||
res[k] = arrayify(objB[k]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function arrayify<T>(thing: T | T[] | undefined): T[] | undefined {
|
||||
if (thing === undefined || thing === null) {
|
||||
return undefined;
|
||||
}
|
||||
if (Array.isArray(thing)) {
|
||||
return thing;
|
||||
} else {
|
||||
return [thing];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
import { DataHandle } from "@azure-tools/datastore";
|
||||
import { omit } from "lodash";
|
||||
import { createDataHandle } from "@autorest/test-utils";
|
||||
import { OpenApi3SchemaValidator } from "./openapi3-schema-validator";
|
||||
const baseSwaggerSpec = {
|
||||
openapi: "3.0.0",
|
||||
info: {
|
||||
title: "Base spec",
|
||||
version: "1.0",
|
||||
},
|
||||
paths: {},
|
||||
};
|
||||
|
||||
describe("OpenAPI3 schema validator", () => {
|
||||
const validator = new OpenApi3SchemaValidator();
|
||||
|
||||
it("returns no errors if the spec is valid", () => {
|
||||
expect(validator.validate(baseSwaggerSpec)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("returns error if the info field is missing", () => {
|
||||
const errors = validator.validate(omit(baseSwaggerSpec, "info"));
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
dataPath: "",
|
||||
keyword: "required",
|
||||
message: "should have required property 'info'",
|
||||
params: { missingProperty: "info" },
|
||||
path: [],
|
||||
schemaPath: "#/required",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("combines erros", () => {
|
||||
const errors = validator.validate({
|
||||
...baseSwaggerSpec,
|
||||
info: { ...baseSwaggerSpec.info, invalidProp: "foo", otherProp: "bar" },
|
||||
});
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
dataPath: "/info",
|
||||
keyword: "additionalProperties",
|
||||
message: "should NOT have additional properties",
|
||||
params: { additionalProperty: ["invalidProp", "otherProp"] },
|
||||
path: ["info"],
|
||||
schemaPath: "#/additionalProperties",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("returns custom error if path is not starting with /", () => {
|
||||
const errors = validator.validate({ ...baseSwaggerSpec, paths: { "foo/bar": {} } });
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
dataPath: "/paths/foo~1bar",
|
||||
keyword: "errorMessage",
|
||||
message: 'should only have path names that start with `/` but found "foo/bar"',
|
||||
params: expect.anything(),
|
||||
path: ["paths", "foo/bar"],
|
||||
schemaPath: "#/additionalProperties/errorMessage",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe("when validating a file", () => {
|
||||
let file: DataHandle;
|
||||
beforeEach(() => {
|
||||
const spec = {
|
||||
...baseSwaggerSpec,
|
||||
info: {
|
||||
...baseSwaggerSpec.info,
|
||||
unexpectedProperty: "value",
|
||||
},
|
||||
};
|
||||
file = createDataHandle(JSON.stringify(spec, null, 2));
|
||||
});
|
||||
|
||||
it("returns the line number where the error is", async () => {
|
||||
const errors = await validator.validateFile(file);
|
||||
|
||||
expect(errors).toHaveLength(1);
|
||||
expect(errors[0].position).toEqual(
|
||||
expect.objectContaining({
|
||||
column: 2,
|
||||
length: 6,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
import addFormats from "ajv-formats";
|
||||
import { JsonSchemaValidator } from "./json-schema-validator";
|
||||
|
||||
export class OpenApi3SchemaValidator extends JsonSchemaValidator {
|
||||
public constructor() {
|
||||
super();
|
||||
addFormats(this.ajv);
|
||||
}
|
||||
|
||||
public get schema() {
|
||||
return require(`@autorest/schemas/openapi3-schema.json`);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { DataHandle } from "@azure-tools/datastore";
|
||||
import { OperationAbortedException } from "@autorest/common";
|
||||
import { Channel } from "../../../message";
|
||||
import { createPerFilePlugin, PipelinePlugin } from "../../common";
|
||||
import { AutorestContext } from "../../../configuration";
|
||||
import { SwaggerSchemaValidator } from "./swagger-schema-validator";
|
||||
import { PositionedValidationError } from "./json-schema-validator";
|
||||
import { OpenApi3SchemaValidator } from "./openapi3-schema-validator";
|
||||
|
||||
export const SCHEMA_VIOLATION_ERROR_CODE = "schema_violation";
|
||||
|
||||
export function createSwaggerSchemaValidatorPlugin(): PipelinePlugin {
|
||||
const swaggerValidator = new SwaggerSchemaValidator();
|
||||
|
||||
return createPerFilePlugin(async (config) => async (fileIn, sink) => {
|
||||
const obj = await fileIn.ReadObject<any>();
|
||||
const isSecondary = !!obj["x-ms-secondary-file"];
|
||||
|
||||
const errors = await swaggerValidator.validateFile(fileIn);
|
||||
if (errors.length > 0) {
|
||||
for (const error of errors) {
|
||||
// secondary files have reduced schema compliancy, so we're gonna just warn them for now.
|
||||
logValidationError(config, fileIn, error, isSecondary ? "warning" : "error");
|
||||
}
|
||||
if (!isSecondary) {
|
||||
throw new OperationAbortedException();
|
||||
}
|
||||
}
|
||||
return sink.Forward(fileIn.Description, fileIn);
|
||||
});
|
||||
}
|
||||
|
||||
export function createOpenApiSchemaValidatorPlugin(): PipelinePlugin {
|
||||
const validator = new OpenApi3SchemaValidator();
|
||||
|
||||
return createPerFilePlugin(async (context) => async (fileIn, sink) => {
|
||||
const obj = await fileIn.ReadObject<any>();
|
||||
const isSecondary = !!obj["x-ms-secondary-file"];
|
||||
const markErrorAsWarnings = context.config["mark-oai3-errors-as-warnings"];
|
||||
const errors = await validator.validateFile(fileIn);
|
||||
if (errors.length > 0) {
|
||||
for (const error of errors) {
|
||||
const level = markErrorAsWarnings || isSecondary ? "warning" : "error";
|
||||
logValidationError(context, fileIn, error as any, level);
|
||||
}
|
||||
if (!isSecondary) {
|
||||
context.Message({
|
||||
Channel: Channel.Error,
|
||||
Plugin: "schema-validator-openapi",
|
||||
Text: [
|
||||
`Unrecoverable schema validation errors were encountered in OpenAPI 3 input files.`,
|
||||
`You can use --markOpenAPI3ErrorsAsWarning to keep mark as warning and let autorest keep going.`,
|
||||
`If you believe this the validation error is incorrect, please open an issue at https://github.com/Azure/autorest`,
|
||||
`NOTE: in the future this flag will be removed and validation error will fail the pipeline.`,
|
||||
].join("\n"),
|
||||
});
|
||||
throw new OperationAbortedException();
|
||||
}
|
||||
}
|
||||
return sink.Forward(fileIn.Description, fileIn);
|
||||
});
|
||||
}
|
||||
|
||||
const IGNORED_AJV_PARAMS = new Set(["type", "errors"]);
|
||||
|
||||
const logValidationError = (
|
||||
config: AutorestContext,
|
||||
fileIn: DataHandle,
|
||||
error: PositionedValidationError,
|
||||
type: "error" | "warning",
|
||||
) => {
|
||||
const messageLines = [`Schema violation: ${error.message} (${error.path.join(" > ")})`];
|
||||
for (const [name, value] of Object.entries(error.params).filter(([name]) => !IGNORED_AJV_PARAMS.has(name))) {
|
||||
const formattedValue = Array.isArray(value) ? [...new Set(value)].join(", ") : value;
|
||||
messageLines.push(` ${name}: ${formattedValue}`);
|
||||
}
|
||||
|
||||
const msg = {
|
||||
code: SCHEMA_VIOLATION_ERROR_CODE,
|
||||
message: messageLines.join("\n"),
|
||||
source: [{ document: fileIn.key, position: error.position }],
|
||||
details: error,
|
||||
};
|
||||
|
||||
if (type == "warning") {
|
||||
config.trackWarning(msg);
|
||||
} else {
|
||||
config.trackError(msg);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,91 @@
|
|||
import { DataHandle } from "@azure-tools/datastore";
|
||||
import { omit } from "lodash";
|
||||
import { SwaggerSchemaValidator } from "./swagger-schema-validator";
|
||||
import { createDataHandle } from "@autorest/test-utils";
|
||||
const baseSwaggerSpec = {
|
||||
swagger: "2.0",
|
||||
info: {
|
||||
title: "Base spec",
|
||||
version: "1.0",
|
||||
},
|
||||
paths: {},
|
||||
};
|
||||
|
||||
describe("Swagger schema validator", () => {
|
||||
const validator = new SwaggerSchemaValidator();
|
||||
|
||||
it("returns no errors if the spec is valid", () => {
|
||||
expect(validator.validate(baseSwaggerSpec)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("returns error if the info field is missing", () => {
|
||||
const errors = validator.validate(omit(baseSwaggerSpec, "info"));
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
dataPath: "",
|
||||
keyword: "required",
|
||||
message: "should have required property 'info'",
|
||||
params: { missingProperty: "info" },
|
||||
path: [],
|
||||
schemaPath: "#/required",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("combines erros", () => {
|
||||
const errors = validator.validate({
|
||||
...baseSwaggerSpec,
|
||||
info: { ...baseSwaggerSpec.info, invalidProp: "foo", otherProp: "bar" },
|
||||
});
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
dataPath: "/info",
|
||||
keyword: "additionalProperties",
|
||||
message: "should NOT have additional properties",
|
||||
params: { additionalProperty: ["invalidProp", "otherProp"] },
|
||||
path: ["info"],
|
||||
schemaPath: "#/additionalProperties",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("returns custom error if path is not starting with /", () => {
|
||||
const errors = validator.validate({ ...baseSwaggerSpec, paths: { "foo/bar": {} } });
|
||||
expect(errors).toEqual([
|
||||
{
|
||||
dataPath: "/paths/foo~1bar",
|
||||
keyword: "errorMessage",
|
||||
message: 'should only have path names that start with `/` but found "foo/bar"',
|
||||
params: expect.anything(),
|
||||
path: ["paths", "foo/bar"],
|
||||
schemaPath: "#/additionalProperties/errorMessage",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
describe("when validating a file", () => {
|
||||
let file: DataHandle;
|
||||
beforeEach(() => {
|
||||
const spec = {
|
||||
...baseSwaggerSpec,
|
||||
info: {
|
||||
...baseSwaggerSpec.info,
|
||||
unexpectedProperty: "value",
|
||||
},
|
||||
};
|
||||
file = createDataHandle(JSON.stringify(spec, null, 2));
|
||||
});
|
||||
|
||||
it("returns the line number where the error is", async () => {
|
||||
const errors = await validator.validateFile(file);
|
||||
|
||||
expect(errors).toHaveLength(1);
|
||||
expect(errors[0].position).toEqual(
|
||||
expect.objectContaining({
|
||||
column: 2,
|
||||
length: 6,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,19 @@
|
|||
import addFormats from "ajv-formats";
|
||||
import { JsonSchemaValidator } from "./json-schema-validator";
|
||||
|
||||
export class SwaggerSchemaValidator extends JsonSchemaValidator {
|
||||
public constructor() {
|
||||
super();
|
||||
addFormats(this.ajv);
|
||||
|
||||
this.ajv.addSchema(require("@autorest/schemas/swagger.json"), "http://json.schemastore.org/swagger-2.0");
|
||||
this.ajv.addSchema(
|
||||
require("@autorest/schemas/example-schema.json"),
|
||||
"https://raw.githubusercontent.com/Azure/autorest/master/schema/example-schema.json",
|
||||
);
|
||||
}
|
||||
|
||||
public get schema() {
|
||||
return require(`@autorest/schemas/swagger-extensions.json`);
|
||||
}
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
import { DataHandle, parseJsonPointer } from "@azure-tools/datastore";
|
||||
import SchemaValidator from "z-schema";
|
||||
import { OperationAbortedException } from "@autorest/common";
|
||||
import { Channel } from "../message";
|
||||
import { createPerFilePlugin, PipelinePlugin } from "./common";
|
||||
import { AutorestContext } from "../configuration";
|
||||
|
||||
export function createSwaggerSchemaValidatorPlugin(): PipelinePlugin {
|
||||
const validator = new SchemaValidator({ breakOnFirstError: false });
|
||||
|
||||
const extendedSwaggerSchema = require(`@autorest/schemas/swagger-extensions.json`);
|
||||
(<any>validator).setRemoteReference(
|
||||
"http://json.schemastore.org/swagger-2.0",
|
||||
require(`@autorest/schemas/swagger.json`),
|
||||
);
|
||||
(<any>validator).setRemoteReference(
|
||||
"https://raw.githubusercontent.com/Azure/autorest/master/schema/example-schema.json",
|
||||
require(`@autorest/schemas/example-schema.json`),
|
||||
);
|
||||
return createPerFilePlugin(async (config) => async (fileIn, sink) => {
|
||||
const obj = await fileIn.ReadObject<any>();
|
||||
const isSecondary = !!obj["x-ms-secondary-file"];
|
||||
|
||||
const errors = await validateSchema(obj, extendedSwaggerSchema, validator);
|
||||
if (errors !== null) {
|
||||
for (const error of errors) {
|
||||
// secondary files have reduced schema compliancy, so we're gonna just warn them for now.
|
||||
logValidationError(config, fileIn, error, "schema-validator-swagger", isSecondary ? "warning" : "error");
|
||||
}
|
||||
if (!isSecondary) {
|
||||
throw new OperationAbortedException();
|
||||
}
|
||||
}
|
||||
return sink.Forward(fileIn.Description, fileIn);
|
||||
});
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export function createOpenApiSchemaValidatorPlugin(): PipelinePlugin {
|
||||
const validator = new SchemaValidator({ breakOnFirstError: false });
|
||||
|
||||
const extendedOpenApiSchema = require(`@autorest/schemas/openapi3-schema.json`);
|
||||
return createPerFilePlugin(async (context) => async (fileIn, sink) => {
|
||||
const obj = await fileIn.ReadObject<any>();
|
||||
const isSecondary = !!obj["x-ms-secondary-file"];
|
||||
const markErrorAsWarnings = context.config["mark-oai3-errors-as-warnings"];
|
||||
const errors = await validateSchema(obj, extendedOpenApiSchema, validator);
|
||||
if (errors !== null) {
|
||||
for (const error of errors) {
|
||||
const level = markErrorAsWarnings || isSecondary ? "warning" : "error";
|
||||
logValidationError(context, fileIn, error, "schema-validator-openapi", level);
|
||||
}
|
||||
if (!isSecondary) {
|
||||
context.Message({
|
||||
Channel: Channel.Error,
|
||||
Plugin: "schema-validator-openapi",
|
||||
Text: [
|
||||
`Unrecoverable schema validation errors were encountered in OpenAPI 3 input files.`,
|
||||
`You can use --markOpenAPI3ErrorsAsWarning to keep mark as warning and let autorest keep going.`,
|
||||
`If you believe this the validation error is incorrect, please open an issue at https://github.com/Azure/autorest`,
|
||||
`NOTE: in the future this flag will be removed and validation error will fail the pipeline.`,
|
||||
].join("\n"),
|
||||
});
|
||||
throw new OperationAbortedException();
|
||||
}
|
||||
}
|
||||
return sink.Forward(fileIn.Description, fileIn);
|
||||
});
|
||||
}
|
||||
|
||||
interface ValidationError {
|
||||
code: "OBJECT_ADDITIONAL_PROPERTIES" | "ONE_OF_MISSING" | string;
|
||||
params: string[];
|
||||
message: string;
|
||||
path: string;
|
||||
inner?: ValidationError[];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value Value to validate.
|
||||
* @param schema Schema as a javascript object.
|
||||
* @param validator Schema validator.
|
||||
*/
|
||||
const validateSchema = (
|
||||
value: unknown,
|
||||
schema: unknown,
|
||||
validator: SchemaValidator,
|
||||
): Promise<ValidationError[] | null> => {
|
||||
return new Promise<ValidationError[] | null>((res) =>
|
||||
validator.validate(value, schema, (err, valid) => res(valid ? null : err)),
|
||||
);
|
||||
};
|
||||
|
||||
const logValidationError = (
|
||||
config: AutorestContext,
|
||||
fileIn: DataHandle,
|
||||
error: ValidationError,
|
||||
pluginName: string,
|
||||
type: "error" | "warning",
|
||||
) => {
|
||||
const path = parseJsonPointer(error.path);
|
||||
config.Message({
|
||||
Channel: type == "warning" ? Channel.Warning : Channel.Error,
|
||||
Details: error,
|
||||
Plugin: pluginName,
|
||||
Source: [{ document: fileIn.key, Position: <any>{ path } }],
|
||||
Text: `Schema violation: ${error.message} (${path.join(" > ")})`,
|
||||
});
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "Base spec",
|
||||
"version": "1.0",
|
||||
"unexpectedProperty": "value"
|
||||
},
|
||||
"paths": {}
|
||||
}
|
|
@ -38,10 +38,33 @@ describe("EndToEnd", () => {
|
|||
},
|
||||
});
|
||||
|
||||
const messages: Message[] = [];
|
||||
const channels = new Set([
|
||||
Channel.Information,
|
||||
Channel.Warning,
|
||||
Channel.Error,
|
||||
Channel.Fatal,
|
||||
Channel.Debug,
|
||||
Channel.Verbose,
|
||||
]);
|
||||
|
||||
autoRest.Message.Subscribe((_, message) => {
|
||||
if (channels.has(message.Channel)) {
|
||||
messages.push(message);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: generate for all, probe results
|
||||
|
||||
const success = await autoRest.Process().finish;
|
||||
assert.strictEqual(success, true);
|
||||
|
||||
if (!success) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log("Messages", messages);
|
||||
fail("Autorest didn't complete with success.");
|
||||
}
|
||||
|
||||
expect(success).toBe(true);
|
||||
});
|
||||
|
||||
it("other configuration scenario", async () => {
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
{
|
||||
"title": "A JSON Schema for Composite Swagger in Swagger 2.0 API.",
|
||||
"id": "https://raw.githubusercontent.com/Azure/autorest/master/schema/composite-swagger.json#",
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"$id": "https://raw.githubusercontent.com/Azure/autorest/master/schema/composite-swagger.json#",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"info",
|
||||
"documents"
|
||||
],
|
||||
"required": ["info", "documents"],
|
||||
"description": "Describes the title, description of the Composite Swagger. It provides a mechanism to bind/package clients generated from multiple swaggers together into one composite client.",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
|
@ -26,10 +23,7 @@
|
|||
"info": {
|
||||
"type": "object",
|
||||
"description": "General information about the API.",
|
||||
"required": [
|
||||
"title",
|
||||
"description"
|
||||
],
|
||||
"required": ["title", "description"],
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^x-(?!ms-).*$": {
|
||||
|
@ -91,9 +85,7 @@
|
|||
},
|
||||
"license": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"required": ["name"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"title": "A JSON Schema for x-ms-examples extension in Swagger 2.0 API.",
|
||||
"id": "https://raw.githubusercontent.com/Azure/autorest/master/packages/libs/autorest-schemas/example-schema.json#",
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"$id": "https://raw.githubusercontent.com/Azure/autorest/master/packages/libs/autorest-schemas/example-schema.json#",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"required": ["parameters", "responses"],
|
||||
"description": "Describes the format of an example defined using the x-ms-examples extension.",
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"title": "A JSON Schema for Swagger 2.0 API.",
|
||||
"id": "https://raw.githubusercontent.com/Azure/autorest/master/schema/swagger-extensions.json#",
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"$id": "https://raw.githubusercontent.com/Azure/autorest/master/schema/swagger-extensions.json#",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"required": ["swagger", "info", "paths"],
|
||||
"additionalProperties": false,
|
||||
|
@ -192,7 +192,10 @@
|
|||
"$ref": "#/definitions/pathItem"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": {
|
||||
"not": true,
|
||||
"errorMessage": "should only have path names that start with `/` but found ${0#}"
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"type": "object",
|
||||
|
@ -400,14 +403,15 @@
|
|||
}
|
||||
},
|
||||
"responseValue": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/response"
|
||||
"if": {
|
||||
"required": ["$ref"]
|
||||
},
|
||||
{
|
||||
"then": {
|
||||
"$ref": "#/definitions/jsonReference"
|
||||
},
|
||||
"else": {
|
||||
"$ref": "#/definitions/response"
|
||||
}
|
||||
]
|
||||
},
|
||||
"response": {
|
||||
"type": "object",
|
||||
|
@ -1063,30 +1067,138 @@
|
|||
}
|
||||
},
|
||||
"nonBodyParameter": {
|
||||
"type": "object",
|
||||
"required": ["name", "in", "type"],
|
||||
"oneOf": [
|
||||
"allOf": [
|
||||
{
|
||||
"if": {
|
||||
"required": ["in"],
|
||||
"properties": {
|
||||
"in": {
|
||||
"enum": ["header"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"$ref": "#/definitions/headerParameterSubSchema"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"required": ["in"],
|
||||
"properties": {
|
||||
"in": {
|
||||
"enum": ["formData"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"$ref": "#/definitions/formDataParameterSubSchema"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"required": ["in"],
|
||||
"properties": {
|
||||
"in": {
|
||||
"enum": ["query"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"$ref": "#/definitions/queryParameterSubSchema"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"required": ["in"],
|
||||
"properties": {
|
||||
"in": {
|
||||
"enum": ["path"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"$ref": "#/definitions/pathParameterSubSchema"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameter": {
|
||||
"oneOf": [
|
||||
"allOf": [
|
||||
{
|
||||
"if": {
|
||||
"required": ["in"],
|
||||
"properties": {
|
||||
"in": {
|
||||
"enum": ["body"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"$ref": "#/definitions/bodyParameter"
|
||||
}
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/nonBodyParameter"
|
||||
"if": {
|
||||
"required": ["in"],
|
||||
"properties": {
|
||||
"in": {
|
||||
"enum": ["header"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"$ref": "#/definitions/headerParameterSubSchema"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"required": ["in"],
|
||||
"properties": {
|
||||
"in": {
|
||||
"enum": ["formData"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"$ref": "#/definitions/formDataParameterSubSchema"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"required": ["in"],
|
||||
"properties": {
|
||||
"in": {
|
||||
"enum": ["query"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"$ref": "#/definitions/queryParameterSubSchema"
|
||||
}
|
||||
},
|
||||
{
|
||||
"if": {
|
||||
"required": ["in"],
|
||||
"properties": {
|
||||
"in": {
|
||||
"enum": ["path"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"$ref": "#/definitions/pathParameterSubSchema"
|
||||
}
|
||||
},
|
||||
{
|
||||
"then": {
|
||||
"type": "object",
|
||||
"required": ["in"],
|
||||
"properties": {
|
||||
"in": {
|
||||
"enum": ["body", "header", "formData", "query", "path"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
|
@ -1114,58 +1226,58 @@
|
|||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/title"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/title"
|
||||
},
|
||||
"description": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/description"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/description"
|
||||
},
|
||||
"default": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/default"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/default"
|
||||
},
|
||||
"multipleOf": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/multipleOf"
|
||||
},
|
||||
"maximum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/maximum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/maximum"
|
||||
},
|
||||
"exclusiveMaximum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum"
|
||||
"$ref": "#/definitions/exclusiveMaximum"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/minimum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/minimum"
|
||||
},
|
||||
"exclusiveMinimum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum"
|
||||
"$ref": "#/definitions/exclusiveMinimum"
|
||||
},
|
||||
"maxLength": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger"
|
||||
},
|
||||
"minLength": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeIntegerDefault0"
|
||||
},
|
||||
"pattern": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/pattern"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/pattern"
|
||||
},
|
||||
"maxItems": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger"
|
||||
},
|
||||
"minItems": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeIntegerDefault0"
|
||||
},
|
||||
"uniqueItems": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/uniqueItems"
|
||||
},
|
||||
"maxProperties": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger"
|
||||
},
|
||||
"minProperties": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeIntegerDefault0"
|
||||
},
|
||||
"required": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/stringArray"
|
||||
},
|
||||
"enum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/enum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/enum"
|
||||
},
|
||||
"x-ms-enum": {
|
||||
"$ref": "#/definitions/xmsEnum"
|
||||
|
@ -1188,7 +1300,7 @@
|
|||
"default": {}
|
||||
},
|
||||
"type": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/type"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/type"
|
||||
},
|
||||
"items": {
|
||||
"anyOf": [
|
||||
|
@ -1274,16 +1386,16 @@
|
|||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/title"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/title"
|
||||
},
|
||||
"description": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/description"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/description"
|
||||
},
|
||||
"default": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/default"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/default"
|
||||
},
|
||||
"required": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/stringArray"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
|
@ -1464,14 +1576,15 @@
|
|||
"description": "The parameters needed to send a valid API call.",
|
||||
"additionalItems": false,
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/parameter"
|
||||
"if": {
|
||||
"required": ["$ref"]
|
||||
},
|
||||
{
|
||||
"then": {
|
||||
"$ref": "#/definitions/jsonReference"
|
||||
},
|
||||
"else": {
|
||||
"$ref": "#/definitions/parameter"
|
||||
}
|
||||
]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
@ -1495,49 +1608,51 @@
|
|||
"default": "csv"
|
||||
},
|
||||
"title": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/title"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/title"
|
||||
},
|
||||
"description": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/description"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/description"
|
||||
},
|
||||
"default": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/default"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/default"
|
||||
},
|
||||
"multipleOf": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/multipleOf"
|
||||
},
|
||||
"maximum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/maximum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/maximum"
|
||||
},
|
||||
"exclusiveMaximum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum"
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/minimum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/minimum"
|
||||
},
|
||||
"exclusiveMinimum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum"
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"maxLength": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger"
|
||||
},
|
||||
"minLength": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeIntegerDefault0"
|
||||
},
|
||||
"pattern": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/pattern"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/pattern"
|
||||
},
|
||||
"maxItems": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger"
|
||||
},
|
||||
"minItems": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeIntegerDefault0"
|
||||
},
|
||||
"uniqueItems": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/uniqueItems"
|
||||
},
|
||||
"enum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/enum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/enum"
|
||||
},
|
||||
"jsonReference": {
|
||||
"type": "object",
|
||||
|
@ -1692,14 +1807,15 @@
|
|||
"description": "The parameters used in conjunction with x-ms-parameterized-host.",
|
||||
"additionalItems": false,
|
||||
"items": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/nonBodyParameter"
|
||||
"if": {
|
||||
"required": ["$ref"]
|
||||
},
|
||||
{
|
||||
"then": {
|
||||
"$ref": "#/definitions/jsonReference"
|
||||
},
|
||||
"else": {
|
||||
"$ref": "#/definitions/nonBodyParameter"
|
||||
}
|
||||
]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
|
@ -1766,14 +1882,15 @@
|
|||
"type": "object",
|
||||
"description": "Describes the 'x-ms-examples' extension.",
|
||||
"additionalProperties": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "https://raw.githubusercontent.com/Azure/autorest/master/schema/example-schema.json#"
|
||||
"if": {
|
||||
"required": ["$ref"]
|
||||
},
|
||||
{
|
||||
"then": {
|
||||
"$ref": "#/definitions/jsonReference"
|
||||
}
|
||||
]
|
||||
},
|
||||
"else": {
|
||||
"$ref": "https://raw.githubusercontent.com/Azure/autorest/master/schema/example-schema.json#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
{
|
||||
"title": "A JSON Schema for Swagger 2.0 API.",
|
||||
"id": "http://swagger.io/v2/schema.json#",
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"$id": "http://swagger.io/v2/schema.json#",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"swagger",
|
||||
"info",
|
||||
"paths"
|
||||
],
|
||||
"required": ["swagger", "info", "paths"],
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^x-": {
|
||||
|
@ -17,9 +13,7 @@
|
|||
"properties": {
|
||||
"swagger": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"2.0"
|
||||
],
|
||||
"enum": ["2.0"],
|
||||
"description": "The Swagger version of this document."
|
||||
},
|
||||
"info": {
|
||||
|
@ -87,10 +81,7 @@
|
|||
"info": {
|
||||
"type": "object",
|
||||
"description": "General information about the API.",
|
||||
"required": [
|
||||
"version",
|
||||
"title"
|
||||
],
|
||||
"required": ["version", "title"],
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^x-": {
|
||||
|
@ -152,9 +143,7 @@
|
|||
},
|
||||
"license": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"required": ["name"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
|
@ -211,9 +200,7 @@
|
|||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"description": "information about external documentation",
|
||||
"required": [
|
||||
"url"
|
||||
],
|
||||
"required": ["url"],
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
|
@ -239,9 +226,7 @@
|
|||
},
|
||||
"operation": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"responses"
|
||||
],
|
||||
"required": ["responses"],
|
||||
"additionalProperties": false,
|
||||
"patternProperties": {
|
||||
"^x-": {
|
||||
|
@ -378,9 +363,7 @@
|
|||
},
|
||||
"response": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"description"
|
||||
],
|
||||
"required": ["description"],
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "string"
|
||||
|
@ -418,19 +401,11 @@
|
|||
"header": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"required": ["type"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"string",
|
||||
"number",
|
||||
"integer",
|
||||
"boolean",
|
||||
"array"
|
||||
]
|
||||
"enum": ["string", "number", "integer", "boolean", "array"]
|
||||
},
|
||||
"format": {
|
||||
"type": "string"
|
||||
|
@ -497,11 +472,7 @@
|
|||
},
|
||||
"bodyParameter": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"in",
|
||||
"schema"
|
||||
],
|
||||
"required": ["name", "in", "schema"],
|
||||
"patternProperties": {
|
||||
"^x-": {
|
||||
"$ref": "#/definitions/vendorExtension"
|
||||
|
@ -519,9 +490,7 @@
|
|||
"in": {
|
||||
"type": "string",
|
||||
"description": "Determines the location of the parameter.",
|
||||
"enum": [
|
||||
"body"
|
||||
]
|
||||
"enum": ["body"]
|
||||
},
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
|
@ -550,9 +519,7 @@
|
|||
"in": {
|
||||
"type": "string",
|
||||
"description": "Determines the location of the parameter.",
|
||||
"enum": [
|
||||
"header"
|
||||
]
|
||||
"enum": ["header"]
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
|
@ -564,13 +531,7 @@
|
|||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"string",
|
||||
"number",
|
||||
"boolean",
|
||||
"integer",
|
||||
"array"
|
||||
]
|
||||
"enum": ["string", "number", "boolean", "integer", "array"]
|
||||
},
|
||||
"format": {
|
||||
"type": "string"
|
||||
|
@ -638,9 +599,7 @@
|
|||
"in": {
|
||||
"type": "string",
|
||||
"description": "Determines the location of the parameter.",
|
||||
"enum": [
|
||||
"query"
|
||||
]
|
||||
"enum": ["query"]
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
|
@ -657,13 +616,7 @@
|
|||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"string",
|
||||
"number",
|
||||
"boolean",
|
||||
"integer",
|
||||
"array"
|
||||
]
|
||||
"enum": ["string", "number", "boolean", "integer", "array"]
|
||||
},
|
||||
"format": {
|
||||
"type": "string"
|
||||
|
@ -731,9 +684,7 @@
|
|||
"in": {
|
||||
"type": "string",
|
||||
"description": "Determines the location of the parameter.",
|
||||
"enum": [
|
||||
"formData"
|
||||
]
|
||||
"enum": ["formData"]
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
|
@ -750,14 +701,7 @@
|
|||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"string",
|
||||
"number",
|
||||
"boolean",
|
||||
"integer",
|
||||
"array",
|
||||
"file"
|
||||
]
|
||||
"enum": ["string", "number", "boolean", "integer", "array", "file"]
|
||||
},
|
||||
"format": {
|
||||
"type": "string"
|
||||
|
@ -816,23 +760,17 @@
|
|||
"$ref": "#/definitions/vendorExtension"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"required"
|
||||
],
|
||||
"required": ["required"],
|
||||
"properties": {
|
||||
"required": {
|
||||
"type": "boolean",
|
||||
"enum": [
|
||||
true
|
||||
],
|
||||
"enum": [true],
|
||||
"description": "Determines whether or not this parameter is required or optional."
|
||||
},
|
||||
"in": {
|
||||
"type": "string",
|
||||
"description": "Determines the location of the parameter.",
|
||||
"enum": [
|
||||
"path"
|
||||
]
|
||||
"enum": ["path"]
|
||||
},
|
||||
"description": {
|
||||
"type": "string",
|
||||
|
@ -844,13 +782,7 @@
|
|||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"string",
|
||||
"number",
|
||||
"boolean",
|
||||
"integer",
|
||||
"array"
|
||||
]
|
||||
"enum": ["string", "number", "boolean", "integer", "array"]
|
||||
},
|
||||
"format": {
|
||||
"type": "string"
|
||||
|
@ -904,11 +836,7 @@
|
|||
},
|
||||
"nonBodyParameter": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name",
|
||||
"in",
|
||||
"type"
|
||||
],
|
||||
"required": ["name", "in", "type"],
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/headerParameterSubSchema"
|
||||
|
@ -950,58 +878,58 @@
|
|||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/title"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/title"
|
||||
},
|
||||
"description": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/description"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/description"
|
||||
},
|
||||
"default": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/default"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/default"
|
||||
},
|
||||
"multipleOf": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/multipleOf"
|
||||
},
|
||||
"maximum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/maximum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/maximum"
|
||||
},
|
||||
"exclusiveMaximum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/exclusiveMaximum"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/minimum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/minimum"
|
||||
},
|
||||
"exclusiveMinimum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/exclusiveMinimum"
|
||||
},
|
||||
"maxLength": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger"
|
||||
},
|
||||
"minLength": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeIntegerDefault0"
|
||||
},
|
||||
"pattern": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/pattern"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/pattern"
|
||||
},
|
||||
"maxItems": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger"
|
||||
},
|
||||
"minItems": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeIntegerDefault0"
|
||||
},
|
||||
"uniqueItems": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/uniqueItems"
|
||||
},
|
||||
"maxProperties": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger"
|
||||
},
|
||||
"minProperties": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeIntegerDefault0"
|
||||
},
|
||||
"required": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/stringArray"
|
||||
},
|
||||
"enum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/enum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/enum"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"anyOf": [
|
||||
|
@ -1015,7 +943,7 @@
|
|||
"default": {}
|
||||
},
|
||||
"type": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/type"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/type"
|
||||
},
|
||||
"items": {
|
||||
"anyOf": [
|
||||
|
@ -1071,30 +999,26 @@
|
|||
"$ref": "#/definitions/vendorExtension"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"required": ["type"],
|
||||
"properties": {
|
||||
"format": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/title"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/title"
|
||||
},
|
||||
"description": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/description"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/description"
|
||||
},
|
||||
"default": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/default"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/default"
|
||||
},
|
||||
"required": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/stringArray"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/stringArray"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"file"
|
||||
]
|
||||
"enum": ["file"]
|
||||
},
|
||||
"readOnly": {
|
||||
"type": "boolean",
|
||||
|
@ -1113,13 +1037,7 @@
|
|||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"string",
|
||||
"number",
|
||||
"integer",
|
||||
"boolean",
|
||||
"array"
|
||||
]
|
||||
"enum": ["string", "number", "integer", "boolean", "array"]
|
||||
},
|
||||
"format": {
|
||||
"type": "string"
|
||||
|
@ -1224,9 +1142,7 @@
|
|||
"tag": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"required": ["name"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
|
@ -1272,15 +1188,11 @@
|
|||
"basicAuthenticationSecurity": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"required": ["type"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"basic"
|
||||
]
|
||||
"enum": ["basic"]
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
|
@ -1295,27 +1207,18 @@
|
|||
"apiKeySecurity": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"type",
|
||||
"name",
|
||||
"in"
|
||||
],
|
||||
"required": ["type", "name", "in"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"apiKey"
|
||||
]
|
||||
"enum": ["apiKey"]
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"in": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"header",
|
||||
"query"
|
||||
]
|
||||
"enum": ["header", "query"]
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
|
@ -1330,23 +1233,15 @@
|
|||
"oauth2ImplicitSecurity": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"type",
|
||||
"flow",
|
||||
"authorizationUrl"
|
||||
],
|
||||
"required": ["type", "flow", "authorizationUrl"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"oauth2"
|
||||
]
|
||||
"enum": ["oauth2"]
|
||||
},
|
||||
"flow": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"implicit"
|
||||
]
|
||||
"enum": ["implicit"]
|
||||
},
|
||||
"scopes": {
|
||||
"$ref": "#/definitions/oauth2Scopes"
|
||||
|
@ -1368,23 +1263,15 @@
|
|||
"oauth2PasswordSecurity": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"type",
|
||||
"flow",
|
||||
"tokenUrl"
|
||||
],
|
||||
"required": ["type", "flow", "tokenUrl"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"oauth2"
|
||||
]
|
||||
"enum": ["oauth2"]
|
||||
},
|
||||
"flow": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"password"
|
||||
]
|
||||
"enum": ["password"]
|
||||
},
|
||||
"scopes": {
|
||||
"$ref": "#/definitions/oauth2Scopes"
|
||||
|
@ -1406,23 +1293,15 @@
|
|||
"oauth2ApplicationSecurity": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"type",
|
||||
"flow",
|
||||
"tokenUrl"
|
||||
],
|
||||
"required": ["type", "flow", "tokenUrl"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"oauth2"
|
||||
]
|
||||
"enum": ["oauth2"]
|
||||
},
|
||||
"flow": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"application"
|
||||
]
|
||||
"enum": ["application"]
|
||||
},
|
||||
"scopes": {
|
||||
"$ref": "#/definitions/oauth2Scopes"
|
||||
|
@ -1444,24 +1323,15 @@
|
|||
"oauth2AccessCodeSecurity": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"type",
|
||||
"flow",
|
||||
"authorizationUrl",
|
||||
"tokenUrl"
|
||||
],
|
||||
"required": ["type", "flow", "authorizationUrl", "tokenUrl"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"oauth2"
|
||||
]
|
||||
"enum": ["oauth2"]
|
||||
},
|
||||
"flow": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"accessCode"
|
||||
]
|
||||
"enum": ["accessCode"]
|
||||
},
|
||||
"scopes": {
|
||||
"$ref": "#/definitions/oauth2Scopes"
|
||||
|
@ -1518,86 +1388,68 @@
|
|||
"description": "The transfer protocol of the API.",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"http",
|
||||
"https",
|
||||
"ws",
|
||||
"wss"
|
||||
]
|
||||
"enum": ["http", "https", "ws", "wss"]
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"collectionFormat": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"csv",
|
||||
"ssv",
|
||||
"tsv",
|
||||
"pipes"
|
||||
],
|
||||
"enum": ["csv", "ssv", "tsv", "pipes"],
|
||||
"default": "csv"
|
||||
},
|
||||
"collectionFormatWithMulti": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"csv",
|
||||
"ssv",
|
||||
"tsv",
|
||||
"pipes",
|
||||
"multi"
|
||||
],
|
||||
"enum": ["csv", "ssv", "tsv", "pipes", "multi"],
|
||||
"default": "csv"
|
||||
},
|
||||
"title": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/title"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/title"
|
||||
},
|
||||
"description": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/description"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/description"
|
||||
},
|
||||
"default": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/default"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/default"
|
||||
},
|
||||
"multipleOf": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/multipleOf"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/multipleOf"
|
||||
},
|
||||
"maximum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/maximum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/maximum"
|
||||
},
|
||||
"exclusiveMaximum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMaximum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/exclusiveMaximum"
|
||||
},
|
||||
"minimum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/minimum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/minimum"
|
||||
},
|
||||
"exclusiveMinimum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/exclusiveMinimum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/exclusiveMinimum"
|
||||
},
|
||||
"maxLength": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger"
|
||||
},
|
||||
"minLength": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeIntegerDefault0"
|
||||
},
|
||||
"pattern": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/pattern"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/pattern"
|
||||
},
|
||||
"maxItems": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveInteger"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeInteger"
|
||||
},
|
||||
"minItems": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/definitions/positiveIntegerDefault0"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/definitions/nonNegativeIntegerDefault0"
|
||||
},
|
||||
"uniqueItems": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/uniqueItems"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/uniqueItems"
|
||||
},
|
||||
"enum": {
|
||||
"$ref": "http://json-schema.org/draft-04/schema#/properties/enum"
|
||||
"$ref": "http://json-schema.org/draft-07/schema#/properties/enum"
|
||||
},
|
||||
"jsonReference": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"$ref"
|
||||
],
|
||||
"required": ["$ref"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"$ref": {
|
||||
|
|
|
@ -2,16 +2,16 @@ import { CancellationToken, DataStore } from "@azure-tools/datastore";
|
|||
|
||||
import { parse } from "./literate-yaml";
|
||||
import { AutorestError } from "../logging";
|
||||
import { OperationAbortedException } from "../exceptions";
|
||||
|
||||
describe("SyntaxValidation", () => {
|
||||
let errors: AutorestError[];
|
||||
|
||||
const logger = {
|
||||
verbose: jest.fn((x) => errors.push(x)),
|
||||
info: jest.fn((x) => errors.push(x)),
|
||||
verbose: jest.fn(),
|
||||
info: jest.fn(),
|
||||
fatal: jest.fn((x) => errors.push(x)),
|
||||
trackError: jest.fn((x) => errors.push(x)),
|
||||
trackWarning: jest.fn((x) => errors.push(x)),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -24,6 +24,11 @@ export interface AutorestDiagnostic {
|
|||
* location where the problem was found.
|
||||
*/
|
||||
readonly source?: SourceLocation[];
|
||||
|
||||
/**
|
||||
* Additional details.
|
||||
*/
|
||||
readonly details?: Error | unknown;
|
||||
}
|
||||
|
||||
export interface AutorestError extends AutorestDiagnostic {}
|
||||
|
@ -52,4 +57,9 @@ export interface AutorestLogger {
|
|||
* Track an error that occurred.
|
||||
*/
|
||||
trackError(error: AutorestError): void;
|
||||
|
||||
/**
|
||||
* Track an warning that occurred.
|
||||
*/
|
||||
trackWarning(error: AutorestWarning): void;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
},
|
||||
"homepage": "https://github.com/Azure/autorest#readme",
|
||||
"dependencies": {
|
||||
"@azure-tools/datastore": "~4.1.271",
|
||||
"@azure-tools/tasks": "~3.0.0",
|
||||
"expect": "~26.6.2",
|
||||
"jest-snapshot": "~26.6.2",
|
||||
"jest": "^26.6.3"
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import { DataHandle, LineIndices } from "@azure-tools/datastore";
|
||||
import { Lazy } from "@azure-tools/tasks";
|
||||
|
||||
/**
|
||||
* Create a data handle from some string content.
|
||||
* @param content Content of the file
|
||||
* @returns DataHandle.
|
||||
*/
|
||||
export function createDataHandle(content: string): DataHandle {
|
||||
const name = "test-generated";
|
||||
return new DataHandle(`mem://${name}`, {
|
||||
name,
|
||||
identity: [name],
|
||||
artifactType: "",
|
||||
cached: content,
|
||||
metadata: {
|
||||
lineIndices: new Lazy<number[]>(() => LineIndices(content)),
|
||||
},
|
||||
});
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from "./data-store-test-utils";
|
Загрузка…
Ссылка в новой задаче