@microsoft/m365-spec-parser 0.2.4 → 0.2.5-alpha.4da5c3b2d.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.esm5.js
CHANGED
|
@@ -62,11 +62,8 @@ var ErrorType;
|
|
|
62
62
|
ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
|
|
63
63
|
ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
|
|
64
64
|
ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
|
|
65
|
-
ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
|
|
66
65
|
ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
|
|
67
66
|
ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
|
|
68
|
-
ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
|
|
69
|
-
ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
|
|
70
67
|
ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
|
|
71
68
|
ErrorType["NoParameter"] = "no-parameter";
|
|
72
69
|
ErrorType["NoAPIInfo"] = "no-api-info";
|
|
@@ -86,6 +83,7 @@ var WarningType;
|
|
|
86
83
|
WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
|
|
87
84
|
WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
|
|
88
85
|
WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
|
|
86
|
+
WarningType["UnsupportedAuthType"] = "unsupported-auth-type";
|
|
89
87
|
WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
|
|
90
88
|
WarningType["Unknown"] = "unknown";
|
|
91
89
|
})(WarningType || (WarningType = {}));
|
|
@@ -133,6 +131,7 @@ ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please conve
|
|
|
133
131
|
ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
|
|
134
132
|
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
135
133
|
ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
|
|
134
|
+
ConstantString.AuthTypeIsNotSupported = "Unsupported authorization type in API '%s'. No authorization will be used.";
|
|
136
135
|
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
137
136
|
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.";
|
|
138
137
|
ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
|
|
@@ -142,17 +141,12 @@ ConstantString.WrappedCardResponseLayout = "list";
|
|
|
142
141
|
ConstantString.GetMethod = "get";
|
|
143
142
|
ConstantString.PostMethod = "post";
|
|
144
143
|
ConstantString.AdaptiveCardVersion = "1.5";
|
|
145
|
-
ConstantString.AdaptiveCardSchema = "
|
|
144
|
+
ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
|
|
146
145
|
ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
147
146
|
ConstantString.TextBlockType = "TextBlock";
|
|
148
147
|
ConstantString.ImageType = "Image";
|
|
149
148
|
ConstantString.ContainerType = "Container";
|
|
150
|
-
ConstantString.RegistrationIdPostfix =
|
|
151
|
-
apiKey: "REGISTRATION_ID",
|
|
152
|
-
oauth2: "CONFIGURATION_ID",
|
|
153
|
-
http: "REGISTRATION_ID",
|
|
154
|
-
openIdConnect: "REGISTRATION_ID",
|
|
155
|
-
};
|
|
149
|
+
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
156
150
|
ConstantString.ResponseCodeFor20X = [
|
|
157
151
|
"200",
|
|
158
152
|
"201",
|
|
@@ -164,6 +158,7 @@ ConstantString.ResponseCodeFor20X = [
|
|
|
164
158
|
"207",
|
|
165
159
|
"208",
|
|
166
160
|
"226",
|
|
161
|
+
"2XX",
|
|
167
162
|
"default",
|
|
168
163
|
];
|
|
169
164
|
ConstantString.AllOperationMethods = [
|
|
@@ -221,17 +216,6 @@ ConstantString.PluginManifestSchema = "https://developer.microsoft.com/json-sche
|
|
|
221
216
|
|
|
222
217
|
// Copyright (c) Microsoft Corporation.
|
|
223
218
|
class Utils {
|
|
224
|
-
static hasNestedObjectInSchema(schema) {
|
|
225
|
-
if (this.isObjectSchema(schema)) {
|
|
226
|
-
for (const property in schema.properties) {
|
|
227
|
-
const nestedSchema = schema.properties[property];
|
|
228
|
-
if (this.isObjectSchema(nestedSchema)) {
|
|
229
|
-
return true;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
return false;
|
|
234
|
-
}
|
|
235
219
|
static isObjectSchema(schema) {
|
|
236
220
|
return schema.type === "object" || (!schema.type && !!schema.properties);
|
|
237
221
|
}
|
|
@@ -244,11 +228,32 @@ class Utils {
|
|
|
244
228
|
static isAPIKeyAuth(authScheme) {
|
|
245
229
|
return authScheme.type === "apiKey";
|
|
246
230
|
}
|
|
231
|
+
static isAPIKeyAuthButNotInCookie(authScheme) {
|
|
232
|
+
return authScheme.type === "apiKey" && authScheme.in !== "cookie";
|
|
233
|
+
}
|
|
247
234
|
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
248
235
|
return !!(authScheme.type === "oauth2" &&
|
|
249
236
|
authScheme.flows &&
|
|
250
237
|
authScheme.flows.authorizationCode);
|
|
251
238
|
}
|
|
239
|
+
static isNotSupportedAuth(authSchemeArray) {
|
|
240
|
+
if (authSchemeArray.length === 0) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
for (const auths of authSchemeArray) {
|
|
247
|
+
if (auths.length === 1) {
|
|
248
|
+
if (Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme) ||
|
|
249
|
+
Utils.isBearerTokenAuth(auths[0].authScheme) ||
|
|
250
|
+
Utils.isAPIKeyAuthButNotInCookie(auths[0].authScheme)) {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
252
257
|
static getAuthArray(securities, spec) {
|
|
253
258
|
var _a;
|
|
254
259
|
const result = [];
|
|
@@ -273,6 +278,20 @@ class Utils {
|
|
|
273
278
|
result.sort((a, b) => a[0].name.localeCompare(b[0].name));
|
|
274
279
|
return result;
|
|
275
280
|
}
|
|
281
|
+
static getAuthMap(spec) {
|
|
282
|
+
const authMap = {};
|
|
283
|
+
for (const url in spec.paths) {
|
|
284
|
+
for (const method in spec.paths[url]) {
|
|
285
|
+
const operation = spec.paths[url][method];
|
|
286
|
+
const authArray = Utils.getAuthArray(operation.security, spec);
|
|
287
|
+
if (authArray && authArray.length > 0) {
|
|
288
|
+
const currentAuth = authArray[0][0];
|
|
289
|
+
authMap[operation.operationId] = currentAuth;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return authMap;
|
|
294
|
+
}
|
|
276
295
|
static getAuthInfo(spec) {
|
|
277
296
|
let authInfo = undefined;
|
|
278
297
|
for (const url in spec.paths) {
|
|
@@ -301,27 +320,33 @@ class Utils {
|
|
|
301
320
|
let multipleMediaType = false;
|
|
302
321
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
303
322
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
304
|
-
if (responseObject
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
else {
|
|
317
|
-
return { json, multipleMediaType };
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
323
|
+
if (!responseObject) {
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
|
|
327
|
+
if (!allowMultipleMediaType && multipleMediaType) {
|
|
328
|
+
json = {};
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
const mediaObj = Utils.getJsonContentType(responseObject);
|
|
332
|
+
if (Object.keys(mediaObj).length > 0) {
|
|
333
|
+
json = mediaObj;
|
|
334
|
+
return { json, multipleMediaType };
|
|
321
335
|
}
|
|
322
336
|
}
|
|
323
337
|
return { json, multipleMediaType };
|
|
324
338
|
}
|
|
339
|
+
static getJsonContentType(responseObject) {
|
|
340
|
+
if (responseObject.content) {
|
|
341
|
+
for (const contentType of Object.keys(responseObject.content)) {
|
|
342
|
+
// json media type can also be "application/json; charset=utf-8"
|
|
343
|
+
if (contentType.indexOf("application/json") >= 0) {
|
|
344
|
+
return responseObject.content[contentType];
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return {};
|
|
349
|
+
}
|
|
325
350
|
static convertPathToCamelCase(path) {
|
|
326
351
|
const pathSegments = path.split(/[./{]/);
|
|
327
352
|
const camelCaseSegments = pathSegments.map((segment) => {
|
|
@@ -357,7 +382,7 @@ class Utils {
|
|
|
357
382
|
}
|
|
358
383
|
return newStr;
|
|
359
384
|
}
|
|
360
|
-
static checkServerUrl(servers) {
|
|
385
|
+
static checkServerUrl(servers, allowHttp = false) {
|
|
361
386
|
const errors = [];
|
|
362
387
|
let serverUrl;
|
|
363
388
|
try {
|
|
@@ -380,8 +405,7 @@ class Utils {
|
|
|
380
405
|
data: servers,
|
|
381
406
|
});
|
|
382
407
|
}
|
|
383
|
-
else if (protocol !== "https:") {
|
|
384
|
-
// Http server url is not supported
|
|
408
|
+
else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
|
|
385
409
|
const protocolString = protocol.slice(0, -1);
|
|
386
410
|
errors.push({
|
|
387
411
|
type: ErrorType.UrlProtocolNotSupported,
|
|
@@ -397,10 +421,11 @@ class Utils {
|
|
|
397
421
|
let hasTopLevelServers = false;
|
|
398
422
|
let hasPathLevelServers = false;
|
|
399
423
|
let hasOperationLevelServers = false;
|
|
424
|
+
const allowHttp = options.projectType === ProjectType.Copilot;
|
|
400
425
|
if (spec.servers && spec.servers.length >= 1) {
|
|
401
426
|
hasTopLevelServers = true;
|
|
402
427
|
// for multiple server, we only use the first url
|
|
403
|
-
const serverErrors = Utils.checkServerUrl(spec.servers);
|
|
428
|
+
const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
|
|
404
429
|
errors.push(...serverErrors);
|
|
405
430
|
}
|
|
406
431
|
const paths = spec.paths;
|
|
@@ -408,7 +433,7 @@ class Utils {
|
|
|
408
433
|
const methods = paths[path];
|
|
409
434
|
if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
|
|
410
435
|
hasPathLevelServers = true;
|
|
411
|
-
const serverErrors = Utils.checkServerUrl(methods.servers);
|
|
436
|
+
const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
|
|
412
437
|
errors.push(...serverErrors);
|
|
413
438
|
}
|
|
414
439
|
for (const method in methods) {
|
|
@@ -416,7 +441,7 @@ class Utils {
|
|
|
416
441
|
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
417
442
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
418
443
|
hasOperationLevelServers = true;
|
|
419
|
-
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
444
|
+
const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
|
|
420
445
|
errors.push(...serverErrors);
|
|
421
446
|
}
|
|
422
447
|
}
|
|
@@ -705,22 +730,6 @@ class Validator {
|
|
|
705
730
|
}
|
|
706
731
|
return result;
|
|
707
732
|
}
|
|
708
|
-
validateResponse(method, path) {
|
|
709
|
-
const result = { isValid: true, reason: [] };
|
|
710
|
-
const operationObject = this.spec.paths[path][method];
|
|
711
|
-
const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
|
|
712
|
-
if (this.options.projectType === ProjectType.SME) {
|
|
713
|
-
// only support response body only contains “application/json” content type
|
|
714
|
-
if (multipleMediaType) {
|
|
715
|
-
result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
|
|
716
|
-
}
|
|
717
|
-
else if (Object.keys(json).length === 0) {
|
|
718
|
-
// response body should not be empty
|
|
719
|
-
result.reason.push(ErrorType.ResponseJsonIsEmpty);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
return result;
|
|
723
|
-
}
|
|
724
733
|
validateServer(method, path) {
|
|
725
734
|
const result = { isValid: true, reason: [] };
|
|
726
735
|
const serverObj = Utils.getServerObject(this.spec, method, path);
|
|
@@ -729,8 +738,8 @@ class Validator {
|
|
|
729
738
|
result.reason.push(ErrorType.NoServerInformation);
|
|
730
739
|
}
|
|
731
740
|
else {
|
|
732
|
-
|
|
733
|
-
const serverValidateResult = Utils.checkServerUrl([serverObj]);
|
|
741
|
+
const allowHttp = this.projectType === ProjectType.Copilot;
|
|
742
|
+
const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
|
|
734
743
|
result.reason.push(...serverValidateResult.map((item) => item.type));
|
|
735
744
|
}
|
|
736
745
|
return result;
|
|
@@ -753,6 +762,9 @@ class Validator {
|
|
|
753
762
|
reason: [ErrorType.MultipleAuthNotSupported],
|
|
754
763
|
};
|
|
755
764
|
}
|
|
765
|
+
if (this.projectType === ProjectType.Copilot) {
|
|
766
|
+
return { isValid: true, reason: [] };
|
|
767
|
+
}
|
|
756
768
|
for (const auths of authSchemeArray) {
|
|
757
769
|
if (auths.length === 1) {
|
|
758
770
|
if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
@@ -765,114 +777,6 @@ class Validator {
|
|
|
765
777
|
}
|
|
766
778
|
return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
|
|
767
779
|
}
|
|
768
|
-
checkPostBodySchema(schema, isRequired = false) {
|
|
769
|
-
var _a;
|
|
770
|
-
const paramResult = {
|
|
771
|
-
requiredNum: 0,
|
|
772
|
-
optionalNum: 0,
|
|
773
|
-
isValid: true,
|
|
774
|
-
reason: [],
|
|
775
|
-
};
|
|
776
|
-
if (Object.keys(schema).length === 0) {
|
|
777
|
-
return paramResult;
|
|
778
|
-
}
|
|
779
|
-
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
780
|
-
const isCopilot = this.projectType === ProjectType.Copilot;
|
|
781
|
-
if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
|
|
782
|
-
paramResult.isValid = false;
|
|
783
|
-
paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
|
|
784
|
-
return paramResult;
|
|
785
|
-
}
|
|
786
|
-
if (schema.type === "string" ||
|
|
787
|
-
schema.type === "integer" ||
|
|
788
|
-
schema.type === "boolean" ||
|
|
789
|
-
schema.type === "number") {
|
|
790
|
-
if (isRequiredWithoutDefault) {
|
|
791
|
-
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
792
|
-
}
|
|
793
|
-
else {
|
|
794
|
-
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
else if (Utils.isObjectSchema(schema)) {
|
|
798
|
-
const { properties } = schema;
|
|
799
|
-
for (const property in properties) {
|
|
800
|
-
let isRequired = false;
|
|
801
|
-
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
802
|
-
isRequired = true;
|
|
803
|
-
}
|
|
804
|
-
const result = this.checkPostBodySchema(properties[property], isRequired);
|
|
805
|
-
paramResult.requiredNum += result.requiredNum;
|
|
806
|
-
paramResult.optionalNum += result.optionalNum;
|
|
807
|
-
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
808
|
-
paramResult.reason.push(...result.reason);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
else {
|
|
812
|
-
if (isRequiredWithoutDefault && !isCopilot) {
|
|
813
|
-
paramResult.isValid = false;
|
|
814
|
-
paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
return paramResult;
|
|
818
|
-
}
|
|
819
|
-
checkParamSchema(paramObject) {
|
|
820
|
-
const paramResult = {
|
|
821
|
-
requiredNum: 0,
|
|
822
|
-
optionalNum: 0,
|
|
823
|
-
isValid: true,
|
|
824
|
-
reason: [],
|
|
825
|
-
};
|
|
826
|
-
if (!paramObject) {
|
|
827
|
-
return paramResult;
|
|
828
|
-
}
|
|
829
|
-
const isCopilot = this.projectType === ProjectType.Copilot;
|
|
830
|
-
for (let i = 0; i < paramObject.length; i++) {
|
|
831
|
-
const param = paramObject[i];
|
|
832
|
-
const schema = param.schema;
|
|
833
|
-
if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
|
|
834
|
-
paramResult.isValid = false;
|
|
835
|
-
paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
|
|
836
|
-
continue;
|
|
837
|
-
}
|
|
838
|
-
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
839
|
-
if (isCopilot) {
|
|
840
|
-
if (isRequiredWithoutDefault) {
|
|
841
|
-
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
842
|
-
}
|
|
843
|
-
else {
|
|
844
|
-
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
845
|
-
}
|
|
846
|
-
continue;
|
|
847
|
-
}
|
|
848
|
-
if (param.in === "header" || param.in === "cookie") {
|
|
849
|
-
if (isRequiredWithoutDefault) {
|
|
850
|
-
paramResult.isValid = false;
|
|
851
|
-
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
852
|
-
}
|
|
853
|
-
continue;
|
|
854
|
-
}
|
|
855
|
-
if (schema.type !== "boolean" &&
|
|
856
|
-
schema.type !== "string" &&
|
|
857
|
-
schema.type !== "number" &&
|
|
858
|
-
schema.type !== "integer") {
|
|
859
|
-
if (isRequiredWithoutDefault) {
|
|
860
|
-
paramResult.isValid = false;
|
|
861
|
-
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
862
|
-
}
|
|
863
|
-
continue;
|
|
864
|
-
}
|
|
865
|
-
if (param.in === "query" || param.in === "path") {
|
|
866
|
-
if (isRequiredWithoutDefault) {
|
|
867
|
-
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
868
|
-
}
|
|
869
|
-
else {
|
|
870
|
-
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
return paramResult;
|
|
875
|
-
}
|
|
876
780
|
}
|
|
877
781
|
|
|
878
782
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -882,7 +786,6 @@ class CopilotValidator extends Validator {
|
|
|
882
786
|
this.projectType = ProjectType.Copilot;
|
|
883
787
|
this.options = options;
|
|
884
788
|
this.spec = spec;
|
|
885
|
-
this.checkCircularReference();
|
|
886
789
|
}
|
|
887
790
|
validateSpec() {
|
|
888
791
|
const result = { errors: [], warnings: [] };
|
|
@@ -908,10 +811,6 @@ class CopilotValidator extends Validator {
|
|
|
908
811
|
if (!methodAndPathResult.isValid) {
|
|
909
812
|
return methodAndPathResult;
|
|
910
813
|
}
|
|
911
|
-
const circularReferenceResult = this.validateCircularReference(method, path);
|
|
912
|
-
if (!circularReferenceResult.isValid) {
|
|
913
|
-
return circularReferenceResult;
|
|
914
|
-
}
|
|
915
814
|
const operationObject = this.spec.paths[path][method];
|
|
916
815
|
// validate auth
|
|
917
816
|
const authCheckResult = this.validateAuth(method, path);
|
|
@@ -923,24 +822,6 @@ class CopilotValidator extends Validator {
|
|
|
923
822
|
// validate server
|
|
924
823
|
const validateServerResult = this.validateServer(method, path);
|
|
925
824
|
result.reason.push(...validateServerResult.reason);
|
|
926
|
-
// validate response
|
|
927
|
-
const validateResponseResult = this.validateResponse(method, path);
|
|
928
|
-
result.reason.push(...validateResponseResult.reason);
|
|
929
|
-
// validate requestBody
|
|
930
|
-
const requestBody = operationObject.requestBody;
|
|
931
|
-
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
932
|
-
if (requestJsonBody) {
|
|
933
|
-
const requestBodySchema = requestJsonBody.schema;
|
|
934
|
-
if (!Utils.isObjectSchema(requestBodySchema)) {
|
|
935
|
-
result.reason.push(ErrorType.PostBodySchemaIsNotJson);
|
|
936
|
-
}
|
|
937
|
-
const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
|
|
938
|
-
result.reason.push(...requestBodyParamResult.reason);
|
|
939
|
-
}
|
|
940
|
-
// validate parameters
|
|
941
|
-
const paramObject = operationObject.parameters;
|
|
942
|
-
const paramResult = this.checkParamSchema(paramObject);
|
|
943
|
-
result.reason.push(...paramResult.reason);
|
|
944
825
|
if (result.reason.length > 0) {
|
|
945
826
|
result.isValid = false;
|
|
946
827
|
}
|
|
@@ -1032,6 +913,108 @@ class SMEValidator extends Validator {
|
|
|
1032
913
|
}
|
|
1033
914
|
return result;
|
|
1034
915
|
}
|
|
916
|
+
validateResponse(method, path) {
|
|
917
|
+
const result = { isValid: true, reason: [] };
|
|
918
|
+
const operationObject = this.spec.paths[path][method];
|
|
919
|
+
const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
|
|
920
|
+
// only support response body only contains “application/json” content type
|
|
921
|
+
if (multipleMediaType) {
|
|
922
|
+
result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
|
|
923
|
+
}
|
|
924
|
+
else if (Object.keys(json).length === 0) {
|
|
925
|
+
// response body should not be empty
|
|
926
|
+
result.reason.push(ErrorType.ResponseJsonIsEmpty);
|
|
927
|
+
}
|
|
928
|
+
return result;
|
|
929
|
+
}
|
|
930
|
+
checkPostBodySchema(schema, isRequired = false) {
|
|
931
|
+
var _a;
|
|
932
|
+
const paramResult = {
|
|
933
|
+
requiredNum: 0,
|
|
934
|
+
optionalNum: 0,
|
|
935
|
+
isValid: true,
|
|
936
|
+
reason: [],
|
|
937
|
+
};
|
|
938
|
+
if (Object.keys(schema).length === 0) {
|
|
939
|
+
return paramResult;
|
|
940
|
+
}
|
|
941
|
+
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
942
|
+
const isCopilot = this.projectType === ProjectType.Copilot;
|
|
943
|
+
if (schema.type === "string" ||
|
|
944
|
+
schema.type === "integer" ||
|
|
945
|
+
schema.type === "boolean" ||
|
|
946
|
+
schema.type === "number") {
|
|
947
|
+
if (isRequiredWithoutDefault) {
|
|
948
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
949
|
+
}
|
|
950
|
+
else {
|
|
951
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
else if (Utils.isObjectSchema(schema)) {
|
|
955
|
+
const { properties } = schema;
|
|
956
|
+
for (const property in properties) {
|
|
957
|
+
let isRequired = false;
|
|
958
|
+
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
959
|
+
isRequired = true;
|
|
960
|
+
}
|
|
961
|
+
const result = this.checkPostBodySchema(properties[property], isRequired);
|
|
962
|
+
paramResult.requiredNum += result.requiredNum;
|
|
963
|
+
paramResult.optionalNum += result.optionalNum;
|
|
964
|
+
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
965
|
+
paramResult.reason.push(...result.reason);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
else {
|
|
969
|
+
if (isRequiredWithoutDefault && !isCopilot) {
|
|
970
|
+
paramResult.isValid = false;
|
|
971
|
+
paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return paramResult;
|
|
975
|
+
}
|
|
976
|
+
checkParamSchema(paramObject) {
|
|
977
|
+
const paramResult = {
|
|
978
|
+
requiredNum: 0,
|
|
979
|
+
optionalNum: 0,
|
|
980
|
+
isValid: true,
|
|
981
|
+
reason: [],
|
|
982
|
+
};
|
|
983
|
+
if (!paramObject) {
|
|
984
|
+
return paramResult;
|
|
985
|
+
}
|
|
986
|
+
for (let i = 0; i < paramObject.length; i++) {
|
|
987
|
+
const param = paramObject[i];
|
|
988
|
+
const schema = param.schema;
|
|
989
|
+
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
990
|
+
if (param.in === "header" || param.in === "cookie") {
|
|
991
|
+
if (isRequiredWithoutDefault) {
|
|
992
|
+
paramResult.isValid = false;
|
|
993
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
994
|
+
}
|
|
995
|
+
continue;
|
|
996
|
+
}
|
|
997
|
+
if (schema.type !== "boolean" &&
|
|
998
|
+
schema.type !== "string" &&
|
|
999
|
+
schema.type !== "number" &&
|
|
1000
|
+
schema.type !== "integer") {
|
|
1001
|
+
if (isRequiredWithoutDefault) {
|
|
1002
|
+
paramResult.isValid = false;
|
|
1003
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
1004
|
+
}
|
|
1005
|
+
continue;
|
|
1006
|
+
}
|
|
1007
|
+
if (param.in === "query" || param.in === "path") {
|
|
1008
|
+
if (isRequiredWithoutDefault) {
|
|
1009
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
1010
|
+
}
|
|
1011
|
+
else {
|
|
1012
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
return paramResult;
|
|
1017
|
+
}
|
|
1035
1018
|
validateParamCount(postBodyResult, paramResult) {
|
|
1036
1019
|
const result = { isValid: true, reason: [] };
|
|
1037
1020
|
const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
|