@microsoft/m365-spec-parser 0.1.1-alpha.cd2ba87f2.0 → 0.1.1-alpha.d1a09e202.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.
@@ -61,7 +61,7 @@ exports.ErrorType = void 0;
61
61
  ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
62
62
  ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
63
63
  ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
64
- ErrorType["MultipleAPIKeyNotSupported"] = "multiple-api-key-not-supported";
64
+ ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
65
65
  ErrorType["ListFailed"] = "list-failed";
66
66
  ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
67
67
  ErrorType["FilterSpecFailed"] = "filter-spec-failed";
@@ -69,6 +69,7 @@ exports.ErrorType = void 0;
69
69
  ErrorType["GenerateAdaptiveCardFailed"] = "generate-adaptive-card-failed";
70
70
  ErrorType["GenerateFailed"] = "generate-failed";
71
71
  ErrorType["ValidateFailed"] = "validate-failed";
72
+ ErrorType["GetSpecFailed"] = "get-spec-failed";
72
73
  ErrorType["Cancelled"] = "cancelled";
73
74
  ErrorType["Unknown"] = "unknown";
74
75
  })(exports.ErrorType || (exports.ErrorType = {}));
@@ -91,7 +92,13 @@ exports.ValidationStatus = void 0;
91
92
  ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
92
93
  ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
93
94
  ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
94
- })(exports.ValidationStatus || (exports.ValidationStatus = {}));
95
+ })(exports.ValidationStatus || (exports.ValidationStatus = {}));
96
+ exports.ProjectType = void 0;
97
+ (function (ProjectType) {
98
+ ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
99
+ ProjectType[ProjectType["SME"] = 1] = "SME";
100
+ ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
101
+ })(exports.ProjectType || (exports.ProjectType = {}));
95
102
 
96
103
  // Copyright (c) Microsoft Corporation.
97
104
  class ConstantString {
@@ -110,7 +117,8 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
110
117
  ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
111
118
  ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
112
119
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
113
- ConstantString.MultipleAPIKeyNotSupported = "Multiple API keys are not supported. Please make sure that all selected APIs use the same API key.";
120
+ ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
121
+ ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
114
122
  ConstantString.WrappedCardVersion = "devPreview";
115
123
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
116
124
  ConstantString.WrappedCardResponseLayout = "list";
@@ -122,6 +130,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
122
130
  ConstantString.TextBlockType = "TextBlock";
123
131
  ConstantString.ContainerType = "Container";
124
132
  ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
133
+ ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
125
134
  ConstantString.ResponseCodeFor20X = [
126
135
  "200",
127
136
  "201",
@@ -181,7 +190,8 @@ ConstantString.FullDescriptionMaxLens = 4000;
181
190
  ConstantString.CommandDescriptionMaxLens = 128;
182
191
  ConstantString.ParameterDescriptionMaxLens = 128;
183
192
  ConstantString.CommandTitleMaxLens = 32;
184
- ConstantString.ParameterTitleMaxLens = 32;
193
+ ConstantString.ParameterTitleMaxLens = 32;
194
+ ConstantString.SMERequiredParamsMaxNum = 5;
185
195
 
186
196
  // Copyright (c) Microsoft Corporation.
187
197
  class SpecParserError extends Error {
@@ -193,7 +203,18 @@ class SpecParserError extends Error {
193
203
 
194
204
  // Copyright (c) Microsoft Corporation.
195
205
  class Utils {
196
- static checkParameters(paramObject) {
206
+ static hasNestedObjectInSchema(schema) {
207
+ if (schema.type === "object") {
208
+ for (const property in schema.properties) {
209
+ const nestedSchema = schema.properties[property];
210
+ if (nestedSchema.type === "object") {
211
+ return true;
212
+ }
213
+ }
214
+ }
215
+ return false;
216
+ }
217
+ static checkParameters(paramObject, isCopilot) {
197
218
  const paramResult = {
198
219
  requiredNum: 0,
199
220
  optionalNum: 0,
@@ -205,7 +226,20 @@ class Utils {
205
226
  for (let i = 0; i < paramObject.length; i++) {
206
227
  const param = paramObject[i];
207
228
  const schema = param.schema;
229
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
230
+ paramResult.isValid = false;
231
+ continue;
232
+ }
208
233
  const isRequiredWithoutDefault = param.required && schema.default === undefined;
234
+ if (isCopilot) {
235
+ if (isRequiredWithoutDefault) {
236
+ paramResult.requiredNum = paramResult.requiredNum + 1;
237
+ }
238
+ else {
239
+ paramResult.optionalNum = paramResult.optionalNum + 1;
240
+ }
241
+ continue;
242
+ }
209
243
  if (param.in === "header" || param.in === "cookie") {
210
244
  if (isRequiredWithoutDefault) {
211
245
  paramResult.isValid = false;
@@ -232,7 +266,7 @@ class Utils {
232
266
  }
233
267
  return paramResult;
234
268
  }
235
- static checkPostBody(schema, isRequired = false) {
269
+ static checkPostBody(schema, isRequired = false, isCopilot = false) {
236
270
  var _a;
237
271
  const paramResult = {
238
272
  requiredNum: 0,
@@ -243,6 +277,10 @@ class Utils {
243
277
  return paramResult;
244
278
  }
245
279
  const isRequiredWithoutDefault = isRequired && schema.default === undefined;
280
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
281
+ paramResult.isValid = false;
282
+ return paramResult;
283
+ }
246
284
  if (schema.type === "string" ||
247
285
  schema.type === "integer" ||
248
286
  schema.type === "boolean" ||
@@ -261,19 +299,22 @@ class Utils {
261
299
  if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
262
300
  isRequired = true;
263
301
  }
264
- const result = Utils.checkPostBody(properties[property], isRequired);
302
+ const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
265
303
  paramResult.requiredNum += result.requiredNum;
266
304
  paramResult.optionalNum += result.optionalNum;
267
305
  paramResult.isValid = paramResult.isValid && result.isValid;
268
306
  }
269
307
  }
270
308
  else {
271
- if (isRequiredWithoutDefault) {
309
+ if (isRequiredWithoutDefault && !isCopilot) {
272
310
  paramResult.isValid = false;
273
311
  }
274
312
  }
275
313
  return paramResult;
276
314
  }
315
+ static containMultipleMediaTypes(bodyObject) {
316
+ return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
317
+ }
277
318
  /**
278
319
  * Checks if the given API is supported.
279
320
  * @param {string} method - The HTTP method of the API.
@@ -288,32 +329,40 @@ class Utils {
288
329
  * 5. response body should be “application/json” and not empty, and response code should be 20X
289
330
  * 6. only support request body with “application/json” content type
290
331
  */
291
- static isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
332
+ static isSupportedApi(method, path, spec, options) {
333
+ var _a;
292
334
  const pathObj = spec.paths[path];
293
335
  method = method.toLocaleLowerCase();
294
336
  if (pathObj) {
295
- if ((method === ConstantString.PostMethod || method === ConstantString.GetMethod) &&
296
- pathObj[method]) {
337
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
297
338
  const securities = pathObj[method].security;
298
- const authArray = Utils.getAuthArray(securities, spec);
299
- if (!Utils.isSupportedAuth(authArray, allowAPIKeyAuth, allowOauth2)) {
300
- return false;
339
+ const isTeamsAi = options.projectType === exports.ProjectType.TeamsAi;
340
+ const isCopilot = options.projectType === exports.ProjectType.Copilot;
341
+ // Teams AI project doesn't care about auth, it will use authProvider for user to implement
342
+ if (!isTeamsAi) {
343
+ const authArray = Utils.getAuthArray(securities, spec);
344
+ if (!Utils.isSupportedAuth(authArray, options)) {
345
+ return false;
346
+ }
301
347
  }
302
348
  const operationObject = pathObj[method];
303
- if (!allowMissingId && !operationObject.operationId) {
349
+ if (!options.allowMissingId && !operationObject.operationId) {
304
350
  return false;
305
351
  }
306
352
  const paramObject = operationObject.parameters;
307
353
  const requestBody = operationObject.requestBody;
308
354
  const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
309
- const mediaTypesCount = Object.keys((requestBody === null || requestBody === void 0 ? void 0 : requestBody.content) || {}).length;
310
- if (mediaTypesCount > 1) {
355
+ if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
311
356
  return false;
312
357
  }
313
- const responseJson = Utils.getResponseJson(operationObject);
358
+ const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
314
359
  if (Object.keys(responseJson).length === 0) {
315
360
  return false;
316
361
  }
362
+ // Teams AI project doesn't care about request parameters/body
363
+ if (isTeamsAi) {
364
+ return true;
365
+ }
317
366
  let requestBodyParamResult = {
318
367
  requiredNum: 0,
319
368
  optionalNum: 0,
@@ -321,18 +370,26 @@ class Utils {
321
370
  };
322
371
  if (requestJsonBody) {
323
372
  const requestBodySchema = requestJsonBody.schema;
324
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required);
373
+ if (isCopilot && requestBodySchema.type !== "object") {
374
+ return false;
375
+ }
376
+ requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
325
377
  }
326
378
  if (!requestBodyParamResult.isValid) {
327
379
  return false;
328
380
  }
329
- const paramResult = Utils.checkParameters(paramObject);
381
+ const paramResult = Utils.checkParameters(paramObject, isCopilot);
330
382
  if (!paramResult.isValid) {
331
383
  return false;
332
384
  }
385
+ // Copilot support arbitrary parameters
386
+ if (isCopilot) {
387
+ return true;
388
+ }
333
389
  if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
334
- if (allowMultipleParameters &&
335
- requestBodyParamResult.requiredNum + paramResult.requiredNum <= 5) {
390
+ if (options.allowMultipleParameters &&
391
+ requestBodyParamResult.requiredNum + paramResult.requiredNum <=
392
+ ConstantString.SMERequiredParamsMaxNum) {
336
393
  return true;
337
394
  }
338
395
  return false;
@@ -351,29 +408,20 @@ class Utils {
351
408
  }
352
409
  return false;
353
410
  }
354
- static isSupportedAuth(authSchemaArray, allowAPIKeyAuth, allowOauth2) {
355
- if (authSchemaArray.length === 0) {
411
+ static isSupportedAuth(authSchemeArray, options) {
412
+ if (authSchemeArray.length === 0) {
356
413
  return true;
357
414
  }
358
- if (allowAPIKeyAuth || allowOauth2) {
415
+ if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
359
416
  // Currently we don't support multiple auth in one operation
360
- if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
417
+ if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
361
418
  return false;
362
419
  }
363
- for (const auths of authSchemaArray) {
420
+ for (const auths of authSchemeArray) {
364
421
  if (auths.length === 1) {
365
- if (!allowOauth2 && allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authSchema)) {
366
- return true;
367
- }
368
- else if (!allowAPIKeyAuth &&
369
- allowOauth2 &&
370
- Utils.isBearerTokenAuth(auths[0].authSchema)) {
371
- return true;
372
- }
373
- else if (allowAPIKeyAuth &&
374
- allowOauth2 &&
375
- (Utils.isAPIKeyAuth(auths[0].authSchema) ||
376
- Utils.isBearerTokenAuth(auths[0].authSchema))) {
422
+ if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
423
+ (options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
424
+ (options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
377
425
  return true;
378
426
  }
379
427
  }
@@ -381,13 +429,17 @@ class Utils {
381
429
  }
382
430
  return false;
383
431
  }
384
- static isAPIKeyAuth(authSchema) {
385
- return authSchema.type === "apiKey";
432
+ static isBearerTokenAuth(authScheme) {
433
+ return authScheme.type === "http" && authScheme.scheme === "bearer";
386
434
  }
387
- static isBearerTokenAuth(authSchema) {
388
- return (authSchema.type === "oauth2" ||
389
- authSchema.type === "openIdConnect" ||
390
- (authSchema.type === "http" && authSchema.scheme === "bearer"));
435
+ static isAPIKeyAuth(authScheme) {
436
+ return authScheme.type === "apiKey";
437
+ }
438
+ static isOAuthWithAuthCodeFlow(authScheme) {
439
+ if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
440
+ return true;
441
+ }
442
+ return false;
391
443
  }
392
444
  static getAuthArray(securities, spec) {
393
445
  var _a;
@@ -400,7 +452,7 @@ class Utils {
400
452
  for (const name in security) {
401
453
  const auth = securitySchemas[name];
402
454
  authArray.push({
403
- authSchema: auth,
455
+ authScheme: auth,
404
456
  name: name,
405
457
  });
406
458
  }
@@ -415,18 +467,19 @@ class Utils {
415
467
  static updateFirstLetter(str) {
416
468
  return str.charAt(0).toUpperCase() + str.slice(1);
417
469
  }
418
- static getResponseJson(operationObject) {
470
+ static getResponseJson(operationObject, isTeamsAiProject = false) {
419
471
  var _a, _b;
420
472
  let json = {};
421
473
  for (const code of ConstantString.ResponseCodeFor20X) {
422
474
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
423
- const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
424
- if (mediaTypesCount > 1) {
425
- return {};
426
- }
427
475
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
428
476
  json = responseObject.content["application/json"];
429
- break;
477
+ if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
478
+ json = {};
479
+ }
480
+ else {
481
+ break;
482
+ }
430
483
  }
431
484
  }
432
485
  return json;
@@ -500,7 +553,7 @@ class Utils {
500
553
  }
501
554
  return errors;
502
555
  }
503
- static validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
556
+ static validateServer(spec, options) {
504
557
  const errors = [];
505
558
  let hasTopLevelServers = false;
506
559
  let hasPathLevelServers = false;
@@ -521,7 +574,7 @@ class Utils {
521
574
  }
522
575
  for (const method in methods) {
523
576
  const operationObject = methods[method];
524
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
577
+ if (Utils.isSupportedApi(method, path, spec, options)) {
525
578
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
526
579
  hasOperationLevelServers = true;
527
580
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -608,7 +661,7 @@ class Utils {
608
661
  param.value = schema.default;
609
662
  }
610
663
  }
611
- static parseApiInfo(operationItem, allowMultipleParameters) {
664
+ static parseApiInfo(operationItem, options) {
612
665
  var _a, _b;
613
666
  const requiredParams = [];
614
667
  const optionalParams = [];
@@ -622,7 +675,7 @@ class Utils {
622
675
  description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
623
676
  };
624
677
  const schema = param.schema;
625
- if (allowMultipleParameters && schema) {
678
+ if (options.allowMultipleParameters && schema) {
626
679
  Utils.updateParameterWithInputType(schema, parameter);
627
680
  }
628
681
  if (param.in !== "header" && param.in !== "cookie") {
@@ -640,7 +693,7 @@ class Utils {
640
693
  const requestJson = requestBody.content["application/json"];
641
694
  if (Object.keys(requestJson).length !== 0) {
642
695
  const schema = requestJson.schema;
643
- const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
696
+ const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
644
697
  requiredParams.push(...requiredP);
645
698
  optionalParams.push(...optionalP);
646
699
  }
@@ -671,14 +724,13 @@ class Utils {
671
724
  }
672
725
  return [command, warning];
673
726
  }
674
- static listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
727
+ static listSupportedAPIs(spec, options) {
675
728
  const paths = spec.paths;
676
729
  const result = {};
677
730
  for (const path in paths) {
678
731
  const methods = paths[path];
679
732
  for (const method in methods) {
680
- // For developer preview, only support GET operation with only 1 parameter without auth
681
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
733
+ if (Utils.isSupportedApi(method, path, spec, options)) {
682
734
  const operationObject = methods[method];
683
735
  result[`${method.toUpperCase()} ${path}`] = operationObject;
684
736
  }
@@ -686,7 +738,7 @@ class Utils {
686
738
  }
687
739
  return result;
688
740
  }
689
- static validateSpec(spec, parser, isSwaggerFile, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
741
+ static validateSpec(spec, parser, isSwaggerFile, options) {
690
742
  const errors = [];
691
743
  const warnings = [];
692
744
  if (isSwaggerFile) {
@@ -696,7 +748,7 @@ class Utils {
696
748
  });
697
749
  }
698
750
  // Server validation
699
- const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
751
+ const serverErrors = Utils.validateServer(spec, options);
700
752
  errors.push(...serverErrors);
701
753
  // Remote reference not supported
702
754
  const refPaths = parser.$refs.paths();
@@ -709,7 +761,7 @@ class Utils {
709
761
  });
710
762
  }
711
763
  // No supported API
712
- const apiMap = Utils.listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
764
+ const apiMap = Utils.listSupportedAPIs(spec, options);
713
765
  if (Object.keys(apiMap).length === 0) {
714
766
  errors.push({
715
767
  type: exports.ErrorType.NoSupportedApi,
@@ -765,14 +817,14 @@ class Utils {
765
817
 
766
818
  // Copyright (c) Microsoft Corporation.
767
819
  class SpecFilter {
768
- static specFilter(filter, unResolveSpec, resolvedSpec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
820
+ static specFilter(filter, unResolveSpec, resolvedSpec, options) {
769
821
  try {
770
822
  const newSpec = Object.assign({}, unResolveSpec);
771
823
  const newPaths = {};
772
824
  for (const filterItem of filter) {
773
825
  const [method, path] = filterItem.split(" ");
774
826
  const methodName = method.toLowerCase();
775
- if (!Utils.isSupportedApi(methodName, path, resolvedSpec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
827
+ if (!Utils.isSupportedApi(methodName, path, resolvedSpec, options)) {
776
828
  continue;
777
829
  }
778
830
  if (!newPaths[path]) {
@@ -798,47 +850,170 @@ class SpecFilter {
798
850
 
799
851
  // Copyright (c) Microsoft Corporation.
800
852
  class ManifestUpdater {
801
- static updateManifest(manifestPath, outputSpecPath, adaptiveCardFolder, spec, allowMultipleParameters, auth) {
853
+ static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options) {
854
+ return __awaiter(this, void 0, void 0, function* () {
855
+ const manifest = yield fs__default['default'].readJSON(manifestPath);
856
+ const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
857
+ manifest.plugins = [
858
+ {
859
+ pluginFile: apiPluginRelativePath,
860
+ },
861
+ ];
862
+ ManifestUpdater.updateManifestDescription(manifest, spec);
863
+ const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
864
+ const apiPlugin = ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, options);
865
+ return [manifest, apiPlugin];
866
+ });
867
+ }
868
+ static updateManifestDescription(manifest, spec) {
802
869
  var _a, _b;
870
+ manifest.description = {
871
+ short: spec.info.title.slice(0, ConstantString.ShortDescriptionMaxLens),
872
+ full: (_b = ((_a = spec.info.description) !== null && _a !== void 0 ? _a : manifest.description.full)) === null || _b === void 0 ? void 0 : _b.slice(0, ConstantString.FullDescriptionMaxLens),
873
+ };
874
+ }
875
+ static mapOpenAPISchemaToFuncParam(schema, method, pathUrl) {
876
+ let parameter;
877
+ if (schema.type === "string" ||
878
+ schema.type === "boolean" ||
879
+ schema.type === "integer" ||
880
+ schema.type === "number" ||
881
+ schema.type === "array") {
882
+ parameter = schema;
883
+ }
884
+ else {
885
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), exports.ErrorType.UpdateManifestFailed);
886
+ }
887
+ return parameter;
888
+ }
889
+ static generatePluginManifestSchema(spec, specRelativePath, options) {
890
+ var _a, _b, _c;
891
+ const functions = [];
892
+ const functionNames = [];
893
+ const paths = spec.paths;
894
+ for (const pathUrl in paths) {
895
+ const pathItem = paths[pathUrl];
896
+ if (pathItem) {
897
+ const operations = pathItem;
898
+ for (const method in operations) {
899
+ if (options.allowMethods.includes(method)) {
900
+ const operationItem = operations[method];
901
+ if (operationItem) {
902
+ const operationId = operationItem.operationId;
903
+ const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
904
+ const paramObject = operationItem.parameters;
905
+ const requestBody = operationItem.requestBody;
906
+ const parameters = {
907
+ type: "object",
908
+ properties: {},
909
+ required: [],
910
+ };
911
+ if (paramObject) {
912
+ for (let i = 0; i < paramObject.length; i++) {
913
+ const param = paramObject[i];
914
+ const schema = param.schema;
915
+ parameters.properties[param.name] = ManifestUpdater.mapOpenAPISchemaToFuncParam(schema, method, pathUrl);
916
+ if (param.required) {
917
+ parameters.required.push(param.name);
918
+ }
919
+ if (!parameters.properties[param.name].description) {
920
+ parameters.properties[param.name].description = (_b = param.description) !== null && _b !== void 0 ? _b : "";
921
+ }
922
+ }
923
+ }
924
+ if (requestBody) {
925
+ const requestJsonBody = requestBody.content["application/json"];
926
+ const requestBodySchema = requestJsonBody.schema;
927
+ if (requestBodySchema.type === "object") {
928
+ if (requestBodySchema.required) {
929
+ parameters.required.push(...requestBodySchema.required);
930
+ }
931
+ for (const property in requestBodySchema.properties) {
932
+ const schema = requestBodySchema.properties[property];
933
+ parameters.properties[property] = ManifestUpdater.mapOpenAPISchemaToFuncParam(schema, method, pathUrl);
934
+ }
935
+ }
936
+ else {
937
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
938
+ }
939
+ }
940
+ const funcObj = {
941
+ name: operationId,
942
+ description: description,
943
+ parameters: parameters,
944
+ };
945
+ functions.push(funcObj);
946
+ functionNames.push(operationId);
947
+ }
948
+ }
949
+ }
950
+ }
951
+ }
952
+ const apiPlugin = {
953
+ schema_version: "v2",
954
+ name_for_human: spec.info.title,
955
+ description_for_human: (_c = spec.info.description) !== null && _c !== void 0 ? _c : "<Please add description of the plugin>",
956
+ functions: functions,
957
+ runtimes: [
958
+ {
959
+ type: "OpenApi",
960
+ auth: {
961
+ type: "none", // TODO, support auth in the future
962
+ },
963
+ spec: {
964
+ url: specRelativePath,
965
+ },
966
+ run_for_functions: functionNames,
967
+ },
968
+ ],
969
+ };
970
+ return apiPlugin;
971
+ }
972
+ static updateManifest(manifestPath, outputSpecPath, spec, options, adaptiveCardFolder, authInfo) {
803
973
  return __awaiter(this, void 0, void 0, function* () {
804
974
  try {
805
975
  const originalManifest = yield fs__default['default'].readJSON(manifestPath);
806
976
  const updatedPart = {};
807
- const [commands, warnings] = yield ManifestUpdater.generateCommands(spec, adaptiveCardFolder, manifestPath, allowMultipleParameters);
808
- const composeExtension = {
809
- composeExtensionType: "apiBased",
810
- apiSpecificationFile: ManifestUpdater.getRelativePath(manifestPath, outputSpecPath),
811
- commands: commands,
812
- };
813
- if (auth) {
814
- if (Utils.isAPIKeyAuth(auth)) {
815
- auth = auth;
816
- const safeApiSecretRegistrationId = Utils.getSafeRegistrationIdEnvName(`${auth.name}_${ConstantString.RegistrationIdPostfix}`);
817
- composeExtension.authorization = {
818
- authType: "apiSecretServiceAuth",
819
- apiSecretServiceAuthConfiguration: {
820
- apiSecretRegistrationId: `\${{${safeApiSecretRegistrationId}}}`,
821
- },
822
- };
823
- }
824
- else if (Utils.isBearerTokenAuth(auth)) {
825
- composeExtension.authorization = {
826
- authType: "microsoftEntra",
827
- microsoftEntraConfiguration: {
828
- supportsSingleSignOn: true,
829
- },
830
- };
831
- updatedPart.webApplicationInfo = {
832
- id: "${{AAD_APP_CLIENT_ID}}",
833
- resource: "api://${{DOMAIN}}/${{AAD_APP_CLIENT_ID}}",
834
- };
977
+ updatedPart.composeExtensions = [];
978
+ let warnings = [];
979
+ if (options.projectType === exports.ProjectType.SME) {
980
+ const updateResult = yield ManifestUpdater.generateCommands(spec, manifestPath, options, adaptiveCardFolder);
981
+ const commands = updateResult[0];
982
+ warnings = updateResult[1];
983
+ const composeExtension = {
984
+ composeExtensionType: "apiBased",
985
+ apiSpecificationFile: ManifestUpdater.getRelativePath(manifestPath, outputSpecPath),
986
+ commands: commands,
987
+ };
988
+ if (authInfo) {
989
+ const auth = authInfo.authScheme;
990
+ if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
991
+ const safeApiSecretRegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
992
+ composeExtension.authorization = {
993
+ authType: "apiSecretServiceAuth",
994
+ apiSecretServiceAuthConfiguration: {
995
+ apiSecretRegistrationId: `\${{${safeApiSecretRegistrationId}}}`,
996
+ },
997
+ };
998
+ }
999
+ else if (Utils.isOAuthWithAuthCodeFlow(auth)) {
1000
+ const safeOAuth2RegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.OAuthRegistrationIdPostFix}`);
1001
+ composeExtension.authorization = {
1002
+ authType: "oAuth2.0",
1003
+ oAuthConfiguration: {
1004
+ oauthConfigurationId: `\${{${safeOAuth2RegistrationId}}}`,
1005
+ },
1006
+ };
1007
+ updatedPart.webApplicationInfo = {
1008
+ id: "${{AAD_APP_CLIENT_ID}}",
1009
+ resource: "api://${{DOMAIN}}/${{AAD_APP_CLIENT_ID}}",
1010
+ };
1011
+ }
835
1012
  }
1013
+ updatedPart.composeExtensions = [composeExtension];
836
1014
  }
837
- updatedPart.description = {
838
- short: spec.info.title.slice(0, ConstantString.ShortDescriptionMaxLens),
839
- full: (_b = ((_a = spec.info.description) !== null && _a !== void 0 ? _a : originalManifest.description.full)) === null || _b === void 0 ? void 0 : _b.slice(0, ConstantString.FullDescriptionMaxLens),
840
- };
841
- updatedPart.composeExtensions = [composeExtension];
1015
+ updatedPart.description = originalManifest.description;
1016
+ ManifestUpdater.updateManifestDescription(updatedPart, spec);
842
1017
  const updatedManifest = Object.assign(Object.assign({}, originalManifest), updatedPart);
843
1018
  return [updatedManifest, warnings];
844
1019
  }
@@ -847,7 +1022,8 @@ class ManifestUpdater {
847
1022
  }
848
1023
  });
849
1024
  }
850
- static generateCommands(spec, adaptiveCardFolder, manifestPath, allowMultipleParameters) {
1025
+ static generateCommands(spec, manifestPath, options, adaptiveCardFolder) {
1026
+ var _a;
851
1027
  return __awaiter(this, void 0, void 0, function* () {
852
1028
  const paths = spec.paths;
853
1029
  const commands = [];
@@ -859,14 +1035,16 @@ class ManifestUpdater {
859
1035
  const operations = pathItem;
860
1036
  // Currently only support GET and POST method
861
1037
  for (const method in operations) {
862
- if (method === ConstantString.PostMethod || method === ConstantString.GetMethod) {
1038
+ if ((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) {
863
1039
  const operationItem = operations[method];
864
1040
  if (operationItem) {
865
- const [command, warning] = Utils.parseApiInfo(operationItem, allowMultipleParameters);
866
- const adaptiveCardPath = path__default['default'].join(adaptiveCardFolder, command.id + ".json");
867
- command.apiResponseRenderingTemplateFile = (yield fs__default['default'].pathExists(adaptiveCardPath))
868
- ? ManifestUpdater.getRelativePath(manifestPath, adaptiveCardPath)
869
- : "";
1041
+ const [command, warning] = Utils.parseApiInfo(operationItem, options);
1042
+ if (adaptiveCardFolder) {
1043
+ const adaptiveCardPath = path__default['default'].join(adaptiveCardFolder, command.id + ".json");
1044
+ command.apiResponseRenderingTemplateFile = (yield fs__default['default'].pathExists(adaptiveCardPath))
1045
+ ? ManifestUpdater.getRelativePath(manifestPath, adaptiveCardPath)
1046
+ : "";
1047
+ }
870
1048
  if (warning) {
871
1049
  warnings.push(warning);
872
1050
  }
@@ -1150,8 +1328,11 @@ class SpecParser {
1150
1328
  allowMissingId: true,
1151
1329
  allowSwagger: true,
1152
1330
  allowAPIKeyAuth: false,
1331
+ allowBearerTokenAuth: false,
1153
1332
  allowMultipleParameters: false,
1154
1333
  allowOauth2: false,
1334
+ allowMethods: ["get", "post"],
1335
+ projectType: exports.ProjectType.SME,
1155
1336
  };
1156
1337
  this.pathOrSpec = pathOrDoc;
1157
1338
  this.parser = new SwaggerParser__default['default']();
@@ -1185,7 +1366,7 @@ class SpecParser {
1185
1366
  ],
1186
1367
  };
1187
1368
  }
1188
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
1369
+ return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
1189
1370
  }
1190
1371
  catch (err) {
1191
1372
  throw new SpecParserError(err.toString(), exports.ErrorType.ValidateFailed);
@@ -1235,7 +1416,7 @@ class SpecParser {
1235
1416
  const authArray = Utils.getAuthArray(operation.security, spec);
1236
1417
  for (const auths of authArray) {
1237
1418
  if (auths.length === 1) {
1238
- apiResult.auth = auths[0].authSchema;
1419
+ apiResult.auth = auths[0].authScheme;
1239
1420
  break;
1240
1421
  }
1241
1422
  }
@@ -1252,49 +1433,110 @@ class SpecParser {
1252
1433
  }
1253
1434
  });
1254
1435
  }
1436
+ /**
1437
+ * Generate specs according to the filters.
1438
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
1439
+ */
1440
+ getFilteredSpecs(filter, signal) {
1441
+ return __awaiter(this, void 0, void 0, function* () {
1442
+ try {
1443
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1444
+ throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1445
+ }
1446
+ yield this.loadSpec();
1447
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1448
+ throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1449
+ }
1450
+ const newUnResolvedSpec = SpecFilter.specFilter(filter, this.unResolveSpec, this.spec, this.options);
1451
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1452
+ throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1453
+ }
1454
+ const newSpec = (yield this.parser.dereference(newUnResolvedSpec));
1455
+ return [newUnResolvedSpec, newSpec];
1456
+ }
1457
+ catch (err) {
1458
+ if (err instanceof SpecParserError) {
1459
+ throw err;
1460
+ }
1461
+ throw new SpecParserError(err.toString(), exports.ErrorType.GetSpecFailed);
1462
+ }
1463
+ });
1464
+ }
1255
1465
  /**
1256
1466
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
1257
1467
  * @param manifestPath A file path of the Teams app manifest file to update.
1258
1468
  * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
1259
1469
  * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
1260
- * @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
1470
+ * @param pluginFilePath File path of the api plugin file to generate.
1261
1471
  */
1262
- generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
1472
+ generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
1263
1473
  return __awaiter(this, void 0, void 0, function* () {
1264
1474
  const result = {
1265
1475
  allSuccess: true,
1266
1476
  warnings: [],
1267
1477
  };
1268
1478
  try {
1269
- if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1270
- throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1479
+ const newSpecs = yield this.getFilteredSpecs(filter, signal);
1480
+ const newUnResolvedSpec = newSpecs[0];
1481
+ const newSpec = newSpecs[1];
1482
+ let resultStr;
1483
+ if (outputSpecPath.endsWith(".yaml") || outputSpecPath.endsWith(".yml")) {
1484
+ resultStr = jsyaml__default['default'].dump(newUnResolvedSpec);
1271
1485
  }
1272
- yield this.loadSpec();
1273
- if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1274
- throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1486
+ else {
1487
+ resultStr = JSON.stringify(newUnResolvedSpec, null, 2);
1275
1488
  }
1276
- const newUnResolvedSpec = SpecFilter.specFilter(filter, this.unResolveSpec, this.spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
1489
+ yield fs__default['default'].outputFile(outputSpecPath, resultStr);
1277
1490
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1278
1491
  throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1279
1492
  }
1280
- const newSpec = (yield this.parser.dereference(newUnResolvedSpec));
1281
- const AuthSet = new Set();
1282
- let hasMultipleAPIKeyAuth = false;
1493
+ const [updatedManifest, apiPlugin] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options);
1494
+ yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 2 });
1495
+ yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 2 });
1496
+ }
1497
+ catch (err) {
1498
+ if (err instanceof SpecParserError) {
1499
+ throw err;
1500
+ }
1501
+ throw new SpecParserError(err.toString(), exports.ErrorType.GenerateFailed);
1502
+ }
1503
+ return result;
1504
+ });
1505
+ }
1506
+ /**
1507
+ * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
1508
+ * @param manifestPath A file path of the Teams app manifest file to update.
1509
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
1510
+ * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
1511
+ * @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
1512
+ */
1513
+ generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
1514
+ return __awaiter(this, void 0, void 0, function* () {
1515
+ const result = {
1516
+ allSuccess: true,
1517
+ warnings: [],
1518
+ };
1519
+ try {
1520
+ const newSpecs = yield this.getFilteredSpecs(filter, signal);
1521
+ const newUnResolvedSpec = newSpecs[0];
1522
+ const newSpec = newSpecs[1];
1523
+ const authSet = new Set();
1524
+ let hasMultipleAuth = false;
1283
1525
  for (const url in newSpec.paths) {
1284
1526
  for (const method in newSpec.paths[url]) {
1285
1527
  const operation = newSpec.paths[url][method];
1286
1528
  const authArray = Utils.getAuthArray(operation.security, newSpec);
1287
1529
  if (authArray && authArray.length > 0) {
1288
- AuthSet.add(authArray[0][0].authSchema);
1289
- if (AuthSet.size > 1) {
1290
- hasMultipleAPIKeyAuth = true;
1530
+ authSet.add(authArray[0][0]);
1531
+ if (authSet.size > 1) {
1532
+ hasMultipleAuth = true;
1291
1533
  break;
1292
1534
  }
1293
1535
  }
1294
1536
  }
1295
1537
  }
1296
- if (hasMultipleAPIKeyAuth) {
1297
- throw new SpecParserError(ConstantString.MultipleAPIKeyNotSupported, exports.ErrorType.MultipleAPIKeyNotSupported);
1538
+ if (hasMultipleAuth && this.options.projectType !== exports.ProjectType.TeamsAi) {
1539
+ throw new SpecParserError(ConstantString.MultipleAuthNotSupported, exports.ErrorType.MultipleAuthNotSupported);
1298
1540
  }
1299
1541
  let resultStr;
1300
1542
  if (outputSpecPath.endsWith(".yaml") || outputSpecPath.endsWith(".yml")) {
@@ -1304,26 +1546,28 @@ class SpecParser {
1304
1546
  resultStr = JSON.stringify(newUnResolvedSpec, null, 2);
1305
1547
  }
1306
1548
  yield fs__default['default'].outputFile(outputSpecPath, resultStr);
1307
- for (const url in newSpec.paths) {
1308
- for (const method in newSpec.paths[url]) {
1309
- // paths object may contain description/summary, so we need to check if it is a operation object
1310
- if (method === ConstantString.PostMethod || method === ConstantString.GetMethod) {
1311
- const operation = newSpec.paths[url][method];
1312
- try {
1313
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
1314
- const fileName = path__default['default'].join(adaptiveCardFolder, `${operation.operationId}.json`);
1315
- const wrappedCard = wrapAdaptiveCard(card, jsonPath);
1316
- yield fs__default['default'].outputJSON(fileName, wrappedCard, { spaces: 2 });
1317
- const dataFileName = path__default['default'].join(adaptiveCardFolder, `${operation.operationId}.data.json`);
1318
- yield fs__default['default'].outputJSON(dataFileName, {}, { spaces: 2 });
1319
- }
1320
- catch (err) {
1321
- result.allSuccess = false;
1322
- result.warnings.push({
1323
- type: exports.WarningType.GenerateCardFailed,
1324
- content: err.toString(),
1325
- data: operation.operationId,
1326
- });
1549
+ if (adaptiveCardFolder) {
1550
+ for (const url in newSpec.paths) {
1551
+ for (const method in newSpec.paths[url]) {
1552
+ // paths object may contain description/summary which is not a http method, so we need to check if it is a operation object
1553
+ if (this.options.allowMethods.includes(method)) {
1554
+ const operation = newSpec.paths[url][method];
1555
+ try {
1556
+ const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
1557
+ const fileName = path__default['default'].join(adaptiveCardFolder, `${operation.operationId}.json`);
1558
+ const wrappedCard = wrapAdaptiveCard(card, jsonPath);
1559
+ yield fs__default['default'].outputJSON(fileName, wrappedCard, { spaces: 2 });
1560
+ const dataFileName = path__default['default'].join(adaptiveCardFolder, `${operation.operationId}.data.json`);
1561
+ yield fs__default['default'].outputJSON(dataFileName, {}, { spaces: 2 });
1562
+ }
1563
+ catch (err) {
1564
+ result.allSuccess = false;
1565
+ result.warnings.push({
1566
+ type: exports.WarningType.GenerateCardFailed,
1567
+ content: err.toString(),
1568
+ data: operation.operationId,
1569
+ });
1570
+ }
1327
1571
  }
1328
1572
  }
1329
1573
  }
@@ -1331,8 +1575,8 @@ class SpecParser {
1331
1575
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1332
1576
  throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
1333
1577
  }
1334
- const auth = Array.from(AuthSet)[0];
1335
- const [updatedManifest, warnings] = yield ManifestUpdater.updateManifest(manifestPath, outputSpecPath, adaptiveCardFolder, newSpec, this.options.allowMultipleParameters, auth);
1578
+ const authInfo = Array.from(authSet)[0];
1579
+ const [updatedManifest, warnings] = yield ManifestUpdater.updateManifest(manifestPath, outputSpecPath, newSpec, this.options, adaptiveCardFolder, authInfo);
1336
1580
  yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 2 });
1337
1581
  result.warnings.push(...warnings);
1338
1582
  }
@@ -1364,12 +1608,13 @@ class SpecParser {
1364
1608
  if (this.apiMap !== undefined) {
1365
1609
  return this.apiMap;
1366
1610
  }
1367
- const result = Utils.listSupportedAPIs(spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
1611
+ const result = Utils.listSupportedAPIs(spec, this.options);
1368
1612
  this.apiMap = result;
1369
1613
  return result;
1370
1614
  }
1371
1615
  }
1372
1616
 
1617
+ exports.AdaptiveCardGenerator = AdaptiveCardGenerator;
1373
1618
  exports.ConstantString = ConstantString;
1374
1619
  exports.SpecParser = SpecParser;
1375
1620
  exports.SpecParserError = SpecParserError;