@microsoft/m365-spec-parser 0.1.1-alpha.784d957e7.0 → 0.1.1-alpha.793c4be4c.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.
@@ -25,6 +25,21 @@ var ErrorType;
25
25
  ErrorType["GenerateFailed"] = "generate-failed";
26
26
  ErrorType["ValidateFailed"] = "validate-failed";
27
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";
28
43
  ErrorType["Cancelled"] = "cancelled";
29
44
  ErrorType["Unknown"] = "unknown";
30
45
  })(ErrorType || (ErrorType = {}));
@@ -72,7 +87,7 @@ ConstantString.RemoteRefNotSupported = "Remote reference is not supported: %s.";
72
87
  ConstantString.MissingOperationId = "Missing operationIds: %s.";
73
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.";
74
89
  ConstantString.AdditionalPropertiesNotSupported = "'additionalProperties' is not supported, and will be ignored.";
75
- ConstantString.SchemaNotSupported = "'oneOf', 'anyOf', and 'not' schema are not supported: %s.";
90
+ ConstantString.SchemaNotSupported = "'oneOf', 'allOf', 'anyOf', and 'not' schema are not supported: %s.";
76
91
  ConstantString.UnknownSchema = "Unknown schema: %s.";
77
92
  ConstantString.UrlProtocolNotSupported = "Server url is not correct: protocol %s is not supported, you should use https protocol instead.";
78
93
  ConstantString.RelativeServerUrlNotSupported = "Server url is not correct: relative server url is not supported.";
@@ -92,9 +107,14 @@ ConstantString.AdaptiveCardVersion = "1.5";
92
107
  ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
93
108
  ConstantString.AdaptiveCardType = "AdaptiveCard";
94
109
  ConstantString.TextBlockType = "TextBlock";
110
+ ConstantString.ImageType = "Image";
95
111
  ConstantString.ContainerType = "Container";
96
- ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
97
- 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
+ };
98
118
  ConstantString.ResponseCodeFor20X = [
99
119
  "200",
100
120
  "201",
@@ -153,9 +173,11 @@ ConstantString.ShortDescriptionMaxLens = 80;
153
173
  ConstantString.FullDescriptionMaxLens = 4000;
154
174
  ConstantString.CommandDescriptionMaxLens = 128;
155
175
  ConstantString.ParameterDescriptionMaxLens = 128;
176
+ ConstantString.ConversationStarterMaxLens = 50;
156
177
  ConstantString.CommandTitleMaxLens = 32;
157
178
  ConstantString.ParameterTitleMaxLens = 32;
158
- ConstantString.SMERequiredParamsMaxNum = 5;
179
+ ConstantString.SMERequiredParamsMaxNum = 5;
180
+ ConstantString.DefaultPluginId = "plugin_1";
159
181
 
160
182
  // Copyright (c) Microsoft Corporation.
161
183
  class Utils {
@@ -170,221 +192,9 @@ class Utils {
170
192
  }
171
193
  return false;
172
194
  }
173
- static checkParameters(paramObject, isCopilot) {
174
- const paramResult = {
175
- requiredNum: 0,
176
- optionalNum: 0,
177
- isValid: true,
178
- };
179
- if (!paramObject) {
180
- return paramResult;
181
- }
182
- for (let i = 0; i < paramObject.length; i++) {
183
- const param = paramObject[i];
184
- const schema = param.schema;
185
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
186
- paramResult.isValid = false;
187
- continue;
188
- }
189
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
190
- if (isCopilot) {
191
- if (isRequiredWithoutDefault) {
192
- paramResult.requiredNum = paramResult.requiredNum + 1;
193
- }
194
- else {
195
- paramResult.optionalNum = paramResult.optionalNum + 1;
196
- }
197
- continue;
198
- }
199
- if (param.in === "header" || param.in === "cookie") {
200
- if (isRequiredWithoutDefault) {
201
- paramResult.isValid = false;
202
- }
203
- continue;
204
- }
205
- if (schema.type !== "boolean" &&
206
- schema.type !== "string" &&
207
- schema.type !== "number" &&
208
- schema.type !== "integer") {
209
- if (isRequiredWithoutDefault) {
210
- paramResult.isValid = false;
211
- }
212
- continue;
213
- }
214
- if (param.in === "query" || param.in === "path") {
215
- if (isRequiredWithoutDefault) {
216
- paramResult.requiredNum = paramResult.requiredNum + 1;
217
- }
218
- else {
219
- paramResult.optionalNum = paramResult.optionalNum + 1;
220
- }
221
- }
222
- }
223
- return paramResult;
224
- }
225
- static checkPostBody(schema, isRequired = false, isCopilot = false) {
226
- var _a;
227
- const paramResult = {
228
- requiredNum: 0,
229
- optionalNum: 0,
230
- isValid: true,
231
- };
232
- if (Object.keys(schema).length === 0) {
233
- return paramResult;
234
- }
235
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
236
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
237
- paramResult.isValid = false;
238
- return paramResult;
239
- }
240
- if (schema.type === "string" ||
241
- schema.type === "integer" ||
242
- schema.type === "boolean" ||
243
- schema.type === "number") {
244
- if (isRequiredWithoutDefault) {
245
- paramResult.requiredNum = paramResult.requiredNum + 1;
246
- }
247
- else {
248
- paramResult.optionalNum = paramResult.optionalNum + 1;
249
- }
250
- }
251
- else if (schema.type === "object") {
252
- const { properties } = schema;
253
- for (const property in properties) {
254
- let isRequired = false;
255
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
256
- isRequired = true;
257
- }
258
- const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
259
- paramResult.requiredNum += result.requiredNum;
260
- paramResult.optionalNum += result.optionalNum;
261
- paramResult.isValid = paramResult.isValid && result.isValid;
262
- }
263
- }
264
- else {
265
- if (isRequiredWithoutDefault && !isCopilot) {
266
- paramResult.isValid = false;
267
- }
268
- }
269
- return paramResult;
270
- }
271
195
  static containMultipleMediaTypes(bodyObject) {
272
196
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
273
197
  }
274
- /**
275
- * Checks if the given API is supported.
276
- * @param {string} method - The HTTP method of the API.
277
- * @param {string} path - The path of the API.
278
- * @param {OpenAPIV3.Document} spec - The OpenAPI specification document.
279
- * @returns {boolean} - Returns true if the API is supported, false otherwise.
280
- * @description The following APIs are supported:
281
- * 1. only support Get/Post operation without auth property
282
- * 2. parameter inside query or path only support string, number, boolean and integer
283
- * 3. parameter inside post body only support string, number, boolean, integer and object
284
- * 4. request body + required parameters <= 1
285
- * 5. response body should be “application/json” and not empty, and response code should be 20X
286
- * 6. only support request body with “application/json” content type
287
- */
288
- static isSupportedApi(method, path, spec, options) {
289
- var _a;
290
- const pathObj = spec.paths[path];
291
- method = method.toLocaleLowerCase();
292
- if (pathObj) {
293
- if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
294
- const securities = pathObj[method].security;
295
- const isTeamsAi = options.projectType === ProjectType.TeamsAi;
296
- const isCopilot = options.projectType === ProjectType.Copilot;
297
- // Teams AI project doesn't care about auth, it will use authProvider for user to implement
298
- if (!isTeamsAi) {
299
- const authArray = Utils.getAuthArray(securities, spec);
300
- if (!Utils.isSupportedAuth(authArray, options)) {
301
- return false;
302
- }
303
- }
304
- const operationObject = pathObj[method];
305
- if (!options.allowMissingId && !operationObject.operationId) {
306
- return false;
307
- }
308
- const paramObject = operationObject.parameters;
309
- const requestBody = operationObject.requestBody;
310
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
311
- if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
312
- return false;
313
- }
314
- const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
315
- if (Object.keys(responseJson).length === 0) {
316
- return false;
317
- }
318
- // Teams AI project doesn't care about request parameters/body
319
- if (isTeamsAi) {
320
- return true;
321
- }
322
- let requestBodyParamResult = {
323
- requiredNum: 0,
324
- optionalNum: 0,
325
- isValid: true,
326
- };
327
- if (requestJsonBody) {
328
- const requestBodySchema = requestJsonBody.schema;
329
- if (isCopilot && requestBodySchema.type !== "object") {
330
- return false;
331
- }
332
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
333
- }
334
- if (!requestBodyParamResult.isValid) {
335
- return false;
336
- }
337
- const paramResult = Utils.checkParameters(paramObject, isCopilot);
338
- if (!paramResult.isValid) {
339
- return false;
340
- }
341
- // Copilot support arbitrary parameters
342
- if (isCopilot) {
343
- return true;
344
- }
345
- if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
346
- if (options.allowMultipleParameters &&
347
- requestBodyParamResult.requiredNum + paramResult.requiredNum <=
348
- ConstantString.SMERequiredParamsMaxNum) {
349
- return true;
350
- }
351
- return false;
352
- }
353
- else if (requestBodyParamResult.requiredNum +
354
- requestBodyParamResult.optionalNum +
355
- paramResult.requiredNum +
356
- paramResult.optionalNum ===
357
- 0) {
358
- return false;
359
- }
360
- else {
361
- return true;
362
- }
363
- }
364
- }
365
- return false;
366
- }
367
- static isSupportedAuth(authSchemeArray, options) {
368
- if (authSchemeArray.length === 0) {
369
- return true;
370
- }
371
- if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
372
- // Currently we don't support multiple auth in one operation
373
- if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
374
- return false;
375
- }
376
- for (const auths of authSchemeArray) {
377
- if (auths.length === 1) {
378
- if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
379
- (options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
380
- (options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
381
- return true;
382
- }
383
- }
384
- }
385
- }
386
- return false;
387
- }
388
198
  static isBearerTokenAuth(authScheme) {
389
199
  return authScheme.type === "http" && authScheme.scheme === "bearer";
390
200
  }
@@ -392,18 +202,18 @@ class Utils {
392
202
  return authScheme.type === "apiKey";
393
203
  }
394
204
  static isOAuthWithAuthCodeFlow(authScheme) {
395
- if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
396
- return true;
397
- }
398
- return false;
205
+ return !!(authScheme.type === "oauth2" &&
206
+ authScheme.flows &&
207
+ authScheme.flows.authorizationCode);
399
208
  }
400
209
  static getAuthArray(securities, spec) {
401
210
  var _a;
402
211
  const result = [];
403
212
  const securitySchemas = (_a = spec.components) === null || _a === void 0 ? void 0 : _a.securitySchemes;
404
- if (securities && securitySchemas) {
405
- for (let i = 0; i < securities.length; i++) {
406
- 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];
407
217
  const authArray = [];
408
218
  for (const name in security) {
409
219
  const auth = securitySchemas[name];
@@ -420,17 +230,39 @@ class Utils {
420
230
  result.sort((a, b) => a[0].name.localeCompare(b[0].name));
421
231
  return result;
422
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
+ }
423
252
  static updateFirstLetter(str) {
424
253
  return str.charAt(0).toUpperCase() + str.slice(1);
425
254
  }
426
- static getResponseJson(operationObject, isTeamsAiProject = false) {
255
+ static getResponseJson(operationObject) {
427
256
  var _a, _b;
428
257
  let json = {};
258
+ let multipleMediaType = false;
429
259
  for (const code of ConstantString.ResponseCodeFor20X) {
430
260
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
431
261
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
262
+ multipleMediaType = false;
432
263
  json = responseObject.content["application/json"];
433
- if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
264
+ if (Utils.containMultipleMediaTypes(responseObject)) {
265
+ multipleMediaType = true;
434
266
  json = {};
435
267
  }
436
268
  else {
@@ -438,7 +270,7 @@ class Utils {
438
270
  }
439
271
  }
440
272
  }
441
- return json;
273
+ return { json, multipleMediaType };
442
274
  }
443
275
  static convertPathToCamelCase(path) {
444
276
  const pathSegments = path.split(/[./{]/);
@@ -458,10 +290,10 @@ class Utils {
458
290
  return undefined;
459
291
  }
460
292
  }
461
- static resolveServerUrl(url) {
293
+ static resolveEnv(str) {
462
294
  const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
463
- let matches = placeHolderReg.exec(url);
464
- let newUrl = url;
295
+ let matches = placeHolderReg.exec(str);
296
+ let newStr = str;
465
297
  while (matches != null) {
466
298
  const envVar = matches[1];
467
299
  const envVal = process.env[envVar];
@@ -469,17 +301,17 @@ class Utils {
469
301
  throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
470
302
  }
471
303
  else {
472
- newUrl = newUrl.replace(matches[0], envVal);
304
+ newStr = newStr.replace(matches[0], envVal);
473
305
  }
474
- matches = placeHolderReg.exec(url);
306
+ matches = placeHolderReg.exec(str);
475
307
  }
476
- return newUrl;
308
+ return newStr;
477
309
  }
478
310
  static checkServerUrl(servers) {
479
311
  const errors = [];
480
312
  let serverUrl;
481
313
  try {
482
- serverUrl = Utils.resolveServerUrl(servers[0].url);
314
+ serverUrl = Utils.resolveEnv(servers[0].url);
483
315
  }
484
316
  catch (err) {
485
317
  errors.push({
@@ -510,6 +342,7 @@ class Utils {
510
342
  return errors;
511
343
  }
512
344
  static validateServer(spec, options) {
345
+ var _a;
513
346
  const errors = [];
514
347
  let hasTopLevelServers = false;
515
348
  let hasPathLevelServers = false;
@@ -530,7 +363,7 @@ class Utils {
530
363
  }
531
364
  for (const method in methods) {
532
365
  const operationObject = methods[method];
533
- if (Utils.isSupportedApi(method, path, spec, options)) {
366
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
534
367
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
535
368
  hasOperationLevelServers = true;
536
369
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -657,13 +490,7 @@ class Utils {
657
490
  }
658
491
  }
659
492
  const operationId = operationItem.operationId;
660
- const parameters = [];
661
- if (requiredParams.length !== 0) {
662
- parameters.push(...requiredParams);
663
- }
664
- else {
665
- parameters.push(optionalParams[0]);
666
- }
493
+ const parameters = [...requiredParams, ...optionalParams];
667
494
  const command = {
668
495
  context: ["compose"],
669
496
  type: "query",
@@ -672,117 +499,534 @@ class Utils {
672
499
  parameters: parameters,
673
500
  description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
674
501
  };
675
- let warning = undefined;
676
- if (requiredParams.length === 0 && optionalParams.length > 1) {
677
- warning = {
678
- type: WarningType.OperationOnlyContainsOptionalParam,
679
- content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, operationId),
680
- data: operationId,
681
- };
502
+ return command;
503
+ }
504
+ static format(str, ...args) {
505
+ let index = 0;
506
+ return str.replace(/%s/g, () => {
507
+ const arg = args[index++];
508
+ return arg !== undefined ? arg : "";
509
+ });
510
+ }
511
+ static getSafeRegistrationIdEnvName(authName) {
512
+ if (!authName) {
513
+ return "";
514
+ }
515
+ let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
516
+ if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
517
+ safeRegistrationIdEnvName = "PREFIX_" + safeRegistrationIdEnvName;
682
518
  }
683
- return [command, warning];
519
+ return safeRegistrationIdEnvName;
684
520
  }
685
- static listSupportedAPIs(spec, options) {
686
- 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;
687
540
  const result = {};
688
541
  for (const path in paths) {
689
542
  const methods = paths[path];
690
543
  for (const method in methods) {
691
- if (Utils.isSupportedApi(method, path, spec, options)) {
692
- const operationObject = methods[method];
693
- 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
+ };
694
552
  }
695
553
  }
696
554
  }
555
+ this.apiMap = result;
697
556
  return result;
698
557
  }
699
- static validateSpec(spec, parser, isSwaggerFile, options) {
700
- const errors = [];
701
- const warnings = [];
702
- if (isSwaggerFile) {
703
- warnings.push({
704
- type: WarningType.ConvertSwaggerToOpenAPI,
705
- content: ConstantString.ConvertSwaggerToOpenAPI,
706
- });
707
- }
708
- // Server validation
709
- const serverErrors = Utils.validateServer(spec, options);
710
- errors.push(...serverErrors);
711
- // Remote reference not supported
712
- const refPaths = parser.$refs.paths();
713
- // refPaths [0] is the current spec file path
714
- if (refPaths.length > 1) {
715
- errors.push({
716
- type: ErrorType.RemoteRefNotSupported,
717
- content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
718
- data: refPaths,
558
+ validateSpecVersion() {
559
+ const result = { errors: [], warnings: [] };
560
+ if (this.spec.openapi >= "3.1.0") {
561
+ result.errors.push({
562
+ type: ErrorType.SpecVersionNotSupported,
563
+ content: Utils.format(ConstantString.SpecVersionNotSupported, this.spec.openapi),
564
+ data: this.spec.openapi,
719
565
  });
720
566
  }
721
- // No supported API
722
- const apiMap = Utils.listSupportedAPIs(spec, options);
723
- if (Object.keys(apiMap).length === 0) {
724
- 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({
725
587
  type: ErrorType.NoSupportedApi,
726
588
  content: ConstantString.NoSupportedApi,
589
+ data,
727
590
  });
728
591
  }
592
+ return result;
593
+ }
594
+ validateSpecOperationId() {
595
+ const result = { errors: [], warnings: [] };
596
+ const apiMap = this.listAPIs();
729
597
  // OperationId missing
730
598
  const apisMissingOperationId = [];
731
599
  for (const key in apiMap) {
732
- const pathObjectItem = apiMap[key];
733
- if (!pathObjectItem.operationId) {
600
+ const { operation } = apiMap[key];
601
+ if (!operation.operationId) {
734
602
  apisMissingOperationId.push(key);
735
603
  }
736
604
  }
737
605
  if (apisMissingOperationId.length > 0) {
738
- warnings.push({
606
+ result.warnings.push({
739
607
  type: WarningType.OperationIdMissing,
740
608
  content: Utils.format(ConstantString.MissingOperationId, apisMissingOperationId.join(", ")),
741
609
  data: apisMissingOperationId,
742
610
  });
743
611
  }
744
- let status = ValidationStatus.Valid;
745
- if (warnings.length > 0 && errors.length === 0) {
746
- 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;
747
620
  }
748
- else if (errors.length > 0) {
749
- status = ValidationStatus.Error;
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;
750
626
  }
751
- return {
752
- status,
753
- warnings,
754
- errors,
755
- };
627
+ return result;
756
628
  }
757
- static format(str, ...args) {
758
- let index = 0;
759
- return str.replace(/%s/g, () => {
760
- const arg = args[index++];
761
- return arg !== undefined ? arg : "";
762
- });
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;
763
644
  }
764
- static getSafeRegistrationIdEnvName(authName) {
765
- if (!authName) {
766
- return "";
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);
767
651
  }
768
- let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
769
- if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
770
- safeRegistrationIdEnvName = "PREFIX_" + safeRegistrationIdEnvName;
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));
771
656
  }
772
- return safeRegistrationIdEnvName;
657
+ return result;
773
658
  }
774
- static getAllAPICount(spec) {
775
- let count = 0;
776
- const paths = spec.paths;
777
- for (const path in paths) {
778
- const methods = paths[path];
779
- for (const method in methods) {
780
- if (ConstantString.AllOperationMethods.includes(method)) {
781
- count++;
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
+ }
686
+ }
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: [],
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;
739
+ }
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;
782
792
  }
783
793
  }
784
794
  }
785
- return count;
795
+ return paramResult;
796
+ }
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
+ }
805
+ }
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}`);
1029
+ }
786
1030
  }
787
1031
  }
788
1032
 
@@ -805,7 +1049,11 @@ class SpecParser {
805
1049
  allowBearerTokenAuth: false,
806
1050
  allowOauth2: false,
807
1051
  allowMethods: ["get", "post"],
1052
+ allowConversationStarters: false,
1053
+ allowResponseSemantics: false,
1054
+ allowConfirmation: false,
808
1055
  projectType: ProjectType.SME,
1056
+ isGptPlugin: false,
809
1057
  };
810
1058
  this.pathOrSpec = pathOrDoc;
811
1059
  this.parser = new SwaggerParser();
@@ -833,16 +1081,46 @@ class SpecParser {
833
1081
  errors: [{ type: ErrorType.SpecNotValid, content: e.toString() }],
834
1082
  };
835
1083
  }
1084
+ const errors = [];
1085
+ const warnings = [];
836
1086
  if (!this.options.allowSwagger && this.isSwaggerFile) {
837
1087
  return {
838
1088
  status: ValidationStatus.Error,
839
1089
  warnings: [],
840
1090
  errors: [
841
- { type: ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported },
1091
+ {
1092
+ type: ErrorType.SwaggerNotSupported,
1093
+ content: ConstantString.SwaggerNotSupported,
1094
+ },
842
1095
  ],
843
1096
  };
844
1097
  }
845
- 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
+ };
846
1124
  }
847
1125
  catch (err) {
848
1126
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -851,17 +1129,20 @@ class SpecParser {
851
1129
  async listSupportedAPIInfo() {
852
1130
  try {
853
1131
  await this.loadSpec();
854
- const apiMap = this.getAllSupportedAPIs(this.spec);
1132
+ const apiMap = this.getAPIs(this.spec);
855
1133
  const apiInfos = [];
856
1134
  for (const key in apiMap) {
857
- const pathObjectItem = apiMap[key];
1135
+ const { operation, isValid } = apiMap[key];
1136
+ if (!isValid) {
1137
+ continue;
1138
+ }
858
1139
  const [method, path] = key.split(" ");
859
- const operationId = pathObjectItem.operationId;
1140
+ const operationId = operation.operationId;
860
1141
  // In Browser environment, this api is by default not support api without operationId
861
1142
  if (!operationId) {
862
1143
  continue;
863
1144
  }
864
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
1145
+ const command = Utils.parseApiInfo(operation, this.options);
865
1146
  const apiInfo = {
866
1147
  method: method,
867
1148
  path: path,
@@ -870,9 +1151,6 @@ class SpecParser {
870
1151
  parameters: command.parameters,
871
1152
  description: command.description,
872
1153
  };
873
- if (warning) {
874
- apiInfo.warning = warning;
875
- }
876
1154
  apiInfos.push(apiInfo);
877
1155
  }
878
1156
  return apiInfos;
@@ -931,13 +1209,18 @@ class SpecParser {
931
1209
  this.spec = (await this.parser.dereference(clonedUnResolveSpec));
932
1210
  }
933
1211
  }
934
- getAllSupportedAPIs(spec) {
935
- if (this.apiMap !== undefined) {
936
- 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;
937
1220
  }
938
- const result = Utils.listSupportedAPIs(spec, this.options);
939
- this.apiMap = result;
940
- return result;
1221
+ const validator = ValidatorFactory.create(spec, this.options);
1222
+ this.validator = validator;
1223
+ return validator;
941
1224
  }
942
1225
  }
943
1226
 
@@ -945,7 +1228,7 @@ class SpecParser {
945
1228
  class AdaptiveCardGenerator {
946
1229
  static generateAdaptiveCard(operationItem) {
947
1230
  try {
948
- const json = Utils.getResponseJson(operationItem);
1231
+ const { json } = Utils.getResponseJson(operationItem);
949
1232
  let cardBody = [];
950
1233
  let schema = json.schema;
951
1234
  let jsonPath = "$";