@microsoft/m365-spec-parser 0.2.3 → 0.2.4-alpha.24cc1dfce.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.
@@ -5,6 +5,7 @@ import fs from 'fs-extra';
5
5
  import path from 'path';
6
6
  import { ManifestUtil } from '@microsoft/teams-manifest';
7
7
  import { createHash } from 'crypto';
8
+ import { $RefParser } from '@apidevtools/json-schema-ref-parser';
8
9
 
9
10
  // Copyright (c) Microsoft Corporation.
10
11
  /**
@@ -38,11 +39,8 @@ var ErrorType;
38
39
  ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
39
40
  ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
40
41
  ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
41
- ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
42
42
  ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
43
43
  ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
44
- ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
45
- ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
46
44
  ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
47
45
  ErrorType["NoParameter"] = "no-parameter";
48
46
  ErrorType["NoAPIInfo"] = "no-api-info";
@@ -61,6 +59,9 @@ var WarningType;
61
59
  WarningType["OperationOnlyContainsOptionalParam"] = "operation-only-contains-optional-param";
62
60
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
63
61
  WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
62
+ WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
63
+ WarningType["UnsupportedAuthType"] = "unsupported-auth-type";
64
+ WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
64
65
  WarningType["Unknown"] = "unknown";
65
66
  })(WarningType || (WarningType = {}));
66
67
  /**
@@ -98,25 +99,23 @@ ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converte
98
99
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
99
100
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
100
101
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
102
+ ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
103
+ ConstantString.AuthTypeIsNotSupported = "Unsupported authorization type in API '%s'. No authorization will be used.";
101
104
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
102
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.";
106
+ ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
103
107
  ConstantString.WrappedCardVersion = "devPreview";
104
108
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
105
109
  ConstantString.WrappedCardResponseLayout = "list";
106
110
  ConstantString.GetMethod = "get";
107
111
  ConstantString.PostMethod = "post";
108
112
  ConstantString.AdaptiveCardVersion = "1.5";
109
- ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
113
+ ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
110
114
  ConstantString.AdaptiveCardType = "AdaptiveCard";
111
115
  ConstantString.TextBlockType = "TextBlock";
112
116
  ConstantString.ImageType = "Image";
113
117
  ConstantString.ContainerType = "Container";
114
- ConstantString.RegistrationIdPostfix = {
115
- apiKey: "REGISTRATION_ID",
116
- oauth2: "CONFIGURATION_ID",
117
- http: "REGISTRATION_ID",
118
- openIdConnect: "REGISTRATION_ID",
119
- };
118
+ ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
120
119
  ConstantString.ResponseCodeFor20X = [
121
120
  "200",
122
121
  "201",
@@ -128,6 +127,7 @@ ConstantString.ResponseCodeFor20X = [
128
127
  "207",
129
128
  "208",
130
129
  "226",
130
+ "2XX",
131
131
  "default",
132
132
  ];
133
133
  ConstantString.AllOperationMethods = [
@@ -193,16 +193,8 @@ class SpecParserError extends Error {
193
193
 
194
194
  // Copyright (c) Microsoft Corporation.
195
195
  class Utils {
196
- static hasNestedObjectInSchema(schema) {
197
- if (schema.type === "object") {
198
- for (const property in schema.properties) {
199
- const nestedSchema = schema.properties[property];
200
- if (nestedSchema.type === "object") {
201
- return true;
202
- }
203
- }
204
- }
205
- return false;
196
+ static isObjectSchema(schema) {
197
+ return schema.type === "object" || (!schema.type && !!schema.properties);
206
198
  }
207
199
  static containMultipleMediaTypes(bodyObject) {
208
200
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
@@ -213,11 +205,32 @@ class Utils {
213
205
  static isAPIKeyAuth(authScheme) {
214
206
  return authScheme.type === "apiKey";
215
207
  }
208
+ static isAPIKeyAuthButNotInCookie(authScheme) {
209
+ return authScheme.type === "apiKey" && authScheme.in !== "cookie";
210
+ }
216
211
  static isOAuthWithAuthCodeFlow(authScheme) {
217
212
  return !!(authScheme.type === "oauth2" &&
218
213
  authScheme.flows &&
219
214
  authScheme.flows.authorizationCode);
220
215
  }
216
+ static isNotSupportedAuth(authSchemeArray) {
217
+ if (authSchemeArray.length === 0) {
218
+ return false;
219
+ }
220
+ if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
221
+ return true;
222
+ }
223
+ for (const auths of authSchemeArray) {
224
+ if (auths.length === 1) {
225
+ if (Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme) ||
226
+ Utils.isBearerTokenAuth(auths[0].authScheme) ||
227
+ Utils.isAPIKeyAuthButNotInCookie(auths[0].authScheme)) {
228
+ return false;
229
+ }
230
+ }
231
+ }
232
+ return true;
233
+ }
221
234
  static getAuthArray(securities, spec) {
222
235
  var _a;
223
236
  const result = [];
@@ -242,6 +255,20 @@ class Utils {
242
255
  result.sort((a, b) => a[0].name.localeCompare(b[0].name));
243
256
  return result;
244
257
  }
258
+ static getAuthMap(spec) {
259
+ const authMap = {};
260
+ for (const url in spec.paths) {
261
+ for (const method in spec.paths[url]) {
262
+ const operation = spec.paths[url][method];
263
+ const authArray = Utils.getAuthArray(operation.security, spec);
264
+ if (authArray && authArray.length > 0) {
265
+ const currentAuth = authArray[0][0];
266
+ authMap[operation.operationId] = currentAuth;
267
+ }
268
+ }
269
+ }
270
+ return authMap;
271
+ }
245
272
  static getAuthInfo(spec) {
246
273
  let authInfo = undefined;
247
274
  for (const url in spec.paths) {
@@ -270,27 +297,33 @@ class Utils {
270
297
  let multipleMediaType = false;
271
298
  for (const code of ConstantString.ResponseCodeFor20X) {
272
299
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
273
- if (responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) {
274
- for (const contentType of Object.keys(responseObject.content)) {
275
- // json media type can also be "application/json; charset=utf-8"
276
- if (contentType.indexOf("application/json") >= 0) {
277
- multipleMediaType = false;
278
- json = responseObject.content[contentType];
279
- if (Utils.containMultipleMediaTypes(responseObject)) {
280
- multipleMediaType = true;
281
- if (!allowMultipleMediaType) {
282
- json = {};
283
- }
284
- }
285
- else {
286
- return { json, multipleMediaType };
287
- }
288
- }
289
- }
300
+ if (!responseObject) {
301
+ continue;
302
+ }
303
+ multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
304
+ if (!allowMultipleMediaType && multipleMediaType) {
305
+ json = {};
306
+ continue;
307
+ }
308
+ const mediaObj = Utils.getJsonContentType(responseObject);
309
+ if (Object.keys(mediaObj).length > 0) {
310
+ json = mediaObj;
311
+ return { json, multipleMediaType };
290
312
  }
291
313
  }
292
314
  return { json, multipleMediaType };
293
315
  }
316
+ static getJsonContentType(responseObject) {
317
+ if (responseObject.content) {
318
+ for (const contentType of Object.keys(responseObject.content)) {
319
+ // json media type can also be "application/json; charset=utf-8"
320
+ if (contentType.indexOf("application/json") >= 0) {
321
+ return responseObject.content[contentType];
322
+ }
323
+ }
324
+ }
325
+ return {};
326
+ }
294
327
  static convertPathToCamelCase(path) {
295
328
  const pathSegments = path.split(/[./{]/);
296
329
  const camelCaseSegments = pathSegments.map((segment) => {
@@ -326,7 +359,7 @@ class Utils {
326
359
  }
327
360
  return newStr;
328
361
  }
329
- static checkServerUrl(servers) {
362
+ static checkServerUrl(servers, allowHttp = false) {
330
363
  const errors = [];
331
364
  let serverUrl;
332
365
  try {
@@ -349,8 +382,7 @@ class Utils {
349
382
  data: servers,
350
383
  });
351
384
  }
352
- else if (protocol !== "https:") {
353
- // Http server url is not supported
385
+ else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
354
386
  const protocolString = protocol.slice(0, -1);
355
387
  errors.push({
356
388
  type: ErrorType.UrlProtocolNotSupported,
@@ -366,10 +398,11 @@ class Utils {
366
398
  let hasTopLevelServers = false;
367
399
  let hasPathLevelServers = false;
368
400
  let hasOperationLevelServers = false;
401
+ const allowHttp = options.projectType === ProjectType.Copilot;
369
402
  if (spec.servers && spec.servers.length >= 1) {
370
403
  hasTopLevelServers = true;
371
404
  // for multiple server, we only use the first url
372
- const serverErrors = Utils.checkServerUrl(spec.servers);
405
+ const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
373
406
  errors.push(...serverErrors);
374
407
  }
375
408
  const paths = spec.paths;
@@ -377,7 +410,7 @@ class Utils {
377
410
  const methods = paths[path];
378
411
  if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
379
412
  hasPathLevelServers = true;
380
- const serverErrors = Utils.checkServerUrl(methods.servers);
413
+ const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
381
414
  errors.push(...serverErrors);
382
415
  }
383
416
  for (const method in methods) {
@@ -385,7 +418,7 @@ class Utils {
385
418
  if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
386
419
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
387
420
  hasOperationLevelServers = true;
388
- const serverErrors = Utils.checkServerUrl(operationObject.servers);
421
+ const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
389
422
  errors.push(...serverErrors);
390
423
  }
391
424
  }
@@ -432,7 +465,7 @@ class Utils {
432
465
  optionalParams.push(parameter);
433
466
  }
434
467
  }
435
- else if (schema.type === "object") {
468
+ else if (Utils.isObjectSchema(schema)) {
436
469
  const { properties } = schema;
437
470
  for (const property in properties) {
438
471
  let isRequired = false;
@@ -546,29 +579,6 @@ class Utils {
546
579
  const serverUrl = operationServer || methodServer || rootServer;
547
580
  return serverUrl;
548
581
  }
549
- static limitACBodyProperties(body, maxCount) {
550
- const result = [];
551
- let currentCount = 0;
552
- for (const element of body) {
553
- if (element.type === ConstantString.ContainerType) {
554
- const items = this.limitACBodyProperties(element.items, maxCount - currentCount);
555
- result.push({
556
- type: ConstantString.ContainerType,
557
- $data: element.$data,
558
- items: items,
559
- });
560
- currentCount += items.length;
561
- }
562
- else {
563
- result.push(element);
564
- currentCount++;
565
- }
566
- if (currentCount >= maxCount) {
567
- break;
568
- }
569
- }
570
- return result;
571
- }
572
582
  }
573
583
 
574
584
  // Copyright (c) Microsoft Corporation.
@@ -697,22 +707,6 @@ class Validator {
697
707
  }
698
708
  return result;
699
709
  }
700
- validateResponse(method, path) {
701
- const result = { isValid: true, reason: [] };
702
- const operationObject = this.spec.paths[path][method];
703
- const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
704
- if (this.options.projectType === ProjectType.SME) {
705
- // only support response body only contains “application/json” content type
706
- if (multipleMediaType) {
707
- result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
708
- }
709
- else if (Object.keys(json).length === 0) {
710
- // response body should not be empty
711
- result.reason.push(ErrorType.ResponseJsonIsEmpty);
712
- }
713
- }
714
- return result;
715
- }
716
710
  validateServer(method, path) {
717
711
  const result = { isValid: true, reason: [] };
718
712
  const serverObj = Utils.getServerObject(this.spec, method, path);
@@ -721,8 +715,8 @@ class Validator {
721
715
  result.reason.push(ErrorType.NoServerInformation);
722
716
  }
723
717
  else {
724
- // server url should be absolute url with https protocol
725
- const serverValidateResult = Utils.checkServerUrl([serverObj]);
718
+ const allowHttp = this.projectType === ProjectType.Copilot;
719
+ const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
726
720
  result.reason.push(...serverValidateResult.map((item) => item.type));
727
721
  }
728
722
  return result;
@@ -745,6 +739,9 @@ class Validator {
745
739
  reason: [ErrorType.MultipleAuthNotSupported],
746
740
  };
747
741
  }
742
+ if (this.projectType === ProjectType.Copilot) {
743
+ return { isValid: true, reason: [] };
744
+ }
748
745
  for (const auths of authSchemeArray) {
749
746
  if (auths.length === 1) {
750
747
  if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
@@ -757,125 +754,6 @@ class Validator {
757
754
  }
758
755
  return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
759
756
  }
760
- checkPostBodySchema(schema, isRequired = false) {
761
- var _a;
762
- const paramResult = {
763
- requiredNum: 0,
764
- optionalNum: 0,
765
- isValid: true,
766
- reason: [],
767
- };
768
- if (Object.keys(schema).length === 0) {
769
- return paramResult;
770
- }
771
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
772
- const isCopilot = this.projectType === ProjectType.Copilot;
773
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
774
- paramResult.isValid = false;
775
- paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
776
- return paramResult;
777
- }
778
- if (schema.type === "string" ||
779
- schema.type === "integer" ||
780
- schema.type === "boolean" ||
781
- schema.type === "number") {
782
- if (isRequiredWithoutDefault) {
783
- paramResult.requiredNum = paramResult.requiredNum + 1;
784
- }
785
- else {
786
- paramResult.optionalNum = paramResult.optionalNum + 1;
787
- }
788
- }
789
- else if (schema.type === "object") {
790
- const { properties } = schema;
791
- for (const property in properties) {
792
- let isRequired = false;
793
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
794
- isRequired = true;
795
- }
796
- const result = this.checkPostBodySchema(properties[property], isRequired);
797
- paramResult.requiredNum += result.requiredNum;
798
- paramResult.optionalNum += result.optionalNum;
799
- paramResult.isValid = paramResult.isValid && result.isValid;
800
- paramResult.reason.push(...result.reason);
801
- }
802
- }
803
- else {
804
- if (isRequiredWithoutDefault && !isCopilot) {
805
- paramResult.isValid = false;
806
- paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
807
- }
808
- }
809
- return paramResult;
810
- }
811
- checkParamSchema(paramObject) {
812
- const paramResult = {
813
- requiredNum: 0,
814
- optionalNum: 0,
815
- isValid: true,
816
- reason: [],
817
- };
818
- if (!paramObject) {
819
- return paramResult;
820
- }
821
- const isCopilot = this.projectType === ProjectType.Copilot;
822
- for (let i = 0; i < paramObject.length; i++) {
823
- const param = paramObject[i];
824
- const schema = param.schema;
825
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
826
- paramResult.isValid = false;
827
- paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
828
- continue;
829
- }
830
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
831
- if (isCopilot) {
832
- if (isRequiredWithoutDefault) {
833
- paramResult.requiredNum = paramResult.requiredNum + 1;
834
- }
835
- else {
836
- paramResult.optionalNum = paramResult.optionalNum + 1;
837
- }
838
- continue;
839
- }
840
- if (param.in === "header" || param.in === "cookie") {
841
- if (isRequiredWithoutDefault) {
842
- paramResult.isValid = false;
843
- paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
844
- }
845
- continue;
846
- }
847
- if (schema.type !== "boolean" &&
848
- schema.type !== "string" &&
849
- schema.type !== "number" &&
850
- schema.type !== "integer") {
851
- if (isRequiredWithoutDefault) {
852
- paramResult.isValid = false;
853
- paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
854
- }
855
- continue;
856
- }
857
- if (param.in === "query" || param.in === "path") {
858
- if (isRequiredWithoutDefault) {
859
- paramResult.requiredNum = paramResult.requiredNum + 1;
860
- }
861
- else {
862
- paramResult.optionalNum = paramResult.optionalNum + 1;
863
- }
864
- }
865
- }
866
- return paramResult;
867
- }
868
- hasNestedObjectInSchema(schema) {
869
- if (schema.type === "object") {
870
- for (const property in schema.properties) {
871
- const nestedSchema = schema.properties[property];
872
- if (nestedSchema.type === "object") {
873
- return true;
874
- }
875
- }
876
- }
877
- return false;
878
- }
879
757
  }
880
758
 
881
759
  // Copyright (c) Microsoft Corporation.
@@ -885,7 +763,6 @@ class CopilotValidator extends Validator {
885
763
  this.projectType = ProjectType.Copilot;
886
764
  this.options = options;
887
765
  this.spec = spec;
888
- this.checkCircularReference();
889
766
  }
890
767
  validateSpec() {
891
768
  const result = { errors: [], warnings: [] };
@@ -911,10 +788,6 @@ class CopilotValidator extends Validator {
911
788
  if (!methodAndPathResult.isValid) {
912
789
  return methodAndPathResult;
913
790
  }
914
- const circularReferenceResult = this.validateCircularReference(method, path);
915
- if (!circularReferenceResult.isValid) {
916
- return circularReferenceResult;
917
- }
918
791
  const operationObject = this.spec.paths[path][method];
919
792
  // validate auth
920
793
  const authCheckResult = this.validateAuth(method, path);
@@ -926,24 +799,6 @@ class CopilotValidator extends Validator {
926
799
  // validate server
927
800
  const validateServerResult = this.validateServer(method, path);
928
801
  result.reason.push(...validateServerResult.reason);
929
- // validate response
930
- const validateResponseResult = this.validateResponse(method, path);
931
- result.reason.push(...validateResponseResult.reason);
932
- // validate requestBody
933
- const requestBody = operationObject.requestBody;
934
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
935
- if (requestJsonBody) {
936
- const requestBodySchema = requestJsonBody.schema;
937
- if (requestBodySchema.type !== "object") {
938
- result.reason.push(ErrorType.PostBodySchemaIsNotJson);
939
- }
940
- const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
941
- result.reason.push(...requestBodyParamResult.reason);
942
- }
943
- // validate parameters
944
- const paramObject = operationObject.parameters;
945
- const paramResult = this.checkParamSchema(paramObject);
946
- result.reason.push(...paramResult.reason);
947
802
  if (result.reason.length > 0) {
948
803
  result.isValid = false;
949
804
  }
@@ -1035,6 +890,108 @@ class SMEValidator extends Validator {
1035
890
  }
1036
891
  return result;
1037
892
  }
893
+ validateResponse(method, path) {
894
+ const result = { isValid: true, reason: [] };
895
+ const operationObject = this.spec.paths[path][method];
896
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
897
+ // only support response body only contains “application/json” content type
898
+ if (multipleMediaType) {
899
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
900
+ }
901
+ else if (Object.keys(json).length === 0) {
902
+ // response body should not be empty
903
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
904
+ }
905
+ return result;
906
+ }
907
+ checkPostBodySchema(schema, isRequired = false) {
908
+ var _a;
909
+ const paramResult = {
910
+ requiredNum: 0,
911
+ optionalNum: 0,
912
+ isValid: true,
913
+ reason: [],
914
+ };
915
+ if (Object.keys(schema).length === 0) {
916
+ return paramResult;
917
+ }
918
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
919
+ const isCopilot = this.projectType === ProjectType.Copilot;
920
+ if (schema.type === "string" ||
921
+ schema.type === "integer" ||
922
+ schema.type === "boolean" ||
923
+ schema.type === "number") {
924
+ if (isRequiredWithoutDefault) {
925
+ paramResult.requiredNum = paramResult.requiredNum + 1;
926
+ }
927
+ else {
928
+ paramResult.optionalNum = paramResult.optionalNum + 1;
929
+ }
930
+ }
931
+ else if (Utils.isObjectSchema(schema)) {
932
+ const { properties } = schema;
933
+ for (const property in properties) {
934
+ let isRequired = false;
935
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
936
+ isRequired = true;
937
+ }
938
+ const result = this.checkPostBodySchema(properties[property], isRequired);
939
+ paramResult.requiredNum += result.requiredNum;
940
+ paramResult.optionalNum += result.optionalNum;
941
+ paramResult.isValid = paramResult.isValid && result.isValid;
942
+ paramResult.reason.push(...result.reason);
943
+ }
944
+ }
945
+ else {
946
+ if (isRequiredWithoutDefault && !isCopilot) {
947
+ paramResult.isValid = false;
948
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
949
+ }
950
+ }
951
+ return paramResult;
952
+ }
953
+ checkParamSchema(paramObject) {
954
+ const paramResult = {
955
+ requiredNum: 0,
956
+ optionalNum: 0,
957
+ isValid: true,
958
+ reason: [],
959
+ };
960
+ if (!paramObject) {
961
+ return paramResult;
962
+ }
963
+ for (let i = 0; i < paramObject.length; i++) {
964
+ const param = paramObject[i];
965
+ const schema = param.schema;
966
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
967
+ if (param.in === "header" || param.in === "cookie") {
968
+ if (isRequiredWithoutDefault) {
969
+ paramResult.isValid = false;
970
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
971
+ }
972
+ continue;
973
+ }
974
+ if (schema.type !== "boolean" &&
975
+ schema.type !== "string" &&
976
+ schema.type !== "number" &&
977
+ schema.type !== "integer") {
978
+ if (isRequiredWithoutDefault) {
979
+ paramResult.isValid = false;
980
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
981
+ }
982
+ continue;
983
+ }
984
+ if (param.in === "query" || param.in === "path") {
985
+ if (isRequiredWithoutDefault) {
986
+ paramResult.requiredNum = paramResult.requiredNum + 1;
987
+ }
988
+ else {
989
+ paramResult.optionalNum = paramResult.optionalNum + 1;
990
+ }
991
+ }
992
+ }
993
+ return paramResult;
994
+ }
1038
995
  validateParamCount(postBodyResult, paramResult) {
1039
996
  const result = { isValid: true, reason: [] };
1040
997
  const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
@@ -1312,20 +1269,157 @@ class SpecFilter {
1312
1269
  }
1313
1270
  }
1314
1271
 
1272
+ // Copyright (c) Microsoft Corporation.
1273
+ class JsonDataGenerator {
1274
+ static generate(schema) {
1275
+ return this.generateMockData(schema);
1276
+ }
1277
+ static generateMockData(schema) {
1278
+ if (this.visitedSchemas.has(schema)) {
1279
+ return null; // Prevent circular reference
1280
+ }
1281
+ this.visitedSchemas.add(schema);
1282
+ let result;
1283
+ if (schema.anyOf) {
1284
+ // Select the first schema in anyOf
1285
+ const selectedSchema = schema.anyOf[0];
1286
+ result = this.generateMockData(selectedSchema);
1287
+ }
1288
+ else if (schema.oneOf) {
1289
+ // Select the first schema in oneOf
1290
+ const selectedSchema = schema.oneOf[0];
1291
+ result = this.generateMockData(selectedSchema);
1292
+ }
1293
+ else if (schema.allOf) {
1294
+ // merge all schemas in allOf
1295
+ result = {};
1296
+ for (const subschema of schema.allOf) {
1297
+ const data = this.generateMockData(subschema);
1298
+ result = Object.assign(Object.assign({}, result), data);
1299
+ }
1300
+ }
1301
+ else {
1302
+ switch (schema.type) {
1303
+ case "string":
1304
+ if (schema.example !== undefined) {
1305
+ result = schema.example;
1306
+ }
1307
+ else if (schema.format) {
1308
+ switch (schema.format) {
1309
+ case "date-time":
1310
+ result = "2024-11-01T05:25:43.593Z";
1311
+ break;
1312
+ case "email":
1313
+ result = "example@example.com";
1314
+ break;
1315
+ case "uuid":
1316
+ result = "123e4567-e89b-12d3-a456-426614174000";
1317
+ break;
1318
+ case "ipv4":
1319
+ result = "192.168.0.1";
1320
+ break;
1321
+ case "ipv6":
1322
+ result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
1323
+ break;
1324
+ default:
1325
+ result = "example string";
1326
+ }
1327
+ }
1328
+ else {
1329
+ result = "example string";
1330
+ }
1331
+ break;
1332
+ case "number":
1333
+ if (schema.example !== undefined) {
1334
+ result = schema.example;
1335
+ }
1336
+ else if (schema.format) {
1337
+ switch (schema.format) {
1338
+ case "float":
1339
+ result = 3.14;
1340
+ break;
1341
+ case "double":
1342
+ result = 3.14159;
1343
+ break;
1344
+ default:
1345
+ result = 123;
1346
+ }
1347
+ }
1348
+ else {
1349
+ result = 123;
1350
+ }
1351
+ break;
1352
+ case "integer":
1353
+ if (schema.example !== undefined) {
1354
+ result = schema.example;
1355
+ }
1356
+ else if (schema.format) {
1357
+ switch (schema.format) {
1358
+ case "int32":
1359
+ result = 123456;
1360
+ break;
1361
+ case "int64":
1362
+ result = 123456789;
1363
+ break;
1364
+ default:
1365
+ result = 123;
1366
+ }
1367
+ }
1368
+ else {
1369
+ result = 123;
1370
+ }
1371
+ break;
1372
+ case "boolean":
1373
+ result = schema.example !== undefined ? schema.example : true;
1374
+ break;
1375
+ case "array":
1376
+ result = [this.generateMockData(schema.items)];
1377
+ break;
1378
+ case "object":
1379
+ result = {};
1380
+ if (schema.properties) {
1381
+ for (const key in schema.properties) {
1382
+ result[key] = this.generateMockData(schema.properties[key]);
1383
+ }
1384
+ }
1385
+ break;
1386
+ default:
1387
+ result = schema.example || null;
1388
+ }
1389
+ }
1390
+ this.visitedSchemas.delete(schema);
1391
+ return result;
1392
+ }
1393
+ }
1394
+ JsonDataGenerator.visitedSchemas = new Set();
1395
+
1315
1396
  // Copyright (c) Microsoft Corporation.
1316
1397
  class AdaptiveCardGenerator {
1317
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1398
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1318
1399
  try {
1319
1400
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1320
1401
  let cardBody = [];
1402
+ let jsonData = {};
1403
+ const warnings = [];
1404
+ const operationId = operationItem.operationId;
1321
1405
  let schema = json.schema;
1322
1406
  let jsonPath = "$";
1323
1407
  if (schema && Object.keys(schema).length > 0) {
1408
+ try {
1409
+ jsonData = JsonDataGenerator.generate(schema);
1410
+ }
1411
+ catch (err) {
1412
+ warnings.push({
1413
+ type: WarningType.GenerateJsonDataFailed,
1414
+ content: Utils.format(ConstantString.GenerateJsonDataFailed, operationId, err.toString()),
1415
+ data: operationId,
1416
+ });
1417
+ }
1324
1418
  jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
1325
1419
  if (jsonPath !== "$") {
1326
1420
  schema = schema.properties[jsonPath];
1327
1421
  }
1328
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1422
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1329
1423
  }
1330
1424
  // if no schema, try to use example value
1331
1425
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1353,16 +1447,20 @@ class AdaptiveCardGenerator {
1353
1447
  version: ConstantString.AdaptiveCardVersion,
1354
1448
  body: cardBody,
1355
1449
  };
1356
- return [fullCard, jsonPath];
1450
+ return [fullCard, jsonPath, jsonData, warnings];
1357
1451
  }
1358
1452
  catch (err) {
1359
1453
  throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
1360
1454
  }
1361
1455
  }
1362
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1456
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1457
+ if (counter.count >= maxElementCount) {
1458
+ return [];
1459
+ }
1363
1460
  if (schema.type === "array") {
1364
1461
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1365
1462
  if (Object.keys(schema.items).length === 0) {
1463
+ counter.count++;
1366
1464
  return [
1367
1465
  {
1368
1466
  type: ConstantString.TextBlockType,
@@ -1371,7 +1469,7 @@ class AdaptiveCardGenerator {
1371
1469
  },
1372
1470
  ];
1373
1471
  }
1374
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1472
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1375
1473
  const template = {
1376
1474
  type: ConstantString.ContainerType,
1377
1475
  $data: name ? `\${${name}}` : "${$root}",
@@ -1381,11 +1479,11 @@ class AdaptiveCardGenerator {
1381
1479
  return [template];
1382
1480
  }
1383
1481
  // some schema may not contain type but contain properties
1384
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1482
+ if (Utils.isObjectSchema(schema)) {
1385
1483
  const { properties } = schema;
1386
1484
  const result = [];
1387
1485
  for (const property in properties) {
1388
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1486
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1389
1487
  result.push(...obj);
1390
1488
  }
1391
1489
  if (schema.additionalProperties) {
@@ -1398,6 +1496,7 @@ class AdaptiveCardGenerator {
1398
1496
  schema.type === "integer" ||
1399
1497
  schema.type === "boolean" ||
1400
1498
  schema.type === "number") {
1499
+ counter.count++;
1401
1500
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1402
1501
  // string in root: "ddd"
1403
1502
  let text = "result: ${$root}";
@@ -1422,24 +1521,17 @@ class AdaptiveCardGenerator {
1422
1521
  ];
1423
1522
  }
1424
1523
  else {
1425
- if (name) {
1426
- return [
1427
- {
1428
- type: "Image",
1429
- url: `\${${name}}`,
1430
- $when: `\${${name} != null && ${name} != ''}`,
1431
- },
1432
- ];
1433
- }
1434
- else {
1435
- return [
1436
- {
1437
- type: "Image",
1438
- url: "${$data}",
1439
- $when: "${$data != null && $data != ''}",
1440
- },
1441
- ];
1442
- }
1524
+ const url = name ? `\${${name}}` : "${$data}";
1525
+ const condition = name
1526
+ ? `\${${name} != null && ${name} != ''}`
1527
+ : "${$data != null && $data != ''}";
1528
+ return [
1529
+ {
1530
+ type: "Image",
1531
+ url,
1532
+ $when: condition,
1533
+ },
1534
+ ];
1443
1535
  }
1444
1536
  }
1445
1537
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1449,7 +1541,7 @@ class AdaptiveCardGenerator {
1449
1541
  }
1450
1542
  // Find the first array property in the response schema object with the well-known name
1451
1543
  static getResponseJsonPathFromSchema(schema) {
1452
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1544
+ if (Utils.isObjectSchema(schema)) {
1453
1545
  const { properties } = schema;
1454
1546
  for (const property in properties) {
1455
1547
  const schema = properties[property];
@@ -1601,7 +1693,7 @@ function inferProperties(card) {
1601
1693
 
1602
1694
  // Copyright (c) Microsoft Corporation.
1603
1695
  class ManifestUpdater {
1604
- static async updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo, existingPluginManifestInfo) {
1696
+ static async updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authMap, existingPluginManifestInfo) {
1605
1697
  const manifest = await fs.readJSON(manifestPath);
1606
1698
  const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
1607
1699
  const useCopilotExtensionsInSchema = await ManifestUtil.useCopilotExtensionsInSchema(manifest);
@@ -1631,7 +1723,7 @@ class ManifestUpdater {
1631
1723
  }
1632
1724
  const appName = this.removeEnvs(manifest.name.short);
1633
1725
  const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
1634
- const [apiPlugin, warnings] = await ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo);
1726
+ const [apiPlugin, warnings] = await ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo);
1635
1727
  return [manifest, apiPlugin, warnings];
1636
1728
  }
1637
1729
  static updateManifestDescription(manifest, spec) {
@@ -1653,28 +1745,13 @@ class ManifestUpdater {
1653
1745
  throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), ErrorType.UpdateManifestFailed);
1654
1746
  }
1655
1747
  }
1656
- static async generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo) {
1748
+ static async generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo) {
1657
1749
  var _a, _b, _c, _d;
1658
1750
  const warnings = [];
1659
1751
  const functions = [];
1660
- const functionNames = [];
1752
+ const functionNamesMap = {};
1661
1753
  const conversationStarters = [];
1662
1754
  const paths = spec.paths;
1663
- const pluginAuthObj = {
1664
- type: "None",
1665
- };
1666
- if (authInfo) {
1667
- if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
1668
- pluginAuthObj.type = "OAuthPluginVault";
1669
- }
1670
- else if (Utils.isBearerTokenAuth(authInfo.authScheme)) {
1671
- pluginAuthObj.type = "ApiKeyPluginVault";
1672
- }
1673
- if (pluginAuthObj.type !== "None") {
1674
- const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
1675
- pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
1676
- }
1677
- }
1678
1755
  for (const pathUrl in paths) {
1679
1756
  const pathItem = paths[pathUrl];
1680
1757
  if (pathItem) {
@@ -1682,36 +1759,11 @@ class ManifestUpdater {
1682
1759
  for (const method in operations) {
1683
1760
  if (options.allowMethods.includes(method)) {
1684
1761
  const operationItem = operations[method];
1685
- const confirmationBodies = [];
1686
1762
  if (operationItem) {
1687
1763
  const operationId = operationItem.operationId;
1688
1764
  const safeFunctionName = operationId.replace(/[^a-zA-Z0-9]/g, "_");
1689
1765
  const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
1690
1766
  const summary = operationItem.summary;
1691
- const paramObject = operationItem.parameters;
1692
- const requestBody = operationItem.requestBody;
1693
- if (paramObject) {
1694
- for (let i = 0; i < paramObject.length; i++) {
1695
- const param = paramObject[i];
1696
- const schema = param.schema;
1697
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1698
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1699
- }
1700
- }
1701
- if (requestBody) {
1702
- const requestJsonBody = requestBody.content["application/json"];
1703
- const requestBodySchema = requestJsonBody.schema;
1704
- if (requestBodySchema.type === "object") {
1705
- for (const property in requestBodySchema.properties) {
1706
- const schema = requestBodySchema.properties[property];
1707
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1708
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1709
- }
1710
- }
1711
- else {
1712
- throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), ErrorType.UpdateManifestFailed);
1713
- }
1714
- }
1715
1767
  let funcDescription = operationItem.description || operationItem.summary || "";
1716
1768
  if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
1717
1769
  warnings.push({
@@ -1729,8 +1781,7 @@ class ManifestUpdater {
1729
1781
  try {
1730
1782
  const { json } = Utils.getResponseJson(operationItem);
1731
1783
  if (json.schema) {
1732
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem);
1733
- card.body = Utils.limitACBodyProperties(card.body, 5);
1784
+ const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem, false, 5);
1734
1785
  const responseSemantic = wrapResponseSemantics(card, jsonPath);
1735
1786
  funcObj.capabilities = {
1736
1787
  response_semantics: responseSemantic,
@@ -1746,19 +1797,66 @@ class ManifestUpdater {
1746
1797
  }
1747
1798
  }
1748
1799
  if (options.allowConfirmation && method !== ConstantString.GetMethod) {
1749
- if (!funcObj.capabilities) {
1750
- funcObj.capabilities = {};
1800
+ const paramObject = operationItem.parameters;
1801
+ const requestBody = operationItem.requestBody;
1802
+ const confirmationBodies = [];
1803
+ if (paramObject) {
1804
+ for (let i = 0; i < paramObject.length; i++) {
1805
+ const param = paramObject[i];
1806
+ const schema = param.schema;
1807
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1808
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1809
+ }
1810
+ }
1811
+ if (requestBody) {
1812
+ const requestJsonBody = Utils.getJsonContentType(requestBody);
1813
+ const requestBodySchema = requestJsonBody.schema;
1814
+ if (Utils.isObjectSchema(requestBodySchema)) {
1815
+ for (const property in requestBodySchema.properties) {
1816
+ const schema = requestBodySchema.properties[property];
1817
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1818
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1819
+ }
1820
+ }
1821
+ else {
1822
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), ErrorType.UpdateManifestFailed);
1823
+ }
1751
1824
  }
1752
- funcObj.capabilities.confirmation = {
1753
- type: "AdaptiveCard",
1754
- title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1755
- };
1756
1825
  if (confirmationBodies.length > 0) {
1826
+ if (!funcObj.capabilities) {
1827
+ funcObj.capabilities = {};
1828
+ }
1829
+ funcObj.capabilities.confirmation = {
1830
+ type: "AdaptiveCard",
1831
+ title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1832
+ };
1757
1833
  funcObj.capabilities.confirmation.body = confirmationBodies.join("\n");
1758
1834
  }
1759
1835
  }
1760
1836
  functions.push(funcObj);
1761
- functionNames.push(safeFunctionName);
1837
+ const authInfo = authMap[operationId];
1838
+ let key = "None";
1839
+ let authName = "None";
1840
+ if (authInfo) {
1841
+ if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
1842
+ key = "OAuthPluginVault";
1843
+ authName = authInfo.name;
1844
+ }
1845
+ else if (Utils.isBearerTokenAuth(authInfo.authScheme) ||
1846
+ Utils.isAPIKeyAuthButNotInCookie(authInfo.authScheme)) {
1847
+ key = "ApiKeyPluginVault";
1848
+ authName = authInfo.name;
1849
+ }
1850
+ }
1851
+ if (functionNamesMap[key]) {
1852
+ functionNamesMap[key].functionNames.push(safeFunctionName);
1853
+ }
1854
+ else {
1855
+ functionNamesMap[key] = {
1856
+ functionNames: [safeFunctionName],
1857
+ authName: authName,
1858
+ };
1859
+ }
1762
1860
  const conversationStarterStr = (summary !== null && summary !== void 0 ? summary : description).slice(0, ConstantString.ConversationStarterMaxLens);
1763
1861
  if (conversationStarterStr) {
1764
1862
  conversationStarters.push(conversationStarterStr);
@@ -1768,6 +1866,12 @@ class ManifestUpdater {
1768
1866
  }
1769
1867
  }
1770
1868
  }
1869
+ if (Object.keys(functionNamesMap).length === 0) {
1870
+ functionNamesMap["None"] = {
1871
+ functionNames: [],
1872
+ authName: "None",
1873
+ };
1874
+ }
1771
1875
  let apiPlugin;
1772
1876
  if (await fs.pathExists(apiPluginFilePath)) {
1773
1877
  apiPlugin = await fs.readJSON(apiPluginFilePath);
@@ -1803,24 +1907,35 @@ class ManifestUpdater {
1803
1907
  const relativePath = ManifestUpdater.getRelativePath(existingPluginManifestInfo.manifestPath, existingPluginManifestInfo.specPath);
1804
1908
  apiPlugin.runtimes = apiPlugin.runtimes.filter((runtime) => runtime.spec.url !== relativePath);
1805
1909
  }
1806
- const index = apiPlugin.runtimes.findIndex((runtime) => {
1807
- var _a, _b;
1808
- return runtime.spec.url === specRelativePath &&
1809
- runtime.type === "OpenApi" &&
1810
- ((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === pluginAuthObj.type;
1811
- });
1812
- if (index === -1) {
1813
- apiPlugin.runtimes.push({
1814
- type: "OpenApi",
1815
- auth: pluginAuthObj,
1816
- spec: {
1817
- url: specRelativePath,
1818
- },
1819
- run_for_functions: functionNames,
1910
+ for (const authType in functionNamesMap) {
1911
+ const pluginAuthObj = {
1912
+ type: authType,
1913
+ };
1914
+ const authName = functionNamesMap[authType].authName;
1915
+ if (pluginAuthObj.type !== "None") {
1916
+ const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authName}_${ConstantString.RegistrationIdPostfix}`);
1917
+ pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
1918
+ }
1919
+ const functionNamesInfo = functionNamesMap[authType];
1920
+ const index = apiPlugin.runtimes.findIndex((runtime) => {
1921
+ var _a, _b;
1922
+ return runtime.spec.url === specRelativePath &&
1923
+ runtime.type === "OpenApi" &&
1924
+ ((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === authType;
1820
1925
  });
1821
- }
1822
- else {
1823
- apiPlugin.runtimes[index].run_for_functions = functionNames;
1926
+ if (index === -1) {
1927
+ apiPlugin.runtimes.push({
1928
+ type: "OpenApi",
1929
+ auth: pluginAuthObj,
1930
+ spec: {
1931
+ url: specRelativePath,
1932
+ },
1933
+ run_for_functions: functionNamesInfo.functionNames,
1934
+ });
1935
+ }
1936
+ else {
1937
+ apiPlugin.runtimes[index].run_for_functions = functionNamesInfo.functionNames;
1938
+ }
1824
1939
  }
1825
1940
  if (!apiPlugin.name_for_human) {
1826
1941
  apiPlugin.name_for_human = appName;
@@ -1861,7 +1976,7 @@ class ManifestUpdater {
1861
1976
  };
1862
1977
  if (authInfo) {
1863
1978
  const auth = authInfo.authScheme;
1864
- const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
1979
+ const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
1865
1980
  if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
1866
1981
  composeExtension.authorization = {
1867
1982
  authType: "apiSecretServiceAuth",
@@ -1988,6 +2103,7 @@ class SpecParser {
1988
2103
  };
1989
2104
  this.pathOrSpec = pathOrDoc;
1990
2105
  this.parser = new SwaggerParser();
2106
+ this.refParser = new $RefParser();
1991
2107
  this.options = Object.assign(Object.assign({}, this.defaultOptions), (options !== null && options !== void 0 ? options : {}));
1992
2108
  }
1993
2109
  /**
@@ -2000,12 +2116,15 @@ class SpecParser {
2000
2116
  let hash = "";
2001
2117
  try {
2002
2118
  await this.loadSpec();
2003
- if (!this.parser.$refs.circular) {
2119
+ if (!this.refParser.$refs.circular) {
2004
2120
  await this.parser.validate(this.spec);
2005
2121
  }
2006
2122
  else {
2123
+ // The following code hangs for Graph API, support will be added when SwaggerParser is updated.
2124
+ /*
2007
2125
  const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
2008
2126
  await this.parser.validate(clonedUnResolveSpec);
2127
+ */
2009
2128
  }
2010
2129
  }
2011
2130
  catch (e) {
@@ -2033,7 +2152,7 @@ class SpecParser {
2033
2152
  };
2034
2153
  }
2035
2154
  // Remote reference not supported
2036
- const refPaths = this.parser.$refs.paths();
2155
+ const refPaths = this.refParser.$refs.paths();
2037
2156
  // refPaths [0] is the current spec file path
2038
2157
  if (refPaths.length > 1) {
2039
2158
  errors.push({
@@ -2162,7 +2281,7 @@ class SpecParser {
2162
2281
  throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
2163
2282
  }
2164
2283
  const clonedUnResolveSpec = JSON.parse(JSON.stringify(newUnResolvedSpec));
2165
- const newSpec = (await this.parser.dereference(clonedUnResolveSpec));
2284
+ const newSpec = await this.deReferenceSpec(clonedUnResolveSpec);
2166
2285
  return [newUnResolvedSpec, newSpec];
2167
2286
  }
2168
2287
  catch (err) {
@@ -2172,6 +2291,10 @@ class SpecParser {
2172
2291
  throw new SpecParserError(err.toString(), ErrorType.GetSpecFailed);
2173
2292
  }
2174
2293
  }
2294
+ async deReferenceSpec(spec) {
2295
+ const result = await this.refParser.dereference(spec);
2296
+ return result;
2297
+ }
2175
2298
  /**
2176
2299
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
2177
2300
  * @param manifestPath A file path of the Teams app manifest file to update.
@@ -2188,7 +2311,31 @@ class SpecParser {
2188
2311
  const newSpecs = await this.getFilteredSpecs(filter, signal);
2189
2312
  const newUnResolvedSpec = newSpecs[0];
2190
2313
  const newSpec = newSpecs[1];
2191
- const authInfo = Utils.getAuthInfo(newSpec);
2314
+ const paths = newUnResolvedSpec.paths;
2315
+ for (const pathUrl in paths) {
2316
+ const operations = paths[pathUrl];
2317
+ for (const method in operations) {
2318
+ const operationItem = operations[method];
2319
+ const operationId = operationItem.operationId;
2320
+ const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
2321
+ if (containsSpecialCharacters) {
2322
+ operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
2323
+ result.warnings.push({
2324
+ type: WarningType.OperationIdContainsSpecialCharacters,
2325
+ content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
2326
+ data: operationId,
2327
+ });
2328
+ }
2329
+ const authArray = Utils.getAuthArray(operationItem.security, newSpec);
2330
+ if (Utils.isNotSupportedAuth(authArray)) {
2331
+ result.warnings.push({
2332
+ type: WarningType.UnsupportedAuthType,
2333
+ content: Utils.format(ConstantString.AuthTypeIsNotSupported, operationId),
2334
+ data: operationId,
2335
+ });
2336
+ }
2337
+ }
2338
+ }
2192
2339
  await this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
2193
2340
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
2194
2341
  throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
@@ -2199,7 +2346,8 @@ class SpecParser {
2199
2346
  specPath: this.pathOrSpec,
2200
2347
  }
2201
2348
  : undefined;
2202
- const [updatedManifest, apiPlugin, warnings] = await ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authInfo, existingPluginManifestInfo);
2349
+ const authMap = Utils.getAuthMap(newSpec);
2350
+ const [updatedManifest, apiPlugin, warnings] = await ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authMap, existingPluginManifestInfo);
2203
2351
  result.warnings.push(...warnings);
2204
2352
  await fs.outputJSON(manifestPath, updatedManifest, { spaces: 4 });
2205
2353
  await fs.outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });
@@ -2240,13 +2388,14 @@ class SpecParser {
2240
2388
  if (this.options.allowMethods.includes(method)) {
2241
2389
  const operation = newSpec.paths[url][method];
2242
2390
  try {
2243
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
2391
+ const [card, jsonPath, jsonData, warnings] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
2392
+ result.warnings.push(...warnings);
2244
2393
  const safeAdaptiveCardName = operation.operationId.replace(/[^a-zA-Z0-9]/g, "_");
2245
2394
  const fileName = path.join(adaptiveCardFolder, `${safeAdaptiveCardName}.json`);
2246
2395
  const wrappedCard = wrapAdaptiveCard(card, jsonPath);
2247
2396
  await fs.outputJSON(fileName, wrappedCard, { spaces: 2 });
2248
2397
  const dataFileName = path.join(adaptiveCardFolder, `${safeAdaptiveCardName}.data.json`);
2249
- await fs.outputJSON(dataFileName, {}, { spaces: 2 });
2398
+ await fs.outputJSON(dataFileName, jsonData, { spaces: 2 });
2250
2399
  }
2251
2400
  catch (err) {
2252
2401
  result.allSuccess = false;
@@ -2286,7 +2435,7 @@ class SpecParser {
2286
2435
  this.isSwaggerFile = true;
2287
2436
  }
2288
2437
  const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
2289
- this.spec = (await this.parser.dereference(clonedUnResolveSpec));
2438
+ this.spec = await this.deReferenceSpec(clonedUnResolveSpec);
2290
2439
  }
2291
2440
  }
2292
2441
  getAPIs(spec) {