@microsoft/m365-spec-parser 0.1.1-alpha.fb5afedc0.0 → 0.1.1-alpha.fbb412c19.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);
@@ -655,13 +490,7 @@ class Utils {
655
490
  }
656
491
  }
657
492
  const operationId = operationItem.operationId;
658
- const parameters = [];
659
- if (requiredParams.length !== 0) {
660
- parameters.push(...requiredParams);
661
- }
662
- else {
663
- parameters.push(optionalParams[0]);
664
- }
493
+ const parameters = [...requiredParams, ...optionalParams];
665
494
  const command = {
666
495
  context: ["compose"],
667
496
  type: "query",
@@ -670,104 +499,534 @@ class Utils {
670
499
  parameters: parameters,
671
500
  description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
672
501
  };
673
- let warning = undefined;
674
- if (requiredParams.length === 0 && optionalParams.length > 1) {
675
- warning = {
676
- type: WarningType.OperationOnlyContainsOptionalParam,
677
- content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, operationId),
678
- data: operationId,
679
- };
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 "";
680
514
  }
681
- return [command, warning];
515
+ let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
516
+ if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
517
+ safeRegistrationIdEnvName = "PREFIX_" + safeRegistrationIdEnvName;
518
+ }
519
+ return safeRegistrationIdEnvName;
682
520
  }
683
- static listSupportedAPIs(spec, options) {
684
- 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;
685
540
  const result = {};
686
541
  for (const path in paths) {
687
542
  const methods = paths[path];
688
543
  for (const method in methods) {
689
- if (Utils.isSupportedApi(method, path, spec, options)) {
690
- const operationObject = methods[method];
691
- 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
+ };
692
552
  }
693
553
  }
694
554
  }
555
+ this.apiMap = result;
695
556
  return result;
696
557
  }
697
- static validateSpec(spec, parser, isSwaggerFile, options) {
698
- const errors = [];
699
- const warnings = [];
700
- if (isSwaggerFile) {
701
- warnings.push({
702
- type: WarningType.ConvertSwaggerToOpenAPI,
703
- content: ConstantString.ConvertSwaggerToOpenAPI,
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,
704
565
  });
705
566
  }
706
- // Server validation
707
- const serverErrors = Utils.validateServer(spec, options);
708
- errors.push(...serverErrors);
709
- // Remote reference not supported
710
- const refPaths = parser.$refs.paths();
711
- // refPaths [0] is the current spec file path
712
- if (refPaths.length > 1) {
713
- errors.push({
714
- type: ErrorType.RemoteRefNotSupported,
715
- content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
716
- data: refPaths,
717
- });
718
- }
719
- // No supported API
720
- const apiMap = Utils.listSupportedAPIs(spec, options);
721
- if (Object.keys(apiMap).length === 0) {
722
- 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({
723
587
  type: ErrorType.NoSupportedApi,
724
588
  content: ConstantString.NoSupportedApi,
589
+ data,
725
590
  });
726
591
  }
592
+ return result;
593
+ }
594
+ validateSpecOperationId() {
595
+ const result = { errors: [], warnings: [] };
596
+ const apiMap = this.listAPIs();
727
597
  // OperationId missing
728
598
  const apisMissingOperationId = [];
729
599
  for (const key in apiMap) {
730
- const pathObjectItem = apiMap[key];
731
- if (!pathObjectItem.operationId) {
600
+ const { operation } = apiMap[key];
601
+ if (!operation.operationId) {
732
602
  apisMissingOperationId.push(key);
733
603
  }
734
604
  }
735
605
  if (apisMissingOperationId.length > 0) {
736
- warnings.push({
606
+ result.warnings.push({
737
607
  type: WarningType.OperationIdMissing,
738
608
  content: Utils.format(ConstantString.MissingOperationId, apisMissingOperationId.join(", ")),
739
609
  data: apisMissingOperationId,
740
610
  });
741
611
  }
742
- let status = ValidationStatus.Valid;
743
- if (warnings.length > 0 && errors.length === 0) {
744
- 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));
745
656
  }
746
- else if (errors.length > 0) {
747
- status = ValidationStatus.Error;
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: [] };
666
+ }
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
+ }
748
686
  }
749
- return {
750
- status,
751
- warnings,
752
- 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: [],
753
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;
754
739
  }
755
- static format(str, ...args) {
756
- let index = 0;
757
- return str.replace(/%s/g, () => {
758
- const arg = args[index++];
759
- return arg !== undefined ? arg : "";
760
- });
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;
761
796
  }
762
- static getSafeRegistrationIdEnvName(authName) {
763
- if (!authName) {
764
- 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
+ }
765
805
  }
766
- let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
767
- if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
768
- 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}`);
769
1029
  }
770
- return safeRegistrationIdEnvName;
771
1030
  }
772
1031
  }
773
1032
 
@@ -790,7 +1049,11 @@ class SpecParser {
790
1049
  allowBearerTokenAuth: false,
791
1050
  allowOauth2: false,
792
1051
  allowMethods: ["get", "post"],
1052
+ allowConversationStarters: false,
1053
+ allowResponseSemantics: false,
1054
+ allowConfirmation: false,
793
1055
  projectType: ProjectType.SME,
1056
+ isGptPlugin: false,
794
1057
  };
795
1058
  this.pathOrSpec = pathOrDoc;
796
1059
  this.parser = new SwaggerParser();
@@ -818,16 +1081,46 @@ class SpecParser {
818
1081
  errors: [{ type: ErrorType.SpecNotValid, content: e.toString() }],
819
1082
  };
820
1083
  }
1084
+ const errors = [];
1085
+ const warnings = [];
821
1086
  if (!this.options.allowSwagger && this.isSwaggerFile) {
822
1087
  return {
823
1088
  status: ValidationStatus.Error,
824
1089
  warnings: [],
825
1090
  errors: [
826
- { type: ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported },
1091
+ {
1092
+ type: ErrorType.SwaggerNotSupported,
1093
+ content: ConstantString.SwaggerNotSupported,
1094
+ },
827
1095
  ],
828
1096
  };
829
1097
  }
830
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
1098
+ // Remote reference not supported
1099
+ const refPaths = this.parser.$refs.paths();
1100
+ // refPaths [0] is the current spec file path
1101
+ if (refPaths.length > 1) {
1102
+ errors.push({
1103
+ type: ErrorType.RemoteRefNotSupported,
1104
+ content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
1105
+ data: refPaths,
1106
+ });
1107
+ }
1108
+ const validator = this.getValidator(this.spec);
1109
+ const validationResult = validator.validateSpec();
1110
+ warnings.push(...validationResult.warnings);
1111
+ errors.push(...validationResult.errors);
1112
+ let status = ValidationStatus.Valid;
1113
+ if (warnings.length > 0 && errors.length === 0) {
1114
+ status = ValidationStatus.Warning;
1115
+ }
1116
+ else if (errors.length > 0) {
1117
+ status = ValidationStatus.Error;
1118
+ }
1119
+ return {
1120
+ status: status,
1121
+ warnings: warnings,
1122
+ errors: errors,
1123
+ };
831
1124
  }
832
1125
  catch (err) {
833
1126
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -836,17 +1129,20 @@ class SpecParser {
836
1129
  async listSupportedAPIInfo() {
837
1130
  try {
838
1131
  await this.loadSpec();
839
- const apiMap = this.getAllSupportedAPIs(this.spec);
1132
+ const apiMap = this.getAPIs(this.spec);
840
1133
  const apiInfos = [];
841
1134
  for (const key in apiMap) {
842
- const pathObjectItem = apiMap[key];
1135
+ const { operation, isValid } = apiMap[key];
1136
+ if (!isValid) {
1137
+ continue;
1138
+ }
843
1139
  const [method, path] = key.split(" ");
844
- const operationId = pathObjectItem.operationId;
1140
+ const operationId = operation.operationId;
845
1141
  // In Browser environment, this api is by default not support api without operationId
846
1142
  if (!operationId) {
847
1143
  continue;
848
1144
  }
849
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
1145
+ const command = Utils.parseApiInfo(operation, this.options);
850
1146
  const apiInfo = {
851
1147
  method: method,
852
1148
  path: path,
@@ -855,9 +1151,6 @@ class SpecParser {
855
1151
  parameters: command.parameters,
856
1152
  description: command.description,
857
1153
  };
858
- if (warning) {
859
- apiInfo.warning = warning;
860
- }
861
1154
  apiInfos.push(apiInfo);
862
1155
  }
863
1156
  return apiInfos;
@@ -916,13 +1209,18 @@ class SpecParser {
916
1209
  this.spec = (await this.parser.dereference(clonedUnResolveSpec));
917
1210
  }
918
1211
  }
919
- getAllSupportedAPIs(spec) {
920
- if (this.apiMap !== undefined) {
921
- return this.apiMap;
1212
+ getAPIs(spec) {
1213
+ const validator = this.getValidator(spec);
1214
+ const apiMap = validator.listAPIs();
1215
+ return apiMap;
1216
+ }
1217
+ getValidator(spec) {
1218
+ if (this.validator) {
1219
+ return this.validator;
922
1220
  }
923
- const result = Utils.listSupportedAPIs(spec, this.options);
924
- this.apiMap = result;
925
- return result;
1221
+ const validator = ValidatorFactory.create(spec, this.options);
1222
+ this.validator = validator;
1223
+ return validator;
926
1224
  }
927
1225
  }
928
1226
 
@@ -930,7 +1228,7 @@ class SpecParser {
930
1228
  class AdaptiveCardGenerator {
931
1229
  static generateAdaptiveCard(operationItem) {
932
1230
  try {
933
- const json = Utils.getResponseJson(operationItem);
1231
+ const { json } = Utils.getResponseJson(operationItem);
934
1232
  let cardBody = [];
935
1233
  let schema = json.schema;
936
1234
  let jsonPath = "$";