This commit is contained in:
Родитель
341a305ee7
Коммит
6122fab5a0
|
@ -92,14 +92,18 @@ export class LiveValidatorLoader implements Loader<SwaggerSpec> {
|
|||
);
|
||||
private constructor(private opts: LiveValidatorLoaderOptions) {
|
||||
setDefaultOpts(opts, {
|
||||
transformToNewSchemaFormat: false,
|
||||
transformToNewSchemaFormat: true,
|
||||
loadSuppression: Object.keys(allErrorConstants),
|
||||
});
|
||||
|
||||
this.jsonLoader = JsonLoader.create(opts);
|
||||
this.swaggerLoader = SwaggerLoader.create(opts);
|
||||
|
||||
this.schemaValidator = new AjvSchemaValidator(this.jsonLoader);
|
||||
this.schemaValidator = new AjvSchemaValidator(this.jsonLoader, {
|
||||
strictTypes: false,
|
||||
strict: false,
|
||||
strictTuples: false
|
||||
});
|
||||
|
||||
this.transformContext = getTransformContext(this.jsonLoader, this.schemaValidator, [
|
||||
xmsPathsTransformer,
|
||||
|
@ -168,8 +172,7 @@ export class LiveValidatorLoader implements Loader<SwaggerSpec> {
|
|||
if (param.required) {
|
||||
copyInfo(param, schema);
|
||||
this.addRequiredToSchema(schema, "body");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
operation._bodyTransform = bodyTransformIfNotRequiredAndEmpty;
|
||||
}
|
||||
break;
|
||||
|
@ -272,11 +275,10 @@ const parameterTransform = {
|
|||
const bodyTransformIfNotRequiredAndEmpty = (body: any) => {
|
||||
if (body && Object.keys(body).length === 0 && body.constructor === Object) {
|
||||
return undefined;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return body;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const addParamTransform = (it: Operation | Response, param: Parameter) => {
|
||||
const transform = parameterTransform[param.type! as keyof typeof parameterTransform];
|
||||
|
|
|
@ -79,8 +79,10 @@ export class RequestResponse {
|
|||
}
|
||||
|
||||
export const requestResponseDefinition: Schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
liveRequest: {
|
||||
type: "object",
|
||||
required: ["url", "method"],
|
||||
properties: {
|
||||
headers: {
|
||||
|
@ -90,6 +92,7 @@ export const requestResponseDefinition: Schema = {
|
|||
},
|
||||
},
|
||||
query: {
|
||||
type: "object",
|
||||
nullable: true,
|
||||
additionalProperties: {
|
||||
oneOf: [
|
||||
|
@ -112,23 +115,45 @@ export const requestResponseDefinition: Schema = {
|
|||
type: "string",
|
||||
},
|
||||
body: {
|
||||
nullable: true,
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
},
|
||||
{
|
||||
type: "array",
|
||||
},
|
||||
{
|
||||
type: "null",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
liveResponse: {
|
||||
type: "object",
|
||||
required: ["statusCode"],
|
||||
properties: {
|
||||
statusCode: {
|
||||
type: "string",
|
||||
},
|
||||
headers: {
|
||||
type: "object",
|
||||
additionalProperties: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
body: {
|
||||
nullable: true,
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
},
|
||||
{
|
||||
type: "array",
|
||||
},
|
||||
{
|
||||
type: "null",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -21,7 +21,7 @@ interface FileCache {
|
|||
mockName: string;
|
||||
}
|
||||
|
||||
export const $id = "id";
|
||||
export const $id = "$id";
|
||||
|
||||
export class JsonLoader implements Loader<Json> {
|
||||
private fileLoader: FileLoader;
|
||||
|
|
|
@ -195,13 +195,13 @@ interface BaseSchema {
|
|||
modelAsString?: boolean;
|
||||
values?: Array<{ value: any; description?: string; name?: string }>;
|
||||
};
|
||||
type?: string;
|
||||
type?: string | string[];
|
||||
items?: Schema | Schema[];
|
||||
}
|
||||
|
||||
export type SchemaType = "object" | "array" | "string" | "integer" | "number" | "boolean" | "null";
|
||||
export interface Schema extends BaseSchema {
|
||||
type?: SchemaType;
|
||||
type?: SchemaType | SchemaType[];
|
||||
allOf?: Schema[];
|
||||
anyOf?: Schema[];
|
||||
oneOf?: Schema[];
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { CodeGen, default as Ajv, Format, _ } from "ajv";
|
||||
import { default as Ajv, Format, _ } from "ajv";
|
||||
import { default as addAjvFormats } from "ajv-formats";
|
||||
import { JsonLoader } from "../swagger/jsonLoader";
|
||||
import { Schema } from "../swagger/swaggerTypes";
|
||||
import { xmsMutability, xmsSecret } from "../util/constants";
|
||||
|
@ -18,7 +19,7 @@ export const ajvEnableReadOnlyAndXmsMutability = (ajv: Ajv) => {
|
|||
const eq = _`===`;
|
||||
cxt.pass(_`this.isResponse || ${cxt.data} ${eq} null || ${cxt.data} ${eq} undefined`);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
ajv.addKeyword({
|
||||
|
@ -35,18 +36,22 @@ export const ajvEnableReadOnlyAndXmsMutability = (ajv: Ajv) => {
|
|||
throw new Error(`Invalid ${xmsMutability} value: ${JSON.stringify(mutability)}`);
|
||||
}
|
||||
const eq = _`===`;
|
||||
cxt.pass(_`${validInRequest ? "!" : ""}this.isResponse || ${cxt.data} ${eq} null || ${cxt.data} ${eq} undefined`);
|
||||
const cond = validInRequest ? _`!this.isResponse` : _`this.isResponse`;
|
||||
cxt.pass(_`${cond} || ${cxt.data} ${eq} null || ${cxt.data} ${eq} undefined`);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const ajvEnableXmsSecret = (ajv: Ajv) => {
|
||||
ajv.addKeyword({
|
||||
keyword: xmsSecret
|
||||
keyword: xmsSecret,
|
||||
metaSchema: { type: "boolean" } as Schema,
|
||||
inline: (it: CompilationContext, _keyword: string, isSecret: boolean) => {
|
||||
const data = `data${it.dataLevel || ""}`;
|
||||
return isSecret ? `!this.isResponse || ${data} === null || ${data} === undefined` : "1";
|
||||
code: (ctx) => {
|
||||
const isSecret = ctx.schema;
|
||||
if (isSecret) {
|
||||
const eq = _`===`;
|
||||
ctx.pass(_`!this.isResponse || ${ctx.data} ${eq} null || ${ctx.data} ${eq} undefined`);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -102,36 +107,8 @@ export const ajvEnableDurationFormat = (ajv: Ajv) => {
|
|||
});
|
||||
};
|
||||
|
||||
// for (const keyword of [
|
||||
// "name",
|
||||
// "in",
|
||||
// "example",
|
||||
// "parameters",
|
||||
// "externalDocs",
|
||||
// "x-nullable",
|
||||
// "x-ms-enum",
|
||||
// "x-ms-azure-resource",
|
||||
// "x-ms-parameter-location",
|
||||
// "x-ms-client-name",
|
||||
// "x-ms-external",
|
||||
// "x-ms-skip-url-encoding",
|
||||
// "x-ms-client-flatten",
|
||||
// "x-ms-api-version",
|
||||
// "x-ms-parameter-grouping",
|
||||
// "x-ms-discriminator-value",
|
||||
// "x-ms-client-request-id",
|
||||
// "x-apim-code-nillable",
|
||||
// "x-new-pattern",
|
||||
// "x-previous-pattern",
|
||||
// "x-comment",
|
||||
// "x-abstract",
|
||||
// "allowEmptyValue",
|
||||
// "collectionFormat",
|
||||
// ]) {
|
||||
// ajv.addKeyword(keyword, {});
|
||||
// }
|
||||
|
||||
export const ajvEnableAll = (ajv: Ajv, jsonLoader: JsonLoader) => {
|
||||
addAjvFormats(ajv);
|
||||
ajvEnableDiscriminatorMap(ajv, jsonLoader);
|
||||
ajvEnableXmsSecret(ajv);
|
||||
ajvEnableReadOnlyAndXmsMutability(ajv);
|
||||
|
@ -141,4 +118,33 @@ export const ajvEnableAll = (ajv: Ajv, jsonLoader: JsonLoader) => {
|
|||
ajvEnableDateTimeRfc1123Format(ajv);
|
||||
ajvAddFormatsDefaultValidation(ajv, "string", ["byte", "password", "file"]);
|
||||
ajvAddFormatsDefaultValidation(ajv, "number", ["double", "float", "decimal"]);
|
||||
ajv.addVocabulary([
|
||||
"name",
|
||||
"in",
|
||||
"example",
|
||||
"parameters",
|
||||
"externalDocs",
|
||||
"x-nullable",
|
||||
"x-ms-enum",
|
||||
"x-ms-azure-resource",
|
||||
"x-ms-parameter-location",
|
||||
"x-ms-client-name",
|
||||
"x-ms-external",
|
||||
"x-ms-examples",
|
||||
"x-ms-skip-url-encoding",
|
||||
"x-ms-client-flatten",
|
||||
"x-ms-api-version",
|
||||
"x-ms-parameter-grouping",
|
||||
"x-ms-discriminator-value",
|
||||
"x-ms-client-request-id",
|
||||
"x-apim-code-nillable",
|
||||
"x-new-pattern",
|
||||
"x-previous-pattern",
|
||||
"x-comment",
|
||||
"x-abstract",
|
||||
"allowEmptyValue",
|
||||
"collectionFormat",
|
||||
"_skipError",
|
||||
"discriminator",
|
||||
]);
|
||||
};
|
||||
|
|
|
@ -6,7 +6,10 @@ export const ajvEnableDiscriminatorMap = (ajv: Ajv, loader: JsonLoader) => {
|
|||
ajv.addKeyword({
|
||||
keyword: "discriminatorMap",
|
||||
errors: "full",
|
||||
metaSchema: { type: "object", additionalProperty: { type: "object,null" } },
|
||||
metaSchema: {
|
||||
type: "object",
|
||||
additionalProperties: { type: "object", nullable: true },
|
||||
},
|
||||
|
||||
compile(schemas: { [key: string]: Schema }, parentSch) {
|
||||
const parentSchema = parentSch as Schema;
|
||||
|
|
|
@ -28,8 +28,6 @@ export class AjvSchemaValidator implements SchemaValidator {
|
|||
|
||||
public constructor(loader: JsonLoader, options?: Options) {
|
||||
this.ajv = new Ajv({
|
||||
// tslint:disable-next-line: no-submodule-imports
|
||||
meta: require("ajv/lib/refs/json-schema-draft-04.json"),
|
||||
strict: true,
|
||||
strictTypes: true,
|
||||
strictTuples: true,
|
||||
|
|
|
@ -49,6 +49,9 @@ const transformNullable = (s: Schema, jsonLoader: JsonLoader, defaultNullable?:
|
|||
|
||||
// Originally it's not nullable
|
||||
if (nullable === false) {
|
||||
if (sch.type === undefined) {
|
||||
sch.type = "object";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -66,6 +69,9 @@ const transformNullable = (s: Schema, jsonLoader: JsonLoader, defaultNullable?:
|
|||
} as Schema;
|
||||
} else {
|
||||
sch.nullable = true;
|
||||
if (sch.type === undefined) {
|
||||
sch.type = "object";
|
||||
}
|
||||
return sch;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@ export const pureObjectTransformer: GlobalTransformer = {
|
|||
(sch.properties === undefined || Object.keys(sch.properties).length === 0) &&
|
||||
sch.additionalProperties === undefined
|
||||
) {
|
||||
delete sch.type;
|
||||
sch.type = ["object", "array"]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -2543,6 +2543,14 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"ajv-formats": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-0.6.1.tgz",
|
||||
"integrity": "sha512-Zze3O7jGabuY4ospj2s8Jvjf5aGNaiwrFRqEdWdHs9oJd6IFXuWuS3ZHbJjyJvkjlDGncGQEBYnPRY9DoyaXgA==",
|
||||
"requires": {
|
||||
"ajv": "^7.0.0-beta.7"
|
||||
}
|
||||
},
|
||||
"amdefine": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
"@microsoft.azure/autorest-extension-base": "1.0.13",
|
||||
"@azure-tools/openapi-tools-common": "^1.2.2",
|
||||
"ajv": "7.0.0-beta.8",
|
||||
"ajv-formats": "^0.6.1",
|
||||
"commonmark": "^0.29.0",
|
||||
"glob": "^7.1.2",
|
||||
"globby": "^9.2.0",
|
||||
|
|
Загрузка…
Ссылка в новой задаче