@microsoft/m365-spec-parser 0.1.1-alpha.d1a09e202.0 → 0.1.1-alpha.d292dc740.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.
@@ -16,6 +16,7 @@ var ErrorType;
16
16
  ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
17
17
  ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
18
18
  ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
19
+ ErrorType["SpecVersionNotSupported"] = "spec-version-not-supported";
19
20
  ErrorType["ListFailed"] = "list-failed";
20
21
  ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
21
22
  ErrorType["FilterSpecFailed"] = "filter-spec-failed";
@@ -24,6 +25,21 @@ var ErrorType;
24
25
  ErrorType["GenerateFailed"] = "generate-failed";
25
26
  ErrorType["ValidateFailed"] = "validate-failed";
26
27
  ErrorType["GetSpecFailed"] = "get-spec-failed";
28
+ ErrorType["AuthTypeIsNotSupported"] = "auth-type-is-not-supported";
29
+ ErrorType["MissingOperationId"] = "missing-operation-id";
30
+ ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
31
+ ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
32
+ ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
33
+ ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
34
+ ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
35
+ ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
36
+ ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
37
+ ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
38
+ ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
39
+ ErrorType["NoParameter"] = "no-parameter";
40
+ ErrorType["NoAPIInfo"] = "no-api-info";
41
+ ErrorType["MethodNotAllowed"] = "method-not-allowed";
42
+ ErrorType["UrlPathNotExist"] = "url-path-not-exist";
27
43
  ErrorType["Cancelled"] = "cancelled";
28
44
  ErrorType["Unknown"] = "unknown";
29
45
  })(ErrorType || (ErrorType = {}));
@@ -71,7 +87,7 @@ ConstantString.RemoteRefNotSupported = "Remote reference is not supported: %s.";
71
87
  ConstantString.MissingOperationId = "Missing operationIds: %s.";
72
88
  ConstantString.NoSupportedApi = "No supported API is found in the OpenAPI description document: only GET and POST methods are supported, additionally, there can be at most one required parameter, and no auth is allowed.";
73
89
  ConstantString.AdditionalPropertiesNotSupported = "'additionalProperties' is not supported, and will be ignored.";
74
- ConstantString.SchemaNotSupported = "'oneOf', 'anyOf', and 'not' schema are not supported: %s.";
90
+ ConstantString.SchemaNotSupported = "'oneOf', 'allOf', 'anyOf', and 'not' schema are not supported: %s.";
75
91
  ConstantString.UnknownSchema = "Unknown schema: %s.";
76
92
  ConstantString.UrlProtocolNotSupported = "Server url is not correct: protocol %s is not supported, you should use https protocol instead.";
77
93
  ConstantString.RelativeServerUrlNotSupported = "Server url is not correct: relative server url is not supported.";
@@ -79,6 +95,7 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
79
95
  ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
80
96
  ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
81
97
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
98
+ ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
82
99
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
83
100
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
84
101
  ConstantString.WrappedCardVersion = "devPreview";
@@ -90,9 +107,14 @@ ConstantString.AdaptiveCardVersion = "1.5";
90
107
  ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
91
108
  ConstantString.AdaptiveCardType = "AdaptiveCard";
92
109
  ConstantString.TextBlockType = "TextBlock";
110
+ ConstantString.ImageType = "Image";
93
111
  ConstantString.ContainerType = "Container";
94
- ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
95
- ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
112
+ ConstantString.RegistrationIdPostfix = {
113
+ apiKey: "REGISTRATION_ID",
114
+ oauth2: "CONFIGURATION_ID",
115
+ http: "REGISTRATION_ID",
116
+ openIdConnect: "REGISTRATION_ID",
117
+ };
96
118
  ConstantString.ResponseCodeFor20X = [
97
119
  "200",
98
120
  "201",
@@ -151,9 +173,11 @@ ConstantString.ShortDescriptionMaxLens = 80;
151
173
  ConstantString.FullDescriptionMaxLens = 4000;
152
174
  ConstantString.CommandDescriptionMaxLens = 128;
153
175
  ConstantString.ParameterDescriptionMaxLens = 128;
176
+ ConstantString.ConversationStarterMaxLens = 50;
154
177
  ConstantString.CommandTitleMaxLens = 32;
155
178
  ConstantString.ParameterTitleMaxLens = 32;
156
- ConstantString.SMERequiredParamsMaxNum = 5;
179
+ ConstantString.SMERequiredParamsMaxNum = 5;
180
+ ConstantString.DefaultPluginId = "plugin_1";
157
181
 
158
182
  // Copyright (c) Microsoft Corporation.
159
183
  class Utils {
@@ -168,221 +192,9 @@ class Utils {
168
192
  }
169
193
  return false;
170
194
  }
171
- static checkParameters(paramObject, isCopilot) {
172
- const paramResult = {
173
- requiredNum: 0,
174
- optionalNum: 0,
175
- isValid: true,
176
- };
177
- if (!paramObject) {
178
- return paramResult;
179
- }
180
- for (let i = 0; i < paramObject.length; i++) {
181
- const param = paramObject[i];
182
- const schema = param.schema;
183
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
184
- paramResult.isValid = false;
185
- continue;
186
- }
187
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
188
- if (isCopilot) {
189
- if (isRequiredWithoutDefault) {
190
- paramResult.requiredNum = paramResult.requiredNum + 1;
191
- }
192
- else {
193
- paramResult.optionalNum = paramResult.optionalNum + 1;
194
- }
195
- continue;
196
- }
197
- if (param.in === "header" || param.in === "cookie") {
198
- if (isRequiredWithoutDefault) {
199
- paramResult.isValid = false;
200
- }
201
- continue;
202
- }
203
- if (schema.type !== "boolean" &&
204
- schema.type !== "string" &&
205
- schema.type !== "number" &&
206
- schema.type !== "integer") {
207
- if (isRequiredWithoutDefault) {
208
- paramResult.isValid = false;
209
- }
210
- continue;
211
- }
212
- if (param.in === "query" || param.in === "path") {
213
- if (isRequiredWithoutDefault) {
214
- paramResult.requiredNum = paramResult.requiredNum + 1;
215
- }
216
- else {
217
- paramResult.optionalNum = paramResult.optionalNum + 1;
218
- }
219
- }
220
- }
221
- return paramResult;
222
- }
223
- static checkPostBody(schema, isRequired = false, isCopilot = false) {
224
- var _a;
225
- const paramResult = {
226
- requiredNum: 0,
227
- optionalNum: 0,
228
- isValid: true,
229
- };
230
- if (Object.keys(schema).length === 0) {
231
- return paramResult;
232
- }
233
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
234
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
235
- paramResult.isValid = false;
236
- return paramResult;
237
- }
238
- if (schema.type === "string" ||
239
- schema.type === "integer" ||
240
- schema.type === "boolean" ||
241
- schema.type === "number") {
242
- if (isRequiredWithoutDefault) {
243
- paramResult.requiredNum = paramResult.requiredNum + 1;
244
- }
245
- else {
246
- paramResult.optionalNum = paramResult.optionalNum + 1;
247
- }
248
- }
249
- else if (schema.type === "object") {
250
- const { properties } = schema;
251
- for (const property in properties) {
252
- let isRequired = false;
253
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
254
- isRequired = true;
255
- }
256
- const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
257
- paramResult.requiredNum += result.requiredNum;
258
- paramResult.optionalNum += result.optionalNum;
259
- paramResult.isValid = paramResult.isValid && result.isValid;
260
- }
261
- }
262
- else {
263
- if (isRequiredWithoutDefault && !isCopilot) {
264
- paramResult.isValid = false;
265
- }
266
- }
267
- return paramResult;
268
- }
269
195
  static containMultipleMediaTypes(bodyObject) {
270
196
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
271
197
  }
272
- /**
273
- * Checks if the given API is supported.
274
- * @param {string} method - The HTTP method of the API.
275
- * @param {string} path - The path of the API.
276
- * @param {OpenAPIV3.Document} spec - The OpenAPI specification document.
277
- * @returns {boolean} - Returns true if the API is supported, false otherwise.
278
- * @description The following APIs are supported:
279
- * 1. only support Get/Post operation without auth property
280
- * 2. parameter inside query or path only support string, number, boolean and integer
281
- * 3. parameter inside post body only support string, number, boolean, integer and object
282
- * 4. request body + required parameters <= 1
283
- * 5. response body should be “application/json” and not empty, and response code should be 20X
284
- * 6. only support request body with “application/json” content type
285
- */
286
- static isSupportedApi(method, path, spec, options) {
287
- var _a;
288
- const pathObj = spec.paths[path];
289
- method = method.toLocaleLowerCase();
290
- if (pathObj) {
291
- if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
292
- const securities = pathObj[method].security;
293
- const isTeamsAi = options.projectType === ProjectType.TeamsAi;
294
- const isCopilot = options.projectType === ProjectType.Copilot;
295
- // Teams AI project doesn't care about auth, it will use authProvider for user to implement
296
- if (!isTeamsAi) {
297
- const authArray = Utils.getAuthArray(securities, spec);
298
- if (!Utils.isSupportedAuth(authArray, options)) {
299
- return false;
300
- }
301
- }
302
- const operationObject = pathObj[method];
303
- if (!options.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
- if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
310
- return false;
311
- }
312
- const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
313
- if (Object.keys(responseJson).length === 0) {
314
- return false;
315
- }
316
- // Teams AI project doesn't care about request parameters/body
317
- if (isTeamsAi) {
318
- return true;
319
- }
320
- let requestBodyParamResult = {
321
- requiredNum: 0,
322
- optionalNum: 0,
323
- isValid: true,
324
- };
325
- if (requestJsonBody) {
326
- const requestBodySchema = requestJsonBody.schema;
327
- if (isCopilot && requestBodySchema.type !== "object") {
328
- return false;
329
- }
330
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
331
- }
332
- if (!requestBodyParamResult.isValid) {
333
- return false;
334
- }
335
- const paramResult = Utils.checkParameters(paramObject, isCopilot);
336
- if (!paramResult.isValid) {
337
- return false;
338
- }
339
- // Copilot support arbitrary parameters
340
- if (isCopilot) {
341
- return true;
342
- }
343
- if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
344
- if (options.allowMultipleParameters &&
345
- requestBodyParamResult.requiredNum + paramResult.requiredNum <=
346
- ConstantString.SMERequiredParamsMaxNum) {
347
- return true;
348
- }
349
- return false;
350
- }
351
- else if (requestBodyParamResult.requiredNum +
352
- requestBodyParamResult.optionalNum +
353
- paramResult.requiredNum +
354
- paramResult.optionalNum ===
355
- 0) {
356
- return false;
357
- }
358
- else {
359
- return true;
360
- }
361
- }
362
- }
363
- return false;
364
- }
365
- static isSupportedAuth(authSchemeArray, options) {
366
- if (authSchemeArray.length === 0) {
367
- return true;
368
- }
369
- if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
370
- // Currently we don't support multiple auth in one operation
371
- if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
372
- return false;
373
- }
374
- for (const auths of authSchemeArray) {
375
- if (auths.length === 1) {
376
- if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
377
- (options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
378
- (options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
379
- return true;
380
- }
381
- }
382
- }
383
- }
384
- return false;
385
- }
386
198
  static isBearerTokenAuth(authScheme) {
387
199
  return authScheme.type === "http" && authScheme.scheme === "bearer";
388
200
  }
@@ -390,18 +202,18 @@ class Utils {
390
202
  return authScheme.type === "apiKey";
391
203
  }
392
204
  static isOAuthWithAuthCodeFlow(authScheme) {
393
- if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
394
- return true;
395
- }
396
- return false;
205
+ return !!(authScheme.type === "oauth2" &&
206
+ authScheme.flows &&
207
+ authScheme.flows.authorizationCode);
397
208
  }
398
209
  static getAuthArray(securities, spec) {
399
210
  var _a;
400
211
  const result = [];
401
212
  const securitySchemas = (_a = spec.components) === null || _a === void 0 ? void 0 : _a.securitySchemes;
402
- if (securities && securitySchemas) {
403
- for (let i = 0; i < securities.length; i++) {
404
- const security = securities[i];
213
+ const securitiesArr = securities !== null && securities !== void 0 ? securities : spec.security;
214
+ if (securitiesArr && securitySchemas) {
215
+ for (let i = 0; i < securitiesArr.length; i++) {
216
+ const security = securitiesArr[i];
405
217
  const authArray = [];
406
218
  for (const name in security) {
407
219
  const auth = securitySchemas[name];
@@ -418,17 +230,39 @@ class Utils {
418
230
  result.sort((a, b) => a[0].name.localeCompare(b[0].name));
419
231
  return result;
420
232
  }
233
+ static getAuthInfo(spec) {
234
+ let authInfo = undefined;
235
+ for (const url in spec.paths) {
236
+ for (const method in spec.paths[url]) {
237
+ const operation = spec.paths[url][method];
238
+ const authArray = Utils.getAuthArray(operation.security, spec);
239
+ if (authArray && authArray.length > 0) {
240
+ const currentAuth = authArray[0][0];
241
+ if (!authInfo) {
242
+ authInfo = authArray[0][0];
243
+ }
244
+ else if (authInfo.name !== currentAuth.name) {
245
+ throw new SpecParserError(ConstantString.MultipleAuthNotSupported, ErrorType.MultipleAuthNotSupported);
246
+ }
247
+ }
248
+ }
249
+ }
250
+ return authInfo;
251
+ }
421
252
  static updateFirstLetter(str) {
422
253
  return str.charAt(0).toUpperCase() + str.slice(1);
423
254
  }
424
- static getResponseJson(operationObject, isTeamsAiProject = false) {
255
+ static getResponseJson(operationObject) {
425
256
  var _a, _b;
426
257
  let json = {};
258
+ let multipleMediaType = false;
427
259
  for (const code of ConstantString.ResponseCodeFor20X) {
428
260
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
429
261
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
262
+ multipleMediaType = false;
430
263
  json = responseObject.content["application/json"];
431
- if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
264
+ if (Utils.containMultipleMediaTypes(responseObject)) {
265
+ multipleMediaType = true;
432
266
  json = {};
433
267
  }
434
268
  else {
@@ -436,7 +270,7 @@ class Utils {
436
270
  }
437
271
  }
438
272
  }
439
- return json;
273
+ return { json, multipleMediaType };
440
274
  }
441
275
  static convertPathToCamelCase(path) {
442
276
  const pathSegments = path.split(/[./{]/);
@@ -456,10 +290,10 @@ class Utils {
456
290
  return undefined;
457
291
  }
458
292
  }
459
- static resolveServerUrl(url) {
293
+ static resolveEnv(str) {
460
294
  const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
461
- let matches = placeHolderReg.exec(url);
462
- let newUrl = url;
295
+ let matches = placeHolderReg.exec(str);
296
+ let newStr = str;
463
297
  while (matches != null) {
464
298
  const envVar = matches[1];
465
299
  const envVal = process.env[envVar];
@@ -467,17 +301,17 @@ class Utils {
467
301
  throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
468
302
  }
469
303
  else {
470
- newUrl = newUrl.replace(matches[0], envVal);
304
+ newStr = newStr.replace(matches[0], envVal);
471
305
  }
472
- matches = placeHolderReg.exec(url);
306
+ matches = placeHolderReg.exec(str);
473
307
  }
474
- return newUrl;
308
+ return newStr;
475
309
  }
476
310
  static checkServerUrl(servers) {
477
311
  const errors = [];
478
312
  let serverUrl;
479
313
  try {
480
- serverUrl = Utils.resolveServerUrl(servers[0].url);
314
+ serverUrl = Utils.resolveEnv(servers[0].url);
481
315
  }
482
316
  catch (err) {
483
317
  errors.push({
@@ -508,6 +342,7 @@ class Utils {
508
342
  return errors;
509
343
  }
510
344
  static validateServer(spec, options) {
345
+ var _a;
511
346
  const errors = [];
512
347
  let hasTopLevelServers = false;
513
348
  let hasPathLevelServers = false;
@@ -528,7 +363,7 @@ class Utils {
528
363
  }
529
364
  for (const method in methods) {
530
365
  const operationObject = methods[method];
531
- if (Utils.isSupportedApi(method, path, spec, options)) {
366
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
532
367
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
533
368
  hasOperationLevelServers = true;
534
369
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -571,6 +406,7 @@ class Utils {
571
406
  Utils.updateParameterWithInputType(schema, parameter);
572
407
  }
573
408
  if (isRequired && schema.default === undefined) {
409
+ parameter.isRequired = true;
574
410
  requiredParams.push(parameter);
575
411
  }
576
412
  else {
@@ -634,6 +470,7 @@ class Utils {
634
470
  }
635
471
  if (param.in !== "header" && param.in !== "cookie") {
636
472
  if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
473
+ parameter.isRequired = true;
637
474
  requiredParams.push(parameter);
638
475
  }
639
476
  else {
@@ -653,13 +490,7 @@ class Utils {
653
490
  }
654
491
  }
655
492
  const operationId = operationItem.operationId;
656
- const parameters = [];
657
- if (requiredParams.length !== 0) {
658
- parameters.push(...requiredParams);
659
- }
660
- else {
661
- parameters.push(optionalParams[0]);
662
- }
493
+ const parameters = [...requiredParams, ...optionalParams];
663
494
  const command = {
664
495
  context: ["compose"],
665
496
  type: "query",
@@ -668,104 +499,534 @@ class Utils {
668
499
  parameters: parameters,
669
500
  description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
670
501
  };
671
- let warning = undefined;
672
- if (requiredParams.length === 0 && optionalParams.length > 1) {
673
- warning = {
674
- type: WarningType.OperationOnlyContainsOptionalParam,
675
- content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, operationId),
676
- data: operationId,
677
- };
502
+ return command;
503
+ }
504
+ static format(str, ...args) {
505
+ let index = 0;
506
+ return str.replace(/%s/g, () => {
507
+ const arg = args[index++];
508
+ return arg !== undefined ? arg : "";
509
+ });
510
+ }
511
+ static getSafeRegistrationIdEnvName(authName) {
512
+ if (!authName) {
513
+ return "";
514
+ }
515
+ let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
516
+ if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
517
+ safeRegistrationIdEnvName = "PREFIX_" + safeRegistrationIdEnvName;
678
518
  }
679
- return [command, warning];
519
+ return safeRegistrationIdEnvName;
680
520
  }
681
- static listSupportedAPIs(spec, options) {
682
- const paths = spec.paths;
521
+ static getServerObject(spec, method, path) {
522
+ const pathObj = spec.paths[path];
523
+ const operationObject = pathObj[method];
524
+ const rootServer = spec.servers && spec.servers[0];
525
+ const methodServer = spec.paths[path].servers && spec.paths[path].servers[0];
526
+ const operationServer = operationObject.servers && operationObject.servers[0];
527
+ const serverUrl = operationServer || methodServer || rootServer;
528
+ return serverUrl;
529
+ }
530
+ }
531
+
532
+ // Copyright (c) Microsoft Corporation.
533
+ class Validator {
534
+ listAPIs() {
535
+ var _a;
536
+ if (this.apiMap) {
537
+ return this.apiMap;
538
+ }
539
+ const paths = this.spec.paths;
683
540
  const result = {};
684
541
  for (const path in paths) {
685
542
  const methods = paths[path];
686
543
  for (const method in methods) {
687
- if (Utils.isSupportedApi(method, path, spec, options)) {
688
- const operationObject = methods[method];
689
- result[`${method.toUpperCase()} ${path}`] = operationObject;
544
+ const operationObject = methods[method];
545
+ if (((_a = this.options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
546
+ const validateResult = this.validateAPI(method, path);
547
+ result[`${method.toUpperCase()} ${path}`] = {
548
+ operation: operationObject,
549
+ isValid: validateResult.isValid,
550
+ reason: validateResult.reason,
551
+ };
690
552
  }
691
553
  }
692
554
  }
555
+ this.apiMap = result;
693
556
  return result;
694
557
  }
695
- static validateSpec(spec, parser, isSwaggerFile, options) {
696
- const errors = [];
697
- const warnings = [];
698
- if (isSwaggerFile) {
699
- warnings.push({
700
- type: WarningType.ConvertSwaggerToOpenAPI,
701
- content: ConstantString.ConvertSwaggerToOpenAPI,
702
- });
703
- }
704
- // Server validation
705
- const serverErrors = Utils.validateServer(spec, options);
706
- errors.push(...serverErrors);
707
- // Remote reference not supported
708
- const refPaths = parser.$refs.paths();
709
- // refPaths [0] is the current spec file path
710
- if (refPaths.length > 1) {
711
- errors.push({
712
- type: ErrorType.RemoteRefNotSupported,
713
- content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
714
- data: refPaths,
558
+ validateSpecVersion() {
559
+ const result = { errors: [], warnings: [] };
560
+ if (this.spec.openapi >= "3.1.0") {
561
+ result.errors.push({
562
+ type: ErrorType.SpecVersionNotSupported,
563
+ content: Utils.format(ConstantString.SpecVersionNotSupported, this.spec.openapi),
564
+ data: this.spec.openapi,
715
565
  });
716
566
  }
717
- // No supported API
718
- const apiMap = Utils.listSupportedAPIs(spec, options);
719
- if (Object.keys(apiMap).length === 0) {
720
- errors.push({
567
+ return result;
568
+ }
569
+ validateSpecServer() {
570
+ const result = { errors: [], warnings: [] };
571
+ const serverErrors = Utils.validateServer(this.spec, this.options);
572
+ result.errors.push(...serverErrors);
573
+ return result;
574
+ }
575
+ validateSpecNoSupportAPI() {
576
+ const result = { errors: [], warnings: [] };
577
+ const apiMap = this.listAPIs();
578
+ const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
579
+ if (validAPIs.length === 0) {
580
+ const data = [];
581
+ for (const key in apiMap) {
582
+ const { reason } = apiMap[key];
583
+ const apiInvalidReason = { api: key, reason: reason };
584
+ data.push(apiInvalidReason);
585
+ }
586
+ result.errors.push({
721
587
  type: ErrorType.NoSupportedApi,
722
588
  content: ConstantString.NoSupportedApi,
589
+ data,
723
590
  });
724
591
  }
592
+ return result;
593
+ }
594
+ validateSpecOperationId() {
595
+ const result = { errors: [], warnings: [] };
596
+ const apiMap = this.listAPIs();
725
597
  // OperationId missing
726
598
  const apisMissingOperationId = [];
727
599
  for (const key in apiMap) {
728
- const pathObjectItem = apiMap[key];
729
- if (!pathObjectItem.operationId) {
600
+ const { operation } = apiMap[key];
601
+ if (!operation.operationId) {
730
602
  apisMissingOperationId.push(key);
731
603
  }
732
604
  }
733
605
  if (apisMissingOperationId.length > 0) {
734
- warnings.push({
606
+ result.warnings.push({
735
607
  type: WarningType.OperationIdMissing,
736
608
  content: Utils.format(ConstantString.MissingOperationId, apisMissingOperationId.join(", ")),
737
609
  data: apisMissingOperationId,
738
610
  });
739
611
  }
740
- let status = ValidationStatus.Valid;
741
- if (warnings.length > 0 && errors.length === 0) {
742
- status = ValidationStatus.Warning;
612
+ return result;
613
+ }
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(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(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
+ if (this.options.projectType === ProjectType.SME) {
634
+ // only support response body only contains “application/json” content type
635
+ if (multipleMediaType) {
636
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
637
+ }
638
+ else if (Object.keys(json).length === 0) {
639
+ // response body should not be empty
640
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
641
+ }
642
+ }
643
+ return result;
644
+ }
645
+ validateServer(method, path) {
646
+ const result = { isValid: true, reason: [] };
647
+ const serverObj = Utils.getServerObject(this.spec, method, path);
648
+ if (!serverObj) {
649
+ // should contain server URL
650
+ result.reason.push(ErrorType.NoServerInformation);
651
+ }
652
+ else {
653
+ // server url should be absolute url with https protocol
654
+ const serverValidateResult = Utils.checkServerUrl([serverObj]);
655
+ result.reason.push(...serverValidateResult.map((item) => item.type));
656
+ }
657
+ return result;
658
+ }
659
+ validateAuth(method, path) {
660
+ const pathObj = this.spec.paths[path];
661
+ const operationObject = pathObj[method];
662
+ const securities = operationObject.security;
663
+ const authSchemeArray = Utils.getAuthArray(securities, this.spec);
664
+ if (authSchemeArray.length === 0) {
665
+ return { isValid: true, reason: [] };
743
666
  }
744
- else if (errors.length > 0) {
745
- status = ValidationStatus.Error;
667
+ if (this.options.allowAPIKeyAuth ||
668
+ this.options.allowOauth2 ||
669
+ this.options.allowBearerTokenAuth) {
670
+ // Currently we don't support multiple auth in one operation
671
+ if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
672
+ return {
673
+ isValid: false,
674
+ reason: [ErrorType.MultipleAuthNotSupported],
675
+ };
676
+ }
677
+ for (const auths of authSchemeArray) {
678
+ if (auths.length === 1) {
679
+ if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
680
+ (this.options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
681
+ (this.options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
682
+ return { isValid: true, reason: [] };
683
+ }
684
+ }
685
+ }
746
686
  }
747
- return {
748
- status,
749
- warnings,
750
- errors,
687
+ return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
688
+ }
689
+ checkPostBodySchema(schema, isRequired = false) {
690
+ var _a;
691
+ const paramResult = {
692
+ requiredNum: 0,
693
+ optionalNum: 0,
694
+ isValid: true,
695
+ reason: [],
751
696
  };
697
+ if (Object.keys(schema).length === 0) {
698
+ return paramResult;
699
+ }
700
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
701
+ const isCopilot = this.projectType === ProjectType.Copilot;
702
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
703
+ paramResult.isValid = false;
704
+ paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
705
+ return paramResult;
706
+ }
707
+ if (schema.type === "string" ||
708
+ schema.type === "integer" ||
709
+ schema.type === "boolean" ||
710
+ schema.type === "number") {
711
+ if (isRequiredWithoutDefault) {
712
+ paramResult.requiredNum = paramResult.requiredNum + 1;
713
+ }
714
+ else {
715
+ paramResult.optionalNum = paramResult.optionalNum + 1;
716
+ }
717
+ }
718
+ else if (schema.type === "object") {
719
+ const { properties } = schema;
720
+ for (const property in properties) {
721
+ let isRequired = false;
722
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
723
+ isRequired = true;
724
+ }
725
+ const result = this.checkPostBodySchema(properties[property], isRequired);
726
+ paramResult.requiredNum += result.requiredNum;
727
+ paramResult.optionalNum += result.optionalNum;
728
+ paramResult.isValid = paramResult.isValid && result.isValid;
729
+ paramResult.reason.push(...result.reason);
730
+ }
731
+ }
732
+ else {
733
+ if (isRequiredWithoutDefault && !isCopilot) {
734
+ paramResult.isValid = false;
735
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
736
+ }
737
+ }
738
+ return paramResult;
752
739
  }
753
- static format(str, ...args) {
754
- let index = 0;
755
- return str.replace(/%s/g, () => {
756
- const arg = args[index++];
757
- return arg !== undefined ? arg : "";
758
- });
740
+ checkParamSchema(paramObject) {
741
+ const paramResult = {
742
+ requiredNum: 0,
743
+ optionalNum: 0,
744
+ isValid: true,
745
+ reason: [],
746
+ };
747
+ if (!paramObject) {
748
+ return paramResult;
749
+ }
750
+ const isCopilot = this.projectType === ProjectType.Copilot;
751
+ for (let i = 0; i < paramObject.length; i++) {
752
+ const param = paramObject[i];
753
+ const schema = param.schema;
754
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
755
+ paramResult.isValid = false;
756
+ paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
757
+ continue;
758
+ }
759
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
760
+ if (isCopilot) {
761
+ if (isRequiredWithoutDefault) {
762
+ paramResult.requiredNum = paramResult.requiredNum + 1;
763
+ }
764
+ else {
765
+ paramResult.optionalNum = paramResult.optionalNum + 1;
766
+ }
767
+ continue;
768
+ }
769
+ if (param.in === "header" || param.in === "cookie") {
770
+ if (isRequiredWithoutDefault) {
771
+ paramResult.isValid = false;
772
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
773
+ }
774
+ continue;
775
+ }
776
+ if (schema.type !== "boolean" &&
777
+ schema.type !== "string" &&
778
+ schema.type !== "number" &&
779
+ schema.type !== "integer") {
780
+ if (isRequiredWithoutDefault) {
781
+ paramResult.isValid = false;
782
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
783
+ }
784
+ continue;
785
+ }
786
+ if (param.in === "query" || param.in === "path") {
787
+ if (isRequiredWithoutDefault) {
788
+ paramResult.requiredNum = paramResult.requiredNum + 1;
789
+ }
790
+ else {
791
+ paramResult.optionalNum = paramResult.optionalNum + 1;
792
+ }
793
+ }
794
+ }
795
+ return paramResult;
759
796
  }
760
- static getSafeRegistrationIdEnvName(authName) {
761
- if (!authName) {
762
- return "";
797
+ hasNestedObjectInSchema(schema) {
798
+ if (schema.type === "object") {
799
+ for (const property in schema.properties) {
800
+ const nestedSchema = schema.properties[property];
801
+ if (nestedSchema.type === "object") {
802
+ return true;
803
+ }
804
+ }
763
805
  }
764
- let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
765
- if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
766
- safeRegistrationIdEnvName = "PREFIX_" + safeRegistrationIdEnvName;
806
+ return false;
807
+ }
808
+ }
809
+
810
+ // Copyright (c) Microsoft Corporation.
811
+ class CopilotValidator extends Validator {
812
+ constructor(spec, options) {
813
+ super();
814
+ this.projectType = ProjectType.Copilot;
815
+ this.options = options;
816
+ this.spec = spec;
817
+ }
818
+ validateSpec() {
819
+ const result = { errors: [], warnings: [] };
820
+ // validate spec version
821
+ let validationResult = this.validateSpecVersion();
822
+ result.errors.push(...validationResult.errors);
823
+ // validate spec server
824
+ validationResult = this.validateSpecServer();
825
+ result.errors.push(...validationResult.errors);
826
+ // validate no supported API
827
+ validationResult = this.validateSpecNoSupportAPI();
828
+ result.errors.push(...validationResult.errors);
829
+ // validate operationId missing
830
+ validationResult = this.validateSpecOperationId();
831
+ result.warnings.push(...validationResult.warnings);
832
+ return result;
833
+ }
834
+ validateAPI(method, path) {
835
+ const result = { isValid: true, reason: [] };
836
+ method = method.toLocaleLowerCase();
837
+ // validate method and path
838
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
839
+ if (!methodAndPathResult.isValid) {
840
+ return methodAndPathResult;
841
+ }
842
+ const operationObject = this.spec.paths[path][method];
843
+ // validate auth
844
+ const authCheckResult = this.validateAuth(method, path);
845
+ result.reason.push(...authCheckResult.reason);
846
+ // validate operationId
847
+ if (!this.options.allowMissingId && !operationObject.operationId) {
848
+ result.reason.push(ErrorType.MissingOperationId);
849
+ }
850
+ // validate server
851
+ const validateServerResult = this.validateServer(method, path);
852
+ result.reason.push(...validateServerResult.reason);
853
+ // validate response
854
+ const validateResponseResult = this.validateResponse(method, path);
855
+ result.reason.push(...validateResponseResult.reason);
856
+ // validate requestBody
857
+ const requestBody = operationObject.requestBody;
858
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
859
+ if (requestJsonBody) {
860
+ const requestBodySchema = requestJsonBody.schema;
861
+ if (requestBodySchema.type !== "object") {
862
+ result.reason.push(ErrorType.PostBodySchemaIsNotJson);
863
+ }
864
+ const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
865
+ result.reason.push(...requestBodyParamResult.reason);
866
+ }
867
+ // validate parameters
868
+ const paramObject = operationObject.parameters;
869
+ const paramResult = this.checkParamSchema(paramObject);
870
+ result.reason.push(...paramResult.reason);
871
+ if (result.reason.length > 0) {
872
+ result.isValid = false;
873
+ }
874
+ return result;
875
+ }
876
+ }
877
+
878
+ // Copyright (c) Microsoft Corporation.
879
+ class SMEValidator extends Validator {
880
+ constructor(spec, options) {
881
+ super();
882
+ this.projectType = ProjectType.SME;
883
+ this.options = options;
884
+ this.spec = spec;
885
+ }
886
+ validateSpec() {
887
+ const result = { errors: [], warnings: [] };
888
+ // validate spec version
889
+ let validationResult = this.validateSpecVersion();
890
+ result.errors.push(...validationResult.errors);
891
+ // validate spec server
892
+ validationResult = this.validateSpecServer();
893
+ result.errors.push(...validationResult.errors);
894
+ // validate no supported API
895
+ validationResult = this.validateSpecNoSupportAPI();
896
+ result.errors.push(...validationResult.errors);
897
+ // validate operationId missing
898
+ if (this.options.allowMissingId) {
899
+ validationResult = this.validateSpecOperationId();
900
+ result.warnings.push(...validationResult.warnings);
901
+ }
902
+ return result;
903
+ }
904
+ validateAPI(method, path) {
905
+ const result = { isValid: true, reason: [] };
906
+ method = method.toLocaleLowerCase();
907
+ // validate method and path
908
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
909
+ if (!methodAndPathResult.isValid) {
910
+ return methodAndPathResult;
911
+ }
912
+ const operationObject = this.spec.paths[path][method];
913
+ // validate auth
914
+ const authCheckResult = this.validateAuth(method, path);
915
+ result.reason.push(...authCheckResult.reason);
916
+ // validate operationId
917
+ if (!this.options.allowMissingId && !operationObject.operationId) {
918
+ result.reason.push(ErrorType.MissingOperationId);
919
+ }
920
+ // validate server
921
+ const validateServerResult = this.validateServer(method, path);
922
+ result.reason.push(...validateServerResult.reason);
923
+ // validate response
924
+ const validateResponseResult = this.validateResponse(method, path);
925
+ result.reason.push(...validateResponseResult.reason);
926
+ let postBodyResult = {
927
+ requiredNum: 0,
928
+ optionalNum: 0,
929
+ isValid: true,
930
+ reason: [],
931
+ };
932
+ // validate requestBody
933
+ const requestBody = operationObject.requestBody;
934
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
935
+ if (Utils.containMultipleMediaTypes(requestBody)) {
936
+ result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
937
+ }
938
+ if (requestJsonBody) {
939
+ const requestBodySchema = requestJsonBody.schema;
940
+ postBodyResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
941
+ result.reason.push(...postBodyResult.reason);
942
+ }
943
+ // validate parameters
944
+ const paramObject = operationObject.parameters;
945
+ const paramResult = this.checkParamSchema(paramObject);
946
+ result.reason.push(...paramResult.reason);
947
+ // validate total parameters count
948
+ if (paramResult.isValid && postBodyResult.isValid) {
949
+ const paramCountResult = this.validateParamCount(postBodyResult, paramResult);
950
+ result.reason.push(...paramCountResult.reason);
951
+ }
952
+ if (result.reason.length > 0) {
953
+ result.isValid = false;
954
+ }
955
+ return result;
956
+ }
957
+ validateParamCount(postBodyResult, paramResult) {
958
+ const result = { isValid: true, reason: [] };
959
+ const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
960
+ const totalParams = totalRequiredParams + postBodyResult.optionalNum + paramResult.optionalNum;
961
+ if (totalRequiredParams > 1) {
962
+ if (!this.options.allowMultipleParameters ||
963
+ totalRequiredParams > SMEValidator.SMERequiredParamsMaxNum) {
964
+ result.reason.push(ErrorType.ExceededRequiredParamsLimit);
965
+ }
966
+ }
967
+ else if (totalParams === 0) {
968
+ result.reason.push(ErrorType.NoParameter);
969
+ }
970
+ return result;
971
+ }
972
+ }
973
+ SMEValidator.SMERequiredParamsMaxNum = 5;
974
+
975
+ // Copyright (c) Microsoft Corporation.
976
+ class TeamsAIValidator extends Validator {
977
+ constructor(spec, options) {
978
+ super();
979
+ this.projectType = ProjectType.TeamsAi;
980
+ this.options = options;
981
+ this.spec = spec;
982
+ }
983
+ validateSpec() {
984
+ const result = { errors: [], warnings: [] };
985
+ // validate spec server
986
+ let validationResult = this.validateSpecServer();
987
+ result.errors.push(...validationResult.errors);
988
+ // validate no supported API
989
+ validationResult = this.validateSpecNoSupportAPI();
990
+ result.errors.push(...validationResult.errors);
991
+ return result;
992
+ }
993
+ validateAPI(method, path) {
994
+ const result = { isValid: true, reason: [] };
995
+ method = method.toLocaleLowerCase();
996
+ // validate method and path
997
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
998
+ if (!methodAndPathResult.isValid) {
999
+ return methodAndPathResult;
1000
+ }
1001
+ const operationObject = this.spec.paths[path][method];
1002
+ // validate operationId
1003
+ if (!this.options.allowMissingId && !operationObject.operationId) {
1004
+ result.reason.push(ErrorType.MissingOperationId);
1005
+ }
1006
+ // validate server
1007
+ const validateServerResult = this.validateServer(method, path);
1008
+ result.reason.push(...validateServerResult.reason);
1009
+ if (result.reason.length > 0) {
1010
+ result.isValid = false;
1011
+ }
1012
+ return result;
1013
+ }
1014
+ }
1015
+
1016
+ class ValidatorFactory {
1017
+ static create(spec, options) {
1018
+ var _a;
1019
+ const type = (_a = options.projectType) !== null && _a !== void 0 ? _a : ProjectType.SME;
1020
+ switch (type) {
1021
+ case ProjectType.SME:
1022
+ return new SMEValidator(spec, options);
1023
+ case ProjectType.Copilot:
1024
+ return new CopilotValidator(spec, options);
1025
+ case ProjectType.TeamsAi:
1026
+ return new TeamsAIValidator(spec, options);
1027
+ default:
1028
+ throw new Error(`Invalid project type: ${type}`);
767
1029
  }
768
- return safeRegistrationIdEnvName;
769
1030
  }
770
1031
  }
771
1032
 
@@ -788,7 +1049,11 @@ class SpecParser {
788
1049
  allowBearerTokenAuth: false,
789
1050
  allowOauth2: false,
790
1051
  allowMethods: ["get", "post"],
1052
+ allowConversationStarters: false,
1053
+ allowResponseSemantics: false,
1054
+ allowConfirmation: false,
791
1055
  projectType: ProjectType.SME,
1056
+ isGptPlugin: false,
792
1057
  };
793
1058
  this.pathOrSpec = pathOrDoc;
794
1059
  this.parser = new SwaggerParser();
@@ -803,11 +1068,7 @@ class SpecParser {
803
1068
  try {
804
1069
  try {
805
1070
  await this.loadSpec();
806
- await this.parser.validate(this.spec, {
807
- validate: {
808
- schema: false,
809
- },
810
- });
1071
+ await this.parser.validate(this.spec);
811
1072
  }
812
1073
  catch (e) {
813
1074
  return {
@@ -816,16 +1077,46 @@ class SpecParser {
816
1077
  errors: [{ type: ErrorType.SpecNotValid, content: e.toString() }],
817
1078
  };
818
1079
  }
1080
+ const errors = [];
1081
+ const warnings = [];
819
1082
  if (!this.options.allowSwagger && this.isSwaggerFile) {
820
1083
  return {
821
1084
  status: ValidationStatus.Error,
822
1085
  warnings: [],
823
1086
  errors: [
824
- { type: ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported },
1087
+ {
1088
+ type: ErrorType.SwaggerNotSupported,
1089
+ content: ConstantString.SwaggerNotSupported,
1090
+ },
825
1091
  ],
826
1092
  };
827
1093
  }
828
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
1094
+ // Remote reference not supported
1095
+ const refPaths = this.parser.$refs.paths();
1096
+ // refPaths [0] is the current spec file path
1097
+ if (refPaths.length > 1) {
1098
+ errors.push({
1099
+ type: ErrorType.RemoteRefNotSupported,
1100
+ content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
1101
+ data: refPaths,
1102
+ });
1103
+ }
1104
+ const validator = this.getValidator(this.spec);
1105
+ const validationResult = validator.validateSpec();
1106
+ warnings.push(...validationResult.warnings);
1107
+ errors.push(...validationResult.errors);
1108
+ let status = ValidationStatus.Valid;
1109
+ if (warnings.length > 0 && errors.length === 0) {
1110
+ status = ValidationStatus.Warning;
1111
+ }
1112
+ else if (errors.length > 0) {
1113
+ status = ValidationStatus.Error;
1114
+ }
1115
+ return {
1116
+ status: status,
1117
+ warnings: warnings,
1118
+ errors: errors,
1119
+ };
829
1120
  }
830
1121
  catch (err) {
831
1122
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -834,17 +1125,20 @@ class SpecParser {
834
1125
  async listSupportedAPIInfo() {
835
1126
  try {
836
1127
  await this.loadSpec();
837
- const apiMap = this.getAllSupportedAPIs(this.spec);
1128
+ const apiMap = this.getAPIs(this.spec);
838
1129
  const apiInfos = [];
839
1130
  for (const key in apiMap) {
840
- const pathObjectItem = apiMap[key];
1131
+ const { operation, isValid } = apiMap[key];
1132
+ if (!isValid) {
1133
+ continue;
1134
+ }
841
1135
  const [method, path] = key.split(" ");
842
- const operationId = pathObjectItem.operationId;
1136
+ const operationId = operation.operationId;
843
1137
  // In Browser environment, this api is by default not support api without operationId
844
1138
  if (!operationId) {
845
1139
  continue;
846
1140
  }
847
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
1141
+ const command = Utils.parseApiInfo(operation, this.options);
848
1142
  const apiInfo = {
849
1143
  method: method,
850
1144
  path: path,
@@ -853,9 +1147,6 @@ class SpecParser {
853
1147
  parameters: command.parameters,
854
1148
  description: command.description,
855
1149
  };
856
- if (warning) {
857
- apiInfo.warning = warning;
858
- }
859
1150
  apiInfos.push(apiInfo);
860
1151
  }
861
1152
  return apiInfos;
@@ -914,13 +1205,18 @@ class SpecParser {
914
1205
  this.spec = (await this.parser.dereference(clonedUnResolveSpec));
915
1206
  }
916
1207
  }
917
- getAllSupportedAPIs(spec) {
918
- if (this.apiMap !== undefined) {
919
- return this.apiMap;
1208
+ getAPIs(spec) {
1209
+ const validator = this.getValidator(spec);
1210
+ const apiMap = validator.listAPIs();
1211
+ return apiMap;
1212
+ }
1213
+ getValidator(spec) {
1214
+ if (this.validator) {
1215
+ return this.validator;
920
1216
  }
921
- const result = Utils.listSupportedAPIs(spec, this.options);
922
- this.apiMap = result;
923
- return result;
1217
+ const validator = ValidatorFactory.create(spec, this.options);
1218
+ this.validator = validator;
1219
+ return validator;
924
1220
  }
925
1221
  }
926
1222
 
@@ -928,7 +1224,7 @@ class SpecParser {
928
1224
  class AdaptiveCardGenerator {
929
1225
  static generateAdaptiveCard(operationItem) {
930
1226
  try {
931
- const json = Utils.getResponseJson(operationItem);
1227
+ const { json } = Utils.getResponseJson(operationItem);
932
1228
  let cardBody = [];
933
1229
  let schema = json.schema;
934
1230
  let jsonPath = "$";