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