@microsoft/m365-spec-parser 0.2.3 → 0.2.4-alpha.5e509eccd.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.
@@ -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";
@@ -85,6 +82,9 @@ var WarningType;
85
82
  WarningType["OperationOnlyContainsOptionalParam"] = "operation-only-contains-optional-param";
86
83
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
87
84
  WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
85
+ WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
86
+ WarningType["UnsupportedAuthType"] = "unsupported-auth-type";
87
+ WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
88
88
  WarningType["Unknown"] = "unknown";
89
89
  })(WarningType || (WarningType = {}));
90
90
  /**
@@ -130,25 +130,23 @@ ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converte
130
130
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
131
131
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
132
132
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
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.";
133
135
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
134
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.";
137
+ ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
135
138
  ConstantString.WrappedCardVersion = "devPreview";
136
139
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
137
140
  ConstantString.WrappedCardResponseLayout = "list";
138
141
  ConstantString.GetMethod = "get";
139
142
  ConstantString.PostMethod = "post";
140
143
  ConstantString.AdaptiveCardVersion = "1.5";
141
- ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
144
+ ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
142
145
  ConstantString.AdaptiveCardType = "AdaptiveCard";
143
146
  ConstantString.TextBlockType = "TextBlock";
144
147
  ConstantString.ImageType = "Image";
145
148
  ConstantString.ContainerType = "Container";
146
- ConstantString.RegistrationIdPostfix = {
147
- apiKey: "REGISTRATION_ID",
148
- oauth2: "CONFIGURATION_ID",
149
- http: "REGISTRATION_ID",
150
- openIdConnect: "REGISTRATION_ID",
151
- };
149
+ ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
152
150
  ConstantString.ResponseCodeFor20X = [
153
151
  "200",
154
152
  "201",
@@ -217,16 +215,8 @@ ConstantString.PluginManifestSchema = "https://developer.microsoft.com/json-sche
217
215
 
218
216
  // Copyright (c) Microsoft Corporation.
219
217
  class Utils {
220
- static hasNestedObjectInSchema(schema) {
221
- if (schema.type === "object") {
222
- for (const property in schema.properties) {
223
- const nestedSchema = schema.properties[property];
224
- if (nestedSchema.type === "object") {
225
- return true;
226
- }
227
- }
228
- }
229
- return false;
218
+ static isObjectSchema(schema) {
219
+ return schema.type === "object" || (!schema.type && !!schema.properties);
230
220
  }
231
221
  static containMultipleMediaTypes(bodyObject) {
232
222
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
@@ -242,6 +232,23 @@ class Utils {
242
232
  authScheme.flows &&
243
233
  authScheme.flows.authorizationCode);
244
234
  }
235
+ static isNotSupportedAuth(authSchemeArray) {
236
+ if (authSchemeArray.length === 0) {
237
+ return false;
238
+ }
239
+ if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
240
+ return true;
241
+ }
242
+ for (const auths of authSchemeArray) {
243
+ if (auths.length === 1) {
244
+ if (Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme) ||
245
+ Utils.isBearerTokenAuth(auths[0].authScheme)) {
246
+ return false;
247
+ }
248
+ }
249
+ }
250
+ return true;
251
+ }
245
252
  static getAuthArray(securities, spec) {
246
253
  var _a;
247
254
  const result = [];
@@ -266,6 +273,20 @@ class Utils {
266
273
  result.sort((a, b) => a[0].name.localeCompare(b[0].name));
267
274
  return result;
268
275
  }
276
+ static getAuthMap(spec) {
277
+ const authMap = {};
278
+ for (const url in spec.paths) {
279
+ for (const method in spec.paths[url]) {
280
+ const operation = spec.paths[url][method];
281
+ const authArray = Utils.getAuthArray(operation.security, spec);
282
+ if (authArray && authArray.length > 0) {
283
+ const currentAuth = authArray[0][0];
284
+ authMap[operation.operationId] = currentAuth;
285
+ }
286
+ }
287
+ }
288
+ return authMap;
289
+ }
269
290
  static getAuthInfo(spec) {
270
291
  let authInfo = undefined;
271
292
  for (const url in spec.paths) {
@@ -294,27 +315,33 @@ class Utils {
294
315
  let multipleMediaType = false;
295
316
  for (const code of ConstantString.ResponseCodeFor20X) {
296
317
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
297
- if (responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) {
298
- for (const contentType of Object.keys(responseObject.content)) {
299
- // json media type can also be "application/json; charset=utf-8"
300
- if (contentType.indexOf("application/json") >= 0) {
301
- multipleMediaType = false;
302
- json = responseObject.content[contentType];
303
- if (Utils.containMultipleMediaTypes(responseObject)) {
304
- multipleMediaType = true;
305
- if (!allowMultipleMediaType) {
306
- json = {};
307
- }
308
- }
309
- else {
310
- return { json, multipleMediaType };
311
- }
312
- }
313
- }
318
+ if (!responseObject) {
319
+ continue;
320
+ }
321
+ multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
322
+ if (!allowMultipleMediaType && multipleMediaType) {
323
+ json = {};
324
+ continue;
325
+ }
326
+ const mediaObj = Utils.getJsonContentType(responseObject);
327
+ if (Object.keys(mediaObj).length > 0) {
328
+ json = mediaObj;
329
+ return { json, multipleMediaType };
314
330
  }
315
331
  }
316
332
  return { json, multipleMediaType };
317
333
  }
334
+ static getJsonContentType(responseObject) {
335
+ if (responseObject.content) {
336
+ for (const contentType of Object.keys(responseObject.content)) {
337
+ // json media type can also be "application/json; charset=utf-8"
338
+ if (contentType.indexOf("application/json") >= 0) {
339
+ return responseObject.content[contentType];
340
+ }
341
+ }
342
+ }
343
+ return {};
344
+ }
318
345
  static convertPathToCamelCase(path) {
319
346
  const pathSegments = path.split(/[./{]/);
320
347
  const camelCaseSegments = pathSegments.map((segment) => {
@@ -350,7 +377,7 @@ class Utils {
350
377
  }
351
378
  return newStr;
352
379
  }
353
- static checkServerUrl(servers) {
380
+ static checkServerUrl(servers, allowHttp = false) {
354
381
  const errors = [];
355
382
  let serverUrl;
356
383
  try {
@@ -373,8 +400,7 @@ class Utils {
373
400
  data: servers,
374
401
  });
375
402
  }
376
- else if (protocol !== "https:") {
377
- // Http server url is not supported
403
+ else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
378
404
  const protocolString = protocol.slice(0, -1);
379
405
  errors.push({
380
406
  type: ErrorType.UrlProtocolNotSupported,
@@ -390,10 +416,11 @@ class Utils {
390
416
  let hasTopLevelServers = false;
391
417
  let hasPathLevelServers = false;
392
418
  let hasOperationLevelServers = false;
419
+ const allowHttp = options.projectType === ProjectType.Copilot;
393
420
  if (spec.servers && spec.servers.length >= 1) {
394
421
  hasTopLevelServers = true;
395
422
  // for multiple server, we only use the first url
396
- const serverErrors = Utils.checkServerUrl(spec.servers);
423
+ const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
397
424
  errors.push(...serverErrors);
398
425
  }
399
426
  const paths = spec.paths;
@@ -401,7 +428,7 @@ class Utils {
401
428
  const methods = paths[path];
402
429
  if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
403
430
  hasPathLevelServers = true;
404
- const serverErrors = Utils.checkServerUrl(methods.servers);
431
+ const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
405
432
  errors.push(...serverErrors);
406
433
  }
407
434
  for (const method in methods) {
@@ -409,7 +436,7 @@ class Utils {
409
436
  if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
410
437
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
411
438
  hasOperationLevelServers = true;
412
- const serverErrors = Utils.checkServerUrl(operationObject.servers);
439
+ const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
413
440
  errors.push(...serverErrors);
414
441
  }
415
442
  }
@@ -456,7 +483,7 @@ class Utils {
456
483
  optionalParams.push(parameter);
457
484
  }
458
485
  }
459
- else if (schema.type === "object") {
486
+ else if (Utils.isObjectSchema(schema)) {
460
487
  const { properties } = schema;
461
488
  for (const property in properties) {
462
489
  let isRequired = false;
@@ -570,29 +597,6 @@ class Utils {
570
597
  const serverUrl = operationServer || methodServer || rootServer;
571
598
  return serverUrl;
572
599
  }
573
- static limitACBodyProperties(body, maxCount) {
574
- const result = [];
575
- let currentCount = 0;
576
- for (const element of body) {
577
- if (element.type === ConstantString.ContainerType) {
578
- const items = this.limitACBodyProperties(element.items, maxCount - currentCount);
579
- result.push({
580
- type: ConstantString.ContainerType,
581
- $data: element.$data,
582
- items: items,
583
- });
584
- currentCount += items.length;
585
- }
586
- else {
587
- result.push(element);
588
- currentCount++;
589
- }
590
- if (currentCount >= maxCount) {
591
- break;
592
- }
593
- }
594
- return result;
595
- }
596
600
  }
597
601
 
598
602
  // Copyright (c) Microsoft Corporation.
@@ -721,22 +725,6 @@ class Validator {
721
725
  }
722
726
  return result;
723
727
  }
724
- validateResponse(method, path) {
725
- const result = { isValid: true, reason: [] };
726
- const operationObject = this.spec.paths[path][method];
727
- const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
728
- if (this.options.projectType === ProjectType.SME) {
729
- // only support response body only contains “application/json” content type
730
- if (multipleMediaType) {
731
- result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
732
- }
733
- else if (Object.keys(json).length === 0) {
734
- // response body should not be empty
735
- result.reason.push(ErrorType.ResponseJsonIsEmpty);
736
- }
737
- }
738
- return result;
739
- }
740
728
  validateServer(method, path) {
741
729
  const result = { isValid: true, reason: [] };
742
730
  const serverObj = Utils.getServerObject(this.spec, method, path);
@@ -745,8 +733,8 @@ class Validator {
745
733
  result.reason.push(ErrorType.NoServerInformation);
746
734
  }
747
735
  else {
748
- // server url should be absolute url with https protocol
749
- const serverValidateResult = Utils.checkServerUrl([serverObj]);
736
+ const allowHttp = this.projectType === ProjectType.Copilot;
737
+ const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
750
738
  result.reason.push(...serverValidateResult.map((item) => item.type));
751
739
  }
752
740
  return result;
@@ -769,6 +757,9 @@ class Validator {
769
757
  reason: [ErrorType.MultipleAuthNotSupported],
770
758
  };
771
759
  }
760
+ if (this.projectType === ProjectType.Copilot) {
761
+ return { isValid: true, reason: [] };
762
+ }
772
763
  for (const auths of authSchemeArray) {
773
764
  if (auths.length === 1) {
774
765
  if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
@@ -781,125 +772,6 @@ class Validator {
781
772
  }
782
773
  return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
783
774
  }
784
- checkPostBodySchema(schema, isRequired = false) {
785
- var _a;
786
- const paramResult = {
787
- requiredNum: 0,
788
- optionalNum: 0,
789
- isValid: true,
790
- reason: [],
791
- };
792
- if (Object.keys(schema).length === 0) {
793
- return paramResult;
794
- }
795
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
796
- const isCopilot = this.projectType === ProjectType.Copilot;
797
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
798
- paramResult.isValid = false;
799
- paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
800
- return paramResult;
801
- }
802
- if (schema.type === "string" ||
803
- schema.type === "integer" ||
804
- schema.type === "boolean" ||
805
- schema.type === "number") {
806
- if (isRequiredWithoutDefault) {
807
- paramResult.requiredNum = paramResult.requiredNum + 1;
808
- }
809
- else {
810
- paramResult.optionalNum = paramResult.optionalNum + 1;
811
- }
812
- }
813
- else if (schema.type === "object") {
814
- const { properties } = schema;
815
- for (const property in properties) {
816
- let isRequired = false;
817
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
818
- isRequired = true;
819
- }
820
- const result = this.checkPostBodySchema(properties[property], isRequired);
821
- paramResult.requiredNum += result.requiredNum;
822
- paramResult.optionalNum += result.optionalNum;
823
- paramResult.isValid = paramResult.isValid && result.isValid;
824
- paramResult.reason.push(...result.reason);
825
- }
826
- }
827
- else {
828
- if (isRequiredWithoutDefault && !isCopilot) {
829
- paramResult.isValid = false;
830
- paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
831
- }
832
- }
833
- return paramResult;
834
- }
835
- checkParamSchema(paramObject) {
836
- const paramResult = {
837
- requiredNum: 0,
838
- optionalNum: 0,
839
- isValid: true,
840
- reason: [],
841
- };
842
- if (!paramObject) {
843
- return paramResult;
844
- }
845
- const isCopilot = this.projectType === ProjectType.Copilot;
846
- for (let i = 0; i < paramObject.length; i++) {
847
- const param = paramObject[i];
848
- const schema = param.schema;
849
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
850
- paramResult.isValid = false;
851
- paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
852
- continue;
853
- }
854
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
855
- if (isCopilot) {
856
- if (isRequiredWithoutDefault) {
857
- paramResult.requiredNum = paramResult.requiredNum + 1;
858
- }
859
- else {
860
- paramResult.optionalNum = paramResult.optionalNum + 1;
861
- }
862
- continue;
863
- }
864
- if (param.in === "header" || param.in === "cookie") {
865
- if (isRequiredWithoutDefault) {
866
- paramResult.isValid = false;
867
- paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
868
- }
869
- continue;
870
- }
871
- if (schema.type !== "boolean" &&
872
- schema.type !== "string" &&
873
- schema.type !== "number" &&
874
- schema.type !== "integer") {
875
- if (isRequiredWithoutDefault) {
876
- paramResult.isValid = false;
877
- paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
878
- }
879
- continue;
880
- }
881
- if (param.in === "query" || param.in === "path") {
882
- if (isRequiredWithoutDefault) {
883
- paramResult.requiredNum = paramResult.requiredNum + 1;
884
- }
885
- else {
886
- paramResult.optionalNum = paramResult.optionalNum + 1;
887
- }
888
- }
889
- }
890
- return paramResult;
891
- }
892
- hasNestedObjectInSchema(schema) {
893
- if (schema.type === "object") {
894
- for (const property in schema.properties) {
895
- const nestedSchema = schema.properties[property];
896
- if (nestedSchema.type === "object") {
897
- return true;
898
- }
899
- }
900
- }
901
- return false;
902
- }
903
775
  }
904
776
 
905
777
  // Copyright (c) Microsoft Corporation.
@@ -909,7 +781,6 @@ class CopilotValidator extends Validator {
909
781
  this.projectType = ProjectType.Copilot;
910
782
  this.options = options;
911
783
  this.spec = spec;
912
- this.checkCircularReference();
913
784
  }
914
785
  validateSpec() {
915
786
  const result = { errors: [], warnings: [] };
@@ -935,10 +806,6 @@ class CopilotValidator extends Validator {
935
806
  if (!methodAndPathResult.isValid) {
936
807
  return methodAndPathResult;
937
808
  }
938
- const circularReferenceResult = this.validateCircularReference(method, path);
939
- if (!circularReferenceResult.isValid) {
940
- return circularReferenceResult;
941
- }
942
809
  const operationObject = this.spec.paths[path][method];
943
810
  // validate auth
944
811
  const authCheckResult = this.validateAuth(method, path);
@@ -950,24 +817,6 @@ class CopilotValidator extends Validator {
950
817
  // validate server
951
818
  const validateServerResult = this.validateServer(method, path);
952
819
  result.reason.push(...validateServerResult.reason);
953
- // validate response
954
- const validateResponseResult = this.validateResponse(method, path);
955
- result.reason.push(...validateResponseResult.reason);
956
- // validate requestBody
957
- const requestBody = operationObject.requestBody;
958
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
959
- if (requestJsonBody) {
960
- const requestBodySchema = requestJsonBody.schema;
961
- if (requestBodySchema.type !== "object") {
962
- result.reason.push(ErrorType.PostBodySchemaIsNotJson);
963
- }
964
- const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
965
- result.reason.push(...requestBodyParamResult.reason);
966
- }
967
- // validate parameters
968
- const paramObject = operationObject.parameters;
969
- const paramResult = this.checkParamSchema(paramObject);
970
- result.reason.push(...paramResult.reason);
971
820
  if (result.reason.length > 0) {
972
821
  result.isValid = false;
973
822
  }
@@ -1059,6 +908,108 @@ class SMEValidator extends Validator {
1059
908
  }
1060
909
  return result;
1061
910
  }
911
+ validateResponse(method, path) {
912
+ const result = { isValid: true, reason: [] };
913
+ const operationObject = this.spec.paths[path][method];
914
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
915
+ // only support response body only contains “application/json” content type
916
+ if (multipleMediaType) {
917
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
918
+ }
919
+ else if (Object.keys(json).length === 0) {
920
+ // response body should not be empty
921
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
922
+ }
923
+ return result;
924
+ }
925
+ checkPostBodySchema(schema, isRequired = false) {
926
+ var _a;
927
+ const paramResult = {
928
+ requiredNum: 0,
929
+ optionalNum: 0,
930
+ isValid: true,
931
+ reason: [],
932
+ };
933
+ if (Object.keys(schema).length === 0) {
934
+ return paramResult;
935
+ }
936
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
937
+ const isCopilot = this.projectType === ProjectType.Copilot;
938
+ if (schema.type === "string" ||
939
+ schema.type === "integer" ||
940
+ schema.type === "boolean" ||
941
+ schema.type === "number") {
942
+ if (isRequiredWithoutDefault) {
943
+ paramResult.requiredNum = paramResult.requiredNum + 1;
944
+ }
945
+ else {
946
+ paramResult.optionalNum = paramResult.optionalNum + 1;
947
+ }
948
+ }
949
+ else if (Utils.isObjectSchema(schema)) {
950
+ const { properties } = schema;
951
+ for (const property in properties) {
952
+ let isRequired = false;
953
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
954
+ isRequired = true;
955
+ }
956
+ const result = this.checkPostBodySchema(properties[property], isRequired);
957
+ paramResult.requiredNum += result.requiredNum;
958
+ paramResult.optionalNum += result.optionalNum;
959
+ paramResult.isValid = paramResult.isValid && result.isValid;
960
+ paramResult.reason.push(...result.reason);
961
+ }
962
+ }
963
+ else {
964
+ if (isRequiredWithoutDefault && !isCopilot) {
965
+ paramResult.isValid = false;
966
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
967
+ }
968
+ }
969
+ return paramResult;
970
+ }
971
+ checkParamSchema(paramObject) {
972
+ const paramResult = {
973
+ requiredNum: 0,
974
+ optionalNum: 0,
975
+ isValid: true,
976
+ reason: [],
977
+ };
978
+ if (!paramObject) {
979
+ return paramResult;
980
+ }
981
+ for (let i = 0; i < paramObject.length; i++) {
982
+ const param = paramObject[i];
983
+ const schema = param.schema;
984
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
985
+ if (param.in === "header" || param.in === "cookie") {
986
+ if (isRequiredWithoutDefault) {
987
+ paramResult.isValid = false;
988
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
989
+ }
990
+ continue;
991
+ }
992
+ if (schema.type !== "boolean" &&
993
+ schema.type !== "string" &&
994
+ schema.type !== "number" &&
995
+ schema.type !== "integer") {
996
+ if (isRequiredWithoutDefault) {
997
+ paramResult.isValid = false;
998
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
999
+ }
1000
+ continue;
1001
+ }
1002
+ if (param.in === "query" || param.in === "path") {
1003
+ if (isRequiredWithoutDefault) {
1004
+ paramResult.requiredNum = paramResult.requiredNum + 1;
1005
+ }
1006
+ else {
1007
+ paramResult.optionalNum = paramResult.optionalNum + 1;
1008
+ }
1009
+ }
1010
+ }
1011
+ return paramResult;
1012
+ }
1062
1013
  validateParamCount(postBodyResult, paramResult) {
1063
1014
  const result = { isValid: true, reason: [] };
1064
1015
  const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
@@ -1348,20 +1299,157 @@ class SpecParser {
1348
1299
  }
1349
1300
  }
1350
1301
 
1302
+ // Copyright (c) Microsoft Corporation.
1303
+ class JsonDataGenerator {
1304
+ static generate(schema) {
1305
+ return this.generateMockData(schema);
1306
+ }
1307
+ static generateMockData(schema) {
1308
+ if (this.visitedSchemas.has(schema)) {
1309
+ return null; // Prevent circular reference
1310
+ }
1311
+ this.visitedSchemas.add(schema);
1312
+ let result;
1313
+ if (schema.anyOf) {
1314
+ // Select the first schema in anyOf
1315
+ const selectedSchema = schema.anyOf[0];
1316
+ result = this.generateMockData(selectedSchema);
1317
+ }
1318
+ else if (schema.oneOf) {
1319
+ // Select the first schema in oneOf
1320
+ const selectedSchema = schema.oneOf[0];
1321
+ result = this.generateMockData(selectedSchema);
1322
+ }
1323
+ else if (schema.allOf) {
1324
+ // merge all schemas in allOf
1325
+ result = {};
1326
+ for (const subschema of schema.allOf) {
1327
+ const data = this.generateMockData(subschema);
1328
+ result = Object.assign(Object.assign({}, result), data);
1329
+ }
1330
+ }
1331
+ else {
1332
+ switch (schema.type) {
1333
+ case "string":
1334
+ if (schema.example !== undefined) {
1335
+ result = schema.example;
1336
+ }
1337
+ else if (schema.format) {
1338
+ switch (schema.format) {
1339
+ case "date-time":
1340
+ result = "2024-11-01T05:25:43.593Z";
1341
+ break;
1342
+ case "email":
1343
+ result = "example@example.com";
1344
+ break;
1345
+ case "uuid":
1346
+ result = "123e4567-e89b-12d3-a456-426614174000";
1347
+ break;
1348
+ case "ipv4":
1349
+ result = "192.168.0.1";
1350
+ break;
1351
+ case "ipv6":
1352
+ result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
1353
+ break;
1354
+ default:
1355
+ result = "example string";
1356
+ }
1357
+ }
1358
+ else {
1359
+ result = "example string";
1360
+ }
1361
+ break;
1362
+ case "number":
1363
+ if (schema.example !== undefined) {
1364
+ result = schema.example;
1365
+ }
1366
+ else if (schema.format) {
1367
+ switch (schema.format) {
1368
+ case "float":
1369
+ result = 3.14;
1370
+ break;
1371
+ case "double":
1372
+ result = 3.14159;
1373
+ break;
1374
+ default:
1375
+ result = 123;
1376
+ }
1377
+ }
1378
+ else {
1379
+ result = 123;
1380
+ }
1381
+ break;
1382
+ case "integer":
1383
+ if (schema.example !== undefined) {
1384
+ result = schema.example;
1385
+ }
1386
+ else if (schema.format) {
1387
+ switch (schema.format) {
1388
+ case "int32":
1389
+ result = 123456;
1390
+ break;
1391
+ case "int64":
1392
+ result = 123456789;
1393
+ break;
1394
+ default:
1395
+ result = 123;
1396
+ }
1397
+ }
1398
+ else {
1399
+ result = 123;
1400
+ }
1401
+ break;
1402
+ case "boolean":
1403
+ result = schema.example !== undefined ? schema.example : true;
1404
+ break;
1405
+ case "array":
1406
+ result = [this.generateMockData(schema.items)];
1407
+ break;
1408
+ case "object":
1409
+ result = {};
1410
+ if (schema.properties) {
1411
+ for (const key in schema.properties) {
1412
+ result[key] = this.generateMockData(schema.properties[key]);
1413
+ }
1414
+ }
1415
+ break;
1416
+ default:
1417
+ result = schema.example || null;
1418
+ }
1419
+ }
1420
+ this.visitedSchemas.delete(schema);
1421
+ return result;
1422
+ }
1423
+ }
1424
+ JsonDataGenerator.visitedSchemas = new Set();
1425
+
1351
1426
  // Copyright (c) Microsoft Corporation.
1352
1427
  class AdaptiveCardGenerator {
1353
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1428
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1354
1429
  try {
1355
1430
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1356
1431
  let cardBody = [];
1432
+ let jsonData = {};
1433
+ const warnings = [];
1434
+ const operationId = operationItem.operationId;
1357
1435
  let schema = json.schema;
1358
1436
  let jsonPath = "$";
1359
1437
  if (schema && Object.keys(schema).length > 0) {
1438
+ try {
1439
+ jsonData = JsonDataGenerator.generate(schema);
1440
+ }
1441
+ catch (err) {
1442
+ warnings.push({
1443
+ type: WarningType.GenerateJsonDataFailed,
1444
+ content: Utils.format(ConstantString.GenerateJsonDataFailed, operationId, err.toString()),
1445
+ data: operationId,
1446
+ });
1447
+ }
1360
1448
  jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
1361
1449
  if (jsonPath !== "$") {
1362
1450
  schema = schema.properties[jsonPath];
1363
1451
  }
1364
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1452
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1365
1453
  }
1366
1454
  // if no schema, try to use example value
1367
1455
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1389,16 +1477,20 @@ class AdaptiveCardGenerator {
1389
1477
  version: ConstantString.AdaptiveCardVersion,
1390
1478
  body: cardBody,
1391
1479
  };
1392
- return [fullCard, jsonPath];
1480
+ return [fullCard, jsonPath, jsonData, warnings];
1393
1481
  }
1394
1482
  catch (err) {
1395
1483
  throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
1396
1484
  }
1397
1485
  }
1398
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1486
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1487
+ if (counter.count >= maxElementCount) {
1488
+ return [];
1489
+ }
1399
1490
  if (schema.type === "array") {
1400
1491
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1401
1492
  if (Object.keys(schema.items).length === 0) {
1493
+ counter.count++;
1402
1494
  return [
1403
1495
  {
1404
1496
  type: ConstantString.TextBlockType,
@@ -1407,7 +1499,7 @@ class AdaptiveCardGenerator {
1407
1499
  },
1408
1500
  ];
1409
1501
  }
1410
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1502
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1411
1503
  const template = {
1412
1504
  type: ConstantString.ContainerType,
1413
1505
  $data: name ? `\${${name}}` : "${$root}",
@@ -1417,11 +1509,11 @@ class AdaptiveCardGenerator {
1417
1509
  return [template];
1418
1510
  }
1419
1511
  // some schema may not contain type but contain properties
1420
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1512
+ if (Utils.isObjectSchema(schema)) {
1421
1513
  const { properties } = schema;
1422
1514
  const result = [];
1423
1515
  for (const property in properties) {
1424
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1516
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1425
1517
  result.push(...obj);
1426
1518
  }
1427
1519
  if (schema.additionalProperties) {
@@ -1434,6 +1526,7 @@ class AdaptiveCardGenerator {
1434
1526
  schema.type === "integer" ||
1435
1527
  schema.type === "boolean" ||
1436
1528
  schema.type === "number") {
1529
+ counter.count++;
1437
1530
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1438
1531
  // string in root: "ddd"
1439
1532
  let text = "result: ${$root}";
@@ -1458,24 +1551,17 @@ class AdaptiveCardGenerator {
1458
1551
  ];
1459
1552
  }
1460
1553
  else {
1461
- if (name) {
1462
- return [
1463
- {
1464
- type: "Image",
1465
- url: `\${${name}}`,
1466
- $when: `\${${name} != null && ${name} != ''}`,
1467
- },
1468
- ];
1469
- }
1470
- else {
1471
- return [
1472
- {
1473
- type: "Image",
1474
- url: "${$data}",
1475
- $when: "${$data != null && $data != ''}",
1476
- },
1477
- ];
1478
- }
1554
+ const url = name ? `\${${name}}` : "${$data}";
1555
+ const condition = name
1556
+ ? `\${${name} != null && ${name} != ''}`
1557
+ : "${$data != null && $data != ''}";
1558
+ return [
1559
+ {
1560
+ type: "Image",
1561
+ url,
1562
+ $when: condition,
1563
+ },
1564
+ ];
1479
1565
  }
1480
1566
  }
1481
1567
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1485,7 +1571,7 @@ class AdaptiveCardGenerator {
1485
1571
  }
1486
1572
  // Find the first array property in the response schema object with the well-known name
1487
1573
  static getResponseJsonPathFromSchema(schema) {
1488
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1574
+ if (Utils.isObjectSchema(schema)) {
1489
1575
  const { properties } = schema;
1490
1576
  for (const property in properties) {
1491
1577
  const schema = properties[property];