@microsoft/m365-spec-parser 0.2.5-beta.2025012205.0 → 0.2.5-rc.1

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,8 +80,11 @@ 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";
83
84
  ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
84
85
  ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
86
+ ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
87
+ ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
85
88
  ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
86
89
  ErrorType["NoParameter"] = "no-parameter";
87
90
  ErrorType["NoAPIInfo"] = "no-api-info";
@@ -101,7 +104,6 @@ exports.WarningType = void 0;
101
104
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
102
105
  WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
103
106
  WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
104
- WarningType["UnsupportedAuthType"] = "unsupported-auth-type";
105
107
  WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
106
108
  WarningType["Unknown"] = "unknown";
107
109
  })(exports.WarningType || (exports.WarningType = {}));
@@ -141,7 +143,6 @@ ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please conve
141
143
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
142
144
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
143
145
  ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
144
- ConstantString.AuthTypeIsNotSupported = "Unsupported authorization type in API '%s'. No authorization will be used.";
145
146
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
146
147
  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.";
147
148
  ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
@@ -151,12 +152,17 @@ ConstantString.WrappedCardResponseLayout = "list";
151
152
  ConstantString.GetMethod = "get";
152
153
  ConstantString.PostMethod = "post";
153
154
  ConstantString.AdaptiveCardVersion = "1.5";
154
- ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
155
+ ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
155
156
  ConstantString.AdaptiveCardType = "AdaptiveCard";
156
157
  ConstantString.TextBlockType = "TextBlock";
157
158
  ConstantString.ImageType = "Image";
158
159
  ConstantString.ContainerType = "Container";
159
- ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
160
+ ConstantString.RegistrationIdPostfix = {
161
+ apiKey: "REGISTRATION_ID",
162
+ oauth2: "CONFIGURATION_ID",
163
+ http: "REGISTRATION_ID",
164
+ openIdConnect: "REGISTRATION_ID",
165
+ };
160
166
  ConstantString.ResponseCodeFor20X = [
161
167
  "200",
162
168
  "201",
@@ -168,7 +174,6 @@ ConstantString.ResponseCodeFor20X = [
168
174
  "207",
169
175
  "208",
170
176
  "226",
171
- "2XX",
172
177
  "default",
173
178
  ];
174
179
  ConstantString.AllOperationMethods = [
@@ -234,6 +239,17 @@ class SpecParserError extends Error {
234
239
 
235
240
  // Copyright (c) Microsoft Corporation.
236
241
  class Utils {
242
+ static hasNestedObjectInSchema(schema) {
243
+ if (this.isObjectSchema(schema)) {
244
+ for (const property in schema.properties) {
245
+ const nestedSchema = schema.properties[property];
246
+ if (this.isObjectSchema(nestedSchema)) {
247
+ return true;
248
+ }
249
+ }
250
+ }
251
+ return false;
252
+ }
237
253
  static isObjectSchema(schema) {
238
254
  return schema.type === "object" || (!schema.type && !!schema.properties);
239
255
  }
@@ -246,32 +262,11 @@ class Utils {
246
262
  static isAPIKeyAuth(authScheme) {
247
263
  return authScheme.type === "apiKey";
248
264
  }
249
- static isAPIKeyAuthButNotInCookie(authScheme) {
250
- return authScheme.type === "apiKey" && authScheme.in !== "cookie";
251
- }
252
265
  static isOAuthWithAuthCodeFlow(authScheme) {
253
266
  return !!(authScheme.type === "oauth2" &&
254
267
  authScheme.flows &&
255
268
  authScheme.flows.authorizationCode);
256
269
  }
257
- static isNotSupportedAuth(authSchemeArray) {
258
- if (authSchemeArray.length === 0) {
259
- return false;
260
- }
261
- if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
262
- return true;
263
- }
264
- for (const auths of authSchemeArray) {
265
- if (auths.length === 1) {
266
- if (Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme) ||
267
- Utils.isBearerTokenAuth(auths[0].authScheme) ||
268
- Utils.isAPIKeyAuthButNotInCookie(auths[0].authScheme)) {
269
- return false;
270
- }
271
- }
272
- }
273
- return true;
274
- }
275
270
  static getAuthArray(securities, spec) {
276
271
  var _a;
277
272
  const result = [];
@@ -296,20 +291,6 @@ class Utils {
296
291
  result.sort((a, b) => a[0].name.localeCompare(b[0].name));
297
292
  return result;
298
293
  }
299
- static getAuthMap(spec) {
300
- const authMap = {};
301
- for (const url in spec.paths) {
302
- for (const method in spec.paths[url]) {
303
- const operation = spec.paths[url][method];
304
- const authArray = Utils.getAuthArray(operation.security, spec);
305
- if (authArray && authArray.length > 0) {
306
- const currentAuth = authArray[0][0];
307
- authMap[operation.operationId] = currentAuth;
308
- }
309
- }
310
- }
311
- return authMap;
312
- }
313
294
  static getAuthInfo(spec) {
314
295
  let authInfo = undefined;
315
296
  for (const url in spec.paths) {
@@ -338,32 +319,26 @@ class Utils {
338
319
  let multipleMediaType = false;
339
320
  for (const code of ConstantString.ResponseCodeFor20X) {
340
321
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
341
- if (!responseObject) {
342
- continue;
343
- }
344
- multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
345
- if (!allowMultipleMediaType && multipleMediaType) {
346
- json = {};
347
- continue;
348
- }
349
- const mediaObj = Utils.getJsonContentType(responseObject);
350
- if (Object.keys(mediaObj).length > 0) {
351
- json = mediaObj;
352
- return { json, multipleMediaType };
353
- }
354
- }
355
- return { json, multipleMediaType };
356
- }
357
- static getJsonContentType(responseObject) {
358
- if (responseObject.content) {
359
- for (const contentType of Object.keys(responseObject.content)) {
360
- // json media type can also be "application/json; charset=utf-8"
361
- if (contentType.indexOf("application/json") >= 0) {
362
- return responseObject.content[contentType];
322
+ if (responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) {
323
+ for (const contentType of Object.keys(responseObject.content)) {
324
+ // json media type can also be "application/json; charset=utf-8"
325
+ if (contentType.indexOf("application/json") >= 0) {
326
+ multipleMediaType = false;
327
+ json = responseObject.content[contentType];
328
+ if (Utils.containMultipleMediaTypes(responseObject)) {
329
+ multipleMediaType = true;
330
+ if (!allowMultipleMediaType) {
331
+ json = {};
332
+ }
333
+ }
334
+ else {
335
+ return { json, multipleMediaType };
336
+ }
337
+ }
363
338
  }
364
339
  }
365
340
  }
366
- return {};
341
+ return { json, multipleMediaType };
367
342
  }
368
343
  static convertPathToCamelCase(path) {
369
344
  const pathSegments = path.split(/[./{]/);
@@ -400,7 +375,7 @@ class Utils {
400
375
  }
401
376
  return newStr;
402
377
  }
403
- static checkServerUrl(servers, allowHttp = false) {
378
+ static checkServerUrl(servers) {
404
379
  const errors = [];
405
380
  let serverUrl;
406
381
  try {
@@ -423,7 +398,8 @@ class Utils {
423
398
  data: servers,
424
399
  });
425
400
  }
426
- else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
401
+ else if (protocol !== "https:") {
402
+ // Http server url is not supported
427
403
  const protocolString = protocol.slice(0, -1);
428
404
  errors.push({
429
405
  type: exports.ErrorType.UrlProtocolNotSupported,
@@ -439,11 +415,10 @@ class Utils {
439
415
  let hasTopLevelServers = false;
440
416
  let hasPathLevelServers = false;
441
417
  let hasOperationLevelServers = false;
442
- const allowHttp = options.projectType === exports.ProjectType.Copilot;
443
418
  if (spec.servers && spec.servers.length >= 1) {
444
419
  hasTopLevelServers = true;
445
420
  // for multiple server, we only use the first url
446
- const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
421
+ const serverErrors = Utils.checkServerUrl(spec.servers);
447
422
  errors.push(...serverErrors);
448
423
  }
449
424
  const paths = spec.paths;
@@ -451,7 +426,7 @@ class Utils {
451
426
  const methods = paths[path];
452
427
  if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
453
428
  hasPathLevelServers = true;
454
- const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
429
+ const serverErrors = Utils.checkServerUrl(methods.servers);
455
430
  errors.push(...serverErrors);
456
431
  }
457
432
  for (const method in methods) {
@@ -459,7 +434,7 @@ class Utils {
459
434
  if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
460
435
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
461
436
  hasOperationLevelServers = true;
462
- const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
437
+ const serverErrors = Utils.checkServerUrl(operationObject.servers);
463
438
  errors.push(...serverErrors);
464
439
  }
465
440
  }
@@ -748,6 +723,22 @@ class Validator {
748
723
  }
749
724
  return result;
750
725
  }
726
+ validateResponse(method, path) {
727
+ const result = { isValid: true, reason: [] };
728
+ const operationObject = this.spec.paths[path][method];
729
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
730
+ if (this.options.projectType === exports.ProjectType.SME) {
731
+ // only support response body only contains “application/json” content type
732
+ if (multipleMediaType) {
733
+ result.reason.push(exports.ErrorType.ResponseContainMultipleMediaTypes);
734
+ }
735
+ else if (Object.keys(json).length === 0) {
736
+ // response body should not be empty
737
+ result.reason.push(exports.ErrorType.ResponseJsonIsEmpty);
738
+ }
739
+ }
740
+ return result;
741
+ }
751
742
  validateServer(method, path) {
752
743
  const result = { isValid: true, reason: [] };
753
744
  const serverObj = Utils.getServerObject(this.spec, method, path);
@@ -756,8 +747,8 @@ class Validator {
756
747
  result.reason.push(exports.ErrorType.NoServerInformation);
757
748
  }
758
749
  else {
759
- const allowHttp = this.projectType === exports.ProjectType.Copilot;
760
- const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
750
+ // server url should be absolute url with https protocol
751
+ const serverValidateResult = Utils.checkServerUrl([serverObj]);
761
752
  result.reason.push(...serverValidateResult.map((item) => item.type));
762
753
  }
763
754
  return result;
@@ -780,9 +771,6 @@ class Validator {
780
771
  reason: [exports.ErrorType.MultipleAuthNotSupported],
781
772
  };
782
773
  }
783
- if (this.projectType === exports.ProjectType.Copilot) {
784
- return { isValid: true, reason: [] };
785
- }
786
774
  for (const auths of authSchemeArray) {
787
775
  if (auths.length === 1) {
788
776
  if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
@@ -795,6 +783,114 @@ class Validator {
795
783
  }
796
784
  return { isValid: false, reason: [exports.ErrorType.AuthTypeIsNotSupported] };
797
785
  }
786
+ checkPostBodySchema(schema, isRequired = false) {
787
+ var _a;
788
+ const paramResult = {
789
+ requiredNum: 0,
790
+ optionalNum: 0,
791
+ isValid: true,
792
+ reason: [],
793
+ };
794
+ if (Object.keys(schema).length === 0) {
795
+ return paramResult;
796
+ }
797
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
798
+ const isCopilot = this.projectType === exports.ProjectType.Copilot;
799
+ if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
800
+ paramResult.isValid = false;
801
+ paramResult.reason = [exports.ErrorType.RequestBodyContainsNestedObject];
802
+ return paramResult;
803
+ }
804
+ if (schema.type === "string" ||
805
+ schema.type === "integer" ||
806
+ schema.type === "boolean" ||
807
+ schema.type === "number") {
808
+ if (isRequiredWithoutDefault) {
809
+ paramResult.requiredNum = paramResult.requiredNum + 1;
810
+ }
811
+ else {
812
+ paramResult.optionalNum = paramResult.optionalNum + 1;
813
+ }
814
+ }
815
+ else if (Utils.isObjectSchema(schema)) {
816
+ const { properties } = schema;
817
+ for (const property in properties) {
818
+ let isRequired = false;
819
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
820
+ isRequired = true;
821
+ }
822
+ const result = this.checkPostBodySchema(properties[property], isRequired);
823
+ paramResult.requiredNum += result.requiredNum;
824
+ paramResult.optionalNum += result.optionalNum;
825
+ paramResult.isValid = paramResult.isValid && result.isValid;
826
+ paramResult.reason.push(...result.reason);
827
+ }
828
+ }
829
+ else {
830
+ if (isRequiredWithoutDefault && !isCopilot) {
831
+ paramResult.isValid = false;
832
+ paramResult.reason.push(exports.ErrorType.PostBodyContainsRequiredUnsupportedSchema);
833
+ }
834
+ }
835
+ return paramResult;
836
+ }
837
+ checkParamSchema(paramObject) {
838
+ const paramResult = {
839
+ requiredNum: 0,
840
+ optionalNum: 0,
841
+ isValid: true,
842
+ reason: [],
843
+ };
844
+ if (!paramObject) {
845
+ return paramResult;
846
+ }
847
+ const isCopilot = this.projectType === exports.ProjectType.Copilot;
848
+ for (let i = 0; i < paramObject.length; i++) {
849
+ const param = paramObject[i];
850
+ const schema = param.schema;
851
+ if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
852
+ paramResult.isValid = false;
853
+ paramResult.reason.push(exports.ErrorType.ParamsContainsNestedObject);
854
+ continue;
855
+ }
856
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
857
+ if (isCopilot) {
858
+ if (isRequiredWithoutDefault) {
859
+ paramResult.requiredNum = paramResult.requiredNum + 1;
860
+ }
861
+ else {
862
+ paramResult.optionalNum = paramResult.optionalNum + 1;
863
+ }
864
+ continue;
865
+ }
866
+ if (param.in === "header" || param.in === "cookie") {
867
+ if (isRequiredWithoutDefault) {
868
+ paramResult.isValid = false;
869
+ paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
870
+ }
871
+ continue;
872
+ }
873
+ if (schema.type !== "boolean" &&
874
+ schema.type !== "string" &&
875
+ schema.type !== "number" &&
876
+ schema.type !== "integer") {
877
+ if (isRequiredWithoutDefault) {
878
+ paramResult.isValid = false;
879
+ paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
880
+ }
881
+ continue;
882
+ }
883
+ if (param.in === "query" || param.in === "path") {
884
+ if (isRequiredWithoutDefault) {
885
+ paramResult.requiredNum = paramResult.requiredNum + 1;
886
+ }
887
+ else {
888
+ paramResult.optionalNum = paramResult.optionalNum + 1;
889
+ }
890
+ }
891
+ }
892
+ return paramResult;
893
+ }
798
894
  }
799
895
 
800
896
  // Copyright (c) Microsoft Corporation.
@@ -804,6 +900,7 @@ class CopilotValidator extends Validator {
804
900
  this.projectType = exports.ProjectType.Copilot;
805
901
  this.options = options;
806
902
  this.spec = spec;
903
+ this.checkCircularReference();
807
904
  }
808
905
  validateSpec() {
809
906
  const result = { errors: [], warnings: [] };
@@ -829,6 +926,10 @@ class CopilotValidator extends Validator {
829
926
  if (!methodAndPathResult.isValid) {
830
927
  return methodAndPathResult;
831
928
  }
929
+ const circularReferenceResult = this.validateCircularReference(method, path);
930
+ if (!circularReferenceResult.isValid) {
931
+ return circularReferenceResult;
932
+ }
832
933
  const operationObject = this.spec.paths[path][method];
833
934
  // validate auth
834
935
  const authCheckResult = this.validateAuth(method, path);
@@ -840,6 +941,24 @@ class CopilotValidator extends Validator {
840
941
  // validate server
841
942
  const validateServerResult = this.validateServer(method, path);
842
943
  result.reason.push(...validateServerResult.reason);
944
+ // validate response
945
+ const validateResponseResult = this.validateResponse(method, path);
946
+ result.reason.push(...validateResponseResult.reason);
947
+ // validate requestBody
948
+ const requestBody = operationObject.requestBody;
949
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
950
+ if (requestJsonBody) {
951
+ const requestBodySchema = requestJsonBody.schema;
952
+ if (!Utils.isObjectSchema(requestBodySchema)) {
953
+ result.reason.push(exports.ErrorType.PostBodySchemaIsNotJson);
954
+ }
955
+ const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
956
+ result.reason.push(...requestBodyParamResult.reason);
957
+ }
958
+ // validate parameters
959
+ const paramObject = operationObject.parameters;
960
+ const paramResult = this.checkParamSchema(paramObject);
961
+ result.reason.push(...paramResult.reason);
843
962
  if (result.reason.length > 0) {
844
963
  result.isValid = false;
845
964
  }
@@ -931,108 +1050,6 @@ class SMEValidator extends Validator {
931
1050
  }
932
1051
  return result;
933
1052
  }
934
- validateResponse(method, path) {
935
- const result = { isValid: true, reason: [] };
936
- const operationObject = this.spec.paths[path][method];
937
- const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
938
- // only support response body only contains “application/json” content type
939
- if (multipleMediaType) {
940
- result.reason.push(exports.ErrorType.ResponseContainMultipleMediaTypes);
941
- }
942
- else if (Object.keys(json).length === 0) {
943
- // response body should not be empty
944
- result.reason.push(exports.ErrorType.ResponseJsonIsEmpty);
945
- }
946
- return result;
947
- }
948
- checkPostBodySchema(schema, isRequired = false) {
949
- var _a;
950
- const paramResult = {
951
- requiredNum: 0,
952
- optionalNum: 0,
953
- isValid: true,
954
- reason: [],
955
- };
956
- if (Object.keys(schema).length === 0) {
957
- return paramResult;
958
- }
959
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
960
- const isCopilot = this.projectType === exports.ProjectType.Copilot;
961
- if (schema.type === "string" ||
962
- schema.type === "integer" ||
963
- schema.type === "boolean" ||
964
- schema.type === "number") {
965
- if (isRequiredWithoutDefault) {
966
- paramResult.requiredNum = paramResult.requiredNum + 1;
967
- }
968
- else {
969
- paramResult.optionalNum = paramResult.optionalNum + 1;
970
- }
971
- }
972
- else if (Utils.isObjectSchema(schema)) {
973
- const { properties } = schema;
974
- for (const property in properties) {
975
- let isRequired = false;
976
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
977
- isRequired = true;
978
- }
979
- const result = this.checkPostBodySchema(properties[property], isRequired);
980
- paramResult.requiredNum += result.requiredNum;
981
- paramResult.optionalNum += result.optionalNum;
982
- paramResult.isValid = paramResult.isValid && result.isValid;
983
- paramResult.reason.push(...result.reason);
984
- }
985
- }
986
- else {
987
- if (isRequiredWithoutDefault && !isCopilot) {
988
- paramResult.isValid = false;
989
- paramResult.reason.push(exports.ErrorType.PostBodyContainsRequiredUnsupportedSchema);
990
- }
991
- }
992
- return paramResult;
993
- }
994
- checkParamSchema(paramObject) {
995
- const paramResult = {
996
- requiredNum: 0,
997
- optionalNum: 0,
998
- isValid: true,
999
- reason: [],
1000
- };
1001
- if (!paramObject) {
1002
- return paramResult;
1003
- }
1004
- for (let i = 0; i < paramObject.length; i++) {
1005
- const param = paramObject[i];
1006
- const schema = param.schema;
1007
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
1008
- if (param.in === "header" || param.in === "cookie") {
1009
- if (isRequiredWithoutDefault) {
1010
- paramResult.isValid = false;
1011
- paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
1012
- }
1013
- continue;
1014
- }
1015
- if (schema.type !== "boolean" &&
1016
- schema.type !== "string" &&
1017
- schema.type !== "number" &&
1018
- schema.type !== "integer") {
1019
- if (isRequiredWithoutDefault) {
1020
- paramResult.isValid = false;
1021
- paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
1022
- }
1023
- continue;
1024
- }
1025
- if (param.in === "query" || param.in === "path") {
1026
- if (isRequiredWithoutDefault) {
1027
- paramResult.requiredNum = paramResult.requiredNum + 1;
1028
- }
1029
- else {
1030
- paramResult.optionalNum = paramResult.optionalNum + 1;
1031
- }
1032
- }
1033
- }
1034
- return paramResult;
1035
- }
1036
1053
  validateParamCount(postBodyResult, paramResult) {
1037
1054
  const result = { isValid: true, reason: [] };
1038
1055
  const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
@@ -1734,7 +1751,7 @@ function inferProperties(card) {
1734
1751
 
1735
1752
  // Copyright (c) Microsoft Corporation.
1736
1753
  class ManifestUpdater {
1737
- static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authMap, existingPluginManifestInfo) {
1754
+ static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo, existingPluginManifestInfo) {
1738
1755
  return __awaiter(this, void 0, void 0, function* () {
1739
1756
  const manifest = yield fs__default['default'].readJSON(manifestPath);
1740
1757
  const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
@@ -1765,7 +1782,7 @@ class ManifestUpdater {
1765
1782
  }
1766
1783
  const appName = this.removeEnvs(manifest.name.short);
1767
1784
  const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
1768
- const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo);
1785
+ const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo);
1769
1786
  return [manifest, apiPlugin, warnings];
1770
1787
  });
1771
1788
  }
@@ -1788,14 +1805,29 @@ class ManifestUpdater {
1788
1805
  throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), exports.ErrorType.UpdateManifestFailed);
1789
1806
  }
1790
1807
  }
1791
- static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo) {
1808
+ static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo) {
1792
1809
  var _a, _b, _c, _d;
1793
1810
  return __awaiter(this, void 0, void 0, function* () {
1794
1811
  const warnings = [];
1795
1812
  const functions = [];
1796
- const functionNamesMap = {};
1813
+ const functionNames = [];
1797
1814
  const conversationStarters = [];
1798
1815
  const paths = spec.paths;
1816
+ const pluginAuthObj = {
1817
+ type: "None",
1818
+ };
1819
+ if (authInfo) {
1820
+ if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
1821
+ pluginAuthObj.type = "OAuthPluginVault";
1822
+ }
1823
+ else if (Utils.isBearerTokenAuth(authInfo.authScheme)) {
1824
+ pluginAuthObj.type = "ApiKeyPluginVault";
1825
+ }
1826
+ if (pluginAuthObj.type !== "None") {
1827
+ const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
1828
+ pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
1829
+ }
1830
+ }
1799
1831
  for (const pathUrl in paths) {
1800
1832
  const pathItem = paths[pathUrl];
1801
1833
  if (pathItem) {
@@ -1803,11 +1835,36 @@ class ManifestUpdater {
1803
1835
  for (const method in operations) {
1804
1836
  if (options.allowMethods.includes(method)) {
1805
1837
  const operationItem = operations[method];
1838
+ const confirmationBodies = [];
1806
1839
  if (operationItem) {
1807
1840
  const operationId = operationItem.operationId;
1808
1841
  const safeFunctionName = operationId.replace(/[^a-zA-Z0-9]/g, "_");
1809
1842
  const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
1810
1843
  const summary = operationItem.summary;
1844
+ const paramObject = operationItem.parameters;
1845
+ const requestBody = operationItem.requestBody;
1846
+ if (paramObject) {
1847
+ for (let i = 0; i < paramObject.length; i++) {
1848
+ const param = paramObject[i];
1849
+ const schema = param.schema;
1850
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1851
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1852
+ }
1853
+ }
1854
+ if (requestBody) {
1855
+ const requestJsonBody = requestBody.content["application/json"];
1856
+ const requestBodySchema = requestJsonBody.schema;
1857
+ if (Utils.isObjectSchema(requestBodySchema)) {
1858
+ for (const property in requestBodySchema.properties) {
1859
+ const schema = requestBodySchema.properties[property];
1860
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1861
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1862
+ }
1863
+ }
1864
+ else {
1865
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
1866
+ }
1867
+ }
1811
1868
  let funcDescription = operationItem.description || operationItem.summary || "";
1812
1869
  if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
1813
1870
  warnings.push({
@@ -1841,66 +1898,19 @@ class ManifestUpdater {
1841
1898
  }
1842
1899
  }
1843
1900
  if (options.allowConfirmation && method !== ConstantString.GetMethod) {
1844
- const paramObject = operationItem.parameters;
1845
- const requestBody = operationItem.requestBody;
1846
- const confirmationBodies = [];
1847
- if (paramObject) {
1848
- for (let i = 0; i < paramObject.length; i++) {
1849
- const param = paramObject[i];
1850
- const schema = param.schema;
1851
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1852
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1853
- }
1854
- }
1855
- if (requestBody) {
1856
- const requestJsonBody = Utils.getJsonContentType(requestBody);
1857
- const requestBodySchema = requestJsonBody.schema;
1858
- if (Utils.isObjectSchema(requestBodySchema)) {
1859
- for (const property in requestBodySchema.properties) {
1860
- const schema = requestBodySchema.properties[property];
1861
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1862
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1863
- }
1864
- }
1865
- else {
1866
- throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
1867
- }
1901
+ if (!funcObj.capabilities) {
1902
+ funcObj.capabilities = {};
1868
1903
  }
1904
+ funcObj.capabilities.confirmation = {
1905
+ type: "AdaptiveCard",
1906
+ title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1907
+ };
1869
1908
  if (confirmationBodies.length > 0) {
1870
- if (!funcObj.capabilities) {
1871
- funcObj.capabilities = {};
1872
- }
1873
- funcObj.capabilities.confirmation = {
1874
- type: "AdaptiveCard",
1875
- title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1876
- };
1877
1909
  funcObj.capabilities.confirmation.body = confirmationBodies.join("\n");
1878
1910
  }
1879
1911
  }
1880
1912
  functions.push(funcObj);
1881
- const authInfo = authMap[operationId];
1882
- let key = "None";
1883
- let authName = "None";
1884
- if (authInfo) {
1885
- if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
1886
- key = "OAuthPluginVault";
1887
- authName = authInfo.name;
1888
- }
1889
- else if (Utils.isBearerTokenAuth(authInfo.authScheme) ||
1890
- Utils.isAPIKeyAuthButNotInCookie(authInfo.authScheme)) {
1891
- key = "ApiKeyPluginVault";
1892
- authName = authInfo.name;
1893
- }
1894
- }
1895
- if (functionNamesMap[key]) {
1896
- functionNamesMap[key].functionNames.push(safeFunctionName);
1897
- }
1898
- else {
1899
- functionNamesMap[key] = {
1900
- functionNames: [safeFunctionName],
1901
- authName: authName,
1902
- };
1903
- }
1913
+ functionNames.push(safeFunctionName);
1904
1914
  const conversationStarterStr = (summary !== null && summary !== void 0 ? summary : description).slice(0, ConstantString.ConversationStarterMaxLens);
1905
1915
  if (conversationStarterStr) {
1906
1916
  conversationStarters.push(conversationStarterStr);
@@ -1910,12 +1920,6 @@ class ManifestUpdater {
1910
1920
  }
1911
1921
  }
1912
1922
  }
1913
- if (Object.keys(functionNamesMap).length === 0) {
1914
- functionNamesMap["None"] = {
1915
- functionNames: [],
1916
- authName: "None",
1917
- };
1918
- }
1919
1923
  let apiPlugin;
1920
1924
  if (yield fs__default['default'].pathExists(apiPluginFilePath)) {
1921
1925
  apiPlugin = yield fs__default['default'].readJSON(apiPluginFilePath);
@@ -1951,35 +1955,24 @@ class ManifestUpdater {
1951
1955
  const relativePath = ManifestUpdater.getRelativePath(existingPluginManifestInfo.manifestPath, existingPluginManifestInfo.specPath);
1952
1956
  apiPlugin.runtimes = apiPlugin.runtimes.filter((runtime) => runtime.spec.url !== relativePath);
1953
1957
  }
1954
- for (const authType in functionNamesMap) {
1955
- const pluginAuthObj = {
1956
- type: authType,
1957
- };
1958
- const authName = functionNamesMap[authType].authName;
1959
- if (pluginAuthObj.type !== "None") {
1960
- const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authName}_${ConstantString.RegistrationIdPostfix}`);
1961
- pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
1962
- }
1963
- const functionNamesInfo = functionNamesMap[authType];
1964
- const index = apiPlugin.runtimes.findIndex((runtime) => {
1965
- var _a, _b;
1966
- return runtime.spec.url === specRelativePath &&
1967
- runtime.type === "OpenApi" &&
1968
- ((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === authType;
1958
+ const index = apiPlugin.runtimes.findIndex((runtime) => {
1959
+ var _a, _b;
1960
+ return runtime.spec.url === specRelativePath &&
1961
+ runtime.type === "OpenApi" &&
1962
+ ((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === pluginAuthObj.type;
1963
+ });
1964
+ if (index === -1) {
1965
+ apiPlugin.runtimes.push({
1966
+ type: "OpenApi",
1967
+ auth: pluginAuthObj,
1968
+ spec: {
1969
+ url: specRelativePath,
1970
+ },
1971
+ run_for_functions: functionNames,
1969
1972
  });
1970
- if (index === -1) {
1971
- apiPlugin.runtimes.push({
1972
- type: "OpenApi",
1973
- auth: pluginAuthObj,
1974
- spec: {
1975
- url: specRelativePath,
1976
- },
1977
- run_for_functions: functionNamesInfo.functionNames,
1978
- });
1979
- }
1980
- else {
1981
- apiPlugin.runtimes[index].run_for_functions = functionNamesInfo.functionNames;
1982
- }
1973
+ }
1974
+ else {
1975
+ apiPlugin.runtimes[index].run_for_functions = functionNames;
1983
1976
  }
1984
1977
  if (!apiPlugin.name_for_human) {
1985
1978
  apiPlugin.name_for_human = appName;
@@ -2022,7 +2015,7 @@ class ManifestUpdater {
2022
2015
  };
2023
2016
  if (authInfo) {
2024
2017
  const auth = authInfo.authScheme;
2025
- const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
2018
+ const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
2026
2019
  if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
2027
2020
  composeExtension.authorization = {
2028
2021
  authType: "apiSecretServiceAuth",
@@ -2169,11 +2162,8 @@ class SpecParser {
2169
2162
  yield this.parser.validate(this.spec);
2170
2163
  }
2171
2164
  else {
2172
- // The following code still hangs for Graph API, support will be added when SwaggerParser is updated.
2173
- /*
2174
2165
  const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
2175
- await this.parser.validate(clonedUnResolveSpec);
2176
- */
2166
+ yield this.parser.validate(clonedUnResolveSpec);
2177
2167
  }
2178
2168
  }
2179
2169
  catch (e) {
@@ -2336,7 +2326,7 @@ class SpecParser {
2336
2326
  throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
2337
2327
  }
2338
2328
  const clonedUnResolveSpec = JSON.parse(JSON.stringify(newUnResolvedSpec));
2339
- const newSpec = yield this.deReferenceSpec(clonedUnResolveSpec);
2329
+ const newSpec = (yield this.parser.dereference(clonedUnResolveSpec));
2340
2330
  return [newUnResolvedSpec, newSpec];
2341
2331
  }
2342
2332
  catch (err) {
@@ -2347,12 +2337,6 @@ class SpecParser {
2347
2337
  }
2348
2338
  });
2349
2339
  }
2350
- deReferenceSpec(spec) {
2351
- return __awaiter(this, void 0, void 0, function* () {
2352
- const result = yield this.parser.dereference(spec);
2353
- return result;
2354
- });
2355
- }
2356
2340
  /**
2357
2341
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
2358
2342
  * @param manifestPath A file path of the Teams app manifest file to update.
@@ -2370,6 +2354,7 @@ class SpecParser {
2370
2354
  const newSpecs = yield this.getFilteredSpecs(filter, signal);
2371
2355
  const newUnResolvedSpec = newSpecs[0];
2372
2356
  const newSpec = newSpecs[1];
2357
+ const authInfo = Utils.getAuthInfo(newSpec);
2373
2358
  const paths = newUnResolvedSpec.paths;
2374
2359
  for (const pathUrl in paths) {
2375
2360
  const operations = paths[pathUrl];
@@ -2377,22 +2362,15 @@ class SpecParser {
2377
2362
  const operationItem = operations[method];
2378
2363
  const operationId = operationItem.operationId;
2379
2364
  const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
2380
- if (containsSpecialCharacters) {
2381
- operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
2382
- result.warnings.push({
2383
- type: exports.WarningType.OperationIdContainsSpecialCharacters,
2384
- content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
2385
- data: operationId,
2386
- });
2387
- }
2388
- const authArray = Utils.getAuthArray(operationItem.security, newSpec);
2389
- if (Utils.isNotSupportedAuth(authArray)) {
2390
- result.warnings.push({
2391
- type: exports.WarningType.UnsupportedAuthType,
2392
- content: Utils.format(ConstantString.AuthTypeIsNotSupported, operationId),
2393
- data: operationId,
2394
- });
2365
+ if (!containsSpecialCharacters) {
2366
+ continue;
2395
2367
  }
2368
+ operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
2369
+ result.warnings.push({
2370
+ type: exports.WarningType.OperationIdContainsSpecialCharacters,
2371
+ content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
2372
+ data: operationId,
2373
+ });
2396
2374
  }
2397
2375
  }
2398
2376
  yield this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
@@ -2405,8 +2383,7 @@ class SpecParser {
2405
2383
  specPath: this.pathOrSpec,
2406
2384
  }
2407
2385
  : undefined;
2408
- const authMap = Utils.getAuthMap(newSpec);
2409
- const [updatedManifest, apiPlugin, warnings] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authMap, existingPluginManifestInfo);
2386
+ const [updatedManifest, apiPlugin, warnings] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authInfo, existingPluginManifestInfo);
2410
2387
  result.warnings.push(...warnings);
2411
2388
  yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 4 });
2412
2389
  yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });
@@ -2498,7 +2475,7 @@ class SpecParser {
2498
2475
  this.isSwaggerFile = true;
2499
2476
  }
2500
2477
  const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
2501
- this.spec = yield this.deReferenceSpec(clonedUnResolveSpec);
2478
+ this.spec = (yield this.parser.dereference(clonedUnResolveSpec));
2502
2479
  }
2503
2480
  });
2504
2481
  }