@microsoft/m365-spec-parser 0.0.2-alpha.2 → 0.1.1-alpha.0de595af8.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.
@@ -61,7 +61,8 @@ exports.ErrorType = void 0;
61
61
  ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
62
62
  ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
63
63
  ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
64
- ErrorType["MultipleAPIKeyNotSupported"] = "multiple-api-key-not-supported";
64
+ ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
65
+ ErrorType["SpecVersionNotSupported"] = "spec-version-not-supported";
65
66
  ErrorType["ListFailed"] = "list-failed";
66
67
  ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
67
68
  ErrorType["FilterSpecFailed"] = "filter-spec-failed";
@@ -69,6 +70,22 @@ exports.ErrorType = void 0;
69
70
  ErrorType["GenerateAdaptiveCardFailed"] = "generate-adaptive-card-failed";
70
71
  ErrorType["GenerateFailed"] = "generate-failed";
71
72
  ErrorType["ValidateFailed"] = "validate-failed";
73
+ ErrorType["GetSpecFailed"] = "get-spec-failed";
74
+ ErrorType["AuthTypeIsNotSupported"] = "auth-type-is-not-supported";
75
+ ErrorType["MissingOperationId"] = "missing-operation-id";
76
+ ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
77
+ ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
78
+ ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
79
+ ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
80
+ ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
81
+ ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
82
+ ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
83
+ ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
84
+ ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
85
+ ErrorType["NoParameter"] = "no-parameter";
86
+ ErrorType["NoAPIInfo"] = "no-api-info";
87
+ ErrorType["MethodNotAllowed"] = "method-not-allowed";
88
+ ErrorType["UrlPathNotExist"] = "url-path-not-exist";
72
89
  ErrorType["Cancelled"] = "cancelled";
73
90
  ErrorType["Unknown"] = "unknown";
74
91
  })(exports.ErrorType || (exports.ErrorType = {}));
@@ -91,7 +108,13 @@ exports.ValidationStatus = void 0;
91
108
  ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
92
109
  ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
93
110
  ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
94
- })(exports.ValidationStatus || (exports.ValidationStatus = {}));
111
+ })(exports.ValidationStatus || (exports.ValidationStatus = {}));
112
+ exports.ProjectType = void 0;
113
+ (function (ProjectType) {
114
+ ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
115
+ ProjectType[ProjectType["SME"] = 1] = "SME";
116
+ ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
117
+ })(exports.ProjectType || (exports.ProjectType = {}));
95
118
 
96
119
  // Copyright (c) Microsoft Corporation.
97
120
  class ConstantString {
@@ -110,7 +133,9 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
110
133
  ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
111
134
  ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
112
135
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
113
- ConstantString.MultipleAPIKeyNotSupported = "Multiple API keys are not supported. Please make sure that all selected APIs use the same API key.";
136
+ ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
137
+ ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
138
+ ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
114
139
  ConstantString.WrappedCardVersion = "devPreview";
115
140
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
116
141
  ConstantString.WrappedCardResponseLayout = "list";
@@ -122,6 +147,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
122
147
  ConstantString.TextBlockType = "TextBlock";
123
148
  ConstantString.ContainerType = "Container";
124
149
  ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
150
+ ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
125
151
  ConstantString.ResponseCodeFor20X = [
126
152
  "200",
127
153
  "201",
@@ -181,7 +207,8 @@ ConstantString.FullDescriptionMaxLens = 4000;
181
207
  ConstantString.CommandDescriptionMaxLens = 128;
182
208
  ConstantString.ParameterDescriptionMaxLens = 128;
183
209
  ConstantString.CommandTitleMaxLens = 32;
184
- ConstantString.ParameterTitleMaxLens = 32;
210
+ ConstantString.ParameterTitleMaxLens = 32;
211
+ ConstantString.SMERequiredParamsMaxNum = 5;
185
212
 
186
213
  // Copyright (c) Microsoft Corporation.
187
214
  class SpecParserError extends Error {
@@ -193,201 +220,30 @@ class SpecParserError extends Error {
193
220
 
194
221
  // Copyright (c) Microsoft Corporation.
195
222
  class Utils {
196
- static checkParameters(paramObject) {
197
- const paramResult = {
198
- requiredNum: 0,
199
- optionalNum: 0,
200
- isValid: true,
201
- };
202
- if (!paramObject) {
203
- return paramResult;
204
- }
205
- for (let i = 0; i < paramObject.length; i++) {
206
- const param = paramObject[i];
207
- const schema = param.schema;
208
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
209
- if (param.in === "header" || param.in === "cookie") {
210
- if (isRequiredWithoutDefault) {
211
- paramResult.isValid = false;
212
- }
213
- continue;
214
- }
215
- if (schema.type !== "boolean" &&
216
- schema.type !== "string" &&
217
- schema.type !== "number" &&
218
- schema.type !== "integer") {
219
- if (isRequiredWithoutDefault) {
220
- paramResult.isValid = false;
221
- }
222
- continue;
223
- }
224
- if (param.in === "query" || param.in === "path") {
225
- if (isRequiredWithoutDefault) {
226
- paramResult.requiredNum = paramResult.requiredNum + 1;
227
- }
228
- else {
229
- paramResult.optionalNum = paramResult.optionalNum + 1;
230
- }
231
- }
232
- }
233
- return paramResult;
234
- }
235
- static checkPostBody(schema, isRequired = false) {
236
- var _a;
237
- const paramResult = {
238
- requiredNum: 0,
239
- optionalNum: 0,
240
- isValid: true,
241
- };
242
- if (Object.keys(schema).length === 0) {
243
- return paramResult;
244
- }
245
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
246
- if (schema.type === "string" ||
247
- schema.type === "integer" ||
248
- schema.type === "boolean" ||
249
- schema.type === "number") {
250
- if (isRequiredWithoutDefault) {
251
- paramResult.requiredNum = paramResult.requiredNum + 1;
252
- }
253
- else {
254
- paramResult.optionalNum = paramResult.optionalNum + 1;
255
- }
256
- }
257
- else if (schema.type === "object") {
258
- const { properties } = schema;
259
- for (const property in properties) {
260
- let isRequired = false;
261
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
262
- isRequired = true;
263
- }
264
- const result = Utils.checkPostBody(properties[property], isRequired);
265
- paramResult.requiredNum += result.requiredNum;
266
- paramResult.optionalNum += result.optionalNum;
267
- paramResult.isValid = paramResult.isValid && result.isValid;
268
- }
269
- }
270
- else {
271
- if (isRequiredWithoutDefault) {
272
- paramResult.isValid = false;
273
- }
274
- }
275
- return paramResult;
276
- }
277
- /**
278
- * Checks if the given API is supported.
279
- * @param {string} method - The HTTP method of the API.
280
- * @param {string} path - The path of the API.
281
- * @param {OpenAPIV3.Document} spec - The OpenAPI specification document.
282
- * @returns {boolean} - Returns true if the API is supported, false otherwise.
283
- * @description The following APIs are supported:
284
- * 1. only support Get/Post operation without auth property
285
- * 2. parameter inside query or path only support string, number, boolean and integer
286
- * 3. parameter inside post body only support string, number, boolean, integer and object
287
- * 4. request body + required parameters <= 1
288
- * 5. response body should be “application/json” and not empty, and response code should be 20X
289
- * 6. only support request body with “application/json” content type
290
- */
291
- static isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
292
- const pathObj = spec.paths[path];
293
- method = method.toLocaleLowerCase();
294
- if (pathObj) {
295
- if ((method === ConstantString.PostMethod || method === ConstantString.GetMethod) &&
296
- pathObj[method]) {
297
- const securities = pathObj[method].security;
298
- const authArray = Utils.getAuthArray(securities, spec);
299
- if (!Utils.isSupportedAuth(authArray, allowAPIKeyAuth, allowOauth2)) {
300
- return false;
301
- }
302
- const operationObject = pathObj[method];
303
- if (!allowMissingId && !operationObject.operationId) {
304
- return false;
305
- }
306
- const paramObject = operationObject.parameters;
307
- const requestBody = operationObject.requestBody;
308
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
309
- const mediaTypesCount = Object.keys((requestBody === null || requestBody === void 0 ? void 0 : requestBody.content) || {}).length;
310
- if (mediaTypesCount > 1) {
311
- return false;
312
- }
313
- const responseJson = Utils.getResponseJson(operationObject);
314
- if (Object.keys(responseJson).length === 0) {
315
- return false;
316
- }
317
- let requestBodyParamResult = {
318
- requiredNum: 0,
319
- optionalNum: 0,
320
- isValid: true,
321
- };
322
- if (requestJsonBody) {
323
- const requestBodySchema = requestJsonBody.schema;
324
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required);
325
- }
326
- if (!requestBodyParamResult.isValid) {
327
- return false;
328
- }
329
- const paramResult = Utils.checkParameters(paramObject);
330
- if (!paramResult.isValid) {
331
- return false;
332
- }
333
- if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
334
- if (allowMultipleParameters &&
335
- requestBodyParamResult.requiredNum + paramResult.requiredNum <= 5) {
336
- return true;
337
- }
338
- return false;
339
- }
340
- else if (requestBodyParamResult.requiredNum +
341
- requestBodyParamResult.optionalNum +
342
- paramResult.requiredNum +
343
- paramResult.optionalNum ===
344
- 0) {
345
- return false;
346
- }
347
- else {
223
+ static hasNestedObjectInSchema(schema) {
224
+ if (schema.type === "object") {
225
+ for (const property in schema.properties) {
226
+ const nestedSchema = schema.properties[property];
227
+ if (nestedSchema.type === "object") {
348
228
  return true;
349
229
  }
350
230
  }
351
231
  }
352
232
  return false;
353
233
  }
354
- static isSupportedAuth(authSchemaArray, allowAPIKeyAuth, allowOauth2) {
355
- if (authSchemaArray.length === 0) {
356
- return true;
357
- }
358
- if (allowAPIKeyAuth || allowOauth2) {
359
- // Currently we don't support multiple auth in one operation
360
- if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
361
- return false;
362
- }
363
- for (const auths of authSchemaArray) {
364
- if (auths.length === 1) {
365
- if (!allowOauth2 && allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authSchema)) {
366
- return true;
367
- }
368
- else if (!allowAPIKeyAuth &&
369
- allowOauth2 &&
370
- Utils.isBearerTokenAuth(auths[0].authSchema)) {
371
- return true;
372
- }
373
- else if (allowAPIKeyAuth &&
374
- allowOauth2 &&
375
- (Utils.isAPIKeyAuth(auths[0].authSchema) ||
376
- Utils.isBearerTokenAuth(auths[0].authSchema))) {
377
- return true;
378
- }
379
- }
380
- }
381
- }
382
- return false;
234
+ static containMultipleMediaTypes(bodyObject) {
235
+ return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
236
+ }
237
+ static isBearerTokenAuth(authScheme) {
238
+ return authScheme.type === "http" && authScheme.scheme === "bearer";
383
239
  }
384
- static isAPIKeyAuth(authSchema) {
385
- return authSchema.type === "apiKey";
240
+ static isAPIKeyAuth(authScheme) {
241
+ return authScheme.type === "apiKey";
386
242
  }
387
- static isBearerTokenAuth(authSchema) {
388
- return (authSchema.type === "oauth2" ||
389
- authSchema.type === "openIdConnect" ||
390
- (authSchema.type === "http" && authSchema.scheme === "bearer"));
243
+ static isOAuthWithAuthCodeFlow(authScheme) {
244
+ return !!(authScheme.type === "oauth2" &&
245
+ authScheme.flows &&
246
+ authScheme.flows.authorizationCode);
391
247
  }
392
248
  static getAuthArray(securities, spec) {
393
249
  var _a;
@@ -400,7 +256,7 @@ class Utils {
400
256
  for (const name in security) {
401
257
  const auth = securitySchemas[name];
402
258
  authArray.push({
403
- authSchema: auth,
259
+ authScheme: auth,
404
260
  name: name,
405
261
  });
406
262
  }
@@ -418,18 +274,22 @@ class Utils {
418
274
  static getResponseJson(operationObject) {
419
275
  var _a, _b;
420
276
  let json = {};
277
+ let multipleMediaType = false;
421
278
  for (const code of ConstantString.ResponseCodeFor20X) {
422
279
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
423
- const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
424
- if (mediaTypesCount > 1) {
425
- return {};
426
- }
427
280
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
281
+ multipleMediaType = false;
428
282
  json = responseObject.content["application/json"];
429
- break;
283
+ if (Utils.containMultipleMediaTypes(responseObject)) {
284
+ multipleMediaType = true;
285
+ json = {};
286
+ }
287
+ else {
288
+ break;
289
+ }
430
290
  }
431
291
  }
432
- return json;
292
+ return { json, multipleMediaType };
433
293
  }
434
294
  static convertPathToCamelCase(path) {
435
295
  const pathSegments = path.split(/[./{]/);
@@ -449,10 +309,10 @@ class Utils {
449
309
  return undefined;
450
310
  }
451
311
  }
452
- static resolveServerUrl(url) {
312
+ static resolveEnv(str) {
453
313
  const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
454
- let matches = placeHolderReg.exec(url);
455
- let newUrl = url;
314
+ let matches = placeHolderReg.exec(str);
315
+ let newStr = str;
456
316
  while (matches != null) {
457
317
  const envVar = matches[1];
458
318
  const envVal = process.env[envVar];
@@ -460,17 +320,17 @@ class Utils {
460
320
  throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
461
321
  }
462
322
  else {
463
- newUrl = newUrl.replace(matches[0], envVal);
323
+ newStr = newStr.replace(matches[0], envVal);
464
324
  }
465
- matches = placeHolderReg.exec(url);
325
+ matches = placeHolderReg.exec(str);
466
326
  }
467
- return newUrl;
327
+ return newStr;
468
328
  }
469
329
  static checkServerUrl(servers) {
470
330
  const errors = [];
471
331
  let serverUrl;
472
332
  try {
473
- serverUrl = Utils.resolveServerUrl(servers[0].url);
333
+ serverUrl = Utils.resolveEnv(servers[0].url);
474
334
  }
475
335
  catch (err) {
476
336
  errors.push({
@@ -500,7 +360,8 @@ class Utils {
500
360
  }
501
361
  return errors;
502
362
  }
503
- static validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
363
+ static validateServer(spec, options) {
364
+ var _a;
504
365
  const errors = [];
505
366
  let hasTopLevelServers = false;
506
367
  let hasPathLevelServers = false;
@@ -521,7 +382,7 @@ class Utils {
521
382
  }
522
383
  for (const method in methods) {
523
384
  const operationObject = methods[method];
524
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
385
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
525
386
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
526
387
  hasOperationLevelServers = true;
527
388
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -564,6 +425,7 @@ class Utils {
564
425
  Utils.updateParameterWithInputType(schema, parameter);
565
426
  }
566
427
  if (isRequired && schema.default === undefined) {
428
+ parameter.isRequired = true;
567
429
  requiredParams.push(parameter);
568
430
  }
569
431
  else {
@@ -608,7 +470,7 @@ class Utils {
608
470
  param.value = schema.default;
609
471
  }
610
472
  }
611
- static parseApiInfo(operationItem, allowMultipleParameters) {
473
+ static parseApiInfo(operationItem, options) {
612
474
  var _a, _b;
613
475
  const requiredParams = [];
614
476
  const optionalParams = [];
@@ -622,11 +484,12 @@ class Utils {
622
484
  description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
623
485
  };
624
486
  const schema = param.schema;
625
- if (allowMultipleParameters && schema) {
487
+ if (options.allowMultipleParameters && schema) {
626
488
  Utils.updateParameterWithInputType(schema, parameter);
627
489
  }
628
490
  if (param.in !== "header" && param.in !== "cookie") {
629
491
  if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
492
+ parameter.isRequired = true;
630
493
  requiredParams.push(parameter);
631
494
  }
632
495
  else {
@@ -640,19 +503,13 @@ class Utils {
640
503
  const requestJson = requestBody.content["application/json"];
641
504
  if (Object.keys(requestJson).length !== 0) {
642
505
  const schema = requestJson.schema;
643
- const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
506
+ const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
644
507
  requiredParams.push(...requiredP);
645
508
  optionalParams.push(...optionalP);
646
509
  }
647
510
  }
648
511
  const operationId = operationItem.operationId;
649
- const parameters = [];
650
- if (requiredParams.length !== 0) {
651
- parameters.push(...requiredParams);
652
- }
653
- else {
654
- parameters.push(optionalParams[0]);
655
- }
512
+ const parameters = [...requiredParams, ...optionalParams];
656
513
  const command = {
657
514
  context: ["compose"],
658
515
  type: "query",
@@ -661,32 +518,9 @@ class Utils {
661
518
  parameters: parameters,
662
519
  description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
663
520
  };
664
- let warning = undefined;
665
- if (requiredParams.length === 0 && optionalParams.length > 1) {
666
- warning = {
667
- type: exports.WarningType.OperationOnlyContainsOptionalParam,
668
- content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, operationId),
669
- data: operationId,
670
- };
671
- }
672
- return [command, warning];
673
- }
674
- static listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
675
- const paths = spec.paths;
676
- const result = {};
677
- for (const path in paths) {
678
- const methods = paths[path];
679
- for (const method in methods) {
680
- // For developer preview, only support GET operation with only 1 parameter without auth
681
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
682
- const operationObject = methods[method];
683
- result[`${method.toUpperCase()} ${path}`] = operationObject;
684
- }
685
- }
686
- }
687
- return result;
521
+ return command;
688
522
  }
689
- static validateSpec(spec, parser, isSwaggerFile, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
523
+ static validateSpec(spec, parser, apiMap, isSwaggerFile, options) {
690
524
  const errors = [];
691
525
  const warnings = [];
692
526
  if (isSwaggerFile) {
@@ -695,8 +529,7 @@ class Utils {
695
529
  content: ConstantString.ConvertSwaggerToOpenAPI,
696
530
  });
697
531
  }
698
- // Server validation
699
- const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
532
+ const serverErrors = Utils.validateServer(spec, options);
700
533
  errors.push(...serverErrors);
701
534
  // Remote reference not supported
702
535
  const refPaths = parser.$refs.paths();
@@ -709,8 +542,8 @@ class Utils {
709
542
  });
710
543
  }
711
544
  // No supported API
712
- const apiMap = Utils.listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
713
- if (Object.keys(apiMap).length === 0) {
545
+ const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
546
+ if (validAPIs.length === 0) {
714
547
  errors.push({
715
548
  type: exports.ErrorType.NoSupportedApi,
716
549
  content: ConstantString.NoSupportedApi,
@@ -719,8 +552,8 @@ class Utils {
719
552
  // OperationId missing
720
553
  const apisMissingOperationId = [];
721
554
  for (const key in apiMap) {
722
- const pathObjectItem = apiMap[key];
723
- if (!pathObjectItem.operationId) {
555
+ const { operation } = apiMap[key];
556
+ if (!operation.operationId) {
724
557
  apisMissingOperationId.push(key);
725
558
  }
726
559
  }
@@ -761,30 +594,434 @@ class Utils {
761
594
  }
762
595
  return safeRegistrationIdEnvName;
763
596
  }
597
+ static getAllAPICount(spec) {
598
+ let count = 0;
599
+ const paths = spec.paths;
600
+ for (const path in paths) {
601
+ const methods = paths[path];
602
+ for (const method in methods) {
603
+ if (ConstantString.AllOperationMethods.includes(method)) {
604
+ count++;
605
+ }
606
+ }
607
+ }
608
+ return count;
609
+ }
610
+ }
611
+
612
+ // Copyright (c) Microsoft Corporation.
613
+ class Validator {
614
+ validateMethodAndPath(method, path) {
615
+ const result = { isValid: true, reason: [] };
616
+ if (this.options.allowMethods && !this.options.allowMethods.includes(method)) {
617
+ result.isValid = false;
618
+ result.reason.push(exports.ErrorType.MethodNotAllowed);
619
+ return result;
620
+ }
621
+ const pathObj = this.spec.paths[path];
622
+ if (!pathObj || !pathObj[method]) {
623
+ result.isValid = false;
624
+ result.reason.push(exports.ErrorType.UrlPathNotExist);
625
+ return result;
626
+ }
627
+ return result;
628
+ }
629
+ validateResponse(method, path) {
630
+ const result = { isValid: true, reason: [] };
631
+ const operationObject = this.spec.paths[path][method];
632
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
633
+ // only support response body only contains “application/json” content type
634
+ if (multipleMediaType) {
635
+ result.reason.push(exports.ErrorType.ResponseContainMultipleMediaTypes);
636
+ }
637
+ else if (Object.keys(json).length === 0) {
638
+ // response body should not be empty
639
+ result.reason.push(exports.ErrorType.ResponseJsonIsEmpty);
640
+ }
641
+ return result;
642
+ }
643
+ validateServer(method, path) {
644
+ const pathObj = this.spec.paths[path];
645
+ const result = { isValid: true, reason: [] };
646
+ const operationObject = pathObj[method];
647
+ const rootServer = this.spec.servers && this.spec.servers[0];
648
+ const methodServer = this.spec.paths[path].servers && this.spec.paths[path].servers[0];
649
+ const operationServer = operationObject.servers && operationObject.servers[0];
650
+ const serverUrl = operationServer || methodServer || rootServer;
651
+ if (!serverUrl) {
652
+ // should contain server URL
653
+ result.reason.push(exports.ErrorType.NoServerInformation);
654
+ }
655
+ else {
656
+ // server url should be absolute url with https protocol
657
+ const serverValidateResult = Utils.checkServerUrl([serverUrl]);
658
+ result.reason.push(...serverValidateResult.map((item) => item.type));
659
+ }
660
+ return result;
661
+ }
662
+ validateAuth(method, path) {
663
+ const pathObj = this.spec.paths[path];
664
+ const operationObject = pathObj[method];
665
+ const securities = operationObject.security;
666
+ const authSchemeArray = Utils.getAuthArray(securities, this.spec);
667
+ if (authSchemeArray.length === 0) {
668
+ return { isValid: true, reason: [] };
669
+ }
670
+ if (this.options.allowAPIKeyAuth ||
671
+ this.options.allowOauth2 ||
672
+ this.options.allowBearerTokenAuth) {
673
+ // Currently we don't support multiple auth in one operation
674
+ if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
675
+ return {
676
+ isValid: false,
677
+ reason: [exports.ErrorType.MultipleAuthNotSupported],
678
+ };
679
+ }
680
+ for (const auths of authSchemeArray) {
681
+ if (auths.length === 1) {
682
+ if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
683
+ (this.options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
684
+ (this.options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
685
+ return { isValid: true, reason: [] };
686
+ }
687
+ }
688
+ }
689
+ }
690
+ return { isValid: false, reason: [exports.ErrorType.AuthTypeIsNotSupported] };
691
+ }
692
+ checkPostBodySchema(schema, isRequired = false) {
693
+ var _a;
694
+ const paramResult = {
695
+ requiredNum: 0,
696
+ optionalNum: 0,
697
+ isValid: true,
698
+ reason: [],
699
+ };
700
+ if (Object.keys(schema).length === 0) {
701
+ return paramResult;
702
+ }
703
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
704
+ const isCopilot = this.projectType === exports.ProjectType.Copilot;
705
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
706
+ paramResult.isValid = false;
707
+ paramResult.reason = [exports.ErrorType.RequestBodyContainsNestedObject];
708
+ return paramResult;
709
+ }
710
+ if (schema.type === "string" ||
711
+ schema.type === "integer" ||
712
+ schema.type === "boolean" ||
713
+ schema.type === "number") {
714
+ if (isRequiredWithoutDefault) {
715
+ paramResult.requiredNum = paramResult.requiredNum + 1;
716
+ }
717
+ else {
718
+ paramResult.optionalNum = paramResult.optionalNum + 1;
719
+ }
720
+ }
721
+ else if (schema.type === "object") {
722
+ const { properties } = schema;
723
+ for (const property in properties) {
724
+ let isRequired = false;
725
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
726
+ isRequired = true;
727
+ }
728
+ const result = this.checkPostBodySchema(properties[property], isRequired);
729
+ paramResult.requiredNum += result.requiredNum;
730
+ paramResult.optionalNum += result.optionalNum;
731
+ paramResult.isValid = paramResult.isValid && result.isValid;
732
+ paramResult.reason.push(...result.reason);
733
+ }
734
+ }
735
+ else {
736
+ if (isRequiredWithoutDefault && !isCopilot) {
737
+ paramResult.isValid = false;
738
+ paramResult.reason.push(exports.ErrorType.PostBodyContainsRequiredUnsupportedSchema);
739
+ }
740
+ }
741
+ return paramResult;
742
+ }
743
+ checkParamSchema(paramObject) {
744
+ const paramResult = {
745
+ requiredNum: 0,
746
+ optionalNum: 0,
747
+ isValid: true,
748
+ reason: [],
749
+ };
750
+ if (!paramObject) {
751
+ return paramResult;
752
+ }
753
+ const isCopilot = this.projectType === exports.ProjectType.Copilot;
754
+ for (let i = 0; i < paramObject.length; i++) {
755
+ const param = paramObject[i];
756
+ const schema = param.schema;
757
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
758
+ paramResult.isValid = false;
759
+ paramResult.reason.push(exports.ErrorType.ParamsContainsNestedObject);
760
+ continue;
761
+ }
762
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
763
+ if (isCopilot) {
764
+ if (isRequiredWithoutDefault) {
765
+ paramResult.requiredNum = paramResult.requiredNum + 1;
766
+ }
767
+ else {
768
+ paramResult.optionalNum = paramResult.optionalNum + 1;
769
+ }
770
+ continue;
771
+ }
772
+ if (param.in === "header" || param.in === "cookie") {
773
+ if (isRequiredWithoutDefault) {
774
+ paramResult.isValid = false;
775
+ paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
776
+ }
777
+ continue;
778
+ }
779
+ if (schema.type !== "boolean" &&
780
+ schema.type !== "string" &&
781
+ schema.type !== "number" &&
782
+ schema.type !== "integer") {
783
+ if (isRequiredWithoutDefault) {
784
+ paramResult.isValid = false;
785
+ paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
786
+ }
787
+ continue;
788
+ }
789
+ if (param.in === "query" || param.in === "path") {
790
+ if (isRequiredWithoutDefault) {
791
+ paramResult.requiredNum = paramResult.requiredNum + 1;
792
+ }
793
+ else {
794
+ paramResult.optionalNum = paramResult.optionalNum + 1;
795
+ }
796
+ }
797
+ }
798
+ return paramResult;
799
+ }
800
+ hasNestedObjectInSchema(schema) {
801
+ if (schema.type === "object") {
802
+ for (const property in schema.properties) {
803
+ const nestedSchema = schema.properties[property];
804
+ if (nestedSchema.type === "object") {
805
+ return true;
806
+ }
807
+ }
808
+ }
809
+ return false;
810
+ }
811
+ }
812
+
813
+ // Copyright (c) Microsoft Corporation.
814
+ class CopilotValidator extends Validator {
815
+ constructor(spec, options) {
816
+ super();
817
+ this.projectType = exports.ProjectType.Copilot;
818
+ this.options = options;
819
+ this.spec = spec;
820
+ }
821
+ validateAPI(method, path) {
822
+ const result = { isValid: true, reason: [] };
823
+ method = method.toLocaleLowerCase();
824
+ // validate method and path
825
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
826
+ if (!methodAndPathResult.isValid) {
827
+ return methodAndPathResult;
828
+ }
829
+ const operationObject = this.spec.paths[path][method];
830
+ // validate auth
831
+ const authCheckResult = this.validateAuth(method, path);
832
+ result.reason.push(...authCheckResult.reason);
833
+ // validate operationId
834
+ if (!this.options.allowMissingId && !operationObject.operationId) {
835
+ result.reason.push(exports.ErrorType.MissingOperationId);
836
+ }
837
+ // validate server
838
+ const validateServerResult = this.validateServer(method, path);
839
+ result.reason.push(...validateServerResult.reason);
840
+ // validate response
841
+ const validateResponseResult = this.validateResponse(method, path);
842
+ result.reason.push(...validateResponseResult.reason);
843
+ // validate requestBody
844
+ const requestBody = operationObject.requestBody;
845
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
846
+ if (Utils.containMultipleMediaTypes(requestBody)) {
847
+ result.reason.push(exports.ErrorType.PostBodyContainMultipleMediaTypes);
848
+ }
849
+ if (requestJsonBody) {
850
+ const requestBodySchema = requestJsonBody.schema;
851
+ if (requestBodySchema.type !== "object") {
852
+ result.reason.push(exports.ErrorType.PostBodySchemaIsNotJson);
853
+ }
854
+ const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
855
+ result.reason.push(...requestBodyParamResult.reason);
856
+ }
857
+ // validate parameters
858
+ const paramObject = operationObject.parameters;
859
+ const paramResult = this.checkParamSchema(paramObject);
860
+ result.reason.push(...paramResult.reason);
861
+ if (result.reason.length > 0) {
862
+ result.isValid = false;
863
+ }
864
+ return result;
865
+ }
866
+ }
867
+
868
+ // Copyright (c) Microsoft Corporation.
869
+ class SMEValidator extends Validator {
870
+ constructor(spec, options) {
871
+ super();
872
+ this.projectType = exports.ProjectType.SME;
873
+ this.options = options;
874
+ this.spec = spec;
875
+ }
876
+ validateAPI(method, path) {
877
+ const result = { isValid: true, reason: [] };
878
+ method = method.toLocaleLowerCase();
879
+ // validate method and path
880
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
881
+ if (!methodAndPathResult.isValid) {
882
+ return methodAndPathResult;
883
+ }
884
+ const operationObject = this.spec.paths[path][method];
885
+ // validate auth
886
+ const authCheckResult = this.validateAuth(method, path);
887
+ result.reason.push(...authCheckResult.reason);
888
+ // validate operationId
889
+ if (!this.options.allowMissingId && !operationObject.operationId) {
890
+ result.reason.push(exports.ErrorType.MissingOperationId);
891
+ }
892
+ // validate server
893
+ const validateServerResult = this.validateServer(method, path);
894
+ result.reason.push(...validateServerResult.reason);
895
+ // validate response
896
+ const validateResponseResult = this.validateResponse(method, path);
897
+ result.reason.push(...validateResponseResult.reason);
898
+ let postBodyResult = {
899
+ requiredNum: 0,
900
+ optionalNum: 0,
901
+ isValid: true,
902
+ reason: [],
903
+ };
904
+ // validate requestBody
905
+ const requestBody = operationObject.requestBody;
906
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
907
+ if (Utils.containMultipleMediaTypes(requestBody)) {
908
+ result.reason.push(exports.ErrorType.PostBodyContainMultipleMediaTypes);
909
+ }
910
+ if (requestJsonBody) {
911
+ const requestBodySchema = requestJsonBody.schema;
912
+ postBodyResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
913
+ result.reason.push(...postBodyResult.reason);
914
+ }
915
+ // validate parameters
916
+ const paramObject = operationObject.parameters;
917
+ const paramResult = this.checkParamSchema(paramObject);
918
+ result.reason.push(...paramResult.reason);
919
+ // validate total parameters count
920
+ if (paramResult.isValid && postBodyResult.isValid) {
921
+ const paramCountResult = this.validateParamCount(postBodyResult, paramResult);
922
+ result.reason.push(...paramCountResult.reason);
923
+ }
924
+ if (result.reason.length > 0) {
925
+ result.isValid = false;
926
+ }
927
+ return result;
928
+ }
929
+ validateParamCount(postBodyResult, paramResult) {
930
+ const result = { isValid: true, reason: [] };
931
+ const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
932
+ const totalParams = totalRequiredParams + postBodyResult.optionalNum + paramResult.optionalNum;
933
+ if (totalRequiredParams > 1) {
934
+ if (!this.options.allowMultipleParameters ||
935
+ totalRequiredParams > SMEValidator.SMERequiredParamsMaxNum) {
936
+ result.reason.push(exports.ErrorType.ExceededRequiredParamsLimit);
937
+ }
938
+ }
939
+ else if (totalParams === 0) {
940
+ result.reason.push(exports.ErrorType.NoParameter);
941
+ }
942
+ return result;
943
+ }
944
+ }
945
+ SMEValidator.SMERequiredParamsMaxNum = 5;
946
+
947
+ // Copyright (c) Microsoft Corporation.
948
+ class TeamsAIValidator extends Validator {
949
+ constructor(spec, options) {
950
+ super();
951
+ this.projectType = exports.ProjectType.TeamsAi;
952
+ this.options = options;
953
+ this.spec = spec;
954
+ }
955
+ validateAPI(method, path) {
956
+ const result = { isValid: true, reason: [] };
957
+ method = method.toLocaleLowerCase();
958
+ // validate method and path
959
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
960
+ if (!methodAndPathResult.isValid) {
961
+ return methodAndPathResult;
962
+ }
963
+ const operationObject = this.spec.paths[path][method];
964
+ // validate operationId
965
+ if (!this.options.allowMissingId && !operationObject.operationId) {
966
+ result.reason.push(exports.ErrorType.MissingOperationId);
967
+ }
968
+ // validate server
969
+ const validateServerResult = this.validateServer(method, path);
970
+ result.reason.push(...validateServerResult.reason);
971
+ if (result.reason.length > 0) {
972
+ result.isValid = false;
973
+ }
974
+ return result;
975
+ }
976
+ }
977
+
978
+ class ValidatorFactory {
979
+ static create(spec, options) {
980
+ var _a;
981
+ const type = (_a = options.projectType) !== null && _a !== void 0 ? _a : exports.ProjectType.SME;
982
+ switch (type) {
983
+ case exports.ProjectType.SME:
984
+ return new SMEValidator(spec, options);
985
+ case exports.ProjectType.Copilot:
986
+ return new CopilotValidator(spec, options);
987
+ case exports.ProjectType.TeamsAi:
988
+ return new TeamsAIValidator(spec, options);
989
+ default:
990
+ throw new Error(`Invalid project type: ${type}`);
991
+ }
992
+ }
764
993
  }
765
994
 
766
995
  // Copyright (c) Microsoft Corporation.
767
996
  class SpecFilter {
768
- static specFilter(filter, unResolveSpec, resolvedSpec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
997
+ static specFilter(filter, unResolveSpec, resolvedSpec, options) {
998
+ var _a;
769
999
  try {
770
1000
  const newSpec = Object.assign({}, unResolveSpec);
771
1001
  const newPaths = {};
772
1002
  for (const filterItem of filter) {
773
1003
  const [method, path] = filterItem.split(" ");
774
1004
  const methodName = method.toLowerCase();
775
- if (!Utils.isSupportedApi(methodName, path, resolvedSpec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
776
- continue;
777
- }
778
- if (!newPaths[path]) {
779
- newPaths[path] = Object.assign({}, unResolveSpec.paths[path]);
780
- for (const m of ConstantString.AllOperationMethods) {
781
- delete newPaths[path][m];
1005
+ const pathObj = (_a = resolvedSpec.paths) === null || _a === void 0 ? void 0 : _a[path];
1006
+ if (ConstantString.AllOperationMethods.includes(methodName) &&
1007
+ pathObj &&
1008
+ pathObj[methodName]) {
1009
+ const validator = ValidatorFactory.create(resolvedSpec, options);
1010
+ const validateResult = validator.validateAPI(methodName, path);
1011
+ if (!validateResult.isValid) {
1012
+ continue;
1013
+ }
1014
+ if (!newPaths[path]) {
1015
+ newPaths[path] = Object.assign({}, unResolveSpec.paths[path]);
1016
+ for (const m of ConstantString.AllOperationMethods) {
1017
+ delete newPaths[path][m];
1018
+ }
1019
+ }
1020
+ newPaths[path][methodName] = unResolveSpec.paths[path][methodName];
1021
+ // Add the operationId if missing
1022
+ if (!newPaths[path][methodName].operationId) {
1023
+ newPaths[path][methodName].operationId = `${methodName}${Utils.convertPathToCamelCase(path)}`;
782
1024
  }
783
- }
784
- newPaths[path][methodName] = unResolveSpec.paths[path][methodName];
785
- // Add the operationId if missing
786
- if (!newPaths[path][methodName].operationId) {
787
- newPaths[path][methodName].operationId = `${methodName}${Utils.convertPathToCamelCase(path)}`;
788
1025
  }
789
1026
  }
790
1027
  newSpec.paths = newPaths;
@@ -798,47 +1035,171 @@ class SpecFilter {
798
1035
 
799
1036
  // Copyright (c) Microsoft Corporation.
800
1037
  class ManifestUpdater {
801
- static updateManifest(manifestPath, outputSpecPath, adaptiveCardFolder, spec, allowMultipleParameters, auth) {
1038
+ static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options) {
1039
+ return __awaiter(this, void 0, void 0, function* () {
1040
+ const manifest = yield fs__default['default'].readJSON(manifestPath);
1041
+ const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
1042
+ manifest.plugins = [
1043
+ {
1044
+ pluginFile: apiPluginRelativePath,
1045
+ },
1046
+ ];
1047
+ const appName = this.removeEnvs(manifest.name.short);
1048
+ ManifestUpdater.updateManifestDescription(manifest, spec);
1049
+ const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
1050
+ const apiPlugin = ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, appName, options);
1051
+ return [manifest, apiPlugin];
1052
+ });
1053
+ }
1054
+ static updateManifestDescription(manifest, spec) {
802
1055
  var _a, _b;
1056
+ manifest.description = {
1057
+ short: spec.info.title.slice(0, ConstantString.ShortDescriptionMaxLens),
1058
+ full: (_b = ((_a = spec.info.description) !== null && _a !== void 0 ? _a : manifest.description.full)) === null || _b === void 0 ? void 0 : _b.slice(0, ConstantString.FullDescriptionMaxLens),
1059
+ };
1060
+ }
1061
+ static mapOpenAPISchemaToFuncParam(schema, method, pathUrl) {
1062
+ let parameter;
1063
+ if (schema.type === "string" ||
1064
+ schema.type === "boolean" ||
1065
+ schema.type === "integer" ||
1066
+ schema.type === "number" ||
1067
+ schema.type === "array") {
1068
+ parameter = schema;
1069
+ }
1070
+ else {
1071
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), exports.ErrorType.UpdateManifestFailed);
1072
+ }
1073
+ return parameter;
1074
+ }
1075
+ static generatePluginManifestSchema(spec, specRelativePath, appName, options) {
1076
+ var _a, _b, _c;
1077
+ const functions = [];
1078
+ const functionNames = [];
1079
+ const paths = spec.paths;
1080
+ for (const pathUrl in paths) {
1081
+ const pathItem = paths[pathUrl];
1082
+ if (pathItem) {
1083
+ const operations = pathItem;
1084
+ for (const method in operations) {
1085
+ if (options.allowMethods.includes(method)) {
1086
+ const operationItem = operations[method];
1087
+ if (operationItem) {
1088
+ const operationId = operationItem.operationId;
1089
+ const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
1090
+ const paramObject = operationItem.parameters;
1091
+ const requestBody = operationItem.requestBody;
1092
+ const parameters = {
1093
+ type: "object",
1094
+ properties: {},
1095
+ required: [],
1096
+ };
1097
+ if (paramObject) {
1098
+ for (let i = 0; i < paramObject.length; i++) {
1099
+ const param = paramObject[i];
1100
+ const schema = param.schema;
1101
+ parameters.properties[param.name] = ManifestUpdater.mapOpenAPISchemaToFuncParam(schema, method, pathUrl);
1102
+ if (param.required) {
1103
+ parameters.required.push(param.name);
1104
+ }
1105
+ if (!parameters.properties[param.name].description) {
1106
+ parameters.properties[param.name].description = (_b = param.description) !== null && _b !== void 0 ? _b : "";
1107
+ }
1108
+ }
1109
+ }
1110
+ if (requestBody) {
1111
+ const requestJsonBody = requestBody.content["application/json"];
1112
+ const requestBodySchema = requestJsonBody.schema;
1113
+ if (requestBodySchema.type === "object") {
1114
+ if (requestBodySchema.required) {
1115
+ parameters.required.push(...requestBodySchema.required);
1116
+ }
1117
+ for (const property in requestBodySchema.properties) {
1118
+ const schema = requestBodySchema.properties[property];
1119
+ parameters.properties[property] = ManifestUpdater.mapOpenAPISchemaToFuncParam(schema, method, pathUrl);
1120
+ }
1121
+ }
1122
+ else {
1123
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
1124
+ }
1125
+ }
1126
+ const funcObj = {
1127
+ name: operationId,
1128
+ description: description,
1129
+ parameters: parameters,
1130
+ };
1131
+ functions.push(funcObj);
1132
+ functionNames.push(operationId);
1133
+ }
1134
+ }
1135
+ }
1136
+ }
1137
+ }
1138
+ const apiPlugin = {
1139
+ schema_version: "v2",
1140
+ name_for_human: appName,
1141
+ description_for_human: (_c = spec.info.description) !== null && _c !== void 0 ? _c : "<Please add description of the plugin>",
1142
+ functions: functions,
1143
+ runtimes: [
1144
+ {
1145
+ type: "OpenApi",
1146
+ auth: {
1147
+ type: "none", // TODO, support auth in the future
1148
+ },
1149
+ spec: {
1150
+ url: specRelativePath,
1151
+ },
1152
+ run_for_functions: functionNames,
1153
+ },
1154
+ ],
1155
+ };
1156
+ return apiPlugin;
1157
+ }
1158
+ static updateManifest(manifestPath, outputSpecPath, spec, options, adaptiveCardFolder, authInfo) {
803
1159
  return __awaiter(this, void 0, void 0, function* () {
804
1160
  try {
805
- const originalManifest = yield fs__default["default"].readJSON(manifestPath);
1161
+ const originalManifest = yield fs__default['default'].readJSON(manifestPath);
806
1162
  const updatedPart = {};
807
- const [commands, warnings] = yield ManifestUpdater.generateCommands(spec, adaptiveCardFolder, manifestPath, allowMultipleParameters);
808
- const composeExtension = {
809
- composeExtensionType: "apiBased",
810
- apiSpecificationFile: ManifestUpdater.getRelativePath(manifestPath, outputSpecPath),
811
- commands: commands,
812
- };
813
- if (auth) {
814
- if (Utils.isAPIKeyAuth(auth)) {
815
- auth = auth;
816
- const safeApiSecretRegistrationId = Utils.getSafeRegistrationIdEnvName(`${auth.name}_${ConstantString.RegistrationIdPostfix}`);
817
- composeExtension.authorization = {
818
- authType: "apiSecretServiceAuth",
819
- apiSecretServiceAuthConfiguration: {
820
- apiSecretRegistrationId: `\${{${safeApiSecretRegistrationId}}}`,
821
- },
822
- };
823
- }
824
- else if (Utils.isBearerTokenAuth(auth)) {
825
- composeExtension.authorization = {
826
- authType: "microsoftEntra",
827
- microsoftEntraConfiguration: {
828
- supportsSingleSignOn: true,
829
- },
830
- };
831
- updatedPart.webApplicationInfo = {
832
- id: "${{AAD_APP_CLIENT_ID}}",
833
- resource: "api://${{DOMAIN}}/${{AAD_APP_CLIENT_ID}}",
834
- };
1163
+ updatedPart.composeExtensions = [];
1164
+ let warnings = [];
1165
+ if (options.projectType === exports.ProjectType.SME) {
1166
+ const updateResult = yield ManifestUpdater.generateCommands(spec, manifestPath, options, adaptiveCardFolder);
1167
+ const commands = updateResult[0];
1168
+ warnings = updateResult[1];
1169
+ const composeExtension = {
1170
+ composeExtensionType: "apiBased",
1171
+ apiSpecificationFile: ManifestUpdater.getRelativePath(manifestPath, outputSpecPath),
1172
+ commands: commands,
1173
+ };
1174
+ if (authInfo) {
1175
+ const auth = authInfo.authScheme;
1176
+ if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
1177
+ const safeApiSecretRegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
1178
+ composeExtension.authorization = {
1179
+ authType: "apiSecretServiceAuth",
1180
+ apiSecretServiceAuthConfiguration: {
1181
+ apiSecretRegistrationId: `\${{${safeApiSecretRegistrationId}}}`,
1182
+ },
1183
+ };
1184
+ }
1185
+ else if (Utils.isOAuthWithAuthCodeFlow(auth)) {
1186
+ const safeOAuth2RegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.OAuthRegistrationIdPostFix}`);
1187
+ composeExtension.authorization = {
1188
+ authType: "oAuth2.0",
1189
+ oAuthConfiguration: {
1190
+ oauthConfigurationId: `\${{${safeOAuth2RegistrationId}}}`,
1191
+ },
1192
+ };
1193
+ updatedPart.webApplicationInfo = {
1194
+ id: "${{AAD_APP_CLIENT_ID}}",
1195
+ resource: "api://${{DOMAIN}}/${{AAD_APP_CLIENT_ID}}",
1196
+ };
1197
+ }
835
1198
  }
1199
+ updatedPart.composeExtensions = [composeExtension];
836
1200
  }
837
- updatedPart.description = {
838
- short: spec.info.title.slice(0, ConstantString.ShortDescriptionMaxLens),
839
- full: (_b = ((_a = spec.info.description) !== null && _a !== void 0 ? _a : originalManifest.description.full)) === null || _b === void 0 ? void 0 : _b.slice(0, ConstantString.FullDescriptionMaxLens),
840
- };
841
- updatedPart.composeExtensions = [composeExtension];
1201
+ updatedPart.description = originalManifest.description;
1202
+ ManifestUpdater.updateManifestDescription(updatedPart, spec);
842
1203
  const updatedManifest = Object.assign(Object.assign({}, originalManifest), updatedPart);
843
1204
  return [updatedManifest, warnings];
844
1205
  }
@@ -847,7 +1208,8 @@ class ManifestUpdater {
847
1208
  }
848
1209
  });
849
1210
  }
850
- static generateCommands(spec, adaptiveCardFolder, manifestPath, allowMultipleParameters) {
1211
+ static generateCommands(spec, manifestPath, options, adaptiveCardFolder) {
1212
+ var _a;
851
1213
  return __awaiter(this, void 0, void 0, function* () {
852
1214
  const paths = spec.paths;
853
1215
  const commands = [];
@@ -859,16 +1221,28 @@ class ManifestUpdater {
859
1221
  const operations = pathItem;
860
1222
  // Currently only support GET and POST method
861
1223
  for (const method in operations) {
862
- if (method === ConstantString.PostMethod || method === ConstantString.GetMethod) {
1224
+ if ((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) {
863
1225
  const operationItem = operations[method];
864
1226
  if (operationItem) {
865
- const [command, warning] = Utils.parseApiInfo(operationItem, allowMultipleParameters);
866
- const adaptiveCardPath = path__default["default"].join(adaptiveCardFolder, command.id + ".json");
867
- command.apiResponseRenderingTemplateFile = (yield fs__default["default"].pathExists(adaptiveCardPath))
868
- ? ManifestUpdater.getRelativePath(manifestPath, adaptiveCardPath)
869
- : "";
870
- if (warning) {
871
- warnings.push(warning);
1227
+ const command = Utils.parseApiInfo(operationItem, options);
1228
+ if (command.parameters &&
1229
+ command.parameters.length >= 1 &&
1230
+ command.parameters.some((param) => param.isRequired)) {
1231
+ command.parameters = command.parameters.filter((param) => param.isRequired);
1232
+ }
1233
+ else if (command.parameters && command.parameters.length > 0) {
1234
+ command.parameters = [command.parameters[0]];
1235
+ warnings.push({
1236
+ type: exports.WarningType.OperationOnlyContainsOptionalParam,
1237
+ content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, command.id),
1238
+ data: command.id,
1239
+ });
1240
+ }
1241
+ if (adaptiveCardFolder) {
1242
+ const adaptiveCardPath = path__default['default'].join(adaptiveCardFolder, command.id + ".json");
1243
+ command.apiResponseRenderingTemplateFile = (yield fs__default['default'].pathExists(adaptiveCardPath))
1244
+ ? ManifestUpdater.getRelativePath(manifestPath, adaptiveCardPath)
1245
+ : "";
872
1246
  }
873
1247
  commands.push(command);
874
1248
  }
@@ -881,8 +1255,17 @@ class ManifestUpdater {
881
1255
  });
882
1256
  }
883
1257
  static getRelativePath(from, to) {
884
- const relativePath = path__default["default"].relative(path__default["default"].dirname(from), to);
885
- return path__default["default"].normalize(relativePath).replace(/\\/g, "/");
1258
+ const relativePath = path__default['default'].relative(path__default['default'].dirname(from), to);
1259
+ return path__default['default'].normalize(relativePath).replace(/\\/g, "/");
1260
+ }
1261
+ static removeEnvs(str) {
1262
+ const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
1263
+ const matches = placeHolderReg.exec(str);
1264
+ let newStr = str;
1265
+ if (matches != null) {
1266
+ newStr = newStr.replace(matches[0], "");
1267
+ }
1268
+ return newStr;
886
1269
  }
887
1270
  }
888
1271
 
@@ -890,7 +1273,7 @@ class ManifestUpdater {
890
1273
  class AdaptiveCardGenerator {
891
1274
  static generateAdaptiveCard(operationItem) {
892
1275
  try {
893
- const json = Utils.getResponseJson(operationItem);
1276
+ const { json } = Utils.getResponseJson(operationItem);
894
1277
  let cardBody = [];
895
1278
  let schema = json.schema;
896
1279
  let jsonPath = "$";
@@ -1150,11 +1533,14 @@ class SpecParser {
1150
1533
  allowMissingId: true,
1151
1534
  allowSwagger: true,
1152
1535
  allowAPIKeyAuth: false,
1536
+ allowBearerTokenAuth: false,
1153
1537
  allowMultipleParameters: false,
1154
1538
  allowOauth2: false,
1539
+ allowMethods: ["get", "post"],
1540
+ projectType: exports.ProjectType.SME,
1155
1541
  };
1156
1542
  this.pathOrSpec = pathOrDoc;
1157
- this.parser = new SwaggerParser__default["default"]();
1543
+ this.parser = new SwaggerParser__default['default']();
1158
1544
  this.options = Object.assign(Object.assign({}, this.defaultOptions), (options !== null && options !== void 0 ? options : {}));
1159
1545
  }
1160
1546
  /**
@@ -1185,7 +1571,24 @@ class SpecParser {
1185
1571
  ],
1186
1572
  };
1187
1573
  }
1188
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
1574
+ if (this.options.projectType === exports.ProjectType.SME ||
1575
+ this.options.projectType === exports.ProjectType.Copilot) {
1576
+ if (this.spec.openapi >= "3.1.0") {
1577
+ return {
1578
+ status: exports.ValidationStatus.Error,
1579
+ warnings: [],
1580
+ errors: [
1581
+ {
1582
+ type: exports.ErrorType.SpecVersionNotSupported,
1583
+ content: Utils.format(ConstantString.SpecVersionNotSupported, this.spec.openapi),
1584
+ data: this.spec.openapi,
1585
+ },
1586
+ ],
1587
+ };
1588
+ }
1589
+ }
1590
+ const apiMap = this.getAPIs(this.spec);
1591
+ return Utils.validateSpec(this.spec, this.parser, apiMap, !!this.isSwaggerFile, this.options);
1189
1592
  }
1190
1593
  catch (err) {
1191
1594
  throw new SpecParserError(err.toString(), exports.ErrorType.ValidateFailed);
@@ -1209,16 +1612,22 @@ class SpecParser {
1209
1612
  try {
1210
1613
  yield this.loadSpec();
1211
1614
  const spec = this.spec;
1212
- const apiMap = this.getAllSupportedAPIs(spec);
1213
- const result = [];
1615
+ const apiMap = this.getAPIs(spec);
1616
+ const result = {
1617
+ APIs: [],
1618
+ allAPICount: 0,
1619
+ validAPICount: 0,
1620
+ };
1214
1621
  for (const apiKey in apiMap) {
1622
+ const { operation, isValid, reason } = apiMap[apiKey];
1623
+ const [method, path] = apiKey.split(" ");
1215
1624
  const apiResult = {
1216
1625
  api: "",
1217
1626
  server: "",
1218
1627
  operationId: "",
1628
+ isValid: isValid,
1629
+ reason: reason,
1219
1630
  };
1220
- const [method, path] = apiKey.split(" ");
1221
- const operation = apiMap[apiKey];
1222
1631
  const rootServer = spec.servers && spec.servers[0];
1223
1632
  const methodServer = spec.paths[path].servers && ((_a = spec.paths[path]) === null || _a === void 0 ? void 0 : _a.servers[0]);
1224
1633
  const operationServer = operation.servers && operation.servers[0];
@@ -1226,7 +1635,7 @@ class SpecParser {
1226
1635
  if (!serverUrl) {
1227
1636
  throw new SpecParserError(ConstantString.NoServerInformation, exports.ErrorType.NoServerInformation);
1228
1637
  }
1229
- apiResult.server = Utils.resolveServerUrl(serverUrl.url);
1638
+ apiResult.server = Utils.resolveEnv(serverUrl.url);
1230
1639
  let operationId = operation.operationId;
1231
1640
  if (!operationId) {
1232
1641
  operationId = `${method.toLowerCase()}${Utils.convertPathToCamelCase(path)}`;
@@ -1235,13 +1644,15 @@ class SpecParser {
1235
1644
  const authArray = Utils.getAuthArray(operation.security, spec);
1236
1645
  for (const auths of authArray) {
1237
1646
  if (auths.length === 1) {
1238
- apiResult.auth = auths[0].authSchema;
1647
+ apiResult.auth = auths[0];
1239
1648
  break;
1240
1649
  }
1241
1650
  }
1242
1651
  apiResult.api = apiKey;
1243
- result.push(apiResult);
1652
+ result.APIs.push(apiResult);
1244
1653
  }
1654
+ result.allAPICount = result.APIs.length;
1655
+ result.validAPICount = result.APIs.filter((api) => api.isValid).length;
1245
1656
  return result;
1246
1657
  }
1247
1658
  catch (err) {
@@ -1252,78 +1663,144 @@ class SpecParser {
1252
1663
  }
1253
1664
  });
1254
1665
  }
1666
+ /**
1667
+ * Generate specs according to the filters.
1668
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
1669
+ */
1670
+ getFilteredSpecs(filter, signal) {
1671
+ return __awaiter(this, void 0, void 0, function* () {
1672
+ try {
1673
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1674
+ throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1675
+ }
1676
+ yield this.loadSpec();
1677
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1678
+ throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1679
+ }
1680
+ const newUnResolvedSpec = SpecFilter.specFilter(filter, this.unResolveSpec, this.spec, this.options);
1681
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1682
+ throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1683
+ }
1684
+ const newSpec = (yield this.parser.dereference(newUnResolvedSpec));
1685
+ return [newUnResolvedSpec, newSpec];
1686
+ }
1687
+ catch (err) {
1688
+ if (err instanceof SpecParserError) {
1689
+ throw err;
1690
+ }
1691
+ throw new SpecParserError(err.toString(), exports.ErrorType.GetSpecFailed);
1692
+ }
1693
+ });
1694
+ }
1255
1695
  /**
1256
1696
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
1257
1697
  * @param manifestPath A file path of the Teams app manifest file to update.
1258
1698
  * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
1259
1699
  * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
1260
- * @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
1700
+ * @param pluginFilePath File path of the api plugin file to generate.
1261
1701
  */
1262
- generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
1702
+ generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
1263
1703
  return __awaiter(this, void 0, void 0, function* () {
1264
1704
  const result = {
1265
1705
  allSuccess: true,
1266
1706
  warnings: [],
1267
1707
  };
1268
1708
  try {
1269
- if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1270
- throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1709
+ const newSpecs = yield this.getFilteredSpecs(filter, signal);
1710
+ const newUnResolvedSpec = newSpecs[0];
1711
+ const newSpec = newSpecs[1];
1712
+ let resultStr;
1713
+ if (outputSpecPath.endsWith(".yaml") || outputSpecPath.endsWith(".yml")) {
1714
+ resultStr = jsyaml__default['default'].dump(newUnResolvedSpec);
1271
1715
  }
1272
- yield this.loadSpec();
1273
- if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1274
- throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1716
+ else {
1717
+ resultStr = JSON.stringify(newUnResolvedSpec, null, 2);
1275
1718
  }
1276
- const newUnResolvedSpec = SpecFilter.specFilter(filter, this.unResolveSpec, this.spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
1719
+ yield fs__default['default'].outputFile(outputSpecPath, resultStr);
1277
1720
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1278
1721
  throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1279
1722
  }
1280
- const newSpec = (yield this.parser.dereference(newUnResolvedSpec));
1281
- const AuthSet = new Set();
1282
- let hasMultipleAPIKeyAuth = false;
1723
+ const [updatedManifest, apiPlugin] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options);
1724
+ yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 2 });
1725
+ yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 2 });
1726
+ }
1727
+ catch (err) {
1728
+ if (err instanceof SpecParserError) {
1729
+ throw err;
1730
+ }
1731
+ throw new SpecParserError(err.toString(), exports.ErrorType.GenerateFailed);
1732
+ }
1733
+ return result;
1734
+ });
1735
+ }
1736
+ /**
1737
+ * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
1738
+ * @param manifestPath A file path of the Teams app manifest file to update.
1739
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
1740
+ * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
1741
+ * @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
1742
+ */
1743
+ generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
1744
+ return __awaiter(this, void 0, void 0, function* () {
1745
+ const result = {
1746
+ allSuccess: true,
1747
+ warnings: [],
1748
+ };
1749
+ try {
1750
+ const newSpecs = yield this.getFilteredSpecs(filter, signal);
1751
+ const newUnResolvedSpec = newSpecs[0];
1752
+ const newSpec = newSpecs[1];
1753
+ let hasMultipleAuth = false;
1754
+ let authInfo = undefined;
1283
1755
  for (const url in newSpec.paths) {
1284
1756
  for (const method in newSpec.paths[url]) {
1285
1757
  const operation = newSpec.paths[url][method];
1286
1758
  const authArray = Utils.getAuthArray(operation.security, newSpec);
1287
1759
  if (authArray && authArray.length > 0) {
1288
- AuthSet.add(authArray[0][0].authSchema);
1289
- if (AuthSet.size > 1) {
1290
- hasMultipleAPIKeyAuth = true;
1760
+ const currentAuth = authArray[0][0];
1761
+ if (!authInfo) {
1762
+ authInfo = authArray[0][0];
1763
+ }
1764
+ else if (authInfo.name !== currentAuth.name) {
1765
+ hasMultipleAuth = true;
1291
1766
  break;
1292
1767
  }
1293
1768
  }
1294
1769
  }
1295
1770
  }
1296
- if (hasMultipleAPIKeyAuth) {
1297
- throw new SpecParserError(ConstantString.MultipleAPIKeyNotSupported, exports.ErrorType.MultipleAPIKeyNotSupported);
1771
+ if (hasMultipleAuth && this.options.projectType !== exports.ProjectType.TeamsAi) {
1772
+ throw new SpecParserError(ConstantString.MultipleAuthNotSupported, exports.ErrorType.MultipleAuthNotSupported);
1298
1773
  }
1299
1774
  let resultStr;
1300
1775
  if (outputSpecPath.endsWith(".yaml") || outputSpecPath.endsWith(".yml")) {
1301
- resultStr = jsyaml__default["default"].dump(newUnResolvedSpec);
1776
+ resultStr = jsyaml__default['default'].dump(newUnResolvedSpec);
1302
1777
  }
1303
1778
  else {
1304
1779
  resultStr = JSON.stringify(newUnResolvedSpec, null, 2);
1305
1780
  }
1306
- yield fs__default["default"].outputFile(outputSpecPath, resultStr);
1307
- for (const url in newSpec.paths) {
1308
- for (const method in newSpec.paths[url]) {
1309
- // paths object may contain description/summary, so we need to check if it is a operation object
1310
- if (method === ConstantString.PostMethod || method === ConstantString.GetMethod) {
1311
- const operation = newSpec.paths[url][method];
1312
- try {
1313
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
1314
- const fileName = path__default["default"].join(adaptiveCardFolder, `${operation.operationId}.json`);
1315
- const wrappedCard = wrapAdaptiveCard(card, jsonPath);
1316
- yield fs__default["default"].outputJSON(fileName, wrappedCard, { spaces: 2 });
1317
- const dataFileName = path__default["default"].join(adaptiveCardFolder, `${operation.operationId}.data.json`);
1318
- yield fs__default["default"].outputJSON(dataFileName, {}, { spaces: 2 });
1319
- }
1320
- catch (err) {
1321
- result.allSuccess = false;
1322
- result.warnings.push({
1323
- type: exports.WarningType.GenerateCardFailed,
1324
- content: err.toString(),
1325
- data: operation.operationId,
1326
- });
1781
+ yield fs__default['default'].outputFile(outputSpecPath, resultStr);
1782
+ if (adaptiveCardFolder) {
1783
+ for (const url in newSpec.paths) {
1784
+ for (const method in newSpec.paths[url]) {
1785
+ // paths object may contain description/summary which is not a http method, so we need to check if it is a operation object
1786
+ if (this.options.allowMethods.includes(method)) {
1787
+ const operation = newSpec.paths[url][method];
1788
+ try {
1789
+ const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
1790
+ const fileName = path__default['default'].join(adaptiveCardFolder, `${operation.operationId}.json`);
1791
+ const wrappedCard = wrapAdaptiveCard(card, jsonPath);
1792
+ yield fs__default['default'].outputJSON(fileName, wrappedCard, { spaces: 2 });
1793
+ const dataFileName = path__default['default'].join(adaptiveCardFolder, `${operation.operationId}.data.json`);
1794
+ yield fs__default['default'].outputJSON(dataFileName, {}, { spaces: 2 });
1795
+ }
1796
+ catch (err) {
1797
+ result.allSuccess = false;
1798
+ result.warnings.push({
1799
+ type: exports.WarningType.GenerateCardFailed,
1800
+ content: err.toString(),
1801
+ data: operation.operationId,
1802
+ });
1803
+ }
1327
1804
  }
1328
1805
  }
1329
1806
  }
@@ -1331,9 +1808,8 @@ class SpecParser {
1331
1808
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1332
1809
  throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1333
1810
  }
1334
- const auth = Array.from(AuthSet)[0];
1335
- const [updatedManifest, warnings] = yield ManifestUpdater.updateManifest(manifestPath, outputSpecPath, adaptiveCardFolder, newSpec, this.options.allowMultipleParameters, auth);
1336
- yield fs__default["default"].outputJSON(manifestPath, updatedManifest, { spaces: 2 });
1811
+ const [updatedManifest, warnings] = yield ManifestUpdater.updateManifest(manifestPath, outputSpecPath, newSpec, this.options, adaptiveCardFolder, authInfo);
1812
+ yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 2 });
1337
1813
  result.warnings.push(...warnings);
1338
1814
  }
1339
1815
  catch (err) {
@@ -1351,7 +1827,7 @@ class SpecParser {
1351
1827
  this.unResolveSpec = (yield this.parser.parse(this.pathOrSpec));
1352
1828
  // Convert swagger 2.0 to openapi 3.0
1353
1829
  if (!this.unResolveSpec.openapi && this.unResolveSpec.swagger === "2.0") {
1354
- const specObj = yield converter__default["default"].convert(this.unResolveSpec, {});
1830
+ const specObj = yield converter__default['default'].convert(this.unResolveSpec, {});
1355
1831
  this.unResolveSpec = specObj.openapi;
1356
1832
  this.isSwaggerFile = true;
1357
1833
  }
@@ -1360,16 +1836,38 @@ class SpecParser {
1360
1836
  }
1361
1837
  });
1362
1838
  }
1363
- getAllSupportedAPIs(spec) {
1839
+ getAPIs(spec) {
1364
1840
  if (this.apiMap !== undefined) {
1365
1841
  return this.apiMap;
1366
1842
  }
1367
- const result = Utils.listSupportedAPIs(spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
1843
+ const result = this.listAPIs(spec, this.options);
1368
1844
  this.apiMap = result;
1369
1845
  return result;
1370
1846
  }
1847
+ listAPIs(spec, options) {
1848
+ var _a;
1849
+ const paths = spec.paths;
1850
+ const result = {};
1851
+ for (const path in paths) {
1852
+ const methods = paths[path];
1853
+ for (const method in methods) {
1854
+ const operationObject = methods[method];
1855
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
1856
+ const validator = ValidatorFactory.create(spec, options);
1857
+ const validateResult = validator.validateAPI(method, path);
1858
+ result[`${method.toUpperCase()} ${path}`] = {
1859
+ operation: operationObject,
1860
+ isValid: validateResult.isValid,
1861
+ reason: validateResult.reason,
1862
+ };
1863
+ }
1864
+ }
1865
+ }
1866
+ return result;
1867
+ }
1371
1868
  }
1372
1869
 
1870
+ exports.AdaptiveCardGenerator = AdaptiveCardGenerator;
1373
1871
  exports.ConstantString = ConstantString;
1374
1872
  exports.SpecParser = SpecParser;
1375
1873
  exports.SpecParserError = SpecParserError;