@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.
@@ -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";
@@ -23,6 +24,22 @@ var ErrorType;
23
24
  ErrorType["GenerateAdaptiveCardFailed"] = "generate-adaptive-card-failed";
24
25
  ErrorType["GenerateFailed"] = "generate-failed";
25
26
  ErrorType["ValidateFailed"] = "validate-failed";
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";
26
43
  ErrorType["Cancelled"] = "cancelled";
27
44
  ErrorType["Unknown"] = "unknown";
28
45
  })(ErrorType || (ErrorType = {}));
@@ -45,7 +62,13 @@ var ValidationStatus;
45
62
  ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
46
63
  ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
47
64
  ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
48
- })(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 = {}));
49
72
 
50
73
  // Copyright (c) Microsoft Corporation.
51
74
  class SpecParserError extends Error {
@@ -72,7 +95,9 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
72
95
  ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
73
96
  ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
74
97
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
75
- 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";
76
101
  ConstantString.WrappedCardVersion = "devPreview";
77
102
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
78
103
  ConstantString.WrappedCardResponseLayout = "list";
@@ -84,6 +109,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
84
109
  ConstantString.TextBlockType = "TextBlock";
85
110
  ConstantString.ContainerType = "Container";
86
111
  ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
112
+ ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
87
113
  ConstantString.ResponseCodeFor20X = [
88
114
  "200",
89
115
  "201",
@@ -143,15 +169,28 @@ ConstantString.FullDescriptionMaxLens = 4000;
143
169
  ConstantString.CommandDescriptionMaxLens = 128;
144
170
  ConstantString.ParameterDescriptionMaxLens = 128;
145
171
  ConstantString.CommandTitleMaxLens = 32;
146
- ConstantString.ParameterTitleMaxLens = 32;
172
+ ConstantString.ParameterTitleMaxLens = 32;
173
+ ConstantString.SMERequiredParamsMaxNum = 5;
147
174
 
148
175
  // Copyright (c) Microsoft Corporation.
149
176
  class Utils {
150
- 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) {
151
189
  const paramResult = {
152
190
  requiredNum: 0,
153
191
  optionalNum: 0,
154
192
  isValid: true,
193
+ reason: [],
155
194
  };
156
195
  if (!paramObject) {
157
196
  return paramResult;
@@ -159,10 +198,25 @@ class Utils {
159
198
  for (let i = 0; i < paramObject.length; i++) {
160
199
  const param = paramObject[i];
161
200
  const schema = param.schema;
201
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
202
+ paramResult.isValid = false;
203
+ paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
204
+ continue;
205
+ }
162
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
+ }
163
216
  if (param.in === "header" || param.in === "cookie") {
164
217
  if (isRequiredWithoutDefault) {
165
218
  paramResult.isValid = false;
219
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
166
220
  }
167
221
  continue;
168
222
  }
@@ -172,6 +226,7 @@ class Utils {
172
226
  schema.type !== "integer") {
173
227
  if (isRequiredWithoutDefault) {
174
228
  paramResult.isValid = false;
229
+ paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
175
230
  }
176
231
  continue;
177
232
  }
@@ -186,17 +241,23 @@ class Utils {
186
241
  }
187
242
  return paramResult;
188
243
  }
189
- static checkPostBody(schema, isRequired = false) {
244
+ static checkPostBody(schema, isRequired = false, isCopilot = false) {
190
245
  var _a;
191
246
  const paramResult = {
192
247
  requiredNum: 0,
193
248
  optionalNum: 0,
194
249
  isValid: true,
250
+ reason: [],
195
251
  };
196
252
  if (Object.keys(schema).length === 0) {
197
253
  return paramResult;
198
254
  }
199
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
+ }
200
261
  if (schema.type === "string" ||
201
262
  schema.type === "integer" ||
202
263
  schema.type === "boolean" ||
@@ -215,19 +276,24 @@ class Utils {
215
276
  if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
216
277
  isRequired = true;
217
278
  }
218
- const result = Utils.checkPostBody(properties[property], isRequired);
279
+ const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
219
280
  paramResult.requiredNum += result.requiredNum;
220
281
  paramResult.optionalNum += result.optionalNum;
221
282
  paramResult.isValid = paramResult.isValid && result.isValid;
283
+ paramResult.reason.push(...result.reason);
222
284
  }
223
285
  }
224
286
  else {
225
- if (isRequiredWithoutDefault) {
287
+ if (isRequiredWithoutDefault && !isCopilot) {
226
288
  paramResult.isValid = false;
289
+ paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
227
290
  }
228
291
  }
229
292
  return paramResult;
230
293
  }
294
+ static containMultipleMediaTypes(bodyObject) {
295
+ return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
296
+ }
231
297
  /**
232
298
  * Checks if the given API is supported.
233
299
  * @param {string} method - The HTTP method of the API.
@@ -242,106 +308,137 @@ class Utils {
242
308
  * 5. response body should be “application/json” and not empty, and response code should be 20X
243
309
  * 6. only support request body with “application/json” content type
244
310
  */
245
- static isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
246
- const pathObj = spec.paths[path];
311
+ static isSupportedApi(method, path, spec, options) {
312
+ var _a;
313
+ const result = { isValid: true, reason: [] };
247
314
  method = method.toLocaleLowerCase();
248
- if (pathObj) {
249
- if ((method === ConstantString.PostMethod || method === ConstantString.GetMethod) &&
250
- pathObj[method]) {
251
- const securities = pathObj[method].security;
252
- const authArray = Utils.getAuthArray(securities, spec);
253
- if (!Utils.isSupportedAuth(authArray, allowAPIKeyAuth, allowOauth2)) {
254
- return false;
255
- }
256
- const operationObject = pathObj[method];
257
- if (!allowMissingId && !operationObject.operationId) {
258
- return false;
259
- }
260
- const paramObject = operationObject.parameters;
261
- const requestBody = operationObject.requestBody;
262
- const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
263
- const mediaTypesCount = Object.keys((requestBody === null || requestBody === void 0 ? void 0 : requestBody.content) || {}).length;
264
- if (mediaTypesCount > 1) {
265
- return false;
266
- }
267
- const responseJson = Utils.getResponseJson(operationObject);
268
- if (Object.keys(responseJson).length === 0) {
269
- return false;
270
- }
271
- let requestBodyParamResult = {
272
- requiredNum: 0,
273
- optionalNum: 0,
274
- isValid: true,
275
- };
276
- if (requestJsonBody) {
277
- const requestBodySchema = requestJsonBody.schema;
278
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required);
279
- }
280
- if (!requestBodyParamResult.isValid) {
281
- 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);
282
377
  }
283
- const paramResult = Utils.checkParameters(paramObject);
284
- if (!paramResult.isValid) {
285
- return false;
378
+ requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
379
+ if (!requestBodyParamResult.isValid && requestBodyParamResult.reason) {
380
+ result.reason.push(...requestBodyParamResult.reason);
286
381
  }
287
- if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
288
- if (allowMultipleParameters &&
289
- requestBodyParamResult.requiredNum + paramResult.requiredNum <= 5) {
290
- 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);
291
395
  }
292
- return false;
293
396
  }
294
- else if (requestBodyParamResult.requiredNum +
295
- requestBodyParamResult.optionalNum +
296
- paramResult.requiredNum +
297
- paramResult.optionalNum ===
298
- 0) {
299
- return false;
300
- }
301
- else {
302
- return true;
397
+ else if (totalParams === 0) {
398
+ result.reason.push(ErrorType.NoParameter);
303
399
  }
304
400
  }
305
401
  }
306
- return false;
402
+ if (result.reason.length > 0) {
403
+ result.isValid = false;
404
+ }
405
+ return result;
307
406
  }
308
- static isSupportedAuth(authSchemaArray, allowAPIKeyAuth, allowOauth2) {
309
- if (authSchemaArray.length === 0) {
310
- return true;
407
+ static isSupportedAuth(authSchemeArray, options) {
408
+ if (authSchemeArray.length === 0) {
409
+ return { isValid: true, reason: [] };
311
410
  }
312
- if (allowAPIKeyAuth || allowOauth2) {
411
+ if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
313
412
  // Currently we don't support multiple auth in one operation
314
- if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
315
- return false;
413
+ if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
414
+ return {
415
+ isValid: false,
416
+ reason: [ErrorType.MultipleAuthNotSupported],
417
+ };
316
418
  }
317
- for (const auths of authSchemaArray) {
419
+ for (const auths of authSchemeArray) {
318
420
  if (auths.length === 1) {
319
- if (!allowOauth2 && allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authSchema)) {
320
- return true;
321
- }
322
- else if (!allowAPIKeyAuth &&
323
- allowOauth2 &&
324
- Utils.isBearerTokenAuth(auths[0].authSchema)) {
325
- return true;
326
- }
327
- else if (allowAPIKeyAuth &&
328
- allowOauth2 &&
329
- (Utils.isAPIKeyAuth(auths[0].authSchema) ||
330
- Utils.isBearerTokenAuth(auths[0].authSchema))) {
331
- 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: [] };
332
425
  }
333
426
  }
334
427
  }
335
428
  }
336
- return false;
429
+ return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
337
430
  }
338
- static isAPIKeyAuth(authSchema) {
339
- return authSchema.type === "apiKey";
431
+ static isBearerTokenAuth(authScheme) {
432
+ return authScheme.type === "http" && authScheme.scheme === "bearer";
340
433
  }
341
- static isBearerTokenAuth(authSchema) {
342
- return (authSchema.type === "oauth2" ||
343
- authSchema.type === "openIdConnect" ||
344
- (authSchema.type === "http" && authSchema.scheme === "bearer"));
434
+ static isAPIKeyAuth(authScheme) {
435
+ return authScheme.type === "apiKey";
436
+ }
437
+ static isOAuthWithAuthCodeFlow(authScheme) {
438
+ if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
439
+ return true;
440
+ }
441
+ return false;
345
442
  }
346
443
  static getAuthArray(securities, spec) {
347
444
  var _a;
@@ -354,7 +451,7 @@ class Utils {
354
451
  for (const name in security) {
355
452
  const auth = securitySchemas[name];
356
453
  authArray.push({
357
- authSchema: auth,
454
+ authScheme: auth,
358
455
  name: name,
359
456
  });
360
457
  }
@@ -369,21 +466,28 @@ class Utils {
369
466
  static updateFirstLetter(str) {
370
467
  return str.charAt(0).toUpperCase() + str.slice(1);
371
468
  }
372
- static getResponseJson(operationObject) {
469
+ static getResponseJson(operationObject, isTeamsAiProject = false) {
373
470
  var _a, _b;
374
471
  let json = {};
472
+ let multipleMediaType = false;
375
473
  for (const code of ConstantString.ResponseCodeFor20X) {
376
474
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
377
- const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
378
- if (mediaTypesCount > 1) {
379
- return {};
380
- }
381
475
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
476
+ multipleMediaType = false;
382
477
  json = responseObject.content["application/json"];
383
- break;
478
+ if (Utils.containMultipleMediaTypes(responseObject)) {
479
+ multipleMediaType = true;
480
+ if (isTeamsAiProject) {
481
+ break;
482
+ }
483
+ json = {};
484
+ }
485
+ else {
486
+ break;
487
+ }
384
488
  }
385
489
  }
386
- return json;
490
+ return { json, multipleMediaType };
387
491
  }
388
492
  static convertPathToCamelCase(path) {
389
493
  const pathSegments = path.split(/[./{]/);
@@ -403,10 +507,10 @@ class Utils {
403
507
  return undefined;
404
508
  }
405
509
  }
406
- static resolveServerUrl(url) {
510
+ static resolveEnv(str) {
407
511
  const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
408
- let matches = placeHolderReg.exec(url);
409
- let newUrl = url;
512
+ let matches = placeHolderReg.exec(str);
513
+ let newStr = str;
410
514
  while (matches != null) {
411
515
  const envVar = matches[1];
412
516
  const envVal = process.env[envVar];
@@ -414,17 +518,17 @@ class Utils {
414
518
  throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
415
519
  }
416
520
  else {
417
- newUrl = newUrl.replace(matches[0], envVal);
521
+ newStr = newStr.replace(matches[0], envVal);
418
522
  }
419
- matches = placeHolderReg.exec(url);
523
+ matches = placeHolderReg.exec(str);
420
524
  }
421
- return newUrl;
525
+ return newStr;
422
526
  }
423
527
  static checkServerUrl(servers) {
424
528
  const errors = [];
425
529
  let serverUrl;
426
530
  try {
427
- serverUrl = Utils.resolveServerUrl(servers[0].url);
531
+ serverUrl = Utils.resolveEnv(servers[0].url);
428
532
  }
429
533
  catch (err) {
430
534
  errors.push({
@@ -454,7 +558,8 @@ class Utils {
454
558
  }
455
559
  return errors;
456
560
  }
457
- static validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
561
+ static validateServer(spec, options) {
562
+ var _a;
458
563
  const errors = [];
459
564
  let hasTopLevelServers = false;
460
565
  let hasPathLevelServers = false;
@@ -475,7 +580,7 @@ class Utils {
475
580
  }
476
581
  for (const method in methods) {
477
582
  const operationObject = methods[method];
478
- 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) {
479
584
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
480
585
  hasOperationLevelServers = true;
481
586
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -518,6 +623,7 @@ class Utils {
518
623
  Utils.updateParameterWithInputType(schema, parameter);
519
624
  }
520
625
  if (isRequired && schema.default === undefined) {
626
+ parameter.isRequired = true;
521
627
  requiredParams.push(parameter);
522
628
  }
523
629
  else {
@@ -562,7 +668,7 @@ class Utils {
562
668
  param.value = schema.default;
563
669
  }
564
670
  }
565
- static parseApiInfo(operationItem, allowMultipleParameters) {
671
+ static parseApiInfo(operationItem, options) {
566
672
  var _a, _b;
567
673
  const requiredParams = [];
568
674
  const optionalParams = [];
@@ -576,11 +682,12 @@ class Utils {
576
682
  description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
577
683
  };
578
684
  const schema = param.schema;
579
- if (allowMultipleParameters && schema) {
685
+ if (options.allowMultipleParameters && schema) {
580
686
  Utils.updateParameterWithInputType(schema, parameter);
581
687
  }
582
688
  if (param.in !== "header" && param.in !== "cookie") {
583
689
  if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
690
+ parameter.isRequired = true;
584
691
  requiredParams.push(parameter);
585
692
  }
586
693
  else {
@@ -594,7 +701,7 @@ class Utils {
594
701
  const requestJson = requestBody.content["application/json"];
595
702
  if (Object.keys(requestJson).length !== 0) {
596
703
  const schema = requestJson.schema;
597
- const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
704
+ const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
598
705
  requiredParams.push(...requiredP);
599
706
  optionalParams.push(...optionalP);
600
707
  }
@@ -625,32 +732,37 @@ class Utils {
625
732
  }
626
733
  return [command, warning];
627
734
  }
628
- static listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
735
+ static listAPIs(spec, options) {
736
+ var _a;
629
737
  const paths = spec.paths;
630
738
  const result = {};
631
739
  for (const path in paths) {
632
740
  const methods = paths[path];
633
741
  for (const method in methods) {
634
- // For developer preview, only support GET operation with only 1 parameter without auth
635
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
636
- const operationObject = methods[method];
637
- result[`${method.toUpperCase()} ${path}`] = operationObject;
742
+ const operationObject = methods[method];
743
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
744
+ const validateResult = Utils.isSupportedApi(method, path, spec, options);
745
+ result[`${method.toUpperCase()} ${path}`] = {
746
+ operation: operationObject,
747
+ isValid: validateResult.isValid,
748
+ reason: validateResult.reason,
749
+ };
638
750
  }
639
751
  }
640
752
  }
641
753
  return result;
642
754
  }
643
- static validateSpec(spec, parser, isSwaggerFile, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
755
+ static validateSpec(spec, parser, isSwaggerFile, options) {
644
756
  const errors = [];
645
757
  const warnings = [];
758
+ const apiMap = Utils.listAPIs(spec, options);
646
759
  if (isSwaggerFile) {
647
760
  warnings.push({
648
761
  type: WarningType.ConvertSwaggerToOpenAPI,
649
762
  content: ConstantString.ConvertSwaggerToOpenAPI,
650
763
  });
651
764
  }
652
- // Server validation
653
- const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
765
+ const serverErrors = Utils.validateServer(spec, options);
654
766
  errors.push(...serverErrors);
655
767
  // Remote reference not supported
656
768
  const refPaths = parser.$refs.paths();
@@ -663,8 +775,8 @@ class Utils {
663
775
  });
664
776
  }
665
777
  // No supported API
666
- const apiMap = Utils.listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
667
- if (Object.keys(apiMap).length === 0) {
778
+ const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
779
+ if (validAPIs.length === 0) {
668
780
  errors.push({
669
781
  type: ErrorType.NoSupportedApi,
670
782
  content: ConstantString.NoSupportedApi,
@@ -673,8 +785,8 @@ class Utils {
673
785
  // OperationId missing
674
786
  const apisMissingOperationId = [];
675
787
  for (const key in apiMap) {
676
- const pathObjectItem = apiMap[key];
677
- if (!pathObjectItem.operationId) {
788
+ const { operation } = apiMap[key];
789
+ if (!operation.operationId) {
678
790
  apisMissingOperationId.push(key);
679
791
  }
680
792
  }
@@ -715,6 +827,19 @@ class Utils {
715
827
  }
716
828
  return safeRegistrationIdEnvName;
717
829
  }
830
+ static getAllAPICount(spec) {
831
+ let count = 0;
832
+ const paths = spec.paths;
833
+ for (const path in paths) {
834
+ const methods = paths[path];
835
+ for (const method in methods) {
836
+ if (ConstantString.AllOperationMethods.includes(method)) {
837
+ count++;
838
+ }
839
+ }
840
+ }
841
+ return count;
842
+ }
718
843
  }
719
844
 
720
845
  // Copyright (c) Microsoft Corporation.
@@ -733,7 +858,10 @@ class SpecParser {
733
858
  allowSwagger: false,
734
859
  allowAPIKeyAuth: false,
735
860
  allowMultipleParameters: false,
861
+ allowBearerTokenAuth: false,
736
862
  allowOauth2: false,
863
+ allowMethods: ["get", "post"],
864
+ projectType: ProjectType.SME,
737
865
  };
738
866
  this.pathOrSpec = pathOrDoc;
739
867
  this.parser = new SwaggerParser();
@@ -770,7 +898,7 @@ class SpecParser {
770
898
  ],
771
899
  };
772
900
  }
773
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
901
+ return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
774
902
  }
775
903
  catch (err) {
776
904
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -789,7 +917,7 @@ class SpecParser {
789
917
  if (!operationId) {
790
918
  continue;
791
919
  }
792
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options.allowMultipleParameters);
920
+ const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
793
921
  const apiInfo = {
794
922
  method: method,
795
923
  path: path,
@@ -818,12 +946,32 @@ class SpecParser {
818
946
  async list() {
819
947
  throw new Error("Method not implemented.");
820
948
  }
949
+ /**
950
+ * Generate specs according to the filters.
951
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
952
+ */
953
+ // eslint-disable-next-line @typescript-eslint/require-await
954
+ async getFilteredSpecs(filter, signal) {
955
+ throw new Error("Method not implemented.");
956
+ }
957
+ /**
958
+ * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
959
+ * @param manifestPath A file path of the Teams app manifest file to update.
960
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
961
+ * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
962
+ * @param pluginFilePath File path of the api plugin file to generate.
963
+ */
964
+ // eslint-disable-next-line @typescript-eslint/require-await
965
+ async generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
966
+ throw new Error("Method not implemented.");
967
+ }
821
968
  /**
822
969
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
823
970
  * @param manifestPath A file path of the Teams app manifest file to update.
824
971
  * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
825
972
  * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
826
973
  * @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
974
+ * @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
827
975
  */
828
976
  // eslint-disable-next-line @typescript-eslint/require-await
829
977
  async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
@@ -843,11 +991,187 @@ class SpecParser {
843
991
  if (this.apiMap !== undefined) {
844
992
  return this.apiMap;
845
993
  }
846
- const result = Utils.listSupportedAPIs(spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
994
+ const result = this.listSupportedAPIs(spec, this.options);
847
995
  this.apiMap = result;
848
996
  return result;
849
997
  }
998
+ listSupportedAPIs(spec, options) {
999
+ var _a;
1000
+ const paths = spec.paths;
1001
+ const result = {};
1002
+ for (const path in paths) {
1003
+ const methods = paths[path];
1004
+ for (const method in methods) {
1005
+ const operationObject = methods[method];
1006
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
1007
+ const validateResult = Utils.isSupportedApi(method, path, spec, options);
1008
+ if (validateResult.isValid) {
1009
+ result[`${method.toUpperCase()} ${path}`] = operationObject;
1010
+ }
1011
+ }
1012
+ }
1013
+ }
1014
+ return result;
1015
+ }
1016
+ }
1017
+
1018
+ // Copyright (c) Microsoft Corporation.
1019
+ class AdaptiveCardGenerator {
1020
+ static generateAdaptiveCard(operationItem) {
1021
+ try {
1022
+ const { json } = Utils.getResponseJson(operationItem);
1023
+ let cardBody = [];
1024
+ let schema = json.schema;
1025
+ let jsonPath = "$";
1026
+ if (schema && Object.keys(schema).length > 0) {
1027
+ jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
1028
+ if (jsonPath !== "$") {
1029
+ schema = schema.properties[jsonPath];
1030
+ }
1031
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1032
+ }
1033
+ // if no schema, try to use example value
1034
+ if (cardBody.length === 0 && (json.examples || json.example)) {
1035
+ cardBody = [
1036
+ {
1037
+ type: ConstantString.TextBlockType,
1038
+ text: "${jsonStringify($root)}",
1039
+ wrap: true,
1040
+ },
1041
+ ];
1042
+ }
1043
+ // if no example value, use default success response
1044
+ if (cardBody.length === 0) {
1045
+ cardBody = [
1046
+ {
1047
+ type: ConstantString.TextBlockType,
1048
+ text: "success",
1049
+ wrap: true,
1050
+ },
1051
+ ];
1052
+ }
1053
+ const fullCard = {
1054
+ type: ConstantString.AdaptiveCardType,
1055
+ $schema: ConstantString.AdaptiveCardSchema,
1056
+ version: ConstantString.AdaptiveCardVersion,
1057
+ body: cardBody,
1058
+ };
1059
+ return [fullCard, jsonPath];
1060
+ }
1061
+ catch (err) {
1062
+ throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
1063
+ }
1064
+ }
1065
+ static generateCardFromResponse(schema, name, parentArrayName = "") {
1066
+ if (schema.type === "array") {
1067
+ // schema.items can be arbitrary object: schema { type: array, items: {} }
1068
+ if (Object.keys(schema.items).length === 0) {
1069
+ return [
1070
+ {
1071
+ type: ConstantString.TextBlockType,
1072
+ text: name ? `${name}: \${jsonStringify(${name})}` : "result: ${jsonStringify($root)}",
1073
+ wrap: true,
1074
+ },
1075
+ ];
1076
+ }
1077
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1078
+ const template = {
1079
+ type: ConstantString.ContainerType,
1080
+ $data: name ? `\${${name}}` : "${$root}",
1081
+ items: Array(),
1082
+ };
1083
+ template.items.push(...obj);
1084
+ return [template];
1085
+ }
1086
+ // some schema may not contain type but contain properties
1087
+ if (schema.type === "object" || (!schema.type && schema.properties)) {
1088
+ const { properties } = schema;
1089
+ const result = [];
1090
+ for (const property in properties) {
1091
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1092
+ result.push(...obj);
1093
+ }
1094
+ if (schema.additionalProperties) {
1095
+ // TODO: better ways to handler warnings.
1096
+ console.warn(ConstantString.AdditionalPropertiesNotSupported);
1097
+ }
1098
+ return result;
1099
+ }
1100
+ if (schema.type === "string" ||
1101
+ schema.type === "integer" ||
1102
+ schema.type === "boolean" ||
1103
+ schema.type === "number") {
1104
+ if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1105
+ // string in root: "ddd"
1106
+ let text = "result: ${$root}";
1107
+ if (name) {
1108
+ // object { id: "1" }
1109
+ text = `${name}: \${if(${name}, ${name}, 'N/A')}`;
1110
+ if (parentArrayName) {
1111
+ // object types inside array: { tags: ["id": 1, "name": "name"] }
1112
+ text = `${parentArrayName}.${text}`;
1113
+ }
1114
+ }
1115
+ else if (parentArrayName) {
1116
+ // string array: photoUrls: ["1", "2"]
1117
+ text = `${parentArrayName}: ` + "${$data}";
1118
+ }
1119
+ return [
1120
+ {
1121
+ type: ConstantString.TextBlockType,
1122
+ text,
1123
+ wrap: true,
1124
+ },
1125
+ ];
1126
+ }
1127
+ else {
1128
+ if (name) {
1129
+ return [
1130
+ {
1131
+ type: "Image",
1132
+ url: `\${${name}}`,
1133
+ $when: `\${${name} != null}`,
1134
+ },
1135
+ ];
1136
+ }
1137
+ else {
1138
+ return [
1139
+ {
1140
+ type: "Image",
1141
+ url: "${$data}",
1142
+ $when: "${$data != null}",
1143
+ },
1144
+ ];
1145
+ }
1146
+ }
1147
+ }
1148
+ if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
1149
+ throw new Error(Utils.format(ConstantString.SchemaNotSupported, JSON.stringify(schema)));
1150
+ }
1151
+ throw new Error(Utils.format(ConstantString.UnknownSchema, JSON.stringify(schema)));
1152
+ }
1153
+ // Find the first array property in the response schema object with the well-known name
1154
+ static getResponseJsonPathFromSchema(schema) {
1155
+ if (schema.type === "object" || (!schema.type && schema.properties)) {
1156
+ const { properties } = schema;
1157
+ for (const property in properties) {
1158
+ const schema = properties[property];
1159
+ if (schema.type === "array" &&
1160
+ Utils.isWellKnownName(property, ConstantString.WellknownResultNames)) {
1161
+ return property;
1162
+ }
1163
+ }
1164
+ }
1165
+ return "$";
1166
+ }
1167
+ static isImageUrlProperty(schema, name, parentArrayName) {
1168
+ const propertyName = name ? name : parentArrayName;
1169
+ return (!!propertyName &&
1170
+ schema.type === "string" &&
1171
+ Utils.isWellKnownName(propertyName, ConstantString.WellknownImageName) &&
1172
+ (propertyName.toLocaleLowerCase().indexOf("url") >= 0 || schema.format === "uri"));
1173
+ }
850
1174
  }
851
1175
 
852
- export { ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
1176
+ export { AdaptiveCardGenerator, ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
853
1177
  //# sourceMappingURL=index.esm2017.js.map