@microsoft/m365-spec-parser 0.1.1-alpha.48b9eab36.0 → 0.1.1-alpha.4f2290daa.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.
@@ -15,7 +15,8 @@ var ErrorType;
15
15
  ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
16
16
  ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
17
17
  ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
18
- ErrorType["MultipleAPIKeyNotSupported"] = "multiple-api-key-not-supported";
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 = {}));
@@ -46,7 +62,13 @@ var ValidationStatus;
46
62
  ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
47
63
  ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
48
64
  ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
49
- })(ValidationStatus || (ValidationStatus = {}));
65
+ })(ValidationStatus || (ValidationStatus = {}));
66
+ var ProjectType;
67
+ (function (ProjectType) {
68
+ ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
69
+ ProjectType[ProjectType["SME"] = 1] = "SME";
70
+ ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
71
+ })(ProjectType || (ProjectType = {}));
50
72
 
51
73
  // Copyright (c) Microsoft Corporation.
52
74
  class SpecParserError extends Error {
@@ -73,7 +95,9 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
73
95
  ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
74
96
  ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
75
97
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
76
- ConstantString.MultipleAPIKeyNotSupported = "Multiple API keys are not supported. Please make sure that all selected APIs use the same API key.";
98
+ ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
99
+ ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
100
+ ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
77
101
  ConstantString.WrappedCardVersion = "devPreview";
78
102
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
79
103
  ConstantString.WrappedCardResponseLayout = "list";
@@ -85,6 +109,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
85
109
  ConstantString.TextBlockType = "TextBlock";
86
110
  ConstantString.ContainerType = "Container";
87
111
  ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
112
+ ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
88
113
  ConstantString.ResponseCodeFor20X = [
89
114
  "200",
90
115
  "201",
@@ -144,15 +169,28 @@ ConstantString.FullDescriptionMaxLens = 4000;
144
169
  ConstantString.CommandDescriptionMaxLens = 128;
145
170
  ConstantString.ParameterDescriptionMaxLens = 128;
146
171
  ConstantString.CommandTitleMaxLens = 32;
147
- ConstantString.ParameterTitleMaxLens = 32;
172
+ ConstantString.ParameterTitleMaxLens = 32;
173
+ ConstantString.SMERequiredParamsMaxNum = 5;
148
174
 
149
175
  // Copyright (c) Microsoft Corporation.
150
176
  class Utils {
151
- static checkParameters(paramObject) {
177
+ static hasNestedObjectInSchema(schema) {
178
+ if (schema.type === "object") {
179
+ for (const property in schema.properties) {
180
+ const nestedSchema = schema.properties[property];
181
+ if (nestedSchema.type === "object") {
182
+ return true;
183
+ }
184
+ }
185
+ }
186
+ return false;
187
+ }
188
+ static checkParameters(paramObject, isCopilot) {
152
189
  const paramResult = {
153
190
  requiredNum: 0,
154
191
  optionalNum: 0,
155
192
  isValid: true,
193
+ reason: [],
156
194
  };
157
195
  if (!paramObject) {
158
196
  return paramResult;
@@ -160,10 +198,25 @@ class Utils {
160
198
  for (let i = 0; i < paramObject.length; i++) {
161
199
  const param = paramObject[i];
162
200
  const schema = param.schema;
201
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
202
+ paramResult.isValid = false;
203
+ paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
204
+ continue;
205
+ }
163
206
  const isRequiredWithoutDefault = param.required && schema.default === undefined;
207
+ if (isCopilot) {
208
+ if (isRequiredWithoutDefault) {
209
+ paramResult.requiredNum = paramResult.requiredNum + 1;
210
+ }
211
+ else {
212
+ paramResult.optionalNum = paramResult.optionalNum + 1;
213
+ }
214
+ continue;
215
+ }
164
216
  if (param.in === "header" || param.in === "cookie") {
165
217
  if (isRequiredWithoutDefault) {
166
218
  paramResult.isValid = false;
219
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
167
220
  }
168
221
  continue;
169
222
  }
@@ -173,6 +226,7 @@ class Utils {
173
226
  schema.type !== "integer") {
174
227
  if (isRequiredWithoutDefault) {
175
228
  paramResult.isValid = false;
229
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
176
230
  }
177
231
  continue;
178
232
  }
@@ -187,17 +241,23 @@ class Utils {
187
241
  }
188
242
  return paramResult;
189
243
  }
190
- static checkPostBody(schema, isRequired = false) {
244
+ static checkPostBody(schema, isRequired = false, isCopilot = false) {
191
245
  var _a;
192
246
  const paramResult = {
193
247
  requiredNum: 0,
194
248
  optionalNum: 0,
195
249
  isValid: true,
250
+ reason: [],
196
251
  };
197
252
  if (Object.keys(schema).length === 0) {
198
253
  return paramResult;
199
254
  }
200
255
  const isRequiredWithoutDefault = isRequired && schema.default === undefined;
256
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
257
+ paramResult.isValid = false;
258
+ paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
259
+ return paramResult;
260
+ }
201
261
  if (schema.type === "string" ||
202
262
  schema.type === "integer" ||
203
263
  schema.type === "boolean" ||
@@ -216,19 +276,24 @@ class Utils {
216
276
  if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
217
277
  isRequired = true;
218
278
  }
219
- const result = Utils.checkPostBody(properties[property], isRequired);
279
+ const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
220
280
  paramResult.requiredNum += result.requiredNum;
221
281
  paramResult.optionalNum += result.optionalNum;
222
282
  paramResult.isValid = paramResult.isValid && result.isValid;
283
+ paramResult.reason.push(...result.reason);
223
284
  }
224
285
  }
225
286
  else {
226
- if (isRequiredWithoutDefault) {
287
+ if (isRequiredWithoutDefault && !isCopilot) {
227
288
  paramResult.isValid = false;
289
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
228
290
  }
229
291
  }
230
292
  return paramResult;
231
293
  }
294
+ static containMultipleMediaTypes(bodyObject) {
295
+ return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
296
+ }
232
297
  /**
233
298
  * Checks if the given API is supported.
234
299
  * @param {string} method - The HTTP method of the API.
@@ -243,106 +308,137 @@ class Utils {
243
308
  * 5. response body should be “application/json” and not empty, and response code should be 20X
244
309
  * 6. only support request body with “application/json” content type
245
310
  */
246
- static isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
247
- const pathObj = spec.paths[path];
311
+ static isSupportedApi(method, path, spec, options) {
312
+ var _a;
313
+ const result = { isValid: true, reason: [] };
248
314
  method = method.toLocaleLowerCase();
249
- if (pathObj) {
250
- if ((method === ConstantString.PostMethod || method === ConstantString.GetMethod) &&
251
- pathObj[method]) {
252
- const securities = pathObj[method].security;
253
- const authArray = Utils.getAuthArray(securities, spec);
254
- if (!Utils.isSupportedAuth(authArray, allowAPIKeyAuth, allowOauth2)) {
255
- return false;
256
- }
257
- const operationObject = pathObj[method];
258
- if (!allowMissingId && !operationObject.operationId) {
259
- return false;
260
- }
261
- const paramObject = operationObject.parameters;
262
- const requestBody = operationObject.requestBody;
263
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
264
- const mediaTypesCount = Object.keys((requestBody === null || requestBody === void 0 ? void 0 : requestBody.content) || {}).length;
265
- if (mediaTypesCount > 1) {
266
- return false;
267
- }
268
- const responseJson = Utils.getResponseJson(operationObject);
269
- if (Object.keys(responseJson).length === 0) {
270
- return false;
271
- }
272
- let requestBodyParamResult = {
273
- requiredNum: 0,
274
- optionalNum: 0,
275
- isValid: true,
276
- };
277
- if (requestJsonBody) {
278
- const requestBodySchema = requestJsonBody.schema;
279
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required);
280
- }
281
- if (!requestBodyParamResult.isValid) {
282
- return false;
315
+ if (options.allowMethods && !options.allowMethods.includes(method)) {
316
+ result.isValid = false;
317
+ result.reason.push(ErrorType.MethodNotAllowed);
318
+ return result;
319
+ }
320
+ const pathObj = spec.paths[path];
321
+ if (!pathObj || !pathObj[method]) {
322
+ result.isValid = false;
323
+ result.reason.push(ErrorType.UrlPathNotExist);
324
+ return result;
325
+ }
326
+ const securities = pathObj[method].security;
327
+ const isTeamsAi = options.projectType === ProjectType.TeamsAi;
328
+ const isCopilot = options.projectType === ProjectType.Copilot;
329
+ // Teams AI project doesn't care about auth, it will use authProvider for user to implement
330
+ if (!isTeamsAi) {
331
+ const authArray = Utils.getAuthArray(securities, spec);
332
+ const authCheckResult = Utils.isSupportedAuth(authArray, options);
333
+ if (!authCheckResult.isValid) {
334
+ result.reason.push(...authCheckResult.reason);
335
+ }
336
+ }
337
+ const operationObject = pathObj[method];
338
+ if (!options.allowMissingId && !operationObject.operationId) {
339
+ result.reason.push(ErrorType.MissingOperationId);
340
+ }
341
+ const rootServer = spec.servers && spec.servers[0];
342
+ const methodServer = spec.paths[path].servers && ((_a = spec.paths[path]) === null || _a === void 0 ? void 0 : _a.servers[0]);
343
+ const operationServer = operationObject.servers && operationObject.servers[0];
344
+ const serverUrl = operationServer || methodServer || rootServer;
345
+ if (!serverUrl) {
346
+ result.reason.push(ErrorType.NoServerInformation);
347
+ }
348
+ else {
349
+ const serverValidateResult = Utils.checkServerUrl([serverUrl]);
350
+ result.reason.push(...serverValidateResult.map((item) => item.type));
351
+ }
352
+ const paramObject = operationObject.parameters;
353
+ const requestBody = operationObject.requestBody;
354
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
355
+ if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
356
+ result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
357
+ }
358
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject, isTeamsAi);
359
+ if (multipleMediaType && !isTeamsAi) {
360
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
361
+ }
362
+ else if (Object.keys(json).length === 0) {
363
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
364
+ }
365
+ // Teams AI project doesn't care about request parameters/body
366
+ if (!isTeamsAi) {
367
+ let requestBodyParamResult = {
368
+ requiredNum: 0,
369
+ optionalNum: 0,
370
+ isValid: true,
371
+ reason: [],
372
+ };
373
+ if (requestJsonBody) {
374
+ const requestBodySchema = requestJsonBody.schema;
375
+ if (isCopilot && requestBodySchema.type !== "object") {
376
+ result.reason.push(ErrorType.PostBodySchemaIsNotJson);
283
377
  }
284
- const paramResult = Utils.checkParameters(paramObject);
285
- if (!paramResult.isValid) {
286
- return false;
378
+ requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
379
+ if (!requestBodyParamResult.isValid && requestBodyParamResult.reason) {
380
+ result.reason.push(...requestBodyParamResult.reason);
287
381
  }
288
- if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
289
- if (allowMultipleParameters &&
290
- requestBodyParamResult.requiredNum + paramResult.requiredNum <= 5) {
291
- return true;
382
+ }
383
+ const paramResult = Utils.checkParameters(paramObject, isCopilot);
384
+ if (!paramResult.isValid && paramResult.reason) {
385
+ result.reason.push(...paramResult.reason);
386
+ }
387
+ // Copilot support arbitrary parameters
388
+ if (!isCopilot && paramResult.isValid && requestBodyParamResult.isValid) {
389
+ const totalRequiredParams = requestBodyParamResult.requiredNum + paramResult.requiredNum;
390
+ const totalParams = totalRequiredParams + requestBodyParamResult.optionalNum + paramResult.optionalNum;
391
+ if (totalRequiredParams > 1) {
392
+ if (!options.allowMultipleParameters ||
393
+ totalRequiredParams > ConstantString.SMERequiredParamsMaxNum) {
394
+ result.reason.push(ErrorType.ExceededRequiredParamsLimit);
292
395
  }
293
- return false;
294
396
  }
295
- else if (requestBodyParamResult.requiredNum +
296
- requestBodyParamResult.optionalNum +
297
- paramResult.requiredNum +
298
- paramResult.optionalNum ===
299
- 0) {
300
- return false;
301
- }
302
- else {
303
- return true;
397
+ else if (totalParams === 0) {
398
+ result.reason.push(ErrorType.NoParameter);
304
399
  }
305
400
  }
306
401
  }
307
- return false;
402
+ if (result.reason.length > 0) {
403
+ result.isValid = false;
404
+ }
405
+ return result;
308
406
  }
309
- static isSupportedAuth(authSchemaArray, allowAPIKeyAuth, allowOauth2) {
310
- if (authSchemaArray.length === 0) {
311
- return true;
407
+ static isSupportedAuth(authSchemeArray, options) {
408
+ if (authSchemeArray.length === 0) {
409
+ return { isValid: true, reason: [] };
312
410
  }
313
- if (allowAPIKeyAuth || allowOauth2) {
411
+ if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
314
412
  // Currently we don't support multiple auth in one operation
315
- if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
316
- return false;
413
+ if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
414
+ return {
415
+ isValid: false,
416
+ reason: [ErrorType.MultipleAuthNotSupported],
417
+ };
317
418
  }
318
- for (const auths of authSchemaArray) {
419
+ for (const auths of authSchemeArray) {
319
420
  if (auths.length === 1) {
320
- if (!allowOauth2 && allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authSchema)) {
321
- return true;
322
- }
323
- else if (!allowAPIKeyAuth &&
324
- allowOauth2 &&
325
- Utils.isBearerTokenAuth(auths[0].authSchema)) {
326
- return true;
327
- }
328
- else if (allowAPIKeyAuth &&
329
- allowOauth2 &&
330
- (Utils.isAPIKeyAuth(auths[0].authSchema) ||
331
- Utils.isBearerTokenAuth(auths[0].authSchema))) {
332
- return true;
421
+ if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
422
+ (options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
423
+ (options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
424
+ return { isValid: true, reason: [] };
333
425
  }
334
426
  }
335
427
  }
336
428
  }
337
- return false;
429
+ return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
430
+ }
431
+ static isBearerTokenAuth(authScheme) {
432
+ return authScheme.type === "http" && authScheme.scheme === "bearer";
338
433
  }
339
- static isAPIKeyAuth(authSchema) {
340
- return authSchema.type === "apiKey";
434
+ static isAPIKeyAuth(authScheme) {
435
+ return authScheme.type === "apiKey";
341
436
  }
342
- static isBearerTokenAuth(authSchema) {
343
- return (authSchema.type === "oauth2" ||
344
- authSchema.type === "openIdConnect" ||
345
- (authSchema.type === "http" && authSchema.scheme === "bearer"));
437
+ static isOAuthWithAuthCodeFlow(authScheme) {
438
+ if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
439
+ return true;
440
+ }
441
+ return false;
346
442
  }
347
443
  static getAuthArray(securities, spec) {
348
444
  var _a;
@@ -355,7 +451,7 @@ class Utils {
355
451
  for (const name in security) {
356
452
  const auth = securitySchemas[name];
357
453
  authArray.push({
358
- authSchema: auth,
454
+ authScheme: auth,
359
455
  name: name,
360
456
  });
361
457
  }
@@ -370,21 +466,28 @@ class Utils {
370
466
  static updateFirstLetter(str) {
371
467
  return str.charAt(0).toUpperCase() + str.slice(1);
372
468
  }
373
- static getResponseJson(operationObject) {
469
+ static getResponseJson(operationObject, isTeamsAiProject = false) {
374
470
  var _a, _b;
375
471
  let json = {};
472
+ let multipleMediaType = false;
376
473
  for (const code of ConstantString.ResponseCodeFor20X) {
377
474
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
378
- const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
379
- if (mediaTypesCount > 1) {
380
- return {};
381
- }
382
475
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
476
+ multipleMediaType = false;
383
477
  json = responseObject.content["application/json"];
384
- break;
478
+ if (Utils.containMultipleMediaTypes(responseObject)) {
479
+ multipleMediaType = true;
480
+ if (isTeamsAiProject) {
481
+ break;
482
+ }
483
+ json = {};
484
+ }
485
+ else {
486
+ break;
487
+ }
385
488
  }
386
489
  }
387
- return json;
490
+ return { json, multipleMediaType };
388
491
  }
389
492
  static convertPathToCamelCase(path) {
390
493
  const pathSegments = path.split(/[./{]/);
@@ -404,10 +507,10 @@ class Utils {
404
507
  return undefined;
405
508
  }
406
509
  }
407
- static resolveServerUrl(url) {
510
+ static resolveEnv(str) {
408
511
  const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
409
- let matches = placeHolderReg.exec(url);
410
- let newUrl = url;
512
+ let matches = placeHolderReg.exec(str);
513
+ let newStr = str;
411
514
  while (matches != null) {
412
515
  const envVar = matches[1];
413
516
  const envVal = process.env[envVar];
@@ -415,17 +518,17 @@ class Utils {
415
518
  throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
416
519
  }
417
520
  else {
418
- newUrl = newUrl.replace(matches[0], envVal);
521
+ newStr = newStr.replace(matches[0], envVal);
419
522
  }
420
- matches = placeHolderReg.exec(url);
523
+ matches = placeHolderReg.exec(str);
421
524
  }
422
- return newUrl;
525
+ return newStr;
423
526
  }
424
527
  static checkServerUrl(servers) {
425
528
  const errors = [];
426
529
  let serverUrl;
427
530
  try {
428
- serverUrl = Utils.resolveServerUrl(servers[0].url);
531
+ serverUrl = Utils.resolveEnv(servers[0].url);
429
532
  }
430
533
  catch (err) {
431
534
  errors.push({
@@ -455,7 +558,8 @@ class Utils {
455
558
  }
456
559
  return errors;
457
560
  }
458
- static validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
561
+ static validateServer(spec, options) {
562
+ var _a;
459
563
  const errors = [];
460
564
  let hasTopLevelServers = false;
461
565
  let hasPathLevelServers = false;
@@ -476,7 +580,7 @@ class Utils {
476
580
  }
477
581
  for (const method in methods) {
478
582
  const operationObject = methods[method];
479
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
583
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
480
584
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
481
585
  hasOperationLevelServers = true;
482
586
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -519,6 +623,7 @@ class Utils {
519
623
  Utils.updateParameterWithInputType(schema, parameter);
520
624
  }
521
625
  if (isRequired && schema.default === undefined) {
626
+ parameter.isRequired = true;
522
627
  requiredParams.push(parameter);
523
628
  }
524
629
  else {
@@ -563,7 +668,7 @@ class Utils {
563
668
  param.value = schema.default;
564
669
  }
565
670
  }
566
- static parseApiInfo(operationItem, allowMultipleParameters) {
671
+ static parseApiInfo(operationItem, options) {
567
672
  var _a, _b;
568
673
  const requiredParams = [];
569
674
  const optionalParams = [];
@@ -577,11 +682,12 @@ class Utils {
577
682
  description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
578
683
  };
579
684
  const schema = param.schema;
580
- if (allowMultipleParameters && schema) {
685
+ if (options.allowMultipleParameters && schema) {
581
686
  Utils.updateParameterWithInputType(schema, parameter);
582
687
  }
583
688
  if (param.in !== "header" && param.in !== "cookie") {
584
689
  if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
690
+ parameter.isRequired = true;
585
691
  requiredParams.push(parameter);
586
692
  }
587
693
  else {
@@ -595,19 +701,13 @@ class Utils {
595
701
  const requestJson = requestBody.content["application/json"];
596
702
  if (Object.keys(requestJson).length !== 0) {
597
703
  const schema = requestJson.schema;
598
- const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
704
+ const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
599
705
  requiredParams.push(...requiredP);
600
706
  optionalParams.push(...optionalP);
601
707
  }
602
708
  }
603
709
  const operationId = operationItem.operationId;
604
- const parameters = [];
605
- if (requiredParams.length !== 0) {
606
- parameters.push(...requiredParams);
607
- }
608
- else {
609
- parameters.push(optionalParams[0]);
610
- }
710
+ const parameters = [...requiredParams, ...optionalParams];
611
711
  const command = {
612
712
  context: ["compose"],
613
713
  type: "query",
@@ -616,42 +716,39 @@ class Utils {
616
716
  parameters: parameters,
617
717
  description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
618
718
  };
619
- let warning = undefined;
620
- if (requiredParams.length === 0 && optionalParams.length > 1) {
621
- warning = {
622
- type: WarningType.OperationOnlyContainsOptionalParam,
623
- content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, operationId),
624
- data: operationId,
625
- };
626
- }
627
- return [command, warning];
719
+ return command;
628
720
  }
629
- static listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
721
+ static listAPIs(spec, options) {
722
+ var _a;
630
723
  const paths = spec.paths;
631
724
  const result = {};
632
725
  for (const path in paths) {
633
726
  const methods = paths[path];
634
727
  for (const method in methods) {
635
- // For developer preview, only support GET operation with only 1 parameter without auth
636
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
637
- const operationObject = methods[method];
638
- result[`${method.toUpperCase()} ${path}`] = operationObject;
728
+ const operationObject = methods[method];
729
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
730
+ const validateResult = Utils.isSupportedApi(method, path, spec, options);
731
+ result[`${method.toUpperCase()} ${path}`] = {
732
+ operation: operationObject,
733
+ isValid: validateResult.isValid,
734
+ reason: validateResult.reason,
735
+ };
639
736
  }
640
737
  }
641
738
  }
642
739
  return result;
643
740
  }
644
- static validateSpec(spec, parser, isSwaggerFile, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
741
+ static validateSpec(spec, parser, isSwaggerFile, options) {
645
742
  const errors = [];
646
743
  const warnings = [];
744
+ const apiMap = Utils.listAPIs(spec, options);
647
745
  if (isSwaggerFile) {
648
746
  warnings.push({
649
747
  type: WarningType.ConvertSwaggerToOpenAPI,
650
748
  content: ConstantString.ConvertSwaggerToOpenAPI,
651
749
  });
652
750
  }
653
- // Server validation
654
- const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
751
+ const serverErrors = Utils.validateServer(spec, options);
655
752
  errors.push(...serverErrors);
656
753
  // Remote reference not supported
657
754
  const refPaths = parser.$refs.paths();
@@ -664,8 +761,8 @@ class Utils {
664
761
  });
665
762
  }
666
763
  // No supported API
667
- const apiMap = Utils.listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
668
- if (Object.keys(apiMap).length === 0) {
764
+ const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
765
+ if (validAPIs.length === 0) {
669
766
  errors.push({
670
767
  type: ErrorType.NoSupportedApi,
671
768
  content: ConstantString.NoSupportedApi,
@@ -674,8 +771,8 @@ class Utils {
674
771
  // OperationId missing
675
772
  const apisMissingOperationId = [];
676
773
  for (const key in apiMap) {
677
- const pathObjectItem = apiMap[key];
678
- if (!pathObjectItem.operationId) {
774
+ const { operation } = apiMap[key];
775
+ if (!operation.operationId) {
679
776
  apisMissingOperationId.push(key);
680
777
  }
681
778
  }
@@ -716,6 +813,19 @@ class Utils {
716
813
  }
717
814
  return safeRegistrationIdEnvName;
718
815
  }
816
+ static getAllAPICount(spec) {
817
+ let count = 0;
818
+ const paths = spec.paths;
819
+ for (const path in paths) {
820
+ const methods = paths[path];
821
+ for (const method in methods) {
822
+ if (ConstantString.AllOperationMethods.includes(method)) {
823
+ count++;
824
+ }
825
+ }
826
+ }
827
+ return count;
828
+ }
719
829
  }
720
830
 
721
831
  // Copyright (c) Microsoft Corporation.
@@ -734,7 +844,10 @@ class SpecParser {
734
844
  allowSwagger: false,
735
845
  allowAPIKeyAuth: false,
736
846
  allowMultipleParameters: false,
847
+ allowBearerTokenAuth: false,
737
848
  allowOauth2: false,
849
+ allowMethods: ["get", "post"],
850
+ projectType: ProjectType.SME,
738
851
  };
739
852
  this.pathOrSpec = pathOrDoc;
740
853
  this.parser = new SwaggerParser();
@@ -771,7 +884,7 @@ class SpecParser {
771
884
  ],
772
885
  };
773
886
  }
774
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
887
+ return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
775
888
  }
776
889
  catch (err) {
777
890
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -790,7 +903,7 @@ class SpecParser {
790
903
  if (!operationId) {
791
904
  continue;
792
905
  }
793
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options.allowMultipleParameters);
906
+ const command = Utils.parseApiInfo(pathObjectItem, this.options);
794
907
  const apiInfo = {
795
908
  method: method,
796
909
  path: path,
@@ -799,9 +912,6 @@ class SpecParser {
799
912
  parameters: command.parameters,
800
913
  description: command.description,
801
914
  };
802
- if (warning) {
803
- apiInfo.warning = warning;
804
- }
805
915
  apiInfos.push(apiInfo);
806
916
  }
807
917
  return apiInfos;
@@ -827,6 +937,17 @@ class SpecParser {
827
937
  async getFilteredSpecs(filter, signal) {
828
938
  throw new Error("Method not implemented.");
829
939
  }
940
+ /**
941
+ * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
942
+ * @param manifestPath A file path of the Teams app manifest file to update.
943
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
944
+ * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
945
+ * @param pluginFilePath File path of the api plugin file to generate.
946
+ */
947
+ // eslint-disable-next-line @typescript-eslint/require-await
948
+ async generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
949
+ throw new Error("Method not implemented.");
950
+ }
830
951
  /**
831
952
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
832
953
  * @param manifestPath A file path of the Teams app manifest file to update.
@@ -836,7 +957,7 @@ class SpecParser {
836
957
  * @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
837
958
  */
838
959
  // eslint-disable-next-line @typescript-eslint/require-await
839
- async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal, isMe) {
960
+ async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
840
961
  throw new Error("Method not implemented.");
841
962
  }
842
963
  async loadSpec() {
@@ -853,17 +974,35 @@ class SpecParser {
853
974
  if (this.apiMap !== undefined) {
854
975
  return this.apiMap;
855
976
  }
856
- const result = Utils.listSupportedAPIs(spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
977
+ const result = this.listSupportedAPIs(spec, this.options);
857
978
  this.apiMap = result;
858
979
  return result;
859
980
  }
981
+ listSupportedAPIs(spec, options) {
982
+ var _a;
983
+ const paths = spec.paths;
984
+ const result = {};
985
+ for (const path in paths) {
986
+ const methods = paths[path];
987
+ for (const method in methods) {
988
+ const operationObject = methods[method];
989
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
990
+ const validateResult = Utils.isSupportedApi(method, path, spec, options);
991
+ if (validateResult.isValid) {
992
+ result[`${method.toUpperCase()} ${path}`] = operationObject;
993
+ }
994
+ }
995
+ }
996
+ }
997
+ return result;
998
+ }
860
999
  }
861
1000
 
862
1001
  // Copyright (c) Microsoft Corporation.
863
1002
  class AdaptiveCardGenerator {
864
1003
  static generateAdaptiveCard(operationItem) {
865
1004
  try {
866
- const json = Utils.getResponseJson(operationItem);
1005
+ const { json } = Utils.getResponseJson(operationItem);
867
1006
  let cardBody = [];
868
1007
  let schema = json.schema;
869
1008
  let jsonPath = "$";