@microsoft/m365-spec-parser 0.1.1-alpha.78701ec6a.0 → 0.1.1-alpha.a372ccf67.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,7 @@ 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
19
  ErrorType["ListFailed"] = "list-failed";
20
20
  ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
21
21
  ErrorType["FilterSpecFailed"] = "filter-spec-failed";
@@ -23,6 +23,7 @@ var ErrorType;
23
23
  ErrorType["GenerateAdaptiveCardFailed"] = "generate-adaptive-card-failed";
24
24
  ErrorType["GenerateFailed"] = "generate-failed";
25
25
  ErrorType["ValidateFailed"] = "validate-failed";
26
+ ErrorType["GetSpecFailed"] = "get-spec-failed";
26
27
  ErrorType["Cancelled"] = "cancelled";
27
28
  ErrorType["Unknown"] = "unknown";
28
29
  })(ErrorType || (ErrorType = {}));
@@ -45,7 +46,13 @@ var ValidationStatus;
45
46
  ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
46
47
  ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
47
48
  ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
48
- })(ValidationStatus || (ValidationStatus = {}));
49
+ })(ValidationStatus || (ValidationStatus = {}));
50
+ var ProjectType;
51
+ (function (ProjectType) {
52
+ ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
53
+ ProjectType[ProjectType["SME"] = 1] = "SME";
54
+ ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
55
+ })(ProjectType || (ProjectType = {}));
49
56
 
50
57
  // Copyright (c) Microsoft Corporation.
51
58
  class SpecParserError extends Error {
@@ -72,7 +79,8 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
72
79
  ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
73
80
  ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
74
81
  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.";
82
+ ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
83
+ ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
76
84
  ConstantString.WrappedCardVersion = "devPreview";
77
85
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
78
86
  ConstantString.WrappedCardResponseLayout = "list";
@@ -84,6 +92,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
84
92
  ConstantString.TextBlockType = "TextBlock";
85
93
  ConstantString.ContainerType = "Container";
86
94
  ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
95
+ ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
87
96
  ConstantString.ResponseCodeFor20X = [
88
97
  "200",
89
98
  "201",
@@ -143,11 +152,23 @@ ConstantString.FullDescriptionMaxLens = 4000;
143
152
  ConstantString.CommandDescriptionMaxLens = 128;
144
153
  ConstantString.ParameterDescriptionMaxLens = 128;
145
154
  ConstantString.CommandTitleMaxLens = 32;
146
- ConstantString.ParameterTitleMaxLens = 32;
155
+ ConstantString.ParameterTitleMaxLens = 32;
156
+ ConstantString.SMERequiredParamsMaxNum = 5;
147
157
 
148
158
  // Copyright (c) Microsoft Corporation.
149
159
  class Utils {
150
- static checkParameters(paramObject) {
160
+ static hasNestedObjectInSchema(schema) {
161
+ if (schema.type === "object") {
162
+ for (const property in schema.properties) {
163
+ const nestedSchema = schema.properties[property];
164
+ if (nestedSchema.type === "object") {
165
+ return true;
166
+ }
167
+ }
168
+ }
169
+ return false;
170
+ }
171
+ static checkParameters(paramObject, isCopilot) {
151
172
  const paramResult = {
152
173
  requiredNum: 0,
153
174
  optionalNum: 0,
@@ -159,7 +180,20 @@ class Utils {
159
180
  for (let i = 0; i < paramObject.length; i++) {
160
181
  const param = paramObject[i];
161
182
  const schema = param.schema;
183
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
184
+ paramResult.isValid = false;
185
+ continue;
186
+ }
162
187
  const isRequiredWithoutDefault = param.required && schema.default === undefined;
188
+ if (isCopilot) {
189
+ if (isRequiredWithoutDefault) {
190
+ paramResult.requiredNum = paramResult.requiredNum + 1;
191
+ }
192
+ else {
193
+ paramResult.optionalNum = paramResult.optionalNum + 1;
194
+ }
195
+ continue;
196
+ }
163
197
  if (param.in === "header" || param.in === "cookie") {
164
198
  if (isRequiredWithoutDefault) {
165
199
  paramResult.isValid = false;
@@ -186,7 +220,7 @@ class Utils {
186
220
  }
187
221
  return paramResult;
188
222
  }
189
- static checkPostBody(schema, isRequired = false) {
223
+ static checkPostBody(schema, isRequired = false, isCopilot = false) {
190
224
  var _a;
191
225
  const paramResult = {
192
226
  requiredNum: 0,
@@ -197,6 +231,10 @@ class Utils {
197
231
  return paramResult;
198
232
  }
199
233
  const isRequiredWithoutDefault = isRequired && schema.default === undefined;
234
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
235
+ paramResult.isValid = false;
236
+ return paramResult;
237
+ }
200
238
  if (schema.type === "string" ||
201
239
  schema.type === "integer" ||
202
240
  schema.type === "boolean" ||
@@ -215,19 +253,22 @@ class Utils {
215
253
  if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
216
254
  isRequired = true;
217
255
  }
218
- const result = Utils.checkPostBody(properties[property], isRequired);
256
+ const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
219
257
  paramResult.requiredNum += result.requiredNum;
220
258
  paramResult.optionalNum += result.optionalNum;
221
259
  paramResult.isValid = paramResult.isValid && result.isValid;
222
260
  }
223
261
  }
224
262
  else {
225
- if (isRequiredWithoutDefault) {
263
+ if (isRequiredWithoutDefault && !isCopilot) {
226
264
  paramResult.isValid = false;
227
265
  }
228
266
  }
229
267
  return paramResult;
230
268
  }
269
+ static containMultipleMediaTypes(bodyObject) {
270
+ return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
271
+ }
231
272
  /**
232
273
  * Checks if the given API is supported.
233
274
  * @param {string} method - The HTTP method of the API.
@@ -242,32 +283,40 @@ class Utils {
242
283
  * 5. response body should be “application/json” and not empty, and response code should be 20X
243
284
  * 6. only support request body with “application/json” content type
244
285
  */
245
- static isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
286
+ static isSupportedApi(method, path, spec, options) {
287
+ var _a;
246
288
  const pathObj = spec.paths[path];
247
289
  method = method.toLocaleLowerCase();
248
290
  if (pathObj) {
249
- if ((method === ConstantString.PostMethod || method === ConstantString.GetMethod) &&
250
- pathObj[method]) {
291
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
251
292
  const securities = pathObj[method].security;
252
- const authArray = Utils.getAuthArray(securities, spec);
253
- if (!Utils.isSupportedAuth(authArray, allowAPIKeyAuth, allowOauth2)) {
254
- return false;
293
+ const isTeamsAi = options.projectType === ProjectType.TeamsAi;
294
+ const isCopilot = options.projectType === ProjectType.Copilot;
295
+ // Teams AI project doesn't care about auth, it will use authProvider for user to implement
296
+ if (!isTeamsAi) {
297
+ const authArray = Utils.getAuthArray(securities, spec);
298
+ if (!Utils.isSupportedAuth(authArray, options)) {
299
+ return false;
300
+ }
255
301
  }
256
302
  const operationObject = pathObj[method];
257
- if (!allowMissingId && !operationObject.operationId) {
303
+ if (!options.allowMissingId && !operationObject.operationId) {
258
304
  return false;
259
305
  }
260
306
  const paramObject = operationObject.parameters;
261
307
  const requestBody = operationObject.requestBody;
262
308
  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) {
309
+ if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
265
310
  return false;
266
311
  }
267
- const responseJson = Utils.getResponseJson(operationObject);
312
+ const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
268
313
  if (Object.keys(responseJson).length === 0) {
269
314
  return false;
270
315
  }
316
+ // Teams AI project doesn't care about request parameters/body
317
+ if (isTeamsAi) {
318
+ return true;
319
+ }
271
320
  let requestBodyParamResult = {
272
321
  requiredNum: 0,
273
322
  optionalNum: 0,
@@ -275,18 +324,26 @@ class Utils {
275
324
  };
276
325
  if (requestJsonBody) {
277
326
  const requestBodySchema = requestJsonBody.schema;
278
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required);
327
+ if (isCopilot && requestBodySchema.type !== "object") {
328
+ return false;
329
+ }
330
+ requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
279
331
  }
280
332
  if (!requestBodyParamResult.isValid) {
281
333
  return false;
282
334
  }
283
- const paramResult = Utils.checkParameters(paramObject);
335
+ const paramResult = Utils.checkParameters(paramObject, isCopilot);
284
336
  if (!paramResult.isValid) {
285
337
  return false;
286
338
  }
339
+ // Copilot support arbitrary parameters
340
+ if (isCopilot) {
341
+ return true;
342
+ }
287
343
  if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
288
- if (allowMultipleParameters &&
289
- requestBodyParamResult.requiredNum + paramResult.requiredNum <= 5) {
344
+ if (options.allowMultipleParameters &&
345
+ requestBodyParamResult.requiredNum + paramResult.requiredNum <=
346
+ ConstantString.SMERequiredParamsMaxNum) {
290
347
  return true;
291
348
  }
292
349
  return false;
@@ -305,29 +362,31 @@ class Utils {
305
362
  }
306
363
  return false;
307
364
  }
308
- static isSupportedAuth(authSchemaArray, allowAPIKeyAuth, allowOauth2) {
365
+ static isSupportedAuth(authSchemaArray, options) {
309
366
  if (authSchemaArray.length === 0) {
310
367
  return true;
311
368
  }
312
- if (allowAPIKeyAuth || allowOauth2) {
369
+ if (options.allowAPIKeyAuth || options.allowOauth2) {
313
370
  // Currently we don't support multiple auth in one operation
314
371
  if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
315
372
  return false;
316
373
  }
317
374
  for (const auths of authSchemaArray) {
318
375
  if (auths.length === 1) {
319
- if (!allowOauth2 && allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authSchema)) {
376
+ if (!options.allowOauth2 &&
377
+ options.allowAPIKeyAuth &&
378
+ Utils.isAPIKeyAuth(auths[0].authSchema)) {
320
379
  return true;
321
380
  }
322
- else if (!allowAPIKeyAuth &&
323
- allowOauth2 &&
324
- Utils.isBearerTokenAuth(auths[0].authSchema)) {
381
+ else if (!options.allowAPIKeyAuth &&
382
+ options.allowOauth2 &&
383
+ Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema)) {
325
384
  return true;
326
385
  }
327
- else if (allowAPIKeyAuth &&
328
- allowOauth2 &&
386
+ else if (options.allowAPIKeyAuth &&
387
+ options.allowOauth2 &&
329
388
  (Utils.isAPIKeyAuth(auths[0].authSchema) ||
330
- Utils.isBearerTokenAuth(auths[0].authSchema))) {
389
+ Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema))) {
331
390
  return true;
332
391
  }
333
392
  }
@@ -338,10 +397,11 @@ class Utils {
338
397
  static isAPIKeyAuth(authSchema) {
339
398
  return authSchema.type === "apiKey";
340
399
  }
341
- static isBearerTokenAuth(authSchema) {
342
- return (authSchema.type === "oauth2" ||
343
- authSchema.type === "openIdConnect" ||
344
- (authSchema.type === "http" && authSchema.scheme === "bearer"));
400
+ static isOAuthWithAuthCodeFlow(authSchema) {
401
+ if (authSchema.type === "oauth2" && authSchema.flows && authSchema.flows.authorizationCode) {
402
+ return true;
403
+ }
404
+ return false;
345
405
  }
346
406
  static getAuthArray(securities, spec) {
347
407
  var _a;
@@ -369,18 +429,19 @@ class Utils {
369
429
  static updateFirstLetter(str) {
370
430
  return str.charAt(0).toUpperCase() + str.slice(1);
371
431
  }
372
- static getResponseJson(operationObject) {
432
+ static getResponseJson(operationObject, isTeamsAiProject = false) {
373
433
  var _a, _b;
374
434
  let json = {};
375
435
  for (const code of ConstantString.ResponseCodeFor20X) {
376
436
  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
437
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
382
438
  json = responseObject.content["application/json"];
383
- break;
439
+ if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
440
+ json = {};
441
+ }
442
+ else {
443
+ break;
444
+ }
384
445
  }
385
446
  }
386
447
  return json;
@@ -454,7 +515,7 @@ class Utils {
454
515
  }
455
516
  return errors;
456
517
  }
457
- static validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
518
+ static validateServer(spec, options) {
458
519
  const errors = [];
459
520
  let hasTopLevelServers = false;
460
521
  let hasPathLevelServers = false;
@@ -475,7 +536,7 @@ class Utils {
475
536
  }
476
537
  for (const method in methods) {
477
538
  const operationObject = methods[method];
478
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
539
+ if (Utils.isSupportedApi(method, path, spec, options)) {
479
540
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
480
541
  hasOperationLevelServers = true;
481
542
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -562,7 +623,7 @@ class Utils {
562
623
  param.value = schema.default;
563
624
  }
564
625
  }
565
- static parseApiInfo(operationItem, allowMultipleParameters) {
626
+ static parseApiInfo(operationItem, options) {
566
627
  var _a, _b;
567
628
  const requiredParams = [];
568
629
  const optionalParams = [];
@@ -576,7 +637,7 @@ class Utils {
576
637
  description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
577
638
  };
578
639
  const schema = param.schema;
579
- if (allowMultipleParameters && schema) {
640
+ if (options.allowMultipleParameters && schema) {
580
641
  Utils.updateParameterWithInputType(schema, parameter);
581
642
  }
582
643
  if (param.in !== "header" && param.in !== "cookie") {
@@ -594,7 +655,7 @@ class Utils {
594
655
  const requestJson = requestBody.content["application/json"];
595
656
  if (Object.keys(requestJson).length !== 0) {
596
657
  const schema = requestJson.schema;
597
- const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
658
+ const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
598
659
  requiredParams.push(...requiredP);
599
660
  optionalParams.push(...optionalP);
600
661
  }
@@ -625,14 +686,13 @@ class Utils {
625
686
  }
626
687
  return [command, warning];
627
688
  }
628
- static listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
689
+ static listSupportedAPIs(spec, options) {
629
690
  const paths = spec.paths;
630
691
  const result = {};
631
692
  for (const path in paths) {
632
693
  const methods = paths[path];
633
694
  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)) {
695
+ if (Utils.isSupportedApi(method, path, spec, options)) {
636
696
  const operationObject = methods[method];
637
697
  result[`${method.toUpperCase()} ${path}`] = operationObject;
638
698
  }
@@ -640,7 +700,7 @@ class Utils {
640
700
  }
641
701
  return result;
642
702
  }
643
- static validateSpec(spec, parser, isSwaggerFile, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
703
+ static validateSpec(spec, parser, isSwaggerFile, options) {
644
704
  const errors = [];
645
705
  const warnings = [];
646
706
  if (isSwaggerFile) {
@@ -650,7 +710,7 @@ class Utils {
650
710
  });
651
711
  }
652
712
  // Server validation
653
- const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
713
+ const serverErrors = Utils.validateServer(spec, options);
654
714
  errors.push(...serverErrors);
655
715
  // Remote reference not supported
656
716
  const refPaths = parser.$refs.paths();
@@ -663,7 +723,7 @@ class Utils {
663
723
  });
664
724
  }
665
725
  // No supported API
666
- const apiMap = Utils.listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
726
+ const apiMap = Utils.listSupportedAPIs(spec, options);
667
727
  if (Object.keys(apiMap).length === 0) {
668
728
  errors.push({
669
729
  type: ErrorType.NoSupportedApi,
@@ -734,6 +794,8 @@ class SpecParser {
734
794
  allowAPIKeyAuth: false,
735
795
  allowMultipleParameters: false,
736
796
  allowOauth2: false,
797
+ allowMethods: ["get", "post"],
798
+ projectType: ProjectType.SME,
737
799
  };
738
800
  this.pathOrSpec = pathOrDoc;
739
801
  this.parser = new SwaggerParser();
@@ -770,7 +832,7 @@ class SpecParser {
770
832
  ],
771
833
  };
772
834
  }
773
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
835
+ return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
774
836
  }
775
837
  catch (err) {
776
838
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -789,7 +851,7 @@ class SpecParser {
789
851
  if (!operationId) {
790
852
  continue;
791
853
  }
792
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options.allowMultipleParameters);
854
+ const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
793
855
  const apiInfo = {
794
856
  method: method,
795
857
  path: path,
@@ -818,12 +880,32 @@ class SpecParser {
818
880
  async list() {
819
881
  throw new Error("Method not implemented.");
820
882
  }
883
+ /**
884
+ * Generate specs according to the filters.
885
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
886
+ */
887
+ // eslint-disable-next-line @typescript-eslint/require-await
888
+ async getFilteredSpecs(filter, signal) {
889
+ throw new Error("Method not implemented.");
890
+ }
891
+ /**
892
+ * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
893
+ * @param manifestPath A file path of the Teams app manifest file to update.
894
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
895
+ * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
896
+ * @param pluginFilePath File path of the api plugin file to generate.
897
+ */
898
+ // eslint-disable-next-line @typescript-eslint/require-await
899
+ async generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
900
+ throw new Error("Method not implemented.");
901
+ }
821
902
  /**
822
903
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
823
904
  * @param manifestPath A file path of the Teams app manifest file to update.
824
905
  * @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
906
  * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
826
907
  * @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
908
+ * @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
827
909
  */
828
910
  // eslint-disable-next-line @typescript-eslint/require-await
829
911
  async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
@@ -843,11 +925,169 @@ class SpecParser {
843
925
  if (this.apiMap !== undefined) {
844
926
  return this.apiMap;
845
927
  }
846
- const result = Utils.listSupportedAPIs(spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
928
+ const result = Utils.listSupportedAPIs(spec, this.options);
847
929
  this.apiMap = result;
848
930
  return result;
849
931
  }
850
932
  }
851
933
 
852
- export { ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
934
+ // Copyright (c) Microsoft Corporation.
935
+ class AdaptiveCardGenerator {
936
+ static generateAdaptiveCard(operationItem) {
937
+ try {
938
+ const json = Utils.getResponseJson(operationItem);
939
+ let cardBody = [];
940
+ let schema = json.schema;
941
+ let jsonPath = "$";
942
+ if (schema && Object.keys(schema).length > 0) {
943
+ jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
944
+ if (jsonPath !== "$") {
945
+ schema = schema.properties[jsonPath];
946
+ }
947
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
948
+ }
949
+ // if no schema, try to use example value
950
+ if (cardBody.length === 0 && (json.examples || json.example)) {
951
+ cardBody = [
952
+ {
953
+ type: ConstantString.TextBlockType,
954
+ text: "${jsonStringify($root)}",
955
+ wrap: true,
956
+ },
957
+ ];
958
+ }
959
+ // if no example value, use default success response
960
+ if (cardBody.length === 0) {
961
+ cardBody = [
962
+ {
963
+ type: ConstantString.TextBlockType,
964
+ text: "success",
965
+ wrap: true,
966
+ },
967
+ ];
968
+ }
969
+ const fullCard = {
970
+ type: ConstantString.AdaptiveCardType,
971
+ $schema: ConstantString.AdaptiveCardSchema,
972
+ version: ConstantString.AdaptiveCardVersion,
973
+ body: cardBody,
974
+ };
975
+ return [fullCard, jsonPath];
976
+ }
977
+ catch (err) {
978
+ throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
979
+ }
980
+ }
981
+ static generateCardFromResponse(schema, name, parentArrayName = "") {
982
+ if (schema.type === "array") {
983
+ // schema.items can be arbitrary object: schema { type: array, items: {} }
984
+ if (Object.keys(schema.items).length === 0) {
985
+ return [
986
+ {
987
+ type: ConstantString.TextBlockType,
988
+ text: name ? `${name}: \${jsonStringify(${name})}` : "result: ${jsonStringify($root)}",
989
+ wrap: true,
990
+ },
991
+ ];
992
+ }
993
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
994
+ const template = {
995
+ type: ConstantString.ContainerType,
996
+ $data: name ? `\${${name}}` : "${$root}",
997
+ items: Array(),
998
+ };
999
+ template.items.push(...obj);
1000
+ return [template];
1001
+ }
1002
+ // some schema may not contain type but contain properties
1003
+ if (schema.type === "object" || (!schema.type && schema.properties)) {
1004
+ const { properties } = schema;
1005
+ const result = [];
1006
+ for (const property in properties) {
1007
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1008
+ result.push(...obj);
1009
+ }
1010
+ if (schema.additionalProperties) {
1011
+ // TODO: better ways to handler warnings.
1012
+ console.warn(ConstantString.AdditionalPropertiesNotSupported);
1013
+ }
1014
+ return result;
1015
+ }
1016
+ if (schema.type === "string" ||
1017
+ schema.type === "integer" ||
1018
+ schema.type === "boolean" ||
1019
+ schema.type === "number") {
1020
+ if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1021
+ // string in root: "ddd"
1022
+ let text = "result: ${$root}";
1023
+ if (name) {
1024
+ // object { id: "1" }
1025
+ text = `${name}: \${if(${name}, ${name}, 'N/A')}`;
1026
+ if (parentArrayName) {
1027
+ // object types inside array: { tags: ["id": 1, "name": "name"] }
1028
+ text = `${parentArrayName}.${text}`;
1029
+ }
1030
+ }
1031
+ else if (parentArrayName) {
1032
+ // string array: photoUrls: ["1", "2"]
1033
+ text = `${parentArrayName}: ` + "${$data}";
1034
+ }
1035
+ return [
1036
+ {
1037
+ type: ConstantString.TextBlockType,
1038
+ text,
1039
+ wrap: true,
1040
+ },
1041
+ ];
1042
+ }
1043
+ else {
1044
+ if (name) {
1045
+ return [
1046
+ {
1047
+ type: "Image",
1048
+ url: `\${${name}}`,
1049
+ $when: `\${${name} != null}`,
1050
+ },
1051
+ ];
1052
+ }
1053
+ else {
1054
+ return [
1055
+ {
1056
+ type: "Image",
1057
+ url: "${$data}",
1058
+ $when: "${$data != null}",
1059
+ },
1060
+ ];
1061
+ }
1062
+ }
1063
+ }
1064
+ if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
1065
+ throw new Error(Utils.format(ConstantString.SchemaNotSupported, JSON.stringify(schema)));
1066
+ }
1067
+ throw new Error(Utils.format(ConstantString.UnknownSchema, JSON.stringify(schema)));
1068
+ }
1069
+ // Find the first array property in the response schema object with the well-known name
1070
+ static getResponseJsonPathFromSchema(schema) {
1071
+ if (schema.type === "object" || (!schema.type && schema.properties)) {
1072
+ const { properties } = schema;
1073
+ for (const property in properties) {
1074
+ const schema = properties[property];
1075
+ if (schema.type === "array" &&
1076
+ Utils.isWellKnownName(property, ConstantString.WellknownResultNames)) {
1077
+ return property;
1078
+ }
1079
+ }
1080
+ }
1081
+ return "$";
1082
+ }
1083
+ static isImageUrlProperty(schema, name, parentArrayName) {
1084
+ const propertyName = name ? name : parentArrayName;
1085
+ return (!!propertyName &&
1086
+ schema.type === "string" &&
1087
+ Utils.isWellKnownName(propertyName, ConstantString.WellknownImageName) &&
1088
+ (propertyName.toLocaleLowerCase().indexOf("url") >= 0 || schema.format === "uri"));
1089
+ }
1090
+ }
1091
+
1092
+ export { AdaptiveCardGenerator, ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
853
1093
  //# sourceMappingURL=index.esm2017.js.map