@microsoft/m365-spec-parser 0.2.3 → 0.2.4-alpha.e84e1682b.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.
@@ -879,7 +720,6 @@ class CopilotValidator extends Validator {
879
720
  this.projectType = ProjectType.Copilot;
880
721
  this.options = options;
881
722
  this.spec = spec;
882
- this.checkCircularReference();
883
723
  }
884
724
  validateSpec() {
885
725
  const result = { errors: [], warnings: [] };
@@ -905,10 +745,6 @@ class CopilotValidator extends Validator {
905
745
  if (!methodAndPathResult.isValid) {
906
746
  return methodAndPathResult;
907
747
  }
908
- const circularReferenceResult = this.validateCircularReference(method, path);
909
- if (!circularReferenceResult.isValid) {
910
- return circularReferenceResult;
911
- }
912
748
  const operationObject = this.spec.paths[path][method];
913
749
  // validate auth
914
750
  const authCheckResult = this.validateAuth(method, path);
@@ -920,24 +756,6 @@ class CopilotValidator extends Validator {
920
756
  // validate server
921
757
  const validateServerResult = this.validateServer(method, path);
922
758
  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
759
  if (result.reason.length > 0) {
942
760
  result.isValid = false;
943
761
  }
@@ -1029,6 +847,108 @@ class SMEValidator extends Validator {
1029
847
  }
1030
848
  return result;
1031
849
  }
850
+ validateResponse(method, path) {
851
+ const result = { isValid: true, reason: [] };
852
+ const operationObject = this.spec.paths[path][method];
853
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
854
+ // only support response body only contains “application/json” content type
855
+ if (multipleMediaType) {
856
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
857
+ }
858
+ else if (Object.keys(json).length === 0) {
859
+ // response body should not be empty
860
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
861
+ }
862
+ return result;
863
+ }
864
+ checkPostBodySchema(schema, isRequired = false) {
865
+ var _a;
866
+ const paramResult = {
867
+ requiredNum: 0,
868
+ optionalNum: 0,
869
+ isValid: true,
870
+ reason: [],
871
+ };
872
+ if (Object.keys(schema).length === 0) {
873
+ return paramResult;
874
+ }
875
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
876
+ const isCopilot = this.projectType === ProjectType.Copilot;
877
+ if (schema.type === "string" ||
878
+ schema.type === "integer" ||
879
+ schema.type === "boolean" ||
880
+ schema.type === "number") {
881
+ if (isRequiredWithoutDefault) {
882
+ paramResult.requiredNum = paramResult.requiredNum + 1;
883
+ }
884
+ else {
885
+ paramResult.optionalNum = paramResult.optionalNum + 1;
886
+ }
887
+ }
888
+ else if (Utils.isObjectSchema(schema)) {
889
+ const { properties } = schema;
890
+ for (const property in properties) {
891
+ let isRequired = false;
892
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
893
+ isRequired = true;
894
+ }
895
+ const result = this.checkPostBodySchema(properties[property], isRequired);
896
+ paramResult.requiredNum += result.requiredNum;
897
+ paramResult.optionalNum += result.optionalNum;
898
+ paramResult.isValid = paramResult.isValid && result.isValid;
899
+ paramResult.reason.push(...result.reason);
900
+ }
901
+ }
902
+ else {
903
+ if (isRequiredWithoutDefault && !isCopilot) {
904
+ paramResult.isValid = false;
905
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
906
+ }
907
+ }
908
+ return paramResult;
909
+ }
910
+ checkParamSchema(paramObject) {
911
+ const paramResult = {
912
+ requiredNum: 0,
913
+ optionalNum: 0,
914
+ isValid: true,
915
+ reason: [],
916
+ };
917
+ if (!paramObject) {
918
+ return paramResult;
919
+ }
920
+ for (let i = 0; i < paramObject.length; i++) {
921
+ const param = paramObject[i];
922
+ const schema = param.schema;
923
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
924
+ if (param.in === "header" || param.in === "cookie") {
925
+ if (isRequiredWithoutDefault) {
926
+ paramResult.isValid = false;
927
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
928
+ }
929
+ continue;
930
+ }
931
+ if (schema.type !== "boolean" &&
932
+ schema.type !== "string" &&
933
+ schema.type !== "number" &&
934
+ schema.type !== "integer") {
935
+ if (isRequiredWithoutDefault) {
936
+ paramResult.isValid = false;
937
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
938
+ }
939
+ continue;
940
+ }
941
+ if (param.in === "query" || param.in === "path") {
942
+ if (isRequiredWithoutDefault) {
943
+ paramResult.requiredNum = paramResult.requiredNum + 1;
944
+ }
945
+ else {
946
+ paramResult.optionalNum = paramResult.optionalNum + 1;
947
+ }
948
+ }
949
+ }
950
+ return paramResult;
951
+ }
1032
952
  validateParamCount(postBodyResult, paramResult) {
1033
953
  const result = { isValid: true, reason: [] };
1034
954
  const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
@@ -1304,20 +1224,157 @@ class SpecParser {
1304
1224
  }
1305
1225
  }
1306
1226
 
1227
+ // Copyright (c) Microsoft Corporation.
1228
+ class JsonDataGenerator {
1229
+ static generate(schema) {
1230
+ return this.generateMockData(schema);
1231
+ }
1232
+ static generateMockData(schema) {
1233
+ if (this.visitedSchemas.has(schema)) {
1234
+ return null; // Prevent circular reference
1235
+ }
1236
+ this.visitedSchemas.add(schema);
1237
+ let result;
1238
+ if (schema.anyOf) {
1239
+ // Select the first schema in anyOf
1240
+ const selectedSchema = schema.anyOf[0];
1241
+ result = this.generateMockData(selectedSchema);
1242
+ }
1243
+ else if (schema.oneOf) {
1244
+ // Select the first schema in oneOf
1245
+ const selectedSchema = schema.oneOf[0];
1246
+ result = this.generateMockData(selectedSchema);
1247
+ }
1248
+ else if (schema.allOf) {
1249
+ // merge all schemas in allOf
1250
+ result = {};
1251
+ for (const subschema of schema.allOf) {
1252
+ const data = this.generateMockData(subschema);
1253
+ result = Object.assign(Object.assign({}, result), data);
1254
+ }
1255
+ }
1256
+ else {
1257
+ switch (schema.type) {
1258
+ case "string":
1259
+ if (schema.example !== undefined) {
1260
+ result = schema.example;
1261
+ }
1262
+ else if (schema.format) {
1263
+ switch (schema.format) {
1264
+ case "date-time":
1265
+ result = "2024-11-01T05:25:43.593Z";
1266
+ break;
1267
+ case "email":
1268
+ result = "example@example.com";
1269
+ break;
1270
+ case "uuid":
1271
+ result = "123e4567-e89b-12d3-a456-426614174000";
1272
+ break;
1273
+ case "ipv4":
1274
+ result = "192.168.0.1";
1275
+ break;
1276
+ case "ipv6":
1277
+ result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
1278
+ break;
1279
+ default:
1280
+ result = "example string";
1281
+ }
1282
+ }
1283
+ else {
1284
+ result = "example string";
1285
+ }
1286
+ break;
1287
+ case "number":
1288
+ if (schema.example !== undefined) {
1289
+ result = schema.example;
1290
+ }
1291
+ else if (schema.format) {
1292
+ switch (schema.format) {
1293
+ case "float":
1294
+ result = 3.14;
1295
+ break;
1296
+ case "double":
1297
+ result = 3.14159;
1298
+ break;
1299
+ default:
1300
+ result = 123;
1301
+ }
1302
+ }
1303
+ else {
1304
+ result = 123;
1305
+ }
1306
+ break;
1307
+ case "integer":
1308
+ if (schema.example !== undefined) {
1309
+ result = schema.example;
1310
+ }
1311
+ else if (schema.format) {
1312
+ switch (schema.format) {
1313
+ case "int32":
1314
+ result = 123456;
1315
+ break;
1316
+ case "int64":
1317
+ result = 123456789;
1318
+ break;
1319
+ default:
1320
+ result = 123;
1321
+ }
1322
+ }
1323
+ else {
1324
+ result = 123;
1325
+ }
1326
+ break;
1327
+ case "boolean":
1328
+ result = schema.example !== undefined ? schema.example : true;
1329
+ break;
1330
+ case "array":
1331
+ result = [this.generateMockData(schema.items)];
1332
+ break;
1333
+ case "object":
1334
+ result = {};
1335
+ if (schema.properties) {
1336
+ for (const key in schema.properties) {
1337
+ result[key] = this.generateMockData(schema.properties[key]);
1338
+ }
1339
+ }
1340
+ break;
1341
+ default:
1342
+ result = schema.example || null;
1343
+ }
1344
+ }
1345
+ this.visitedSchemas.delete(schema);
1346
+ return result;
1347
+ }
1348
+ }
1349
+ JsonDataGenerator.visitedSchemas = new Set();
1350
+
1307
1351
  // Copyright (c) Microsoft Corporation.
1308
1352
  class AdaptiveCardGenerator {
1309
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1353
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1310
1354
  try {
1311
1355
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1312
1356
  let cardBody = [];
1357
+ let jsonData = {};
1358
+ const warnings = [];
1359
+ const operationId = operationItem.operationId;
1313
1360
  let schema = json.schema;
1314
1361
  let jsonPath = "$";
1315
1362
  if (schema && Object.keys(schema).length > 0) {
1363
+ try {
1364
+ jsonData = JsonDataGenerator.generate(schema);
1365
+ }
1366
+ catch (err) {
1367
+ warnings.push({
1368
+ type: WarningType.GenerateJsonDataFailed,
1369
+ content: Utils.format(ConstantString.GenerateJsonDataFailed, operationId, err.toString()),
1370
+ data: operationId,
1371
+ });
1372
+ }
1316
1373
  jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
1317
1374
  if (jsonPath !== "$") {
1318
1375
  schema = schema.properties[jsonPath];
1319
1376
  }
1320
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1377
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1321
1378
  }
1322
1379
  // if no schema, try to use example value
1323
1380
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1345,16 +1402,20 @@ class AdaptiveCardGenerator {
1345
1402
  version: ConstantString.AdaptiveCardVersion,
1346
1403
  body: cardBody,
1347
1404
  };
1348
- return [fullCard, jsonPath];
1405
+ return [fullCard, jsonPath, jsonData, warnings];
1349
1406
  }
1350
1407
  catch (err) {
1351
1408
  throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
1352
1409
  }
1353
1410
  }
1354
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1411
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1412
+ if (counter.count >= maxElementCount) {
1413
+ return [];
1414
+ }
1355
1415
  if (schema.type === "array") {
1356
1416
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1357
1417
  if (Object.keys(schema.items).length === 0) {
1418
+ counter.count++;
1358
1419
  return [
1359
1420
  {
1360
1421
  type: ConstantString.TextBlockType,
@@ -1363,7 +1424,7 @@ class AdaptiveCardGenerator {
1363
1424
  },
1364
1425
  ];
1365
1426
  }
1366
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1427
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1367
1428
  const template = {
1368
1429
  type: ConstantString.ContainerType,
1369
1430
  $data: name ? `\${${name}}` : "${$root}",
@@ -1373,11 +1434,11 @@ class AdaptiveCardGenerator {
1373
1434
  return [template];
1374
1435
  }
1375
1436
  // some schema may not contain type but contain properties
1376
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1437
+ if (Utils.isObjectSchema(schema)) {
1377
1438
  const { properties } = schema;
1378
1439
  const result = [];
1379
1440
  for (const property in properties) {
1380
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1441
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1381
1442
  result.push(...obj);
1382
1443
  }
1383
1444
  if (schema.additionalProperties) {
@@ -1390,6 +1451,7 @@ class AdaptiveCardGenerator {
1390
1451
  schema.type === "integer" ||
1391
1452
  schema.type === "boolean" ||
1392
1453
  schema.type === "number") {
1454
+ counter.count++;
1393
1455
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1394
1456
  // string in root: "ddd"
1395
1457
  let text = "result: ${$root}";
@@ -1414,24 +1476,17 @@ class AdaptiveCardGenerator {
1414
1476
  ];
1415
1477
  }
1416
1478
  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
- }
1479
+ const url = name ? `\${${name}}` : "${$data}";
1480
+ const condition = name
1481
+ ? `\${${name} != null && ${name} != ''}`
1482
+ : "${$data != null && $data != ''}";
1483
+ return [
1484
+ {
1485
+ type: "Image",
1486
+ url,
1487
+ $when: condition,
1488
+ },
1489
+ ];
1435
1490
  }
1436
1491
  }
1437
1492
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1441,7 +1496,7 @@ class AdaptiveCardGenerator {
1441
1496
  }
1442
1497
  // Find the first array property in the response schema object with the well-known name
1443
1498
  static getResponseJsonPathFromSchema(schema) {
1444
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1499
+ if (Utils.isObjectSchema(schema)) {
1445
1500
  const { properties } = schema;
1446
1501
  for (const property in properties) {
1447
1502
  const schema = properties[property];