@microsoft/m365-spec-parser 0.1.1-alpha.2a327dc81.0 → 0.1.1-alpha.2c983f96a.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,9 @@ 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
- ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
96
113
  ConstantString.ResponseCodeFor20X = [
97
114
  "200",
98
115
  "201",
@@ -153,7 +170,8 @@ ConstantString.CommandDescriptionMaxLens = 128;
153
170
  ConstantString.ParameterDescriptionMaxLens = 128;
154
171
  ConstantString.CommandTitleMaxLens = 32;
155
172
  ConstantString.ParameterTitleMaxLens = 32;
156
- ConstantString.SMERequiredParamsMaxNum = 5;
173
+ ConstantString.SMERequiredParamsMaxNum = 5;
174
+ ConstantString.DefaultPluginId = "plugin_1";
157
175
 
158
176
  // Copyright (c) Microsoft Corporation.
159
177
  class Utils {
@@ -168,221 +186,9 @@ class Utils {
168
186
  }
169
187
  return false;
170
188
  }
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
189
  static containMultipleMediaTypes(bodyObject) {
270
190
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
271
191
  }
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
192
  static isBearerTokenAuth(authScheme) {
387
193
  return authScheme.type === "http" && authScheme.scheme === "bearer";
388
194
  }
@@ -390,18 +196,18 @@ class Utils {
390
196
  return authScheme.type === "apiKey";
391
197
  }
392
198
  static isOAuthWithAuthCodeFlow(authScheme) {
393
- if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
394
- return true;
395
- }
396
- return false;
199
+ return !!(authScheme.type === "oauth2" &&
200
+ authScheme.flows &&
201
+ authScheme.flows.authorizationCode);
397
202
  }
398
203
  static getAuthArray(securities, spec) {
399
204
  var _a;
400
205
  const result = [];
401
206
  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];
207
+ const securitiesArr = securities !== null && securities !== void 0 ? securities : spec.security;
208
+ if (securitiesArr && securitySchemas) {
209
+ for (let i = 0; i < securitiesArr.length; i++) {
210
+ const security = securitiesArr[i];
405
211
  const authArray = [];
406
212
  for (const name in security) {
407
213
  const auth = securitySchemas[name];
@@ -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);
@@ -655,13 +484,7 @@ class Utils {
655
484
  }
656
485
  }
657
486
  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
- }
487
+ const parameters = [...requiredParams, ...optionalParams];
665
488
  const command = {
666
489
  context: ["compose"],
667
490
  type: "query",
@@ -670,117 +493,534 @@ class Utils {
670
493
  parameters: parameters,
671
494
  description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
672
495
  };
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
- };
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;
680
512
  }
681
- return [command, warning];
513
+ return safeRegistrationIdEnvName;
682
514
  }
683
- static listSupportedAPIs(spec, options) {
684
- 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;
685
534
  const result = {};
686
535
  for (const path in paths) {
687
536
  const methods = paths[path];
688
537
  for (const method in methods) {
689
- if (Utils.isSupportedApi(method, path, spec, options)) {
690
- const operationObject = methods[method];
691
- 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
+ };
692
546
  }
693
547
  }
694
548
  }
549
+ this.apiMap = result;
695
550
  return result;
696
551
  }
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,
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,
704
559
  });
705
560
  }
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({
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({
723
581
  type: ErrorType.NoSupportedApi,
724
582
  content: ConstantString.NoSupportedApi,
583
+ data,
725
584
  });
726
585
  }
586
+ return result;
587
+ }
588
+ validateSpecOperationId() {
589
+ const result = { errors: [], warnings: [] };
590
+ const apiMap = this.listAPIs();
727
591
  // OperationId missing
728
592
  const apisMissingOperationId = [];
729
593
  for (const key in apiMap) {
730
- const pathObjectItem = apiMap[key];
731
- if (!pathObjectItem.operationId) {
594
+ const { operation } = apiMap[key];
595
+ if (!operation.operationId) {
732
596
  apisMissingOperationId.push(key);
733
597
  }
734
598
  }
735
599
  if (apisMissingOperationId.length > 0) {
736
- warnings.push({
600
+ result.warnings.push({
737
601
  type: WarningType.OperationIdMissing,
738
602
  content: Utils.format(ConstantString.MissingOperationId, apisMissingOperationId.join(", ")),
739
603
  data: apisMissingOperationId,
740
604
  });
741
605
  }
742
- let status = ValidationStatus.Valid;
743
- if (warnings.length > 0 && errors.length === 0) {
744
- 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;
745
614
  }
746
- else if (errors.length > 0) {
747
- status = ValidationStatus.Error;
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;
748
620
  }
749
- return {
750
- status,
751
- warnings,
752
- errors,
753
- };
621
+ return result;
754
622
  }
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
- });
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;
761
638
  }
762
- static getSafeRegistrationIdEnvName(authName) {
763
- if (!authName) {
764
- return "";
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);
765
645
  }
766
- let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
767
- if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
768
- safeRegistrationIdEnvName = "PREFIX_" + safeRegistrationIdEnvName;
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));
769
650
  }
770
- return safeRegistrationIdEnvName;
651
+ return result;
771
652
  }
772
- static getAllAPICount(spec) {
773
- let count = 0;
774
- const paths = spec.paths;
775
- for (const path in paths) {
776
- const methods = paths[path];
777
- for (const method in methods) {
778
- if (ConstantString.AllOperationMethods.includes(method)) {
779
- count++;
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: [] };
660
+ }
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
+ }
680
+ }
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: [],
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;
780
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);
781
724
  }
782
725
  }
783
- return count;
726
+ else {
727
+ if (isRequiredWithoutDefault && !isCopilot) {
728
+ paramResult.isValid = false;
729
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
730
+ }
731
+ }
732
+ return paramResult;
733
+ }
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;
790
+ }
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
+ }
799
+ }
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}`);
1023
+ }
784
1024
  }
785
1025
  }
786
1026
 
@@ -803,6 +1043,9 @@ class SpecParser {
803
1043
  allowBearerTokenAuth: false,
804
1044
  allowOauth2: false,
805
1045
  allowMethods: ["get", "post"],
1046
+ allowConversationStarters: false,
1047
+ allowResponseSemantics: false,
1048
+ allowConfirmation: false,
806
1049
  projectType: ProjectType.SME,
807
1050
  };
808
1051
  this.pathOrSpec = pathOrDoc;
@@ -818,11 +1061,7 @@ class SpecParser {
818
1061
  try {
819
1062
  try {
820
1063
  await this.loadSpec();
821
- await this.parser.validate(this.spec, {
822
- validate: {
823
- schema: false,
824
- },
825
- });
1064
+ await this.parser.validate(this.spec);
826
1065
  }
827
1066
  catch (e) {
828
1067
  return {
@@ -831,16 +1070,46 @@ class SpecParser {
831
1070
  errors: [{ type: ErrorType.SpecNotValid, content: e.toString() }],
832
1071
  };
833
1072
  }
1073
+ const errors = [];
1074
+ const warnings = [];
834
1075
  if (!this.options.allowSwagger && this.isSwaggerFile) {
835
1076
  return {
836
1077
  status: ValidationStatus.Error,
837
1078
  warnings: [],
838
1079
  errors: [
839
- { type: ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported },
1080
+ {
1081
+ type: ErrorType.SwaggerNotSupported,
1082
+ content: ConstantString.SwaggerNotSupported,
1083
+ },
840
1084
  ],
841
1085
  };
842
1086
  }
843
- 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
+ };
844
1113
  }
845
1114
  catch (err) {
846
1115
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -849,17 +1118,20 @@ class SpecParser {
849
1118
  async listSupportedAPIInfo() {
850
1119
  try {
851
1120
  await this.loadSpec();
852
- const apiMap = this.getAllSupportedAPIs(this.spec);
1121
+ const apiMap = this.getAPIs(this.spec);
853
1122
  const apiInfos = [];
854
1123
  for (const key in apiMap) {
855
- const pathObjectItem = apiMap[key];
1124
+ const { operation, isValid } = apiMap[key];
1125
+ if (!isValid) {
1126
+ continue;
1127
+ }
856
1128
  const [method, path] = key.split(" ");
857
- const operationId = pathObjectItem.operationId;
1129
+ const operationId = operation.operationId;
858
1130
  // In Browser environment, this api is by default not support api without operationId
859
1131
  if (!operationId) {
860
1132
  continue;
861
1133
  }
862
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
1134
+ const command = Utils.parseApiInfo(operation, this.options);
863
1135
  const apiInfo = {
864
1136
  method: method,
865
1137
  path: path,
@@ -868,9 +1140,6 @@ class SpecParser {
868
1140
  parameters: command.parameters,
869
1141
  description: command.description,
870
1142
  };
871
- if (warning) {
872
- apiInfo.warning = warning;
873
- }
874
1143
  apiInfos.push(apiInfo);
875
1144
  }
876
1145
  return apiInfos;
@@ -929,13 +1198,18 @@ class SpecParser {
929
1198
  this.spec = (await this.parser.dereference(clonedUnResolveSpec));
930
1199
  }
931
1200
  }
932
- getAllSupportedAPIs(spec) {
933
- if (this.apiMap !== undefined) {
934
- 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;
935
1209
  }
936
- const result = Utils.listSupportedAPIs(spec, this.options);
937
- this.apiMap = result;
938
- return result;
1210
+ const validator = ValidatorFactory.create(spec, this.options);
1211
+ this.validator = validator;
1212
+ return validator;
939
1213
  }
940
1214
  }
941
1215
 
@@ -943,7 +1217,7 @@ class SpecParser {
943
1217
  class AdaptiveCardGenerator {
944
1218
  static generateAdaptiveCard(operationItem) {
945
1219
  try {
946
- const json = Utils.getResponseJson(operationItem);
1220
+ const { json } = Utils.getResponseJson(operationItem);
947
1221
  let cardBody = [];
948
1222
  let schema = json.schema;
949
1223
  let jsonPath = "$";