@microsoft/m365-spec-parser 0.1.1-alpha.cf377d39f.0 → 0.1.1-alpha.f04ac4ba4.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.
@@ -46,7 +46,13 @@ var ValidationStatus;
46
46
  ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
47
47
  ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
48
48
  ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
49
- })(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 = {}));
50
56
 
51
57
  // Copyright (c) Microsoft Corporation.
52
58
  class SpecParserError extends Error {
@@ -74,6 +80,7 @@ ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multi
74
80
  ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
75
81
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
76
82
  ConstantString.MultipleAPIKeyNotSupported = "Multiple API keys are not supported. Please make sure that all selected APIs use the same API key.";
83
+ ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
77
84
  ConstantString.WrappedCardVersion = "devPreview";
78
85
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
79
86
  ConstantString.WrappedCardResponseLayout = "list";
@@ -144,11 +151,23 @@ ConstantString.FullDescriptionMaxLens = 4000;
144
151
  ConstantString.CommandDescriptionMaxLens = 128;
145
152
  ConstantString.ParameterDescriptionMaxLens = 128;
146
153
  ConstantString.CommandTitleMaxLens = 32;
147
- ConstantString.ParameterTitleMaxLens = 32;
154
+ ConstantString.ParameterTitleMaxLens = 32;
155
+ ConstantString.SMERequiredParamsMaxNum = 5;
148
156
 
149
157
  // Copyright (c) Microsoft Corporation.
150
158
  class Utils {
151
- static checkParameters(paramObject) {
159
+ static hasNestedObjectInSchema(schema) {
160
+ if (schema.type === "object") {
161
+ for (const property in schema.properties) {
162
+ const nestedSchema = schema.properties[property];
163
+ if (nestedSchema.type === "object") {
164
+ return true;
165
+ }
166
+ }
167
+ }
168
+ return false;
169
+ }
170
+ static checkParameters(paramObject, isCopilot) {
152
171
  const paramResult = {
153
172
  requiredNum: 0,
154
173
  optionalNum: 0,
@@ -160,7 +179,20 @@ class Utils {
160
179
  for (let i = 0; i < paramObject.length; i++) {
161
180
  const param = paramObject[i];
162
181
  const schema = param.schema;
182
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
183
+ paramResult.isValid = false;
184
+ continue;
185
+ }
163
186
  const isRequiredWithoutDefault = param.required && schema.default === undefined;
187
+ if (isCopilot) {
188
+ if (isRequiredWithoutDefault) {
189
+ paramResult.requiredNum = paramResult.requiredNum + 1;
190
+ }
191
+ else {
192
+ paramResult.optionalNum = paramResult.optionalNum + 1;
193
+ }
194
+ continue;
195
+ }
164
196
  if (param.in === "header" || param.in === "cookie") {
165
197
  if (isRequiredWithoutDefault) {
166
198
  paramResult.isValid = false;
@@ -187,7 +219,7 @@ class Utils {
187
219
  }
188
220
  return paramResult;
189
221
  }
190
- static checkPostBody(schema, isRequired = false) {
222
+ static checkPostBody(schema, isRequired = false, isCopilot = false) {
191
223
  var _a;
192
224
  const paramResult = {
193
225
  requiredNum: 0,
@@ -198,6 +230,10 @@ class Utils {
198
230
  return paramResult;
199
231
  }
200
232
  const isRequiredWithoutDefault = isRequired && schema.default === undefined;
233
+ if (isCopilot && this.hasNestedObjectInSchema(schema)) {
234
+ paramResult.isValid = false;
235
+ return paramResult;
236
+ }
201
237
  if (schema.type === "string" ||
202
238
  schema.type === "integer" ||
203
239
  schema.type === "boolean" ||
@@ -216,14 +252,14 @@ class Utils {
216
252
  if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
217
253
  isRequired = true;
218
254
  }
219
- const result = Utils.checkPostBody(properties[property], isRequired);
255
+ const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
220
256
  paramResult.requiredNum += result.requiredNum;
221
257
  paramResult.optionalNum += result.optionalNum;
222
258
  paramResult.isValid = paramResult.isValid && result.isValid;
223
259
  }
224
260
  }
225
261
  else {
226
- if (isRequiredWithoutDefault) {
262
+ if (isRequiredWithoutDefault && !isCopilot) {
227
263
  paramResult.isValid = false;
228
264
  }
229
265
  }
@@ -243,19 +279,19 @@ class Utils {
243
279
  * 5. response body should be “application/json” and not empty, and response code should be 20X
244
280
  * 6. only support request body with “application/json” content type
245
281
  */
246
- static isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
282
+ static isSupportedApi(method, path, spec, options) {
283
+ var _a;
247
284
  const pathObj = spec.paths[path];
248
285
  method = method.toLocaleLowerCase();
249
286
  if (pathObj) {
250
- if ((method === ConstantString.PostMethod || method === ConstantString.GetMethod) &&
251
- pathObj[method]) {
287
+ if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
252
288
  const securities = pathObj[method].security;
253
289
  const authArray = Utils.getAuthArray(securities, spec);
254
- if (!Utils.isSupportedAuth(authArray, allowAPIKeyAuth, allowOauth2)) {
290
+ if (!Utils.isSupportedAuth(authArray, options)) {
255
291
  return false;
256
292
  }
257
293
  const operationObject = pathObj[method];
258
- if (!allowMissingId && !operationObject.operationId) {
294
+ if (!options.allowMissingId && !operationObject.operationId) {
259
295
  return false;
260
296
  }
261
297
  const paramObject = operationObject.parameters;
@@ -274,20 +310,29 @@ class Utils {
274
310
  optionalNum: 0,
275
311
  isValid: true,
276
312
  };
313
+ const isCopilot = options.projectType === ProjectType.Copilot;
277
314
  if (requestJsonBody) {
278
315
  const requestBodySchema = requestJsonBody.schema;
279
- requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required);
316
+ if (isCopilot && requestBodySchema.type !== "object") {
317
+ return false;
318
+ }
319
+ requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
280
320
  }
281
321
  if (!requestBodyParamResult.isValid) {
282
322
  return false;
283
323
  }
284
- const paramResult = Utils.checkParameters(paramObject);
324
+ const paramResult = Utils.checkParameters(paramObject, isCopilot);
285
325
  if (!paramResult.isValid) {
286
326
  return false;
287
327
  }
328
+ // Copilot support arbitrary parameters
329
+ if (isCopilot) {
330
+ return true;
331
+ }
288
332
  if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
289
- if (allowMultipleParameters &&
290
- requestBodyParamResult.requiredNum + paramResult.requiredNum <= 5) {
333
+ if (options.allowMultipleParameters &&
334
+ requestBodyParamResult.requiredNum + paramResult.requiredNum <=
335
+ ConstantString.SMERequiredParamsMaxNum) {
291
336
  return true;
292
337
  }
293
338
  return false;
@@ -306,27 +351,29 @@ class Utils {
306
351
  }
307
352
  return false;
308
353
  }
309
- static isSupportedAuth(authSchemaArray, allowAPIKeyAuth, allowOauth2) {
354
+ static isSupportedAuth(authSchemaArray, options) {
310
355
  if (authSchemaArray.length === 0) {
311
356
  return true;
312
357
  }
313
- if (allowAPIKeyAuth || allowOauth2) {
358
+ if (options.allowAPIKeyAuth || options.allowOauth2) {
314
359
  // Currently we don't support multiple auth in one operation
315
360
  if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
316
361
  return false;
317
362
  }
318
363
  for (const auths of authSchemaArray) {
319
364
  if (auths.length === 1) {
320
- if (!allowOauth2 && allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authSchema)) {
365
+ if (!options.allowOauth2 &&
366
+ options.allowAPIKeyAuth &&
367
+ Utils.isAPIKeyAuth(auths[0].authSchema)) {
321
368
  return true;
322
369
  }
323
- else if (!allowAPIKeyAuth &&
324
- allowOauth2 &&
370
+ else if (!options.allowAPIKeyAuth &&
371
+ options.allowOauth2 &&
325
372
  Utils.isBearerTokenAuth(auths[0].authSchema)) {
326
373
  return true;
327
374
  }
328
- else if (allowAPIKeyAuth &&
329
- allowOauth2 &&
375
+ else if (options.allowAPIKeyAuth &&
376
+ options.allowOauth2 &&
330
377
  (Utils.isAPIKeyAuth(auths[0].authSchema) ||
331
378
  Utils.isBearerTokenAuth(auths[0].authSchema))) {
332
379
  return true;
@@ -455,7 +502,7 @@ class Utils {
455
502
  }
456
503
  return errors;
457
504
  }
458
- static validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
505
+ static validateServer(spec, options) {
459
506
  const errors = [];
460
507
  let hasTopLevelServers = false;
461
508
  let hasPathLevelServers = false;
@@ -476,7 +523,7 @@ class Utils {
476
523
  }
477
524
  for (const method in methods) {
478
525
  const operationObject = methods[method];
479
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
526
+ if (Utils.isSupportedApi(method, path, spec, options)) {
480
527
  if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
481
528
  hasOperationLevelServers = true;
482
529
  const serverErrors = Utils.checkServerUrl(operationObject.servers);
@@ -563,7 +610,7 @@ class Utils {
563
610
  param.value = schema.default;
564
611
  }
565
612
  }
566
- static parseApiInfo(operationItem, allowMultipleParameters) {
613
+ static parseApiInfo(operationItem, options) {
567
614
  var _a, _b;
568
615
  const requiredParams = [];
569
616
  const optionalParams = [];
@@ -577,7 +624,7 @@ class Utils {
577
624
  description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
578
625
  };
579
626
  const schema = param.schema;
580
- if (allowMultipleParameters && schema) {
627
+ if (options.allowMultipleParameters && schema) {
581
628
  Utils.updateParameterWithInputType(schema, parameter);
582
629
  }
583
630
  if (param.in !== "header" && param.in !== "cookie") {
@@ -595,7 +642,7 @@ class Utils {
595
642
  const requestJson = requestBody.content["application/json"];
596
643
  if (Object.keys(requestJson).length !== 0) {
597
644
  const schema = requestJson.schema;
598
- const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
645
+ const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
599
646
  requiredParams.push(...requiredP);
600
647
  optionalParams.push(...optionalP);
601
648
  }
@@ -626,14 +673,14 @@ class Utils {
626
673
  }
627
674
  return [command, warning];
628
675
  }
629
- static listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
676
+ static listSupportedAPIs(spec, options) {
630
677
  const paths = spec.paths;
631
678
  const result = {};
632
679
  for (const path in paths) {
633
680
  const methods = paths[path];
634
681
  for (const method in methods) {
635
682
  // For developer preview, only support GET operation with only 1 parameter without auth
636
- if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
683
+ if (Utils.isSupportedApi(method, path, spec, options)) {
637
684
  const operationObject = methods[method];
638
685
  result[`${method.toUpperCase()} ${path}`] = operationObject;
639
686
  }
@@ -641,7 +688,7 @@ class Utils {
641
688
  }
642
689
  return result;
643
690
  }
644
- static validateSpec(spec, parser, isSwaggerFile, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2) {
691
+ static validateSpec(spec, parser, isSwaggerFile, options) {
645
692
  const errors = [];
646
693
  const warnings = [];
647
694
  if (isSwaggerFile) {
@@ -651,7 +698,7 @@ class Utils {
651
698
  });
652
699
  }
653
700
  // Server validation
654
- const serverErrors = Utils.validateServer(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
701
+ const serverErrors = Utils.validateServer(spec, options);
655
702
  errors.push(...serverErrors);
656
703
  // Remote reference not supported
657
704
  const refPaths = parser.$refs.paths();
@@ -664,7 +711,7 @@ class Utils {
664
711
  });
665
712
  }
666
713
  // No supported API
667
- const apiMap = Utils.listSupportedAPIs(spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2);
714
+ const apiMap = Utils.listSupportedAPIs(spec, options);
668
715
  if (Object.keys(apiMap).length === 0) {
669
716
  errors.push({
670
717
  type: ErrorType.NoSupportedApi,
@@ -735,6 +782,8 @@ class SpecParser {
735
782
  allowAPIKeyAuth: false,
736
783
  allowMultipleParameters: false,
737
784
  allowOauth2: false,
785
+ allowMethods: ["get", "post"],
786
+ projectType: ProjectType.SME,
738
787
  };
739
788
  this.pathOrSpec = pathOrDoc;
740
789
  this.parser = new SwaggerParser();
@@ -771,7 +820,7 @@ class SpecParser {
771
820
  ],
772
821
  };
773
822
  }
774
- return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
823
+ return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
775
824
  }
776
825
  catch (err) {
777
826
  throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
@@ -790,7 +839,7 @@ class SpecParser {
790
839
  if (!operationId) {
791
840
  continue;
792
841
  }
793
- const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options.allowMultipleParameters);
842
+ const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
794
843
  const apiInfo = {
795
844
  method: method,
796
845
  path: path,
@@ -827,6 +876,17 @@ class SpecParser {
827
876
  async getFilteredSpecs(filter, signal) {
828
877
  throw new Error("Method not implemented.");
829
878
  }
879
+ /**
880
+ * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
881
+ * @param manifestPath A file path of the Teams app manifest file to update.
882
+ * @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
883
+ * @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
884
+ * @param pluginFilePath File path of the api plugin file to generate.
885
+ */
886
+ // eslint-disable-next-line @typescript-eslint/require-await
887
+ async generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
888
+ throw new Error("Method not implemented.");
889
+ }
830
890
  /**
831
891
  * Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
832
892
  * @param manifestPath A file path of the Teams app manifest file to update.
@@ -836,7 +896,7 @@ class SpecParser {
836
896
  * @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
837
897
  */
838
898
  // eslint-disable-next-line @typescript-eslint/require-await
839
- async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal, isMe) {
899
+ async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
840
900
  throw new Error("Method not implemented.");
841
901
  }
842
902
  async loadSpec() {
@@ -853,7 +913,7 @@ class SpecParser {
853
913
  if (this.apiMap !== undefined) {
854
914
  return this.apiMap;
855
915
  }
856
- const result = Utils.listSupportedAPIs(spec, this.options.allowMissingId, this.options.allowAPIKeyAuth, this.options.allowMultipleParameters, this.options.allowOauth2);
916
+ const result = Utils.listSupportedAPIs(spec, this.options);
857
917
  this.apiMap = result;
858
918
  return result;
859
919
  }