@microsoft/m365-spec-parser 0.2.2 → 0.2.3-alpha.2269ef021.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.
@@ -103,6 +103,7 @@ exports.WarningType = void 0;
103
103
  WarningType["OperationOnlyContainsOptionalParam"] = "operation-only-contains-optional-param";
104
104
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
105
105
  WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
106
+ WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
106
107
  WarningType["Unknown"] = "unknown";
107
108
  })(exports.WarningType || (exports.WarningType = {}));
108
109
  /**
@@ -140,6 +141,7 @@ ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converte
140
141
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
141
142
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
142
143
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
144
+ ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
143
145
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
144
146
  ConstantString.FuncDescriptionTooLong = "The description of the function '%s' is too long. The current length is %s characters, while the maximum allowed length is %s characters.";
145
147
  ConstantString.WrappedCardVersion = "devPreview";
@@ -236,16 +238,19 @@ class SpecParserError extends Error {
236
238
  // Copyright (c) Microsoft Corporation.
237
239
  class Utils {
238
240
  static hasNestedObjectInSchema(schema) {
239
- if (schema.type === "object") {
241
+ if (this.isObjectSchema(schema)) {
240
242
  for (const property in schema.properties) {
241
243
  const nestedSchema = schema.properties[property];
242
- if (nestedSchema.type === "object") {
244
+ if (this.isObjectSchema(nestedSchema)) {
243
245
  return true;
244
246
  }
245
247
  }
246
248
  }
247
249
  return false;
248
250
  }
251
+ static isObjectSchema(schema) {
252
+ return schema.type === "object" || (!schema.type && !!schema.properties);
253
+ }
249
254
  static containMultipleMediaTypes(bodyObject) {
250
255
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
251
256
  }
@@ -474,7 +479,7 @@ class Utils {
474
479
  optionalParams.push(parameter);
475
480
  }
476
481
  }
477
- else if (schema.type === "object") {
482
+ else if (Utils.isObjectSchema(schema)) {
478
483
  const { properties } = schema;
479
484
  for (const property in properties) {
480
485
  let isRequired = false;
@@ -588,29 +593,6 @@ class Utils {
588
593
  const serverUrl = operationServer || methodServer || rootServer;
589
594
  return serverUrl;
590
595
  }
591
- static limitACBodyProperties(body, maxCount) {
592
- const result = [];
593
- let currentCount = 0;
594
- for (const element of body) {
595
- if (element.type === ConstantString.ContainerType) {
596
- const items = this.limitACBodyProperties(element.items, maxCount - currentCount);
597
- result.push({
598
- type: ConstantString.ContainerType,
599
- $data: element.$data,
600
- items: items,
601
- });
602
- currentCount += items.length;
603
- }
604
- else {
605
- result.push(element);
606
- currentCount++;
607
- }
608
- if (currentCount >= maxCount) {
609
- break;
610
- }
611
- }
612
- return result;
613
- }
614
596
  }
615
597
 
616
598
  // Copyright (c) Microsoft Corporation.
@@ -812,7 +794,7 @@ class Validator {
812
794
  }
813
795
  const isRequiredWithoutDefault = isRequired && schema.default === undefined;
814
796
  const isCopilot = this.projectType === exports.ProjectType.Copilot;
815
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
797
+ if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
816
798
  paramResult.isValid = false;
817
799
  paramResult.reason = [exports.ErrorType.RequestBodyContainsNestedObject];
818
800
  return paramResult;
@@ -828,7 +810,7 @@ class Validator {
828
810
  paramResult.optionalNum = paramResult.optionalNum + 1;
829
811
  }
830
812
  }
831
- else if (schema.type === "object") {
813
+ else if (Utils.isObjectSchema(schema)) {
832
814
  const { properties } = schema;
833
815
  for (const property in properties) {
834
816
  let isRequired = false;
@@ -864,7 +846,7 @@ class Validator {
864
846
  for (let i = 0; i < paramObject.length; i++) {
865
847
  const param = paramObject[i];
866
848
  const schema = param.schema;
867
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
849
+ if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
868
850
  paramResult.isValid = false;
869
851
  paramResult.reason.push(exports.ErrorType.ParamsContainsNestedObject);
870
852
  continue;
@@ -907,17 +889,6 @@ class Validator {
907
889
  }
908
890
  return paramResult;
909
891
  }
910
- hasNestedObjectInSchema(schema) {
911
- if (schema.type === "object") {
912
- for (const property in schema.properties) {
913
- const nestedSchema = schema.properties[property];
914
- if (nestedSchema.type === "object") {
915
- return true;
916
- }
917
- }
918
- }
919
- return false;
920
- }
921
892
  }
922
893
 
923
894
  // Copyright (c) Microsoft Corporation.
@@ -976,7 +947,7 @@ class CopilotValidator extends Validator {
976
947
  const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
977
948
  if (requestJsonBody) {
978
949
  const requestBodySchema = requestJsonBody.schema;
979
- if (requestBodySchema.type !== "object") {
950
+ if (!Utils.isObjectSchema(requestBodySchema)) {
980
951
  result.reason.push(exports.ErrorType.PostBodySchemaIsNotJson);
981
952
  }
982
953
  const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
@@ -1356,7 +1327,7 @@ class SpecFilter {
1356
1327
 
1357
1328
  // Copyright (c) Microsoft Corporation.
1358
1329
  class AdaptiveCardGenerator {
1359
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1330
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1360
1331
  try {
1361
1332
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1362
1333
  let cardBody = [];
@@ -1367,7 +1338,7 @@ class AdaptiveCardGenerator {
1367
1338
  if (jsonPath !== "$") {
1368
1339
  schema = schema.properties[jsonPath];
1369
1340
  }
1370
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1341
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1371
1342
  }
1372
1343
  // if no schema, try to use example value
1373
1344
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1401,10 +1372,14 @@ class AdaptiveCardGenerator {
1401
1372
  throw new SpecParserError(err.toString(), exports.ErrorType.GenerateAdaptiveCardFailed);
1402
1373
  }
1403
1374
  }
1404
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1375
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1376
+ if (counter.count >= maxElementCount) {
1377
+ return [];
1378
+ }
1405
1379
  if (schema.type === "array") {
1406
1380
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1407
1381
  if (Object.keys(schema.items).length === 0) {
1382
+ counter.count++;
1408
1383
  return [
1409
1384
  {
1410
1385
  type: ConstantString.TextBlockType,
@@ -1413,7 +1388,7 @@ class AdaptiveCardGenerator {
1413
1388
  },
1414
1389
  ];
1415
1390
  }
1416
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1391
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1417
1392
  const template = {
1418
1393
  type: ConstantString.ContainerType,
1419
1394
  $data: name ? `\${${name}}` : "${$root}",
@@ -1423,11 +1398,11 @@ class AdaptiveCardGenerator {
1423
1398
  return [template];
1424
1399
  }
1425
1400
  // some schema may not contain type but contain properties
1426
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1401
+ if (Utils.isObjectSchema(schema)) {
1427
1402
  const { properties } = schema;
1428
1403
  const result = [];
1429
1404
  for (const property in properties) {
1430
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1405
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1431
1406
  result.push(...obj);
1432
1407
  }
1433
1408
  if (schema.additionalProperties) {
@@ -1440,6 +1415,7 @@ class AdaptiveCardGenerator {
1440
1415
  schema.type === "integer" ||
1441
1416
  schema.type === "boolean" ||
1442
1417
  schema.type === "number") {
1418
+ counter.count++;
1443
1419
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1444
1420
  // string in root: "ddd"
1445
1421
  let text = "result: ${$root}";
@@ -1464,24 +1440,17 @@ class AdaptiveCardGenerator {
1464
1440
  ];
1465
1441
  }
1466
1442
  else {
1467
- if (name) {
1468
- return [
1469
- {
1470
- type: "Image",
1471
- url: `\${${name}}`,
1472
- $when: `\${${name} != null && ${name} != ''}`,
1473
- },
1474
- ];
1475
- }
1476
- else {
1477
- return [
1478
- {
1479
- type: "Image",
1480
- url: "${$data}",
1481
- $when: "${$data != null && $data != ''}",
1482
- },
1483
- ];
1484
- }
1443
+ const url = name ? `\${${name}}` : "${$data}";
1444
+ const condition = name
1445
+ ? `\${${name} != null && ${name} != ''}`
1446
+ : "${$data != null && $data != ''}";
1447
+ return [
1448
+ {
1449
+ type: "Image",
1450
+ url,
1451
+ $when: condition,
1452
+ },
1453
+ ];
1485
1454
  }
1486
1455
  }
1487
1456
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1491,7 +1460,7 @@ class AdaptiveCardGenerator {
1491
1460
  }
1492
1461
  // Find the first array property in the response schema object with the well-known name
1493
1462
  static getResponseJsonPathFromSchema(schema) {
1494
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1463
+ if (Utils.isObjectSchema(schema)) {
1495
1464
  const { properties } = schema;
1496
1465
  for (const property in properties) {
1497
1466
  const schema = properties[property];
@@ -1746,7 +1715,7 @@ class ManifestUpdater {
1746
1715
  if (requestBody) {
1747
1716
  const requestJsonBody = requestBody.content["application/json"];
1748
1717
  const requestBodySchema = requestJsonBody.schema;
1749
- if (requestBodySchema.type === "object") {
1718
+ if (Utils.isObjectSchema(requestBodySchema)) {
1750
1719
  for (const property in requestBodySchema.properties) {
1751
1720
  const schema = requestBodySchema.properties[property];
1752
1721
  ManifestUpdater.checkSchema(schema, method, pathUrl);
@@ -1774,8 +1743,7 @@ class ManifestUpdater {
1774
1743
  try {
1775
1744
  const { json } = Utils.getResponseJson(operationItem);
1776
1745
  if (json.schema) {
1777
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem);
1778
- card.body = Utils.limitACBodyProperties(card.body, 5);
1746
+ const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem, false, 5);
1779
1747
  const responseSemantic = wrapResponseSemantics(card, jsonPath);
1780
1748
  funcObj.capabilities = {
1781
1749
  response_semantics: responseSemantic,
@@ -2250,6 +2218,24 @@ class SpecParser {
2250
2218
  const newUnResolvedSpec = newSpecs[0];
2251
2219
  const newSpec = newSpecs[1];
2252
2220
  const authInfo = Utils.getAuthInfo(newSpec);
2221
+ const paths = newUnResolvedSpec.paths;
2222
+ for (const pathUrl in paths) {
2223
+ const operations = paths[pathUrl];
2224
+ for (const method in operations) {
2225
+ const operationItem = operations[method];
2226
+ const operationId = operationItem.operationId;
2227
+ const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
2228
+ if (!containsSpecialCharacters) {
2229
+ continue;
2230
+ }
2231
+ operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
2232
+ result.warnings.push({
2233
+ type: exports.WarningType.OperationIdContainsSpecialCharacters,
2234
+ content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
2235
+ data: operationId,
2236
+ });
2237
+ }
2238
+ }
2253
2239
  yield this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
2254
2240
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
2255
2241
  throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);