@microsoft/m365-spec-parser 0.2.4 → 0.2.5-alpha.038ce65fb.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.esm2017.js +176 -193
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +299 -276
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +176 -193
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +302 -277
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/constants.d.ts +3 -4
- package/dist/src/interfaces.d.ts +10 -3
- package/dist/src/manifestUpdater.d.ts +3 -3
- package/dist/src/specParser.d.ts +2 -0
- package/dist/src/utils.d.ts +6 -3
- package/package.json +4 -4
package/dist/index.esm2017.js
CHANGED
|
@@ -32,11 +32,8 @@ var ErrorType;
|
|
|
32
32
|
ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
|
|
33
33
|
ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
|
|
34
34
|
ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
|
|
35
|
-
ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
|
|
36
35
|
ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
|
|
37
36
|
ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
|
|
38
|
-
ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
|
|
39
|
-
ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
|
|
40
37
|
ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
|
|
41
38
|
ErrorType["NoParameter"] = "no-parameter";
|
|
42
39
|
ErrorType["NoAPIInfo"] = "no-api-info";
|
|
@@ -56,6 +53,7 @@ var WarningType;
|
|
|
56
53
|
WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
|
|
57
54
|
WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
|
|
58
55
|
WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
|
|
56
|
+
WarningType["UnsupportedAuthType"] = "unsupported-auth-type";
|
|
59
57
|
WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
|
|
60
58
|
WarningType["Unknown"] = "unknown";
|
|
61
59
|
})(WarningType || (WarningType = {}));
|
|
@@ -103,6 +101,7 @@ ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please conve
|
|
|
103
101
|
ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
|
|
104
102
|
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
105
103
|
ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
|
|
104
|
+
ConstantString.AuthTypeIsNotSupported = "Unsupported authorization type in API '%s'. No authorization will be used.";
|
|
106
105
|
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
107
106
|
ConstantString.FuncDescriptionTooLong = "The description of the function '%s' is too long. The current length is %s characters, while the maximum allowed length is %s characters.";
|
|
108
107
|
ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
|
|
@@ -112,17 +111,12 @@ ConstantString.WrappedCardResponseLayout = "list";
|
|
|
112
111
|
ConstantString.GetMethod = "get";
|
|
113
112
|
ConstantString.PostMethod = "post";
|
|
114
113
|
ConstantString.AdaptiveCardVersion = "1.5";
|
|
115
|
-
ConstantString.AdaptiveCardSchema = "
|
|
114
|
+
ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
|
|
116
115
|
ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
117
116
|
ConstantString.TextBlockType = "TextBlock";
|
|
118
117
|
ConstantString.ImageType = "Image";
|
|
119
118
|
ConstantString.ContainerType = "Container";
|
|
120
|
-
ConstantString.RegistrationIdPostfix =
|
|
121
|
-
apiKey: "REGISTRATION_ID",
|
|
122
|
-
oauth2: "CONFIGURATION_ID",
|
|
123
|
-
http: "REGISTRATION_ID",
|
|
124
|
-
openIdConnect: "REGISTRATION_ID",
|
|
125
|
-
};
|
|
119
|
+
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
126
120
|
ConstantString.ResponseCodeFor20X = [
|
|
127
121
|
"200",
|
|
128
122
|
"201",
|
|
@@ -134,6 +128,7 @@ ConstantString.ResponseCodeFor20X = [
|
|
|
134
128
|
"207",
|
|
135
129
|
"208",
|
|
136
130
|
"226",
|
|
131
|
+
"2XX",
|
|
137
132
|
"default",
|
|
138
133
|
];
|
|
139
134
|
ConstantString.AllOperationMethods = [
|
|
@@ -191,17 +186,6 @@ ConstantString.PluginManifestSchema = "https://developer.microsoft.com/json-sche
|
|
|
191
186
|
|
|
192
187
|
// Copyright (c) Microsoft Corporation.
|
|
193
188
|
class Utils {
|
|
194
|
-
static hasNestedObjectInSchema(schema) {
|
|
195
|
-
if (this.isObjectSchema(schema)) {
|
|
196
|
-
for (const property in schema.properties) {
|
|
197
|
-
const nestedSchema = schema.properties[property];
|
|
198
|
-
if (this.isObjectSchema(nestedSchema)) {
|
|
199
|
-
return true;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return false;
|
|
204
|
-
}
|
|
205
189
|
static isObjectSchema(schema) {
|
|
206
190
|
return schema.type === "object" || (!schema.type && !!schema.properties);
|
|
207
191
|
}
|
|
@@ -214,11 +198,32 @@ class Utils {
|
|
|
214
198
|
static isAPIKeyAuth(authScheme) {
|
|
215
199
|
return authScheme.type === "apiKey";
|
|
216
200
|
}
|
|
201
|
+
static isAPIKeyAuthButNotInCookie(authScheme) {
|
|
202
|
+
return authScheme.type === "apiKey" && authScheme.in !== "cookie";
|
|
203
|
+
}
|
|
217
204
|
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
218
205
|
return !!(authScheme.type === "oauth2" &&
|
|
219
206
|
authScheme.flows &&
|
|
220
207
|
authScheme.flows.authorizationCode);
|
|
221
208
|
}
|
|
209
|
+
static isNotSupportedAuth(authSchemeArray) {
|
|
210
|
+
if (authSchemeArray.length === 0) {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
for (const auths of authSchemeArray) {
|
|
217
|
+
if (auths.length === 1) {
|
|
218
|
+
if (Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme) ||
|
|
219
|
+
Utils.isBearerTokenAuth(auths[0].authScheme) ||
|
|
220
|
+
Utils.isAPIKeyAuthButNotInCookie(auths[0].authScheme)) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
222
227
|
static getAuthArray(securities, spec) {
|
|
223
228
|
var _a;
|
|
224
229
|
const result = [];
|
|
@@ -243,6 +248,20 @@ class Utils {
|
|
|
243
248
|
result.sort((a, b) => a[0].name.localeCompare(b[0].name));
|
|
244
249
|
return result;
|
|
245
250
|
}
|
|
251
|
+
static getAuthMap(spec) {
|
|
252
|
+
const authMap = {};
|
|
253
|
+
for (const url in spec.paths) {
|
|
254
|
+
for (const method in spec.paths[url]) {
|
|
255
|
+
const operation = spec.paths[url][method];
|
|
256
|
+
const authArray = Utils.getAuthArray(operation.security, spec);
|
|
257
|
+
if (authArray && authArray.length > 0) {
|
|
258
|
+
const currentAuth = authArray[0][0];
|
|
259
|
+
authMap[operation.operationId] = currentAuth;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return authMap;
|
|
264
|
+
}
|
|
246
265
|
static getAuthInfo(spec) {
|
|
247
266
|
let authInfo = undefined;
|
|
248
267
|
for (const url in spec.paths) {
|
|
@@ -271,27 +290,33 @@ class Utils {
|
|
|
271
290
|
let multipleMediaType = false;
|
|
272
291
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
273
292
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
274
|
-
if (responseObject
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
else {
|
|
287
|
-
return { json, multipleMediaType };
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
}
|
|
293
|
+
if (!responseObject) {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
|
|
297
|
+
if (!allowMultipleMediaType && multipleMediaType) {
|
|
298
|
+
json = {};
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
const mediaObj = Utils.getJsonContentType(responseObject);
|
|
302
|
+
if (Object.keys(mediaObj).length > 0) {
|
|
303
|
+
json = mediaObj;
|
|
304
|
+
return { json, multipleMediaType };
|
|
291
305
|
}
|
|
292
306
|
}
|
|
293
307
|
return { json, multipleMediaType };
|
|
294
308
|
}
|
|
309
|
+
static getJsonContentType(responseObject) {
|
|
310
|
+
if (responseObject.content) {
|
|
311
|
+
for (const contentType of Object.keys(responseObject.content)) {
|
|
312
|
+
// json media type can also be "application/json; charset=utf-8"
|
|
313
|
+
if (contentType.indexOf("application/json") >= 0) {
|
|
314
|
+
return responseObject.content[contentType];
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return {};
|
|
319
|
+
}
|
|
295
320
|
static convertPathToCamelCase(path) {
|
|
296
321
|
const pathSegments = path.split(/[./{]/);
|
|
297
322
|
const camelCaseSegments = pathSegments.map((segment) => {
|
|
@@ -327,7 +352,7 @@ class Utils {
|
|
|
327
352
|
}
|
|
328
353
|
return newStr;
|
|
329
354
|
}
|
|
330
|
-
static checkServerUrl(servers) {
|
|
355
|
+
static checkServerUrl(servers, allowHttp = false) {
|
|
331
356
|
const errors = [];
|
|
332
357
|
let serverUrl;
|
|
333
358
|
try {
|
|
@@ -350,8 +375,7 @@ class Utils {
|
|
|
350
375
|
data: servers,
|
|
351
376
|
});
|
|
352
377
|
}
|
|
353
|
-
else if (protocol !== "https:") {
|
|
354
|
-
// Http server url is not supported
|
|
378
|
+
else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
|
|
355
379
|
const protocolString = protocol.slice(0, -1);
|
|
356
380
|
errors.push({
|
|
357
381
|
type: ErrorType.UrlProtocolNotSupported,
|
|
@@ -367,10 +391,11 @@ class Utils {
|
|
|
367
391
|
let hasTopLevelServers = false;
|
|
368
392
|
let hasPathLevelServers = false;
|
|
369
393
|
let hasOperationLevelServers = false;
|
|
394
|
+
const allowHttp = options.projectType === ProjectType.Copilot;
|
|
370
395
|
if (spec.servers && spec.servers.length >= 1) {
|
|
371
396
|
hasTopLevelServers = true;
|
|
372
397
|
// for multiple server, we only use the first url
|
|
373
|
-
const serverErrors = Utils.checkServerUrl(spec.servers);
|
|
398
|
+
const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
|
|
374
399
|
errors.push(...serverErrors);
|
|
375
400
|
}
|
|
376
401
|
const paths = spec.paths;
|
|
@@ -378,7 +403,7 @@ class Utils {
|
|
|
378
403
|
const methods = paths[path];
|
|
379
404
|
if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
|
|
380
405
|
hasPathLevelServers = true;
|
|
381
|
-
const serverErrors = Utils.checkServerUrl(methods.servers);
|
|
406
|
+
const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
|
|
382
407
|
errors.push(...serverErrors);
|
|
383
408
|
}
|
|
384
409
|
for (const method in methods) {
|
|
@@ -386,7 +411,7 @@ class Utils {
|
|
|
386
411
|
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
387
412
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
388
413
|
hasOperationLevelServers = true;
|
|
389
|
-
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
414
|
+
const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
|
|
390
415
|
errors.push(...serverErrors);
|
|
391
416
|
}
|
|
392
417
|
}
|
|
@@ -675,22 +700,6 @@ class Validator {
|
|
|
675
700
|
}
|
|
676
701
|
return result;
|
|
677
702
|
}
|
|
678
|
-
validateResponse(method, path) {
|
|
679
|
-
const result = { isValid: true, reason: [] };
|
|
680
|
-
const operationObject = this.spec.paths[path][method];
|
|
681
|
-
const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
|
|
682
|
-
if (this.options.projectType === ProjectType.SME) {
|
|
683
|
-
// only support response body only contains “application/json” content type
|
|
684
|
-
if (multipleMediaType) {
|
|
685
|
-
result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
|
|
686
|
-
}
|
|
687
|
-
else if (Object.keys(json).length === 0) {
|
|
688
|
-
// response body should not be empty
|
|
689
|
-
result.reason.push(ErrorType.ResponseJsonIsEmpty);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
return result;
|
|
693
|
-
}
|
|
694
703
|
validateServer(method, path) {
|
|
695
704
|
const result = { isValid: true, reason: [] };
|
|
696
705
|
const serverObj = Utils.getServerObject(this.spec, method, path);
|
|
@@ -699,8 +708,8 @@ class Validator {
|
|
|
699
708
|
result.reason.push(ErrorType.NoServerInformation);
|
|
700
709
|
}
|
|
701
710
|
else {
|
|
702
|
-
|
|
703
|
-
const serverValidateResult = Utils.checkServerUrl([serverObj]);
|
|
711
|
+
const allowHttp = this.projectType === ProjectType.Copilot;
|
|
712
|
+
const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
|
|
704
713
|
result.reason.push(...serverValidateResult.map((item) => item.type));
|
|
705
714
|
}
|
|
706
715
|
return result;
|
|
@@ -723,6 +732,9 @@ class Validator {
|
|
|
723
732
|
reason: [ErrorType.MultipleAuthNotSupported],
|
|
724
733
|
};
|
|
725
734
|
}
|
|
735
|
+
if (this.projectType === ProjectType.Copilot) {
|
|
736
|
+
return { isValid: true, reason: [] };
|
|
737
|
+
}
|
|
726
738
|
for (const auths of authSchemeArray) {
|
|
727
739
|
if (auths.length === 1) {
|
|
728
740
|
if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
@@ -735,114 +747,6 @@ class Validator {
|
|
|
735
747
|
}
|
|
736
748
|
return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
|
|
737
749
|
}
|
|
738
|
-
checkPostBodySchema(schema, isRequired = false) {
|
|
739
|
-
var _a;
|
|
740
|
-
const paramResult = {
|
|
741
|
-
requiredNum: 0,
|
|
742
|
-
optionalNum: 0,
|
|
743
|
-
isValid: true,
|
|
744
|
-
reason: [],
|
|
745
|
-
};
|
|
746
|
-
if (Object.keys(schema).length === 0) {
|
|
747
|
-
return paramResult;
|
|
748
|
-
}
|
|
749
|
-
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
750
|
-
const isCopilot = this.projectType === ProjectType.Copilot;
|
|
751
|
-
if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
|
|
752
|
-
paramResult.isValid = false;
|
|
753
|
-
paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
|
|
754
|
-
return paramResult;
|
|
755
|
-
}
|
|
756
|
-
if (schema.type === "string" ||
|
|
757
|
-
schema.type === "integer" ||
|
|
758
|
-
schema.type === "boolean" ||
|
|
759
|
-
schema.type === "number") {
|
|
760
|
-
if (isRequiredWithoutDefault) {
|
|
761
|
-
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
762
|
-
}
|
|
763
|
-
else {
|
|
764
|
-
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
else if (Utils.isObjectSchema(schema)) {
|
|
768
|
-
const { properties } = schema;
|
|
769
|
-
for (const property in properties) {
|
|
770
|
-
let isRequired = false;
|
|
771
|
-
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
772
|
-
isRequired = true;
|
|
773
|
-
}
|
|
774
|
-
const result = this.checkPostBodySchema(properties[property], isRequired);
|
|
775
|
-
paramResult.requiredNum += result.requiredNum;
|
|
776
|
-
paramResult.optionalNum += result.optionalNum;
|
|
777
|
-
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
778
|
-
paramResult.reason.push(...result.reason);
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
else {
|
|
782
|
-
if (isRequiredWithoutDefault && !isCopilot) {
|
|
783
|
-
paramResult.isValid = false;
|
|
784
|
-
paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
return paramResult;
|
|
788
|
-
}
|
|
789
|
-
checkParamSchema(paramObject) {
|
|
790
|
-
const paramResult = {
|
|
791
|
-
requiredNum: 0,
|
|
792
|
-
optionalNum: 0,
|
|
793
|
-
isValid: true,
|
|
794
|
-
reason: [],
|
|
795
|
-
};
|
|
796
|
-
if (!paramObject) {
|
|
797
|
-
return paramResult;
|
|
798
|
-
}
|
|
799
|
-
const isCopilot = this.projectType === ProjectType.Copilot;
|
|
800
|
-
for (let i = 0; i < paramObject.length; i++) {
|
|
801
|
-
const param = paramObject[i];
|
|
802
|
-
const schema = param.schema;
|
|
803
|
-
if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
|
|
804
|
-
paramResult.isValid = false;
|
|
805
|
-
paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
|
|
806
|
-
continue;
|
|
807
|
-
}
|
|
808
|
-
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
809
|
-
if (isCopilot) {
|
|
810
|
-
if (isRequiredWithoutDefault) {
|
|
811
|
-
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
812
|
-
}
|
|
813
|
-
else {
|
|
814
|
-
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
815
|
-
}
|
|
816
|
-
continue;
|
|
817
|
-
}
|
|
818
|
-
if (param.in === "header" || param.in === "cookie") {
|
|
819
|
-
if (isRequiredWithoutDefault) {
|
|
820
|
-
paramResult.isValid = false;
|
|
821
|
-
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
822
|
-
}
|
|
823
|
-
continue;
|
|
824
|
-
}
|
|
825
|
-
if (schema.type !== "boolean" &&
|
|
826
|
-
schema.type !== "string" &&
|
|
827
|
-
schema.type !== "number" &&
|
|
828
|
-
schema.type !== "integer") {
|
|
829
|
-
if (isRequiredWithoutDefault) {
|
|
830
|
-
paramResult.isValid = false;
|
|
831
|
-
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
832
|
-
}
|
|
833
|
-
continue;
|
|
834
|
-
}
|
|
835
|
-
if (param.in === "query" || param.in === "path") {
|
|
836
|
-
if (isRequiredWithoutDefault) {
|
|
837
|
-
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
838
|
-
}
|
|
839
|
-
else {
|
|
840
|
-
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
return paramResult;
|
|
845
|
-
}
|
|
846
750
|
}
|
|
847
751
|
|
|
848
752
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -852,7 +756,6 @@ class CopilotValidator extends Validator {
|
|
|
852
756
|
this.projectType = ProjectType.Copilot;
|
|
853
757
|
this.options = options;
|
|
854
758
|
this.spec = spec;
|
|
855
|
-
this.checkCircularReference();
|
|
856
759
|
}
|
|
857
760
|
validateSpec() {
|
|
858
761
|
const result = { errors: [], warnings: [] };
|
|
@@ -878,10 +781,6 @@ class CopilotValidator extends Validator {
|
|
|
878
781
|
if (!methodAndPathResult.isValid) {
|
|
879
782
|
return methodAndPathResult;
|
|
880
783
|
}
|
|
881
|
-
const circularReferenceResult = this.validateCircularReference(method, path);
|
|
882
|
-
if (!circularReferenceResult.isValid) {
|
|
883
|
-
return circularReferenceResult;
|
|
884
|
-
}
|
|
885
784
|
const operationObject = this.spec.paths[path][method];
|
|
886
785
|
// validate auth
|
|
887
786
|
const authCheckResult = this.validateAuth(method, path);
|
|
@@ -893,24 +792,6 @@ class CopilotValidator extends Validator {
|
|
|
893
792
|
// validate server
|
|
894
793
|
const validateServerResult = this.validateServer(method, path);
|
|
895
794
|
result.reason.push(...validateServerResult.reason);
|
|
896
|
-
// validate response
|
|
897
|
-
const validateResponseResult = this.validateResponse(method, path);
|
|
898
|
-
result.reason.push(...validateResponseResult.reason);
|
|
899
|
-
// validate requestBody
|
|
900
|
-
const requestBody = operationObject.requestBody;
|
|
901
|
-
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
902
|
-
if (requestJsonBody) {
|
|
903
|
-
const requestBodySchema = requestJsonBody.schema;
|
|
904
|
-
if (!Utils.isObjectSchema(requestBodySchema)) {
|
|
905
|
-
result.reason.push(ErrorType.PostBodySchemaIsNotJson);
|
|
906
|
-
}
|
|
907
|
-
const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
|
|
908
|
-
result.reason.push(...requestBodyParamResult.reason);
|
|
909
|
-
}
|
|
910
|
-
// validate parameters
|
|
911
|
-
const paramObject = operationObject.parameters;
|
|
912
|
-
const paramResult = this.checkParamSchema(paramObject);
|
|
913
|
-
result.reason.push(...paramResult.reason);
|
|
914
795
|
if (result.reason.length > 0) {
|
|
915
796
|
result.isValid = false;
|
|
916
797
|
}
|
|
@@ -1002,6 +883,108 @@ class SMEValidator extends Validator {
|
|
|
1002
883
|
}
|
|
1003
884
|
return result;
|
|
1004
885
|
}
|
|
886
|
+
validateResponse(method, path) {
|
|
887
|
+
const result = { isValid: true, reason: [] };
|
|
888
|
+
const operationObject = this.spec.paths[path][method];
|
|
889
|
+
const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
|
|
890
|
+
// only support response body only contains “application/json” content type
|
|
891
|
+
if (multipleMediaType) {
|
|
892
|
+
result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
|
|
893
|
+
}
|
|
894
|
+
else if (Object.keys(json).length === 0) {
|
|
895
|
+
// response body should not be empty
|
|
896
|
+
result.reason.push(ErrorType.ResponseJsonIsEmpty);
|
|
897
|
+
}
|
|
898
|
+
return result;
|
|
899
|
+
}
|
|
900
|
+
checkPostBodySchema(schema, isRequired = false) {
|
|
901
|
+
var _a;
|
|
902
|
+
const paramResult = {
|
|
903
|
+
requiredNum: 0,
|
|
904
|
+
optionalNum: 0,
|
|
905
|
+
isValid: true,
|
|
906
|
+
reason: [],
|
|
907
|
+
};
|
|
908
|
+
if (Object.keys(schema).length === 0) {
|
|
909
|
+
return paramResult;
|
|
910
|
+
}
|
|
911
|
+
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
912
|
+
const isCopilot = this.projectType === ProjectType.Copilot;
|
|
913
|
+
if (schema.type === "string" ||
|
|
914
|
+
schema.type === "integer" ||
|
|
915
|
+
schema.type === "boolean" ||
|
|
916
|
+
schema.type === "number") {
|
|
917
|
+
if (isRequiredWithoutDefault) {
|
|
918
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
919
|
+
}
|
|
920
|
+
else {
|
|
921
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
else if (Utils.isObjectSchema(schema)) {
|
|
925
|
+
const { properties } = schema;
|
|
926
|
+
for (const property in properties) {
|
|
927
|
+
let isRequired = false;
|
|
928
|
+
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
929
|
+
isRequired = true;
|
|
930
|
+
}
|
|
931
|
+
const result = this.checkPostBodySchema(properties[property], isRequired);
|
|
932
|
+
paramResult.requiredNum += result.requiredNum;
|
|
933
|
+
paramResult.optionalNum += result.optionalNum;
|
|
934
|
+
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
935
|
+
paramResult.reason.push(...result.reason);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
else {
|
|
939
|
+
if (isRequiredWithoutDefault && !isCopilot) {
|
|
940
|
+
paramResult.isValid = false;
|
|
941
|
+
paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
return paramResult;
|
|
945
|
+
}
|
|
946
|
+
checkParamSchema(paramObject) {
|
|
947
|
+
const paramResult = {
|
|
948
|
+
requiredNum: 0,
|
|
949
|
+
optionalNum: 0,
|
|
950
|
+
isValid: true,
|
|
951
|
+
reason: [],
|
|
952
|
+
};
|
|
953
|
+
if (!paramObject) {
|
|
954
|
+
return paramResult;
|
|
955
|
+
}
|
|
956
|
+
for (let i = 0; i < paramObject.length; i++) {
|
|
957
|
+
const param = paramObject[i];
|
|
958
|
+
const schema = param.schema;
|
|
959
|
+
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
960
|
+
if (param.in === "header" || param.in === "cookie") {
|
|
961
|
+
if (isRequiredWithoutDefault) {
|
|
962
|
+
paramResult.isValid = false;
|
|
963
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
964
|
+
}
|
|
965
|
+
continue;
|
|
966
|
+
}
|
|
967
|
+
if (schema.type !== "boolean" &&
|
|
968
|
+
schema.type !== "string" &&
|
|
969
|
+
schema.type !== "number" &&
|
|
970
|
+
schema.type !== "integer") {
|
|
971
|
+
if (isRequiredWithoutDefault) {
|
|
972
|
+
paramResult.isValid = false;
|
|
973
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
974
|
+
}
|
|
975
|
+
continue;
|
|
976
|
+
}
|
|
977
|
+
if (param.in === "query" || param.in === "path") {
|
|
978
|
+
if (isRequiredWithoutDefault) {
|
|
979
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
980
|
+
}
|
|
981
|
+
else {
|
|
982
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
return paramResult;
|
|
987
|
+
}
|
|
1005
988
|
validateParamCount(postBodyResult, paramResult) {
|
|
1006
989
|
const result = { isValid: true, reason: [] };
|
|
1007
990
|
const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
|