@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.
@@ -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 = "http://adaptivecards.io/schemas/adaptive-card.json";
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 === null || responseObject === void 0 ? void 0 : responseObject.content) {
275
- for (const contentType of Object.keys(responseObject.content)) {
276
- // json media type can also be "application/json; charset=utf-8"
277
- if (contentType.indexOf("application/json") >= 0) {
278
- multipleMediaType = false;
279
- json = responseObject.content[contentType];
280
- if (Utils.containMultipleMediaTypes(responseObject)) {
281
- multipleMediaType = true;
282
- if (!allowMultipleMediaType) {
283
- json = {};
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
- // server url should be absolute url with https protocol
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;