@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.
@@ -9,6 +9,7 @@ var fs = require('fs-extra');
9
9
  var path = require('path');
10
10
  var teamsManifest = require('@microsoft/teams-manifest');
11
11
  var crypto = require('crypto');
12
+ var jsonSchemaRefParser = require('@apidevtools/json-schema-ref-parser');
12
13
 
13
14
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
14
15
 
@@ -80,11 +81,8 @@ exports.ErrorType = void 0;
80
81
  ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
81
82
  ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
82
83
  ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
83
- ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
84
84
  ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
85
85
  ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
86
- ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
87
- ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
88
86
  ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
89
87
  ErrorType["NoParameter"] = "no-parameter";
90
88
  ErrorType["NoAPIInfo"] = "no-api-info";
@@ -103,6 +101,9 @@ exports.WarningType = void 0;
103
101
  WarningType["OperationOnlyContainsOptionalParam"] = "operation-only-contains-optional-param";
104
102
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
105
103
  WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
104
+ WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
105
+ WarningType["UnsupportedAuthType"] = "unsupported-auth-type";
106
+ WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
106
107
  WarningType["Unknown"] = "unknown";
107
108
  })(exports.WarningType || (exports.WarningType = {}));
108
109
  /**
@@ -140,25 +141,23 @@ ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converte
140
141
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
141
142
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
142
143
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
144
+ ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
145
+ ConstantString.AuthTypeIsNotSupported = "Unsupported authorization type in API '%s'. No authorization will be used.";
143
146
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
144
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.";
148
+ ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
145
149
  ConstantString.WrappedCardVersion = "devPreview";
146
150
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
147
151
  ConstantString.WrappedCardResponseLayout = "list";
148
152
  ConstantString.GetMethod = "get";
149
153
  ConstantString.PostMethod = "post";
150
154
  ConstantString.AdaptiveCardVersion = "1.5";
151
- ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
155
+ ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
152
156
  ConstantString.AdaptiveCardType = "AdaptiveCard";
153
157
  ConstantString.TextBlockType = "TextBlock";
154
158
  ConstantString.ImageType = "Image";
155
159
  ConstantString.ContainerType = "Container";
156
- ConstantString.RegistrationIdPostfix = {
157
- apiKey: "REGISTRATION_ID",
158
- oauth2: "CONFIGURATION_ID",
159
- http: "REGISTRATION_ID",
160
- openIdConnect: "REGISTRATION_ID",
161
- };
160
+ ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
162
161
  ConstantString.ResponseCodeFor20X = [
163
162
  "200",
164
163
  "201",
@@ -170,6 +169,7 @@ ConstantString.ResponseCodeFor20X = [
170
169
  "207",
171
170
  "208",
172
171
  "226",
172
+ "2XX",
173
173
  "default",
174
174
  ];
175
175
  ConstantString.AllOperationMethods = [
@@ -235,16 +235,8 @@ class SpecParserError extends Error {
235
235
 
236
236
  // Copyright (c) Microsoft Corporation.
237
237
  class Utils {
238
- static hasNestedObjectInSchema(schema) {
239
- if (schema.type === "object") {
240
- for (const property in schema.properties) {
241
- const nestedSchema = schema.properties[property];
242
- if (nestedSchema.type === "object") {
243
- return true;
244
- }
245
- }
246
- }
247
- return false;
238
+ static isObjectSchema(schema) {
239
+ return schema.type === "object" || (!schema.type && !!schema.properties);
248
240
  }
249
241
  static containMultipleMediaTypes(bodyObject) {
250
242
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
@@ -255,11 +247,32 @@ class Utils {
255
247
  static isAPIKeyAuth(authScheme) {
256
248
  return authScheme.type === "apiKey";
257
249
  }
250
+ static isAPIKeyAuthButNotInCookie(authScheme) {
251
+ return authScheme.type === "apiKey" && authScheme.in !== "cookie";
252
+ }
258
253
  static isOAuthWithAuthCodeFlow(authScheme) {
259
254
  return !!(authScheme.type === "oauth2" &&
260
255
  authScheme.flows &&
261
256
  authScheme.flows.authorizationCode);
262
257
  }
258
+ static isNotSupportedAuth(authSchemeArray) {
259
+ if (authSchemeArray.length === 0) {
260
+ return false;
261
+ }
262
+ if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
263
+ return true;
264
+ }
265
+ for (const auths of authSchemeArray) {
266
+ if (auths.length === 1) {
267
+ if (Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme) ||
268
+ Utils.isBearerTokenAuth(auths[0].authScheme) ||
269
+ Utils.isAPIKeyAuthButNotInCookie(auths[0].authScheme)) {
270
+ return false;
271
+ }
272
+ }
273
+ }
274
+ return true;
275
+ }
263
276
  static getAuthArray(securities, spec) {
264
277
  var _a;
265
278
  const result = [];
@@ -284,6 +297,20 @@ class Utils {
284
297
  result.sort((a, b) => a[0].name.localeCompare(b[0].name));
285
298
  return result;
286
299
  }
300
+ static getAuthMap(spec) {
301
+ const authMap = {};
302
+ for (const url in spec.paths) {
303
+ for (const method in spec.paths[url]) {
304
+ const operation = spec.paths[url][method];
305
+ const authArray = Utils.getAuthArray(operation.security, spec);
306
+ if (authArray && authArray.length > 0) {
307
+ const currentAuth = authArray[0][0];
308
+ authMap[operation.operationId] = currentAuth;
309
+ }
310
+ }
311
+ }
312
+ return authMap;
313
+ }
287
314
  static getAuthInfo(spec) {
288
315
  let authInfo = undefined;
289
316
  for (const url in spec.paths) {
@@ -312,27 +339,33 @@ class Utils {
312
339
  let multipleMediaType = false;
313
340
  for (const code of ConstantString.ResponseCodeFor20X) {
314
341
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
315
- if (responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) {
316
- for (const contentType of Object.keys(responseObject.content)) {
317
- // json media type can also be "application/json; charset=utf-8"
318
- if (contentType.indexOf("application/json") >= 0) {
319
- multipleMediaType = false;
320
- json = responseObject.content[contentType];
321
- if (Utils.containMultipleMediaTypes(responseObject)) {
322
- multipleMediaType = true;
323
- if (!allowMultipleMediaType) {
324
- json = {};
325
- }
326
- }
327
- else {
328
- return { json, multipleMediaType };
329
- }
330
- }
331
- }
342
+ if (!responseObject) {
343
+ continue;
344
+ }
345
+ multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
346
+ if (!allowMultipleMediaType && multipleMediaType) {
347
+ json = {};
348
+ continue;
349
+ }
350
+ const mediaObj = Utils.getJsonContentType(responseObject);
351
+ if (Object.keys(mediaObj).length > 0) {
352
+ json = mediaObj;
353
+ return { json, multipleMediaType };
332
354
  }
333
355
  }
334
356
  return { json, multipleMediaType };
335
357
  }
358
+ static getJsonContentType(responseObject) {
359
+ if (responseObject.content) {
360
+ for (const contentType of Object.keys(responseObject.content)) {
361
+ // json media type can also be "application/json; charset=utf-8"
362
+ if (contentType.indexOf("application/json") >= 0) {
363
+ return responseObject.content[contentType];
364
+ }
365
+ }
366
+ }
367
+ return {};
368
+ }
336
369
  static convertPathToCamelCase(path) {
337
370
  const pathSegments = path.split(/[./{]/);
338
371
  const camelCaseSegments = pathSegments.map((segment) => {
@@ -368,7 +401,7 @@ class Utils {
368
401
  }
369
402
  return newStr;
370
403
  }
371
- static checkServerUrl(servers) {
404
+ static checkServerUrl(servers, allowHttp = false) {
372
405
  const errors = [];
373
406
  let serverUrl;
374
407
  try {
@@ -391,8 +424,7 @@ class Utils {
391
424
  data: servers,
392
425
  });
393
426
  }
394
- else if (protocol !== "https:") {
395
- // Http server url is not supported
427
+ else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
396
428
  const protocolString = protocol.slice(0, -1);
397
429
  errors.push({
398
430
  type: exports.ErrorType.UrlProtocolNotSupported,
@@ -408,10 +440,11 @@ class Utils {
408
440
  let hasTopLevelServers = false;
409
441
  let hasPathLevelServers = false;
410
442
  let hasOperationLevelServers = false;
443
+ const allowHttp = options.projectType === exports.ProjectType.Copilot;
411
444
  if (spec.servers && spec.servers.length >= 1) {
412
445
  hasTopLevelServers = true;
413
446
  // for multiple server, we only use the first url
414
- const serverErrors = Utils.checkServerUrl(spec.servers);
447
+ const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
415
448
  errors.push(...serverErrors);
416
449
  }
417
450
  const paths = spec.paths;
@@ -419,7 +452,7 @@ class Utils {
419
452
  const methods = paths[path];
420
453
  if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
421
454
  hasPathLevelServers = true;
422
- const serverErrors = Utils.checkServerUrl(methods.servers);
455
+ const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
423
456
  errors.push(...serverErrors);
424
457
  }
425
458
  for (const method in methods) {
@@ -427,7 +460,7 @@ class Utils {
427
460
  if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
428
461
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
429
462
  hasOperationLevelServers = true;
430
- const serverErrors = Utils.checkServerUrl(operationObject.servers);
463
+ const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
431
464
  errors.push(...serverErrors);
432
465
  }
433
466
  }
@@ -474,7 +507,7 @@ class Utils {
474
507
  optionalParams.push(parameter);
475
508
  }
476
509
  }
477
- else if (schema.type === "object") {
510
+ else if (Utils.isObjectSchema(schema)) {
478
511
  const { properties } = schema;
479
512
  for (const property in properties) {
480
513
  let isRequired = false;
@@ -588,29 +621,6 @@ class Utils {
588
621
  const serverUrl = operationServer || methodServer || rootServer;
589
622
  return serverUrl;
590
623
  }
591
- static limitACBodyProperties(body, maxCount) {
592
- const result = [];
593
- let currentCount = 0;
594
- for (const element of body) {
595
- if (element.type === ConstantString.ContainerType) {
596
- const items = this.limitACBodyProperties(element.items, maxCount - currentCount);
597
- result.push({
598
- type: ConstantString.ContainerType,
599
- $data: element.$data,
600
- items: items,
601
- });
602
- currentCount += items.length;
603
- }
604
- else {
605
- result.push(element);
606
- currentCount++;
607
- }
608
- if (currentCount >= maxCount) {
609
- break;
610
- }
611
- }
612
- return result;
613
- }
614
624
  }
615
625
 
616
626
  // Copyright (c) Microsoft Corporation.
@@ -739,22 +749,6 @@ class Validator {
739
749
  }
740
750
  return result;
741
751
  }
742
- validateResponse(method, path) {
743
- const result = { isValid: true, reason: [] };
744
- const operationObject = this.spec.paths[path][method];
745
- const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
746
- if (this.options.projectType === exports.ProjectType.SME) {
747
- // only support response body only contains “application/json” content type
748
- if (multipleMediaType) {
749
- result.reason.push(exports.ErrorType.ResponseContainMultipleMediaTypes);
750
- }
751
- else if (Object.keys(json).length === 0) {
752
- // response body should not be empty
753
- result.reason.push(exports.ErrorType.ResponseJsonIsEmpty);
754
- }
755
- }
756
- return result;
757
- }
758
752
  validateServer(method, path) {
759
753
  const result = { isValid: true, reason: [] };
760
754
  const serverObj = Utils.getServerObject(this.spec, method, path);
@@ -763,8 +757,8 @@ class Validator {
763
757
  result.reason.push(exports.ErrorType.NoServerInformation);
764
758
  }
765
759
  else {
766
- // server url should be absolute url with https protocol
767
- const serverValidateResult = Utils.checkServerUrl([serverObj]);
760
+ const allowHttp = this.projectType === exports.ProjectType.Copilot;
761
+ const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
768
762
  result.reason.push(...serverValidateResult.map((item) => item.type));
769
763
  }
770
764
  return result;
@@ -787,6 +781,9 @@ class Validator {
787
781
  reason: [exports.ErrorType.MultipleAuthNotSupported],
788
782
  };
789
783
  }
784
+ if (this.projectType === exports.ProjectType.Copilot) {
785
+ return { isValid: true, reason: [] };
786
+ }
790
787
  for (const auths of authSchemeArray) {
791
788
  if (auths.length === 1) {
792
789
  if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
@@ -799,125 +796,6 @@ class Validator {
799
796
  }
800
797
  return { isValid: false, reason: [exports.ErrorType.AuthTypeIsNotSupported] };
801
798
  }
802
- checkPostBodySchema(schema, isRequired = false) {
803
- var _a;
804
- const paramResult = {
805
- requiredNum: 0,
806
- optionalNum: 0,
807
- isValid: true,
808
- reason: [],
809
- };
810
- if (Object.keys(schema).length === 0) {
811
- return paramResult;
812
- }
813
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
814
- const isCopilot = this.projectType === exports.ProjectType.Copilot;
815
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
816
- paramResult.isValid = false;
817
- paramResult.reason = [exports.ErrorType.RequestBodyContainsNestedObject];
818
- return paramResult;
819
- }
820
- if (schema.type === "string" ||
821
- schema.type === "integer" ||
822
- schema.type === "boolean" ||
823
- schema.type === "number") {
824
- if (isRequiredWithoutDefault) {
825
- paramResult.requiredNum = paramResult.requiredNum + 1;
826
- }
827
- else {
828
- paramResult.optionalNum = paramResult.optionalNum + 1;
829
- }
830
- }
831
- else if (schema.type === "object") {
832
- const { properties } = schema;
833
- for (const property in properties) {
834
- let isRequired = false;
835
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
836
- isRequired = true;
837
- }
838
- const result = this.checkPostBodySchema(properties[property], isRequired);
839
- paramResult.requiredNum += result.requiredNum;
840
- paramResult.optionalNum += result.optionalNum;
841
- paramResult.isValid = paramResult.isValid && result.isValid;
842
- paramResult.reason.push(...result.reason);
843
- }
844
- }
845
- else {
846
- if (isRequiredWithoutDefault && !isCopilot) {
847
- paramResult.isValid = false;
848
- paramResult.reason.push(exports.ErrorType.PostBodyContainsRequiredUnsupportedSchema);
849
- }
850
- }
851
- return paramResult;
852
- }
853
- checkParamSchema(paramObject) {
854
- const paramResult = {
855
- requiredNum: 0,
856
- optionalNum: 0,
857
- isValid: true,
858
- reason: [],
859
- };
860
- if (!paramObject) {
861
- return paramResult;
862
- }
863
- const isCopilot = this.projectType === exports.ProjectType.Copilot;
864
- for (let i = 0; i < paramObject.length; i++) {
865
- const param = paramObject[i];
866
- const schema = param.schema;
867
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
868
- paramResult.isValid = false;
869
- paramResult.reason.push(exports.ErrorType.ParamsContainsNestedObject);
870
- continue;
871
- }
872
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
873
- if (isCopilot) {
874
- if (isRequiredWithoutDefault) {
875
- paramResult.requiredNum = paramResult.requiredNum + 1;
876
- }
877
- else {
878
- paramResult.optionalNum = paramResult.optionalNum + 1;
879
- }
880
- continue;
881
- }
882
- if (param.in === "header" || param.in === "cookie") {
883
- if (isRequiredWithoutDefault) {
884
- paramResult.isValid = false;
885
- paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
886
- }
887
- continue;
888
- }
889
- if (schema.type !== "boolean" &&
890
- schema.type !== "string" &&
891
- schema.type !== "number" &&
892
- schema.type !== "integer") {
893
- if (isRequiredWithoutDefault) {
894
- paramResult.isValid = false;
895
- paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
896
- }
897
- continue;
898
- }
899
- if (param.in === "query" || param.in === "path") {
900
- if (isRequiredWithoutDefault) {
901
- paramResult.requiredNum = paramResult.requiredNum + 1;
902
- }
903
- else {
904
- paramResult.optionalNum = paramResult.optionalNum + 1;
905
- }
906
- }
907
- }
908
- return paramResult;
909
- }
910
- hasNestedObjectInSchema(schema) {
911
- if (schema.type === "object") {
912
- for (const property in schema.properties) {
913
- const nestedSchema = schema.properties[property];
914
- if (nestedSchema.type === "object") {
915
- return true;
916
- }
917
- }
918
- }
919
- return false;
920
- }
921
799
  }
922
800
 
923
801
  // Copyright (c) Microsoft Corporation.
@@ -927,7 +805,6 @@ class CopilotValidator extends Validator {
927
805
  this.projectType = exports.ProjectType.Copilot;
928
806
  this.options = options;
929
807
  this.spec = spec;
930
- this.checkCircularReference();
931
808
  }
932
809
  validateSpec() {
933
810
  const result = { errors: [], warnings: [] };
@@ -953,10 +830,6 @@ class CopilotValidator extends Validator {
953
830
  if (!methodAndPathResult.isValid) {
954
831
  return methodAndPathResult;
955
832
  }
956
- const circularReferenceResult = this.validateCircularReference(method, path);
957
- if (!circularReferenceResult.isValid) {
958
- return circularReferenceResult;
959
- }
960
833
  const operationObject = this.spec.paths[path][method];
961
834
  // validate auth
962
835
  const authCheckResult = this.validateAuth(method, path);
@@ -968,24 +841,6 @@ class CopilotValidator extends Validator {
968
841
  // validate server
969
842
  const validateServerResult = this.validateServer(method, path);
970
843
  result.reason.push(...validateServerResult.reason);
971
- // validate response
972
- const validateResponseResult = this.validateResponse(method, path);
973
- result.reason.push(...validateResponseResult.reason);
974
- // validate requestBody
975
- const requestBody = operationObject.requestBody;
976
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
977
- if (requestJsonBody) {
978
- const requestBodySchema = requestJsonBody.schema;
979
- if (requestBodySchema.type !== "object") {
980
- result.reason.push(exports.ErrorType.PostBodySchemaIsNotJson);
981
- }
982
- const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
983
- result.reason.push(...requestBodyParamResult.reason);
984
- }
985
- // validate parameters
986
- const paramObject = operationObject.parameters;
987
- const paramResult = this.checkParamSchema(paramObject);
988
- result.reason.push(...paramResult.reason);
989
844
  if (result.reason.length > 0) {
990
845
  result.isValid = false;
991
846
  }
@@ -1077,6 +932,108 @@ class SMEValidator extends Validator {
1077
932
  }
1078
933
  return result;
1079
934
  }
935
+ validateResponse(method, path) {
936
+ const result = { isValid: true, reason: [] };
937
+ const operationObject = this.spec.paths[path][method];
938
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
939
+ // only support response body only contains “application/json” content type
940
+ if (multipleMediaType) {
941
+ result.reason.push(exports.ErrorType.ResponseContainMultipleMediaTypes);
942
+ }
943
+ else if (Object.keys(json).length === 0) {
944
+ // response body should not be empty
945
+ result.reason.push(exports.ErrorType.ResponseJsonIsEmpty);
946
+ }
947
+ return result;
948
+ }
949
+ checkPostBodySchema(schema, isRequired = false) {
950
+ var _a;
951
+ const paramResult = {
952
+ requiredNum: 0,
953
+ optionalNum: 0,
954
+ isValid: true,
955
+ reason: [],
956
+ };
957
+ if (Object.keys(schema).length === 0) {
958
+ return paramResult;
959
+ }
960
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
961
+ const isCopilot = this.projectType === exports.ProjectType.Copilot;
962
+ if (schema.type === "string" ||
963
+ schema.type === "integer" ||
964
+ schema.type === "boolean" ||
965
+ schema.type === "number") {
966
+ if (isRequiredWithoutDefault) {
967
+ paramResult.requiredNum = paramResult.requiredNum + 1;
968
+ }
969
+ else {
970
+ paramResult.optionalNum = paramResult.optionalNum + 1;
971
+ }
972
+ }
973
+ else if (Utils.isObjectSchema(schema)) {
974
+ const { properties } = schema;
975
+ for (const property in properties) {
976
+ let isRequired = false;
977
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
978
+ isRequired = true;
979
+ }
980
+ const result = this.checkPostBodySchema(properties[property], isRequired);
981
+ paramResult.requiredNum += result.requiredNum;
982
+ paramResult.optionalNum += result.optionalNum;
983
+ paramResult.isValid = paramResult.isValid && result.isValid;
984
+ paramResult.reason.push(...result.reason);
985
+ }
986
+ }
987
+ else {
988
+ if (isRequiredWithoutDefault && !isCopilot) {
989
+ paramResult.isValid = false;
990
+ paramResult.reason.push(exports.ErrorType.PostBodyContainsRequiredUnsupportedSchema);
991
+ }
992
+ }
993
+ return paramResult;
994
+ }
995
+ checkParamSchema(paramObject) {
996
+ const paramResult = {
997
+ requiredNum: 0,
998
+ optionalNum: 0,
999
+ isValid: true,
1000
+ reason: [],
1001
+ };
1002
+ if (!paramObject) {
1003
+ return paramResult;
1004
+ }
1005
+ for (let i = 0; i < paramObject.length; i++) {
1006
+ const param = paramObject[i];
1007
+ const schema = param.schema;
1008
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
1009
+ if (param.in === "header" || param.in === "cookie") {
1010
+ if (isRequiredWithoutDefault) {
1011
+ paramResult.isValid = false;
1012
+ paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
1013
+ }
1014
+ continue;
1015
+ }
1016
+ if (schema.type !== "boolean" &&
1017
+ schema.type !== "string" &&
1018
+ schema.type !== "number" &&
1019
+ schema.type !== "integer") {
1020
+ if (isRequiredWithoutDefault) {
1021
+ paramResult.isValid = false;
1022
+ paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
1023
+ }
1024
+ continue;
1025
+ }
1026
+ if (param.in === "query" || param.in === "path") {
1027
+ if (isRequiredWithoutDefault) {
1028
+ paramResult.requiredNum = paramResult.requiredNum + 1;
1029
+ }
1030
+ else {
1031
+ paramResult.optionalNum = paramResult.optionalNum + 1;
1032
+ }
1033
+ }
1034
+ }
1035
+ return paramResult;
1036
+ }
1080
1037
  validateParamCount(postBodyResult, paramResult) {
1081
1038
  const result = { isValid: true, reason: [] };
1082
1039
  const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
@@ -1354,20 +1311,157 @@ class SpecFilter {
1354
1311
  }
1355
1312
  }
1356
1313
 
1314
+ // Copyright (c) Microsoft Corporation.
1315
+ class JsonDataGenerator {
1316
+ static generate(schema) {
1317
+ return this.generateMockData(schema);
1318
+ }
1319
+ static generateMockData(schema) {
1320
+ if (this.visitedSchemas.has(schema)) {
1321
+ return null; // Prevent circular reference
1322
+ }
1323
+ this.visitedSchemas.add(schema);
1324
+ let result;
1325
+ if (schema.anyOf) {
1326
+ // Select the first schema in anyOf
1327
+ const selectedSchema = schema.anyOf[0];
1328
+ result = this.generateMockData(selectedSchema);
1329
+ }
1330
+ else if (schema.oneOf) {
1331
+ // Select the first schema in oneOf
1332
+ const selectedSchema = schema.oneOf[0];
1333
+ result = this.generateMockData(selectedSchema);
1334
+ }
1335
+ else if (schema.allOf) {
1336
+ // merge all schemas in allOf
1337
+ result = {};
1338
+ for (const subschema of schema.allOf) {
1339
+ const data = this.generateMockData(subschema);
1340
+ result = Object.assign(Object.assign({}, result), data);
1341
+ }
1342
+ }
1343
+ else {
1344
+ switch (schema.type) {
1345
+ case "string":
1346
+ if (schema.example !== undefined) {
1347
+ result = schema.example;
1348
+ }
1349
+ else if (schema.format) {
1350
+ switch (schema.format) {
1351
+ case "date-time":
1352
+ result = "2024-11-01T05:25:43.593Z";
1353
+ break;
1354
+ case "email":
1355
+ result = "example@example.com";
1356
+ break;
1357
+ case "uuid":
1358
+ result = "123e4567-e89b-12d3-a456-426614174000";
1359
+ break;
1360
+ case "ipv4":
1361
+ result = "192.168.0.1";
1362
+ break;
1363
+ case "ipv6":
1364
+ result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
1365
+ break;
1366
+ default:
1367
+ result = "example string";
1368
+ }
1369
+ }
1370
+ else {
1371
+ result = "example string";
1372
+ }
1373
+ break;
1374
+ case "number":
1375
+ if (schema.example !== undefined) {
1376
+ result = schema.example;
1377
+ }
1378
+ else if (schema.format) {
1379
+ switch (schema.format) {
1380
+ case "float":
1381
+ result = 3.14;
1382
+ break;
1383
+ case "double":
1384
+ result = 3.14159;
1385
+ break;
1386
+ default:
1387
+ result = 123;
1388
+ }
1389
+ }
1390
+ else {
1391
+ result = 123;
1392
+ }
1393
+ break;
1394
+ case "integer":
1395
+ if (schema.example !== undefined) {
1396
+ result = schema.example;
1397
+ }
1398
+ else if (schema.format) {
1399
+ switch (schema.format) {
1400
+ case "int32":
1401
+ result = 123456;
1402
+ break;
1403
+ case "int64":
1404
+ result = 123456789;
1405
+ break;
1406
+ default:
1407
+ result = 123;
1408
+ }
1409
+ }
1410
+ else {
1411
+ result = 123;
1412
+ }
1413
+ break;
1414
+ case "boolean":
1415
+ result = schema.example !== undefined ? schema.example : true;
1416
+ break;
1417
+ case "array":
1418
+ result = [this.generateMockData(schema.items)];
1419
+ break;
1420
+ case "object":
1421
+ result = {};
1422
+ if (schema.properties) {
1423
+ for (const key in schema.properties) {
1424
+ result[key] = this.generateMockData(schema.properties[key]);
1425
+ }
1426
+ }
1427
+ break;
1428
+ default:
1429
+ result = schema.example || null;
1430
+ }
1431
+ }
1432
+ this.visitedSchemas.delete(schema);
1433
+ return result;
1434
+ }
1435
+ }
1436
+ JsonDataGenerator.visitedSchemas = new Set();
1437
+
1357
1438
  // Copyright (c) Microsoft Corporation.
1358
1439
  class AdaptiveCardGenerator {
1359
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1440
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1360
1441
  try {
1361
1442
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1362
1443
  let cardBody = [];
1444
+ let jsonData = {};
1445
+ const warnings = [];
1446
+ const operationId = operationItem.operationId;
1363
1447
  let schema = json.schema;
1364
1448
  let jsonPath = "$";
1365
1449
  if (schema && Object.keys(schema).length > 0) {
1450
+ try {
1451
+ jsonData = JsonDataGenerator.generate(schema);
1452
+ }
1453
+ catch (err) {
1454
+ warnings.push({
1455
+ type: exports.WarningType.GenerateJsonDataFailed,
1456
+ content: Utils.format(ConstantString.GenerateJsonDataFailed, operationId, err.toString()),
1457
+ data: operationId,
1458
+ });
1459
+ }
1366
1460
  jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
1367
1461
  if (jsonPath !== "$") {
1368
1462
  schema = schema.properties[jsonPath];
1369
1463
  }
1370
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1464
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1371
1465
  }
1372
1466
  // if no schema, try to use example value
1373
1467
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1395,16 +1489,20 @@ class AdaptiveCardGenerator {
1395
1489
  version: ConstantString.AdaptiveCardVersion,
1396
1490
  body: cardBody,
1397
1491
  };
1398
- return [fullCard, jsonPath];
1492
+ return [fullCard, jsonPath, jsonData, warnings];
1399
1493
  }
1400
1494
  catch (err) {
1401
1495
  throw new SpecParserError(err.toString(), exports.ErrorType.GenerateAdaptiveCardFailed);
1402
1496
  }
1403
1497
  }
1404
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1498
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1499
+ if (counter.count >= maxElementCount) {
1500
+ return [];
1501
+ }
1405
1502
  if (schema.type === "array") {
1406
1503
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1407
1504
  if (Object.keys(schema.items).length === 0) {
1505
+ counter.count++;
1408
1506
  return [
1409
1507
  {
1410
1508
  type: ConstantString.TextBlockType,
@@ -1413,7 +1511,7 @@ class AdaptiveCardGenerator {
1413
1511
  },
1414
1512
  ];
1415
1513
  }
1416
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1514
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1417
1515
  const template = {
1418
1516
  type: ConstantString.ContainerType,
1419
1517
  $data: name ? `\${${name}}` : "${$root}",
@@ -1423,11 +1521,11 @@ class AdaptiveCardGenerator {
1423
1521
  return [template];
1424
1522
  }
1425
1523
  // some schema may not contain type but contain properties
1426
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1524
+ if (Utils.isObjectSchema(schema)) {
1427
1525
  const { properties } = schema;
1428
1526
  const result = [];
1429
1527
  for (const property in properties) {
1430
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1528
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1431
1529
  result.push(...obj);
1432
1530
  }
1433
1531
  if (schema.additionalProperties) {
@@ -1440,6 +1538,7 @@ class AdaptiveCardGenerator {
1440
1538
  schema.type === "integer" ||
1441
1539
  schema.type === "boolean" ||
1442
1540
  schema.type === "number") {
1541
+ counter.count++;
1443
1542
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1444
1543
  // string in root: "ddd"
1445
1544
  let text = "result: ${$root}";
@@ -1464,24 +1563,17 @@ class AdaptiveCardGenerator {
1464
1563
  ];
1465
1564
  }
1466
1565
  else {
1467
- if (name) {
1468
- return [
1469
- {
1470
- type: "Image",
1471
- url: `\${${name}}`,
1472
- $when: `\${${name} != null && ${name} != ''}`,
1473
- },
1474
- ];
1475
- }
1476
- else {
1477
- return [
1478
- {
1479
- type: "Image",
1480
- url: "${$data}",
1481
- $when: "${$data != null && $data != ''}",
1482
- },
1483
- ];
1484
- }
1566
+ const url = name ? `\${${name}}` : "${$data}";
1567
+ const condition = name
1568
+ ? `\${${name} != null && ${name} != ''}`
1569
+ : "${$data != null && $data != ''}";
1570
+ return [
1571
+ {
1572
+ type: "Image",
1573
+ url,
1574
+ $when: condition,
1575
+ },
1576
+ ];
1485
1577
  }
1486
1578
  }
1487
1579
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1491,7 +1583,7 @@ class AdaptiveCardGenerator {
1491
1583
  }
1492
1584
  // Find the first array property in the response schema object with the well-known name
1493
1585
  static getResponseJsonPathFromSchema(schema) {
1494
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1586
+ if (Utils.isObjectSchema(schema)) {
1495
1587
  const { properties } = schema;
1496
1588
  for (const property in properties) {
1497
1589
  const schema = properties[property];
@@ -1643,7 +1735,7 @@ function inferProperties(card) {
1643
1735
 
1644
1736
  // Copyright (c) Microsoft Corporation.
1645
1737
  class ManifestUpdater {
1646
- static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo, existingPluginManifestInfo) {
1738
+ static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authMap, existingPluginManifestInfo) {
1647
1739
  return __awaiter(this, void 0, void 0, function* () {
1648
1740
  const manifest = yield fs__default['default'].readJSON(manifestPath);
1649
1741
  const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
@@ -1674,7 +1766,7 @@ class ManifestUpdater {
1674
1766
  }
1675
1767
  const appName = this.removeEnvs(manifest.name.short);
1676
1768
  const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
1677
- const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo);
1769
+ const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo);
1678
1770
  return [manifest, apiPlugin, warnings];
1679
1771
  });
1680
1772
  }
@@ -1697,29 +1789,14 @@ class ManifestUpdater {
1697
1789
  throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), exports.ErrorType.UpdateManifestFailed);
1698
1790
  }
1699
1791
  }
1700
- static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo) {
1792
+ static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo) {
1701
1793
  var _a, _b, _c, _d;
1702
1794
  return __awaiter(this, void 0, void 0, function* () {
1703
1795
  const warnings = [];
1704
1796
  const functions = [];
1705
- const functionNames = [];
1797
+ const functionNamesMap = {};
1706
1798
  const conversationStarters = [];
1707
1799
  const paths = spec.paths;
1708
- const pluginAuthObj = {
1709
- type: "None",
1710
- };
1711
- if (authInfo) {
1712
- if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
1713
- pluginAuthObj.type = "OAuthPluginVault";
1714
- }
1715
- else if (Utils.isBearerTokenAuth(authInfo.authScheme)) {
1716
- pluginAuthObj.type = "ApiKeyPluginVault";
1717
- }
1718
- if (pluginAuthObj.type !== "None") {
1719
- const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
1720
- pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
1721
- }
1722
- }
1723
1800
  for (const pathUrl in paths) {
1724
1801
  const pathItem = paths[pathUrl];
1725
1802
  if (pathItem) {
@@ -1727,36 +1804,11 @@ class ManifestUpdater {
1727
1804
  for (const method in operations) {
1728
1805
  if (options.allowMethods.includes(method)) {
1729
1806
  const operationItem = operations[method];
1730
- const confirmationBodies = [];
1731
1807
  if (operationItem) {
1732
1808
  const operationId = operationItem.operationId;
1733
1809
  const safeFunctionName = operationId.replace(/[^a-zA-Z0-9]/g, "_");
1734
1810
  const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
1735
1811
  const summary = operationItem.summary;
1736
- const paramObject = operationItem.parameters;
1737
- const requestBody = operationItem.requestBody;
1738
- if (paramObject) {
1739
- for (let i = 0; i < paramObject.length; i++) {
1740
- const param = paramObject[i];
1741
- const schema = param.schema;
1742
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1743
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1744
- }
1745
- }
1746
- if (requestBody) {
1747
- const requestJsonBody = requestBody.content["application/json"];
1748
- const requestBodySchema = requestJsonBody.schema;
1749
- if (requestBodySchema.type === "object") {
1750
- for (const property in requestBodySchema.properties) {
1751
- const schema = requestBodySchema.properties[property];
1752
- ManifestUpdater.checkSchema(schema, method, pathUrl);
1753
- confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1754
- }
1755
- }
1756
- else {
1757
- throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
1758
- }
1759
- }
1760
1812
  let funcDescription = operationItem.description || operationItem.summary || "";
1761
1813
  if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
1762
1814
  warnings.push({
@@ -1774,8 +1826,7 @@ class ManifestUpdater {
1774
1826
  try {
1775
1827
  const { json } = Utils.getResponseJson(operationItem);
1776
1828
  if (json.schema) {
1777
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem);
1778
- card.body = Utils.limitACBodyProperties(card.body, 5);
1829
+ const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem, false, 5);
1779
1830
  const responseSemantic = wrapResponseSemantics(card, jsonPath);
1780
1831
  funcObj.capabilities = {
1781
1832
  response_semantics: responseSemantic,
@@ -1791,19 +1842,66 @@ class ManifestUpdater {
1791
1842
  }
1792
1843
  }
1793
1844
  if (options.allowConfirmation && method !== ConstantString.GetMethod) {
1794
- if (!funcObj.capabilities) {
1795
- funcObj.capabilities = {};
1845
+ const paramObject = operationItem.parameters;
1846
+ const requestBody = operationItem.requestBody;
1847
+ const confirmationBodies = [];
1848
+ if (paramObject) {
1849
+ for (let i = 0; i < paramObject.length; i++) {
1850
+ const param = paramObject[i];
1851
+ const schema = param.schema;
1852
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1853
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
1854
+ }
1855
+ }
1856
+ if (requestBody) {
1857
+ const requestJsonBody = Utils.getJsonContentType(requestBody);
1858
+ const requestBodySchema = requestJsonBody.schema;
1859
+ if (Utils.isObjectSchema(requestBodySchema)) {
1860
+ for (const property in requestBodySchema.properties) {
1861
+ const schema = requestBodySchema.properties[property];
1862
+ ManifestUpdater.checkSchema(schema, method, pathUrl);
1863
+ confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
1864
+ }
1865
+ }
1866
+ else {
1867
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
1868
+ }
1796
1869
  }
1797
- funcObj.capabilities.confirmation = {
1798
- type: "AdaptiveCard",
1799
- title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1800
- };
1801
1870
  if (confirmationBodies.length > 0) {
1871
+ if (!funcObj.capabilities) {
1872
+ funcObj.capabilities = {};
1873
+ }
1874
+ funcObj.capabilities.confirmation = {
1875
+ type: "AdaptiveCard",
1876
+ title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
1877
+ };
1802
1878
  funcObj.capabilities.confirmation.body = confirmationBodies.join("\n");
1803
1879
  }
1804
1880
  }
1805
1881
  functions.push(funcObj);
1806
- functionNames.push(safeFunctionName);
1882
+ const authInfo = authMap[operationId];
1883
+ let key = "None";
1884
+ let authName = "None";
1885
+ if (authInfo) {
1886
+ if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
1887
+ key = "OAuthPluginVault";
1888
+ authName = authInfo.name;
1889
+ }
1890
+ else if (Utils.isBearerTokenAuth(authInfo.authScheme) ||
1891
+ Utils.isAPIKeyAuthButNotInCookie(authInfo.authScheme)) {
1892
+ key = "ApiKeyPluginVault";
1893
+ authName = authInfo.name;
1894
+ }
1895
+ }
1896
+ if (functionNamesMap[key]) {
1897
+ functionNamesMap[key].functionNames.push(safeFunctionName);
1898
+ }
1899
+ else {
1900
+ functionNamesMap[key] = {
1901
+ functionNames: [safeFunctionName],
1902
+ authName: authName,
1903
+ };
1904
+ }
1807
1905
  const conversationStarterStr = (summary !== null && summary !== void 0 ? summary : description).slice(0, ConstantString.ConversationStarterMaxLens);
1808
1906
  if (conversationStarterStr) {
1809
1907
  conversationStarters.push(conversationStarterStr);
@@ -1813,6 +1911,12 @@ class ManifestUpdater {
1813
1911
  }
1814
1912
  }
1815
1913
  }
1914
+ if (Object.keys(functionNamesMap).length === 0) {
1915
+ functionNamesMap["None"] = {
1916
+ functionNames: [],
1917
+ authName: "None",
1918
+ };
1919
+ }
1816
1920
  let apiPlugin;
1817
1921
  if (yield fs__default['default'].pathExists(apiPluginFilePath)) {
1818
1922
  apiPlugin = yield fs__default['default'].readJSON(apiPluginFilePath);
@@ -1848,24 +1952,35 @@ class ManifestUpdater {
1848
1952
  const relativePath = ManifestUpdater.getRelativePath(existingPluginManifestInfo.manifestPath, existingPluginManifestInfo.specPath);
1849
1953
  apiPlugin.runtimes = apiPlugin.runtimes.filter((runtime) => runtime.spec.url !== relativePath);
1850
1954
  }
1851
- const index = apiPlugin.runtimes.findIndex((runtime) => {
1852
- var _a, _b;
1853
- return runtime.spec.url === specRelativePath &&
1854
- runtime.type === "OpenApi" &&
1855
- ((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === pluginAuthObj.type;
1856
- });
1857
- if (index === -1) {
1858
- apiPlugin.runtimes.push({
1859
- type: "OpenApi",
1860
- auth: pluginAuthObj,
1861
- spec: {
1862
- url: specRelativePath,
1863
- },
1864
- run_for_functions: functionNames,
1955
+ for (const authType in functionNamesMap) {
1956
+ const pluginAuthObj = {
1957
+ type: authType,
1958
+ };
1959
+ const authName = functionNamesMap[authType].authName;
1960
+ if (pluginAuthObj.type !== "None") {
1961
+ const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authName}_${ConstantString.RegistrationIdPostfix}`);
1962
+ pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
1963
+ }
1964
+ const functionNamesInfo = functionNamesMap[authType];
1965
+ const index = apiPlugin.runtimes.findIndex((runtime) => {
1966
+ var _a, _b;
1967
+ return runtime.spec.url === specRelativePath &&
1968
+ runtime.type === "OpenApi" &&
1969
+ ((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === authType;
1865
1970
  });
1866
- }
1867
- else {
1868
- apiPlugin.runtimes[index].run_for_functions = functionNames;
1971
+ if (index === -1) {
1972
+ apiPlugin.runtimes.push({
1973
+ type: "OpenApi",
1974
+ auth: pluginAuthObj,
1975
+ spec: {
1976
+ url: specRelativePath,
1977
+ },
1978
+ run_for_functions: functionNamesInfo.functionNames,
1979
+ });
1980
+ }
1981
+ else {
1982
+ apiPlugin.runtimes[index].run_for_functions = functionNamesInfo.functionNames;
1983
+ }
1869
1984
  }
1870
1985
  if (!apiPlugin.name_for_human) {
1871
1986
  apiPlugin.name_for_human = appName;
@@ -1908,7 +2023,7 @@ class ManifestUpdater {
1908
2023
  };
1909
2024
  if (authInfo) {
1910
2025
  const auth = authInfo.authScheme;
1911
- const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
2026
+ const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
1912
2027
  if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
1913
2028
  composeExtension.authorization = {
1914
2029
  authType: "apiSecretServiceAuth",
@@ -2038,6 +2153,7 @@ class SpecParser {
2038
2153
  };
2039
2154
  this.pathOrSpec = pathOrDoc;
2040
2155
  this.parser = new SwaggerParser__default['default']();
2156
+ this.refParser = new jsonSchemaRefParser.$RefParser();
2041
2157
  this.options = Object.assign(Object.assign({}, this.defaultOptions), (options !== null && options !== void 0 ? options : {}));
2042
2158
  }
2043
2159
  /**
@@ -2051,12 +2167,15 @@ class SpecParser {
2051
2167
  let hash = "";
2052
2168
  try {
2053
2169
  yield this.loadSpec();
2054
- if (!this.parser.$refs.circular) {
2170
+ if (!this.refParser.$refs.circular) {
2055
2171
  yield this.parser.validate(this.spec);
2056
2172
  }
2057
2173
  else {
2174
+ // The following code hangs for Graph API, support will be added when SwaggerParser is updated.
2175
+ /*
2058
2176
  const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
2059
- yield this.parser.validate(clonedUnResolveSpec);
2177
+ await this.parser.validate(clonedUnResolveSpec);
2178
+ */
2060
2179
  }
2061
2180
  }
2062
2181
  catch (e) {
@@ -2084,7 +2203,7 @@ class SpecParser {
2084
2203
  };
2085
2204
  }
2086
2205
  // Remote reference not supported
2087
- const refPaths = this.parser.$refs.paths();
2206
+ const refPaths = this.refParser.$refs.paths();
2088
2207
  // refPaths [0] is the current spec file path
2089
2208
  if (refPaths.length > 1) {
2090
2209
  errors.push({
@@ -2219,7 +2338,7 @@ class SpecParser {
2219
2338
  throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
2220
2339
  }
2221
2340
  const clonedUnResolveSpec = JSON.parse(JSON.stringify(newUnResolvedSpec));
2222
- const newSpec = (yield this.parser.dereference(clonedUnResolveSpec));
2341
+ const newSpec = yield this.deReferenceSpec(clonedUnResolveSpec);
2223
2342
  return [newUnResolvedSpec, newSpec];
2224
2343
  }
2225
2344
  catch (err) {
@@ -2230,6 +2349,12 @@ class SpecParser {
2230
2349
  }
2231
2350
  });
2232
2351
  }
2352
+ deReferenceSpec(spec) {
2353
+ return __awaiter(this, void 0, void 0, function* () {
2354
+ const result = yield this.refParser.dereference(spec);
2355
+ return result;
2356
+ });
2357
+ }
2233
2358
  /**
2234
2359
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
2235
2360
  * @param manifestPath A file path of the Teams app manifest file to update.
@@ -2247,7 +2372,31 @@ class SpecParser {
2247
2372
  const newSpecs = yield this.getFilteredSpecs(filter, signal);
2248
2373
  const newUnResolvedSpec = newSpecs[0];
2249
2374
  const newSpec = newSpecs[1];
2250
- const authInfo = Utils.getAuthInfo(newSpec);
2375
+ const paths = newUnResolvedSpec.paths;
2376
+ for (const pathUrl in paths) {
2377
+ const operations = paths[pathUrl];
2378
+ for (const method in operations) {
2379
+ const operationItem = operations[method];
2380
+ const operationId = operationItem.operationId;
2381
+ const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
2382
+ if (containsSpecialCharacters) {
2383
+ operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
2384
+ result.warnings.push({
2385
+ type: exports.WarningType.OperationIdContainsSpecialCharacters,
2386
+ content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
2387
+ data: operationId,
2388
+ });
2389
+ }
2390
+ const authArray = Utils.getAuthArray(operationItem.security, newSpec);
2391
+ if (Utils.isNotSupportedAuth(authArray)) {
2392
+ result.warnings.push({
2393
+ type: exports.WarningType.UnsupportedAuthType,
2394
+ content: Utils.format(ConstantString.AuthTypeIsNotSupported, operationId),
2395
+ data: operationId,
2396
+ });
2397
+ }
2398
+ }
2399
+ }
2251
2400
  yield this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
2252
2401
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
2253
2402
  throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
@@ -2258,7 +2407,8 @@ class SpecParser {
2258
2407
  specPath: this.pathOrSpec,
2259
2408
  }
2260
2409
  : undefined;
2261
- const [updatedManifest, apiPlugin, warnings] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authInfo, existingPluginManifestInfo);
2410
+ const authMap = Utils.getAuthMap(newSpec);
2411
+ const [updatedManifest, apiPlugin, warnings] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authMap, existingPluginManifestInfo);
2262
2412
  result.warnings.push(...warnings);
2263
2413
  yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 4 });
2264
2414
  yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });
@@ -2301,13 +2451,14 @@ class SpecParser {
2301
2451
  if (this.options.allowMethods.includes(method)) {
2302
2452
  const operation = newSpec.paths[url][method];
2303
2453
  try {
2304
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
2454
+ const [card, jsonPath, jsonData, warnings] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
2455
+ result.warnings.push(...warnings);
2305
2456
  const safeAdaptiveCardName = operation.operationId.replace(/[^a-zA-Z0-9]/g, "_");
2306
2457
  const fileName = path__default['default'].join(adaptiveCardFolder, `${safeAdaptiveCardName}.json`);
2307
2458
  const wrappedCard = wrapAdaptiveCard(card, jsonPath);
2308
2459
  yield fs__default['default'].outputJSON(fileName, wrappedCard, { spaces: 2 });
2309
2460
  const dataFileName = path__default['default'].join(adaptiveCardFolder, `${safeAdaptiveCardName}.data.json`);
2310
- yield fs__default['default'].outputJSON(dataFileName, {}, { spaces: 2 });
2461
+ yield fs__default['default'].outputJSON(dataFileName, jsonData, { spaces: 2 });
2311
2462
  }
2312
2463
  catch (err) {
2313
2464
  result.allSuccess = false;
@@ -2349,7 +2500,7 @@ class SpecParser {
2349
2500
  this.isSwaggerFile = true;
2350
2501
  }
2351
2502
  const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
2352
- this.spec = (yield this.parser.dereference(clonedUnResolveSpec));
2503
+ this.spec = yield this.deReferenceSpec(clonedUnResolveSpec);
2353
2504
  }
2354
2505
  });
2355
2506
  }