@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.
@@ -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";
@@ -55,6 +52,8 @@ var WarningType;
55
52
  WarningType["OperationOnlyContainsOptionalParam"] = "operation-only-contains-optional-param";
56
53
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
57
54
  WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
55
+ WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
56
+ WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
58
57
  WarningType["Unknown"] = "unknown";
59
58
  })(WarningType || (WarningType = {}));
60
59
  /**
@@ -100,15 +99,17 @@ ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converte
100
99
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
101
100
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
102
101
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
102
+ ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
103
103
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
104
104
  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.";
105
+ ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
105
106
  ConstantString.WrappedCardVersion = "devPreview";
106
107
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
107
108
  ConstantString.WrappedCardResponseLayout = "list";
108
109
  ConstantString.GetMethod = "get";
109
110
  ConstantString.PostMethod = "post";
110
111
  ConstantString.AdaptiveCardVersion = "1.5";
111
- ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
112
+ ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
112
113
  ConstantString.AdaptiveCardType = "AdaptiveCard";
113
114
  ConstantString.TextBlockType = "TextBlock";
114
115
  ConstantString.ImageType = "Image";
@@ -187,16 +188,8 @@ ConstantString.PluginManifestSchema = "https://developer.microsoft.com/json-sche
187
188
 
188
189
  // Copyright (c) Microsoft Corporation.
189
190
  class Utils {
190
- static hasNestedObjectInSchema(schema) {
191
- if (schema.type === "object") {
192
- for (const property in schema.properties) {
193
- const nestedSchema = schema.properties[property];
194
- if (nestedSchema.type === "object") {
195
- return true;
196
- }
197
- }
198
- }
199
- return false;
191
+ static isObjectSchema(schema) {
192
+ return schema.type === "object" || (!schema.type && !!schema.properties);
200
193
  }
201
194
  static containMultipleMediaTypes(bodyObject) {
202
195
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
@@ -264,27 +257,33 @@ class Utils {
264
257
  let multipleMediaType = false;
265
258
  for (const code of ConstantString.ResponseCodeFor20X) {
266
259
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
267
- if (responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) {
268
- for (const contentType of Object.keys(responseObject.content)) {
269
- // json media type can also be "application/json; charset=utf-8"
270
- if (contentType.indexOf("application/json") >= 0) {
271
- multipleMediaType = false;
272
- json = responseObject.content[contentType];
273
- if (Utils.containMultipleMediaTypes(responseObject)) {
274
- multipleMediaType = true;
275
- if (!allowMultipleMediaType) {
276
- json = {};
277
- }
278
- }
279
- else {
280
- return { json, multipleMediaType };
281
- }
282
- }
283
- }
260
+ if (!responseObject) {
261
+ continue;
262
+ }
263
+ multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
264
+ if (!allowMultipleMediaType && multipleMediaType) {
265
+ json = {};
266
+ continue;
267
+ }
268
+ const mediaObj = Utils.getJsonContentType(responseObject);
269
+ if (Object.keys(mediaObj).length > 0) {
270
+ json = mediaObj;
271
+ return { json, multipleMediaType };
284
272
  }
285
273
  }
286
274
  return { json, multipleMediaType };
287
275
  }
276
+ static getJsonContentType(responseObject) {
277
+ if (responseObject.content) {
278
+ for (const contentType of Object.keys(responseObject.content)) {
279
+ // json media type can also be "application/json; charset=utf-8"
280
+ if (contentType.indexOf("application/json") >= 0) {
281
+ return responseObject.content[contentType];
282
+ }
283
+ }
284
+ }
285
+ return {};
286
+ }
288
287
  static convertPathToCamelCase(path) {
289
288
  const pathSegments = path.split(/[./{]/);
290
289
  const camelCaseSegments = pathSegments.map((segment) => {
@@ -320,7 +319,7 @@ class Utils {
320
319
  }
321
320
  return newStr;
322
321
  }
323
- static checkServerUrl(servers) {
322
+ static checkServerUrl(servers, allowHttp = false) {
324
323
  const errors = [];
325
324
  let serverUrl;
326
325
  try {
@@ -343,8 +342,7 @@ class Utils {
343
342
  data: servers,
344
343
  });
345
344
  }
346
- else if (protocol !== "https:") {
347
- // Http server url is not supported
345
+ else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
348
346
  const protocolString = protocol.slice(0, -1);
349
347
  errors.push({
350
348
  type: ErrorType.UrlProtocolNotSupported,
@@ -360,10 +358,11 @@ class Utils {
360
358
  let hasTopLevelServers = false;
361
359
  let hasPathLevelServers = false;
362
360
  let hasOperationLevelServers = false;
361
+ const allowHttp = options.projectType === ProjectType.Copilot;
363
362
  if (spec.servers && spec.servers.length >= 1) {
364
363
  hasTopLevelServers = true;
365
364
  // for multiple server, we only use the first url
366
- const serverErrors = Utils.checkServerUrl(spec.servers);
365
+ const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
367
366
  errors.push(...serverErrors);
368
367
  }
369
368
  const paths = spec.paths;
@@ -371,7 +370,7 @@ class Utils {
371
370
  const methods = paths[path];
372
371
  if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
373
372
  hasPathLevelServers = true;
374
- const serverErrors = Utils.checkServerUrl(methods.servers);
373
+ const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
375
374
  errors.push(...serverErrors);
376
375
  }
377
376
  for (const method in methods) {
@@ -379,7 +378,7 @@ class Utils {
379
378
  if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
380
379
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
381
380
  hasOperationLevelServers = true;
382
- const serverErrors = Utils.checkServerUrl(operationObject.servers);
381
+ const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
383
382
  errors.push(...serverErrors);
384
383
  }
385
384
  }
@@ -426,7 +425,7 @@ class Utils {
426
425
  optionalParams.push(parameter);
427
426
  }
428
427
  }
429
- else if (schema.type === "object") {
428
+ else if (Utils.isObjectSchema(schema)) {
430
429
  const { properties } = schema;
431
430
  for (const property in properties) {
432
431
  let isRequired = false;
@@ -540,29 +539,6 @@ class Utils {
540
539
  const serverUrl = operationServer || methodServer || rootServer;
541
540
  return serverUrl;
542
541
  }
543
- static limitACBodyProperties(body, maxCount) {
544
- const result = [];
545
- let currentCount = 0;
546
- for (const element of body) {
547
- if (element.type === ConstantString.ContainerType) {
548
- const items = this.limitACBodyProperties(element.items, maxCount - currentCount);
549
- result.push({
550
- type: ConstantString.ContainerType,
551
- $data: element.$data,
552
- items: items,
553
- });
554
- currentCount += items.length;
555
- }
556
- else {
557
- result.push(element);
558
- currentCount++;
559
- }
560
- if (currentCount >= maxCount) {
561
- break;
562
- }
563
- }
564
- return result;
565
- }
566
542
  }
567
543
 
568
544
  // Copyright (c) Microsoft Corporation.
@@ -691,22 +667,6 @@ class Validator {
691
667
  }
692
668
  return result;
693
669
  }
694
- validateResponse(method, path) {
695
- const result = { isValid: true, reason: [] };
696
- const operationObject = this.spec.paths[path][method];
697
- const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
698
- if (this.options.projectType === ProjectType.SME) {
699
- // only support response body only contains “application/json” content type
700
- if (multipleMediaType) {
701
- result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
702
- }
703
- else if (Object.keys(json).length === 0) {
704
- // response body should not be empty
705
- result.reason.push(ErrorType.ResponseJsonIsEmpty);
706
- }
707
- }
708
- return result;
709
- }
710
670
  validateServer(method, path) {
711
671
  const result = { isValid: true, reason: [] };
712
672
  const serverObj = Utils.getServerObject(this.spec, method, path);
@@ -715,8 +675,8 @@ class Validator {
715
675
  result.reason.push(ErrorType.NoServerInformation);
716
676
  }
717
677
  else {
718
- // server url should be absolute url with https protocol
719
- const serverValidateResult = Utils.checkServerUrl([serverObj]);
678
+ const allowHttp = this.projectType === ProjectType.Copilot;
679
+ const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
720
680
  result.reason.push(...serverValidateResult.map((item) => item.type));
721
681
  }
722
682
  return result;
@@ -751,125 +711,6 @@ class Validator {
751
711
  }
752
712
  return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
753
713
  }
754
- checkPostBodySchema(schema, isRequired = false) {
755
- var _a;
756
- const paramResult = {
757
- requiredNum: 0,
758
- optionalNum: 0,
759
- isValid: true,
760
- reason: [],
761
- };
762
- if (Object.keys(schema).length === 0) {
763
- return paramResult;
764
- }
765
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
766
- const isCopilot = this.projectType === ProjectType.Copilot;
767
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
768
- paramResult.isValid = false;
769
- paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
770
- return paramResult;
771
- }
772
- if (schema.type === "string" ||
773
- schema.type === "integer" ||
774
- schema.type === "boolean" ||
775
- schema.type === "number") {
776
- if (isRequiredWithoutDefault) {
777
- paramResult.requiredNum = paramResult.requiredNum + 1;
778
- }
779
- else {
780
- paramResult.optionalNum = paramResult.optionalNum + 1;
781
- }
782
- }
783
- else if (schema.type === "object") {
784
- const { properties } = schema;
785
- for (const property in properties) {
786
- let isRequired = false;
787
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
788
- isRequired = true;
789
- }
790
- const result = this.checkPostBodySchema(properties[property], isRequired);
791
- paramResult.requiredNum += result.requiredNum;
792
- paramResult.optionalNum += result.optionalNum;
793
- paramResult.isValid = paramResult.isValid && result.isValid;
794
- paramResult.reason.push(...result.reason);
795
- }
796
- }
797
- else {
798
- if (isRequiredWithoutDefault && !isCopilot) {
799
- paramResult.isValid = false;
800
- paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
801
- }
802
- }
803
- return paramResult;
804
- }
805
- checkParamSchema(paramObject) {
806
- const paramResult = {
807
- requiredNum: 0,
808
- optionalNum: 0,
809
- isValid: true,
810
- reason: [],
811
- };
812
- if (!paramObject) {
813
- return paramResult;
814
- }
815
- const isCopilot = this.projectType === ProjectType.Copilot;
816
- for (let i = 0; i < paramObject.length; i++) {
817
- const param = paramObject[i];
818
- const schema = param.schema;
819
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
820
- paramResult.isValid = false;
821
- paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
822
- continue;
823
- }
824
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
825
- if (isCopilot) {
826
- if (isRequiredWithoutDefault) {
827
- paramResult.requiredNum = paramResult.requiredNum + 1;
828
- }
829
- else {
830
- paramResult.optionalNum = paramResult.optionalNum + 1;
831
- }
832
- continue;
833
- }
834
- if (param.in === "header" || param.in === "cookie") {
835
- if (isRequiredWithoutDefault) {
836
- paramResult.isValid = false;
837
- paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
838
- }
839
- continue;
840
- }
841
- if (schema.type !== "boolean" &&
842
- schema.type !== "string" &&
843
- schema.type !== "number" &&
844
- schema.type !== "integer") {
845
- if (isRequiredWithoutDefault) {
846
- paramResult.isValid = false;
847
- paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
848
- }
849
- continue;
850
- }
851
- if (param.in === "query" || param.in === "path") {
852
- if (isRequiredWithoutDefault) {
853
- paramResult.requiredNum = paramResult.requiredNum + 1;
854
- }
855
- else {
856
- paramResult.optionalNum = paramResult.optionalNum + 1;
857
- }
858
- }
859
- }
860
- return paramResult;
861
- }
862
- hasNestedObjectInSchema(schema) {
863
- if (schema.type === "object") {
864
- for (const property in schema.properties) {
865
- const nestedSchema = schema.properties[property];
866
- if (nestedSchema.type === "object") {
867
- return true;
868
- }
869
- }
870
- }
871
- return false;
872
- }
873
714
  }
874
715
 
875
716
  // Copyright (c) Microsoft Corporation.
@@ -920,24 +761,6 @@ class CopilotValidator extends Validator {
920
761
  // validate server
921
762
  const validateServerResult = this.validateServer(method, path);
922
763
  result.reason.push(...validateServerResult.reason);
923
- // validate response
924
- const validateResponseResult = this.validateResponse(method, path);
925
- result.reason.push(...validateResponseResult.reason);
926
- // validate requestBody
927
- const requestBody = operationObject.requestBody;
928
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
929
- if (requestJsonBody) {
930
- const requestBodySchema = requestJsonBody.schema;
931
- if (requestBodySchema.type !== "object") {
932
- result.reason.push(ErrorType.PostBodySchemaIsNotJson);
933
- }
934
- const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
935
- result.reason.push(...requestBodyParamResult.reason);
936
- }
937
- // validate parameters
938
- const paramObject = operationObject.parameters;
939
- const paramResult = this.checkParamSchema(paramObject);
940
- result.reason.push(...paramResult.reason);
941
764
  if (result.reason.length > 0) {
942
765
  result.isValid = false;
943
766
  }
@@ -1029,6 +852,108 @@ class SMEValidator extends Validator {
1029
852
  }
1030
853
  return result;
1031
854
  }
855
+ validateResponse(method, path) {
856
+ const result = { isValid: true, reason: [] };
857
+ const operationObject = this.spec.paths[path][method];
858
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
859
+ // only support response body only contains “application/json” content type
860
+ if (multipleMediaType) {
861
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
862
+ }
863
+ else if (Object.keys(json).length === 0) {
864
+ // response body should not be empty
865
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
866
+ }
867
+ return result;
868
+ }
869
+ checkPostBodySchema(schema, isRequired = false) {
870
+ var _a;
871
+ const paramResult = {
872
+ requiredNum: 0,
873
+ optionalNum: 0,
874
+ isValid: true,
875
+ reason: [],
876
+ };
877
+ if (Object.keys(schema).length === 0) {
878
+ return paramResult;
879
+ }
880
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
881
+ const isCopilot = this.projectType === ProjectType.Copilot;
882
+ if (schema.type === "string" ||
883
+ schema.type === "integer" ||
884
+ schema.type === "boolean" ||
885
+ schema.type === "number") {
886
+ if (isRequiredWithoutDefault) {
887
+ paramResult.requiredNum = paramResult.requiredNum + 1;
888
+ }
889
+ else {
890
+ paramResult.optionalNum = paramResult.optionalNum + 1;
891
+ }
892
+ }
893
+ else if (Utils.isObjectSchema(schema)) {
894
+ const { properties } = schema;
895
+ for (const property in properties) {
896
+ let isRequired = false;
897
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
898
+ isRequired = true;
899
+ }
900
+ const result = this.checkPostBodySchema(properties[property], isRequired);
901
+ paramResult.requiredNum += result.requiredNum;
902
+ paramResult.optionalNum += result.optionalNum;
903
+ paramResult.isValid = paramResult.isValid && result.isValid;
904
+ paramResult.reason.push(...result.reason);
905
+ }
906
+ }
907
+ else {
908
+ if (isRequiredWithoutDefault && !isCopilot) {
909
+ paramResult.isValid = false;
910
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
911
+ }
912
+ }
913
+ return paramResult;
914
+ }
915
+ checkParamSchema(paramObject) {
916
+ const paramResult = {
917
+ requiredNum: 0,
918
+ optionalNum: 0,
919
+ isValid: true,
920
+ reason: [],
921
+ };
922
+ if (!paramObject) {
923
+ return paramResult;
924
+ }
925
+ for (let i = 0; i < paramObject.length; i++) {
926
+ const param = paramObject[i];
927
+ const schema = param.schema;
928
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
929
+ if (param.in === "header" || param.in === "cookie") {
930
+ if (isRequiredWithoutDefault) {
931
+ paramResult.isValid = false;
932
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
933
+ }
934
+ continue;
935
+ }
936
+ if (schema.type !== "boolean" &&
937
+ schema.type !== "string" &&
938
+ schema.type !== "number" &&
939
+ schema.type !== "integer") {
940
+ if (isRequiredWithoutDefault) {
941
+ paramResult.isValid = false;
942
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
943
+ }
944
+ continue;
945
+ }
946
+ if (param.in === "query" || param.in === "path") {
947
+ if (isRequiredWithoutDefault) {
948
+ paramResult.requiredNum = paramResult.requiredNum + 1;
949
+ }
950
+ else {
951
+ paramResult.optionalNum = paramResult.optionalNum + 1;
952
+ }
953
+ }
954
+ }
955
+ return paramResult;
956
+ }
1032
957
  validateParamCount(postBodyResult, paramResult) {
1033
958
  const result = { isValid: true, reason: [] };
1034
959
  const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
@@ -1304,20 +1229,157 @@ class SpecParser {
1304
1229
  }
1305
1230
  }
1306
1231
 
1232
+ // Copyright (c) Microsoft Corporation.
1233
+ class JsonDataGenerator {
1234
+ static generate(schema) {
1235
+ return this.generateMockData(schema);
1236
+ }
1237
+ static generateMockData(schema) {
1238
+ if (this.visitedSchemas.has(schema)) {
1239
+ return null; // Prevent circular reference
1240
+ }
1241
+ this.visitedSchemas.add(schema);
1242
+ let result;
1243
+ if (schema.anyOf) {
1244
+ // Select the first schema in anyOf
1245
+ const selectedSchema = schema.anyOf[0];
1246
+ result = this.generateMockData(selectedSchema);
1247
+ }
1248
+ else if (schema.oneOf) {
1249
+ // Select the first schema in oneOf
1250
+ const selectedSchema = schema.oneOf[0];
1251
+ result = this.generateMockData(selectedSchema);
1252
+ }
1253
+ else if (schema.allOf) {
1254
+ // merge all schemas in allOf
1255
+ result = {};
1256
+ for (const subschema of schema.allOf) {
1257
+ const data = this.generateMockData(subschema);
1258
+ result = Object.assign(Object.assign({}, result), data);
1259
+ }
1260
+ }
1261
+ else {
1262
+ switch (schema.type) {
1263
+ case "string":
1264
+ if (schema.example !== undefined) {
1265
+ result = schema.example;
1266
+ }
1267
+ else if (schema.format) {
1268
+ switch (schema.format) {
1269
+ case "date-time":
1270
+ result = "2024-11-01T05:25:43.593Z";
1271
+ break;
1272
+ case "email":
1273
+ result = "example@example.com";
1274
+ break;
1275
+ case "uuid":
1276
+ result = "123e4567-e89b-12d3-a456-426614174000";
1277
+ break;
1278
+ case "ipv4":
1279
+ result = "192.168.0.1";
1280
+ break;
1281
+ case "ipv6":
1282
+ result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
1283
+ break;
1284
+ default:
1285
+ result = "example string";
1286
+ }
1287
+ }
1288
+ else {
1289
+ result = "example string";
1290
+ }
1291
+ break;
1292
+ case "number":
1293
+ if (schema.example !== undefined) {
1294
+ result = schema.example;
1295
+ }
1296
+ else if (schema.format) {
1297
+ switch (schema.format) {
1298
+ case "float":
1299
+ result = 3.14;
1300
+ break;
1301
+ case "double":
1302
+ result = 3.14159;
1303
+ break;
1304
+ default:
1305
+ result = 123;
1306
+ }
1307
+ }
1308
+ else {
1309
+ result = 123;
1310
+ }
1311
+ break;
1312
+ case "integer":
1313
+ if (schema.example !== undefined) {
1314
+ result = schema.example;
1315
+ }
1316
+ else if (schema.format) {
1317
+ switch (schema.format) {
1318
+ case "int32":
1319
+ result = 123456;
1320
+ break;
1321
+ case "int64":
1322
+ result = 123456789;
1323
+ break;
1324
+ default:
1325
+ result = 123;
1326
+ }
1327
+ }
1328
+ else {
1329
+ result = 123;
1330
+ }
1331
+ break;
1332
+ case "boolean":
1333
+ result = schema.example !== undefined ? schema.example : true;
1334
+ break;
1335
+ case "array":
1336
+ result = [this.generateMockData(schema.items)];
1337
+ break;
1338
+ case "object":
1339
+ result = {};
1340
+ if (schema.properties) {
1341
+ for (const key in schema.properties) {
1342
+ result[key] = this.generateMockData(schema.properties[key]);
1343
+ }
1344
+ }
1345
+ break;
1346
+ default:
1347
+ result = schema.example || null;
1348
+ }
1349
+ }
1350
+ this.visitedSchemas.delete(schema);
1351
+ return result;
1352
+ }
1353
+ }
1354
+ JsonDataGenerator.visitedSchemas = new Set();
1355
+
1307
1356
  // Copyright (c) Microsoft Corporation.
1308
1357
  class AdaptiveCardGenerator {
1309
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1358
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1310
1359
  try {
1311
1360
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1312
1361
  let cardBody = [];
1362
+ let jsonData = {};
1363
+ const warnings = [];
1364
+ const operationId = operationItem.operationId;
1313
1365
  let schema = json.schema;
1314
1366
  let jsonPath = "$";
1315
1367
  if (schema && Object.keys(schema).length > 0) {
1368
+ try {
1369
+ jsonData = JsonDataGenerator.generate(schema);
1370
+ }
1371
+ catch (err) {
1372
+ warnings.push({
1373
+ type: WarningType.GenerateJsonDataFailed,
1374
+ content: Utils.format(ConstantString.GenerateJsonDataFailed, operationId, err.toString()),
1375
+ data: operationId,
1376
+ });
1377
+ }
1316
1378
  jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
1317
1379
  if (jsonPath !== "$") {
1318
1380
  schema = schema.properties[jsonPath];
1319
1381
  }
1320
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1382
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1321
1383
  }
1322
1384
  // if no schema, try to use example value
1323
1385
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1345,16 +1407,20 @@ class AdaptiveCardGenerator {
1345
1407
  version: ConstantString.AdaptiveCardVersion,
1346
1408
  body: cardBody,
1347
1409
  };
1348
- return [fullCard, jsonPath];
1410
+ return [fullCard, jsonPath, jsonData, warnings];
1349
1411
  }
1350
1412
  catch (err) {
1351
1413
  throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
1352
1414
  }
1353
1415
  }
1354
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1416
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1417
+ if (counter.count >= maxElementCount) {
1418
+ return [];
1419
+ }
1355
1420
  if (schema.type === "array") {
1356
1421
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1357
1422
  if (Object.keys(schema.items).length === 0) {
1423
+ counter.count++;
1358
1424
  return [
1359
1425
  {
1360
1426
  type: ConstantString.TextBlockType,
@@ -1363,7 +1429,7 @@ class AdaptiveCardGenerator {
1363
1429
  },
1364
1430
  ];
1365
1431
  }
1366
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1432
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1367
1433
  const template = {
1368
1434
  type: ConstantString.ContainerType,
1369
1435
  $data: name ? `\${${name}}` : "${$root}",
@@ -1373,11 +1439,11 @@ class AdaptiveCardGenerator {
1373
1439
  return [template];
1374
1440
  }
1375
1441
  // some schema may not contain type but contain properties
1376
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1442
+ if (Utils.isObjectSchema(schema)) {
1377
1443
  const { properties } = schema;
1378
1444
  const result = [];
1379
1445
  for (const property in properties) {
1380
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1446
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1381
1447
  result.push(...obj);
1382
1448
  }
1383
1449
  if (schema.additionalProperties) {
@@ -1390,6 +1456,7 @@ class AdaptiveCardGenerator {
1390
1456
  schema.type === "integer" ||
1391
1457
  schema.type === "boolean" ||
1392
1458
  schema.type === "number") {
1459
+ counter.count++;
1393
1460
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1394
1461
  // string in root: "ddd"
1395
1462
  let text = "result: ${$root}";
@@ -1414,24 +1481,17 @@ class AdaptiveCardGenerator {
1414
1481
  ];
1415
1482
  }
1416
1483
  else {
1417
- if (name) {
1418
- return [
1419
- {
1420
- type: "Image",
1421
- url: `\${${name}}`,
1422
- $when: `\${${name} != null && ${name} != ''}`,
1423
- },
1424
- ];
1425
- }
1426
- else {
1427
- return [
1428
- {
1429
- type: "Image",
1430
- url: "${$data}",
1431
- $when: "${$data != null && $data != ''}",
1432
- },
1433
- ];
1434
- }
1484
+ const url = name ? `\${${name}}` : "${$data}";
1485
+ const condition = name
1486
+ ? `\${${name} != null && ${name} != ''}`
1487
+ : "${$data != null && $data != ''}";
1488
+ return [
1489
+ {
1490
+ type: "Image",
1491
+ url,
1492
+ $when: condition,
1493
+ },
1494
+ ];
1435
1495
  }
1436
1496
  }
1437
1497
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1441,7 +1501,7 @@ class AdaptiveCardGenerator {
1441
1501
  }
1442
1502
  // Find the first array property in the response schema object with the well-known name
1443
1503
  static getResponseJsonPathFromSchema(schema) {
1444
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1504
+ if (Utils.isObjectSchema(schema)) {
1445
1505
  const { properties } = schema;
1446
1506
  for (const property in properties) {
1447
1507
  const schema = properties[property];