@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.
@@ -38,11 +38,8 @@ var ErrorType;
38
38
  ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
39
39
  ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
40
40
  ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
41
- ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
42
41
  ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
43
42
  ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
44
- ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
45
- ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
46
43
  ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
47
44
  ErrorType["NoParameter"] = "no-parameter";
48
45
  ErrorType["NoAPIInfo"] = "no-api-info";
@@ -61,6 +58,8 @@ var WarningType;
61
58
  WarningType["OperationOnlyContainsOptionalParam"] = "operation-only-contains-optional-param";
62
59
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
63
60
  WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
61
+ WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
62
+ WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
64
63
  WarningType["Unknown"] = "unknown";
65
64
  })(WarningType || (WarningType = {}));
66
65
  /**
@@ -98,15 +97,17 @@ ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converte
98
97
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
99
98
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
100
99
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
100
+ ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
101
101
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
102
102
  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.";
103
+ ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
103
104
  ConstantString.WrappedCardVersion = "devPreview";
104
105
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
105
106
  ConstantString.WrappedCardResponseLayout = "list";
106
107
  ConstantString.GetMethod = "get";
107
108
  ConstantString.PostMethod = "post";
108
109
  ConstantString.AdaptiveCardVersion = "1.5";
109
- ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
110
+ ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
110
111
  ConstantString.AdaptiveCardType = "AdaptiveCard";
111
112
  ConstantString.TextBlockType = "TextBlock";
112
113
  ConstantString.ImageType = "Image";
@@ -193,16 +194,8 @@ class SpecParserError extends Error {
193
194
 
194
195
  // Copyright (c) Microsoft Corporation.
195
196
  class Utils {
196
- static hasNestedObjectInSchema(schema) {
197
- if (schema.type === "object") {
198
- for (const property in schema.properties) {
199
- const nestedSchema = schema.properties[property];
200
- if (nestedSchema.type === "object") {
201
- return true;
202
- }
203
- }
204
- }
205
- return false;
197
+ static isObjectSchema(schema) {
198
+ return schema.type === "object" || (!schema.type && !!schema.properties);
206
199
  }
207
200
  static containMultipleMediaTypes(bodyObject) {
208
201
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
@@ -270,27 +263,33 @@ class Utils {
270
263
  let multipleMediaType = false;
271
264
  for (const code of ConstantString.ResponseCodeFor20X) {
272
265
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
273
- if (responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) {
274
- for (const contentType of Object.keys(responseObject.content)) {
275
- // json media type can also be "application/json; charset=utf-8"
276
- if (contentType.indexOf("application/json") >= 0) {
277
- multipleMediaType = false;
278
- json = responseObject.content[contentType];
279
- if (Utils.containMultipleMediaTypes(responseObject)) {
280
- multipleMediaType = true;
281
- if (!allowMultipleMediaType) {
282
- json = {};
283
- }
284
- }
285
- else {
286
- return { json, multipleMediaType };
287
- }
288
- }
289
- }
266
+ if (!responseObject) {
267
+ continue;
268
+ }
269
+ multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
270
+ if (!allowMultipleMediaType && multipleMediaType) {
271
+ json = {};
272
+ continue;
273
+ }
274
+ const mediaObj = Utils.getJsonContentType(responseObject);
275
+ if (Object.keys(mediaObj).length > 0) {
276
+ json = mediaObj;
277
+ return { json, multipleMediaType };
290
278
  }
291
279
  }
292
280
  return { json, multipleMediaType };
293
281
  }
282
+ static getJsonContentType(responseObject) {
283
+ if (responseObject.content) {
284
+ for (const contentType of Object.keys(responseObject.content)) {
285
+ // json media type can also be "application/json; charset=utf-8"
286
+ if (contentType.indexOf("application/json") >= 0) {
287
+ return responseObject.content[contentType];
288
+ }
289
+ }
290
+ }
291
+ return {};
292
+ }
294
293
  static convertPathToCamelCase(path) {
295
294
  const pathSegments = path.split(/[./{]/);
296
295
  const camelCaseSegments = pathSegments.map((segment) => {
@@ -326,7 +325,7 @@ class Utils {
326
325
  }
327
326
  return newStr;
328
327
  }
329
- static checkServerUrl(servers) {
328
+ static checkServerUrl(servers, allowHttp = false) {
330
329
  const errors = [];
331
330
  let serverUrl;
332
331
  try {
@@ -349,8 +348,7 @@ class Utils {
349
348
  data: servers,
350
349
  });
351
350
  }
352
- else if (protocol !== "https:") {
353
- // Http server url is not supported
351
+ else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
354
352
  const protocolString = protocol.slice(0, -1);
355
353
  errors.push({
356
354
  type: ErrorType.UrlProtocolNotSupported,
@@ -366,10 +364,11 @@ class Utils {
366
364
  let hasTopLevelServers = false;
367
365
  let hasPathLevelServers = false;
368
366
  let hasOperationLevelServers = false;
367
+ const allowHttp = options.projectType === ProjectType.Copilot;
369
368
  if (spec.servers && spec.servers.length >= 1) {
370
369
  hasTopLevelServers = true;
371
370
  // for multiple server, we only use the first url
372
- const serverErrors = Utils.checkServerUrl(spec.servers);
371
+ const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
373
372
  errors.push(...serverErrors);
374
373
  }
375
374
  const paths = spec.paths;
@@ -377,7 +376,7 @@ class Utils {
377
376
  const methods = paths[path];
378
377
  if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
379
378
  hasPathLevelServers = true;
380
- const serverErrors = Utils.checkServerUrl(methods.servers);
379
+ const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
381
380
  errors.push(...serverErrors);
382
381
  }
383
382
  for (const method in methods) {
@@ -385,7 +384,7 @@ class Utils {
385
384
  if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
386
385
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
387
386
  hasOperationLevelServers = true;
388
- const serverErrors = Utils.checkServerUrl(operationObject.servers);
387
+ const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
389
388
  errors.push(...serverErrors);
390
389
  }
391
390
  }
@@ -432,7 +431,7 @@ class Utils {
432
431
  optionalParams.push(parameter);
433
432
  }
434
433
  }
435
- else if (schema.type === "object") {
434
+ else if (Utils.isObjectSchema(schema)) {
436
435
  const { properties } = schema;
437
436
  for (const property in properties) {
438
437
  let isRequired = false;
@@ -546,29 +545,6 @@ class Utils {
546
545
  const serverUrl = operationServer || methodServer || rootServer;
547
546
  return serverUrl;
548
547
  }
549
- static limitACBodyProperties(body, maxCount) {
550
- const result = [];
551
- let currentCount = 0;
552
- for (const element of body) {
553
- if (element.type === ConstantString.ContainerType) {
554
- const items = this.limitACBodyProperties(element.items, maxCount - currentCount);
555
- result.push({
556
- type: ConstantString.ContainerType,
557
- $data: element.$data,
558
- items: items,
559
- });
560
- currentCount += items.length;
561
- }
562
- else {
563
- result.push(element);
564
- currentCount++;
565
- }
566
- if (currentCount >= maxCount) {
567
- break;
568
- }
569
- }
570
- return result;
571
- }
572
548
  }
573
549
 
574
550
  // Copyright (c) Microsoft Corporation.
@@ -697,22 +673,6 @@ class Validator {
697
673
  }
698
674
  return result;
699
675
  }
700
- validateResponse(method, path) {
701
- const result = { isValid: true, reason: [] };
702
- const operationObject = this.spec.paths[path][method];
703
- const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
704
- if (this.options.projectType === ProjectType.SME) {
705
- // only support response body only contains “application/json” content type
706
- if (multipleMediaType) {
707
- result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
708
- }
709
- else if (Object.keys(json).length === 0) {
710
- // response body should not be empty
711
- result.reason.push(ErrorType.ResponseJsonIsEmpty);
712
- }
713
- }
714
- return result;
715
- }
716
676
  validateServer(method, path) {
717
677
  const result = { isValid: true, reason: [] };
718
678
  const serverObj = Utils.getServerObject(this.spec, method, path);
@@ -721,8 +681,8 @@ class Validator {
721
681
  result.reason.push(ErrorType.NoServerInformation);
722
682
  }
723
683
  else {
724
- // server url should be absolute url with https protocol
725
- const serverValidateResult = Utils.checkServerUrl([serverObj]);
684
+ const allowHttp = this.projectType === ProjectType.Copilot;
685
+ const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
726
686
  result.reason.push(...serverValidateResult.map((item) => item.type));
727
687
  }
728
688
  return result;
@@ -757,125 +717,6 @@ class Validator {
757
717
  }
758
718
  return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
759
719
  }
760
- checkPostBodySchema(schema, isRequired = false) {
761
- var _a;
762
- const paramResult = {
763
- requiredNum: 0,
764
- optionalNum: 0,
765
- isValid: true,
766
- reason: [],
767
- };
768
- if (Object.keys(schema).length === 0) {
769
- return paramResult;
770
- }
771
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
772
- const isCopilot = this.projectType === ProjectType.Copilot;
773
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
774
- paramResult.isValid = false;
775
- paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
776
- return paramResult;
777
- }
778
- if (schema.type === "string" ||
779
- schema.type === "integer" ||
780
- schema.type === "boolean" ||
781
- schema.type === "number") {
782
- if (isRequiredWithoutDefault) {
783
- paramResult.requiredNum = paramResult.requiredNum + 1;
784
- }
785
- else {
786
- paramResult.optionalNum = paramResult.optionalNum + 1;
787
- }
788
- }
789
- else if (schema.type === "object") {
790
- const { properties } = schema;
791
- for (const property in properties) {
792
- let isRequired = false;
793
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
794
- isRequired = true;
795
- }
796
- const result = this.checkPostBodySchema(properties[property], isRequired);
797
- paramResult.requiredNum += result.requiredNum;
798
- paramResult.optionalNum += result.optionalNum;
799
- paramResult.isValid = paramResult.isValid && result.isValid;
800
- paramResult.reason.push(...result.reason);
801
- }
802
- }
803
- else {
804
- if (isRequiredWithoutDefault && !isCopilot) {
805
- paramResult.isValid = false;
806
- paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
807
- }
808
- }
809
- return paramResult;
810
- }
811
- checkParamSchema(paramObject) {
812
- const paramResult = {
813
- requiredNum: 0,
814
- optionalNum: 0,
815
- isValid: true,
816
- reason: [],
817
- };
818
- if (!paramObject) {
819
- return paramResult;
820
- }
821
- const isCopilot = this.projectType === ProjectType.Copilot;
822
- for (let i = 0; i < paramObject.length; i++) {
823
- const param = paramObject[i];
824
- const schema = param.schema;
825
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
826
- paramResult.isValid = false;
827
- paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
828
- continue;
829
- }
830
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
831
- if (isCopilot) {
832
- if (isRequiredWithoutDefault) {
833
- paramResult.requiredNum = paramResult.requiredNum + 1;
834
- }
835
- else {
836
- paramResult.optionalNum = paramResult.optionalNum + 1;
837
- }
838
- continue;
839
- }
840
- if (param.in === "header" || param.in === "cookie") {
841
- if (isRequiredWithoutDefault) {
842
- paramResult.isValid = false;
843
- paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
844
- }
845
- continue;
846
- }
847
- if (schema.type !== "boolean" &&
848
- schema.type !== "string" &&
849
- schema.type !== "number" &&
850
- schema.type !== "integer") {
851
- if (isRequiredWithoutDefault) {
852
- paramResult.isValid = false;
853
- paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
854
- }
855
- continue;
856
- }
857
- if (param.in === "query" || param.in === "path") {
858
- if (isRequiredWithoutDefault) {
859
- paramResult.requiredNum = paramResult.requiredNum + 1;
860
- }
861
- else {
862
- paramResult.optionalNum = paramResult.optionalNum + 1;
863
- }
864
- }
865
- }
866
- return paramResult;
867
- }
868
- hasNestedObjectInSchema(schema) {
869
- if (schema.type === "object") {
870
- for (const property in schema.properties) {
871
- const nestedSchema = schema.properties[property];
872
- if (nestedSchema.type === "object") {
873
- return true;
874
- }
875
- }
876
- }
877
- return false;
878
- }
879
720
  }
880
721
 
881
722
  // Copyright (c) Microsoft Corporation.
@@ -885,7 +726,6 @@ class CopilotValidator extends Validator {
885
726
  this.projectType = ProjectType.Copilot;
886
727
  this.options = options;
887
728
  this.spec = spec;
888
- this.checkCircularReference();
889
729
  }
890
730
  validateSpec() {
891
731
  const result = { errors: [], warnings: [] };
@@ -911,10 +751,6 @@ class CopilotValidator extends Validator {
911
751
  if (!methodAndPathResult.isValid) {
912
752
  return methodAndPathResult;
913
753
  }
914
- const circularReferenceResult = this.validateCircularReference(method, path);
915
- if (!circularReferenceResult.isValid) {
916
- return circularReferenceResult;
917
- }
918
754
  const operationObject = this.spec.paths[path][method];
919
755
  // validate auth
920
756
  const authCheckResult = this.validateAuth(method, path);
@@ -926,24 +762,6 @@ class CopilotValidator extends Validator {
926
762
  // validate server
927
763
  const validateServerResult = this.validateServer(method, path);
928
764
  result.reason.push(...validateServerResult.reason);
929
- // validate response
930
- const validateResponseResult = this.validateResponse(method, path);
931
- result.reason.push(...validateResponseResult.reason);
932
- // validate requestBody
933
- const requestBody = operationObject.requestBody;
934
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
935
- if (requestJsonBody) {
936
- const requestBodySchema = requestJsonBody.schema;
937
- if (requestBodySchema.type !== "object") {
938
- result.reason.push(ErrorType.PostBodySchemaIsNotJson);
939
- }
940
- const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
941
- result.reason.push(...requestBodyParamResult.reason);
942
- }
943
- // validate parameters
944
- const paramObject = operationObject.parameters;
945
- const paramResult = this.checkParamSchema(paramObject);
946
- result.reason.push(...paramResult.reason);
947
765
  if (result.reason.length > 0) {
948
766
  result.isValid = false;
949
767
  }
@@ -1035,6 +853,108 @@ class SMEValidator extends Validator {
1035
853
  }
1036
854
  return result;
1037
855
  }
856
+ validateResponse(method, path) {
857
+ const result = { isValid: true, reason: [] };
858
+ const operationObject = this.spec.paths[path][method];
859
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
860
+ // only support response body only contains “application/json” content type
861
+ if (multipleMediaType) {
862
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
863
+ }
864
+ else if (Object.keys(json).length === 0) {
865
+ // response body should not be empty
866
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
867
+ }
868
+ return result;
869
+ }
870
+ checkPostBodySchema(schema, isRequired = false) {
871
+ var _a;
872
+ const paramResult = {
873
+ requiredNum: 0,
874
+ optionalNum: 0,
875
+ isValid: true,
876
+ reason: [],
877
+ };
878
+ if (Object.keys(schema).length === 0) {
879
+ return paramResult;
880
+ }
881
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
882
+ const isCopilot = this.projectType === ProjectType.Copilot;
883
+ if (schema.type === "string" ||
884
+ schema.type === "integer" ||
885
+ schema.type === "boolean" ||
886
+ schema.type === "number") {
887
+ if (isRequiredWithoutDefault) {
888
+ paramResult.requiredNum = paramResult.requiredNum + 1;
889
+ }
890
+ else {
891
+ paramResult.optionalNum = paramResult.optionalNum + 1;
892
+ }
893
+ }
894
+ else if (Utils.isObjectSchema(schema)) {
895
+ const { properties } = schema;
896
+ for (const property in properties) {
897
+ let isRequired = false;
898
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
899
+ isRequired = true;
900
+ }
901
+ const result = this.checkPostBodySchema(properties[property], isRequired);
902
+ paramResult.requiredNum += result.requiredNum;
903
+ paramResult.optionalNum += result.optionalNum;
904
+ paramResult.isValid = paramResult.isValid && result.isValid;
905
+ paramResult.reason.push(...result.reason);
906
+ }
907
+ }
908
+ else {
909
+ if (isRequiredWithoutDefault && !isCopilot) {
910
+ paramResult.isValid = false;
911
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
912
+ }
913
+ }
914
+ return paramResult;
915
+ }
916
+ checkParamSchema(paramObject) {
917
+ const paramResult = {
918
+ requiredNum: 0,
919
+ optionalNum: 0,
920
+ isValid: true,
921
+ reason: [],
922
+ };
923
+ if (!paramObject) {
924
+ return paramResult;
925
+ }
926
+ for (let i = 0; i < paramObject.length; i++) {
927
+ const param = paramObject[i];
928
+ const schema = param.schema;
929
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
930
+ if (param.in === "header" || param.in === "cookie") {
931
+ if (isRequiredWithoutDefault) {
932
+ paramResult.isValid = false;
933
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
934
+ }
935
+ continue;
936
+ }
937
+ if (schema.type !== "boolean" &&
938
+ schema.type !== "string" &&
939
+ schema.type !== "number" &&
940
+ schema.type !== "integer") {
941
+ if (isRequiredWithoutDefault) {
942
+ paramResult.isValid = false;
943
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
944
+ }
945
+ continue;
946
+ }
947
+ if (param.in === "query" || param.in === "path") {
948
+ if (isRequiredWithoutDefault) {
949
+ paramResult.requiredNum = paramResult.requiredNum + 1;
950
+ }
951
+ else {
952
+ paramResult.optionalNum = paramResult.optionalNum + 1;
953
+ }
954
+ }
955
+ }
956
+ return paramResult;
957
+ }
1038
958
  validateParamCount(postBodyResult, paramResult) {
1039
959
  const result = { isValid: true, reason: [] };
1040
960
  const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
@@ -1312,20 +1232,157 @@ class SpecFilter {
1312
1232
  }
1313
1233
  }
1314
1234
 
1235
+ // Copyright (c) Microsoft Corporation.
1236
+ class JsonDataGenerator {
1237
+ static generate(schema) {
1238
+ return this.generateMockData(schema);
1239
+ }
1240
+ static generateMockData(schema) {
1241
+ if (this.visitedSchemas.has(schema)) {
1242
+ return null; // Prevent circular reference
1243
+ }
1244
+ this.visitedSchemas.add(schema);
1245
+ let result;
1246
+ if (schema.anyOf) {
1247
+ // Select the first schema in anyOf
1248
+ const selectedSchema = schema.anyOf[0];
1249
+ result = this.generateMockData(selectedSchema);
1250
+ }
1251
+ else if (schema.oneOf) {
1252
+ // Select the first schema in oneOf
1253
+ const selectedSchema = schema.oneOf[0];
1254
+ result = this.generateMockData(selectedSchema);
1255
+ }
1256
+ else if (schema.allOf) {
1257
+ // merge all schemas in allOf
1258
+ result = {};
1259
+ for (const subschema of schema.allOf) {
1260
+ const data = this.generateMockData(subschema);
1261
+ result = Object.assign(Object.assign({}, result), data);
1262
+ }
1263
+ }
1264
+ else {
1265
+ switch (schema.type) {
1266
+ case "string":
1267
+ if (schema.example !== undefined) {
1268
+ result = schema.example;
1269
+ }
1270
+ else if (schema.format) {
1271
+ switch (schema.format) {
1272
+ case "date-time":
1273
+ result = "2024-11-01T05:25:43.593Z";
1274
+ break;
1275
+ case "email":
1276
+ result = "example@example.com";
1277
+ break;
1278
+ case "uuid":
1279
+ result = "123e4567-e89b-12d3-a456-426614174000";
1280
+ break;
1281
+ case "ipv4":
1282
+ result = "192.168.0.1";
1283
+ break;
1284
+ case "ipv6":
1285
+ result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
1286
+ break;
1287
+ default:
1288
+ result = "example string";
1289
+ }
1290
+ }
1291
+ else {
1292
+ result = "example string";
1293
+ }
1294
+ break;
1295
+ case "number":
1296
+ if (schema.example !== undefined) {
1297
+ result = schema.example;
1298
+ }
1299
+ else if (schema.format) {
1300
+ switch (schema.format) {
1301
+ case "float":
1302
+ result = 3.14;
1303
+ break;
1304
+ case "double":
1305
+ result = 3.14159;
1306
+ break;
1307
+ default:
1308
+ result = 123;
1309
+ }
1310
+ }
1311
+ else {
1312
+ result = 123;
1313
+ }
1314
+ break;
1315
+ case "integer":
1316
+ if (schema.example !== undefined) {
1317
+ result = schema.example;
1318
+ }
1319
+ else if (schema.format) {
1320
+ switch (schema.format) {
1321
+ case "int32":
1322
+ result = 123456;
1323
+ break;
1324
+ case "int64":
1325
+ result = 123456789;
1326
+ break;
1327
+ default:
1328
+ result = 123;
1329
+ }
1330
+ }
1331
+ else {
1332
+ result = 123;
1333
+ }
1334
+ break;
1335
+ case "boolean":
1336
+ result = schema.example !== undefined ? schema.example : true;
1337
+ break;
1338
+ case "array":
1339
+ result = [this.generateMockData(schema.items)];
1340
+ break;
1341
+ case "object":
1342
+ result = {};
1343
+ if (schema.properties) {
1344
+ for (const key in schema.properties) {
1345
+ result[key] = this.generateMockData(schema.properties[key]);
1346
+ }
1347
+ }
1348
+ break;
1349
+ default:
1350
+ result = schema.example || null;
1351
+ }
1352
+ }
1353
+ this.visitedSchemas.delete(schema);
1354
+ return result;
1355
+ }
1356
+ }
1357
+ JsonDataGenerator.visitedSchemas = new Set();
1358
+
1315
1359
  // Copyright (c) Microsoft Corporation.
1316
1360
  class AdaptiveCardGenerator {
1317
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1361
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1318
1362
  try {
1319
1363
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1320
1364
  let cardBody = [];
1365
+ let jsonData = {};
1366
+ const warnings = [];
1367
+ const operationId = operationItem.operationId;
1321
1368
  let schema = json.schema;
1322
1369
  let jsonPath = "$";
1323
1370
  if (schema && Object.keys(schema).length > 0) {
1371
+ try {
1372
+ jsonData = JsonDataGenerator.generate(schema);
1373
+ }
1374
+ catch (err) {
1375
+ warnings.push({
1376
+ type: WarningType.GenerateJsonDataFailed,
1377
+ content: Utils.format(ConstantString.GenerateJsonDataFailed, operationId, err.toString()),
1378
+ data: operationId,
1379
+ });
1380
+ }
1324
1381
  jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
1325
1382
  if (jsonPath !== "$") {
1326
1383
  schema = schema.properties[jsonPath];
1327
1384
  }
1328
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1385
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1329
1386
  }
1330
1387
  // if no schema, try to use example value
1331
1388
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1353,16 +1410,20 @@ class AdaptiveCardGenerator {
1353
1410
  version: ConstantString.AdaptiveCardVersion,
1354
1411
  body: cardBody,
1355
1412
  };
1356
- return [fullCard, jsonPath];
1413
+ return [fullCard, jsonPath, jsonData, warnings];
1357
1414
  }
1358
1415
  catch (err) {
1359
1416
  throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
1360
1417
  }
1361
1418
  }
1362
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1419
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1420
+ if (counter.count >= maxElementCount) {
1421
+ return [];
1422
+ }
1363
1423
  if (schema.type === "array") {
1364
1424
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1365
1425
  if (Object.keys(schema.items).length === 0) {
1426
+ counter.count++;
1366
1427
  return [
1367
1428
  {
1368
1429
  type: ConstantString.TextBlockType,
@@ -1371,7 +1432,7 @@ class AdaptiveCardGenerator {
1371
1432
  },
1372
1433
  ];
1373
1434
  }
1374
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1435
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1375
1436
  const template = {
1376
1437
  type: ConstantString.ContainerType,
1377
1438
  $data: name ? `\${${name}}` : "${$root}",
@@ -1381,11 +1442,11 @@ class AdaptiveCardGenerator {
1381
1442
  return [template];
1382
1443
  }
1383
1444
  // some schema may not contain type but contain properties
1384
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1445
+ if (Utils.isObjectSchema(schema)) {
1385
1446
  const { properties } = schema;
1386
1447
  const result = [];
1387
1448
  for (const property in properties) {
1388
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1449
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1389
1450
  result.push(...obj);
1390
1451
  }
1391
1452
  if (schema.additionalProperties) {
@@ -1398,6 +1459,7 @@ class AdaptiveCardGenerator {
1398
1459
  schema.type === "integer" ||
1399
1460
  schema.type === "boolean" ||
1400
1461
  schema.type === "number") {
1462
+ counter.count++;
1401
1463
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1402
1464
  // string in root: "ddd"
1403
1465
  let text = "result: ${$root}";
@@ -1422,24 +1484,17 @@ class AdaptiveCardGenerator {
1422
1484
  ];
1423
1485
  }
1424
1486
  else {
1425
- if (name) {
1426
- return [
1427
- {
1428
- type: "Image",
1429
- url: `\${${name}}`,
1430
- $when: `\${${name} != null && ${name} != ''}`,
1431
- },
1432
- ];
1433
- }
1434
- else {
1435
- return [
1436
- {
1437
- type: "Image",
1438
- url: "${$data}",
1439
- $when: "${$data != null && $data != ''}",
1440
- },
1441
- ];
1442
- }
1487
+ const url = name ? `\${${name}}` : "${$data}";
1488
+ const condition = name
1489
+ ? `\${${name} != null && ${name} != ''}`
1490
+ : "${$data != null && $data != ''}";
1491
+ return [
1492
+ {
1493
+ type: "Image",
1494
+ url,
1495
+ $when: condition,
1496
+ },
1497
+ ];
1443
1498
  }
1444
1499
  }
1445
1500
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1449,7 +1504,7 @@ class AdaptiveCardGenerator {
1449
1504
  }
1450
1505
  // Find the first array property in the response schema object with the well-known name
1451
1506
  static getResponseJsonPathFromSchema(schema) {
1452
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1507
+ if (Utils.isObjectSchema(schema)) {
1453
1508
  const { properties } = schema;
1454
1509
  for (const property in properties) {
1455
1510
  const schema = properties[property];
@@ -1682,36 +1737,11 @@ class ManifestUpdater {
1682
1737
  for (const method in operations) {
1683
1738
  if (options.allowMethods.includes(method)) {
1684
1739
  const operationItem = operations[method];
1685
- const confirmationBodies = [];
1686
1740
  if (operationItem) {
1687
1741
  const operationId = operationItem.operationId;
1688
1742
  const safeFunctionName = operationId.replace(/[^a-zA-Z0-9]/g, "_");
1689
1743
  const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
1690
1744
  const summary = operationItem.summary;
1691
- const paramObject = operationItem.parameters;
1692
- const requestBody = operationItem.requestBody;
1693
- if (paramObject) {
1694
- for (let i = 0; i < paramObject.length; i++) {
1695
- const param = paramObject[i];
1696
- const schema = param.schema;
1697
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1698
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1699
- }
1700
- }
1701
- if (requestBody) {
1702
- const requestJsonBody = requestBody.content["application/json"];
1703
- const requestBodySchema = requestJsonBody.schema;
1704
- if (requestBodySchema.type === "object") {
1705
- for (const property in requestBodySchema.properties) {
1706
- const schema = requestBodySchema.properties[property];
1707
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1708
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1709
- }
1710
- }
1711
- else {
1712
- throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), ErrorType.UpdateManifestFailed);
1713
- }
1714
- }
1715
1745
  let funcDescription = operationItem.description || operationItem.summary || "";
1716
1746
  if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
1717
1747
  warnings.push({
@@ -1729,8 +1759,7 @@ class ManifestUpdater {
1729
1759
  try {
1730
1760
  const { json } = Utils.getResponseJson(operationItem);
1731
1761
  if (json.schema) {
1732
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem);
1733
- card.body = Utils.limitACBodyProperties(card.body, 5);
1762
+ const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem, false, 5);
1734
1763
  const responseSemantic = wrapResponseSemantics(card, jsonPath);
1735
1764
  funcObj.capabilities = {
1736
1765
  response_semantics: responseSemantic,
@@ -1746,14 +1775,39 @@ class ManifestUpdater {
1746
1775
  }
1747
1776
  }
1748
1777
  if (options.allowConfirmation && method !== ConstantString.GetMethod) {
1749
- if (!funcObj.capabilities) {
1750
- funcObj.capabilities = {};
1778
+ const paramObject = operationItem.parameters;
1779
+ const requestBody = operationItem.requestBody;
1780
+ const confirmationBodies = [];
1781
+ if (paramObject) {
1782
+ for (let i = 0; i < paramObject.length; i++) {
1783
+ const param = paramObject[i];
1784
+ const schema = param.schema;
1785
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1786
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1787
+ }
1788
+ }
1789
+ if (requestBody) {
1790
+ const requestJsonBody = Utils.getJsonContentType(requestBody);
1791
+ const requestBodySchema = requestJsonBody.schema;
1792
+ if (Utils.isObjectSchema(requestBodySchema)) {
1793
+ for (const property in requestBodySchema.properties) {
1794
+ const schema = requestBodySchema.properties[property];
1795
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1796
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1797
+ }
1798
+ }
1799
+ else {
1800
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), ErrorType.UpdateManifestFailed);
1801
+ }
1751
1802
  }
1752
- funcObj.capabilities.confirmation = {
1753
- type: "AdaptiveCard",
1754
- title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1755
- };
1756
1803
  if (confirmationBodies.length > 0) {
1804
+ if (!funcObj.capabilities) {
1805
+ funcObj.capabilities = {};
1806
+ }
1807
+ funcObj.capabilities.confirmation = {
1808
+ type: "AdaptiveCard",
1809
+ title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1810
+ };
1757
1811
  funcObj.capabilities.confirmation.body = confirmationBodies.join("\n");
1758
1812
  }
1759
1813
  }
@@ -2189,6 +2243,24 @@ class SpecParser {
2189
2243
  const newUnResolvedSpec = newSpecs[0];
2190
2244
  const newSpec = newSpecs[1];
2191
2245
  const authInfo = Utils.getAuthInfo(newSpec);
2246
+ const paths = newUnResolvedSpec.paths;
2247
+ for (const pathUrl in paths) {
2248
+ const operations = paths[pathUrl];
2249
+ for (const method in operations) {
2250
+ const operationItem = operations[method];
2251
+ const operationId = operationItem.operationId;
2252
+ const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
2253
+ if (!containsSpecialCharacters) {
2254
+ continue;
2255
+ }
2256
+ operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
2257
+ result.warnings.push({
2258
+ type: WarningType.OperationIdContainsSpecialCharacters,
2259
+ content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
2260
+ data: operationId,
2261
+ });
2262
+ }
2263
+ }
2192
2264
  await this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
2193
2265
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
2194
2266
  throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
@@ -2240,13 +2312,14 @@ class SpecParser {
2240
2312
  if (this.options.allowMethods.includes(method)) {
2241
2313
  const operation = newSpec.paths[url][method];
2242
2314
  try {
2243
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
2315
+ const [card, jsonPath, jsonData, warnings] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
2316
+ result.warnings.push(...warnings);
2244
2317
  const safeAdaptiveCardName = operation.operationId.replace(/[^a-zA-Z0-9]/g, "_");
2245
2318
  const fileName = path.join(adaptiveCardFolder, `${safeAdaptiveCardName}.json`);
2246
2319
  const wrappedCard = wrapAdaptiveCard(card, jsonPath);
2247
2320
  await fs.outputJSON(fileName, wrappedCard, { spaces: 2 });
2248
2321
  const dataFileName = path.join(adaptiveCardFolder, `${safeAdaptiveCardName}.data.json`);
2249
- await fs.outputJSON(dataFileName, {}, { spaces: 2 });
2322
+ await fs.outputJSON(dataFileName, jsonData, { spaces: 2 });
2250
2323
  }
2251
2324
  catch (err) {
2252
2325
  result.allSuccess = false;