@microsoft/m365-spec-parser 0.1.1-alpha.cf377d39f.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.
@@ -19,7 +19,7 @@ var ErrorType;
19
19
  ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
20
20
  ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
21
21
  ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
22
- ErrorType["MultipleAPIKeyNotSupported"] = "multiple-api-key-not-supported";
22
+ ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
23
23
  ErrorType["ListFailed"] = "list-failed";
24
24
  ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
25
25
  ErrorType["FilterSpecFailed"] = "filter-spec-failed";
@@ -50,7 +50,13 @@ var ValidationStatus;
50
50
  ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
51
51
  ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
52
52
  ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
53
- })(ValidationStatus || (ValidationStatus = {}));
53
+ })(ValidationStatus || (ValidationStatus = {}));
54
+ var ProjectType;
55
+ (function (ProjectType) {
56
+ ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
57
+ ProjectType[ProjectType["SME"] = 1] = "SME";
58
+ ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
59
+ })(ProjectType || (ProjectType = {}));
54
60
 
55
61
  // Copyright (c) Microsoft Corporation.
56
62
  class ConstantString {
@@ -69,7 +75,8 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
69
75
  ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
70
76
  ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
71
77
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
72
- ConstantString.MultipleAPIKeyNotSupported = "Multiple API keys are not supported. Please make sure that all selected APIs use the same API key.";
78
+ ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
79
+ ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
73
80
  ConstantString.WrappedCardVersion = "devPreview";
74
81
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
75
82
  ConstantString.WrappedCardResponseLayout = "list";
@@ -81,6 +88,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
81
88
  ConstantString.TextBlockType = "TextBlock";
82
89
  ConstantString.ContainerType = "Container";
83
90
  ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
91
+ ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
84
92
  ConstantString.ResponseCodeFor20X = [
85
93
  "200",
86
94
  "201",
@@ -140,7 +148,8 @@ ConstantString.FullDescriptionMaxLens = 4000;
140
148
  ConstantString.CommandDescriptionMaxLens = 128;
141
149
  ConstantString.ParameterDescriptionMaxLens = 128;
142
150
  ConstantString.CommandTitleMaxLens = 32;
143
- ConstantString.ParameterTitleMaxLens = 32;
151
+ ConstantString.ParameterTitleMaxLens = 32;
152
+ ConstantString.SMERequiredParamsMaxNum = 5;
144
153
 
145
154
  // Copyright (c) Microsoft Corporation.
146
155
  class SpecParserError extends Error {
@@ -152,7 +161,18 @@ class SpecParserError extends Error {
152
161
 
153
162
  // Copyright (c) Microsoft Corporation.
154
163
  class Utils {
155
- static checkParameters(paramObject) {
164
+ static hasNestedObjectInSchema(schema) {
165
+ if (schema.type === "object") {
166
+ for (const property in schema.properties) {
167
+ const nestedSchema = schema.properties[property];
168
+ if (nestedSchema.type === "object") {
169
+ return true;
170
+ }
171
+ }
172
+ }
173
+ return false;
174
+ }
175
+ static checkParameters(paramObject, isCopilot) {
156
176
  const paramResult = {
157
177
  requiredNum: 0,
158
178
  optionalNum: 0,
@@ -164,7 +184,20 @@ class Utils {
164
184
  for (let i = 0; i < paramObject.length; i++) {
165
185
  const param = paramObject[i];
166
186
  const schema = param.schema;
187
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
188
+ paramResult.isValid = false;
189
+ continue;
190
+ }
167
191
  const isRequiredWithoutDefault = param.required && schema.default === undefined;
192
+ if (isCopilot) {
193
+ if (isRequiredWithoutDefault) {
194
+ paramResult.requiredNum = paramResult.requiredNum + 1;
195
+ }
196
+ else {
197
+ paramResult.optionalNum = paramResult.optionalNum + 1;
198
+ }
199
+ continue;
200
+ }
168
201
  if (param.in === "header" || param.in === "cookie") {
169
202
  if (isRequiredWithoutDefault) {
170
203
  paramResult.isValid = false;
@@ -191,7 +224,7 @@ class Utils {
191
224
  }
192
225
  return paramResult;
193
226
  }
194
- static checkPostBody(schema, isRequired = false) {
227
+ static checkPostBody(schema, isRequired = false, isCopilot = false) {
195
228
  var _a;
196
229
  const paramResult = {
197
230
  requiredNum: 0,
@@ -202,6 +235,10 @@ class Utils {
202
235
  return paramResult;
203
236
  }
204
237
  const isRequiredWithoutDefault = isRequired && schema.default === undefined;
238
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
239
+ paramResult.isValid = false;
240
+ return paramResult;
241
+ }
205
242
  if (schema.type === "string" ||
206
243
  schema.type === "integer" ||
207
244
  schema.type === "boolean" ||
@@ -220,19 +257,22 @@ class Utils {
220
257
  if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
221
258
  isRequired = true;
222
259
  }
223
- const result = Utils.checkPostBody(properties[property], isRequired);
260
+ const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
224
261
  paramResult.requiredNum += result.requiredNum;
225
262
  paramResult.optionalNum += result.optionalNum;
226
263
  paramResult.isValid = paramResult.isValid && result.isValid;
227
264
  }
228
265
  }
229
266
  else {
230
- if (isRequiredWithoutDefault) {
267
+ if (isRequiredWithoutDefault && !isCopilot) {
231
268
  paramResult.isValid = false;
232
269
  }
233
270
  }
234
271
  return paramResult;
235
272
  }
273
+ static containMultipleMediaTypes(bodyObject) {
274
+ return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
275
+ }
236
276
  /**
237
277
  * Checks if the given API is supported.
238
278
  * @param {string} method - The HTTP method of the API.
@@ -247,32 +287,40 @@ class Utils {
247
287
  * 5. response body should be “application/json” and not empty, and response code should be 20X
248
288
  * 6. only support request body with “application/json” content type
249
289
  */
250
- static isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
290
+ static isSupportedApi(method, path, spec, options) {
291
+ var _a;
251
292
  const pathObj = spec.paths[path];
252
293
  method = method.toLocaleLowerCase();
253
294
  if (pathObj) {
254
- if ((method === ConstantString.PostMethod || method === ConstantString.GetMethod) &&
255
- pathObj[method]) {
295
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
256
296
  const securities = pathObj[method].security;
257
- const authArray = Utils.getAuthArray(securities, spec);
258
- if (!Utils.isSupportedAuth(authArray, allowAPIKeyAuth, allowOauth2)) {
259
- return false;
297
+ const isTeamsAi = options.projectType === ProjectType.TeamsAi;
298
+ const isCopilot = options.projectType === ProjectType.Copilot;
299
+ // Teams AI project doesn't care about auth, it will use authProvider for user to implement
300
+ if (!isTeamsAi) {
301
+ const authArray = Utils.getAuthArray(securities, spec);
302
+ if (!Utils.isSupportedAuth(authArray, options)) {
303
+ return false;
304
+ }
260
305
  }
261
306
  const operationObject = pathObj[method];
262
- if (!allowMissingId && !operationObject.operationId) {
307
+ if (!options.allowMissingId && !operationObject.operationId) {
263
308
  return false;
264
309
  }
265
310
  const paramObject = operationObject.parameters;
266
311
  const requestBody = operationObject.requestBody;
267
312
  const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
268
- const mediaTypesCount = Object.keys((requestBody === null || requestBody === void 0 ? void 0 : requestBody.content) || {}).length;
269
- if (mediaTypesCount > 1) {
313
+ if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
270
314
  return false;
271
315
  }
272
- const responseJson = Utils.getResponseJson(operationObject);
316
+ const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
273
317
  if (Object.keys(responseJson).length === 0) {
274
318
  return false;
275
319
  }
320
+ // Teams AI project doesn't care about request parameters/body
321
+ if (isTeamsAi) {
322
+ return true;
323
+ }
276
324
  let requestBodyParamResult = {
277
325
  requiredNum: 0,
278
326
  optionalNum: 0,
@@ -280,18 +328,26 @@ class Utils {
280
328
  };
281
329
  if (requestJsonBody) {
282
330
  const requestBodySchema = requestJsonBody.schema;
283
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required);
331
+ if (isCopilot && requestBodySchema.type !== "object") {
332
+ return false;
333
+ }
334
+ requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
284
335
  }
285
336
  if (!requestBodyParamResult.isValid) {
286
337
  return false;
287
338
  }
288
- const paramResult = Utils.checkParameters(paramObject);
339
+ const paramResult = Utils.checkParameters(paramObject, isCopilot);
289
340
  if (!paramResult.isValid) {
290
341
  return false;
291
342
  }
343
+ // Copilot support arbitrary parameters
344
+ if (isCopilot) {
345
+ return true;
346
+ }
292
347
  if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
293
- if (allowMultipleParameters &&
294
- requestBodyParamResult.requiredNum + paramResult.requiredNum <= 5) {
348
+ if (options.allowMultipleParameters &&
349
+ requestBodyParamResult.requiredNum + paramResult.requiredNum <=
350
+ ConstantString.SMERequiredParamsMaxNum) {
295
351
  return true;
296
352
  }
297
353
  return false;
@@ -310,29 +366,31 @@ class Utils {
310
366
  }
311
367
  return false;
312
368
  }
313
- static isSupportedAuth(authSchemaArray, allowAPIKeyAuth, allowOauth2) {
369
+ static isSupportedAuth(authSchemaArray, options) {
314
370
  if (authSchemaArray.length === 0) {
315
371
  return true;
316
372
  }
317
- if (allowAPIKeyAuth || allowOauth2) {
373
+ if (options.allowAPIKeyAuth || options.allowOauth2) {
318
374
  // Currently we don't support multiple auth in one operation
319
375
  if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
320
376
  return false;
321
377
  }
322
378
  for (const auths of authSchemaArray) {
323
379
  if (auths.length === 1) {
324
- if (!allowOauth2 && allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authSchema)) {
380
+ if (!options.allowOauth2 &&
381
+ options.allowAPIKeyAuth &&
382
+ Utils.isAPIKeyAuth(auths[0].authSchema)) {
325
383
  return true;
326
384
  }
327
- else if (!allowAPIKeyAuth &&
328
- allowOauth2 &&
329
- Utils.isBearerTokenAuth(auths[0].authSchema)) {
385
+ else if (!options.allowAPIKeyAuth &&
386
+ options.allowOauth2 &&
387
+ Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema)) {
330
388
  return true;
331
389
  }
332
- else if (allowAPIKeyAuth &&
333
- allowOauth2 &&
390
+ else if (options.allowAPIKeyAuth &&
391
+ options.allowOauth2 &&
334
392
  (Utils.isAPIKeyAuth(auths[0].authSchema) ||
335
- Utils.isBearerTokenAuth(auths[0].authSchema))) {
393
+ Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema))) {
336
394
  return true;
337
395
  }
338
396
  }
@@ -343,10 +401,11 @@ class Utils {
343
401
  static isAPIKeyAuth(authSchema) {
344
402
  return authSchema.type === "apiKey";
345
403
  }
346
- static isBearerTokenAuth(authSchema) {
347
- return (authSchema.type === "oauth2" ||
348
- authSchema.type === "openIdConnect" ||
349
- (authSchema.type === "http" && authSchema.scheme === "bearer"));
404
+ static isOAuthWithAuthCodeFlow(authSchema) {
405
+ if (authSchema.type === "oauth2" && authSchema.flows && authSchema.flows.authorizationCode) {
406
+ return true;
407
+ }
408
+ return false;
350
409
  }
351
410
  static getAuthArray(securities, spec) {
352
411
  var _a;
@@ -374,18 +433,19 @@ class Utils {
374
433
  static updateFirstLetter(str) {
375
434
  return str.charAt(0).toUpperCase() + str.slice(1);
376
435
  }
377
- static getResponseJson(operationObject) {
436
+ static getResponseJson(operationObject, isTeamsAiProject = false) {
378
437
  var _a, _b;
379
438
  let json = {};
380
439
  for (const code of ConstantString.ResponseCodeFor20X) {
381
440
  const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
382
- const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
383
- if (mediaTypesCount > 1) {
384
- return {};
385
- }
386
441
  if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
387
442
  json = responseObject.content["application/json"];
388
- break;
443
+ if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
444
+ json = {};
445
+ }
446
+ else {
447
+ break;
448
+ }
389
449
  }
390
450
  }
391
451
  return json;
@@ -459,7 +519,7 @@ class Utils {
459
519
  }
460
520
  return errors;
461
521
  }
462
- static validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
522
+ static validateServer(spec, options) {
463
523
  const errors = [];
464
524
  let hasTopLevelServers = false;
465
525
  let hasPathLevelServers = false;
@@ -480,7 +540,7 @@ class Utils {
480
540
  }
481
541
  for (const method in methods) {
482
542
  const operationObject = methods[method];
483
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
543
+ if (Utils.isSupportedApi(method, path, spec, options)) {
484
544
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
485
545
  hasOperationLevelServers = true;
486
546
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -567,7 +627,7 @@ class Utils {
567
627
  param.value = schema.default;
568
628
  }
569
629
  }
570
- static parseApiInfo(operationItem, allowMultipleParameters) {
630
+ static parseApiInfo(operationItem, options) {
571
631
  var _a, _b;
572
632
  const requiredParams = [];
573
633
  const optionalParams = [];
@@ -581,7 +641,7 @@ class Utils {
581
641
  description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
582
642
  };
583
643
  const schema = param.schema;
584
- if (allowMultipleParameters && schema) {
644
+ if (options.allowMultipleParameters && schema) {
585
645
  Utils.updateParameterWithInputType(schema, parameter);
586
646
  }
587
647
  if (param.in !== "header" && param.in !== "cookie") {
@@ -599,7 +659,7 @@ class Utils {
599
659
  const requestJson = requestBody.content["application/json"];
600
660
  if (Object.keys(requestJson).length !== 0) {
601
661
  const schema = requestJson.schema;
602
- const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
662
+ const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
603
663
  requiredParams.push(...requiredP);
604
664
  optionalParams.push(...optionalP);
605
665
  }
@@ -630,14 +690,13 @@ class Utils {
630
690
  }
631
691
  return [command, warning];
632
692
  }
633
- static listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
693
+ static listSupportedAPIs(spec, options) {
634
694
  const paths = spec.paths;
635
695
  const result = {};
636
696
  for (const path in paths) {
637
697
  const methods = paths[path];
638
698
  for (const method in methods) {
639
- // For developer preview, only support GET operation with only 1 parameter without auth
640
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
699
+ if (Utils.isSupportedApi(method, path, spec, options)) {
641
700
  const operationObject = methods[method];
642
701
  result[`${method.toUpperCase()} ${path}`] = operationObject;
643
702
  }
@@ -645,7 +704,7 @@ class Utils {
645
704
  }
646
705
  return result;
647
706
  }
648
- static validateSpec(spec, parser, isSwaggerFile, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
707
+ static validateSpec(spec, parser, isSwaggerFile, options) {
649
708
  const errors = [];
650
709
  const warnings = [];
651
710
  if (isSwaggerFile) {
@@ -655,7 +714,7 @@ class Utils {
655
714
  });
656
715
  }
657
716
  // Server validation
658
- const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
717
+ const serverErrors = Utils.validateServer(spec, options);
659
718
  errors.push(...serverErrors);
660
719
  // Remote reference not supported
661
720
  const refPaths = parser.$refs.paths();
@@ -668,7 +727,7 @@ class Utils {
668
727
  });
669
728
  }
670
729
  // No supported API
671
- const apiMap = Utils.listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
730
+ const apiMap = Utils.listSupportedAPIs(spec, options);
672
731
  if (Object.keys(apiMap).length === 0) {
673
732
  errors.push({
674
733
  type: ErrorType.NoSupportedApi,
@@ -724,14 +783,14 @@ class Utils {
724
783
 
725
784
  // Copyright (c) Microsoft Corporation.
726
785
  class SpecFilter {
727
- static specFilter(filter, unResolveSpec, resolvedSpec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
786
+ static specFilter(filter, unResolveSpec, resolvedSpec, options) {
728
787
  try {
729
788
  const newSpec = Object.assign({}, unResolveSpec);
730
789
  const newPaths = {};
731
790
  for (const filterItem of filter) {
732
791
  const [method, path] = filterItem.split(" ");
733
792
  const methodName = method.toLowerCase();
734
- if (!Utils.isSupportedApi(methodName, path, resolvedSpec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
793
+ if (!Utils.isSupportedApi(methodName, path, resolvedSpec, options)) {
735
794
  continue;
736
795
  }
737
796
  if (!newPaths[path]) {
@@ -757,46 +816,168 @@ class SpecFilter {
757
816
 
758
817
  // Copyright (c) Microsoft Corporation.
759
818
  class ManifestUpdater {
760
- static async updateManifest(manifestPath, outputSpecPath, adaptiveCardFolder, spec, allowMultipleParameters, auth, isMe) {
819
+ static async updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options) {
820
+ const manifest = await fs.readJSON(manifestPath);
821
+ const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
822
+ manifest.plugins = [
823
+ {
824
+ pluginFile: apiPluginRelativePath,
825
+ },
826
+ ];
827
+ ManifestUpdater.updateManifestDescription(manifest, spec);
828
+ const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
829
+ const apiPlugin = ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, options);
830
+ return [manifest, apiPlugin];
831
+ }
832
+ static updateManifestDescription(manifest, spec) {
761
833
  var _a, _b;
834
+ manifest.description = {
835
+ short: spec.info.title.slice(0, ConstantString.ShortDescriptionMaxLens),
836
+ 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),
837
+ };
838
+ }
839
+ static mapOpenAPISchemaToFuncParam(schema, method, pathUrl) {
840
+ let parameter;
841
+ if (schema.type === "string" ||
842
+ schema.type === "boolean" ||
843
+ schema.type === "integer" ||
844
+ schema.type === "number" ||
845
+ schema.type === "array") {
846
+ parameter = schema;
847
+ }
848
+ else {
849
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), ErrorType.UpdateManifestFailed);
850
+ }
851
+ return parameter;
852
+ }
853
+ static generatePluginManifestSchema(spec, specRelativePath, options) {
854
+ var _a, _b, _c;
855
+ const functions = [];
856
+ const functionNames = [];
857
+ const paths = spec.paths;
858
+ for (const pathUrl in paths) {
859
+ const pathItem = paths[pathUrl];
860
+ if (pathItem) {
861
+ const operations = pathItem;
862
+ for (const method in operations) {
863
+ if (options.allowMethods.includes(method)) {
864
+ const operationItem = operations[method];
865
+ if (operationItem) {
866
+ const operationId = operationItem.operationId;
867
+ const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
868
+ const paramObject = operationItem.parameters;
869
+ const requestBody = operationItem.requestBody;
870
+ const parameters = {
871
+ type: "object",
872
+ properties: {},
873
+ required: [],
874
+ };
875
+ if (paramObject) {
876
+ for (let i = 0; i < paramObject.length; i++) {
877
+ const param = paramObject[i];
878
+ const schema = param.schema;
879
+ parameters.properties[param.name] = ManifestUpdater.mapOpenAPISchemaToFuncParam(schema, method, pathUrl);
880
+ if (param.required) {
881
+ parameters.required.push(param.name);
882
+ }
883
+ if (!parameters.properties[param.name].description) {
884
+ parameters.properties[param.name].description = (_b = param.description) !== null && _b !== void 0 ? _b : "";
885
+ }
886
+ }
887
+ }
888
+ if (requestBody) {
889
+ const requestJsonBody = requestBody.content["application/json"];
890
+ const requestBodySchema = requestJsonBody.schema;
891
+ if (requestBodySchema.type === "object") {
892
+ if (requestBodySchema.required) {
893
+ parameters.required.push(...requestBodySchema.required);
894
+ }
895
+ for (const property in requestBodySchema.properties) {
896
+ const schema = requestBodySchema.properties[property];
897
+ parameters.properties[property] = ManifestUpdater.mapOpenAPISchemaToFuncParam(schema, method, pathUrl);
898
+ }
899
+ }
900
+ else {
901
+ throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), ErrorType.UpdateManifestFailed);
902
+ }
903
+ }
904
+ const funcObj = {
905
+ name: operationId,
906
+ description: description,
907
+ parameters: parameters,
908
+ };
909
+ functions.push(funcObj);
910
+ functionNames.push(operationId);
911
+ }
912
+ }
913
+ }
914
+ }
915
+ }
916
+ const apiPlugin = {
917
+ schema_version: "v2",
918
+ name_for_human: spec.info.title,
919
+ description_for_human: (_c = spec.info.description) !== null && _c !== void 0 ? _c : "<Please add description of the plugin>",
920
+ functions: functions,
921
+ runtimes: [
922
+ {
923
+ type: "OpenApi",
924
+ auth: {
925
+ type: "none", // TODO, support auth in the future
926
+ },
927
+ spec: {
928
+ url: specRelativePath,
929
+ },
930
+ run_for_functions: functionNames,
931
+ },
932
+ ],
933
+ };
934
+ return apiPlugin;
935
+ }
936
+ static async updateManifest(manifestPath, outputSpecPath, spec, options, adaptiveCardFolder, authInfo) {
762
937
  try {
763
938
  const originalManifest = await fs.readJSON(manifestPath);
764
939
  const updatedPart = {};
765
- const [commands, warnings] = await ManifestUpdater.generateCommands(spec, adaptiveCardFolder, manifestPath, allowMultipleParameters);
766
- const composeExtension = {
767
- composeExtensionType: "apiBased",
768
- apiSpecificationFile: ManifestUpdater.getRelativePath(manifestPath, outputSpecPath),
769
- commands: commands,
770
- };
771
- if (auth) {
772
- if (Utils.isAPIKeyAuth(auth)) {
773
- auth = auth;
774
- const safeApiSecretRegistrationId = Utils.getSafeRegistrationIdEnvName(`${auth.name}_${ConstantString.RegistrationIdPostfix}`);
775
- composeExtension.authorization = {
776
- authType: "apiSecretServiceAuth",
777
- apiSecretServiceAuthConfiguration: {
778
- apiSecretRegistrationId: `\${{${safeApiSecretRegistrationId}}}`,
779
- },
780
- };
781
- }
782
- else if (Utils.isBearerTokenAuth(auth)) {
783
- composeExtension.authorization = {
784
- authType: "microsoftEntra",
785
- microsoftEntraConfiguration: {
786
- supportsSingleSignOn: true,
787
- },
788
- };
789
- updatedPart.webApplicationInfo = {
790
- id: "${{AAD_APP_CLIENT_ID}}",
791
- resource: "api://${{DOMAIN}}/${{AAD_APP_CLIENT_ID}}",
792
- };
940
+ updatedPart.composeExtensions = [];
941
+ let warnings = [];
942
+ if (options.projectType === ProjectType.SME) {
943
+ const updateResult = await ManifestUpdater.generateCommands(spec, manifestPath, options, adaptiveCardFolder);
944
+ const commands = updateResult[0];
945
+ warnings = updateResult[1];
946
+ const composeExtension = {
947
+ composeExtensionType: "apiBased",
948
+ apiSpecificationFile: ManifestUpdater.getRelativePath(manifestPath, outputSpecPath),
949
+ commands: commands,
950
+ };
951
+ if (authInfo) {
952
+ let auth = authInfo.authSchema;
953
+ if (Utils.isAPIKeyAuth(auth)) {
954
+ auth = auth;
955
+ const safeApiSecretRegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
956
+ composeExtension.authorization = {
957
+ authType: "apiSecretServiceAuth",
958
+ apiSecretServiceAuthConfiguration: {
959
+ apiSecretRegistrationId: `\${{${safeApiSecretRegistrationId}}}`,
960
+ },
961
+ };
962
+ }
963
+ else if (Utils.isOAuthWithAuthCodeFlow(auth)) {
964
+ const safeOAuth2RegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.OAuthRegistrationIdPostFix}`);
965
+ composeExtension.authorization = {
966
+ authType: "oAuth2.0",
967
+ oAuthConfiguration: {
968
+ oauthConfigurationId: `\${{${safeOAuth2RegistrationId}}}`,
969
+ },
970
+ };
971
+ updatedPart.webApplicationInfo = {
972
+ id: "${{AAD_APP_CLIENT_ID}}",
973
+ resource: "api://${{DOMAIN}}/${{AAD_APP_CLIENT_ID}}",
974
+ };
975
+ }
793
976
  }
977
+ updatedPart.composeExtensions = [composeExtension];
794
978
  }
795
- updatedPart.description = {
796
- short: spec.info.title.slice(0, ConstantString.ShortDescriptionMaxLens),
797
- 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),
798
- };
799
- updatedPart.composeExtensions = isMe === undefined || isMe === true ? [composeExtension] : [];
979
+ updatedPart.description = originalManifest.description;
980
+ ManifestUpdater.updateManifestDescription(updatedPart, spec);
800
981
  const updatedManifest = Object.assign(Object.assign({}, originalManifest), updatedPart);
801
982
  return [updatedManifest, warnings];
802
983
  }
@@ -804,7 +985,8 @@ class ManifestUpdater {
804
985
  throw new SpecParserError(err.toString(), ErrorType.UpdateManifestFailed);
805
986
  }
806
987
  }
807
- static async generateCommands(spec, adaptiveCardFolder, manifestPath, allowMultipleParameters) {
988
+ static async generateCommands(spec, manifestPath, options, adaptiveCardFolder) {
989
+ var _a;
808
990
  const paths = spec.paths;
809
991
  const commands = [];
810
992
  const warnings = [];
@@ -815,14 +997,16 @@ class ManifestUpdater {
815
997
  const operations = pathItem;
816
998
  // Currently only support GET and POST method
817
999
  for (const method in operations) {
818
- if (method === ConstantString.PostMethod || method === ConstantString.GetMethod) {
1000
+ if ((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) {
819
1001
  const operationItem = operations[method];
820
1002
  if (operationItem) {
821
- const [command, warning] = Utils.parseApiInfo(operationItem, allowMultipleParameters);
822
- const adaptiveCardPath = path.join(adaptiveCardFolder, command.id + ".json");
823
- command.apiResponseRenderingTemplateFile = (await fs.pathExists(adaptiveCardPath))
824
- ? ManifestUpdater.getRelativePath(manifestPath, adaptiveCardPath)
825
- : "";
1003
+ const [command, warning] = Utils.parseApiInfo(operationItem, options);
1004
+ if (adaptiveCardFolder) {
1005
+ const adaptiveCardPath = path.join(adaptiveCardFolder, command.id + ".json");
1006
+ command.apiResponseRenderingTemplateFile = (await fs.pathExists(adaptiveCardPath))
1007
+ ? ManifestUpdater.getRelativePath(manifestPath, adaptiveCardPath)
1008
+ : "";
1009
+ }
826
1010
  if (warning) {
827
1011
  warnings.push(warning);
828
1012
  }
@@ -1107,6 +1291,8 @@ class SpecParser {
1107
1291
  allowAPIKeyAuth: false,
1108
1292
  allowMultipleParameters: false,
1109
1293
  allowOauth2: false,
1294
+ allowMethods: ["get", "post"],
1295
+ projectType: ProjectType.SME,
1110
1296
  };
1111
1297
  this.pathOrSpec = pathOrDoc;
1112
1298
  this.parser = new SwaggerParser();
@@ -1139,7 +1325,7 @@ class SpecParser {
1139
1325
  ],
1140
1326
  };
1141
1327
  }
1142
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
1328
+ return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
1143
1329
  }
1144
1330
  catch (err) {
1145
1331
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -1214,7 +1400,7 @@ class SpecParser {
1214
1400
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1215
1401
  throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
1216
1402
  }
1217
- const newUnResolvedSpec = SpecFilter.specFilter(filter, this.unResolveSpec, this.spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
1403
+ const newUnResolvedSpec = SpecFilter.specFilter(filter, this.unResolveSpec, this.spec, this.options);
1218
1404
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1219
1405
  throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
1220
1406
  }
@@ -1228,15 +1414,53 @@ class SpecParser {
1228
1414
  throw new SpecParserError(err.toString(), ErrorType.GetSpecFailed);
1229
1415
  }
1230
1416
  }
1417
+ /**
1418
+ * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
1419
+ * @param manifestPath A file path of the Teams app manifest file to update.
1420
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
1421
+ * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
1422
+ * @param pluginFilePath File path of the api plugin file to generate.
1423
+ */
1424
+ async generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
1425
+ const result = {
1426
+ allSuccess: true,
1427
+ warnings: [],
1428
+ };
1429
+ try {
1430
+ const newSpecs = await this.getFilteredSpecs(filter, signal);
1431
+ const newUnResolvedSpec = newSpecs[0];
1432
+ const newSpec = newSpecs[1];
1433
+ let resultStr;
1434
+ if (outputSpecPath.endsWith(".yaml") || outputSpecPath.endsWith(".yml")) {
1435
+ resultStr = jsyaml.dump(newUnResolvedSpec);
1436
+ }
1437
+ else {
1438
+ resultStr = JSON.stringify(newUnResolvedSpec, null, 2);
1439
+ }
1440
+ await fs.outputFile(outputSpecPath, resultStr);
1441
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1442
+ throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
1443
+ }
1444
+ const [updatedManifest, apiPlugin] = await ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options);
1445
+ await fs.outputJSON(manifestPath, updatedManifest, { spaces: 2 });
1446
+ await fs.outputJSON(pluginFilePath, apiPlugin, { spaces: 2 });
1447
+ }
1448
+ catch (err) {
1449
+ if (err instanceof SpecParserError) {
1450
+ throw err;
1451
+ }
1452
+ throw new SpecParserError(err.toString(), ErrorType.GenerateFailed);
1453
+ }
1454
+ return result;
1455
+ }
1231
1456
  /**
1232
1457
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
1233
1458
  * @param manifestPath A file path of the Teams app manifest file to update.
1234
1459
  * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
1235
1460
  * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
1236
1461
  * @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
1237
- * @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
1238
1462
  */
1239
- async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal, isMe) {
1463
+ async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
1240
1464
  const result = {
1241
1465
  allSuccess: true,
1242
1466
  warnings: [],
@@ -1245,23 +1469,23 @@ class SpecParser {
1245
1469
  const newSpecs = await this.getFilteredSpecs(filter, signal);
1246
1470
  const newUnResolvedSpec = newSpecs[0];
1247
1471
  const newSpec = newSpecs[1];
1248
- const AuthSet = new Set();
1249
- let hasMultipleAPIKeyAuth = false;
1472
+ const authSet = new Set();
1473
+ let hasMultipleAuth = false;
1250
1474
  for (const url in newSpec.paths) {
1251
1475
  for (const method in newSpec.paths[url]) {
1252
1476
  const operation = newSpec.paths[url][method];
1253
1477
  const authArray = Utils.getAuthArray(operation.security, newSpec);
1254
1478
  if (authArray && authArray.length > 0) {
1255
- AuthSet.add(authArray[0][0].authSchema);
1256
- if (AuthSet.size > 1) {
1257
- hasMultipleAPIKeyAuth = true;
1479
+ authSet.add(authArray[0][0]);
1480
+ if (authSet.size > 1) {
1481
+ hasMultipleAuth = true;
1258
1482
  break;
1259
1483
  }
1260
1484
  }
1261
1485
  }
1262
1486
  }
1263
- if (hasMultipleAPIKeyAuth) {
1264
- throw new SpecParserError(ConstantString.MultipleAPIKeyNotSupported, ErrorType.MultipleAPIKeyNotSupported);
1487
+ if (hasMultipleAuth && this.options.projectType !== ProjectType.TeamsAi) {
1488
+ throw new SpecParserError(ConstantString.MultipleAuthNotSupported, ErrorType.MultipleAuthNotSupported);
1265
1489
  }
1266
1490
  let resultStr;
1267
1491
  if (outputSpecPath.endsWith(".yaml") || outputSpecPath.endsWith(".yml")) {
@@ -1271,26 +1495,28 @@ class SpecParser {
1271
1495
  resultStr = JSON.stringify(newUnResolvedSpec, null, 2);
1272
1496
  }
1273
1497
  await fs.outputFile(outputSpecPath, resultStr);
1274
- for (const url in newSpec.paths) {
1275
- for (const method in newSpec.paths[url]) {
1276
- // paths object may contain description/summary, so we need to check if it is a operation object
1277
- if (method === ConstantString.PostMethod || method === ConstantString.GetMethod) {
1278
- const operation = newSpec.paths[url][method];
1279
- try {
1280
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
1281
- const fileName = path.join(adaptiveCardFolder, `${operation.operationId}.json`);
1282
- const wrappedCard = wrapAdaptiveCard(card, jsonPath);
1283
- await fs.outputJSON(fileName, wrappedCard, { spaces: 2 });
1284
- const dataFileName = path.join(adaptiveCardFolder, `${operation.operationId}.data.json`);
1285
- await fs.outputJSON(dataFileName, {}, { spaces: 2 });
1286
- }
1287
- catch (err) {
1288
- result.allSuccess = false;
1289
- result.warnings.push({
1290
- type: WarningType.GenerateCardFailed,
1291
- content: err.toString(),
1292
- data: operation.operationId,
1293
- });
1498
+ if (adaptiveCardFolder) {
1499
+ for (const url in newSpec.paths) {
1500
+ for (const method in newSpec.paths[url]) {
1501
+ // paths object may contain description/summary which is not a http method, so we need to check if it is a operation object
1502
+ if (this.options.allowMethods.includes(method)) {
1503
+ const operation = newSpec.paths[url][method];
1504
+ try {
1505
+ const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
1506
+ const fileName = path.join(adaptiveCardFolder, `${operation.operationId}.json`);
1507
+ const wrappedCard = wrapAdaptiveCard(card, jsonPath);
1508
+ await fs.outputJSON(fileName, wrappedCard, { spaces: 2 });
1509
+ const dataFileName = path.join(adaptiveCardFolder, `${operation.operationId}.data.json`);
1510
+ await fs.outputJSON(dataFileName, {}, { spaces: 2 });
1511
+ }
1512
+ catch (err) {
1513
+ result.allSuccess = false;
1514
+ result.warnings.push({
1515
+ type: WarningType.GenerateCardFailed,
1516
+ content: err.toString(),
1517
+ data: operation.operationId,
1518
+ });
1519
+ }
1294
1520
  }
1295
1521
  }
1296
1522
  }
@@ -1298,8 +1524,8 @@ class SpecParser {
1298
1524
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
1299
1525
  throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
1300
1526
  }
1301
- const auth = Array.from(AuthSet)[0];
1302
- const [updatedManifest, warnings] = await ManifestUpdater.updateManifest(manifestPath, outputSpecPath, adaptiveCardFolder, newSpec, this.options.allowMultipleParameters, auth, isMe);
1527
+ const authInfo = Array.from(authSet)[0];
1528
+ const [updatedManifest, warnings] = await ManifestUpdater.updateManifest(manifestPath, outputSpecPath, newSpec, this.options, adaptiveCardFolder, authInfo);
1303
1529
  await fs.outputJSON(manifestPath, updatedManifest, { spaces: 2 });
1304
1530
  result.warnings.push(...warnings);
1305
1531
  }
@@ -1328,11 +1554,11 @@ class SpecParser {
1328
1554
  if (this.apiMap !== undefined) {
1329
1555
  return this.apiMap;
1330
1556
  }
1331
- const result = Utils.listSupportedAPIs(spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
1557
+ const result = Utils.listSupportedAPIs(spec, this.options);
1332
1558
  this.apiMap = result;
1333
1559
  return result;
1334
1560
  }
1335
1561
  }
1336
1562
 
1337
- export { AdaptiveCardGenerator, ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
1563
+ export { AdaptiveCardGenerator, ConstantString, ErrorType, ProjectType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
1338
1564
  //# sourceMappingURL=index.esm2017.mjs.map