@microsoft/m365-spec-parser 0.1.1-alpha.d1a09e202.0 → 0.1.1-alpha.ded43fb2d.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 = {}));
@@ -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,6 +107,7 @@ 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
112
  ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
95
113
  ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
@@ -153,7 +171,8 @@ ConstantString.CommandDescriptionMaxLens = 128;
153
171
  ConstantString.ParameterDescriptionMaxLens = 128;
154
172
  ConstantString.CommandTitleMaxLens = 32;
155
173
  ConstantString.ParameterTitleMaxLens = 32;
156
- ConstantString.SMERequiredParamsMaxNum = 5;
174
+ ConstantString.SMERequiredParamsMaxNum = 5;
175
+ ConstantString.DefaultPluginId = "plugin_1";
157
176
 
158
177
  // Copyright (c) Microsoft Corporation.
159
178
  class Utils {
@@ -168,221 +187,9 @@ class Utils {
168
187
  }
169
188
  return false;
170
189
  }
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
190
  static containMultipleMediaTypes(bodyObject) {
270
191
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
271
192
  }
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
193
  static isBearerTokenAuth(authScheme) {
387
194
  return authScheme.type === "http" && authScheme.scheme === "bearer";
388
195
  }
@@ -390,10 +197,9 @@ class Utils {
390
197
  return authScheme.type === "apiKey";
391
198
  }
392
199
  static isOAuthWithAuthCodeFlow(authScheme) {
393
- if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
394
- return true;
395
- }
396
- return false;
200
+ return !!(authScheme.type === "oauth2" &&
201
+ authScheme.flows &&
202
+ authScheme.flows.authorizationCode);
397
203
  }
398
204
  static getAuthArray(securities, spec) {
399
205
  var _a;
@@ -418,17 +224,39 @@ class Utils {
418
224
  result.sort((a, b) => a[0].name.localeCompare(b[0].name));
419
225
  return result;
420
226
  }
227
+ static getAuthInfo(spec) {
228
+ let authInfo = undefined;
229
+ for (const url in spec.paths) {
230
+ for (const method in spec.paths[url]) {
231
+ const operation = spec.paths[url][method];
232
+ const authArray = Utils.getAuthArray(operation.security, spec);
233
+ if (authArray && authArray.length > 0) {
234
+ const currentAuth = authArray[0][0];
235
+ if (!authInfo) {
236
+ authInfo = authArray[0][0];
237
+ }
238
+ else if (authInfo.name !== currentAuth.name) {
239
+ throw new SpecParserError(ConstantString.MultipleAuthNotSupported, ErrorType.MultipleAuthNotSupported);
240
+ }
241
+ }
242
+ }
243
+ }
244
+ return authInfo;
245
+ }
421
246
  static updateFirstLetter(str) {
422
247
  return str.charAt(0).toUpperCase() + str.slice(1);
423
248
  }
424
- static getResponseJson(operationObject, isTeamsAiProject = false) {
249
+ static getResponseJson(operationObject) {
425
250
  var _a, _b;
426
251
  let json = {};
252
+ let multipleMediaType = false;
427
253
  for (const code of ConstantString.ResponseCodeFor20X) {
428
254
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
429
255
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
256
+ multipleMediaType = false;
430
257
  json = responseObject.content["application/json"];
431
- if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
258
+ if (Utils.containMultipleMediaTypes(responseObject)) {
259
+ multipleMediaType = true;
432
260
  json = {};
433
261
  }
434
262
  else {
@@ -436,7 +264,7 @@ class Utils {
436
264
  }
437
265
  }
438
266
  }
439
- return json;
267
+ return { json, multipleMediaType };
440
268
  }
441
269
  static convertPathToCamelCase(path) {
442
270
  const pathSegments = path.split(/[./{]/);
@@ -456,10 +284,10 @@ class Utils {
456
284
  return undefined;
457
285
  }
458
286
  }
459
- static resolveServerUrl(url) {
287
+ static resolveEnv(str) {
460
288
  const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
461
- let matches = placeHolderReg.exec(url);
462
- let newUrl = url;
289
+ let matches = placeHolderReg.exec(str);
290
+ let newStr = str;
463
291
  while (matches != null) {
464
292
  const envVar = matches[1];
465
293
  const envVal = process.env[envVar];
@@ -467,17 +295,17 @@ class Utils {
467
295
  throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
468
296
  }
469
297
  else {
470
- newUrl = newUrl.replace(matches[0], envVal);
298
+ newStr = newStr.replace(matches[0], envVal);
471
299
  }
472
- matches = placeHolderReg.exec(url);
300
+ matches = placeHolderReg.exec(str);
473
301
  }
474
- return newUrl;
302
+ return newStr;
475
303
  }
476
304
  static checkServerUrl(servers) {
477
305
  const errors = [];
478
306
  let serverUrl;
479
307
  try {
480
- serverUrl = Utils.resolveServerUrl(servers[0].url);
308
+ serverUrl = Utils.resolveEnv(servers[0].url);
481
309
  }
482
310
  catch (err) {
483
311
  errors.push({
@@ -508,6 +336,7 @@ class Utils {
508
336
  return errors;
509
337
  }
510
338
  static validateServer(spec, options) {
339
+ var _a;
511
340
  const errors = [];
512
341
  let hasTopLevelServers = false;
513
342
  let hasPathLevelServers = false;
@@ -528,7 +357,7 @@ class Utils {
528
357
  }
529
358
  for (const method in methods) {
530
359
  const operationObject = methods[method];
531
- if (Utils.isSupportedApi(method, path, spec, options)) {
360
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
532
361
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
533
362
  hasOperationLevelServers = true;
534
363
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -571,6 +400,7 @@ class Utils {
571
400
  Utils.updateParameterWithInputType(schema, parameter);
572
401
  }
573
402
  if (isRequired && schema.default === undefined) {
403
+ parameter.isRequired = true;
574
404
  requiredParams.push(parameter);
575
405
  }
576
406
  else {
@@ -634,6 +464,7 @@ class Utils {
634
464
  }
635
465
  if (param.in !== "header" && param.in !== "cookie") {
636
466
  if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
467
+ parameter.isRequired = true;
637
468
  requiredParams.push(parameter);
638
469
  }
639
470
  else {
@@ -653,13 +484,7 @@ class Utils {
653
484
  }
654
485
  }
655
486
  const operationId = operationItem.operationId;
656
- const parameters = [];
657
- if (requiredParams.length !== 0) {
658
- parameters.push(...requiredParams);
659
- }
660
- else {
661
- parameters.push(optionalParams[0]);
662
- }
487
+ const parameters = [...requiredParams, ...optionalParams];
663
488
  const command = {
664
489
  context: ["compose"],
665
490
  type: "query",
@@ -668,104 +493,534 @@ class Utils {
668
493
  parameters: parameters,
669
494
  description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
670
495
  };
671
- let warning = undefined;
672
- if (requiredParams.length === 0 && optionalParams.length > 1) {
673
- warning = {
674
- type: WarningType.OperationOnlyContainsOptionalParam,
675
- content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, operationId),
676
- data: operationId,
677
- };
496
+ return command;
497
+ }
498
+ static format(str, ...args) {
499
+ let index = 0;
500
+ return str.replace(/%s/g, () => {
501
+ const arg = args[index++];
502
+ return arg !== undefined ? arg : "";
503
+ });
504
+ }
505
+ static getSafeRegistrationIdEnvName(authName) {
506
+ if (!authName) {
507
+ return "";
508
+ }
509
+ let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
510
+ if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
511
+ safeRegistrationIdEnvName = "PREFIX_" + safeRegistrationIdEnvName;
678
512
  }
679
- return [command, warning];
513
+ return safeRegistrationIdEnvName;
680
514
  }
681
- static listSupportedAPIs(spec, options) {
682
- const paths = spec.paths;
515
+ static getServerObject(spec, method, path) {
516
+ const pathObj = spec.paths[path];
517
+ const operationObject = pathObj[method];
518
+ const rootServer = spec.servers && spec.servers[0];
519
+ const methodServer = spec.paths[path].servers && spec.paths[path].servers[0];
520
+ const operationServer = operationObject.servers && operationObject.servers[0];
521
+ const serverUrl = operationServer || methodServer || rootServer;
522
+ return serverUrl;
523
+ }
524
+ }
525
+
526
+ // Copyright (c) Microsoft Corporation.
527
+ class Validator {
528
+ listAPIs() {
529
+ var _a;
530
+ if (this.apiMap) {
531
+ return this.apiMap;
532
+ }
533
+ const paths = this.spec.paths;
683
534
  const result = {};
684
535
  for (const path in paths) {
685
536
  const methods = paths[path];
686
537
  for (const method in methods) {
687
- if (Utils.isSupportedApi(method, path, spec, options)) {
688
- const operationObject = methods[method];
689
- result[`${method.toUpperCase()} ${path}`] = operationObject;
538
+ const operationObject = methods[method];
539
+ if (((_a = this.options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
540
+ const validateResult = this.validateAPI(method, path);
541
+ result[`${method.toUpperCase()} ${path}`] = {
542
+ operation: operationObject,
543
+ isValid: validateResult.isValid,
544
+ reason: validateResult.reason,
545
+ };
690
546
  }
691
547
  }
692
548
  }
549
+ this.apiMap = result;
693
550
  return result;
694
551
  }
695
- static validateSpec(spec, parser, isSwaggerFile, options) {
696
- const errors = [];
697
- const warnings = [];
698
- if (isSwaggerFile) {
699
- warnings.push({
700
- type: WarningType.ConvertSwaggerToOpenAPI,
701
- content: ConstantString.ConvertSwaggerToOpenAPI,
702
- });
703
- }
704
- // Server validation
705
- const serverErrors = Utils.validateServer(spec, options);
706
- errors.push(...serverErrors);
707
- // Remote reference not supported
708
- const refPaths = parser.$refs.paths();
709
- // refPaths [0] is the current spec file path
710
- if (refPaths.length > 1) {
711
- errors.push({
712
- type: ErrorType.RemoteRefNotSupported,
713
- content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
714
- data: refPaths,
552
+ validateSpecVersion() {
553
+ const result = { errors: [], warnings: [] };
554
+ if (this.spec.openapi >= "3.1.0") {
555
+ result.errors.push({
556
+ type: ErrorType.SpecVersionNotSupported,
557
+ content: Utils.format(ConstantString.SpecVersionNotSupported, this.spec.openapi),
558
+ data: this.spec.openapi,
715
559
  });
716
560
  }
717
- // No supported API
718
- const apiMap = Utils.listSupportedAPIs(spec, options);
719
- if (Object.keys(apiMap).length === 0) {
720
- errors.push({
561
+ return result;
562
+ }
563
+ validateSpecServer() {
564
+ const result = { errors: [], warnings: [] };
565
+ const serverErrors = Utils.validateServer(this.spec, this.options);
566
+ result.errors.push(...serverErrors);
567
+ return result;
568
+ }
569
+ validateSpecNoSupportAPI() {
570
+ const result = { errors: [], warnings: [] };
571
+ const apiMap = this.listAPIs();
572
+ const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
573
+ if (validAPIs.length === 0) {
574
+ const data = [];
575
+ for (const key in apiMap) {
576
+ const { reason } = apiMap[key];
577
+ const apiInvalidReason = { api: key, reason: reason };
578
+ data.push(apiInvalidReason);
579
+ }
580
+ result.errors.push({
721
581
  type: ErrorType.NoSupportedApi,
722
582
  content: ConstantString.NoSupportedApi,
583
+ data,
723
584
  });
724
585
  }
586
+ return result;
587
+ }
588
+ validateSpecOperationId() {
589
+ const result = { errors: [], warnings: [] };
590
+ const apiMap = this.listAPIs();
725
591
  // OperationId missing
726
592
  const apisMissingOperationId = [];
727
593
  for (const key in apiMap) {
728
- const pathObjectItem = apiMap[key];
729
- if (!pathObjectItem.operationId) {
594
+ const { operation } = apiMap[key];
595
+ if (!operation.operationId) {
730
596
  apisMissingOperationId.push(key);
731
597
  }
732
598
  }
733
599
  if (apisMissingOperationId.length > 0) {
734
- warnings.push({
600
+ result.warnings.push({
735
601
  type: WarningType.OperationIdMissing,
736
602
  content: Utils.format(ConstantString.MissingOperationId, apisMissingOperationId.join(", ")),
737
603
  data: apisMissingOperationId,
738
604
  });
739
605
  }
740
- let status = ValidationStatus.Valid;
741
- if (warnings.length > 0 && errors.length === 0) {
742
- status = ValidationStatus.Warning;
606
+ return result;
607
+ }
608
+ validateMethodAndPath(method, path) {
609
+ const result = { isValid: true, reason: [] };
610
+ if (this.options.allowMethods && !this.options.allowMethods.includes(method)) {
611
+ result.isValid = false;
612
+ result.reason.push(ErrorType.MethodNotAllowed);
613
+ return result;
614
+ }
615
+ const pathObj = this.spec.paths[path];
616
+ if (!pathObj || !pathObj[method]) {
617
+ result.isValid = false;
618
+ result.reason.push(ErrorType.UrlPathNotExist);
619
+ return result;
620
+ }
621
+ return result;
622
+ }
623
+ validateResponse(method, path) {
624
+ const result = { isValid: true, reason: [] };
625
+ const operationObject = this.spec.paths[path][method];
626
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
627
+ if (this.options.projectType === ProjectType.SME) {
628
+ // only support response body only contains “application/json” content type
629
+ if (multipleMediaType) {
630
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
631
+ }
632
+ else if (Object.keys(json).length === 0) {
633
+ // response body should not be empty
634
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
635
+ }
636
+ }
637
+ return result;
638
+ }
639
+ validateServer(method, path) {
640
+ const result = { isValid: true, reason: [] };
641
+ const serverObj = Utils.getServerObject(this.spec, method, path);
642
+ if (!serverObj) {
643
+ // should contain server URL
644
+ result.reason.push(ErrorType.NoServerInformation);
645
+ }
646
+ else {
647
+ // server url should be absolute url with https protocol
648
+ const serverValidateResult = Utils.checkServerUrl([serverObj]);
649
+ result.reason.push(...serverValidateResult.map((item) => item.type));
650
+ }
651
+ return result;
652
+ }
653
+ validateAuth(method, path) {
654
+ const pathObj = this.spec.paths[path];
655
+ const operationObject = pathObj[method];
656
+ const securities = operationObject.security;
657
+ const authSchemeArray = Utils.getAuthArray(securities, this.spec);
658
+ if (authSchemeArray.length === 0) {
659
+ return { isValid: true, reason: [] };
743
660
  }
744
- else if (errors.length > 0) {
745
- status = ValidationStatus.Error;
661
+ if (this.options.allowAPIKeyAuth ||
662
+ this.options.allowOauth2 ||
663
+ this.options.allowBearerTokenAuth) {
664
+ // Currently we don't support multiple auth in one operation
665
+ if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
666
+ return {
667
+ isValid: false,
668
+ reason: [ErrorType.MultipleAuthNotSupported],
669
+ };
670
+ }
671
+ for (const auths of authSchemeArray) {
672
+ if (auths.length === 1) {
673
+ if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
674
+ (this.options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
675
+ (this.options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
676
+ return { isValid: true, reason: [] };
677
+ }
678
+ }
679
+ }
746
680
  }
747
- return {
748
- status,
749
- warnings,
750
- errors,
681
+ return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
682
+ }
683
+ checkPostBodySchema(schema, isRequired = false) {
684
+ var _a;
685
+ const paramResult = {
686
+ requiredNum: 0,
687
+ optionalNum: 0,
688
+ isValid: true,
689
+ reason: [],
751
690
  };
691
+ if (Object.keys(schema).length === 0) {
692
+ return paramResult;
693
+ }
694
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
695
+ const isCopilot = this.projectType === ProjectType.Copilot;
696
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
697
+ paramResult.isValid = false;
698
+ paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
699
+ return paramResult;
700
+ }
701
+ if (schema.type === "string" ||
702
+ schema.type === "integer" ||
703
+ schema.type === "boolean" ||
704
+ schema.type === "number") {
705
+ if (isRequiredWithoutDefault) {
706
+ paramResult.requiredNum = paramResult.requiredNum + 1;
707
+ }
708
+ else {
709
+ paramResult.optionalNum = paramResult.optionalNum + 1;
710
+ }
711
+ }
712
+ else if (schema.type === "object") {
713
+ const { properties } = schema;
714
+ for (const property in properties) {
715
+ let isRequired = false;
716
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
717
+ isRequired = true;
718
+ }
719
+ const result = this.checkPostBodySchema(properties[property], isRequired);
720
+ paramResult.requiredNum += result.requiredNum;
721
+ paramResult.optionalNum += result.optionalNum;
722
+ paramResult.isValid = paramResult.isValid && result.isValid;
723
+ paramResult.reason.push(...result.reason);
724
+ }
725
+ }
726
+ else {
727
+ if (isRequiredWithoutDefault && !isCopilot) {
728
+ paramResult.isValid = false;
729
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
730
+ }
731
+ }
732
+ return paramResult;
752
733
  }
753
- static format(str, ...args) {
754
- let index = 0;
755
- return str.replace(/%s/g, () => {
756
- const arg = args[index++];
757
- return arg !== undefined ? arg : "";
758
- });
734
+ checkParamSchema(paramObject) {
735
+ const paramResult = {
736
+ requiredNum: 0,
737
+ optionalNum: 0,
738
+ isValid: true,
739
+ reason: [],
740
+ };
741
+ if (!paramObject) {
742
+ return paramResult;
743
+ }
744
+ const isCopilot = this.projectType === ProjectType.Copilot;
745
+ for (let i = 0; i < paramObject.length; i++) {
746
+ const param = paramObject[i];
747
+ const schema = param.schema;
748
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
749
+ paramResult.isValid = false;
750
+ paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
751
+ continue;
752
+ }
753
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
754
+ if (isCopilot) {
755
+ if (isRequiredWithoutDefault) {
756
+ paramResult.requiredNum = paramResult.requiredNum + 1;
757
+ }
758
+ else {
759
+ paramResult.optionalNum = paramResult.optionalNum + 1;
760
+ }
761
+ continue;
762
+ }
763
+ if (param.in === "header" || param.in === "cookie") {
764
+ if (isRequiredWithoutDefault) {
765
+ paramResult.isValid = false;
766
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
767
+ }
768
+ continue;
769
+ }
770
+ if (schema.type !== "boolean" &&
771
+ schema.type !== "string" &&
772
+ schema.type !== "number" &&
773
+ schema.type !== "integer") {
774
+ if (isRequiredWithoutDefault) {
775
+ paramResult.isValid = false;
776
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
777
+ }
778
+ continue;
779
+ }
780
+ if (param.in === "query" || param.in === "path") {
781
+ if (isRequiredWithoutDefault) {
782
+ paramResult.requiredNum = paramResult.requiredNum + 1;
783
+ }
784
+ else {
785
+ paramResult.optionalNum = paramResult.optionalNum + 1;
786
+ }
787
+ }
788
+ }
789
+ return paramResult;
759
790
  }
760
- static getSafeRegistrationIdEnvName(authName) {
761
- if (!authName) {
762
- return "";
791
+ hasNestedObjectInSchema(schema) {
792
+ if (schema.type === "object") {
793
+ for (const property in schema.properties) {
794
+ const nestedSchema = schema.properties[property];
795
+ if (nestedSchema.type === "object") {
796
+ return true;
797
+ }
798
+ }
763
799
  }
764
- let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
765
- if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
766
- safeRegistrationIdEnvName = "PREFIX_" + safeRegistrationIdEnvName;
800
+ return false;
801
+ }
802
+ }
803
+
804
+ // Copyright (c) Microsoft Corporation.
805
+ class CopilotValidator extends Validator {
806
+ constructor(spec, options) {
807
+ super();
808
+ this.projectType = ProjectType.Copilot;
809
+ this.options = options;
810
+ this.spec = spec;
811
+ }
812
+ validateSpec() {
813
+ const result = { errors: [], warnings: [] };
814
+ // validate spec version
815
+ let validationResult = this.validateSpecVersion();
816
+ result.errors.push(...validationResult.errors);
817
+ // validate spec server
818
+ validationResult = this.validateSpecServer();
819
+ result.errors.push(...validationResult.errors);
820
+ // validate no supported API
821
+ validationResult = this.validateSpecNoSupportAPI();
822
+ result.errors.push(...validationResult.errors);
823
+ // validate operationId missing
824
+ validationResult = this.validateSpecOperationId();
825
+ result.warnings.push(...validationResult.warnings);
826
+ return result;
827
+ }
828
+ validateAPI(method, path) {
829
+ const result = { isValid: true, reason: [] };
830
+ method = method.toLocaleLowerCase();
831
+ // validate method and path
832
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
833
+ if (!methodAndPathResult.isValid) {
834
+ return methodAndPathResult;
835
+ }
836
+ const operationObject = this.spec.paths[path][method];
837
+ // validate auth
838
+ const authCheckResult = this.validateAuth(method, path);
839
+ result.reason.push(...authCheckResult.reason);
840
+ // validate operationId
841
+ if (!this.options.allowMissingId && !operationObject.operationId) {
842
+ result.reason.push(ErrorType.MissingOperationId);
843
+ }
844
+ // validate server
845
+ const validateServerResult = this.validateServer(method, path);
846
+ result.reason.push(...validateServerResult.reason);
847
+ // validate response
848
+ const validateResponseResult = this.validateResponse(method, path);
849
+ result.reason.push(...validateResponseResult.reason);
850
+ // validate requestBody
851
+ const requestBody = operationObject.requestBody;
852
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
853
+ if (requestJsonBody) {
854
+ const requestBodySchema = requestJsonBody.schema;
855
+ if (requestBodySchema.type !== "object") {
856
+ result.reason.push(ErrorType.PostBodySchemaIsNotJson);
857
+ }
858
+ const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
859
+ result.reason.push(...requestBodyParamResult.reason);
860
+ }
861
+ // validate parameters
862
+ const paramObject = operationObject.parameters;
863
+ const paramResult = this.checkParamSchema(paramObject);
864
+ result.reason.push(...paramResult.reason);
865
+ if (result.reason.length > 0) {
866
+ result.isValid = false;
867
+ }
868
+ return result;
869
+ }
870
+ }
871
+
872
+ // Copyright (c) Microsoft Corporation.
873
+ class SMEValidator extends Validator {
874
+ constructor(spec, options) {
875
+ super();
876
+ this.projectType = ProjectType.SME;
877
+ this.options = options;
878
+ this.spec = spec;
879
+ }
880
+ validateSpec() {
881
+ const result = { errors: [], warnings: [] };
882
+ // validate spec version
883
+ let validationResult = this.validateSpecVersion();
884
+ result.errors.push(...validationResult.errors);
885
+ // validate spec server
886
+ validationResult = this.validateSpecServer();
887
+ result.errors.push(...validationResult.errors);
888
+ // validate no supported API
889
+ validationResult = this.validateSpecNoSupportAPI();
890
+ result.errors.push(...validationResult.errors);
891
+ // validate operationId missing
892
+ if (this.options.allowMissingId) {
893
+ validationResult = this.validateSpecOperationId();
894
+ result.warnings.push(...validationResult.warnings);
895
+ }
896
+ return result;
897
+ }
898
+ validateAPI(method, path) {
899
+ const result = { isValid: true, reason: [] };
900
+ method = method.toLocaleLowerCase();
901
+ // validate method and path
902
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
903
+ if (!methodAndPathResult.isValid) {
904
+ return methodAndPathResult;
905
+ }
906
+ const operationObject = this.spec.paths[path][method];
907
+ // validate auth
908
+ const authCheckResult = this.validateAuth(method, path);
909
+ result.reason.push(...authCheckResult.reason);
910
+ // validate operationId
911
+ if (!this.options.allowMissingId && !operationObject.operationId) {
912
+ result.reason.push(ErrorType.MissingOperationId);
913
+ }
914
+ // validate server
915
+ const validateServerResult = this.validateServer(method, path);
916
+ result.reason.push(...validateServerResult.reason);
917
+ // validate response
918
+ const validateResponseResult = this.validateResponse(method, path);
919
+ result.reason.push(...validateResponseResult.reason);
920
+ let postBodyResult = {
921
+ requiredNum: 0,
922
+ optionalNum: 0,
923
+ isValid: true,
924
+ reason: [],
925
+ };
926
+ // validate requestBody
927
+ const requestBody = operationObject.requestBody;
928
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
929
+ if (Utils.containMultipleMediaTypes(requestBody)) {
930
+ result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
931
+ }
932
+ if (requestJsonBody) {
933
+ const requestBodySchema = requestJsonBody.schema;
934
+ postBodyResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
935
+ result.reason.push(...postBodyResult.reason);
936
+ }
937
+ // validate parameters
938
+ const paramObject = operationObject.parameters;
939
+ const paramResult = this.checkParamSchema(paramObject);
940
+ result.reason.push(...paramResult.reason);
941
+ // validate total parameters count
942
+ if (paramResult.isValid && postBodyResult.isValid) {
943
+ const paramCountResult = this.validateParamCount(postBodyResult, paramResult);
944
+ result.reason.push(...paramCountResult.reason);
945
+ }
946
+ if (result.reason.length > 0) {
947
+ result.isValid = false;
948
+ }
949
+ return result;
950
+ }
951
+ validateParamCount(postBodyResult, paramResult) {
952
+ const result = { isValid: true, reason: [] };
953
+ const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
954
+ const totalParams = totalRequiredParams + postBodyResult.optionalNum + paramResult.optionalNum;
955
+ if (totalRequiredParams > 1) {
956
+ if (!this.options.allowMultipleParameters ||
957
+ totalRequiredParams > SMEValidator.SMERequiredParamsMaxNum) {
958
+ result.reason.push(ErrorType.ExceededRequiredParamsLimit);
959
+ }
960
+ }
961
+ else if (totalParams === 0) {
962
+ result.reason.push(ErrorType.NoParameter);
963
+ }
964
+ return result;
965
+ }
966
+ }
967
+ SMEValidator.SMERequiredParamsMaxNum = 5;
968
+
969
+ // Copyright (c) Microsoft Corporation.
970
+ class TeamsAIValidator extends Validator {
971
+ constructor(spec, options) {
972
+ super();
973
+ this.projectType = ProjectType.TeamsAi;
974
+ this.options = options;
975
+ this.spec = spec;
976
+ }
977
+ validateSpec() {
978
+ const result = { errors: [], warnings: [] };
979
+ // validate spec server
980
+ let validationResult = this.validateSpecServer();
981
+ result.errors.push(...validationResult.errors);
982
+ // validate no supported API
983
+ validationResult = this.validateSpecNoSupportAPI();
984
+ result.errors.push(...validationResult.errors);
985
+ return result;
986
+ }
987
+ validateAPI(method, path) {
988
+ const result = { isValid: true, reason: [] };
989
+ method = method.toLocaleLowerCase();
990
+ // validate method and path
991
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
992
+ if (!methodAndPathResult.isValid) {
993
+ return methodAndPathResult;
994
+ }
995
+ const operationObject = this.spec.paths[path][method];
996
+ // validate operationId
997
+ if (!this.options.allowMissingId && !operationObject.operationId) {
998
+ result.reason.push(ErrorType.MissingOperationId);
999
+ }
1000
+ // validate server
1001
+ const validateServerResult = this.validateServer(method, path);
1002
+ result.reason.push(...validateServerResult.reason);
1003
+ if (result.reason.length > 0) {
1004
+ result.isValid = false;
1005
+ }
1006
+ return result;
1007
+ }
1008
+ }
1009
+
1010
+ class ValidatorFactory {
1011
+ static create(spec, options) {
1012
+ var _a;
1013
+ const type = (_a = options.projectType) !== null && _a !== void 0 ? _a : ProjectType.SME;
1014
+ switch (type) {
1015
+ case ProjectType.SME:
1016
+ return new SMEValidator(spec, options);
1017
+ case ProjectType.Copilot:
1018
+ return new CopilotValidator(spec, options);
1019
+ case ProjectType.TeamsAi:
1020
+ return new TeamsAIValidator(spec, options);
1021
+ default:
1022
+ throw new Error(`Invalid project type: ${type}`);
767
1023
  }
768
- return safeRegistrationIdEnvName;
769
1024
  }
770
1025
  }
771
1026
 
@@ -788,6 +1043,9 @@ class SpecParser {
788
1043
  allowBearerTokenAuth: false,
789
1044
  allowOauth2: false,
790
1045
  allowMethods: ["get", "post"],
1046
+ allowConversationStarters: false,
1047
+ allowResponseSemantics: false,
1048
+ allowConfirmation: false,
791
1049
  projectType: ProjectType.SME,
792
1050
  };
793
1051
  this.pathOrSpec = pathOrDoc;
@@ -803,11 +1061,7 @@ class SpecParser {
803
1061
  try {
804
1062
  try {
805
1063
  await this.loadSpec();
806
- await this.parser.validate(this.spec, {
807
- validate: {
808
- schema: false,
809
- },
810
- });
1064
+ await this.parser.validate(this.spec);
811
1065
  }
812
1066
  catch (e) {
813
1067
  return {
@@ -816,16 +1070,46 @@ class SpecParser {
816
1070
  errors: [{ type: ErrorType.SpecNotValid, content: e.toString() }],
817
1071
  };
818
1072
  }
1073
+ const errors = [];
1074
+ const warnings = [];
819
1075
  if (!this.options.allowSwagger && this.isSwaggerFile) {
820
1076
  return {
821
1077
  status: ValidationStatus.Error,
822
1078
  warnings: [],
823
1079
  errors: [
824
- { type: ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported },
1080
+ {
1081
+ type: ErrorType.SwaggerNotSupported,
1082
+ content: ConstantString.SwaggerNotSupported,
1083
+ },
825
1084
  ],
826
1085
  };
827
1086
  }
828
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
1087
+ // Remote reference not supported
1088
+ const refPaths = this.parser.$refs.paths();
1089
+ // refPaths [0] is the current spec file path
1090
+ if (refPaths.length > 1) {
1091
+ errors.push({
1092
+ type: ErrorType.RemoteRefNotSupported,
1093
+ content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
1094
+ data: refPaths,
1095
+ });
1096
+ }
1097
+ const validator = this.getValidator(this.spec);
1098
+ const validationResult = validator.validateSpec();
1099
+ warnings.push(...validationResult.warnings);
1100
+ errors.push(...validationResult.errors);
1101
+ let status = ValidationStatus.Valid;
1102
+ if (warnings.length > 0 && errors.length === 0) {
1103
+ status = ValidationStatus.Warning;
1104
+ }
1105
+ else if (errors.length > 0) {
1106
+ status = ValidationStatus.Error;
1107
+ }
1108
+ return {
1109
+ status: status,
1110
+ warnings: warnings,
1111
+ errors: errors,
1112
+ };
829
1113
  }
830
1114
  catch (err) {
831
1115
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -834,17 +1118,20 @@ class SpecParser {
834
1118
  async listSupportedAPIInfo() {
835
1119
  try {
836
1120
  await this.loadSpec();
837
- const apiMap = this.getAllSupportedAPIs(this.spec);
1121
+ const apiMap = this.getAPIs(this.spec);
838
1122
  const apiInfos = [];
839
1123
  for (const key in apiMap) {
840
- const pathObjectItem = apiMap[key];
1124
+ const { operation, isValid } = apiMap[key];
1125
+ if (!isValid) {
1126
+ continue;
1127
+ }
841
1128
  const [method, path] = key.split(" ");
842
- const operationId = pathObjectItem.operationId;
1129
+ const operationId = operation.operationId;
843
1130
  // In Browser environment, this api is by default not support api without operationId
844
1131
  if (!operationId) {
845
1132
  continue;
846
1133
  }
847
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
1134
+ const command = Utils.parseApiInfo(operation, this.options);
848
1135
  const apiInfo = {
849
1136
  method: method,
850
1137
  path: path,
@@ -853,9 +1140,6 @@ class SpecParser {
853
1140
  parameters: command.parameters,
854
1141
  description: command.description,
855
1142
  };
856
- if (warning) {
857
- apiInfo.warning = warning;
858
- }
859
1143
  apiInfos.push(apiInfo);
860
1144
  }
861
1145
  return apiInfos;
@@ -914,13 +1198,18 @@ class SpecParser {
914
1198
  this.spec = (await this.parser.dereference(clonedUnResolveSpec));
915
1199
  }
916
1200
  }
917
- getAllSupportedAPIs(spec) {
918
- if (this.apiMap !== undefined) {
919
- return this.apiMap;
1201
+ getAPIs(spec) {
1202
+ const validator = this.getValidator(spec);
1203
+ const apiMap = validator.listAPIs();
1204
+ return apiMap;
1205
+ }
1206
+ getValidator(spec) {
1207
+ if (this.validator) {
1208
+ return this.validator;
920
1209
  }
921
- const result = Utils.listSupportedAPIs(spec, this.options);
922
- this.apiMap = result;
923
- return result;
1210
+ const validator = ValidatorFactory.create(spec, this.options);
1211
+ this.validator = validator;
1212
+ return validator;
924
1213
  }
925
1214
  }
926
1215
 
@@ -928,7 +1217,7 @@ class SpecParser {
928
1217
  class AdaptiveCardGenerator {
929
1218
  static generateAdaptiveCard(operationItem) {
930
1219
  try {
931
- const json = Utils.getResponseJson(operationItem);
1220
+ const { json } = Utils.getResponseJson(operationItem);
932
1221
  let cardBody = [];
933
1222
  let schema = json.schema;
934
1223
  let jsonPath = "$";