@microsoft/m365-spec-parser 0.1.1-alpha.78701ec6a.0 → 0.1.1-alpha.7fe3da414.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";
@@ -53,6 +54,22 @@ var ErrorType;
53
54
  ErrorType["GenerateAdaptiveCardFailed"] = "generate-adaptive-card-failed";
54
55
  ErrorType["GenerateFailed"] = "generate-failed";
55
56
  ErrorType["ValidateFailed"] = "validate-failed";
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";
56
73
  ErrorType["Cancelled"] = "cancelled";
57
74
  ErrorType["Unknown"] = "unknown";
58
75
  })(ErrorType || (ErrorType = {}));
@@ -75,7 +92,13 @@ var ValidationStatus;
75
92
  ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
76
93
  ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
77
94
  ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
78
- })(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 = {}));
79
102
 
80
103
  // Copyright (c) Microsoft Corporation.
81
104
  class SpecParserError extends Error {
@@ -102,7 +125,9 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
102
125
  ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
103
126
  ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
104
127
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
105
- 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";
106
131
  ConstantString.WrappedCardVersion = "devPreview";
107
132
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
108
133
  ConstantString.WrappedCardResponseLayout = "list";
@@ -114,6 +139,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
114
139
  ConstantString.TextBlockType = "TextBlock";
115
140
  ConstantString.ContainerType = "Container";
116
141
  ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
142
+ ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
117
143
  ConstantString.ResponseCodeFor20X = [
118
144
  "200",
119
145
  "201",
@@ -173,15 +199,28 @@ ConstantString.FullDescriptionMaxLens = 4000;
173
199
  ConstantString.CommandDescriptionMaxLens = 128;
174
200
  ConstantString.ParameterDescriptionMaxLens = 128;
175
201
  ConstantString.CommandTitleMaxLens = 32;
176
- ConstantString.ParameterTitleMaxLens = 32;
202
+ ConstantString.ParameterTitleMaxLens = 32;
203
+ ConstantString.SMERequiredParamsMaxNum = 5;
177
204
 
178
205
  // Copyright (c) Microsoft Corporation.
179
206
  class Utils {
180
- static checkParameters(paramObject) {
207
+ static hasNestedObjectInSchema(schema) {
208
+ if (schema.type === "object") {
209
+ for (const property in schema.properties) {
210
+ const nestedSchema = schema.properties[property];
211
+ if (nestedSchema.type === "object") {
212
+ return true;
213
+ }
214
+ }
215
+ }
216
+ return false;
217
+ }
218
+ static checkParameters(paramObject, isCopilot) {
181
219
  const paramResult = {
182
220
  requiredNum: 0,
183
221
  optionalNum: 0,
184
222
  isValid: true,
223
+ reason: [],
185
224
  };
186
225
  if (!paramObject) {
187
226
  return paramResult;
@@ -189,10 +228,25 @@ class Utils {
189
228
  for (let i = 0; i < paramObject.length; i++) {
190
229
  const param = paramObject[i];
191
230
  const schema = param.schema;
231
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
232
+ paramResult.isValid = false;
233
+ paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
234
+ continue;
235
+ }
192
236
  const isRequiredWithoutDefault = param.required && schema.default === undefined;
237
+ if (isCopilot) {
238
+ if (isRequiredWithoutDefault) {
239
+ paramResult.requiredNum = paramResult.requiredNum + 1;
240
+ }
241
+ else {
242
+ paramResult.optionalNum = paramResult.optionalNum + 1;
243
+ }
244
+ continue;
245
+ }
193
246
  if (param.in === "header" || param.in === "cookie") {
194
247
  if (isRequiredWithoutDefault) {
195
248
  paramResult.isValid = false;
249
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
196
250
  }
197
251
  continue;
198
252
  }
@@ -202,6 +256,7 @@ class Utils {
202
256
  schema.type !== "integer") {
203
257
  if (isRequiredWithoutDefault) {
204
258
  paramResult.isValid = false;
259
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
205
260
  }
206
261
  continue;
207
262
  }
@@ -216,17 +271,23 @@ class Utils {
216
271
  }
217
272
  return paramResult;
218
273
  }
219
- static checkPostBody(schema, isRequired = false) {
274
+ static checkPostBody(schema, isRequired = false, isCopilot = false) {
220
275
  var _a;
221
276
  const paramResult = {
222
277
  requiredNum: 0,
223
278
  optionalNum: 0,
224
279
  isValid: true,
280
+ reason: [],
225
281
  };
226
282
  if (Object.keys(schema).length === 0) {
227
283
  return paramResult;
228
284
  }
229
285
  const isRequiredWithoutDefault = isRequired && schema.default === undefined;
286
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
287
+ paramResult.isValid = false;
288
+ paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
289
+ return paramResult;
290
+ }
230
291
  if (schema.type === "string" ||
231
292
  schema.type === "integer" ||
232
293
  schema.type === "boolean" ||
@@ -245,19 +306,24 @@ class Utils {
245
306
  if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
246
307
  isRequired = true;
247
308
  }
248
- const result = Utils.checkPostBody(properties[property], isRequired);
309
+ const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
249
310
  paramResult.requiredNum += result.requiredNum;
250
311
  paramResult.optionalNum += result.optionalNum;
251
312
  paramResult.isValid = paramResult.isValid && result.isValid;
313
+ paramResult.reason.push(...result.reason);
252
314
  }
253
315
  }
254
316
  else {
255
- if (isRequiredWithoutDefault) {
317
+ if (isRequiredWithoutDefault && !isCopilot) {
256
318
  paramResult.isValid = false;
319
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
257
320
  }
258
321
  }
259
322
  return paramResult;
260
323
  }
324
+ static containMultipleMediaTypes(bodyObject) {
325
+ return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
326
+ }
261
327
  /**
262
328
  * Checks if the given API is supported.
263
329
  * @param {string} method - The HTTP method of the API.
@@ -272,106 +338,137 @@ class Utils {
272
338
  * 5. response body should be “application/json” and not empty, and response code should be 20X
273
339
  * 6. only support request body with “application/json” content type
274
340
  */
275
- static isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
276
- const pathObj = spec.paths[path];
341
+ static isSupportedApi(method, path, spec, options) {
342
+ var _a;
343
+ const result = { isValid: true, reason: [] };
277
344
  method = method.toLocaleLowerCase();
278
- if (pathObj) {
279
- if ((method === ConstantString.PostMethod || method === ConstantString.GetMethod) &&
280
- pathObj[method]) {
281
- const securities = pathObj[method].security;
282
- const authArray = Utils.getAuthArray(securities, spec);
283
- if (!Utils.isSupportedAuth(authArray, allowAPIKeyAuth, allowOauth2)) {
284
- return false;
285
- }
286
- const operationObject = pathObj[method];
287
- if (!allowMissingId && !operationObject.operationId) {
288
- return false;
289
- }
290
- const paramObject = operationObject.parameters;
291
- const requestBody = operationObject.requestBody;
292
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
293
- const mediaTypesCount = Object.keys((requestBody === null || requestBody === void 0 ? void 0 : requestBody.content) || {}).length;
294
- if (mediaTypesCount > 1) {
295
- return false;
296
- }
297
- const responseJson = Utils.getResponseJson(operationObject);
298
- if (Object.keys(responseJson).length === 0) {
299
- return false;
300
- }
301
- let requestBodyParamResult = {
302
- requiredNum: 0,
303
- optionalNum: 0,
304
- isValid: true,
305
- };
306
- if (requestJsonBody) {
307
- const requestBodySchema = requestJsonBody.schema;
308
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required);
309
- }
310
- if (!requestBodyParamResult.isValid) {
311
- return false;
345
+ if (options.allowMethods && !options.allowMethods.includes(method)) {
346
+ result.isValid = false;
347
+ result.reason.push(ErrorType.MethodNotAllowed);
348
+ return result;
349
+ }
350
+ const pathObj = spec.paths[path];
351
+ if (!pathObj || !pathObj[method]) {
352
+ result.isValid = false;
353
+ result.reason.push(ErrorType.UrlPathNotExist);
354
+ return result;
355
+ }
356
+ const securities = pathObj[method].security;
357
+ const isTeamsAi = options.projectType === ProjectType.TeamsAi;
358
+ const isCopilot = options.projectType === ProjectType.Copilot;
359
+ // Teams AI project doesn't care about auth, it will use authProvider for user to implement
360
+ if (!isTeamsAi) {
361
+ const authArray = Utils.getAuthArray(securities, spec);
362
+ const authCheckResult = Utils.isSupportedAuth(authArray, options);
363
+ if (!authCheckResult.isValid) {
364
+ result.reason.push(...authCheckResult.reason);
365
+ }
366
+ }
367
+ const operationObject = pathObj[method];
368
+ if (!options.allowMissingId && !operationObject.operationId) {
369
+ result.reason.push(ErrorType.MissingOperationId);
370
+ }
371
+ const rootServer = spec.servers && spec.servers[0];
372
+ const methodServer = spec.paths[path].servers && ((_a = spec.paths[path]) === null || _a === void 0 ? void 0 : _a.servers[0]);
373
+ const operationServer = operationObject.servers && operationObject.servers[0];
374
+ const serverUrl = operationServer || methodServer || rootServer;
375
+ if (!serverUrl) {
376
+ result.reason.push(ErrorType.NoServerInformation);
377
+ }
378
+ else {
379
+ const serverValidateResult = Utils.checkServerUrl([serverUrl]);
380
+ result.reason.push(...serverValidateResult.map((item) => item.type));
381
+ }
382
+ const paramObject = operationObject.parameters;
383
+ const requestBody = operationObject.requestBody;
384
+ const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
385
+ if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
386
+ result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
387
+ }
388
+ const { json, multipleMediaType } = Utils.getResponseJson(operationObject, isTeamsAi);
389
+ if (multipleMediaType && !isTeamsAi) {
390
+ result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
391
+ }
392
+ else if (Object.keys(json).length === 0) {
393
+ result.reason.push(ErrorType.ResponseJsonIsEmpty);
394
+ }
395
+ // Teams AI project doesn't care about request parameters/body
396
+ if (!isTeamsAi) {
397
+ let requestBodyParamResult = {
398
+ requiredNum: 0,
399
+ optionalNum: 0,
400
+ isValid: true,
401
+ reason: [],
402
+ };
403
+ if (requestJsonBody) {
404
+ const requestBodySchema = requestJsonBody.schema;
405
+ if (isCopilot && requestBodySchema.type !== "object") {
406
+ result.reason.push(ErrorType.PostBodySchemaIsNotJson);
312
407
  }
313
- const paramResult = Utils.checkParameters(paramObject);
314
- if (!paramResult.isValid) {
315
- return false;
408
+ requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
409
+ if (!requestBodyParamResult.isValid && requestBodyParamResult.reason) {
410
+ result.reason.push(...requestBodyParamResult.reason);
316
411
  }
317
- if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
318
- if (allowMultipleParameters &&
319
- requestBodyParamResult.requiredNum + paramResult.requiredNum <= 5) {
320
- return true;
412
+ }
413
+ const paramResult = Utils.checkParameters(paramObject, isCopilot);
414
+ if (!paramResult.isValid && paramResult.reason) {
415
+ result.reason.push(...paramResult.reason);
416
+ }
417
+ // Copilot support arbitrary parameters
418
+ if (!isCopilot && paramResult.isValid && requestBodyParamResult.isValid) {
419
+ const totalRequiredParams = requestBodyParamResult.requiredNum + paramResult.requiredNum;
420
+ const totalParams = totalRequiredParams + requestBodyParamResult.optionalNum + paramResult.optionalNum;
421
+ if (totalRequiredParams > 1) {
422
+ if (!options.allowMultipleParameters ||
423
+ totalRequiredParams > ConstantString.SMERequiredParamsMaxNum) {
424
+ result.reason.push(ErrorType.ExceededRequiredParamsLimit);
321
425
  }
322
- return false;
323
- }
324
- else if (requestBodyParamResult.requiredNum +
325
- requestBodyParamResult.optionalNum +
326
- paramResult.requiredNum +
327
- paramResult.optionalNum ===
328
- 0) {
329
- return false;
330
426
  }
331
- else {
332
- return true;
427
+ else if (totalParams === 0) {
428
+ result.reason.push(ErrorType.NoParameter);
333
429
  }
334
430
  }
335
431
  }
336
- return false;
432
+ if (result.reason.length > 0) {
433
+ result.isValid = false;
434
+ }
435
+ return result;
337
436
  }
338
- static isSupportedAuth(authSchemaArray, allowAPIKeyAuth, allowOauth2) {
339
- if (authSchemaArray.length === 0) {
340
- return true;
437
+ static isSupportedAuth(authSchemeArray, options) {
438
+ if (authSchemeArray.length === 0) {
439
+ return { isValid: true, reason: [] };
341
440
  }
342
- if (allowAPIKeyAuth || allowOauth2) {
441
+ if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
343
442
  // Currently we don't support multiple auth in one operation
344
- if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
345
- return false;
443
+ if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
444
+ return {
445
+ isValid: false,
446
+ reason: [ErrorType.MultipleAuthNotSupported],
447
+ };
346
448
  }
347
- for (const auths of authSchemaArray) {
449
+ for (const auths of authSchemeArray) {
348
450
  if (auths.length === 1) {
349
- if (!allowOauth2 && allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authSchema)) {
350
- return true;
351
- }
352
- else if (!allowAPIKeyAuth &&
353
- allowOauth2 &&
354
- Utils.isBearerTokenAuth(auths[0].authSchema)) {
355
- return true;
356
- }
357
- else if (allowAPIKeyAuth &&
358
- allowOauth2 &&
359
- (Utils.isAPIKeyAuth(auths[0].authSchema) ||
360
- Utils.isBearerTokenAuth(auths[0].authSchema))) {
361
- return true;
451
+ if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
452
+ (options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
453
+ (options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
454
+ return { isValid: true, reason: [] };
362
455
  }
363
456
  }
364
457
  }
365
458
  }
366
- return false;
459
+ return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
367
460
  }
368
- static isAPIKeyAuth(authSchema) {
369
- return authSchema.type === "apiKey";
461
+ static isBearerTokenAuth(authScheme) {
462
+ return authScheme.type === "http" && authScheme.scheme === "bearer";
370
463
  }
371
- static isBearerTokenAuth(authSchema) {
372
- return (authSchema.type === "oauth2" ||
373
- authSchema.type === "openIdConnect" ||
374
- (authSchema.type === "http" && authSchema.scheme === "bearer"));
464
+ static isAPIKeyAuth(authScheme) {
465
+ return authScheme.type === "apiKey";
466
+ }
467
+ static isOAuthWithAuthCodeFlow(authScheme) {
468
+ if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
469
+ return true;
470
+ }
471
+ return false;
375
472
  }
376
473
  static getAuthArray(securities, spec) {
377
474
  var _a;
@@ -384,7 +481,7 @@ class Utils {
384
481
  for (const name in security) {
385
482
  const auth = securitySchemas[name];
386
483
  authArray.push({
387
- authSchema: auth,
484
+ authScheme: auth,
388
485
  name: name,
389
486
  });
390
487
  }
@@ -399,21 +496,28 @@ class Utils {
399
496
  static updateFirstLetter(str) {
400
497
  return str.charAt(0).toUpperCase() + str.slice(1);
401
498
  }
402
- static getResponseJson(operationObject) {
499
+ static getResponseJson(operationObject, isTeamsAiProject = false) {
403
500
  var _a, _b;
404
501
  let json = {};
502
+ let multipleMediaType = false;
405
503
  for (const code of ConstantString.ResponseCodeFor20X) {
406
504
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
407
- const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
408
- if (mediaTypesCount > 1) {
409
- return {};
410
- }
411
505
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
506
+ multipleMediaType = false;
412
507
  json = responseObject.content["application/json"];
413
- break;
508
+ if (Utils.containMultipleMediaTypes(responseObject)) {
509
+ multipleMediaType = true;
510
+ if (isTeamsAiProject) {
511
+ break;
512
+ }
513
+ json = {};
514
+ }
515
+ else {
516
+ break;
517
+ }
414
518
  }
415
519
  }
416
- return json;
520
+ return { json, multipleMediaType };
417
521
  }
418
522
  static convertPathToCamelCase(path) {
419
523
  const pathSegments = path.split(/[./{]/);
@@ -433,10 +537,10 @@ class Utils {
433
537
  return undefined;
434
538
  }
435
539
  }
436
- static resolveServerUrl(url) {
540
+ static resolveEnv(str) {
437
541
  const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
438
- let matches = placeHolderReg.exec(url);
439
- let newUrl = url;
542
+ let matches = placeHolderReg.exec(str);
543
+ let newStr = str;
440
544
  while (matches != null) {
441
545
  const envVar = matches[1];
442
546
  const envVal = process.env[envVar];
@@ -444,17 +548,17 @@ class Utils {
444
548
  throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
445
549
  }
446
550
  else {
447
- newUrl = newUrl.replace(matches[0], envVal);
551
+ newStr = newStr.replace(matches[0], envVal);
448
552
  }
449
- matches = placeHolderReg.exec(url);
553
+ matches = placeHolderReg.exec(str);
450
554
  }
451
- return newUrl;
555
+ return newStr;
452
556
  }
453
557
  static checkServerUrl(servers) {
454
558
  const errors = [];
455
559
  let serverUrl;
456
560
  try {
457
- serverUrl = Utils.resolveServerUrl(servers[0].url);
561
+ serverUrl = Utils.resolveEnv(servers[0].url);
458
562
  }
459
563
  catch (err) {
460
564
  errors.push({
@@ -484,7 +588,8 @@ class Utils {
484
588
  }
485
589
  return errors;
486
590
  }
487
- static validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
591
+ static validateServer(spec, options) {
592
+ var _a;
488
593
  const errors = [];
489
594
  let hasTopLevelServers = false;
490
595
  let hasPathLevelServers = false;
@@ -505,7 +610,7 @@ class Utils {
505
610
  }
506
611
  for (const method in methods) {
507
612
  const operationObject = methods[method];
508
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
613
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
509
614
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
510
615
  hasOperationLevelServers = true;
511
616
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -548,6 +653,7 @@ class Utils {
548
653
  Utils.updateParameterWithInputType(schema, parameter);
549
654
  }
550
655
  if (isRequired && schema.default === undefined) {
656
+ parameter.isRequired = true;
551
657
  requiredParams.push(parameter);
552
658
  }
553
659
  else {
@@ -592,7 +698,7 @@ class Utils {
592
698
  param.value = schema.default;
593
699
  }
594
700
  }
595
- static parseApiInfo(operationItem, allowMultipleParameters) {
701
+ static parseApiInfo(operationItem, options) {
596
702
  var _a, _b;
597
703
  const requiredParams = [];
598
704
  const optionalParams = [];
@@ -606,11 +712,12 @@ class Utils {
606
712
  description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
607
713
  };
608
714
  const schema = param.schema;
609
- if (allowMultipleParameters && schema) {
715
+ if (options.allowMultipleParameters && schema) {
610
716
  Utils.updateParameterWithInputType(schema, parameter);
611
717
  }
612
718
  if (param.in !== "header" && param.in !== "cookie") {
613
719
  if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
720
+ parameter.isRequired = true;
614
721
  requiredParams.push(parameter);
615
722
  }
616
723
  else {
@@ -624,7 +731,7 @@ class Utils {
624
731
  const requestJson = requestBody.content["application/json"];
625
732
  if (Object.keys(requestJson).length !== 0) {
626
733
  const schema = requestJson.schema;
627
- const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
734
+ const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
628
735
  requiredParams.push(...requiredP);
629
736
  optionalParams.push(...optionalP);
630
737
  }
@@ -655,32 +762,37 @@ class Utils {
655
762
  }
656
763
  return [command, warning];
657
764
  }
658
- static listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
765
+ static listAPIs(spec, options) {
766
+ var _a;
659
767
  const paths = spec.paths;
660
768
  const result = {};
661
769
  for (const path in paths) {
662
770
  const methods = paths[path];
663
771
  for (const method in methods) {
664
- // For developer preview, only support GET operation with only 1 parameter without auth
665
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
666
- const operationObject = methods[method];
667
- result[`${method.toUpperCase()} ${path}`] = operationObject;
772
+ const operationObject = methods[method];
773
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
774
+ const validateResult = Utils.isSupportedApi(method, path, spec, options);
775
+ result[`${method.toUpperCase()} ${path}`] = {
776
+ operation: operationObject,
777
+ isValid: validateResult.isValid,
778
+ reason: validateResult.reason,
779
+ };
668
780
  }
669
781
  }
670
782
  }
671
783
  return result;
672
784
  }
673
- static validateSpec(spec, parser, isSwaggerFile, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
785
+ static validateSpec(spec, parser, isSwaggerFile, options) {
674
786
  const errors = [];
675
787
  const warnings = [];
788
+ const apiMap = Utils.listAPIs(spec, options);
676
789
  if (isSwaggerFile) {
677
790
  warnings.push({
678
791
  type: WarningType.ConvertSwaggerToOpenAPI,
679
792
  content: ConstantString.ConvertSwaggerToOpenAPI,
680
793
  });
681
794
  }
682
- // Server validation
683
- const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
795
+ const serverErrors = Utils.validateServer(spec, options);
684
796
  errors.push(...serverErrors);
685
797
  // Remote reference not supported
686
798
  const refPaths = parser.$refs.paths();
@@ -693,8 +805,8 @@ class Utils {
693
805
  });
694
806
  }
695
807
  // No supported API
696
- const apiMap = Utils.listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
697
- if (Object.keys(apiMap).length === 0) {
808
+ const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
809
+ if (validAPIs.length === 0) {
698
810
  errors.push({
699
811
  type: ErrorType.NoSupportedApi,
700
812
  content: ConstantString.NoSupportedApi,
@@ -703,8 +815,8 @@ class Utils {
703
815
  // OperationId missing
704
816
  const apisMissingOperationId = [];
705
817
  for (const key in apiMap) {
706
- const pathObjectItem = apiMap[key];
707
- if (!pathObjectItem.operationId) {
818
+ const { operation } = apiMap[key];
819
+ if (!operation.operationId) {
708
820
  apisMissingOperationId.push(key);
709
821
  }
710
822
  }
@@ -745,6 +857,19 @@ class Utils {
745
857
  }
746
858
  return safeRegistrationIdEnvName;
747
859
  }
860
+ static getAllAPICount(spec) {
861
+ let count = 0;
862
+ const paths = spec.paths;
863
+ for (const path in paths) {
864
+ const methods = paths[path];
865
+ for (const method in methods) {
866
+ if (ConstantString.AllOperationMethods.includes(method)) {
867
+ count++;
868
+ }
869
+ }
870
+ }
871
+ return count;
872
+ }
748
873
  }
749
874
 
750
875
  // Copyright (c) Microsoft Corporation.
@@ -763,7 +888,10 @@ class SpecParser {
763
888
  allowSwagger: false,
764
889
  allowAPIKeyAuth: false,
765
890
  allowMultipleParameters: false,
891
+ allowBearerTokenAuth: false,
766
892
  allowOauth2: false,
893
+ allowMethods: ["get", "post"],
894
+ projectType: ProjectType.SME,
767
895
  };
768
896
  this.pathOrSpec = pathOrDoc;
769
897
  this.parser = new SwaggerParser();
@@ -801,7 +929,7 @@ class SpecParser {
801
929
  ],
802
930
  };
803
931
  }
804
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
932
+ return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
805
933
  }
806
934
  catch (err) {
807
935
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -822,7 +950,7 @@ class SpecParser {
822
950
  if (!operationId) {
823
951
  continue;
824
952
  }
825
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options.allowMultipleParameters);
953
+ const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
826
954
  const apiInfo = {
827
955
  method: method,
828
956
  path: path,
@@ -854,12 +982,36 @@ class SpecParser {
854
982
  throw new Error("Method not implemented.");
855
983
  });
856
984
  }
985
+ /**
986
+ * Generate specs according to the filters.
987
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
988
+ */
989
+ // eslint-disable-next-line @typescript-eslint/require-await
990
+ getFilteredSpecs(filter, signal) {
991
+ return __awaiter(this, void 0, void 0, function* () {
992
+ throw new Error("Method not implemented.");
993
+ });
994
+ }
995
+ /**
996
+ * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
997
+ * @param manifestPath A file path of the Teams app manifest file to update.
998
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
999
+ * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
1000
+ * @param pluginFilePath File path of the api plugin file to generate.
1001
+ */
1002
+ // eslint-disable-next-line @typescript-eslint/require-await
1003
+ generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
1004
+ return __awaiter(this, void 0, void 0, function* () {
1005
+ throw new Error("Method not implemented.");
1006
+ });
1007
+ }
857
1008
  /**
858
1009
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
859
1010
  * @param manifestPath A file path of the Teams app manifest file to update.
860
1011
  * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
861
1012
  * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
862
1013
  * @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
1014
+ * @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
863
1015
  */
864
1016
  // eslint-disable-next-line @typescript-eslint/require-await
865
1017
  generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
@@ -883,11 +1035,187 @@ class SpecParser {
883
1035
  if (this.apiMap !== undefined) {
884
1036
  return this.apiMap;
885
1037
  }
886
- const result = Utils.listSupportedAPIs(spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
1038
+ const result = this.listSupportedAPIs(spec, this.options);
887
1039
  this.apiMap = result;
888
1040
  return result;
889
1041
  }
1042
+ listSupportedAPIs(spec, options) {
1043
+ var _a;
1044
+ const paths = spec.paths;
1045
+ const result = {};
1046
+ for (const path in paths) {
1047
+ const methods = paths[path];
1048
+ for (const method in methods) {
1049
+ const operationObject = methods[method];
1050
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
1051
+ const validateResult = Utils.isSupportedApi(method, path, spec, options);
1052
+ if (validateResult.isValid) {
1053
+ result[`${method.toUpperCase()} ${path}`] = operationObject;
1054
+ }
1055
+ }
1056
+ }
1057
+ }
1058
+ return result;
1059
+ }
1060
+ }
1061
+
1062
+ // Copyright (c) Microsoft Corporation.
1063
+ class AdaptiveCardGenerator {
1064
+ static generateAdaptiveCard(operationItem) {
1065
+ try {
1066
+ const { json } = Utils.getResponseJson(operationItem);
1067
+ let cardBody = [];
1068
+ let schema = json.schema;
1069
+ let jsonPath = "$";
1070
+ if (schema && Object.keys(schema).length > 0) {
1071
+ jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
1072
+ if (jsonPath !== "$") {
1073
+ schema = schema.properties[jsonPath];
1074
+ }
1075
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1076
+ }
1077
+ // if no schema, try to use example value
1078
+ if (cardBody.length === 0 && (json.examples || json.example)) {
1079
+ cardBody = [
1080
+ {
1081
+ type: ConstantString.TextBlockType,
1082
+ text: "${jsonStringify($root)}",
1083
+ wrap: true,
1084
+ },
1085
+ ];
1086
+ }
1087
+ // if no example value, use default success response
1088
+ if (cardBody.length === 0) {
1089
+ cardBody = [
1090
+ {
1091
+ type: ConstantString.TextBlockType,
1092
+ text: "success",
1093
+ wrap: true,
1094
+ },
1095
+ ];
1096
+ }
1097
+ const fullCard = {
1098
+ type: ConstantString.AdaptiveCardType,
1099
+ $schema: ConstantString.AdaptiveCardSchema,
1100
+ version: ConstantString.AdaptiveCardVersion,
1101
+ body: cardBody,
1102
+ };
1103
+ return [fullCard, jsonPath];
1104
+ }
1105
+ catch (err) {
1106
+ throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
1107
+ }
1108
+ }
1109
+ static generateCardFromResponse(schema, name, parentArrayName = "") {
1110
+ if (schema.type === "array") {
1111
+ // schema.items can be arbitrary object: schema { type: array, items: {} }
1112
+ if (Object.keys(schema.items).length === 0) {
1113
+ return [
1114
+ {
1115
+ type: ConstantString.TextBlockType,
1116
+ text: name ? `${name}: \${jsonStringify(${name})}` : "result: ${jsonStringify($root)}",
1117
+ wrap: true,
1118
+ },
1119
+ ];
1120
+ }
1121
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1122
+ const template = {
1123
+ type: ConstantString.ContainerType,
1124
+ $data: name ? `\${${name}}` : "${$root}",
1125
+ items: Array(),
1126
+ };
1127
+ template.items.push(...obj);
1128
+ return [template];
1129
+ }
1130
+ // some schema may not contain type but contain properties
1131
+ if (schema.type === "object" || (!schema.type && schema.properties)) {
1132
+ const { properties } = schema;
1133
+ const result = [];
1134
+ for (const property in properties) {
1135
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1136
+ result.push(...obj);
1137
+ }
1138
+ if (schema.additionalProperties) {
1139
+ // TODO: better ways to handler warnings.
1140
+ console.warn(ConstantString.AdditionalPropertiesNotSupported);
1141
+ }
1142
+ return result;
1143
+ }
1144
+ if (schema.type === "string" ||
1145
+ schema.type === "integer" ||
1146
+ schema.type === "boolean" ||
1147
+ schema.type === "number") {
1148
+ if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1149
+ // string in root: "ddd"
1150
+ let text = "result: ${$root}";
1151
+ if (name) {
1152
+ // object { id: "1" }
1153
+ text = `${name}: \${if(${name}, ${name}, 'N/A')}`;
1154
+ if (parentArrayName) {
1155
+ // object types inside array: { tags: ["id": 1, "name": "name"] }
1156
+ text = `${parentArrayName}.${text}`;
1157
+ }
1158
+ }
1159
+ else if (parentArrayName) {
1160
+ // string array: photoUrls: ["1", "2"]
1161
+ text = `${parentArrayName}: ` + "${$data}";
1162
+ }
1163
+ return [
1164
+ {
1165
+ type: ConstantString.TextBlockType,
1166
+ text,
1167
+ wrap: true,
1168
+ },
1169
+ ];
1170
+ }
1171
+ else {
1172
+ if (name) {
1173
+ return [
1174
+ {
1175
+ type: "Image",
1176
+ url: `\${${name}}`,
1177
+ $when: `\${${name} != null}`,
1178
+ },
1179
+ ];
1180
+ }
1181
+ else {
1182
+ return [
1183
+ {
1184
+ type: "Image",
1185
+ url: "${$data}",
1186
+ $when: "${$data != null}",
1187
+ },
1188
+ ];
1189
+ }
1190
+ }
1191
+ }
1192
+ if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
1193
+ throw new Error(Utils.format(ConstantString.SchemaNotSupported, JSON.stringify(schema)));
1194
+ }
1195
+ throw new Error(Utils.format(ConstantString.UnknownSchema, JSON.stringify(schema)));
1196
+ }
1197
+ // Find the first array property in the response schema object with the well-known name
1198
+ static getResponseJsonPathFromSchema(schema) {
1199
+ if (schema.type === "object" || (!schema.type && schema.properties)) {
1200
+ const { properties } = schema;
1201
+ for (const property in properties) {
1202
+ const schema = properties[property];
1203
+ if (schema.type === "array" &&
1204
+ Utils.isWellKnownName(property, ConstantString.WellknownResultNames)) {
1205
+ return property;
1206
+ }
1207
+ }
1208
+ }
1209
+ return "$";
1210
+ }
1211
+ static isImageUrlProperty(schema, name, parentArrayName) {
1212
+ const propertyName = name ? name : parentArrayName;
1213
+ return (!!propertyName &&
1214
+ schema.type === "string" &&
1215
+ Utils.isWellKnownName(propertyName, ConstantString.WellknownImageName) &&
1216
+ (propertyName.toLocaleLowerCase().indexOf("url") >= 0 || schema.format === "uri"));
1217
+ }
890
1218
  }
891
1219
 
892
- export { ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
1220
+ export { AdaptiveCardGenerator, ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
893
1221
  //# sourceMappingURL=index.esm5.js.map