@microsoft/m365-spec-parser 0.2.3 → 0.2.4-rc-hotfix.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,8 @@ 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["GenerateJsonDataFailed"] = "generate-json-data-failed";
88
87
  WarningType["Unknown"] = "unknown";
89
88
  })(WarningType || (WarningType = {}));
90
89
  /**
@@ -130,15 +129,17 @@ ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converte
130
129
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
131
130
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
132
131
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
132
+ ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
133
133
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
134
134
  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.";
135
+ ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
135
136
  ConstantString.WrappedCardVersion = "devPreview";
136
137
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
137
138
  ConstantString.WrappedCardResponseLayout = "list";
138
139
  ConstantString.GetMethod = "get";
139
140
  ConstantString.PostMethod = "post";
140
141
  ConstantString.AdaptiveCardVersion = "1.5";
141
- ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
142
+ ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
142
143
  ConstantString.AdaptiveCardType = "AdaptiveCard";
143
144
  ConstantString.TextBlockType = "TextBlock";
144
145
  ConstantString.ImageType = "Image";
@@ -217,16 +218,8 @@ ConstantString.PluginManifestSchema = "https://developer.microsoft.com/json-sche
217
218
 
218
219
  // Copyright (c) Microsoft Corporation.
219
220
  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;
221
+ static isObjectSchema(schema) {
222
+ return schema.type === "object" || (!schema.type && !!schema.properties);
230
223
  }
231
224
  static containMultipleMediaTypes(bodyObject) {
232
225
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
@@ -294,27 +287,33 @@ class Utils {
294
287
  let multipleMediaType = false;
295
288
  for (const code of ConstantString.ResponseCodeFor20X) {
296
289
  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
- }
290
+ if (!responseObject) {
291
+ continue;
292
+ }
293
+ multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
294
+ if (!allowMultipleMediaType && multipleMediaType) {
295
+ json = {};
296
+ continue;
297
+ }
298
+ const mediaObj = Utils.getJsonContentType(responseObject);
299
+ if (Object.keys(mediaObj).length > 0) {
300
+ json = mediaObj;
301
+ return { json, multipleMediaType };
314
302
  }
315
303
  }
316
304
  return { json, multipleMediaType };
317
305
  }
306
+ static getJsonContentType(responseObject) {
307
+ if (responseObject.content) {
308
+ for (const contentType of Object.keys(responseObject.content)) {
309
+ // json media type can also be "application/json; charset=utf-8"
310
+ if (contentType.indexOf("application/json") >= 0) {
311
+ return responseObject.content[contentType];
312
+ }
313
+ }
314
+ }
315
+ return {};
316
+ }
318
317
  static convertPathToCamelCase(path) {
319
318
  const pathSegments = path.split(/[./{]/);
320
319
  const camelCaseSegments = pathSegments.map((segment) => {
@@ -350,7 +349,7 @@ class Utils {
350
349
  }
351
350
  return newStr;
352
351
  }
353
- static checkServerUrl(servers) {
352
+ static checkServerUrl(servers, allowHttp = false) {
354
353
  const errors = [];
355
354
  let serverUrl;
356
355
  try {
@@ -373,8 +372,7 @@ class Utils {
373
372
  data: servers,
374
373
  });
375
374
  }
376
- else if (protocol !== "https:") {
377
- // Http server url is not supported
375
+ else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
378
376
  const protocolString = protocol.slice(0, -1);
379
377
  errors.push({
380
378
  type: ErrorType.UrlProtocolNotSupported,
@@ -390,10 +388,11 @@ class Utils {
390
388
  let hasTopLevelServers = false;
391
389
  let hasPathLevelServers = false;
392
390
  let hasOperationLevelServers = false;
391
+ const allowHttp = options.projectType === ProjectType.Copilot;
393
392
  if (spec.servers && spec.servers.length >= 1) {
394
393
  hasTopLevelServers = true;
395
394
  // for multiple server, we only use the first url
396
- const serverErrors = Utils.checkServerUrl(spec.servers);
395
+ const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
397
396
  errors.push(...serverErrors);
398
397
  }
399
398
  const paths = spec.paths;
@@ -401,7 +400,7 @@ class Utils {
401
400
  const methods = paths[path];
402
401
  if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
403
402
  hasPathLevelServers = true;
404
- const serverErrors = Utils.checkServerUrl(methods.servers);
403
+ const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
405
404
  errors.push(...serverErrors);
406
405
  }
407
406
  for (const method in methods) {
@@ -409,7 +408,7 @@ class Utils {
409
408
  if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
410
409
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
411
410
  hasOperationLevelServers = true;
412
- const serverErrors = Utils.checkServerUrl(operationObject.servers);
411
+ const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
413
412
  errors.push(...serverErrors);
414
413
  }
415
414
  }
@@ -456,7 +455,7 @@ class Utils {
456
455
  optionalParams.push(parameter);
457
456
  }
458
457
  }
459
- else if (schema.type === "object") {
458
+ else if (Utils.isObjectSchema(schema)) {
460
459
  const { properties } = schema;
461
460
  for (const property in properties) {
462
461
  let isRequired = false;
@@ -570,29 +569,6 @@ class Utils {
570
569
  const serverUrl = operationServer || methodServer || rootServer;
571
570
  return serverUrl;
572
571
  }
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
572
  }
597
573
 
598
574
  // Copyright (c) Microsoft Corporation.
@@ -721,22 +697,6 @@ class Validator {
721
697
  }
722
698
  return result;
723
699
  }
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
700
  validateServer(method, path) {
741
701
  const result = { isValid: true, reason: [] };
742
702
  const serverObj = Utils.getServerObject(this.spec, method, path);
@@ -745,8 +705,8 @@ class Validator {
745
705
  result.reason.push(ErrorType.NoServerInformation);
746
706
  }
747
707
  else {
748
- // server url should be absolute url with https protocol
749
- const serverValidateResult = Utils.checkServerUrl([serverObj]);
708
+ const allowHttp = this.projectType === ProjectType.Copilot;
709
+ const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
750
710
  result.reason.push(...serverValidateResult.map((item) => item.type));
751
711
  }
752
712
  return result;
@@ -781,125 +741,6 @@ class Validator {
781
741
  }
782
742
  return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
783
743
  }
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
744
  }
904
745
 
905
746
  // Copyright (c) Microsoft Corporation.
@@ -950,24 +791,6 @@ class CopilotValidator extends Validator {
950
791
  // validate server
951
792
  const validateServerResult = this.validateServer(method, path);
952
793
  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
794
  if (result.reason.length > 0) {
972
795
  result.isValid = false;
973
796
  }
@@ -1059,6 +882,108 @@ class SMEValidator extends Validator {
1059
882
  }
1060
883
  return result;
1061
884
  }
885
+ validateResponse(method, path) {
886
+ const result = { isValid: true, reason: [] };
887
+ const operationObject = this.spec.paths[path][method];
888
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
889
+ // only support response body only contains “application/json” content type
890
+ if (multipleMediaType) {
891
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
892
+ }
893
+ else if (Object.keys(json).length === 0) {
894
+ // response body should not be empty
895
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
896
+ }
897
+ return result;
898
+ }
899
+ checkPostBodySchema(schema, isRequired = false) {
900
+ var _a;
901
+ const paramResult = {
902
+ requiredNum: 0,
903
+ optionalNum: 0,
904
+ isValid: true,
905
+ reason: [],
906
+ };
907
+ if (Object.keys(schema).length === 0) {
908
+ return paramResult;
909
+ }
910
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
911
+ const isCopilot = this.projectType === ProjectType.Copilot;
912
+ if (schema.type === "string" ||
913
+ schema.type === "integer" ||
914
+ schema.type === "boolean" ||
915
+ schema.type === "number") {
916
+ if (isRequiredWithoutDefault) {
917
+ paramResult.requiredNum = paramResult.requiredNum + 1;
918
+ }
919
+ else {
920
+ paramResult.optionalNum = paramResult.optionalNum + 1;
921
+ }
922
+ }
923
+ else if (Utils.isObjectSchema(schema)) {
924
+ const { properties } = schema;
925
+ for (const property in properties) {
926
+ let isRequired = false;
927
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
928
+ isRequired = true;
929
+ }
930
+ const result = this.checkPostBodySchema(properties[property], isRequired);
931
+ paramResult.requiredNum += result.requiredNum;
932
+ paramResult.optionalNum += result.optionalNum;
933
+ paramResult.isValid = paramResult.isValid && result.isValid;
934
+ paramResult.reason.push(...result.reason);
935
+ }
936
+ }
937
+ else {
938
+ if (isRequiredWithoutDefault && !isCopilot) {
939
+ paramResult.isValid = false;
940
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
941
+ }
942
+ }
943
+ return paramResult;
944
+ }
945
+ checkParamSchema(paramObject) {
946
+ const paramResult = {
947
+ requiredNum: 0,
948
+ optionalNum: 0,
949
+ isValid: true,
950
+ reason: [],
951
+ };
952
+ if (!paramObject) {
953
+ return paramResult;
954
+ }
955
+ for (let i = 0; i < paramObject.length; i++) {
956
+ const param = paramObject[i];
957
+ const schema = param.schema;
958
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
959
+ if (param.in === "header" || param.in === "cookie") {
960
+ if (isRequiredWithoutDefault) {
961
+ paramResult.isValid = false;
962
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
963
+ }
964
+ continue;
965
+ }
966
+ if (schema.type !== "boolean" &&
967
+ schema.type !== "string" &&
968
+ schema.type !== "number" &&
969
+ schema.type !== "integer") {
970
+ if (isRequiredWithoutDefault) {
971
+ paramResult.isValid = false;
972
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
973
+ }
974
+ continue;
975
+ }
976
+ if (param.in === "query" || param.in === "path") {
977
+ if (isRequiredWithoutDefault) {
978
+ paramResult.requiredNum = paramResult.requiredNum + 1;
979
+ }
980
+ else {
981
+ paramResult.optionalNum = paramResult.optionalNum + 1;
982
+ }
983
+ }
984
+ }
985
+ return paramResult;
986
+ }
1062
987
  validateParamCount(postBodyResult, paramResult) {
1063
988
  const result = { isValid: true, reason: [] };
1064
989
  const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
@@ -1348,20 +1273,157 @@ class SpecParser {
1348
1273
  }
1349
1274
  }
1350
1275
 
1276
+ // Copyright (c) Microsoft Corporation.
1277
+ class JsonDataGenerator {
1278
+ static generate(schema) {
1279
+ return this.generateMockData(schema);
1280
+ }
1281
+ static generateMockData(schema) {
1282
+ if (this.visitedSchemas.has(schema)) {
1283
+ return null; // Prevent circular reference
1284
+ }
1285
+ this.visitedSchemas.add(schema);
1286
+ let result;
1287
+ if (schema.anyOf) {
1288
+ // Select the first schema in anyOf
1289
+ const selectedSchema = schema.anyOf[0];
1290
+ result = this.generateMockData(selectedSchema);
1291
+ }
1292
+ else if (schema.oneOf) {
1293
+ // Select the first schema in oneOf
1294
+ const selectedSchema = schema.oneOf[0];
1295
+ result = this.generateMockData(selectedSchema);
1296
+ }
1297
+ else if (schema.allOf) {
1298
+ // merge all schemas in allOf
1299
+ result = {};
1300
+ for (const subschema of schema.allOf) {
1301
+ const data = this.generateMockData(subschema);
1302
+ result = Object.assign(Object.assign({}, result), data);
1303
+ }
1304
+ }
1305
+ else {
1306
+ switch (schema.type) {
1307
+ case "string":
1308
+ if (schema.example !== undefined) {
1309
+ result = schema.example;
1310
+ }
1311
+ else if (schema.format) {
1312
+ switch (schema.format) {
1313
+ case "date-time":
1314
+ result = "2024-11-01T05:25:43.593Z";
1315
+ break;
1316
+ case "email":
1317
+ result = "example@example.com";
1318
+ break;
1319
+ case "uuid":
1320
+ result = "123e4567-e89b-12d3-a456-426614174000";
1321
+ break;
1322
+ case "ipv4":
1323
+ result = "192.168.0.1";
1324
+ break;
1325
+ case "ipv6":
1326
+ result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
1327
+ break;
1328
+ default:
1329
+ result = "example string";
1330
+ }
1331
+ }
1332
+ else {
1333
+ result = "example string";
1334
+ }
1335
+ break;
1336
+ case "number":
1337
+ if (schema.example !== undefined) {
1338
+ result = schema.example;
1339
+ }
1340
+ else if (schema.format) {
1341
+ switch (schema.format) {
1342
+ case "float":
1343
+ result = 3.14;
1344
+ break;
1345
+ case "double":
1346
+ result = 3.14159;
1347
+ break;
1348
+ default:
1349
+ result = 123;
1350
+ }
1351
+ }
1352
+ else {
1353
+ result = 123;
1354
+ }
1355
+ break;
1356
+ case "integer":
1357
+ if (schema.example !== undefined) {
1358
+ result = schema.example;
1359
+ }
1360
+ else if (schema.format) {
1361
+ switch (schema.format) {
1362
+ case "int32":
1363
+ result = 123456;
1364
+ break;
1365
+ case "int64":
1366
+ result = 123456789;
1367
+ break;
1368
+ default:
1369
+ result = 123;
1370
+ }
1371
+ }
1372
+ else {
1373
+ result = 123;
1374
+ }
1375
+ break;
1376
+ case "boolean":
1377
+ result = schema.example !== undefined ? schema.example : true;
1378
+ break;
1379
+ case "array":
1380
+ result = [this.generateMockData(schema.items)];
1381
+ break;
1382
+ case "object":
1383
+ result = {};
1384
+ if (schema.properties) {
1385
+ for (const key in schema.properties) {
1386
+ result[key] = this.generateMockData(schema.properties[key]);
1387
+ }
1388
+ }
1389
+ break;
1390
+ default:
1391
+ result = schema.example || null;
1392
+ }
1393
+ }
1394
+ this.visitedSchemas.delete(schema);
1395
+ return result;
1396
+ }
1397
+ }
1398
+ JsonDataGenerator.visitedSchemas = new Set();
1399
+
1351
1400
  // Copyright (c) Microsoft Corporation.
1352
1401
  class AdaptiveCardGenerator {
1353
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1402
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1354
1403
  try {
1355
1404
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1356
1405
  let cardBody = [];
1406
+ let jsonData = {};
1407
+ const warnings = [];
1408
+ const operationId = operationItem.operationId;
1357
1409
  let schema = json.schema;
1358
1410
  let jsonPath = "$";
1359
1411
  if (schema && Object.keys(schema).length > 0) {
1412
+ try {
1413
+ jsonData = JsonDataGenerator.generate(schema);
1414
+ }
1415
+ catch (err) {
1416
+ warnings.push({
1417
+ type: WarningType.GenerateJsonDataFailed,
1418
+ content: Utils.format(ConstantString.GenerateJsonDataFailed, operationId, err.toString()),
1419
+ data: operationId,
1420
+ });
1421
+ }
1360
1422
  jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
1361
1423
  if (jsonPath !== "$") {
1362
1424
  schema = schema.properties[jsonPath];
1363
1425
  }
1364
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1426
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1365
1427
  }
1366
1428
  // if no schema, try to use example value
1367
1429
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1389,16 +1451,20 @@ class AdaptiveCardGenerator {
1389
1451
  version: ConstantString.AdaptiveCardVersion,
1390
1452
  body: cardBody,
1391
1453
  };
1392
- return [fullCard, jsonPath];
1454
+ return [fullCard, jsonPath, jsonData, warnings];
1393
1455
  }
1394
1456
  catch (err) {
1395
1457
  throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
1396
1458
  }
1397
1459
  }
1398
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1460
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1461
+ if (counter.count >= maxElementCount) {
1462
+ return [];
1463
+ }
1399
1464
  if (schema.type === "array") {
1400
1465
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1401
1466
  if (Object.keys(schema.items).length === 0) {
1467
+ counter.count++;
1402
1468
  return [
1403
1469
  {
1404
1470
  type: ConstantString.TextBlockType,
@@ -1407,7 +1473,7 @@ class AdaptiveCardGenerator {
1407
1473
  },
1408
1474
  ];
1409
1475
  }
1410
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1476
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1411
1477
  const template = {
1412
1478
  type: ConstantString.ContainerType,
1413
1479
  $data: name ? `\${${name}}` : "${$root}",
@@ -1417,11 +1483,11 @@ class AdaptiveCardGenerator {
1417
1483
  return [template];
1418
1484
  }
1419
1485
  // some schema may not contain type but contain properties
1420
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1486
+ if (Utils.isObjectSchema(schema)) {
1421
1487
  const { properties } = schema;
1422
1488
  const result = [];
1423
1489
  for (const property in properties) {
1424
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1490
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1425
1491
  result.push(...obj);
1426
1492
  }
1427
1493
  if (schema.additionalProperties) {
@@ -1434,6 +1500,7 @@ class AdaptiveCardGenerator {
1434
1500
  schema.type === "integer" ||
1435
1501
  schema.type === "boolean" ||
1436
1502
  schema.type === "number") {
1503
+ counter.count++;
1437
1504
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1438
1505
  // string in root: "ddd"
1439
1506
  let text = "result: ${$root}";
@@ -1458,24 +1525,17 @@ class AdaptiveCardGenerator {
1458
1525
  ];
1459
1526
  }
1460
1527
  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
- }
1528
+ const url = name ? `\${${name}}` : "${$data}";
1529
+ const condition = name
1530
+ ? `\${${name} != null && ${name} != ''}`
1531
+ : "${$data != null && $data != ''}";
1532
+ return [
1533
+ {
1534
+ type: "Image",
1535
+ url,
1536
+ $when: condition,
1537
+ },
1538
+ ];
1479
1539
  }
1480
1540
  }
1481
1541
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1485,7 +1545,7 @@ class AdaptiveCardGenerator {
1485
1545
  }
1486
1546
  // Find the first array property in the response schema object with the well-known name
1487
1547
  static getResponseJsonPathFromSchema(schema) {
1488
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1548
+ if (Utils.isObjectSchema(schema)) {
1489
1549
  const { properties } = schema;
1490
1550
  for (const property in properties) {
1491
1551
  const schema = properties[property];