@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.
@@ -80,11 +80,8 @@ exports.ErrorType = void 0;
80
80
  ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
81
81
  ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
82
82
  ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
83
- ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
84
83
  ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
85
84
  ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
86
- ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
87
- ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
88
85
  ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
89
86
  ErrorType["NoParameter"] = "no-parameter";
90
87
  ErrorType["NoAPIInfo"] = "no-api-info";
@@ -103,6 +100,8 @@ exports.WarningType = void 0;
103
100
  WarningType["OperationOnlyContainsOptionalParam"] = "operation-only-contains-optional-param";
104
101
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
105
102
  WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
103
+ WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
104
+ WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
106
105
  WarningType["Unknown"] = "unknown";
107
106
  })(exports.WarningType || (exports.WarningType = {}));
108
107
  /**
@@ -140,15 +139,17 @@ ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converte
140
139
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
141
140
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
142
141
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
142
+ ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
143
143
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
144
144
  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.";
145
+ ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
145
146
  ConstantString.WrappedCardVersion = "devPreview";
146
147
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
147
148
  ConstantString.WrappedCardResponseLayout = "list";
148
149
  ConstantString.GetMethod = "get";
149
150
  ConstantString.PostMethod = "post";
150
151
  ConstantString.AdaptiveCardVersion = "1.5";
151
- ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
152
+ ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
152
153
  ConstantString.AdaptiveCardType = "AdaptiveCard";
153
154
  ConstantString.TextBlockType = "TextBlock";
154
155
  ConstantString.ImageType = "Image";
@@ -235,16 +236,8 @@ class SpecParserError extends Error {
235
236
 
236
237
  // Copyright (c) Microsoft Corporation.
237
238
  class Utils {
238
- static hasNestedObjectInSchema(schema) {
239
- if (schema.type === "object") {
240
- for (const property in schema.properties) {
241
- const nestedSchema = schema.properties[property];
242
- if (nestedSchema.type === "object") {
243
- return true;
244
- }
245
- }
246
- }
247
- return false;
239
+ static isObjectSchema(schema) {
240
+ return schema.type === "object" || (!schema.type && !!schema.properties);
248
241
  }
249
242
  static containMultipleMediaTypes(bodyObject) {
250
243
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
@@ -312,27 +305,33 @@ class Utils {
312
305
  let multipleMediaType = false;
313
306
  for (const code of ConstantString.ResponseCodeFor20X) {
314
307
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
315
- if (responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) {
316
- for (const contentType of Object.keys(responseObject.content)) {
317
- // json media type can also be "application/json; charset=utf-8"
318
- if (contentType.indexOf("application/json") >= 0) {
319
- multipleMediaType = false;
320
- json = responseObject.content[contentType];
321
- if (Utils.containMultipleMediaTypes(responseObject)) {
322
- multipleMediaType = true;
323
- if (!allowMultipleMediaType) {
324
- json = {};
325
- }
326
- }
327
- else {
328
- return { json, multipleMediaType };
329
- }
330
- }
331
- }
308
+ if (!responseObject) {
309
+ continue;
310
+ }
311
+ multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
312
+ if (!allowMultipleMediaType && multipleMediaType) {
313
+ json = {};
314
+ continue;
315
+ }
316
+ const mediaObj = Utils.getJsonContentType(responseObject);
317
+ if (Object.keys(mediaObj).length > 0) {
318
+ json = mediaObj;
319
+ return { json, multipleMediaType };
332
320
  }
333
321
  }
334
322
  return { json, multipleMediaType };
335
323
  }
324
+ static getJsonContentType(responseObject) {
325
+ if (responseObject.content) {
326
+ for (const contentType of Object.keys(responseObject.content)) {
327
+ // json media type can also be "application/json; charset=utf-8"
328
+ if (contentType.indexOf("application/json") >= 0) {
329
+ return responseObject.content[contentType];
330
+ }
331
+ }
332
+ }
333
+ return {};
334
+ }
336
335
  static convertPathToCamelCase(path) {
337
336
  const pathSegments = path.split(/[./{]/);
338
337
  const camelCaseSegments = pathSegments.map((segment) => {
@@ -368,7 +367,7 @@ class Utils {
368
367
  }
369
368
  return newStr;
370
369
  }
371
- static checkServerUrl(servers) {
370
+ static checkServerUrl(servers, allowHttp = false) {
372
371
  const errors = [];
373
372
  let serverUrl;
374
373
  try {
@@ -391,8 +390,7 @@ class Utils {
391
390
  data: servers,
392
391
  });
393
392
  }
394
- else if (protocol !== "https:") {
395
- // Http server url is not supported
393
+ else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
396
394
  const protocolString = protocol.slice(0, -1);
397
395
  errors.push({
398
396
  type: exports.ErrorType.UrlProtocolNotSupported,
@@ -408,10 +406,11 @@ class Utils {
408
406
  let hasTopLevelServers = false;
409
407
  let hasPathLevelServers = false;
410
408
  let hasOperationLevelServers = false;
409
+ const allowHttp = options.projectType === exports.ProjectType.Copilot;
411
410
  if (spec.servers && spec.servers.length >= 1) {
412
411
  hasTopLevelServers = true;
413
412
  // for multiple server, we only use the first url
414
- const serverErrors = Utils.checkServerUrl(spec.servers);
413
+ const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
415
414
  errors.push(...serverErrors);
416
415
  }
417
416
  const paths = spec.paths;
@@ -419,7 +418,7 @@ class Utils {
419
418
  const methods = paths[path];
420
419
  if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
421
420
  hasPathLevelServers = true;
422
- const serverErrors = Utils.checkServerUrl(methods.servers);
421
+ const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
423
422
  errors.push(...serverErrors);
424
423
  }
425
424
  for (const method in methods) {
@@ -427,7 +426,7 @@ class Utils {
427
426
  if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
428
427
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
429
428
  hasOperationLevelServers = true;
430
- const serverErrors = Utils.checkServerUrl(operationObject.servers);
429
+ const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
431
430
  errors.push(...serverErrors);
432
431
  }
433
432
  }
@@ -474,7 +473,7 @@ class Utils {
474
473
  optionalParams.push(parameter);
475
474
  }
476
475
  }
477
- else if (schema.type === "object") {
476
+ else if (Utils.isObjectSchema(schema)) {
478
477
  const { properties } = schema;
479
478
  for (const property in properties) {
480
479
  let isRequired = false;
@@ -588,29 +587,6 @@ class Utils {
588
587
  const serverUrl = operationServer || methodServer || rootServer;
589
588
  return serverUrl;
590
589
  }
591
- static limitACBodyProperties(body, maxCount) {
592
- const result = [];
593
- let currentCount = 0;
594
- for (const element of body) {
595
- if (element.type === ConstantString.ContainerType) {
596
- const items = this.limitACBodyProperties(element.items, maxCount - currentCount);
597
- result.push({
598
- type: ConstantString.ContainerType,
599
- $data: element.$data,
600
- items: items,
601
- });
602
- currentCount += items.length;
603
- }
604
- else {
605
- result.push(element);
606
- currentCount++;
607
- }
608
- if (currentCount >= maxCount) {
609
- break;
610
- }
611
- }
612
- return result;
613
- }
614
590
  }
615
591
 
616
592
  // Copyright (c) Microsoft Corporation.
@@ -739,22 +715,6 @@ class Validator {
739
715
  }
740
716
  return result;
741
717
  }
742
- validateResponse(method, path) {
743
- const result = { isValid: true, reason: [] };
744
- const operationObject = this.spec.paths[path][method];
745
- const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
746
- if (this.options.projectType === exports.ProjectType.SME) {
747
- // only support response body only contains “application/json” content type
748
- if (multipleMediaType) {
749
- result.reason.push(exports.ErrorType.ResponseContainMultipleMediaTypes);
750
- }
751
- else if (Object.keys(json).length === 0) {
752
- // response body should not be empty
753
- result.reason.push(exports.ErrorType.ResponseJsonIsEmpty);
754
- }
755
- }
756
- return result;
757
- }
758
718
  validateServer(method, path) {
759
719
  const result = { isValid: true, reason: [] };
760
720
  const serverObj = Utils.getServerObject(this.spec, method, path);
@@ -763,8 +723,8 @@ class Validator {
763
723
  result.reason.push(exports.ErrorType.NoServerInformation);
764
724
  }
765
725
  else {
766
- // server url should be absolute url with https protocol
767
- const serverValidateResult = Utils.checkServerUrl([serverObj]);
726
+ const allowHttp = this.projectType === exports.ProjectType.Copilot;
727
+ const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
768
728
  result.reason.push(...serverValidateResult.map((item) => item.type));
769
729
  }
770
730
  return result;
@@ -799,125 +759,6 @@ class Validator {
799
759
  }
800
760
  return { isValid: false, reason: [exports.ErrorType.AuthTypeIsNotSupported] };
801
761
  }
802
- checkPostBodySchema(schema, isRequired = false) {
803
- var _a;
804
- const paramResult = {
805
- requiredNum: 0,
806
- optionalNum: 0,
807
- isValid: true,
808
- reason: [],
809
- };
810
- if (Object.keys(schema).length === 0) {
811
- return paramResult;
812
- }
813
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
814
- const isCopilot = this.projectType === exports.ProjectType.Copilot;
815
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
816
- paramResult.isValid = false;
817
- paramResult.reason = [exports.ErrorType.RequestBodyContainsNestedObject];
818
- return paramResult;
819
- }
820
- if (schema.type === "string" ||
821
- schema.type === "integer" ||
822
- schema.type === "boolean" ||
823
- schema.type === "number") {
824
- if (isRequiredWithoutDefault) {
825
- paramResult.requiredNum = paramResult.requiredNum + 1;
826
- }
827
- else {
828
- paramResult.optionalNum = paramResult.optionalNum + 1;
829
- }
830
- }
831
- else if (schema.type === "object") {
832
- const { properties } = schema;
833
- for (const property in properties) {
834
- let isRequired = false;
835
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
836
- isRequired = true;
837
- }
838
- const result = this.checkPostBodySchema(properties[property], isRequired);
839
- paramResult.requiredNum += result.requiredNum;
840
- paramResult.optionalNum += result.optionalNum;
841
- paramResult.isValid = paramResult.isValid && result.isValid;
842
- paramResult.reason.push(...result.reason);
843
- }
844
- }
845
- else {
846
- if (isRequiredWithoutDefault && !isCopilot) {
847
- paramResult.isValid = false;
848
- paramResult.reason.push(exports.ErrorType.PostBodyContainsRequiredUnsupportedSchema);
849
- }
850
- }
851
- return paramResult;
852
- }
853
- checkParamSchema(paramObject) {
854
- const paramResult = {
855
- requiredNum: 0,
856
- optionalNum: 0,
857
- isValid: true,
858
- reason: [],
859
- };
860
- if (!paramObject) {
861
- return paramResult;
862
- }
863
- const isCopilot = this.projectType === exports.ProjectType.Copilot;
864
- for (let i = 0; i < paramObject.length; i++) {
865
- const param = paramObject[i];
866
- const schema = param.schema;
867
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
868
- paramResult.isValid = false;
869
- paramResult.reason.push(exports.ErrorType.ParamsContainsNestedObject);
870
- continue;
871
- }
872
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
873
- if (isCopilot) {
874
- if (isRequiredWithoutDefault) {
875
- paramResult.requiredNum = paramResult.requiredNum + 1;
876
- }
877
- else {
878
- paramResult.optionalNum = paramResult.optionalNum + 1;
879
- }
880
- continue;
881
- }
882
- if (param.in === "header" || param.in === "cookie") {
883
- if (isRequiredWithoutDefault) {
884
- paramResult.isValid = false;
885
- paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
886
- }
887
- continue;
888
- }
889
- if (schema.type !== "boolean" &&
890
- schema.type !== "string" &&
891
- schema.type !== "number" &&
892
- schema.type !== "integer") {
893
- if (isRequiredWithoutDefault) {
894
- paramResult.isValid = false;
895
- paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
896
- }
897
- continue;
898
- }
899
- if (param.in === "query" || param.in === "path") {
900
- if (isRequiredWithoutDefault) {
901
- paramResult.requiredNum = paramResult.requiredNum + 1;
902
- }
903
- else {
904
- paramResult.optionalNum = paramResult.optionalNum + 1;
905
- }
906
- }
907
- }
908
- return paramResult;
909
- }
910
- hasNestedObjectInSchema(schema) {
911
- if (schema.type === "object") {
912
- for (const property in schema.properties) {
913
- const nestedSchema = schema.properties[property];
914
- if (nestedSchema.type === "object") {
915
- return true;
916
- }
917
- }
918
- }
919
- return false;
920
- }
921
762
  }
922
763
 
923
764
  // Copyright (c) Microsoft Corporation.
@@ -968,24 +809,6 @@ class CopilotValidator extends Validator {
968
809
  // validate server
969
810
  const validateServerResult = this.validateServer(method, path);
970
811
  result.reason.push(...validateServerResult.reason);
971
- // validate response
972
- const validateResponseResult = this.validateResponse(method, path);
973
- result.reason.push(...validateResponseResult.reason);
974
- // validate requestBody
975
- const requestBody = operationObject.requestBody;
976
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
977
- if (requestJsonBody) {
978
- const requestBodySchema = requestJsonBody.schema;
979
- if (requestBodySchema.type !== "object") {
980
- result.reason.push(exports.ErrorType.PostBodySchemaIsNotJson);
981
- }
982
- const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
983
- result.reason.push(...requestBodyParamResult.reason);
984
- }
985
- // validate parameters
986
- const paramObject = operationObject.parameters;
987
- const paramResult = this.checkParamSchema(paramObject);
988
- result.reason.push(...paramResult.reason);
989
812
  if (result.reason.length > 0) {
990
813
  result.isValid = false;
991
814
  }
@@ -1077,6 +900,108 @@ class SMEValidator extends Validator {
1077
900
  }
1078
901
  return result;
1079
902
  }
903
+ validateResponse(method, path) {
904
+ const result = { isValid: true, reason: [] };
905
+ const operationObject = this.spec.paths[path][method];
906
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
907
+ // only support response body only contains “application/json” content type
908
+ if (multipleMediaType) {
909
+ result.reason.push(exports.ErrorType.ResponseContainMultipleMediaTypes);
910
+ }
911
+ else if (Object.keys(json).length === 0) {
912
+ // response body should not be empty
913
+ result.reason.push(exports.ErrorType.ResponseJsonIsEmpty);
914
+ }
915
+ return result;
916
+ }
917
+ checkPostBodySchema(schema, isRequired = false) {
918
+ var _a;
919
+ const paramResult = {
920
+ requiredNum: 0,
921
+ optionalNum: 0,
922
+ isValid: true,
923
+ reason: [],
924
+ };
925
+ if (Object.keys(schema).length === 0) {
926
+ return paramResult;
927
+ }
928
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
929
+ const isCopilot = this.projectType === exports.ProjectType.Copilot;
930
+ if (schema.type === "string" ||
931
+ schema.type === "integer" ||
932
+ schema.type === "boolean" ||
933
+ schema.type === "number") {
934
+ if (isRequiredWithoutDefault) {
935
+ paramResult.requiredNum = paramResult.requiredNum + 1;
936
+ }
937
+ else {
938
+ paramResult.optionalNum = paramResult.optionalNum + 1;
939
+ }
940
+ }
941
+ else if (Utils.isObjectSchema(schema)) {
942
+ const { properties } = schema;
943
+ for (const property in properties) {
944
+ let isRequired = false;
945
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
946
+ isRequired = true;
947
+ }
948
+ const result = this.checkPostBodySchema(properties[property], isRequired);
949
+ paramResult.requiredNum += result.requiredNum;
950
+ paramResult.optionalNum += result.optionalNum;
951
+ paramResult.isValid = paramResult.isValid && result.isValid;
952
+ paramResult.reason.push(...result.reason);
953
+ }
954
+ }
955
+ else {
956
+ if (isRequiredWithoutDefault && !isCopilot) {
957
+ paramResult.isValid = false;
958
+ paramResult.reason.push(exports.ErrorType.PostBodyContainsRequiredUnsupportedSchema);
959
+ }
960
+ }
961
+ return paramResult;
962
+ }
963
+ checkParamSchema(paramObject) {
964
+ const paramResult = {
965
+ requiredNum: 0,
966
+ optionalNum: 0,
967
+ isValid: true,
968
+ reason: [],
969
+ };
970
+ if (!paramObject) {
971
+ return paramResult;
972
+ }
973
+ for (let i = 0; i < paramObject.length; i++) {
974
+ const param = paramObject[i];
975
+ const schema = param.schema;
976
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
977
+ if (param.in === "header" || param.in === "cookie") {
978
+ if (isRequiredWithoutDefault) {
979
+ paramResult.isValid = false;
980
+ paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
981
+ }
982
+ continue;
983
+ }
984
+ if (schema.type !== "boolean" &&
985
+ schema.type !== "string" &&
986
+ schema.type !== "number" &&
987
+ schema.type !== "integer") {
988
+ if (isRequiredWithoutDefault) {
989
+ paramResult.isValid = false;
990
+ paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
991
+ }
992
+ continue;
993
+ }
994
+ if (param.in === "query" || param.in === "path") {
995
+ if (isRequiredWithoutDefault) {
996
+ paramResult.requiredNum = paramResult.requiredNum + 1;
997
+ }
998
+ else {
999
+ paramResult.optionalNum = paramResult.optionalNum + 1;
1000
+ }
1001
+ }
1002
+ }
1003
+ return paramResult;
1004
+ }
1080
1005
  validateParamCount(postBodyResult, paramResult) {
1081
1006
  const result = { isValid: true, reason: [] };
1082
1007
  const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
@@ -1354,20 +1279,157 @@ class SpecFilter {
1354
1279
  }
1355
1280
  }
1356
1281
 
1282
+ // Copyright (c) Microsoft Corporation.
1283
+ class JsonDataGenerator {
1284
+ static generate(schema) {
1285
+ return this.generateMockData(schema);
1286
+ }
1287
+ static generateMockData(schema) {
1288
+ if (this.visitedSchemas.has(schema)) {
1289
+ return null; // Prevent circular reference
1290
+ }
1291
+ this.visitedSchemas.add(schema);
1292
+ let result;
1293
+ if (schema.anyOf) {
1294
+ // Select the first schema in anyOf
1295
+ const selectedSchema = schema.anyOf[0];
1296
+ result = this.generateMockData(selectedSchema);
1297
+ }
1298
+ else if (schema.oneOf) {
1299
+ // Select the first schema in oneOf
1300
+ const selectedSchema = schema.oneOf[0];
1301
+ result = this.generateMockData(selectedSchema);
1302
+ }
1303
+ else if (schema.allOf) {
1304
+ // merge all schemas in allOf
1305
+ result = {};
1306
+ for (const subschema of schema.allOf) {
1307
+ const data = this.generateMockData(subschema);
1308
+ result = Object.assign(Object.assign({}, result), data);
1309
+ }
1310
+ }
1311
+ else {
1312
+ switch (schema.type) {
1313
+ case "string":
1314
+ if (schema.example !== undefined) {
1315
+ result = schema.example;
1316
+ }
1317
+ else if (schema.format) {
1318
+ switch (schema.format) {
1319
+ case "date-time":
1320
+ result = "2024-11-01T05:25:43.593Z";
1321
+ break;
1322
+ case "email":
1323
+ result = "example@example.com";
1324
+ break;
1325
+ case "uuid":
1326
+ result = "123e4567-e89b-12d3-a456-426614174000";
1327
+ break;
1328
+ case "ipv4":
1329
+ result = "192.168.0.1";
1330
+ break;
1331
+ case "ipv6":
1332
+ result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
1333
+ break;
1334
+ default:
1335
+ result = "example string";
1336
+ }
1337
+ }
1338
+ else {
1339
+ result = "example string";
1340
+ }
1341
+ break;
1342
+ case "number":
1343
+ if (schema.example !== undefined) {
1344
+ result = schema.example;
1345
+ }
1346
+ else if (schema.format) {
1347
+ switch (schema.format) {
1348
+ case "float":
1349
+ result = 3.14;
1350
+ break;
1351
+ case "double":
1352
+ result = 3.14159;
1353
+ break;
1354
+ default:
1355
+ result = 123;
1356
+ }
1357
+ }
1358
+ else {
1359
+ result = 123;
1360
+ }
1361
+ break;
1362
+ case "integer":
1363
+ if (schema.example !== undefined) {
1364
+ result = schema.example;
1365
+ }
1366
+ else if (schema.format) {
1367
+ switch (schema.format) {
1368
+ case "int32":
1369
+ result = 123456;
1370
+ break;
1371
+ case "int64":
1372
+ result = 123456789;
1373
+ break;
1374
+ default:
1375
+ result = 123;
1376
+ }
1377
+ }
1378
+ else {
1379
+ result = 123;
1380
+ }
1381
+ break;
1382
+ case "boolean":
1383
+ result = schema.example !== undefined ? schema.example : true;
1384
+ break;
1385
+ case "array":
1386
+ result = [this.generateMockData(schema.items)];
1387
+ break;
1388
+ case "object":
1389
+ result = {};
1390
+ if (schema.properties) {
1391
+ for (const key in schema.properties) {
1392
+ result[key] = this.generateMockData(schema.properties[key]);
1393
+ }
1394
+ }
1395
+ break;
1396
+ default:
1397
+ result = schema.example || null;
1398
+ }
1399
+ }
1400
+ this.visitedSchemas.delete(schema);
1401
+ return result;
1402
+ }
1403
+ }
1404
+ JsonDataGenerator.visitedSchemas = new Set();
1405
+
1357
1406
  // Copyright (c) Microsoft Corporation.
1358
1407
  class AdaptiveCardGenerator {
1359
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1408
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1360
1409
  try {
1361
1410
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1362
1411
  let cardBody = [];
1412
+ let jsonData = {};
1413
+ const warnings = [];
1414
+ const operationId = operationItem.operationId;
1363
1415
  let schema = json.schema;
1364
1416
  let jsonPath = "$";
1365
1417
  if (schema && Object.keys(schema).length > 0) {
1418
+ try {
1419
+ jsonData = JsonDataGenerator.generate(schema);
1420
+ }
1421
+ catch (err) {
1422
+ warnings.push({
1423
+ type: exports.WarningType.GenerateJsonDataFailed,
1424
+ content: Utils.format(ConstantString.GenerateJsonDataFailed, operationId, err.toString()),
1425
+ data: operationId,
1426
+ });
1427
+ }
1366
1428
  jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
1367
1429
  if (jsonPath !== "$") {
1368
1430
  schema = schema.properties[jsonPath];
1369
1431
  }
1370
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1432
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1371
1433
  }
1372
1434
  // if no schema, try to use example value
1373
1435
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1395,16 +1457,20 @@ class AdaptiveCardGenerator {
1395
1457
  version: ConstantString.AdaptiveCardVersion,
1396
1458
  body: cardBody,
1397
1459
  };
1398
- return [fullCard, jsonPath];
1460
+ return [fullCard, jsonPath, jsonData, warnings];
1399
1461
  }
1400
1462
  catch (err) {
1401
1463
  throw new SpecParserError(err.toString(), exports.ErrorType.GenerateAdaptiveCardFailed);
1402
1464
  }
1403
1465
  }
1404
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1466
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1467
+ if (counter.count >= maxElementCount) {
1468
+ return [];
1469
+ }
1405
1470
  if (schema.type === "array") {
1406
1471
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1407
1472
  if (Object.keys(schema.items).length === 0) {
1473
+ counter.count++;
1408
1474
  return [
1409
1475
  {
1410
1476
  type: ConstantString.TextBlockType,
@@ -1413,7 +1479,7 @@ class AdaptiveCardGenerator {
1413
1479
  },
1414
1480
  ];
1415
1481
  }
1416
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1482
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1417
1483
  const template = {
1418
1484
  type: ConstantString.ContainerType,
1419
1485
  $data: name ? `\${${name}}` : "${$root}",
@@ -1423,11 +1489,11 @@ class AdaptiveCardGenerator {
1423
1489
  return [template];
1424
1490
  }
1425
1491
  // some schema may not contain type but contain properties
1426
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1492
+ if (Utils.isObjectSchema(schema)) {
1427
1493
  const { properties } = schema;
1428
1494
  const result = [];
1429
1495
  for (const property in properties) {
1430
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1496
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1431
1497
  result.push(...obj);
1432
1498
  }
1433
1499
  if (schema.additionalProperties) {
@@ -1440,6 +1506,7 @@ class AdaptiveCardGenerator {
1440
1506
  schema.type === "integer" ||
1441
1507
  schema.type === "boolean" ||
1442
1508
  schema.type === "number") {
1509
+ counter.count++;
1443
1510
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1444
1511
  // string in root: "ddd"
1445
1512
  let text = "result: ${$root}";
@@ -1464,24 +1531,17 @@ class AdaptiveCardGenerator {
1464
1531
  ];
1465
1532
  }
1466
1533
  else {
1467
- if (name) {
1468
- return [
1469
- {
1470
- type: "Image",
1471
- url: `\${${name}}`,
1472
- $when: `\${${name} != null && ${name} != ''}`,
1473
- },
1474
- ];
1475
- }
1476
- else {
1477
- return [
1478
- {
1479
- type: "Image",
1480
- url: "${$data}",
1481
- $when: "${$data != null && $data != ''}",
1482
- },
1483
- ];
1484
- }
1534
+ const url = name ? `\${${name}}` : "${$data}";
1535
+ const condition = name
1536
+ ? `\${${name} != null && ${name} != ''}`
1537
+ : "${$data != null && $data != ''}";
1538
+ return [
1539
+ {
1540
+ type: "Image",
1541
+ url,
1542
+ $when: condition,
1543
+ },
1544
+ ];
1485
1545
  }
1486
1546
  }
1487
1547
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1491,7 +1551,7 @@ class AdaptiveCardGenerator {
1491
1551
  }
1492
1552
  // Find the first array property in the response schema object with the well-known name
1493
1553
  static getResponseJsonPathFromSchema(schema) {
1494
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1554
+ if (Utils.isObjectSchema(schema)) {
1495
1555
  const { properties } = schema;
1496
1556
  for (const property in properties) {
1497
1557
  const schema = properties[property];
@@ -1727,36 +1787,11 @@ class ManifestUpdater {
1727
1787
  for (const method in operations) {
1728
1788
  if (options.allowMethods.includes(method)) {
1729
1789
  const operationItem = operations[method];
1730
- const confirmationBodies = [];
1731
1790
  if (operationItem) {
1732
1791
  const operationId = operationItem.operationId;
1733
1792
  const safeFunctionName = operationId.replace(/[^a-zA-Z0-9]/g, "_");
1734
1793
  const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
1735
1794
  const summary = operationItem.summary;
1736
- const paramObject = operationItem.parameters;
1737
- const requestBody = operationItem.requestBody;
1738
- if (paramObject) {
1739
- for (let i = 0; i < paramObject.length; i++) {
1740
- const param = paramObject[i];
1741
- const schema = param.schema;
1742
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1743
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1744
- }
1745
- }
1746
- if (requestBody) {
1747
- const requestJsonBody = requestBody.content["application/json"];
1748
- const requestBodySchema = requestJsonBody.schema;
1749
- if (requestBodySchema.type === "object") {
1750
- for (const property in requestBodySchema.properties) {
1751
- const schema = requestBodySchema.properties[property];
1752
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1753
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1754
- }
1755
- }
1756
- else {
1757
- throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
1758
- }
1759
- }
1760
1795
  let funcDescription = operationItem.description || operationItem.summary || "";
1761
1796
  if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
1762
1797
  warnings.push({
@@ -1774,8 +1809,7 @@ class ManifestUpdater {
1774
1809
  try {
1775
1810
  const { json } = Utils.getResponseJson(operationItem);
1776
1811
  if (json.schema) {
1777
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem);
1778
- card.body = Utils.limitACBodyProperties(card.body, 5);
1812
+ const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem, false, 5);
1779
1813
  const responseSemantic = wrapResponseSemantics(card, jsonPath);
1780
1814
  funcObj.capabilities = {
1781
1815
  response_semantics: responseSemantic,
@@ -1791,14 +1825,39 @@ class ManifestUpdater {
1791
1825
  }
1792
1826
  }
1793
1827
  if (options.allowConfirmation && method !== ConstantString.GetMethod) {
1794
- if (!funcObj.capabilities) {
1795
- funcObj.capabilities = {};
1828
+ const paramObject = operationItem.parameters;
1829
+ const requestBody = operationItem.requestBody;
1830
+ const confirmationBodies = [];
1831
+ if (paramObject) {
1832
+ for (let i = 0; i < paramObject.length; i++) {
1833
+ const param = paramObject[i];
1834
+ const schema = param.schema;
1835
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1836
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1837
+ }
1838
+ }
1839
+ if (requestBody) {
1840
+ const requestJsonBody = Utils.getJsonContentType(requestBody);
1841
+ const requestBodySchema = requestJsonBody.schema;
1842
+ if (Utils.isObjectSchema(requestBodySchema)) {
1843
+ for (const property in requestBodySchema.properties) {
1844
+ const schema = requestBodySchema.properties[property];
1845
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1846
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1847
+ }
1848
+ }
1849
+ else {
1850
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
1851
+ }
1796
1852
  }
1797
- funcObj.capabilities.confirmation = {
1798
- type: "AdaptiveCard",
1799
- title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1800
- };
1801
1853
  if (confirmationBodies.length > 0) {
1854
+ if (!funcObj.capabilities) {
1855
+ funcObj.capabilities = {};
1856
+ }
1857
+ funcObj.capabilities.confirmation = {
1858
+ type: "AdaptiveCard",
1859
+ title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1860
+ };
1802
1861
  funcObj.capabilities.confirmation.body = confirmationBodies.join("\n");
1803
1862
  }
1804
1863
  }
@@ -2248,6 +2307,24 @@ class SpecParser {
2248
2307
  const newUnResolvedSpec = newSpecs[0];
2249
2308
  const newSpec = newSpecs[1];
2250
2309
  const authInfo = Utils.getAuthInfo(newSpec);
2310
+ const paths = newUnResolvedSpec.paths;
2311
+ for (const pathUrl in paths) {
2312
+ const operations = paths[pathUrl];
2313
+ for (const method in operations) {
2314
+ const operationItem = operations[method];
2315
+ const operationId = operationItem.operationId;
2316
+ const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
2317
+ if (!containsSpecialCharacters) {
2318
+ continue;
2319
+ }
2320
+ operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
2321
+ result.warnings.push({
2322
+ type: exports.WarningType.OperationIdContainsSpecialCharacters,
2323
+ content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
2324
+ data: operationId,
2325
+ });
2326
+ }
2327
+ }
2251
2328
  yield this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
2252
2329
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
2253
2330
  throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
@@ -2301,13 +2378,14 @@ class SpecParser {
2301
2378
  if (this.options.allowMethods.includes(method)) {
2302
2379
  const operation = newSpec.paths[url][method];
2303
2380
  try {
2304
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
2381
+ const [card, jsonPath, jsonData, warnings] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
2382
+ result.warnings.push(...warnings);
2305
2383
  const safeAdaptiveCardName = operation.operationId.replace(/[^a-zA-Z0-9]/g, "_");
2306
2384
  const fileName = path__default['default'].join(adaptiveCardFolder, `${safeAdaptiveCardName}.json`);
2307
2385
  const wrappedCard = wrapAdaptiveCard(card, jsonPath);
2308
2386
  yield fs__default['default'].outputJSON(fileName, wrappedCard, { spaces: 2 });
2309
2387
  const dataFileName = path__default['default'].join(adaptiveCardFolder, `${safeAdaptiveCardName}.data.json`);
2310
- yield fs__default['default'].outputJSON(dataFileName, {}, { spaces: 2 });
2388
+ yield fs__default['default'].outputJSON(dataFileName, jsonData, { spaces: 2 });
2311
2389
  }
2312
2390
  catch (err) {
2313
2391
  result.allSuccess = false;