@microsoft/m365-spec-parser 0.1.1-alpha.a372ccf67.0 → 0.1.1-alpha.ad8f60cf1.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,253 +186,33 @@ 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(authSchemaArray, options) {
366
- if (authSchemaArray.length === 0) {
367
- return true;
368
- }
369
- if (options.allowAPIKeyAuth || options.allowOauth2) {
370
- // Currently we don't support multiple auth in one operation
371
- if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
372
- return false;
373
- }
374
- for (const auths of authSchemaArray) {
375
- if (auths.length === 1) {
376
- if (!options.allowOauth2 &&
377
- options.allowAPIKeyAuth &&
378
- Utils.isAPIKeyAuth(auths[0].authSchema)) {
379
- return true;
380
- }
381
- else if (!options.allowAPIKeyAuth &&
382
- options.allowOauth2 &&
383
- Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema)) {
384
- return true;
385
- }
386
- else if (options.allowAPIKeyAuth &&
387
- options.allowOauth2 &&
388
- (Utils.isAPIKeyAuth(auths[0].authSchema) ||
389
- Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema))) {
390
- return true;
391
- }
392
- }
393
- }
394
- }
395
- return false;
192
+ static isBearerTokenAuth(authScheme) {
193
+ return authScheme.type === "http" && authScheme.scheme === "bearer";
396
194
  }
397
- static isAPIKeyAuth(authSchema) {
398
- return authSchema.type === "apiKey";
195
+ static isAPIKeyAuth(authScheme) {
196
+ return authScheme.type === "apiKey";
399
197
  }
400
- static isOAuthWithAuthCodeFlow(authSchema) {
401
- if (authSchema.type === "oauth2" && authSchema.flows && authSchema.flows.authorizationCode) {
402
- return true;
403
- }
404
- return false;
198
+ static isOAuthWithAuthCodeFlow(authScheme) {
199
+ return !!(authScheme.type === "oauth2" &&
200
+ authScheme.flows &&
201
+ authScheme.flows.authorizationCode);
405
202
  }
406
203
  static getAuthArray(securities, spec) {
407
204
  var _a;
408
205
  const result = [];
409
206
  const securitySchemas = (_a = spec.components) === null || _a === void 0 ? void 0 : _a.securitySchemes;
410
- if (securities && securitySchemas) {
411
- for (let i = 0; i < securities.length; i++) {
412
- 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];
413
211
  const authArray = [];
414
212
  for (const name in security) {
415
213
  const auth = securitySchemas[name];
416
214
  authArray.push({
417
- authSchema: auth,
215
+ authScheme: auth,
418
216
  name: name,
419
217
  });
420
218
  }
@@ -426,17 +224,39 @@ class Utils {
426
224
  result.sort((a, b) => a[0].name.localeCompare(b[0].name));
427
225
  return result;
428
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
+ }
429
246
  static updateFirstLetter(str) {
430
247
  return str.charAt(0).toUpperCase() + str.slice(1);
431
248
  }
432
- static getResponseJson(operationObject, isTeamsAiProject = false) {
249
+ static getResponseJson(operationObject) {
433
250
  var _a, _b;
434
251
  let json = {};
252
+ let multipleMediaType = false;
435
253
  for (const code of ConstantString.ResponseCodeFor20X) {
436
254
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
437
255
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
256
+ multipleMediaType = false;
438
257
  json = responseObject.content["application/json"];
439
- if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
258
+ if (Utils.containMultipleMediaTypes(responseObject)) {
259
+ multipleMediaType = true;
440
260
  json = {};
441
261
  }
442
262
  else {
@@ -444,7 +264,7 @@ class Utils {
444
264
  }
445
265
  }
446
266
  }
447
- return json;
267
+ return { json, multipleMediaType };
448
268
  }
449
269
  static convertPathToCamelCase(path) {
450
270
  const pathSegments = path.split(/[./{]/);
@@ -464,10 +284,10 @@ class Utils {
464
284
  return undefined;
465
285
  }
466
286
  }
467
- static resolveServerUrl(url) {
287
+ static resolveEnv(str) {
468
288
  const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
469
- let matches = placeHolderReg.exec(url);
470
- let newUrl = url;
289
+ let matches = placeHolderReg.exec(str);
290
+ let newStr = str;
471
291
  while (matches != null) {
472
292
  const envVar = matches[1];
473
293
  const envVal = process.env[envVar];
@@ -475,17 +295,17 @@ class Utils {
475
295
  throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
476
296
  }
477
297
  else {
478
- newUrl = newUrl.replace(matches[0], envVal);
298
+ newStr = newStr.replace(matches[0], envVal);
479
299
  }
480
- matches = placeHolderReg.exec(url);
300
+ matches = placeHolderReg.exec(str);
481
301
  }
482
- return newUrl;
302
+ return newStr;
483
303
  }
484
304
  static checkServerUrl(servers) {
485
305
  const errors = [];
486
306
  let serverUrl;
487
307
  try {
488
- serverUrl = Utils.resolveServerUrl(servers[0].url);
308
+ serverUrl = Utils.resolveEnv(servers[0].url);
489
309
  }
490
310
  catch (err) {
491
311
  errors.push({
@@ -516,6 +336,7 @@ class Utils {
516
336
  return errors;
517
337
  }
518
338
  static validateServer(spec, options) {
339
+ var _a;
519
340
  const errors = [];
520
341
  let hasTopLevelServers = false;
521
342
  let hasPathLevelServers = false;
@@ -536,7 +357,7 @@ class Utils {
536
357
  }
537
358
  for (const method in methods) {
538
359
  const operationObject = methods[method];
539
- if (Utils.isSupportedApi(method, path, spec, options)) {
360
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
540
361
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
541
362
  hasOperationLevelServers = true;
542
363
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -579,6 +400,7 @@ class Utils {
579
400
  Utils.updateParameterWithInputType(schema, parameter);
580
401
  }
581
402
  if (isRequired && schema.default === undefined) {
403
+ parameter.isRequired = true;
582
404
  requiredParams.push(parameter);
583
405
  }
584
406
  else {
@@ -642,6 +464,7 @@ class Utils {
642
464
  }
643
465
  if (param.in !== "header" && param.in !== "cookie") {
644
466
  if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
467
+ parameter.isRequired = true;
645
468
  requiredParams.push(parameter);
646
469
  }
647
470
  else {
@@ -661,13 +484,7 @@ class Utils {
661
484
  }
662
485
  }
663
486
  const operationId = operationItem.operationId;
664
- const parameters = [];
665
- if (requiredParams.length !== 0) {
666
- parameters.push(...requiredParams);
667
- }
668
- else {
669
- parameters.push(optionalParams[0]);
670
- }
487
+ const parameters = [...requiredParams, ...optionalParams];
671
488
  const command = {
672
489
  context: ["compose"],
673
490
  type: "query",
@@ -676,104 +493,534 @@ class Utils {
676
493
  parameters: parameters,
677
494
  description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
678
495
  };
679
- let warning = undefined;
680
- if (requiredParams.length === 0 && optionalParams.length > 1) {
681
- warning = {
682
- type: WarningType.OperationOnlyContainsOptionalParam,
683
- content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, operationId),
684
- data: operationId,
685
- };
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;
686
512
  }
687
- return [command, warning];
513
+ return safeRegistrationIdEnvName;
688
514
  }
689
- static listSupportedAPIs(spec, options) {
690
- 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;
691
534
  const result = {};
692
535
  for (const path in paths) {
693
536
  const methods = paths[path];
694
537
  for (const method in methods) {
695
- if (Utils.isSupportedApi(method, path, spec, options)) {
696
- const operationObject = methods[method];
697
- 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
+ };
698
546
  }
699
547
  }
700
548
  }
549
+ this.apiMap = result;
701
550
  return result;
702
551
  }
703
- static validateSpec(spec, parser, isSwaggerFile, options) {
704
- const errors = [];
705
- const warnings = [];
706
- if (isSwaggerFile) {
707
- warnings.push({
708
- type: WarningType.ConvertSwaggerToOpenAPI,
709
- content: ConstantString.ConvertSwaggerToOpenAPI,
710
- });
711
- }
712
- // Server validation
713
- const serverErrors = Utils.validateServer(spec, options);
714
- errors.push(...serverErrors);
715
- // Remote reference not supported
716
- const refPaths = parser.$refs.paths();
717
- // refPaths [0] is the current spec file path
718
- if (refPaths.length > 1) {
719
- errors.push({
720
- type: ErrorType.RemoteRefNotSupported,
721
- content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
722
- 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,
723
559
  });
724
560
  }
725
- // No supported API
726
- const apiMap = Utils.listSupportedAPIs(spec, options);
727
- if (Object.keys(apiMap).length === 0) {
728
- 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({
729
581
  type: ErrorType.NoSupportedApi,
730
582
  content: ConstantString.NoSupportedApi,
583
+ data,
731
584
  });
732
585
  }
586
+ return result;
587
+ }
588
+ validateSpecOperationId() {
589
+ const result = { errors: [], warnings: [] };
590
+ const apiMap = this.listAPIs();
733
591
  // OperationId missing
734
592
  const apisMissingOperationId = [];
735
593
  for (const key in apiMap) {
736
- const pathObjectItem = apiMap[key];
737
- if (!pathObjectItem.operationId) {
594
+ const { operation } = apiMap[key];
595
+ if (!operation.operationId) {
738
596
  apisMissingOperationId.push(key);
739
597
  }
740
598
  }
741
599
  if (apisMissingOperationId.length > 0) {
742
- warnings.push({
600
+ result.warnings.push({
743
601
  type: WarningType.OperationIdMissing,
744
602
  content: Utils.format(ConstantString.MissingOperationId, apisMissingOperationId.join(", ")),
745
603
  data: apisMissingOperationId,
746
604
  });
747
605
  }
748
- let status = ValidationStatus.Valid;
749
- if (warnings.length > 0 && errors.length === 0) {
750
- 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
+ }
751
636
  }
752
- else if (errors.length > 0) {
753
- status = ValidationStatus.Error;
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);
754
645
  }
755
- return {
756
- status,
757
- warnings,
758
- errors,
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: [] };
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: [],
759
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;
760
733
  }
761
- static format(str, ...args) {
762
- let index = 0;
763
- return str.replace(/%s/g, () => {
764
- const arg = args[index++];
765
- return arg !== undefined ? arg : "";
766
- });
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;
767
790
  }
768
- static getSafeRegistrationIdEnvName(authName) {
769
- if (!authName) {
770
- 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
+ }
771
799
  }
772
- let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
773
- if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
774
- 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}`);
775
1023
  }
776
- return safeRegistrationIdEnvName;
777
1024
  }
778
1025
  }
779
1026
 
@@ -793,9 +1040,14 @@ class SpecParser {
793
1040
  allowSwagger: false,
794
1041
  allowAPIKeyAuth: false,
795
1042
  allowMultipleParameters: false,
1043
+ allowBearerTokenAuth: false,
796
1044
  allowOauth2: false,
797
1045
  allowMethods: ["get", "post"],
1046
+ allowConversationStarters: false,
1047
+ allowResponseSemantics: false,
1048
+ allowConfirmation: false,
798
1049
  projectType: ProjectType.SME,
1050
+ isGptPlugin: false,
799
1051
  };
800
1052
  this.pathOrSpec = pathOrDoc;
801
1053
  this.parser = new SwaggerParser();
@@ -810,11 +1062,7 @@ class SpecParser {
810
1062
  try {
811
1063
  try {
812
1064
  await this.loadSpec();
813
- await this.parser.validate(this.spec, {
814
- validate: {
815
- schema: false,
816
- },
817
- });
1065
+ await this.parser.validate(this.spec);
818
1066
  }
819
1067
  catch (e) {
820
1068
  return {
@@ -823,16 +1071,46 @@ class SpecParser {
823
1071
  errors: [{ type: ErrorType.SpecNotValid, content: e.toString() }],
824
1072
  };
825
1073
  }
1074
+ const errors = [];
1075
+ const warnings = [];
826
1076
  if (!this.options.allowSwagger && this.isSwaggerFile) {
827
1077
  return {
828
1078
  status: ValidationStatus.Error,
829
1079
  warnings: [],
830
1080
  errors: [
831
- { type: ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported },
1081
+ {
1082
+ type: ErrorType.SwaggerNotSupported,
1083
+ content: ConstantString.SwaggerNotSupported,
1084
+ },
832
1085
  ],
833
1086
  };
834
1087
  }
835
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
1088
+ // Remote reference not supported
1089
+ const refPaths = this.parser.$refs.paths();
1090
+ // refPaths [0] is the current spec file path
1091
+ if (refPaths.length > 1) {
1092
+ errors.push({
1093
+ type: ErrorType.RemoteRefNotSupported,
1094
+ content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
1095
+ data: refPaths,
1096
+ });
1097
+ }
1098
+ const validator = this.getValidator(this.spec);
1099
+ const validationResult = validator.validateSpec();
1100
+ warnings.push(...validationResult.warnings);
1101
+ errors.push(...validationResult.errors);
1102
+ let status = ValidationStatus.Valid;
1103
+ if (warnings.length > 0 && errors.length === 0) {
1104
+ status = ValidationStatus.Warning;
1105
+ }
1106
+ else if (errors.length > 0) {
1107
+ status = ValidationStatus.Error;
1108
+ }
1109
+ return {
1110
+ status: status,
1111
+ warnings: warnings,
1112
+ errors: errors,
1113
+ };
836
1114
  }
837
1115
  catch (err) {
838
1116
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -841,17 +1119,20 @@ class SpecParser {
841
1119
  async listSupportedAPIInfo() {
842
1120
  try {
843
1121
  await this.loadSpec();
844
- const apiMap = this.getAllSupportedAPIs(this.spec);
1122
+ const apiMap = this.getAPIs(this.spec);
845
1123
  const apiInfos = [];
846
1124
  for (const key in apiMap) {
847
- const pathObjectItem = apiMap[key];
1125
+ const { operation, isValid } = apiMap[key];
1126
+ if (!isValid) {
1127
+ continue;
1128
+ }
848
1129
  const [method, path] = key.split(" ");
849
- const operationId = pathObjectItem.operationId;
1130
+ const operationId = operation.operationId;
850
1131
  // In Browser environment, this api is by default not support api without operationId
851
1132
  if (!operationId) {
852
1133
  continue;
853
1134
  }
854
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
1135
+ const command = Utils.parseApiInfo(operation, this.options);
855
1136
  const apiInfo = {
856
1137
  method: method,
857
1138
  path: path,
@@ -860,9 +1141,6 @@ class SpecParser {
860
1141
  parameters: command.parameters,
861
1142
  description: command.description,
862
1143
  };
863
- if (warning) {
864
- apiInfo.warning = warning;
865
- }
866
1144
  apiInfos.push(apiInfo);
867
1145
  }
868
1146
  return apiInfos;
@@ -921,13 +1199,18 @@ class SpecParser {
921
1199
  this.spec = (await this.parser.dereference(clonedUnResolveSpec));
922
1200
  }
923
1201
  }
924
- getAllSupportedAPIs(spec) {
925
- if (this.apiMap !== undefined) {
926
- return this.apiMap;
1202
+ getAPIs(spec) {
1203
+ const validator = this.getValidator(spec);
1204
+ const apiMap = validator.listAPIs();
1205
+ return apiMap;
1206
+ }
1207
+ getValidator(spec) {
1208
+ if (this.validator) {
1209
+ return this.validator;
927
1210
  }
928
- const result = Utils.listSupportedAPIs(spec, this.options);
929
- this.apiMap = result;
930
- return result;
1211
+ const validator = ValidatorFactory.create(spec, this.options);
1212
+ this.validator = validator;
1213
+ return validator;
931
1214
  }
932
1215
  }
933
1216
 
@@ -935,7 +1218,7 @@ class SpecParser {
935
1218
  class AdaptiveCardGenerator {
936
1219
  static generateAdaptiveCard(operationItem) {
937
1220
  try {
938
- const json = Utils.getResponseJson(operationItem);
1221
+ const { json } = Utils.getResponseJson(operationItem);
939
1222
  let cardBody = [];
940
1223
  let schema = json.schema;
941
1224
  let jsonPath = "$";