@microsoft/m365-spec-parser 0.1.1-alpha.cf377d39f.0 → 0.1.1-alpha.ded43fb2d.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,7 +45,8 @@ var ErrorType;
45
45
  ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
46
46
  ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
47
47
  ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
48
- ErrorType["MultipleAPIKeyNotSupported"] = "multiple-api-key-not-supported";
48
+ ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
49
+ ErrorType["SpecVersionNotSupported"] = "spec-version-not-supported";
49
50
  ErrorType["ListFailed"] = "list-failed";
50
51
  ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
51
52
  ErrorType["FilterSpecFailed"] = "filter-spec-failed";
@@ -54,6 +55,21 @@ var ErrorType;
54
55
  ErrorType["GenerateFailed"] = "generate-failed";
55
56
  ErrorType["ValidateFailed"] = "validate-failed";
56
57
  ErrorType["GetSpecFailed"] = "get-spec-failed";
58
+ ErrorType["AuthTypeIsNotSupported"] = "auth-type-is-not-supported";
59
+ ErrorType["MissingOperationId"] = "missing-operation-id";
60
+ ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
61
+ ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
62
+ ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
63
+ ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
64
+ ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
65
+ ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
66
+ ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
67
+ ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
68
+ ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
69
+ ErrorType["NoParameter"] = "no-parameter";
70
+ ErrorType["NoAPIInfo"] = "no-api-info";
71
+ ErrorType["MethodNotAllowed"] = "method-not-allowed";
72
+ ErrorType["UrlPathNotExist"] = "url-path-not-exist";
57
73
  ErrorType["Cancelled"] = "cancelled";
58
74
  ErrorType["Unknown"] = "unknown";
59
75
  })(ErrorType || (ErrorType = {}));
@@ -76,7 +92,13 @@ var ValidationStatus;
76
92
  ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
77
93
  ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
78
94
  ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
79
- })(ValidationStatus || (ValidationStatus = {}));
95
+ })(ValidationStatus || (ValidationStatus = {}));
96
+ var ProjectType;
97
+ (function (ProjectType) {
98
+ ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
99
+ ProjectType[ProjectType["SME"] = 1] = "SME";
100
+ ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
101
+ })(ProjectType || (ProjectType = {}));
80
102
 
81
103
  // Copyright (c) Microsoft Corporation.
82
104
  class SpecParserError extends Error {
@@ -103,7 +125,9 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
103
125
  ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
104
126
  ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
105
127
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
106
- ConstantString.MultipleAPIKeyNotSupported = "Multiple API keys are not supported. Please make sure that all selected APIs use the same API key.";
128
+ ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
129
+ ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
130
+ ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
107
131
  ConstantString.WrappedCardVersion = "devPreview";
108
132
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
109
133
  ConstantString.WrappedCardResponseLayout = "list";
@@ -113,8 +137,10 @@ ConstantString.AdaptiveCardVersion = "1.5";
113
137
  ConstantString.AdaptiveCardSchema = "http://adaptivecards.io/schemas/adaptive-card.json";
114
138
  ConstantString.AdaptiveCardType = "AdaptiveCard";
115
139
  ConstantString.TextBlockType = "TextBlock";
140
+ ConstantString.ImageType = "Image";
116
141
  ConstantString.ContainerType = "Container";
117
142
  ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
143
+ ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
118
144
  ConstantString.ResponseCodeFor20X = [
119
145
  "200",
120
146
  "201",
@@ -174,205 +200,36 @@ ConstantString.FullDescriptionMaxLens = 4000;
174
200
  ConstantString.CommandDescriptionMaxLens = 128;
175
201
  ConstantString.ParameterDescriptionMaxLens = 128;
176
202
  ConstantString.CommandTitleMaxLens = 32;
177
- ConstantString.ParameterTitleMaxLens = 32;
203
+ ConstantString.ParameterTitleMaxLens = 32;
204
+ ConstantString.SMERequiredParamsMaxNum = 5;
205
+ ConstantString.DefaultPluginId = "plugin_1";
178
206
 
179
207
  // Copyright (c) Microsoft Corporation.
180
208
  class Utils {
181
- static checkParameters(paramObject) {
182
- const paramResult = {
183
- requiredNum: 0,
184
- optionalNum: 0,
185
- isValid: true,
186
- };
187
- if (!paramObject) {
188
- return paramResult;
189
- }
190
- for (let i = 0; i < paramObject.length; i++) {
191
- const param = paramObject[i];
192
- const schema = param.schema;
193
- const isRequiredWithoutDefault = param.required && schema.default === undefined;
194
- if (param.in === "header" || param.in === "cookie") {
195
- if (isRequiredWithoutDefault) {
196
- paramResult.isValid = false;
197
- }
198
- continue;
199
- }
200
- if (schema.type !== "boolean" &&
201
- schema.type !== "string" &&
202
- schema.type !== "number" &&
203
- schema.type !== "integer") {
204
- if (isRequiredWithoutDefault) {
205
- paramResult.isValid = false;
206
- }
207
- continue;
208
- }
209
- if (param.in === "query" || param.in === "path") {
210
- if (isRequiredWithoutDefault) {
211
- paramResult.requiredNum = paramResult.requiredNum + 1;
212
- }
213
- else {
214
- paramResult.optionalNum = paramResult.optionalNum + 1;
215
- }
216
- }
217
- }
218
- return paramResult;
219
- }
220
- static checkPostBody(schema, isRequired = false) {
221
- var _a;
222
- const paramResult = {
223
- requiredNum: 0,
224
- optionalNum: 0,
225
- isValid: true,
226
- };
227
- if (Object.keys(schema).length === 0) {
228
- return paramResult;
229
- }
230
- const isRequiredWithoutDefault = isRequired && schema.default === undefined;
231
- if (schema.type === "string" ||
232
- schema.type === "integer" ||
233
- schema.type === "boolean" ||
234
- schema.type === "number") {
235
- if (isRequiredWithoutDefault) {
236
- paramResult.requiredNum = paramResult.requiredNum + 1;
237
- }
238
- else {
239
- paramResult.optionalNum = paramResult.optionalNum + 1;
240
- }
241
- }
242
- else if (schema.type === "object") {
243
- const { properties } = schema;
244
- for (const property in properties) {
245
- let isRequired = false;
246
- if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
247
- isRequired = true;
248
- }
249
- const result = Utils.checkPostBody(properties[property], isRequired);
250
- paramResult.requiredNum += result.requiredNum;
251
- paramResult.optionalNum += result.optionalNum;
252
- paramResult.isValid = paramResult.isValid && result.isValid;
253
- }
254
- }
255
- else {
256
- if (isRequiredWithoutDefault) {
257
- paramResult.isValid = false;
258
- }
259
- }
260
- return paramResult;
261
- }
262
- /**
263
- * Checks if the given API is supported.
264
- * @param {string} method - The HTTP method of the API.
265
- * @param {string} path - The path of the API.
266
- * @param {OpenAPIV3.Document} spec - The OpenAPI specification document.
267
- * @returns {boolean} - Returns true if the API is supported, false otherwise.
268
- * @description The following APIs are supported:
269
- * 1. only support Get/Post operation without auth property
270
- * 2. parameter inside query or path only support string, number, boolean and integer
271
- * 3. parameter inside post body only support string, number, boolean, integer and object
272
- * 4. request body + required parameters <= 1
273
- * 5. response body should be “application/json” and not empty, and response code should be 20X
274
- * 6. only support request body with “application/json” content type
275
- */
276
- static isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
277
- const pathObj = spec.paths[path];
278
- method = method.toLocaleLowerCase();
279
- if (pathObj) {
280
- if ((method === ConstantString.PostMethod || method === ConstantString.GetMethod) &&
281
- pathObj[method]) {
282
- const securities = pathObj[method].security;
283
- const authArray = Utils.getAuthArray(securities, spec);
284
- if (!Utils.isSupportedAuth(authArray, allowAPIKeyAuth, allowOauth2)) {
285
- return false;
286
- }
287
- const operationObject = pathObj[method];
288
- if (!allowMissingId && !operationObject.operationId) {
289
- return false;
290
- }
291
- const paramObject = operationObject.parameters;
292
- const requestBody = operationObject.requestBody;
293
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
294
- const mediaTypesCount = Object.keys((requestBody === null || requestBody === void 0 ? void 0 : requestBody.content) || {}).length;
295
- if (mediaTypesCount > 1) {
296
- return false;
297
- }
298
- const responseJson = Utils.getResponseJson(operationObject);
299
- if (Object.keys(responseJson).length === 0) {
300
- return false;
301
- }
302
- let requestBodyParamResult = {
303
- requiredNum: 0,
304
- optionalNum: 0,
305
- isValid: true,
306
- };
307
- if (requestJsonBody) {
308
- const requestBodySchema = requestJsonBody.schema;
309
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required);
310
- }
311
- if (!requestBodyParamResult.isValid) {
312
- return false;
313
- }
314
- const paramResult = Utils.checkParameters(paramObject);
315
- if (!paramResult.isValid) {
316
- return false;
317
- }
318
- if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
319
- if (allowMultipleParameters &&
320
- requestBodyParamResult.requiredNum + paramResult.requiredNum <= 5) {
321
- return true;
322
- }
323
- return false;
324
- }
325
- else if (requestBodyParamResult.requiredNum +
326
- requestBodyParamResult.optionalNum +
327
- paramResult.requiredNum +
328
- paramResult.optionalNum ===
329
- 0) {
330
- return false;
331
- }
332
- else {
209
+ static hasNestedObjectInSchema(schema) {
210
+ if (schema.type === "object") {
211
+ for (const property in schema.properties) {
212
+ const nestedSchema = schema.properties[property];
213
+ if (nestedSchema.type === "object") {
333
214
  return true;
334
215
  }
335
216
  }
336
217
  }
337
218
  return false;
338
219
  }
339
- static isSupportedAuth(authSchemaArray, allowAPIKeyAuth, allowOauth2) {
340
- if (authSchemaArray.length === 0) {
341
- return true;
342
- }
343
- if (allowAPIKeyAuth || allowOauth2) {
344
- // Currently we don't support multiple auth in one operation
345
- if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
346
- return false;
347
- }
348
- for (const auths of authSchemaArray) {
349
- if (auths.length === 1) {
350
- if (!allowOauth2 && allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authSchema)) {
351
- return true;
352
- }
353
- else if (!allowAPIKeyAuth &&
354
- allowOauth2 &&
355
- Utils.isBearerTokenAuth(auths[0].authSchema)) {
356
- return true;
357
- }
358
- else if (allowAPIKeyAuth &&
359
- allowOauth2 &&
360
- (Utils.isAPIKeyAuth(auths[0].authSchema) ||
361
- Utils.isBearerTokenAuth(auths[0].authSchema))) {
362
- return true;
363
- }
364
- }
365
- }
366
- }
367
- return false;
220
+ static containMultipleMediaTypes(bodyObject) {
221
+ return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
368
222
  }
369
- static isAPIKeyAuth(authSchema) {
370
- return authSchema.type === "apiKey";
223
+ static isBearerTokenAuth(authScheme) {
224
+ return authScheme.type === "http" && authScheme.scheme === "bearer";
371
225
  }
372
- static isBearerTokenAuth(authSchema) {
373
- return (authSchema.type === "oauth2" ||
374
- authSchema.type === "openIdConnect" ||
375
- (authSchema.type === "http" && authSchema.scheme === "bearer"));
226
+ static isAPIKeyAuth(authScheme) {
227
+ return authScheme.type === "apiKey";
228
+ }
229
+ static isOAuthWithAuthCodeFlow(authScheme) {
230
+ return !!(authScheme.type === "oauth2" &&
231
+ authScheme.flows &&
232
+ authScheme.flows.authorizationCode);
376
233
  }
377
234
  static getAuthArray(securities, spec) {
378
235
  var _a;
@@ -385,7 +242,7 @@ class Utils {
385
242
  for (const name in security) {
386
243
  const auth = securitySchemas[name];
387
244
  authArray.push({
388
- authSchema: auth,
245
+ authScheme: auth,
389
246
  name: name,
390
247
  });
391
248
  }
@@ -397,24 +254,47 @@ class Utils {
397
254
  result.sort((a, b) => a[0].name.localeCompare(b[0].name));
398
255
  return result;
399
256
  }
257
+ static getAuthInfo(spec) {
258
+ let authInfo = undefined;
259
+ for (const url in spec.paths) {
260
+ for (const method in spec.paths[url]) {
261
+ const operation = spec.paths[url][method];
262
+ const authArray = Utils.getAuthArray(operation.security, spec);
263
+ if (authArray && authArray.length > 0) {
264
+ const currentAuth = authArray[0][0];
265
+ if (!authInfo) {
266
+ authInfo = authArray[0][0];
267
+ }
268
+ else if (authInfo.name !== currentAuth.name) {
269
+ throw new SpecParserError(ConstantString.MultipleAuthNotSupported, ErrorType.MultipleAuthNotSupported);
270
+ }
271
+ }
272
+ }
273
+ }
274
+ return authInfo;
275
+ }
400
276
  static updateFirstLetter(str) {
401
277
  return str.charAt(0).toUpperCase() + str.slice(1);
402
278
  }
403
279
  static getResponseJson(operationObject) {
404
280
  var _a, _b;
405
281
  let json = {};
282
+ let multipleMediaType = false;
406
283
  for (const code of ConstantString.ResponseCodeFor20X) {
407
284
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
408
- const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
409
- if (mediaTypesCount > 1) {
410
- return {};
411
- }
412
285
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
286
+ multipleMediaType = false;
413
287
  json = responseObject.content["application/json"];
414
- break;
288
+ if (Utils.containMultipleMediaTypes(responseObject)) {
289
+ multipleMediaType = true;
290
+ json = {};
291
+ }
292
+ else {
293
+ break;
294
+ }
415
295
  }
416
296
  }
417
- return json;
297
+ return { json, multipleMediaType };
418
298
  }
419
299
  static convertPathToCamelCase(path) {
420
300
  const pathSegments = path.split(/[./{]/);
@@ -434,10 +314,10 @@ class Utils {
434
314
  return undefined;
435
315
  }
436
316
  }
437
- static resolveServerUrl(url) {
317
+ static resolveEnv(str) {
438
318
  const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
439
- let matches = placeHolderReg.exec(url);
440
- let newUrl = url;
319
+ let matches = placeHolderReg.exec(str);
320
+ let newStr = str;
441
321
  while (matches != null) {
442
322
  const envVar = matches[1];
443
323
  const envVal = process.env[envVar];
@@ -445,17 +325,17 @@ class Utils {
445
325
  throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
446
326
  }
447
327
  else {
448
- newUrl = newUrl.replace(matches[0], envVal);
328
+ newStr = newStr.replace(matches[0], envVal);
449
329
  }
450
- matches = placeHolderReg.exec(url);
330
+ matches = placeHolderReg.exec(str);
451
331
  }
452
- return newUrl;
332
+ return newStr;
453
333
  }
454
334
  static checkServerUrl(servers) {
455
335
  const errors = [];
456
336
  let serverUrl;
457
337
  try {
458
- serverUrl = Utils.resolveServerUrl(servers[0].url);
338
+ serverUrl = Utils.resolveEnv(servers[0].url);
459
339
  }
460
340
  catch (err) {
461
341
  errors.push({
@@ -485,7 +365,8 @@ class Utils {
485
365
  }
486
366
  return errors;
487
367
  }
488
- static validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
368
+ static validateServer(spec, options) {
369
+ var _a;
489
370
  const errors = [];
490
371
  let hasTopLevelServers = false;
491
372
  let hasPathLevelServers = false;
@@ -506,7 +387,7 @@ class Utils {
506
387
  }
507
388
  for (const method in methods) {
508
389
  const operationObject = methods[method];
509
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
390
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
510
391
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
511
392
  hasOperationLevelServers = true;
512
393
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -549,6 +430,7 @@ class Utils {
549
430
  Utils.updateParameterWithInputType(schema, parameter);
550
431
  }
551
432
  if (isRequired && schema.default === undefined) {
433
+ parameter.isRequired = true;
552
434
  requiredParams.push(parameter);
553
435
  }
554
436
  else {
@@ -593,7 +475,7 @@ class Utils {
593
475
  param.value = schema.default;
594
476
  }
595
477
  }
596
- static parseApiInfo(operationItem, allowMultipleParameters) {
478
+ static parseApiInfo(operationItem, options) {
597
479
  var _a, _b;
598
480
  const requiredParams = [];
599
481
  const optionalParams = [];
@@ -607,11 +489,12 @@ class Utils {
607
489
  description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
608
490
  };
609
491
  const schema = param.schema;
610
- if (allowMultipleParameters && schema) {
492
+ if (options.allowMultipleParameters && schema) {
611
493
  Utils.updateParameterWithInputType(schema, parameter);
612
494
  }
613
495
  if (param.in !== "header" && param.in !== "cookie") {
614
496
  if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
497
+ parameter.isRequired = true;
615
498
  requiredParams.push(parameter);
616
499
  }
617
500
  else {
@@ -625,19 +508,13 @@ class Utils {
625
508
  const requestJson = requestBody.content["application/json"];
626
509
  if (Object.keys(requestJson).length !== 0) {
627
510
  const schema = requestJson.schema;
628
- const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
511
+ const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
629
512
  requiredParams.push(...requiredP);
630
513
  optionalParams.push(...optionalP);
631
514
  }
632
515
  }
633
516
  const operationId = operationItem.operationId;
634
- const parameters = [];
635
- if (requiredParams.length !== 0) {
636
- parameters.push(...requiredParams);
637
- }
638
- else {
639
- parameters.push(optionalParams[0]);
640
- }
517
+ const parameters = [...requiredParams, ...optionalParams];
641
518
  const command = {
642
519
  context: ["compose"],
643
520
  type: "query",
@@ -646,105 +523,534 @@ class Utils {
646
523
  parameters: parameters,
647
524
  description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
648
525
  };
649
- let warning = undefined;
650
- if (requiredParams.length === 0 && optionalParams.length > 1) {
651
- warning = {
652
- type: WarningType.OperationOnlyContainsOptionalParam,
653
- content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, operationId),
654
- data: operationId,
655
- };
526
+ return command;
527
+ }
528
+ static format(str, ...args) {
529
+ let index = 0;
530
+ return str.replace(/%s/g, () => {
531
+ const arg = args[index++];
532
+ return arg !== undefined ? arg : "";
533
+ });
534
+ }
535
+ static getSafeRegistrationIdEnvName(authName) {
536
+ if (!authName) {
537
+ return "";
656
538
  }
657
- return [command, warning];
539
+ let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
540
+ if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
541
+ safeRegistrationIdEnvName = "PREFIX_" + safeRegistrationIdEnvName;
542
+ }
543
+ return safeRegistrationIdEnvName;
658
544
  }
659
- static listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
660
- const paths = spec.paths;
545
+ static getServerObject(spec, method, path) {
546
+ const pathObj = spec.paths[path];
547
+ const operationObject = pathObj[method];
548
+ const rootServer = spec.servers && spec.servers[0];
549
+ const methodServer = spec.paths[path].servers && spec.paths[path].servers[0];
550
+ const operationServer = operationObject.servers && operationObject.servers[0];
551
+ const serverUrl = operationServer || methodServer || rootServer;
552
+ return serverUrl;
553
+ }
554
+ }
555
+
556
+ // Copyright (c) Microsoft Corporation.
557
+ class Validator {
558
+ listAPIs() {
559
+ var _a;
560
+ if (this.apiMap) {
561
+ return this.apiMap;
562
+ }
563
+ const paths = this.spec.paths;
661
564
  const result = {};
662
565
  for (const path in paths) {
663
566
  const methods = paths[path];
664
567
  for (const method in methods) {
665
- // For developer preview, only support GET operation with only 1 parameter without auth
666
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
667
- const operationObject = methods[method];
668
- result[`${method.toUpperCase()} ${path}`] = operationObject;
568
+ const operationObject = methods[method];
569
+ if (((_a = this.options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
570
+ const validateResult = this.validateAPI(method, path);
571
+ result[`${method.toUpperCase()} ${path}`] = {
572
+ operation: operationObject,
573
+ isValid: validateResult.isValid,
574
+ reason: validateResult.reason,
575
+ };
669
576
  }
670
577
  }
671
578
  }
579
+ this.apiMap = result;
672
580
  return result;
673
581
  }
674
- static validateSpec(spec, parser, isSwaggerFile, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
675
- const errors = [];
676
- const warnings = [];
677
- if (isSwaggerFile) {
678
- warnings.push({
679
- type: WarningType.ConvertSwaggerToOpenAPI,
680
- content: ConstantString.ConvertSwaggerToOpenAPI,
582
+ validateSpecVersion() {
583
+ const result = { errors: [], warnings: [] };
584
+ if (this.spec.openapi >= "3.1.0") {
585
+ result.errors.push({
586
+ type: ErrorType.SpecVersionNotSupported,
587
+ content: Utils.format(ConstantString.SpecVersionNotSupported, this.spec.openapi),
588
+ data: this.spec.openapi,
681
589
  });
682
590
  }
683
- // Server validation
684
- const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
685
- errors.push(...serverErrors);
686
- // Remote reference not supported
687
- const refPaths = parser.$refs.paths();
688
- // refPaths [0] is the current spec file path
689
- if (refPaths.length > 1) {
690
- errors.push({
691
- type: ErrorType.RemoteRefNotSupported,
692
- content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
693
- data: refPaths,
694
- });
695
- }
696
- // No supported API
697
- const apiMap = Utils.listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
698
- if (Object.keys(apiMap).length === 0) {
699
- errors.push({
591
+ return result;
592
+ }
593
+ validateSpecServer() {
594
+ const result = { errors: [], warnings: [] };
595
+ const serverErrors = Utils.validateServer(this.spec, this.options);
596
+ result.errors.push(...serverErrors);
597
+ return result;
598
+ }
599
+ validateSpecNoSupportAPI() {
600
+ const result = { errors: [], warnings: [] };
601
+ const apiMap = this.listAPIs();
602
+ const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
603
+ if (validAPIs.length === 0) {
604
+ const data = [];
605
+ for (const key in apiMap) {
606
+ const { reason } = apiMap[key];
607
+ const apiInvalidReason = { api: key, reason: reason };
608
+ data.push(apiInvalidReason);
609
+ }
610
+ result.errors.push({
700
611
  type: ErrorType.NoSupportedApi,
701
612
  content: ConstantString.NoSupportedApi,
613
+ data,
702
614
  });
703
615
  }
616
+ return result;
617
+ }
618
+ validateSpecOperationId() {
619
+ const result = { errors: [], warnings: [] };
620
+ const apiMap = this.listAPIs();
704
621
  // OperationId missing
705
622
  const apisMissingOperationId = [];
706
623
  for (const key in apiMap) {
707
- const pathObjectItem = apiMap[key];
708
- if (!pathObjectItem.operationId) {
624
+ const { operation } = apiMap[key];
625
+ if (!operation.operationId) {
709
626
  apisMissingOperationId.push(key);
710
627
  }
711
628
  }
712
629
  if (apisMissingOperationId.length > 0) {
713
- warnings.push({
630
+ result.warnings.push({
714
631
  type: WarningType.OperationIdMissing,
715
632
  content: Utils.format(ConstantString.MissingOperationId, apisMissingOperationId.join(", ")),
716
633
  data: apisMissingOperationId,
717
634
  });
718
635
  }
719
- let status = ValidationStatus.Valid;
720
- if (warnings.length > 0 && errors.length === 0) {
721
- status = ValidationStatus.Warning;
636
+ return result;
637
+ }
638
+ validateMethodAndPath(method, path) {
639
+ const result = { isValid: true, reason: [] };
640
+ if (this.options.allowMethods && !this.options.allowMethods.includes(method)) {
641
+ result.isValid = false;
642
+ result.reason.push(ErrorType.MethodNotAllowed);
643
+ return result;
644
+ }
645
+ const pathObj = this.spec.paths[path];
646
+ if (!pathObj || !pathObj[method]) {
647
+ result.isValid = false;
648
+ result.reason.push(ErrorType.UrlPathNotExist);
649
+ return result;
650
+ }
651
+ return result;
652
+ }
653
+ validateResponse(method, path) {
654
+ const result = { isValid: true, reason: [] };
655
+ const operationObject = this.spec.paths[path][method];
656
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
657
+ if (this.options.projectType === ProjectType.SME) {
658
+ // only support response body only contains “application/json” content type
659
+ if (multipleMediaType) {
660
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
661
+ }
662
+ else if (Object.keys(json).length === 0) {
663
+ // response body should not be empty
664
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
665
+ }
666
+ }
667
+ return result;
668
+ }
669
+ validateServer(method, path) {
670
+ const result = { isValid: true, reason: [] };
671
+ const serverObj = Utils.getServerObject(this.spec, method, path);
672
+ if (!serverObj) {
673
+ // should contain server URL
674
+ result.reason.push(ErrorType.NoServerInformation);
722
675
  }
723
- else if (errors.length > 0) {
724
- status = ValidationStatus.Error;
676
+ else {
677
+ // server url should be absolute url with https protocol
678
+ const serverValidateResult = Utils.checkServerUrl([serverObj]);
679
+ result.reason.push(...serverValidateResult.map((item) => item.type));
680
+ }
681
+ return result;
682
+ }
683
+ validateAuth(method, path) {
684
+ const pathObj = this.spec.paths[path];
685
+ const operationObject = pathObj[method];
686
+ const securities = operationObject.security;
687
+ const authSchemeArray = Utils.getAuthArray(securities, this.spec);
688
+ if (authSchemeArray.length === 0) {
689
+ return { isValid: true, reason: [] };
690
+ }
691
+ if (this.options.allowAPIKeyAuth ||
692
+ this.options.allowOauth2 ||
693
+ this.options.allowBearerTokenAuth) {
694
+ // Currently we don't support multiple auth in one operation
695
+ if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
696
+ return {
697
+ isValid: false,
698
+ reason: [ErrorType.MultipleAuthNotSupported],
699
+ };
700
+ }
701
+ for (const auths of authSchemeArray) {
702
+ if (auths.length === 1) {
703
+ if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
704
+ (this.options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
705
+ (this.options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
706
+ return { isValid: true, reason: [] };
707
+ }
708
+ }
709
+ }
725
710
  }
726
- return {
727
- status,
728
- warnings,
729
- errors,
711
+ return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
712
+ }
713
+ checkPostBodySchema(schema, isRequired = false) {
714
+ var _a;
715
+ const paramResult = {
716
+ requiredNum: 0,
717
+ optionalNum: 0,
718
+ isValid: true,
719
+ reason: [],
730
720
  };
721
+ if (Object.keys(schema).length === 0) {
722
+ return paramResult;
723
+ }
724
+ const isRequiredWithoutDefault = isRequired && schema.default === undefined;
725
+ const isCopilot = this.projectType === ProjectType.Copilot;
726
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
727
+ paramResult.isValid = false;
728
+ paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
729
+ return paramResult;
730
+ }
731
+ if (schema.type === "string" ||
732
+ schema.type === "integer" ||
733
+ schema.type === "boolean" ||
734
+ schema.type === "number") {
735
+ if (isRequiredWithoutDefault) {
736
+ paramResult.requiredNum = paramResult.requiredNum + 1;
737
+ }
738
+ else {
739
+ paramResult.optionalNum = paramResult.optionalNum + 1;
740
+ }
741
+ }
742
+ else if (schema.type === "object") {
743
+ const { properties } = schema;
744
+ for (const property in properties) {
745
+ let isRequired = false;
746
+ if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
747
+ isRequired = true;
748
+ }
749
+ const result = this.checkPostBodySchema(properties[property], isRequired);
750
+ paramResult.requiredNum += result.requiredNum;
751
+ paramResult.optionalNum += result.optionalNum;
752
+ paramResult.isValid = paramResult.isValid && result.isValid;
753
+ paramResult.reason.push(...result.reason);
754
+ }
755
+ }
756
+ else {
757
+ if (isRequiredWithoutDefault && !isCopilot) {
758
+ paramResult.isValid = false;
759
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
760
+ }
761
+ }
762
+ return paramResult;
731
763
  }
732
- static format(str, ...args) {
733
- let index = 0;
734
- return str.replace(/%s/g, () => {
735
- const arg = args[index++];
736
- return arg !== undefined ? arg : "";
737
- });
764
+ checkParamSchema(paramObject) {
765
+ const paramResult = {
766
+ requiredNum: 0,
767
+ optionalNum: 0,
768
+ isValid: true,
769
+ reason: [],
770
+ };
771
+ if (!paramObject) {
772
+ return paramResult;
773
+ }
774
+ const isCopilot = this.projectType === ProjectType.Copilot;
775
+ for (let i = 0; i < paramObject.length; i++) {
776
+ const param = paramObject[i];
777
+ const schema = param.schema;
778
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
779
+ paramResult.isValid = false;
780
+ paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
781
+ continue;
782
+ }
783
+ const isRequiredWithoutDefault = param.required && schema.default === undefined;
784
+ if (isCopilot) {
785
+ if (isRequiredWithoutDefault) {
786
+ paramResult.requiredNum = paramResult.requiredNum + 1;
787
+ }
788
+ else {
789
+ paramResult.optionalNum = paramResult.optionalNum + 1;
790
+ }
791
+ continue;
792
+ }
793
+ if (param.in === "header" || param.in === "cookie") {
794
+ if (isRequiredWithoutDefault) {
795
+ paramResult.isValid = false;
796
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
797
+ }
798
+ continue;
799
+ }
800
+ if (schema.type !== "boolean" &&
801
+ schema.type !== "string" &&
802
+ schema.type !== "number" &&
803
+ schema.type !== "integer") {
804
+ if (isRequiredWithoutDefault) {
805
+ paramResult.isValid = false;
806
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
807
+ }
808
+ continue;
809
+ }
810
+ if (param.in === "query" || param.in === "path") {
811
+ if (isRequiredWithoutDefault) {
812
+ paramResult.requiredNum = paramResult.requiredNum + 1;
813
+ }
814
+ else {
815
+ paramResult.optionalNum = paramResult.optionalNum + 1;
816
+ }
817
+ }
818
+ }
819
+ return paramResult;
738
820
  }
739
- static getSafeRegistrationIdEnvName(authName) {
740
- if (!authName) {
741
- return "";
821
+ hasNestedObjectInSchema(schema) {
822
+ if (schema.type === "object") {
823
+ for (const property in schema.properties) {
824
+ const nestedSchema = schema.properties[property];
825
+ if (nestedSchema.type === "object") {
826
+ return true;
827
+ }
828
+ }
742
829
  }
743
- let safeRegistrationIdEnvName = authName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
744
- if (!safeRegistrationIdEnvName.match(/^[A-Z]/)) {
745
- safeRegistrationIdEnvName = "PREFIX_" + safeRegistrationIdEnvName;
830
+ return false;
831
+ }
832
+ }
833
+
834
+ // Copyright (c) Microsoft Corporation.
835
+ class CopilotValidator extends Validator {
836
+ constructor(spec, options) {
837
+ super();
838
+ this.projectType = ProjectType.Copilot;
839
+ this.options = options;
840
+ this.spec = spec;
841
+ }
842
+ validateSpec() {
843
+ const result = { errors: [], warnings: [] };
844
+ // validate spec version
845
+ let validationResult = this.validateSpecVersion();
846
+ result.errors.push(...validationResult.errors);
847
+ // validate spec server
848
+ validationResult = this.validateSpecServer();
849
+ result.errors.push(...validationResult.errors);
850
+ // validate no supported API
851
+ validationResult = this.validateSpecNoSupportAPI();
852
+ result.errors.push(...validationResult.errors);
853
+ // validate operationId missing
854
+ validationResult = this.validateSpecOperationId();
855
+ result.warnings.push(...validationResult.warnings);
856
+ return result;
857
+ }
858
+ validateAPI(method, path) {
859
+ const result = { isValid: true, reason: [] };
860
+ method = method.toLocaleLowerCase();
861
+ // validate method and path
862
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
863
+ if (!methodAndPathResult.isValid) {
864
+ return methodAndPathResult;
865
+ }
866
+ const operationObject = this.spec.paths[path][method];
867
+ // validate auth
868
+ const authCheckResult = this.validateAuth(method, path);
869
+ result.reason.push(...authCheckResult.reason);
870
+ // validate operationId
871
+ if (!this.options.allowMissingId && !operationObject.operationId) {
872
+ result.reason.push(ErrorType.MissingOperationId);
873
+ }
874
+ // validate server
875
+ const validateServerResult = this.validateServer(method, path);
876
+ result.reason.push(...validateServerResult.reason);
877
+ // validate response
878
+ const validateResponseResult = this.validateResponse(method, path);
879
+ result.reason.push(...validateResponseResult.reason);
880
+ // validate requestBody
881
+ const requestBody = operationObject.requestBody;
882
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
883
+ if (requestJsonBody) {
884
+ const requestBodySchema = requestJsonBody.schema;
885
+ if (requestBodySchema.type !== "object") {
886
+ result.reason.push(ErrorType.PostBodySchemaIsNotJson);
887
+ }
888
+ const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
889
+ result.reason.push(...requestBodyParamResult.reason);
890
+ }
891
+ // validate parameters
892
+ const paramObject = operationObject.parameters;
893
+ const paramResult = this.checkParamSchema(paramObject);
894
+ result.reason.push(...paramResult.reason);
895
+ if (result.reason.length > 0) {
896
+ result.isValid = false;
897
+ }
898
+ return result;
899
+ }
900
+ }
901
+
902
+ // Copyright (c) Microsoft Corporation.
903
+ class SMEValidator extends Validator {
904
+ constructor(spec, options) {
905
+ super();
906
+ this.projectType = ProjectType.SME;
907
+ this.options = options;
908
+ this.spec = spec;
909
+ }
910
+ validateSpec() {
911
+ const result = { errors: [], warnings: [] };
912
+ // validate spec version
913
+ let validationResult = this.validateSpecVersion();
914
+ result.errors.push(...validationResult.errors);
915
+ // validate spec server
916
+ validationResult = this.validateSpecServer();
917
+ result.errors.push(...validationResult.errors);
918
+ // validate no supported API
919
+ validationResult = this.validateSpecNoSupportAPI();
920
+ result.errors.push(...validationResult.errors);
921
+ // validate operationId missing
922
+ if (this.options.allowMissingId) {
923
+ validationResult = this.validateSpecOperationId();
924
+ result.warnings.push(...validationResult.warnings);
925
+ }
926
+ return result;
927
+ }
928
+ validateAPI(method, path) {
929
+ const result = { isValid: true, reason: [] };
930
+ method = method.toLocaleLowerCase();
931
+ // validate method and path
932
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
933
+ if (!methodAndPathResult.isValid) {
934
+ return methodAndPathResult;
935
+ }
936
+ const operationObject = this.spec.paths[path][method];
937
+ // validate auth
938
+ const authCheckResult = this.validateAuth(method, path);
939
+ result.reason.push(...authCheckResult.reason);
940
+ // validate operationId
941
+ if (!this.options.allowMissingId && !operationObject.operationId) {
942
+ result.reason.push(ErrorType.MissingOperationId);
943
+ }
944
+ // validate server
945
+ const validateServerResult = this.validateServer(method, path);
946
+ result.reason.push(...validateServerResult.reason);
947
+ // validate response
948
+ const validateResponseResult = this.validateResponse(method, path);
949
+ result.reason.push(...validateResponseResult.reason);
950
+ let postBodyResult = {
951
+ requiredNum: 0,
952
+ optionalNum: 0,
953
+ isValid: true,
954
+ reason: [],
955
+ };
956
+ // validate requestBody
957
+ const requestBody = operationObject.requestBody;
958
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
959
+ if (Utils.containMultipleMediaTypes(requestBody)) {
960
+ result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
961
+ }
962
+ if (requestJsonBody) {
963
+ const requestBodySchema = requestJsonBody.schema;
964
+ postBodyResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
965
+ result.reason.push(...postBodyResult.reason);
966
+ }
967
+ // validate parameters
968
+ const paramObject = operationObject.parameters;
969
+ const paramResult = this.checkParamSchema(paramObject);
970
+ result.reason.push(...paramResult.reason);
971
+ // validate total parameters count
972
+ if (paramResult.isValid && postBodyResult.isValid) {
973
+ const paramCountResult = this.validateParamCount(postBodyResult, paramResult);
974
+ result.reason.push(...paramCountResult.reason);
975
+ }
976
+ if (result.reason.length > 0) {
977
+ result.isValid = false;
978
+ }
979
+ return result;
980
+ }
981
+ validateParamCount(postBodyResult, paramResult) {
982
+ const result = { isValid: true, reason: [] };
983
+ const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
984
+ const totalParams = totalRequiredParams + postBodyResult.optionalNum + paramResult.optionalNum;
985
+ if (totalRequiredParams > 1) {
986
+ if (!this.options.allowMultipleParameters ||
987
+ totalRequiredParams > SMEValidator.SMERequiredParamsMaxNum) {
988
+ result.reason.push(ErrorType.ExceededRequiredParamsLimit);
989
+ }
990
+ }
991
+ else if (totalParams === 0) {
992
+ result.reason.push(ErrorType.NoParameter);
993
+ }
994
+ return result;
995
+ }
996
+ }
997
+ SMEValidator.SMERequiredParamsMaxNum = 5;
998
+
999
+ // Copyright (c) Microsoft Corporation.
1000
+ class TeamsAIValidator extends Validator {
1001
+ constructor(spec, options) {
1002
+ super();
1003
+ this.projectType = ProjectType.TeamsAi;
1004
+ this.options = options;
1005
+ this.spec = spec;
1006
+ }
1007
+ validateSpec() {
1008
+ const result = { errors: [], warnings: [] };
1009
+ // validate spec server
1010
+ let validationResult = this.validateSpecServer();
1011
+ result.errors.push(...validationResult.errors);
1012
+ // validate no supported API
1013
+ validationResult = this.validateSpecNoSupportAPI();
1014
+ result.errors.push(...validationResult.errors);
1015
+ return result;
1016
+ }
1017
+ validateAPI(method, path) {
1018
+ const result = { isValid: true, reason: [] };
1019
+ method = method.toLocaleLowerCase();
1020
+ // validate method and path
1021
+ const methodAndPathResult = this.validateMethodAndPath(method, path);
1022
+ if (!methodAndPathResult.isValid) {
1023
+ return methodAndPathResult;
1024
+ }
1025
+ const operationObject = this.spec.paths[path][method];
1026
+ // validate operationId
1027
+ if (!this.options.allowMissingId && !operationObject.operationId) {
1028
+ result.reason.push(ErrorType.MissingOperationId);
1029
+ }
1030
+ // validate server
1031
+ const validateServerResult = this.validateServer(method, path);
1032
+ result.reason.push(...validateServerResult.reason);
1033
+ if (result.reason.length > 0) {
1034
+ result.isValid = false;
1035
+ }
1036
+ return result;
1037
+ }
1038
+ }
1039
+
1040
+ class ValidatorFactory {
1041
+ static create(spec, options) {
1042
+ var _a;
1043
+ const type = (_a = options.projectType) !== null && _a !== void 0 ? _a : ProjectType.SME;
1044
+ switch (type) {
1045
+ case ProjectType.SME:
1046
+ return new SMEValidator(spec, options);
1047
+ case ProjectType.Copilot:
1048
+ return new CopilotValidator(spec, options);
1049
+ case ProjectType.TeamsAi:
1050
+ return new TeamsAIValidator(spec, options);
1051
+ default:
1052
+ throw new Error(`Invalid project type: ${type}`);
746
1053
  }
747
- return safeRegistrationIdEnvName;
748
1054
  }
749
1055
  }
750
1056
 
@@ -764,7 +1070,13 @@ class SpecParser {
764
1070
  allowSwagger: false,
765
1071
  allowAPIKeyAuth: false,
766
1072
  allowMultipleParameters: false,
1073
+ allowBearerTokenAuth: false,
767
1074
  allowOauth2: false,
1075
+ allowMethods: ["get", "post"],
1076
+ allowConversationStarters: false,
1077
+ allowResponseSemantics: false,
1078
+ allowConfirmation: false,
1079
+ projectType: ProjectType.SME,
768
1080
  };
769
1081
  this.pathOrSpec = pathOrDoc;
770
1082
  this.parser = new SwaggerParser();
@@ -780,11 +1092,7 @@ class SpecParser {
780
1092
  try {
781
1093
  try {
782
1094
  yield this.loadSpec();
783
- yield this.parser.validate(this.spec, {
784
- validate: {
785
- schema: false,
786
- },
787
- });
1095
+ yield this.parser.validate(this.spec);
788
1096
  }
789
1097
  catch (e) {
790
1098
  return {
@@ -793,16 +1101,46 @@ class SpecParser {
793
1101
  errors: [{ type: ErrorType.SpecNotValid, content: e.toString() }],
794
1102
  };
795
1103
  }
1104
+ const errors = [];
1105
+ const warnings = [];
796
1106
  if (!this.options.allowSwagger && this.isSwaggerFile) {
797
1107
  return {
798
1108
  status: ValidationStatus.Error,
799
1109
  warnings: [],
800
1110
  errors: [
801
- { type: ErrorType.SwaggerNotSupported, content: ConstantString.SwaggerNotSupported },
1111
+ {
1112
+ type: ErrorType.SwaggerNotSupported,
1113
+ content: ConstantString.SwaggerNotSupported,
1114
+ },
802
1115
  ],
803
1116
  };
804
1117
  }
805
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
1118
+ // Remote reference not supported
1119
+ const refPaths = this.parser.$refs.paths();
1120
+ // refPaths [0] is the current spec file path
1121
+ if (refPaths.length > 1) {
1122
+ errors.push({
1123
+ type: ErrorType.RemoteRefNotSupported,
1124
+ content: Utils.format(ConstantString.RemoteRefNotSupported, refPaths.join(", ")),
1125
+ data: refPaths,
1126
+ });
1127
+ }
1128
+ const validator = this.getValidator(this.spec);
1129
+ const validationResult = validator.validateSpec();
1130
+ warnings.push(...validationResult.warnings);
1131
+ errors.push(...validationResult.errors);
1132
+ let status = ValidationStatus.Valid;
1133
+ if (warnings.length > 0 && errors.length === 0) {
1134
+ status = ValidationStatus.Warning;
1135
+ }
1136
+ else if (errors.length > 0) {
1137
+ status = ValidationStatus.Error;
1138
+ }
1139
+ return {
1140
+ status: status,
1141
+ warnings: warnings,
1142
+ errors: errors,
1143
+ };
806
1144
  }
807
1145
  catch (err) {
808
1146
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -813,17 +1151,20 @@ class SpecParser {
813
1151
  return __awaiter(this, void 0, void 0, function* () {
814
1152
  try {
815
1153
  yield this.loadSpec();
816
- const apiMap = this.getAllSupportedAPIs(this.spec);
1154
+ const apiMap = this.getAPIs(this.spec);
817
1155
  const apiInfos = [];
818
1156
  for (const key in apiMap) {
819
- const pathObjectItem = apiMap[key];
1157
+ const { operation, isValid } = apiMap[key];
1158
+ if (!isValid) {
1159
+ continue;
1160
+ }
820
1161
  const [method, path] = key.split(" ");
821
- const operationId = pathObjectItem.operationId;
1162
+ const operationId = operation.operationId;
822
1163
  // In Browser environment, this api is by default not support api without operationId
823
1164
  if (!operationId) {
824
1165
  continue;
825
1166
  }
826
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options.allowMultipleParameters);
1167
+ const command = Utils.parseApiInfo(operation, this.options);
827
1168
  const apiInfo = {
828
1169
  method: method,
829
1170
  path: path,
@@ -832,9 +1173,6 @@ class SpecParser {
832
1173
  parameters: command.parameters,
833
1174
  description: command.description,
834
1175
  };
835
- if (warning) {
836
- apiInfo.warning = warning;
837
- }
838
1176
  apiInfos.push(apiInfo);
839
1177
  }
840
1178
  return apiInfos;
@@ -865,6 +1203,19 @@ class SpecParser {
865
1203
  throw new Error("Method not implemented.");
866
1204
  });
867
1205
  }
1206
+ /**
1207
+ * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
1208
+ * @param manifestPath A file path of the Teams app manifest file to update.
1209
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
1210
+ * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
1211
+ * @param pluginFilePath File path of the api plugin file to generate.
1212
+ */
1213
+ // eslint-disable-next-line @typescript-eslint/require-await
1214
+ generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
1215
+ return __awaiter(this, void 0, void 0, function* () {
1216
+ throw new Error("Method not implemented.");
1217
+ });
1218
+ }
868
1219
  /**
869
1220
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
870
1221
  * @param manifestPath A file path of the Teams app manifest file to update.
@@ -874,7 +1225,7 @@ class SpecParser {
874
1225
  * @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
875
1226
  */
876
1227
  // eslint-disable-next-line @typescript-eslint/require-await
877
- generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal, isMe) {
1228
+ generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
878
1229
  return __awaiter(this, void 0, void 0, function* () {
879
1230
  throw new Error("Method not implemented.");
880
1231
  });
@@ -891,13 +1242,18 @@ class SpecParser {
891
1242
  }
892
1243
  });
893
1244
  }
894
- getAllSupportedAPIs(spec) {
895
- if (this.apiMap !== undefined) {
896
- return this.apiMap;
1245
+ getAPIs(spec) {
1246
+ const validator = this.getValidator(spec);
1247
+ const apiMap = validator.listAPIs();
1248
+ return apiMap;
1249
+ }
1250
+ getValidator(spec) {
1251
+ if (this.validator) {
1252
+ return this.validator;
897
1253
  }
898
- const result = Utils.listSupportedAPIs(spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
899
- this.apiMap = result;
900
- return result;
1254
+ const validator = ValidatorFactory.create(spec, this.options);
1255
+ this.validator = validator;
1256
+ return validator;
901
1257
  }
902
1258
  }
903
1259
 
@@ -905,7 +1261,7 @@ class SpecParser {
905
1261
  class AdaptiveCardGenerator {
906
1262
  static generateAdaptiveCard(operationItem) {
907
1263
  try {
908
- const json = Utils.getResponseJson(operationItem);
1264
+ const { json } = Utils.getResponseJson(operationItem);
909
1265
  let cardBody = [];
910
1266
  let schema = json.schema;
911
1267
  let jsonPath = "$";