@microsoft/m365-spec-parser 0.1.1-alpha.cd2ba87f2.0 → 0.1.1-alpha.e17ffd4d1.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,7 @@ 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
49
  ErrorType["ListFailed"] = "list-failed";
50
50
  ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
51
51
  ErrorType["FilterSpecFailed"] = "filter-spec-failed";
@@ -53,6 +53,7 @@ var ErrorType;
53
53
  ErrorType["GenerateAdaptiveCardFailed"] = "generate-adaptive-card-failed";
54
54
  ErrorType["GenerateFailed"] = "generate-failed";
55
55
  ErrorType["ValidateFailed"] = "validate-failed";
56
+ ErrorType["GetSpecFailed"] = "get-spec-failed";
56
57
  ErrorType["Cancelled"] = "cancelled";
57
58
  ErrorType["Unknown"] = "unknown";
58
59
  })(ErrorType || (ErrorType = {}));
@@ -75,7 +76,13 @@ var ValidationStatus;
75
76
  ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
76
77
  ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
77
78
  ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
78
- })(ValidationStatus || (ValidationStatus = {}));
79
+ })(ValidationStatus || (ValidationStatus = {}));
80
+ var ProjectType;
81
+ (function (ProjectType) {
82
+ ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
83
+ ProjectType[ProjectType["SME"] = 1] = "SME";
84
+ ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
85
+ })(ProjectType || (ProjectType = {}));
79
86
 
80
87
  // Copyright (c) Microsoft Corporation.
81
88
  class SpecParserError extends Error {
@@ -102,7 +109,8 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
102
109
  ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
103
110
  ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
104
111
  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.";
112
+ ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
113
+ ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
106
114
  ConstantString.WrappedCardVersion = "devPreview";
107
115
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
108
116
  ConstantString.WrappedCardResponseLayout = "list";
@@ -114,6 +122,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
114
122
  ConstantString.TextBlockType = "TextBlock";
115
123
  ConstantString.ContainerType = "Container";
116
124
  ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
125
+ ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
117
126
  ConstantString.ResponseCodeFor20X = [
118
127
  "200",
119
128
  "201",
@@ -173,11 +182,23 @@ ConstantString.FullDescriptionMaxLens = 4000;
173
182
  ConstantString.CommandDescriptionMaxLens = 128;
174
183
  ConstantString.ParameterDescriptionMaxLens = 128;
175
184
  ConstantString.CommandTitleMaxLens = 32;
176
- ConstantString.ParameterTitleMaxLens = 32;
185
+ ConstantString.ParameterTitleMaxLens = 32;
186
+ ConstantString.SMERequiredParamsMaxNum = 5;
177
187
 
178
188
  // Copyright (c) Microsoft Corporation.
179
189
  class Utils {
180
- static checkParameters(paramObject) {
190
+ static hasNestedObjectInSchema(schema) {
191
+ if (schema.type === "object") {
192
+ for (const property in schema.properties) {
193
+ const nestedSchema = schema.properties[property];
194
+ if (nestedSchema.type === "object") {
195
+ return true;
196
+ }
197
+ }
198
+ }
199
+ return false;
200
+ }
201
+ static checkParameters(paramObject, isCopilot) {
181
202
  const paramResult = {
182
203
  requiredNum: 0,
183
204
  optionalNum: 0,
@@ -189,7 +210,20 @@ class Utils {
189
210
  for (let i = 0; i < paramObject.length; i++) {
190
211
  const param = paramObject[i];
191
212
  const schema = param.schema;
213
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
214
+ paramResult.isValid = false;
215
+ continue;
216
+ }
192
217
  const isRequiredWithoutDefault = param.required && schema.default === undefined;
218
+ if (isCopilot) {
219
+ if (isRequiredWithoutDefault) {
220
+ paramResult.requiredNum = paramResult.requiredNum + 1;
221
+ }
222
+ else {
223
+ paramResult.optionalNum = paramResult.optionalNum + 1;
224
+ }
225
+ continue;
226
+ }
193
227
  if (param.in === "header" || param.in === "cookie") {
194
228
  if (isRequiredWithoutDefault) {
195
229
  paramResult.isValid = false;
@@ -216,7 +250,7 @@ class Utils {
216
250
  }
217
251
  return paramResult;
218
252
  }
219
- static checkPostBody(schema, isRequired = false) {
253
+ static checkPostBody(schema, isRequired = false, isCopilot = false) {
220
254
  var _a;
221
255
  const paramResult = {
222
256
  requiredNum: 0,
@@ -227,6 +261,10 @@ class Utils {
227
261
  return paramResult;
228
262
  }
229
263
  const isRequiredWithoutDefault = isRequired && schema.default === undefined;
264
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
265
+ paramResult.isValid = false;
266
+ return paramResult;
267
+ }
230
268
  if (schema.type === "string" ||
231
269
  schema.type === "integer" ||
232
270
  schema.type === "boolean" ||
@@ -245,19 +283,22 @@ class Utils {
245
283
  if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
246
284
  isRequired = true;
247
285
  }
248
- const result = Utils.checkPostBody(properties[property], isRequired);
286
+ const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
249
287
  paramResult.requiredNum += result.requiredNum;
250
288
  paramResult.optionalNum += result.optionalNum;
251
289
  paramResult.isValid = paramResult.isValid && result.isValid;
252
290
  }
253
291
  }
254
292
  else {
255
- if (isRequiredWithoutDefault) {
293
+ if (isRequiredWithoutDefault && !isCopilot) {
256
294
  paramResult.isValid = false;
257
295
  }
258
296
  }
259
297
  return paramResult;
260
298
  }
299
+ static containMultipleMediaTypes(bodyObject) {
300
+ return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
301
+ }
261
302
  /**
262
303
  * Checks if the given API is supported.
263
304
  * @param {string} method - The HTTP method of the API.
@@ -272,32 +313,40 @@ class Utils {
272
313
  * 5. response body should be “application/json” and not empty, and response code should be 20X
273
314
  * 6. only support request body with “application/json” content type
274
315
  */
275
- static isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
316
+ static isSupportedApi(method, path, spec, options) {
317
+ var _a;
276
318
  const pathObj = spec.paths[path];
277
319
  method = method.toLocaleLowerCase();
278
320
  if (pathObj) {
279
- if ((method === ConstantString.PostMethod || method === ConstantString.GetMethod) &&
280
- pathObj[method]) {
321
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
281
322
  const securities = pathObj[method].security;
282
- const authArray = Utils.getAuthArray(securities, spec);
283
- if (!Utils.isSupportedAuth(authArray, allowAPIKeyAuth, allowOauth2)) {
284
- return false;
323
+ const isTeamsAi = options.projectType === ProjectType.TeamsAi;
324
+ const isCopilot = options.projectType === ProjectType.Copilot;
325
+ // Teams AI project doesn't care about auth, it will use authProvider for user to implement
326
+ if (!isTeamsAi) {
327
+ const authArray = Utils.getAuthArray(securities, spec);
328
+ if (!Utils.isSupportedAuth(authArray, options)) {
329
+ return false;
330
+ }
285
331
  }
286
332
  const operationObject = pathObj[method];
287
- if (!allowMissingId && !operationObject.operationId) {
333
+ if (!options.allowMissingId && !operationObject.operationId) {
288
334
  return false;
289
335
  }
290
336
  const paramObject = operationObject.parameters;
291
337
  const requestBody = operationObject.requestBody;
292
338
  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) {
339
+ if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
295
340
  return false;
296
341
  }
297
- const responseJson = Utils.getResponseJson(operationObject);
342
+ const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
298
343
  if (Object.keys(responseJson).length === 0) {
299
344
  return false;
300
345
  }
346
+ // Teams AI project doesn't care about request parameters/body
347
+ if (isTeamsAi) {
348
+ return true;
349
+ }
301
350
  let requestBodyParamResult = {
302
351
  requiredNum: 0,
303
352
  optionalNum: 0,
@@ -305,18 +354,26 @@ class Utils {
305
354
  };
306
355
  if (requestJsonBody) {
307
356
  const requestBodySchema = requestJsonBody.schema;
308
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required);
357
+ if (isCopilot && requestBodySchema.type !== "object") {
358
+ return false;
359
+ }
360
+ requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
309
361
  }
310
362
  if (!requestBodyParamResult.isValid) {
311
363
  return false;
312
364
  }
313
- const paramResult = Utils.checkParameters(paramObject);
365
+ const paramResult = Utils.checkParameters(paramObject, isCopilot);
314
366
  if (!paramResult.isValid) {
315
367
  return false;
316
368
  }
369
+ // Copilot support arbitrary parameters
370
+ if (isCopilot) {
371
+ return true;
372
+ }
317
373
  if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
318
- if (allowMultipleParameters &&
319
- requestBodyParamResult.requiredNum + paramResult.requiredNum <= 5) {
374
+ if (options.allowMultipleParameters &&
375
+ requestBodyParamResult.requiredNum + paramResult.requiredNum <=
376
+ ConstantString.SMERequiredParamsMaxNum) {
320
377
  return true;
321
378
  }
322
379
  return false;
@@ -335,29 +392,31 @@ class Utils {
335
392
  }
336
393
  return false;
337
394
  }
338
- static isSupportedAuth(authSchemaArray, allowAPIKeyAuth, allowOauth2) {
395
+ static isSupportedAuth(authSchemaArray, options) {
339
396
  if (authSchemaArray.length === 0) {
340
397
  return true;
341
398
  }
342
- if (allowAPIKeyAuth || allowOauth2) {
399
+ if (options.allowAPIKeyAuth || options.allowOauth2) {
343
400
  // Currently we don't support multiple auth in one operation
344
401
  if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
345
402
  return false;
346
403
  }
347
404
  for (const auths of authSchemaArray) {
348
405
  if (auths.length === 1) {
349
- if (!allowOauth2 && allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authSchema)) {
406
+ if (!options.allowOauth2 &&
407
+ options.allowAPIKeyAuth &&
408
+ Utils.isAPIKeyAuth(auths[0].authSchema)) {
350
409
  return true;
351
410
  }
352
- else if (!allowAPIKeyAuth &&
353
- allowOauth2 &&
354
- Utils.isBearerTokenAuth(auths[0].authSchema)) {
411
+ else if (!options.allowAPIKeyAuth &&
412
+ options.allowOauth2 &&
413
+ Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema)) {
355
414
  return true;
356
415
  }
357
- else if (allowAPIKeyAuth &&
358
- allowOauth2 &&
416
+ else if (options.allowAPIKeyAuth &&
417
+ options.allowOauth2 &&
359
418
  (Utils.isAPIKeyAuth(auths[0].authSchema) ||
360
- Utils.isBearerTokenAuth(auths[0].authSchema))) {
419
+ Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema))) {
361
420
  return true;
362
421
  }
363
422
  }
@@ -368,10 +427,11 @@ class Utils {
368
427
  static isAPIKeyAuth(authSchema) {
369
428
  return authSchema.type === "apiKey";
370
429
  }
371
- static isBearerTokenAuth(authSchema) {
372
- return (authSchema.type === "oauth2" ||
373
- authSchema.type === "openIdConnect" ||
374
- (authSchema.type === "http" && authSchema.scheme === "bearer"));
430
+ static isOAuthWithAuthCodeFlow(authSchema) {
431
+ if (authSchema.type === "oauth2" && authSchema.flows && authSchema.flows.authorizationCode) {
432
+ return true;
433
+ }
434
+ return false;
375
435
  }
376
436
  static getAuthArray(securities, spec) {
377
437
  var _a;
@@ -399,18 +459,19 @@ class Utils {
399
459
  static updateFirstLetter(str) {
400
460
  return str.charAt(0).toUpperCase() + str.slice(1);
401
461
  }
402
- static getResponseJson(operationObject) {
462
+ static getResponseJson(operationObject, isTeamsAiProject = false) {
403
463
  var _a, _b;
404
464
  let json = {};
405
465
  for (const code of ConstantString.ResponseCodeFor20X) {
406
466
  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
467
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
412
468
  json = responseObject.content["application/json"];
413
- break;
469
+ if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
470
+ json = {};
471
+ }
472
+ else {
473
+ break;
474
+ }
414
475
  }
415
476
  }
416
477
  return json;
@@ -484,7 +545,7 @@ class Utils {
484
545
  }
485
546
  return errors;
486
547
  }
487
- static validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
548
+ static validateServer(spec, options) {
488
549
  const errors = [];
489
550
  let hasTopLevelServers = false;
490
551
  let hasPathLevelServers = false;
@@ -505,7 +566,7 @@ class Utils {
505
566
  }
506
567
  for (const method in methods) {
507
568
  const operationObject = methods[method];
508
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
569
+ if (Utils.isSupportedApi(method, path, spec, options)) {
509
570
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
510
571
  hasOperationLevelServers = true;
511
572
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -592,7 +653,7 @@ class Utils {
592
653
  param.value = schema.default;
593
654
  }
594
655
  }
595
- static parseApiInfo(operationItem, allowMultipleParameters) {
656
+ static parseApiInfo(operationItem, options) {
596
657
  var _a, _b;
597
658
  const requiredParams = [];
598
659
  const optionalParams = [];
@@ -606,7 +667,7 @@ class Utils {
606
667
  description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
607
668
  };
608
669
  const schema = param.schema;
609
- if (allowMultipleParameters && schema) {
670
+ if (options.allowMultipleParameters && schema) {
610
671
  Utils.updateParameterWithInputType(schema, parameter);
611
672
  }
612
673
  if (param.in !== "header" && param.in !== "cookie") {
@@ -624,7 +685,7 @@ class Utils {
624
685
  const requestJson = requestBody.content["application/json"];
625
686
  if (Object.keys(requestJson).length !== 0) {
626
687
  const schema = requestJson.schema;
627
- const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
688
+ const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
628
689
  requiredParams.push(...requiredP);
629
690
  optionalParams.push(...optionalP);
630
691
  }
@@ -655,14 +716,13 @@ class Utils {
655
716
  }
656
717
  return [command, warning];
657
718
  }
658
- static listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
719
+ static listSupportedAPIs(spec, options) {
659
720
  const paths = spec.paths;
660
721
  const result = {};
661
722
  for (const path in paths) {
662
723
  const methods = paths[path];
663
724
  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)) {
725
+ if (Utils.isSupportedApi(method, path, spec, options)) {
666
726
  const operationObject = methods[method];
667
727
  result[`${method.toUpperCase()} ${path}`] = operationObject;
668
728
  }
@@ -670,7 +730,7 @@ class Utils {
670
730
  }
671
731
  return result;
672
732
  }
673
- static validateSpec(spec, parser, isSwaggerFile, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
733
+ static validateSpec(spec, parser, isSwaggerFile, options) {
674
734
  const errors = [];
675
735
  const warnings = [];
676
736
  if (isSwaggerFile) {
@@ -680,7 +740,7 @@ class Utils {
680
740
  });
681
741
  }
682
742
  // Server validation
683
- const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
743
+ const serverErrors = Utils.validateServer(spec, options);
684
744
  errors.push(...serverErrors);
685
745
  // Remote reference not supported
686
746
  const refPaths = parser.$refs.paths();
@@ -693,7 +753,7 @@ class Utils {
693
753
  });
694
754
  }
695
755
  // No supported API
696
- const apiMap = Utils.listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
756
+ const apiMap = Utils.listSupportedAPIs(spec, options);
697
757
  if (Object.keys(apiMap).length === 0) {
698
758
  errors.push({
699
759
  type: ErrorType.NoSupportedApi,
@@ -764,6 +824,8 @@ class SpecParser {
764
824
  allowAPIKeyAuth: false,
765
825
  allowMultipleParameters: false,
766
826
  allowOauth2: false,
827
+ allowMethods: ["get", "post"],
828
+ projectType: ProjectType.SME,
767
829
  };
768
830
  this.pathOrSpec = pathOrDoc;
769
831
  this.parser = new SwaggerParser();
@@ -801,7 +863,7 @@ class SpecParser {
801
863
  ],
802
864
  };
803
865
  }
804
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
866
+ return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
805
867
  }
806
868
  catch (err) {
807
869
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -822,7 +884,7 @@ class SpecParser {
822
884
  if (!operationId) {
823
885
  continue;
824
886
  }
825
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options.allowMultipleParameters);
887
+ const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
826
888
  const apiInfo = {
827
889
  method: method,
828
890
  path: path,
@@ -854,12 +916,36 @@ class SpecParser {
854
916
  throw new Error("Method not implemented.");
855
917
  });
856
918
  }
919
+ /**
920
+ * Generate specs according to the filters.
921
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
922
+ */
923
+ // eslint-disable-next-line @typescript-eslint/require-await
924
+ getFilteredSpecs(filter, signal) {
925
+ return __awaiter(this, void 0, void 0, function* () {
926
+ throw new Error("Method not implemented.");
927
+ });
928
+ }
929
+ /**
930
+ * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
931
+ * @param manifestPath A file path of the Teams app manifest file to update.
932
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
933
+ * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
934
+ * @param pluginFilePath File path of the api plugin file to generate.
935
+ */
936
+ // eslint-disable-next-line @typescript-eslint/require-await
937
+ generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
938
+ return __awaiter(this, void 0, void 0, function* () {
939
+ throw new Error("Method not implemented.");
940
+ });
941
+ }
857
942
  /**
858
943
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
859
944
  * @param manifestPath A file path of the Teams app manifest file to update.
860
945
  * @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
946
  * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
862
947
  * @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
948
+ * @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
863
949
  */
864
950
  // eslint-disable-next-line @typescript-eslint/require-await
865
951
  generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
@@ -883,11 +969,169 @@ class SpecParser {
883
969
  if (this.apiMap !== undefined) {
884
970
  return this.apiMap;
885
971
  }
886
- const result = Utils.listSupportedAPIs(spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
972
+ const result = Utils.listSupportedAPIs(spec, this.options);
887
973
  this.apiMap = result;
888
974
  return result;
889
975
  }
890
976
  }
891
977
 
892
- export { ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
978
+ // Copyright (c) Microsoft Corporation.
979
+ class AdaptiveCardGenerator {
980
+ static generateAdaptiveCard(operationItem) {
981
+ try {
982
+ const json = Utils.getResponseJson(operationItem);
983
+ let cardBody = [];
984
+ let schema = json.schema;
985
+ let jsonPath = "$";
986
+ if (schema && Object.keys(schema).length > 0) {
987
+ jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
988
+ if (jsonPath !== "$") {
989
+ schema = schema.properties[jsonPath];
990
+ }
991
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
992
+ }
993
+ // if no schema, try to use example value
994
+ if (cardBody.length === 0 && (json.examples || json.example)) {
995
+ cardBody = [
996
+ {
997
+ type: ConstantString.TextBlockType,
998
+ text: "${jsonStringify($root)}",
999
+ wrap: true,
1000
+ },
1001
+ ];
1002
+ }
1003
+ // if no example value, use default success response
1004
+ if (cardBody.length === 0) {
1005
+ cardBody = [
1006
+ {
1007
+ type: ConstantString.TextBlockType,
1008
+ text: "success",
1009
+ wrap: true,
1010
+ },
1011
+ ];
1012
+ }
1013
+ const fullCard = {
1014
+ type: ConstantString.AdaptiveCardType,
1015
+ $schema: ConstantString.AdaptiveCardSchema,
1016
+ version: ConstantString.AdaptiveCardVersion,
1017
+ body: cardBody,
1018
+ };
1019
+ return [fullCard, jsonPath];
1020
+ }
1021
+ catch (err) {
1022
+ throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
1023
+ }
1024
+ }
1025
+ static generateCardFromResponse(schema, name, parentArrayName = "") {
1026
+ if (schema.type === "array") {
1027
+ // schema.items can be arbitrary object: schema { type: array, items: {} }
1028
+ if (Object.keys(schema.items).length === 0) {
1029
+ return [
1030
+ {
1031
+ type: ConstantString.TextBlockType,
1032
+ text: name ? `${name}: \${jsonStringify(${name})}` : "result: ${jsonStringify($root)}",
1033
+ wrap: true,
1034
+ },
1035
+ ];
1036
+ }
1037
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1038
+ const template = {
1039
+ type: ConstantString.ContainerType,
1040
+ $data: name ? `\${${name}}` : "${$root}",
1041
+ items: Array(),
1042
+ };
1043
+ template.items.push(...obj);
1044
+ return [template];
1045
+ }
1046
+ // some schema may not contain type but contain properties
1047
+ if (schema.type === "object" || (!schema.type && schema.properties)) {
1048
+ const { properties } = schema;
1049
+ const result = [];
1050
+ for (const property in properties) {
1051
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1052
+ result.push(...obj);
1053
+ }
1054
+ if (schema.additionalProperties) {
1055
+ // TODO: better ways to handler warnings.
1056
+ console.warn(ConstantString.AdditionalPropertiesNotSupported);
1057
+ }
1058
+ return result;
1059
+ }
1060
+ if (schema.type === "string" ||
1061
+ schema.type === "integer" ||
1062
+ schema.type === "boolean" ||
1063
+ schema.type === "number") {
1064
+ if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1065
+ // string in root: "ddd"
1066
+ let text = "result: ${$root}";
1067
+ if (name) {
1068
+ // object { id: "1" }
1069
+ text = `${name}: \${if(${name}, ${name}, 'N/A')}`;
1070
+ if (parentArrayName) {
1071
+ // object types inside array: { tags: ["id": 1, "name": "name"] }
1072
+ text = `${parentArrayName}.${text}`;
1073
+ }
1074
+ }
1075
+ else if (parentArrayName) {
1076
+ // string array: photoUrls: ["1", "2"]
1077
+ text = `${parentArrayName}: ` + "${$data}";
1078
+ }
1079
+ return [
1080
+ {
1081
+ type: ConstantString.TextBlockType,
1082
+ text,
1083
+ wrap: true,
1084
+ },
1085
+ ];
1086
+ }
1087
+ else {
1088
+ if (name) {
1089
+ return [
1090
+ {
1091
+ type: "Image",
1092
+ url: `\${${name}}`,
1093
+ $when: `\${${name} != null}`,
1094
+ },
1095
+ ];
1096
+ }
1097
+ else {
1098
+ return [
1099
+ {
1100
+ type: "Image",
1101
+ url: "${$data}",
1102
+ $when: "${$data != null}",
1103
+ },
1104
+ ];
1105
+ }
1106
+ }
1107
+ }
1108
+ if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
1109
+ throw new Error(Utils.format(ConstantString.SchemaNotSupported, JSON.stringify(schema)));
1110
+ }
1111
+ throw new Error(Utils.format(ConstantString.UnknownSchema, JSON.stringify(schema)));
1112
+ }
1113
+ // Find the first array property in the response schema object with the well-known name
1114
+ static getResponseJsonPathFromSchema(schema) {
1115
+ if (schema.type === "object" || (!schema.type && schema.properties)) {
1116
+ const { properties } = schema;
1117
+ for (const property in properties) {
1118
+ const schema = properties[property];
1119
+ if (schema.type === "array" &&
1120
+ Utils.isWellKnownName(property, ConstantString.WellknownResultNames)) {
1121
+ return property;
1122
+ }
1123
+ }
1124
+ }
1125
+ return "$";
1126
+ }
1127
+ static isImageUrlProperty(schema, name, parentArrayName) {
1128
+ const propertyName = name ? name : parentArrayName;
1129
+ return (!!propertyName &&
1130
+ schema.type === "string" &&
1131
+ Utils.isWellKnownName(propertyName, ConstantString.WellknownImageName) &&
1132
+ (propertyName.toLocaleLowerCase().indexOf("url") >= 0 || schema.format === "uri"));
1133
+ }
1134
+ }
1135
+
1136
+ export { AdaptiveCardGenerator, ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
893
1137
  //# sourceMappingURL=index.esm5.js.map