@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.
@@ -38,8 +38,11 @@ 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";
41
42
  ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
42
43
  ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
44
+ ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
45
+ ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
43
46
  ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
44
47
  ErrorType["NoParameter"] = "no-parameter";
45
48
  ErrorType["NoAPIInfo"] = "no-api-info";
@@ -59,7 +62,6 @@ var WarningType;
59
62
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
60
63
  WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
61
64
  WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
62
- WarningType["UnsupportedAuthType"] = "unsupported-auth-type";
63
65
  WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
64
66
  WarningType["Unknown"] = "unknown";
65
67
  })(WarningType || (WarningType = {}));
@@ -99,7 +101,6 @@ ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please conve
99
101
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
100
102
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
101
103
  ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
102
- ConstantString.AuthTypeIsNotSupported = "Unsupported authorization type in API '%s'. No authorization will be used.";
103
104
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
104
105
  ConstantString.FuncDescriptionTooLong = "The description of the function '%s' is too long. The current length is %s characters, while the maximum allowed length is %s characters.";
105
106
  ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
@@ -109,12 +110,17 @@ ConstantString.WrappedCardResponseLayout = "list";
109
110
  ConstantString.GetMethod = "get";
110
111
  ConstantString.PostMethod = "post";
111
112
  ConstantString.AdaptiveCardVersion = "1.5";
112
- ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
113
+ ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
113
114
  ConstantString.AdaptiveCardType = "AdaptiveCard";
114
115
  ConstantString.TextBlockType = "TextBlock";
115
116
  ConstantString.ImageType = "Image";
116
117
  ConstantString.ContainerType = "Container";
117
- ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
118
+ ConstantString.RegistrationIdPostfix = {
119
+ apiKey: "REGISTRATION_ID",
120
+ oauth2: "CONFIGURATION_ID",
121
+ http: "REGISTRATION_ID",
122
+ openIdConnect: "REGISTRATION_ID",
123
+ };
118
124
  ConstantString.ResponseCodeFor20X = [
119
125
  "200",
120
126
  "201",
@@ -126,7 +132,6 @@ ConstantString.ResponseCodeFor20X = [
126
132
  "207",
127
133
  "208",
128
134
  "226",
129
- "2XX",
130
135
  "default",
131
136
  ];
132
137
  ConstantString.AllOperationMethods = [
@@ -192,6 +197,17 @@ class SpecParserError extends Error {
192
197
 
193
198
  // Copyright (c) Microsoft Corporation.
194
199
  class Utils {
200
+ static hasNestedObjectInSchema(schema) {
201
+ if (this.isObjectSchema(schema)) {
202
+ for (const property in schema.properties) {
203
+ const nestedSchema = schema.properties[property];
204
+ if (this.isObjectSchema(nestedSchema)) {
205
+ return true;
206
+ }
207
+ }
208
+ }
209
+ return false;
210
+ }
195
211
  static isObjectSchema(schema) {
196
212
  return schema.type === "object" || (!schema.type && !!schema.properties);
197
213
  }
@@ -204,32 +220,11 @@ class Utils {
204
220
  static isAPIKeyAuth(authScheme) {
205
221
  return authScheme.type === "apiKey";
206
222
  }
207
- static isAPIKeyAuthButNotInCookie(authScheme) {
208
- return authScheme.type === "apiKey" && authScheme.in !== "cookie";
209
- }
210
223
  static isOAuthWithAuthCodeFlow(authScheme) {
211
224
  return !!(authScheme.type === "oauth2" &&
212
225
  authScheme.flows &&
213
226
  authScheme.flows.authorizationCode);
214
227
  }
215
- static isNotSupportedAuth(authSchemeArray) {
216
- if (authSchemeArray.length === 0) {
217
- return false;
218
- }
219
- if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
220
- return true;
221
- }
222
- for (const auths of authSchemeArray) {
223
- if (auths.length === 1) {
224
- if (Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme) ||
225
- Utils.isBearerTokenAuth(auths[0].authScheme) ||
226
- Utils.isAPIKeyAuthButNotInCookie(auths[0].authScheme)) {
227
- return false;
228
- }
229
- }
230
- }
231
- return true;
232
- }
233
228
  static getAuthArray(securities, spec) {
234
229
  var _a;
235
230
  const result = [];
@@ -254,20 +249,6 @@ class Utils {
254
249
  result.sort((a, b) => a[0].name.localeCompare(b[0].name));
255
250
  return result;
256
251
  }
257
- static getAuthMap(spec) {
258
- const authMap = {};
259
- for (const url in spec.paths) {
260
- for (const method in spec.paths[url]) {
261
- const operation = spec.paths[url][method];
262
- const authArray = Utils.getAuthArray(operation.security, spec);
263
- if (authArray && authArray.length > 0) {
264
- const currentAuth = authArray[0][0];
265
- authMap[operation.operationId] = currentAuth;
266
- }
267
- }
268
- }
269
- return authMap;
270
- }
271
252
  static getAuthInfo(spec) {
272
253
  let authInfo = undefined;
273
254
  for (const url in spec.paths) {
@@ -296,32 +277,26 @@ class Utils {
296
277
  let multipleMediaType = false;
297
278
  for (const code of ConstantString.ResponseCodeFor20X) {
298
279
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
299
- if (!responseObject) {
300
- continue;
301
- }
302
- multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
303
- if (!allowMultipleMediaType && multipleMediaType) {
304
- json = {};
305
- continue;
306
- }
307
- const mediaObj = Utils.getJsonContentType(responseObject);
308
- if (Object.keys(mediaObj).length > 0) {
309
- json = mediaObj;
310
- return { json, multipleMediaType };
311
- }
312
- }
313
- return { json, multipleMediaType };
314
- }
315
- static getJsonContentType(responseObject) {
316
- if (responseObject.content) {
317
- for (const contentType of Object.keys(responseObject.content)) {
318
- // json media type can also be "application/json; charset=utf-8"
319
- if (contentType.indexOf("application/json") >= 0) {
320
- return responseObject.content[contentType];
280
+ if (responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) {
281
+ for (const contentType of Object.keys(responseObject.content)) {
282
+ // json media type can also be "application/json; charset=utf-8"
283
+ if (contentType.indexOf("application/json") >= 0) {
284
+ multipleMediaType = false;
285
+ json = responseObject.content[contentType];
286
+ if (Utils.containMultipleMediaTypes(responseObject)) {
287
+ multipleMediaType = true;
288
+ if (!allowMultipleMediaType) {
289
+ json = {};
290
+ }
291
+ }
292
+ else {
293
+ return { json, multipleMediaType };
294
+ }
295
+ }
321
296
  }
322
297
  }
323
298
  }
324
- return {};
299
+ return { json, multipleMediaType };
325
300
  }
326
301
  static convertPathToCamelCase(path) {
327
302
  const pathSegments = path.split(/[./{]/);
@@ -358,7 +333,7 @@ class Utils {
358
333
  }
359
334
  return newStr;
360
335
  }
361
- static checkServerUrl(servers, allowHttp = false) {
336
+ static checkServerUrl(servers) {
362
337
  const errors = [];
363
338
  let serverUrl;
364
339
  try {
@@ -381,7 +356,8 @@ class Utils {
381
356
  data: servers,
382
357
  });
383
358
  }
384
- else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
359
+ else if (protocol !== "https:") {
360
+ // Http server url is not supported
385
361
  const protocolString = protocol.slice(0, -1);
386
362
  errors.push({
387
363
  type: ErrorType.UrlProtocolNotSupported,
@@ -397,11 +373,10 @@ class Utils {
397
373
  let hasTopLevelServers = false;
398
374
  let hasPathLevelServers = false;
399
375
  let hasOperationLevelServers = false;
400
- const allowHttp = options.projectType === ProjectType.Copilot;
401
376
  if (spec.servers && spec.servers.length >= 1) {
402
377
  hasTopLevelServers = true;
403
378
  // for multiple server, we only use the first url
404
- const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
379
+ const serverErrors = Utils.checkServerUrl(spec.servers);
405
380
  errors.push(...serverErrors);
406
381
  }
407
382
  const paths = spec.paths;
@@ -409,7 +384,7 @@ class Utils {
409
384
  const methods = paths[path];
410
385
  if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
411
386
  hasPathLevelServers = true;
412
- const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
387
+ const serverErrors = Utils.checkServerUrl(methods.servers);
413
388
  errors.push(...serverErrors);
414
389
  }
415
390
  for (const method in methods) {
@@ -417,7 +392,7 @@ class Utils {
417
392
  if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
418
393
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
419
394
  hasOperationLevelServers = true;
420
- const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
395
+ const serverErrors = Utils.checkServerUrl(operationObject.servers);
421
396
  errors.push(...serverErrors);
422
397
  }
423
398
  }
@@ -706,6 +681,22 @@ class Validator {
706
681
  }
707
682
  return result;
708
683
  }
684
+ validateResponse(method, path) {
685
+ const result = { isValid: true, reason: [] };
686
+ const operationObject = this.spec.paths[path][method];
687
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
688
+ if (this.options.projectType === ProjectType.SME) {
689
+ // only support response body only contains “application/json” content type
690
+ if (multipleMediaType) {
691
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
692
+ }
693
+ else if (Object.keys(json).length === 0) {
694
+ // response body should not be empty
695
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
696
+ }
697
+ }
698
+ return result;
699
+ }
709
700
  validateServer(method, path) {
710
701
  const result = { isValid: true, reason: [] };
711
702
  const serverObj = Utils.getServerObject(this.spec, method, path);
@@ -714,8 +705,8 @@ class Validator {
714
705
  result.reason.push(ErrorType.NoServerInformation);
715
706
  }
716
707
  else {
717
- const allowHttp = this.projectType === ProjectType.Copilot;
718
- const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
708
+ // server url should be absolute url with https protocol
709
+ const serverValidateResult = Utils.checkServerUrl([serverObj]);
719
710
  result.reason.push(...serverValidateResult.map((item) => item.type));
720
711
  }
721
712
  return result;
@@ -738,9 +729,6 @@ class Validator {
738
729
  reason: [ErrorType.MultipleAuthNotSupported],
739
730
  };
740
731
  }
741
- if (this.projectType === ProjectType.Copilot) {
742
- return { isValid: true, reason: [] };
743
- }
744
732
  for (const auths of authSchemeArray) {
745
733
  if (auths.length === 1) {
746
734
  if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
@@ -753,6 +741,114 @@ class Validator {
753
741
  }
754
742
  return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
755
743
  }
744
+ checkPostBodySchema(schema, isRequired = false) {
745
+ var _a;
746
+ const paramResult = {
747
+ requiredNum: 0,
748
+ optionalNum: 0,
749
+ isValid: true,
750
+ reason: [],
751
+ };
752
+ if (Object.keys(schema).length === 0) {
753
+ return paramResult;
754
+ }
755
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
756
+ const isCopilot = this.projectType === ProjectType.Copilot;
757
+ if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
758
+ paramResult.isValid = false;
759
+ paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
760
+ return paramResult;
761
+ }
762
+ if (schema.type === "string" ||
763
+ schema.type === "integer" ||
764
+ schema.type === "boolean" ||
765
+ schema.type === "number") {
766
+ if (isRequiredWithoutDefault) {
767
+ paramResult.requiredNum = paramResult.requiredNum + 1;
768
+ }
769
+ else {
770
+ paramResult.optionalNum = paramResult.optionalNum + 1;
771
+ }
772
+ }
773
+ else if (Utils.isObjectSchema(schema)) {
774
+ const { properties } = schema;
775
+ for (const property in properties) {
776
+ let isRequired = false;
777
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
778
+ isRequired = true;
779
+ }
780
+ const result = this.checkPostBodySchema(properties[property], isRequired);
781
+ paramResult.requiredNum += result.requiredNum;
782
+ paramResult.optionalNum += result.optionalNum;
783
+ paramResult.isValid = paramResult.isValid && result.isValid;
784
+ paramResult.reason.push(...result.reason);
785
+ }
786
+ }
787
+ else {
788
+ if (isRequiredWithoutDefault && !isCopilot) {
789
+ paramResult.isValid = false;
790
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
791
+ }
792
+ }
793
+ return paramResult;
794
+ }
795
+ checkParamSchema(paramObject) {
796
+ const paramResult = {
797
+ requiredNum: 0,
798
+ optionalNum: 0,
799
+ isValid: true,
800
+ reason: [],
801
+ };
802
+ if (!paramObject) {
803
+ return paramResult;
804
+ }
805
+ const isCopilot = this.projectType === ProjectType.Copilot;
806
+ for (let i = 0; i < paramObject.length; i++) {
807
+ const param = paramObject[i];
808
+ const schema = param.schema;
809
+ if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
810
+ paramResult.isValid = false;
811
+ paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
812
+ continue;
813
+ }
814
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
815
+ if (isCopilot) {
816
+ if (isRequiredWithoutDefault) {
817
+ paramResult.requiredNum = paramResult.requiredNum + 1;
818
+ }
819
+ else {
820
+ paramResult.optionalNum = paramResult.optionalNum + 1;
821
+ }
822
+ continue;
823
+ }
824
+ if (param.in === "header" || param.in === "cookie") {
825
+ if (isRequiredWithoutDefault) {
826
+ paramResult.isValid = false;
827
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
828
+ }
829
+ continue;
830
+ }
831
+ if (schema.type !== "boolean" &&
832
+ schema.type !== "string" &&
833
+ schema.type !== "number" &&
834
+ schema.type !== "integer") {
835
+ if (isRequiredWithoutDefault) {
836
+ paramResult.isValid = false;
837
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
838
+ }
839
+ continue;
840
+ }
841
+ if (param.in === "query" || param.in === "path") {
842
+ if (isRequiredWithoutDefault) {
843
+ paramResult.requiredNum = paramResult.requiredNum + 1;
844
+ }
845
+ else {
846
+ paramResult.optionalNum = paramResult.optionalNum + 1;
847
+ }
848
+ }
849
+ }
850
+ return paramResult;
851
+ }
756
852
  }
757
853
 
758
854
  // Copyright (c) Microsoft Corporation.
@@ -762,6 +858,7 @@ class CopilotValidator extends Validator {
762
858
  this.projectType = ProjectType.Copilot;
763
859
  this.options = options;
764
860
  this.spec = spec;
861
+ this.checkCircularReference();
765
862
  }
766
863
  validateSpec() {
767
864
  const result = { errors: [], warnings: [] };
@@ -787,6 +884,10 @@ class CopilotValidator extends Validator {
787
884
  if (!methodAndPathResult.isValid) {
788
885
  return methodAndPathResult;
789
886
  }
887
+ const circularReferenceResult = this.validateCircularReference(method, path);
888
+ if (!circularReferenceResult.isValid) {
889
+ return circularReferenceResult;
890
+ }
790
891
  const operationObject = this.spec.paths[path][method];
791
892
  // validate auth
792
893
  const authCheckResult = this.validateAuth(method, path);
@@ -798,6 +899,24 @@ class CopilotValidator extends Validator {
798
899
  // validate server
799
900
  const validateServerResult = this.validateServer(method, path);
800
901
  result.reason.push(...validateServerResult.reason);
902
+ // validate response
903
+ const validateResponseResult = this.validateResponse(method, path);
904
+ result.reason.push(...validateResponseResult.reason);
905
+ // validate requestBody
906
+ const requestBody = operationObject.requestBody;
907
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
908
+ if (requestJsonBody) {
909
+ const requestBodySchema = requestJsonBody.schema;
910
+ if (!Utils.isObjectSchema(requestBodySchema)) {
911
+ result.reason.push(ErrorType.PostBodySchemaIsNotJson);
912
+ }
913
+ const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
914
+ result.reason.push(...requestBodyParamResult.reason);
915
+ }
916
+ // validate parameters
917
+ const paramObject = operationObject.parameters;
918
+ const paramResult = this.checkParamSchema(paramObject);
919
+ result.reason.push(...paramResult.reason);
801
920
  if (result.reason.length > 0) {
802
921
  result.isValid = false;
803
922
  }
@@ -889,108 +1008,6 @@ class SMEValidator extends Validator {
889
1008
  }
890
1009
  return result;
891
1010
  }
892
- validateResponse(method, path) {
893
- const result = { isValid: true, reason: [] };
894
- const operationObject = this.spec.paths[path][method];
895
- const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
896
- // only support response body only contains “application/json” content type
897
- if (multipleMediaType) {
898
- result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
899
- }
900
- else if (Object.keys(json).length === 0) {
901
- // response body should not be empty
902
- result.reason.push(ErrorType.ResponseJsonIsEmpty);
903
- }
904
- return result;
905
- }
906
- checkPostBodySchema(schema, isRequired = false) {
907
- var _a;
908
- const paramResult = {
909
- requiredNum: 0,
910
- optionalNum: 0,
911
- isValid: true,
912
- reason: [],
913
- };
914
- if (Object.keys(schema).length === 0) {
915
- return paramResult;
916
- }
917
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
918
- const isCopilot = this.projectType === ProjectType.Copilot;
919
- if (schema.type === "string" ||
920
- schema.type === "integer" ||
921
- schema.type === "boolean" ||
922
- schema.type === "number") {
923
- if (isRequiredWithoutDefault) {
924
- paramResult.requiredNum = paramResult.requiredNum + 1;
925
- }
926
- else {
927
- paramResult.optionalNum = paramResult.optionalNum + 1;
928
- }
929
- }
930
- else if (Utils.isObjectSchema(schema)) {
931
- const { properties } = schema;
932
- for (const property in properties) {
933
- let isRequired = false;
934
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
935
- isRequired = true;
936
- }
937
- const result = this.checkPostBodySchema(properties[property], isRequired);
938
- paramResult.requiredNum += result.requiredNum;
939
- paramResult.optionalNum += result.optionalNum;
940
- paramResult.isValid = paramResult.isValid && result.isValid;
941
- paramResult.reason.push(...result.reason);
942
- }
943
- }
944
- else {
945
- if (isRequiredWithoutDefault && !isCopilot) {
946
- paramResult.isValid = false;
947
- paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
948
- }
949
- }
950
- return paramResult;
951
- }
952
- checkParamSchema(paramObject) {
953
- const paramResult = {
954
- requiredNum: 0,
955
- optionalNum: 0,
956
- isValid: true,
957
- reason: [],
958
- };
959
- if (!paramObject) {
960
- return paramResult;
961
- }
962
- for (let i = 0; i < paramObject.length; i++) {
963
- const param = paramObject[i];
964
- const schema = param.schema;
965
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
966
- if (param.in === "header" || param.in === "cookie") {
967
- if (isRequiredWithoutDefault) {
968
- paramResult.isValid = false;
969
- paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
970
- }
971
- continue;
972
- }
973
- if (schema.type !== "boolean" &&
974
- schema.type !== "string" &&
975
- schema.type !== "number" &&
976
- schema.type !== "integer") {
977
- if (isRequiredWithoutDefault) {
978
- paramResult.isValid = false;
979
- paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
980
- }
981
- continue;
982
- }
983
- if (param.in === "query" || param.in === "path") {
984
- if (isRequiredWithoutDefault) {
985
- paramResult.requiredNum = paramResult.requiredNum + 1;
986
- }
987
- else {
988
- paramResult.optionalNum = paramResult.optionalNum + 1;
989
- }
990
- }
991
- }
992
- return paramResult;
993
- }
994
1011
  validateParamCount(postBodyResult, paramResult) {
995
1012
  const result = { isValid: true, reason: [] };
996
1013
  const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
@@ -1692,7 +1709,7 @@ function inferProperties(card) {
1692
1709
 
1693
1710
  // Copyright (c) Microsoft Corporation.
1694
1711
  class ManifestUpdater {
1695
- static async updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authMap, existingPluginManifestInfo) {
1712
+ static async updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo, existingPluginManifestInfo) {
1696
1713
  const manifest = await fs.readJSON(manifestPath);
1697
1714
  const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
1698
1715
  const useCopilotExtensionsInSchema = await ManifestUtil.useCopilotExtensionsInSchema(manifest);
@@ -1722,7 +1739,7 @@ class ManifestUpdater {
1722
1739
  }
1723
1740
  const appName = this.removeEnvs(manifest.name.short);
1724
1741
  const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
1725
- const [apiPlugin, warnings] = await ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo);
1742
+ const [apiPlugin, warnings] = await ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo);
1726
1743
  return [manifest, apiPlugin, warnings];
1727
1744
  }
1728
1745
  static updateManifestDescription(manifest, spec) {
@@ -1744,13 +1761,28 @@ class ManifestUpdater {
1744
1761
  throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), ErrorType.UpdateManifestFailed);
1745
1762
  }
1746
1763
  }
1747
- static async generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo) {
1764
+ static async generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo) {
1748
1765
  var _a, _b, _c, _d;
1749
1766
  const warnings = [];
1750
1767
  const functions = [];
1751
- const functionNamesMap = {};
1768
+ const functionNames = [];
1752
1769
  const conversationStarters = [];
1753
1770
  const paths = spec.paths;
1771
+ const pluginAuthObj = {
1772
+ type: "None",
1773
+ };
1774
+ if (authInfo) {
1775
+ if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
1776
+ pluginAuthObj.type = "OAuthPluginVault";
1777
+ }
1778
+ else if (Utils.isBearerTokenAuth(authInfo.authScheme)) {
1779
+ pluginAuthObj.type = "ApiKeyPluginVault";
1780
+ }
1781
+ if (pluginAuthObj.type !== "None") {
1782
+ const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
1783
+ pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
1784
+ }
1785
+ }
1754
1786
  for (const pathUrl in paths) {
1755
1787
  const pathItem = paths[pathUrl];
1756
1788
  if (pathItem) {
@@ -1758,11 +1790,36 @@ class ManifestUpdater {
1758
1790
  for (const method in operations) {
1759
1791
  if (options.allowMethods.includes(method)) {
1760
1792
  const operationItem = operations[method];
1793
+ const confirmationBodies = [];
1761
1794
  if (operationItem) {
1762
1795
  const operationId = operationItem.operationId;
1763
1796
  const safeFunctionName = operationId.replace(/[^a-zA-Z0-9]/g, "_");
1764
1797
  const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
1765
1798
  const summary = operationItem.summary;
1799
+ const paramObject = operationItem.parameters;
1800
+ const requestBody = operationItem.requestBody;
1801
+ if (paramObject) {
1802
+ for (let i = 0; i < paramObject.length; i++) {
1803
+ const param = paramObject[i];
1804
+ const schema = param.schema;
1805
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1806
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1807
+ }
1808
+ }
1809
+ if (requestBody) {
1810
+ const requestJsonBody = requestBody.content["application/json"];
1811
+ const requestBodySchema = requestJsonBody.schema;
1812
+ if (Utils.isObjectSchema(requestBodySchema)) {
1813
+ for (const property in requestBodySchema.properties) {
1814
+ const schema = requestBodySchema.properties[property];
1815
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1816
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1817
+ }
1818
+ }
1819
+ else {
1820
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), ErrorType.UpdateManifestFailed);
1821
+ }
1822
+ }
1766
1823
  let funcDescription = operationItem.description || operationItem.summary || "";
1767
1824
  if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
1768
1825
  warnings.push({
@@ -1796,66 +1853,19 @@ class ManifestUpdater {
1796
1853
  }
1797
1854
  }
1798
1855
  if (options.allowConfirmation && method !== ConstantString.GetMethod) {
1799
- const paramObject = operationItem.parameters;
1800
- const requestBody = operationItem.requestBody;
1801
- const confirmationBodies = [];
1802
- if (paramObject) {
1803
- for (let i = 0; i < paramObject.length; i++) {
1804
- const param = paramObject[i];
1805
- const schema = param.schema;
1806
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1807
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1808
- }
1809
- }
1810
- if (requestBody) {
1811
- const requestJsonBody = Utils.getJsonContentType(requestBody);
1812
- const requestBodySchema = requestJsonBody.schema;
1813
- if (Utils.isObjectSchema(requestBodySchema)) {
1814
- for (const property in requestBodySchema.properties) {
1815
- const schema = requestBodySchema.properties[property];
1816
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1817
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1818
- }
1819
- }
1820
- else {
1821
- throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), ErrorType.UpdateManifestFailed);
1822
- }
1856
+ if (!funcObj.capabilities) {
1857
+ funcObj.capabilities = {};
1823
1858
  }
1859
+ funcObj.capabilities.confirmation = {
1860
+ type: "AdaptiveCard",
1861
+ title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1862
+ };
1824
1863
  if (confirmationBodies.length > 0) {
1825
- if (!funcObj.capabilities) {
1826
- funcObj.capabilities = {};
1827
- }
1828
- funcObj.capabilities.confirmation = {
1829
- type: "AdaptiveCard",
1830
- title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1831
- };
1832
1864
  funcObj.capabilities.confirmation.body = confirmationBodies.join("\n");
1833
1865
  }
1834
1866
  }
1835
1867
  functions.push(funcObj);
1836
- const authInfo = authMap[operationId];
1837
- let key = "None";
1838
- let authName = "None";
1839
- if (authInfo) {
1840
- if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
1841
- key = "OAuthPluginVault";
1842
- authName = authInfo.name;
1843
- }
1844
- else if (Utils.isBearerTokenAuth(authInfo.authScheme) ||
1845
- Utils.isAPIKeyAuthButNotInCookie(authInfo.authScheme)) {
1846
- key = "ApiKeyPluginVault";
1847
- authName = authInfo.name;
1848
- }
1849
- }
1850
- if (functionNamesMap[key]) {
1851
- functionNamesMap[key].functionNames.push(safeFunctionName);
1852
- }
1853
- else {
1854
- functionNamesMap[key] = {
1855
- functionNames: [safeFunctionName],
1856
- authName: authName,
1857
- };
1858
- }
1868
+ functionNames.push(safeFunctionName);
1859
1869
  const conversationStarterStr = (summary !== null && summary !== void 0 ? summary : description).slice(0, ConstantString.ConversationStarterMaxLens);
1860
1870
  if (conversationStarterStr) {
1861
1871
  conversationStarters.push(conversationStarterStr);
@@ -1865,12 +1875,6 @@ class ManifestUpdater {
1865
1875
  }
1866
1876
  }
1867
1877
  }
1868
- if (Object.keys(functionNamesMap).length === 0) {
1869
- functionNamesMap["None"] = {
1870
- functionNames: [],
1871
- authName: "None",
1872
- };
1873
- }
1874
1878
  let apiPlugin;
1875
1879
  if (await fs.pathExists(apiPluginFilePath)) {
1876
1880
  apiPlugin = await fs.readJSON(apiPluginFilePath);
@@ -1906,35 +1910,24 @@ class ManifestUpdater {
1906
1910
  const relativePath = ManifestUpdater.getRelativePath(existingPluginManifestInfo.manifestPath, existingPluginManifestInfo.specPath);
1907
1911
  apiPlugin.runtimes = apiPlugin.runtimes.filter((runtime) => runtime.spec.url !== relativePath);
1908
1912
  }
1909
- for (const authType in functionNamesMap) {
1910
- const pluginAuthObj = {
1911
- type: authType,
1912
- };
1913
- const authName = functionNamesMap[authType].authName;
1914
- if (pluginAuthObj.type !== "None") {
1915
- const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authName}_${ConstantString.RegistrationIdPostfix}`);
1916
- pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
1917
- }
1918
- const functionNamesInfo = functionNamesMap[authType];
1919
- const index = apiPlugin.runtimes.findIndex((runtime) => {
1920
- var _a, _b;
1921
- return runtime.spec.url === specRelativePath &&
1922
- runtime.type === "OpenApi" &&
1923
- ((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === authType;
1913
+ const index = apiPlugin.runtimes.findIndex((runtime) => {
1914
+ var _a, _b;
1915
+ return runtime.spec.url === specRelativePath &&
1916
+ runtime.type === "OpenApi" &&
1917
+ ((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === pluginAuthObj.type;
1918
+ });
1919
+ if (index === -1) {
1920
+ apiPlugin.runtimes.push({
1921
+ type: "OpenApi",
1922
+ auth: pluginAuthObj,
1923
+ spec: {
1924
+ url: specRelativePath,
1925
+ },
1926
+ run_for_functions: functionNames,
1924
1927
  });
1925
- if (index === -1) {
1926
- apiPlugin.runtimes.push({
1927
- type: "OpenApi",
1928
- auth: pluginAuthObj,
1929
- spec: {
1930
- url: specRelativePath,
1931
- },
1932
- run_for_functions: functionNamesInfo.functionNames,
1933
- });
1934
- }
1935
- else {
1936
- apiPlugin.runtimes[index].run_for_functions = functionNamesInfo.functionNames;
1937
- }
1928
+ }
1929
+ else {
1930
+ apiPlugin.runtimes[index].run_for_functions = functionNames;
1938
1931
  }
1939
1932
  if (!apiPlugin.name_for_human) {
1940
1933
  apiPlugin.name_for_human = appName;
@@ -1975,7 +1968,7 @@ class ManifestUpdater {
1975
1968
  };
1976
1969
  if (authInfo) {
1977
1970
  const auth = authInfo.authScheme;
1978
- const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
1971
+ const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
1979
1972
  if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
1980
1973
  composeExtension.authorization = {
1981
1974
  authType: "apiSecretServiceAuth",
@@ -2118,11 +2111,8 @@ class SpecParser {
2118
2111
  await this.parser.validate(this.spec);
2119
2112
  }
2120
2113
  else {
2121
- // The following code still hangs for Graph API, support will be added when SwaggerParser is updated.
2122
- /*
2123
2114
  const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
2124
2115
  await this.parser.validate(clonedUnResolveSpec);
2125
- */
2126
2116
  }
2127
2117
  }
2128
2118
  catch (e) {
@@ -2279,7 +2269,7 @@ class SpecParser {
2279
2269
  throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
2280
2270
  }
2281
2271
  const clonedUnResolveSpec = JSON.parse(JSON.stringify(newUnResolvedSpec));
2282
- const newSpec = await this.deReferenceSpec(clonedUnResolveSpec);
2272
+ const newSpec = (await this.parser.dereference(clonedUnResolveSpec));
2283
2273
  return [newUnResolvedSpec, newSpec];
2284
2274
  }
2285
2275
  catch (err) {
@@ -2289,10 +2279,6 @@ class SpecParser {
2289
2279
  throw new SpecParserError(err.toString(), ErrorType.GetSpecFailed);
2290
2280
  }
2291
2281
  }
2292
- async deReferenceSpec(spec) {
2293
- const result = await this.parser.dereference(spec);
2294
- return result;
2295
- }
2296
2282
  /**
2297
2283
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
2298
2284
  * @param manifestPath A file path of the Teams app manifest file to update.
@@ -2309,6 +2295,7 @@ class SpecParser {
2309
2295
  const newSpecs = await this.getFilteredSpecs(filter, signal);
2310
2296
  const newUnResolvedSpec = newSpecs[0];
2311
2297
  const newSpec = newSpecs[1];
2298
+ const authInfo = Utils.getAuthInfo(newSpec);
2312
2299
  const paths = newUnResolvedSpec.paths;
2313
2300
  for (const pathUrl in paths) {
2314
2301
  const operations = paths[pathUrl];
@@ -2316,22 +2303,15 @@ class SpecParser {
2316
2303
  const operationItem = operations[method];
2317
2304
  const operationId = operationItem.operationId;
2318
2305
  const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
2319
- if (containsSpecialCharacters) {
2320
- operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
2321
- result.warnings.push({
2322
- type: WarningType.OperationIdContainsSpecialCharacters,
2323
- content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
2324
- data: operationId,
2325
- });
2326
- }
2327
- const authArray = Utils.getAuthArray(operationItem.security, newSpec);
2328
- if (Utils.isNotSupportedAuth(authArray)) {
2329
- result.warnings.push({
2330
- type: WarningType.UnsupportedAuthType,
2331
- content: Utils.format(ConstantString.AuthTypeIsNotSupported, operationId),
2332
- data: operationId,
2333
- });
2306
+ if (!containsSpecialCharacters) {
2307
+ continue;
2334
2308
  }
2309
+ operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
2310
+ result.warnings.push({
2311
+ type: WarningType.OperationIdContainsSpecialCharacters,
2312
+ content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
2313
+ data: operationId,
2314
+ });
2335
2315
  }
2336
2316
  }
2337
2317
  await this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
@@ -2344,8 +2324,7 @@ class SpecParser {
2344
2324
  specPath: this.pathOrSpec,
2345
2325
  }
2346
2326
  : undefined;
2347
- const authMap = Utils.getAuthMap(newSpec);
2348
- const [updatedManifest, apiPlugin, warnings] = await ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authMap, existingPluginManifestInfo);
2327
+ const [updatedManifest, apiPlugin, warnings] = await ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authInfo, existingPluginManifestInfo);
2349
2328
  result.warnings.push(...warnings);
2350
2329
  await fs.outputJSON(manifestPath, updatedManifest, { spaces: 4 });
2351
2330
  await fs.outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });
@@ -2433,7 +2412,7 @@ class SpecParser {
2433
2412
  this.isSwaggerFile = true;
2434
2413
  }
2435
2414
  const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
2436
- this.spec = await this.deReferenceSpec(clonedUnResolveSpec);
2415
+ this.spec = (await this.parser.dereference(clonedUnResolveSpec));
2437
2416
  }
2438
2417
  }
2439
2418
  getAPIs(spec) {