@microsoft/m365-spec-parser 0.1.1-alpha.48b9eab36.0 → 0.1.1-alpha.4e708f092.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.
@@ -45,7 +45,8 @@ var ErrorType;
45
45
  ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
46
46
  ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
47
47
  ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
48
- ErrorType["MultipleAPIKeyNotSupported"] = "multiple-api-key-not-supported";
48
+ ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
49
+ ErrorType["SpecVersionNotSupported"] = "spec-version-not-supported";
49
50
  ErrorType["ListFailed"] = "list-failed";
50
51
  ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
51
52
  ErrorType["FilterSpecFailed"] = "filter-spec-failed";
@@ -54,6 +55,21 @@ var ErrorType;
54
55
  ErrorType["GenerateFailed"] = "generate-failed";
55
56
  ErrorType["ValidateFailed"] = "validate-failed";
56
57
  ErrorType["GetSpecFailed"] = "get-spec-failed";
58
+ ErrorType["AuthTypeIsNotSupported"] = "auth-type-is-not-supported";
59
+ ErrorType["MissingOperationId"] = "missing-operation-id";
60
+ ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
61
+ ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
62
+ ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
63
+ ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
64
+ ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
65
+ ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
66
+ ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
67
+ ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
68
+ ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
69
+ ErrorType["NoParameter"] = "no-parameter";
70
+ ErrorType["NoAPIInfo"] = "no-api-info";
71
+ ErrorType["MethodNotAllowed"] = "method-not-allowed";
72
+ ErrorType["UrlPathNotExist"] = "url-path-not-exist";
57
73
  ErrorType["Cancelled"] = "cancelled";
58
74
  ErrorType["Unknown"] = "unknown";
59
75
  })(ErrorType || (ErrorType = {}));
@@ -76,7 +92,13 @@ var ValidationStatus;
76
92
  ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
77
93
  ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
78
94
  ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
79
- })(ValidationStatus || (ValidationStatus = {}));
95
+ })(ValidationStatus || (ValidationStatus = {}));
96
+ var ProjectType;
97
+ (function (ProjectType) {
98
+ ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
99
+ ProjectType[ProjectType["SME"] = 1] = "SME";
100
+ ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
101
+ })(ProjectType || (ProjectType = {}));
80
102
 
81
103
  // Copyright (c) Microsoft Corporation.
82
104
  class SpecParserError extends Error {
@@ -103,7 +125,9 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
103
125
  ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
104
126
  ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
105
127
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
106
- ConstantString.MultipleAPIKeyNotSupported = "Multiple API keys are not supported. Please make sure that all selected APIs use the same API key.";
128
+ ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
129
+ ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
130
+ ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
107
131
  ConstantString.WrappedCardVersion = "devPreview";
108
132
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
109
133
  ConstantString.WrappedCardResponseLayout = "list";
@@ -113,8 +137,10 @@ ConstantString.AdaptiveCardVersion = "1.5";
113
137
  ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
114
138
  ConstantString.AdaptiveCardType = "AdaptiveCard";
115
139
  ConstantString.TextBlockType = "TextBlock";
140
+ ConstantString.ImageType = "Image";
116
141
  ConstantString.ContainerType = "Container";
117
142
  ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
143
+ ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
118
144
  ConstantString.ResponseCodeFor20X = [
119
145
  "200",
120
146
  "201",
@@ -174,205 +200,36 @@ ConstantString.FullDescriptionMaxLens = 4000;
174
200
  ConstantString.CommandDescriptionMaxLens = 128;
175
201
  ConstantString.ParameterDescriptionMaxLens = 128;
176
202
  ConstantString.CommandTitleMaxLens = 32;
177
- ConstantString.ParameterTitleMaxLens = 32;
203
+ ConstantString.ParameterTitleMaxLens = 32;
204
+ ConstantString.SMERequiredParamsMaxNum = 5;
205
+ ConstantString.DefaultPluginId = "plugin_1";
178
206
 
179
207
  // Copyright (c) Microsoft Corporation.
180
208
  class Utils {
181
- static checkParameters(paramObject) {
182
- const paramResult = {
183
- requiredNum: 0,
184
- optionalNum: 0,
185
- isValid: true,
186
- };
187
- if (!paramObject) {
188
- return paramResult;
189
- }
190
- for (let i = 0; i < paramObject.length; i++) {
191
- const param = paramObject[i];
192
- const schema = param.schema;
193
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
194
- if (param.in === "header" || param.in === "cookie") {
195
- if (isRequiredWithoutDefault) {
196
- paramResult.isValid = false;
197
- }
198
- continue;
199
- }
200
- if (schema.type !== "boolean" &&
201
- schema.type !== "string" &&
202
- schema.type !== "number" &&
203
- schema.type !== "integer") {
204
- if (isRequiredWithoutDefault) {
205
- paramResult.isValid = false;
206
- }
207
- continue;
208
- }
209
- if (param.in === "query" || param.in === "path") {
210
- if (isRequiredWithoutDefault) {
211
- paramResult.requiredNum = paramResult.requiredNum + 1;
212
- }
213
- else {
214
- paramResult.optionalNum = paramResult.optionalNum + 1;
215
- }
216
- }
217
- }
218
- return paramResult;
219
- }
220
- static checkPostBody(schema, isRequired = false) {
221
- var _a;
222
- const paramResult = {
223
- requiredNum: 0,
224
- optionalNum: 0,
225
- isValid: true,
226
- };
227
- if (Object.keys(schema).length === 0) {
228
- return paramResult;
229
- }
230
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
231
- if (schema.type === "string" ||
232
- schema.type === "integer" ||
233
- schema.type === "boolean" ||
234
- schema.type === "number") {
235
- if (isRequiredWithoutDefault) {
236
- paramResult.requiredNum = paramResult.requiredNum + 1;
237
- }
238
- else {
239
- paramResult.optionalNum = paramResult.optionalNum + 1;
240
- }
241
- }
242
- else if (schema.type === "object") {
243
- const { properties } = schema;
244
- for (const property in properties) {
245
- let isRequired = false;
246
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
247
- isRequired = true;
248
- }
249
- const result = Utils.checkPostBody(properties[property], isRequired);
250
- paramResult.requiredNum += result.requiredNum;
251
- paramResult.optionalNum += result.optionalNum;
252
- paramResult.isValid = paramResult.isValid && result.isValid;
253
- }
254
- }
255
- else {
256
- if (isRequiredWithoutDefault) {
257
- paramResult.isValid = false;
258
- }
259
- }
260
- return paramResult;
261
- }
262
- /**
263
- * Checks if the given API is supported.
264
- * @param {string} method - The HTTP method of the API.
265
- * @param {string} path - The path of the API.
266
- * @param {OpenAPIV3.Document} spec - The OpenAPI specification document.
267
- * @returns {boolean} - Returns true if the API is supported, false otherwise.
268
- * @description The following APIs are supported:
269
- * 1. only support Get/Post operation without auth property
270
- * 2. parameter inside query or path only support string, number, boolean and integer
271
- * 3. parameter inside post body only support string, number, boolean, integer and object
272
- * 4. request body + required parameters <= 1
273
- * 5. response body should be “application/json” and not empty, and response code should be 20X
274
- * 6. only support request body with “application/json” content type
275
- */
276
- static isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
277
- const pathObj = spec.paths[path];
278
- method = method.toLocaleLowerCase();
279
- if (pathObj) {
280
- if ((method === ConstantString.PostMethod || method === ConstantString.GetMethod) &&
281
- pathObj[method]) {
282
- const securities = pathObj[method].security;
283
- const authArray = Utils.getAuthArray(securities, spec);
284
- if (!Utils.isSupportedAuth(authArray, allowAPIKeyAuth, allowOauth2)) {
285
- return false;
286
- }
287
- const operationObject = pathObj[method];
288
- if (!allowMissingId && !operationObject.operationId) {
289
- return false;
290
- }
291
- const paramObject = operationObject.parameters;
292
- const requestBody = operationObject.requestBody;
293
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
294
- const mediaTypesCount = Object.keys((requestBody === null || requestBody === void 0 ? void 0 : requestBody.content) || {}).length;
295
- if (mediaTypesCount > 1) {
296
- return false;
297
- }
298
- const responseJson = Utils.getResponseJson(operationObject);
299
- if (Object.keys(responseJson).length === 0) {
300
- return false;
301
- }
302
- let requestBodyParamResult = {
303
- requiredNum: 0,
304
- optionalNum: 0,
305
- isValid: true,
306
- };
307
- if (requestJsonBody) {
308
- const requestBodySchema = requestJsonBody.schema;
309
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required);
310
- }
311
- if (!requestBodyParamResult.isValid) {
312
- return false;
313
- }
314
- const paramResult = Utils.checkParameters(paramObject);
315
- if (!paramResult.isValid) {
316
- return false;
317
- }
318
- if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
319
- if (allowMultipleParameters &&
320
- requestBodyParamResult.requiredNum + paramResult.requiredNum <= 5) {
321
- return true;
322
- }
323
- return false;
324
- }
325
- else if (requestBodyParamResult.requiredNum +
326
- requestBodyParamResult.optionalNum +
327
- paramResult.requiredNum +
328
- paramResult.optionalNum ===
329
- 0) {
330
- return false;
331
- }
332
- else {
209
+ static hasNestedObjectInSchema(schema) {
210
+ if (schema.type === "object") {
211
+ for (const property in schema.properties) {
212
+ const nestedSchema = schema.properties[property];
213
+ if (nestedSchema.type === "object") {
333
214
  return true;
334
215
  }
335
216
  }
336
217
  }
337
218
  return false;
338
219
  }
339
- static isSupportedAuth(authSchemaArray, allowAPIKeyAuth, allowOauth2) {
340
- if (authSchemaArray.length === 0) {
341
- return true;
342
- }
343
- if (allowAPIKeyAuth || allowOauth2) {
344
- // Currently we don't support multiple auth in one operation
345
- if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
346
- return false;
347
- }
348
- for (const auths of authSchemaArray) {
349
- if (auths.length === 1) {
350
- if (!allowOauth2 && allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authSchema)) {
351
- return true;
352
- }
353
- else if (!allowAPIKeyAuth &&
354
- allowOauth2 &&
355
- Utils.isBearerTokenAuth(auths[0].authSchema)) {
356
- return true;
357
- }
358
- else if (allowAPIKeyAuth &&
359
- allowOauth2 &&
360
- (Utils.isAPIKeyAuth(auths[0].authSchema) ||
361
- Utils.isBearerTokenAuth(auths[0].authSchema))) {
362
- return true;
363
- }
364
- }
365
- }
366
- }
367
- return false;
220
+ static containMultipleMediaTypes(bodyObject) {
221
+ return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
222
+ }
223
+ static isBearerTokenAuth(authScheme) {
224
+ return authScheme.type === "http" && authScheme.scheme === "bearer";
368
225
  }
369
- static isAPIKeyAuth(authSchema) {
370
- return authSchema.type === "apiKey";
226
+ static isAPIKeyAuth(authScheme) {
227
+ return authScheme.type === "apiKey";
371
228
  }
372
- static isBearerTokenAuth(authSchema) {
373
- return (authSchema.type === "oauth2" ||
374
- authSchema.type === "openIdConnect" ||
375
- (authSchema.type === "http" && authSchema.scheme === "bearer"));
229
+ static isOAuthWithAuthCodeFlow(authScheme) {
230
+ return !!(authScheme.type === "oauth2" &&
231
+ authScheme.flows &&
232
+ authScheme.flows.authorizationCode);
376
233
  }
377
234
  static getAuthArray(securities, spec) {
378
235
  var _a;
@@ -385,7 +242,7 @@ class Utils {
385
242
  for (const name in security) {
386
243
  const auth = securitySchemas[name];
387
244
  authArray.push({
388
- authSchema: auth,
245
+ authScheme: auth,
389
246
  name: name,
390
247
  });
391
248
  }
@@ -403,18 +260,22 @@ class Utils {
403
260
  static getResponseJson(operationObject) {
404
261
  var _a, _b;
405
262
  let json = {};
263
+ let multipleMediaType = false;
406
264
  for (const code of ConstantString.ResponseCodeFor20X) {
407
265
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
408
- const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
409
- if (mediaTypesCount > 1) {
410
- return {};
411
- }
412
266
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
267
+ multipleMediaType = false;
413
268
  json = responseObject.content["application/json"];
414
- break;
269
+ if (Utils.containMultipleMediaTypes(responseObject)) {
270
+ multipleMediaType = true;
271
+ json = {};
272
+ }
273
+ else {
274
+ break;
275
+ }
415
276
  }
416
277
  }
417
- return json;
278
+ return { json, multipleMediaType };
418
279
  }
419
280
  static convertPathToCamelCase(path) {
420
281
  const pathSegments = path.split(/[./{]/);
@@ -434,10 +295,10 @@ class Utils {
434
295
  return undefined;
435
296
  }
436
297
  }
437
- static resolveServerUrl(url) {
298
+ static resolveEnv(str) {
438
299
  const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
439
- let matches = placeHolderReg.exec(url);
440
- let newUrl = url;
300
+ let matches = placeHolderReg.exec(str);
301
+ let newStr = str;
441
302
  while (matches != null) {
442
303
  const envVar = matches[1];
443
304
  const envVal = process.env[envVar];
@@ -445,17 +306,17 @@ class Utils {
445
306
  throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
446
307
  }
447
308
  else {
448
- newUrl = newUrl.replace(matches[0], envVal);
309
+ newStr = newStr.replace(matches[0], envVal);
449
310
  }
450
- matches = placeHolderReg.exec(url);
311
+ matches = placeHolderReg.exec(str);
451
312
  }
452
- return newUrl;
313
+ return newStr;
453
314
  }
454
315
  static checkServerUrl(servers) {
455
316
  const errors = [];
456
317
  let serverUrl;
457
318
  try {
458
- serverUrl = Utils.resolveServerUrl(servers[0].url);
319
+ serverUrl = Utils.resolveEnv(servers[0].url);
459
320
  }
460
321
  catch (err) {
461
322
  errors.push({
@@ -485,7 +346,8 @@ class Utils {
485
346
  }
486
347
  return errors;
487
348
  }
488
- static validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
349
+ static validateServer(spec, options) {
350
+ var _a;
489
351
  const errors = [];
490
352
  let hasTopLevelServers = false;
491
353
  let hasPathLevelServers = false;
@@ -506,7 +368,7 @@ class Utils {
506
368
  }
507
369
  for (const method in methods) {
508
370
  const operationObject = methods[method];
509
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
371
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
510
372
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
511
373
  hasOperationLevelServers = true;
512
374
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -549,6 +411,7 @@ class Utils {
549
411
  Utils.updateParameterWithInputType(schema, parameter);
550
412
  }
551
413
  if (isRequired && schema.default === undefined) {
414
+ parameter.isRequired = true;
552
415
  requiredParams.push(parameter);
553
416
  }
554
417
  else {
@@ -593,7 +456,7 @@ class Utils {
593
456
  param.value = schema.default;
594
457
  }
595
458
  }
596
- static parseApiInfo(operationItem, allowMultipleParameters) {
459
+ static parseApiInfo(operationItem, options) {
597
460
  var _a, _b;
598
461
  const requiredParams = [];
599
462
  const optionalParams = [];
@@ -607,11 +470,12 @@ class Utils {
607
470
  description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
608
471
  };
609
472
  const schema = param.schema;
610
- if (allowMultipleParameters && schema) {
473
+ if (options.allowMultipleParameters && schema) {
611
474
  Utils.updateParameterWithInputType(schema, parameter);
612
475
  }
613
476
  if (param.in !== "header" && param.in !== "cookie") {
614
477
  if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
478
+ parameter.isRequired = true;
615
479
  requiredParams.push(parameter);
616
480
  }
617
481
  else {
@@ -625,19 +489,13 @@ class Utils {
625
489
  const requestJson = requestBody.content["application/json"];
626
490
  if (Object.keys(requestJson).length !== 0) {
627
491
  const schema = requestJson.schema;
628
- const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
492
+ const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
629
493
  requiredParams.push(...requiredP);
630
494
  optionalParams.push(...optionalP);
631
495
  }
632
496
  }
633
497
  const operationId = operationItem.operationId;
634
- const parameters = [];
635
- if (requiredParams.length !== 0) {
636
- parameters.push(...requiredParams);
637
- }
638
- else {
639
- parameters.push(optionalParams[0]);
640
- }
498
+ const parameters = [...requiredParams, ...optionalParams];
641
499
  const command = {
642
500
  context: ["compose"],
643
501
  type: "query",
@@ -646,105 +504,535 @@ class Utils {
646
504
  parameters: parameters,
647
505
  description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
648
506
  };
649
- let warning = undefined;
650
- if (requiredParams.length === 0 && optionalParams.length > 1) {
651
- warning = {
652
- type: WarningType.OperationOnlyContainsOptionalParam,
653
- content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, operationId),
654
- data: operationId,
655
- };
507
+ return command;
508
+ }
509
+ static format(str, ...args) {
510
+ let index = 0;
511
+ return str.replace(/%s/g, () => {
512
+ const arg = args[index++];
513
+ return arg !== undefined ? arg : "";
514
+ });
515
+ }
516
+ static getSafeRegistrationIdEnvName(authName) {
517
+ if (!authName) {
518
+ return "";
656
519
  }
657
- return [command, warning];
520
+ let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
521
+ if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
522
+ safeRegistrationIdEnvName = "PREFIX_" + safeRegistrationIdEnvName;
523
+ }
524
+ return safeRegistrationIdEnvName;
658
525
  }
659
- static listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
660
- const paths = spec.paths;
526
+ static getServerObject(spec, method, path) {
527
+ const pathObj = spec.paths[path];
528
+ const operationObject = pathObj[method];
529
+ const rootServer = spec.servers && spec.servers[0];
530
+ const methodServer = spec.paths[path].servers && spec.paths[path].servers[0];
531
+ const operationServer = operationObject.servers && operationObject.servers[0];
532
+ const serverUrl = operationServer || methodServer || rootServer;
533
+ return serverUrl;
534
+ }
535
+ }
536
+
537
+ // Copyright (c) Microsoft Corporation.
538
+ class Validator {
539
+ listAPIs() {
540
+ var _a;
541
+ if (this.apiMap) {
542
+ return this.apiMap;
543
+ }
544
+ const paths = this.spec.paths;
661
545
  const result = {};
662
546
  for (const path in paths) {
663
547
  const methods = paths[path];
664
548
  for (const method in methods) {
665
- // For developer preview, only support GET operation with only 1 parameter without auth
666
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
667
- const operationObject = methods[method];
668
- result[`${method.toUpperCase()} ${path}`] = operationObject;
549
+ const operationObject = methods[method];
550
+ if (((_a = this.options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
551
+ const validateResult = this.validateAPI(method, path);
552
+ result[`${method.toUpperCase()} ${path}`] = {
553
+ operation: operationObject,
554
+ isValid: validateResult.isValid,
555
+ reason: validateResult.reason,
556
+ };
669
557
  }
670
558
  }
671
559
  }
560
+ this.apiMap = result;
672
561
  return result;
673
562
  }
674
- static validateSpec(spec, parser, isSwaggerFile, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
675
- const errors = [];
676
- const warnings = [];
677
- if (isSwaggerFile) {
678
- warnings.push({
679
- type: WarningType.ConvertSwaggerToOpenAPI,
680
- content: ConstantString.ConvertSwaggerToOpenAPI,
563
+ validateSpecVersion() {
564
+ const result = { errors: [], warnings: [] };
565
+ if (this.spec.openapi >= "3.1.0") {
566
+ result.errors.push({
567
+ type: ErrorType.SpecVersionNotSupported,
568
+ content: Utils.format(ConstantString.SpecVersionNotSupported, this.spec.openapi),
569
+ data: this.spec.openapi,
681
570
  });
682
571
  }
683
- // Server validation
684
- const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
685
- errors.push(...serverErrors);
686
- // Remote reference not supported
687
- const refPaths = parser.$refs.paths();
688
- // refPaths [0] is the current spec file path
689
- if (refPaths.length > 1) {
690
- errors.push({
691
- type: ErrorType.RemoteRefNotSupported,
692
- content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
693
- data: refPaths,
694
- });
695
- }
696
- // No supported API
697
- const apiMap = Utils.listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
698
- if (Object.keys(apiMap).length === 0) {
699
- errors.push({
572
+ return result;
573
+ }
574
+ validateSpecServer() {
575
+ const result = { errors: [], warnings: [] };
576
+ const serverErrors = Utils.validateServer(this.spec, this.options);
577
+ result.errors.push(...serverErrors);
578
+ return result;
579
+ }
580
+ validateSpecNoSupportAPI() {
581
+ const result = { errors: [], warnings: [] };
582
+ const apiMap = this.listAPIs();
583
+ const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
584
+ if (validAPIs.length === 0) {
585
+ const data = [];
586
+ for (const key in apiMap) {
587
+ const { reason } = apiMap[key];
588
+ const apiInvalidReason = { api: key, reason: reason };
589
+ data.push(apiInvalidReason);
590
+ }
591
+ result.errors.push({
700
592
  type: ErrorType.NoSupportedApi,
701
593
  content: ConstantString.NoSupportedApi,
594
+ data,
702
595
  });
703
596
  }
597
+ return result;
598
+ }
599
+ validateSpecOperationId() {
600
+ const result = { errors: [], warnings: [] };
601
+ const apiMap = this.listAPIs();
704
602
  // OperationId missing
705
603
  const apisMissingOperationId = [];
706
604
  for (const key in apiMap) {
707
- const pathObjectItem = apiMap[key];
708
- if (!pathObjectItem.operationId) {
605
+ const { operation } = apiMap[key];
606
+ if (!operation.operationId) {
709
607
  apisMissingOperationId.push(key);
710
608
  }
711
609
  }
712
610
  if (apisMissingOperationId.length > 0) {
713
- warnings.push({
611
+ result.warnings.push({
714
612
  type: WarningType.OperationIdMissing,
715
613
  content: Utils.format(ConstantString.MissingOperationId, apisMissingOperationId.join(", ")),
716
614
  data: apisMissingOperationId,
717
615
  });
718
616
  }
719
- let status = ValidationStatus.Valid;
720
- if (warnings.length > 0 && errors.length === 0) {
721
- status = ValidationStatus.Warning;
617
+ return result;
618
+ }
619
+ validateMethodAndPath(method, path) {
620
+ const result = { isValid: true, reason: [] };
621
+ if (this.options.allowMethods && !this.options.allowMethods.includes(method)) {
622
+ result.isValid = false;
623
+ result.reason.push(ErrorType.MethodNotAllowed);
624
+ return result;
722
625
  }
723
- else if (errors.length > 0) {
724
- status = ValidationStatus.Error;
626
+ const pathObj = this.spec.paths[path];
627
+ if (!pathObj || !pathObj[method]) {
628
+ result.isValid = false;
629
+ result.reason.push(ErrorType.UrlPathNotExist);
630
+ return result;
725
631
  }
726
- return {
727
- status,
728
- warnings,
729
- errors,
632
+ return result;
633
+ }
634
+ validateResponse(method, path) {
635
+ const result = { isValid: true, reason: [] };
636
+ const operationObject = this.spec.paths[path][method];
637
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
638
+ // only support response body only contains “application/json” content type
639
+ if (multipleMediaType) {
640
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
641
+ }
642
+ else if (Object.keys(json).length === 0) {
643
+ // response body should not be empty
644
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
645
+ }
646
+ return result;
647
+ }
648
+ validateServer(method, path) {
649
+ const result = { isValid: true, reason: [] };
650
+ const serverObj = Utils.getServerObject(this.spec, method, path);
651
+ if (!serverObj) {
652
+ // should contain server URL
653
+ result.reason.push(ErrorType.NoServerInformation);
654
+ }
655
+ else {
656
+ // server url should be absolute url with https protocol
657
+ const serverValidateResult = Utils.checkServerUrl([serverObj]);
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: [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: [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: [],
730
699
  };
700
+ if (Object.keys(schema).length === 0) {
701
+ return paramResult;
702
+ }
703
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
704
+ const isCopilot = this.projectType === ProjectType.Copilot;
705
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
706
+ paramResult.isValid = false;
707
+ paramResult.reason = [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(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
739
+ }
740
+ }
741
+ return paramResult;
731
742
  }
732
- static format(str, ...args) {
733
- let index = 0;
734
- return str.replace(/%s/g, () => {
735
- const arg = args[index++];
736
- return arg !== undefined ? arg : "";
737
- });
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 === 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(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(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(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;
738
799
  }
739
- static getSafeRegistrationIdEnvName(authName) {
740
- if (!authName) {
741
- return "";
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
+ }
742
808
  }
743
- let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
744
- if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
745
- safeRegistrationIdEnvName = "PREFIX_" + safeRegistrationIdEnvName;
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 = ProjectType.Copilot;
818
+ this.options = options;
819
+ this.spec = spec;
820
+ }
821
+ validateSpec() {
822
+ const result = { errors: [], warnings: [] };
823
+ // validate spec version
824
+ let validationResult = this.validateSpecVersion();
825
+ result.errors.push(...validationResult.errors);
826
+ // validate spec server
827
+ validationResult = this.validateSpecServer();
828
+ result.errors.push(...validationResult.errors);
829
+ // validate no supported API
830
+ validationResult = this.validateSpecNoSupportAPI();
831
+ result.errors.push(...validationResult.errors);
832
+ // validate operationId missing
833
+ validationResult = this.validateSpecOperationId();
834
+ result.warnings.push(...validationResult.warnings);
835
+ return result;
836
+ }
837
+ validateAPI(method, path) {
838
+ const result = { isValid: true, reason: [] };
839
+ method = method.toLocaleLowerCase();
840
+ // validate method and path
841
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
842
+ if (!methodAndPathResult.isValid) {
843
+ return methodAndPathResult;
844
+ }
845
+ const operationObject = this.spec.paths[path][method];
846
+ // validate auth
847
+ const authCheckResult = this.validateAuth(method, path);
848
+ result.reason.push(...authCheckResult.reason);
849
+ // validate operationId
850
+ if (!this.options.allowMissingId && !operationObject.operationId) {
851
+ result.reason.push(ErrorType.MissingOperationId);
852
+ }
853
+ // validate server
854
+ const validateServerResult = this.validateServer(method, path);
855
+ result.reason.push(...validateServerResult.reason);
856
+ // validate response
857
+ const validateResponseResult = this.validateResponse(method, path);
858
+ result.reason.push(...validateResponseResult.reason);
859
+ // validate requestBody
860
+ const requestBody = operationObject.requestBody;
861
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
862
+ if (Utils.containMultipleMediaTypes(requestBody)) {
863
+ result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
864
+ }
865
+ if (requestJsonBody) {
866
+ const requestBodySchema = requestJsonBody.schema;
867
+ if (requestBodySchema.type !== "object") {
868
+ result.reason.push(ErrorType.PostBodySchemaIsNotJson);
869
+ }
870
+ const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
871
+ result.reason.push(...requestBodyParamResult.reason);
872
+ }
873
+ // validate parameters
874
+ const paramObject = operationObject.parameters;
875
+ const paramResult = this.checkParamSchema(paramObject);
876
+ result.reason.push(...paramResult.reason);
877
+ if (result.reason.length > 0) {
878
+ result.isValid = false;
879
+ }
880
+ return result;
881
+ }
882
+ }
883
+
884
+ // Copyright (c) Microsoft Corporation.
885
+ class SMEValidator extends Validator {
886
+ constructor(spec, options) {
887
+ super();
888
+ this.projectType = ProjectType.SME;
889
+ this.options = options;
890
+ this.spec = spec;
891
+ }
892
+ validateSpec() {
893
+ const result = { errors: [], warnings: [] };
894
+ // validate spec version
895
+ let validationResult = this.validateSpecVersion();
896
+ result.errors.push(...validationResult.errors);
897
+ // validate spec server
898
+ validationResult = this.validateSpecServer();
899
+ result.errors.push(...validationResult.errors);
900
+ // validate no supported API
901
+ validationResult = this.validateSpecNoSupportAPI();
902
+ result.errors.push(...validationResult.errors);
903
+ // validate operationId missing
904
+ if (this.options.allowMissingId) {
905
+ validationResult = this.validateSpecOperationId();
906
+ result.warnings.push(...validationResult.warnings);
907
+ }
908
+ return result;
909
+ }
910
+ validateAPI(method, path) {
911
+ const result = { isValid: true, reason: [] };
912
+ method = method.toLocaleLowerCase();
913
+ // validate method and path
914
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
915
+ if (!methodAndPathResult.isValid) {
916
+ return methodAndPathResult;
917
+ }
918
+ const operationObject = this.spec.paths[path][method];
919
+ // validate auth
920
+ const authCheckResult = this.validateAuth(method, path);
921
+ result.reason.push(...authCheckResult.reason);
922
+ // validate operationId
923
+ if (!this.options.allowMissingId && !operationObject.operationId) {
924
+ result.reason.push(ErrorType.MissingOperationId);
925
+ }
926
+ // validate server
927
+ const validateServerResult = this.validateServer(method, path);
928
+ result.reason.push(...validateServerResult.reason);
929
+ // validate response
930
+ const validateResponseResult = this.validateResponse(method, path);
931
+ result.reason.push(...validateResponseResult.reason);
932
+ let postBodyResult = {
933
+ requiredNum: 0,
934
+ optionalNum: 0,
935
+ isValid: true,
936
+ reason: [],
937
+ };
938
+ // validate requestBody
939
+ const requestBody = operationObject.requestBody;
940
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
941
+ if (Utils.containMultipleMediaTypes(requestBody)) {
942
+ result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
943
+ }
944
+ if (requestJsonBody) {
945
+ const requestBodySchema = requestJsonBody.schema;
946
+ postBodyResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
947
+ result.reason.push(...postBodyResult.reason);
948
+ }
949
+ // validate parameters
950
+ const paramObject = operationObject.parameters;
951
+ const paramResult = this.checkParamSchema(paramObject);
952
+ result.reason.push(...paramResult.reason);
953
+ // validate total parameters count
954
+ if (paramResult.isValid && postBodyResult.isValid) {
955
+ const paramCountResult = this.validateParamCount(postBodyResult, paramResult);
956
+ result.reason.push(...paramCountResult.reason);
957
+ }
958
+ if (result.reason.length > 0) {
959
+ result.isValid = false;
960
+ }
961
+ return result;
962
+ }
963
+ validateParamCount(postBodyResult, paramResult) {
964
+ const result = { isValid: true, reason: [] };
965
+ const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
966
+ const totalParams = totalRequiredParams + postBodyResult.optionalNum + paramResult.optionalNum;
967
+ if (totalRequiredParams > 1) {
968
+ if (!this.options.allowMultipleParameters ||
969
+ totalRequiredParams > SMEValidator.SMERequiredParamsMaxNum) {
970
+ result.reason.push(ErrorType.ExceededRequiredParamsLimit);
971
+ }
972
+ }
973
+ else if (totalParams === 0) {
974
+ result.reason.push(ErrorType.NoParameter);
975
+ }
976
+ return result;
977
+ }
978
+ }
979
+ SMEValidator.SMERequiredParamsMaxNum = 5;
980
+
981
+ // Copyright (c) Microsoft Corporation.
982
+ class TeamsAIValidator extends Validator {
983
+ constructor(spec, options) {
984
+ super();
985
+ this.projectType = ProjectType.TeamsAi;
986
+ this.options = options;
987
+ this.spec = spec;
988
+ }
989
+ validateSpec() {
990
+ const result = { errors: [], warnings: [] };
991
+ // validate spec server
992
+ let validationResult = this.validateSpecServer();
993
+ result.errors.push(...validationResult.errors);
994
+ // validate no supported API
995
+ validationResult = this.validateSpecNoSupportAPI();
996
+ result.errors.push(...validationResult.errors);
997
+ return result;
998
+ }
999
+ validateAPI(method, path) {
1000
+ const result = { isValid: true, reason: [] };
1001
+ method = method.toLocaleLowerCase();
1002
+ // validate method and path
1003
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
1004
+ if (!methodAndPathResult.isValid) {
1005
+ return methodAndPathResult;
1006
+ }
1007
+ const operationObject = this.spec.paths[path][method];
1008
+ // validate operationId
1009
+ if (!this.options.allowMissingId && !operationObject.operationId) {
1010
+ result.reason.push(ErrorType.MissingOperationId);
1011
+ }
1012
+ // validate server
1013
+ const validateServerResult = this.validateServer(method, path);
1014
+ result.reason.push(...validateServerResult.reason);
1015
+ if (result.reason.length > 0) {
1016
+ result.isValid = false;
1017
+ }
1018
+ return result;
1019
+ }
1020
+ }
1021
+
1022
+ class ValidatorFactory {
1023
+ static create(spec, options) {
1024
+ var _a;
1025
+ const type = (_a = options.projectType) !== null && _a !== void 0 ? _a : ProjectType.SME;
1026
+ switch (type) {
1027
+ case ProjectType.SME:
1028
+ return new SMEValidator(spec, options);
1029
+ case ProjectType.Copilot:
1030
+ return new CopilotValidator(spec, options);
1031
+ case ProjectType.TeamsAi:
1032
+ return new TeamsAIValidator(spec, options);
1033
+ default:
1034
+ throw new Error(`Invalid project type: ${type}`);
746
1035
  }
747
- return safeRegistrationIdEnvName;
748
1036
  }
749
1037
  }
750
1038
 
@@ -764,7 +1052,12 @@ class SpecParser {
764
1052
  allowSwagger: false,
765
1053
  allowAPIKeyAuth: false,
766
1054
  allowMultipleParameters: false,
1055
+ allowBearerTokenAuth: false,
767
1056
  allowOauth2: false,
1057
+ allowMethods: ["get", "post"],
1058
+ allowConversationStarters: false,
1059
+ allowResponseSemantics: false,
1060
+ projectType: ProjectType.SME,
768
1061
  };
769
1062
  this.pathOrSpec = pathOrDoc;
770
1063
  this.parser = new SwaggerParser();
@@ -780,11 +1073,7 @@ class SpecParser {
780
1073
  try {
781
1074
  try {
782
1075
  yield this.loadSpec();
783
- yield this.parser.validate(this.spec, {
784
- validate: {
785
- schema: false,
786
- },
787
- });
1076
+ yield this.parser.validate(this.spec);
788
1077
  }
789
1078
  catch (e) {
790
1079
  return {
@@ -793,16 +1082,46 @@ class SpecParser {
793
1082
  errors: [{ type: ErrorType.SpecNotValid, content: e.toString() }],
794
1083
  };
795
1084
  }
1085
+ const errors = [];
1086
+ const warnings = [];
796
1087
  if (!this.options.allowSwagger && this.isSwaggerFile) {
797
1088
  return {
798
1089
  status: ValidationStatus.Error,
799
1090
  warnings: [],
800
1091
  errors: [
801
- { type: ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported },
1092
+ {
1093
+ type: ErrorType.SwaggerNotSupported,
1094
+ content: ConstantString.SwaggerNotSupported,
1095
+ },
802
1096
  ],
803
1097
  };
804
1098
  }
805
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
1099
+ // Remote reference not supported
1100
+ const refPaths = this.parser.$refs.paths();
1101
+ // refPaths [0] is the current spec file path
1102
+ if (refPaths.length > 1) {
1103
+ errors.push({
1104
+ type: ErrorType.RemoteRefNotSupported,
1105
+ content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
1106
+ data: refPaths,
1107
+ });
1108
+ }
1109
+ const validator = this.getValidator(this.spec);
1110
+ const validationResult = validator.validateSpec();
1111
+ warnings.push(...validationResult.warnings);
1112
+ errors.push(...validationResult.errors);
1113
+ let status = ValidationStatus.Valid;
1114
+ if (warnings.length > 0 && errors.length === 0) {
1115
+ status = ValidationStatus.Warning;
1116
+ }
1117
+ else if (errors.length > 0) {
1118
+ status = ValidationStatus.Error;
1119
+ }
1120
+ return {
1121
+ status: status,
1122
+ warnings: warnings,
1123
+ errors: errors,
1124
+ };
806
1125
  }
807
1126
  catch (err) {
808
1127
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -813,17 +1132,20 @@ class SpecParser {
813
1132
  return __awaiter(this, void 0, void 0, function* () {
814
1133
  try {
815
1134
  yield this.loadSpec();
816
- const apiMap = this.getAllSupportedAPIs(this.spec);
1135
+ const apiMap = this.getAPIs(this.spec);
817
1136
  const apiInfos = [];
818
1137
  for (const key in apiMap) {
819
- const pathObjectItem = apiMap[key];
1138
+ const { operation, isValid } = apiMap[key];
1139
+ if (!isValid) {
1140
+ continue;
1141
+ }
820
1142
  const [method, path] = key.split(" ");
821
- const operationId = pathObjectItem.operationId;
1143
+ const operationId = operation.operationId;
822
1144
  // In Browser environment, this api is by default not support api without operationId
823
1145
  if (!operationId) {
824
1146
  continue;
825
1147
  }
826
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options.allowMultipleParameters);
1148
+ const command = Utils.parseApiInfo(operation, this.options);
827
1149
  const apiInfo = {
828
1150
  method: method,
829
1151
  path: path,
@@ -832,9 +1154,6 @@ class SpecParser {
832
1154
  parameters: command.parameters,
833
1155
  description: command.description,
834
1156
  };
835
- if (warning) {
836
- apiInfo.warning = warning;
837
- }
838
1157
  apiInfos.push(apiInfo);
839
1158
  }
840
1159
  return apiInfos;
@@ -865,6 +1184,19 @@ class SpecParser {
865
1184
  throw new Error("Method not implemented.");
866
1185
  });
867
1186
  }
1187
+ /**
1188
+ * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
1189
+ * @param manifestPath A file path of the Teams app manifest file to update.
1190
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
1191
+ * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
1192
+ * @param pluginFilePath File path of the api plugin file to generate.
1193
+ */
1194
+ // eslint-disable-next-line @typescript-eslint/require-await
1195
+ generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
1196
+ return __awaiter(this, void 0, void 0, function* () {
1197
+ throw new Error("Method not implemented.");
1198
+ });
1199
+ }
868
1200
  /**
869
1201
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
870
1202
  * @param manifestPath A file path of the Teams app manifest file to update.
@@ -874,7 +1206,7 @@ class SpecParser {
874
1206
  * @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
875
1207
  */
876
1208
  // eslint-disable-next-line @typescript-eslint/require-await
877
- generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal, isMe) {
1209
+ generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
878
1210
  return __awaiter(this, void 0, void 0, function* () {
879
1211
  throw new Error("Method not implemented.");
880
1212
  });
@@ -891,13 +1223,18 @@ class SpecParser {
891
1223
  }
892
1224
  });
893
1225
  }
894
- getAllSupportedAPIs(spec) {
895
- if (this.apiMap !== undefined) {
896
- return this.apiMap;
1226
+ getAPIs(spec) {
1227
+ const validator = this.getValidator(spec);
1228
+ const apiMap = validator.listAPIs();
1229
+ return apiMap;
1230
+ }
1231
+ getValidator(spec) {
1232
+ if (this.validator) {
1233
+ return this.validator;
897
1234
  }
898
- const result = Utils.listSupportedAPIs(spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
899
- this.apiMap = result;
900
- return result;
1235
+ const validator = ValidatorFactory.create(spec, this.options);
1236
+ this.validator = validator;
1237
+ return validator;
901
1238
  }
902
1239
  }
903
1240
 
@@ -905,7 +1242,7 @@ class SpecParser {
905
1242
  class AdaptiveCardGenerator {
906
1243
  static generateAdaptiveCard(operationItem) {
907
1244
  try {
908
- const json = Utils.getResponseJson(operationItem);
1245
+ const { json } = Utils.getResponseJson(operationItem);
909
1246
  let cardBody = [];
910
1247
  let schema = json.schema;
911
1248
  let jsonPath = "$";