@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.
@@ -61,6 +61,7 @@ var WarningType;
61
61
  WarningType["OperationOnlyContainsOptionalParam"] = "operation-only-contains-optional-param";
62
62
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
63
63
  WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
64
+ WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
64
65
  WarningType["Unknown"] = "unknown";
65
66
  })(WarningType || (WarningType = {}));
66
67
  /**
@@ -98,6 +99,7 @@ ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converte
98
99
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
99
100
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
100
101
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
102
+ ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
101
103
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
102
104
  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.";
103
105
  ConstantString.WrappedCardVersion = "devPreview";
@@ -194,16 +196,19 @@ class SpecParserError extends Error {
194
196
  // Copyright (c) Microsoft Corporation.
195
197
  class Utils {
196
198
  static hasNestedObjectInSchema(schema) {
197
- if (schema.type === "object") {
199
+ if (this.isObjectSchema(schema)) {
198
200
  for (const property in schema.properties) {
199
201
  const nestedSchema = schema.properties[property];
200
- if (nestedSchema.type === "object") {
202
+ if (this.isObjectSchema(nestedSchema)) {
201
203
  return true;
202
204
  }
203
205
  }
204
206
  }
205
207
  return false;
206
208
  }
209
+ static isObjectSchema(schema) {
210
+ return schema.type === "object" || (!schema.type && !!schema.properties);
211
+ }
207
212
  static containMultipleMediaTypes(bodyObject) {
208
213
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
209
214
  }
@@ -432,7 +437,7 @@ class Utils {
432
437
  optionalParams.push(parameter);
433
438
  }
434
439
  }
435
- else if (schema.type === "object") {
440
+ else if (Utils.isObjectSchema(schema)) {
436
441
  const { properties } = schema;
437
442
  for (const property in properties) {
438
443
  let isRequired = false;
@@ -546,29 +551,6 @@ class Utils {
546
551
  const serverUrl = operationServer || methodServer || rootServer;
547
552
  return serverUrl;
548
553
  }
549
- static limitACBodyProperties(body, maxCount) {
550
- const result = [];
551
- let currentCount = 0;
552
- for (const element of body) {
553
- if (element.type === ConstantString.ContainerType) {
554
- const items = this.limitACBodyProperties(element.items, maxCount - currentCount);
555
- result.push({
556
- type: ConstantString.ContainerType,
557
- $data: element.$data,
558
- items: items,
559
- });
560
- currentCount += items.length;
561
- }
562
- else {
563
- result.push(element);
564
- currentCount++;
565
- }
566
- if (currentCount >= maxCount) {
567
- break;
568
- }
569
- }
570
- return result;
571
- }
572
554
  }
573
555
 
574
556
  // Copyright (c) Microsoft Corporation.
@@ -770,7 +752,7 @@ class Validator {
770
752
  }
771
753
  const isRequiredWithoutDefault = isRequired && schema.default === undefined;
772
754
  const isCopilot = this.projectType === ProjectType.Copilot;
773
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
755
+ if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
774
756
  paramResult.isValid = false;
775
757
  paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
776
758
  return paramResult;
@@ -786,7 +768,7 @@ class Validator {
786
768
  paramResult.optionalNum = paramResult.optionalNum + 1;
787
769
  }
788
770
  }
789
- else if (schema.type === "object") {
771
+ else if (Utils.isObjectSchema(schema)) {
790
772
  const { properties } = schema;
791
773
  for (const property in properties) {
792
774
  let isRequired = false;
@@ -822,7 +804,7 @@ class Validator {
822
804
  for (let i = 0; i < paramObject.length; i++) {
823
805
  const param = paramObject[i];
824
806
  const schema = param.schema;
825
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
807
+ if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
826
808
  paramResult.isValid = false;
827
809
  paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
828
810
  continue;
@@ -865,17 +847,6 @@ class Validator {
865
847
  }
866
848
  return paramResult;
867
849
  }
868
- hasNestedObjectInSchema(schema) {
869
- if (schema.type === "object") {
870
- for (const property in schema.properties) {
871
- const nestedSchema = schema.properties[property];
872
- if (nestedSchema.type === "object") {
873
- return true;
874
- }
875
- }
876
- }
877
- return false;
878
- }
879
850
  }
880
851
 
881
852
  // Copyright (c) Microsoft Corporation.
@@ -934,7 +905,7 @@ class CopilotValidator extends Validator {
934
905
  const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
935
906
  if (requestJsonBody) {
936
907
  const requestBodySchema = requestJsonBody.schema;
937
- if (requestBodySchema.type !== "object") {
908
+ if (!Utils.isObjectSchema(requestBodySchema)) {
938
909
  result.reason.push(ErrorType.PostBodySchemaIsNotJson);
939
910
  }
940
911
  const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
@@ -1314,7 +1285,7 @@ class SpecFilter {
1314
1285
 
1315
1286
  // Copyright (c) Microsoft Corporation.
1316
1287
  class AdaptiveCardGenerator {
1317
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1288
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1318
1289
  try {
1319
1290
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1320
1291
  let cardBody = [];
@@ -1325,7 +1296,7 @@ class AdaptiveCardGenerator {
1325
1296
  if (jsonPath !== "$") {
1326
1297
  schema = schema.properties[jsonPath];
1327
1298
  }
1328
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1299
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1329
1300
  }
1330
1301
  // if no schema, try to use example value
1331
1302
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1359,10 +1330,14 @@ class AdaptiveCardGenerator {
1359
1330
  throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
1360
1331
  }
1361
1332
  }
1362
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1333
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1334
+ if (counter.count >= maxElementCount) {
1335
+ return [];
1336
+ }
1363
1337
  if (schema.type === "array") {
1364
1338
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1365
1339
  if (Object.keys(schema.items).length === 0) {
1340
+ counter.count++;
1366
1341
  return [
1367
1342
  {
1368
1343
  type: ConstantString.TextBlockType,
@@ -1371,7 +1346,7 @@ class AdaptiveCardGenerator {
1371
1346
  },
1372
1347
  ];
1373
1348
  }
1374
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1349
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1375
1350
  const template = {
1376
1351
  type: ConstantString.ContainerType,
1377
1352
  $data: name ? `\${${name}}` : "${$root}",
@@ -1381,11 +1356,11 @@ class AdaptiveCardGenerator {
1381
1356
  return [template];
1382
1357
  }
1383
1358
  // some schema may not contain type but contain properties
1384
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1359
+ if (Utils.isObjectSchema(schema)) {
1385
1360
  const { properties } = schema;
1386
1361
  const result = [];
1387
1362
  for (const property in properties) {
1388
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1363
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1389
1364
  result.push(...obj);
1390
1365
  }
1391
1366
  if (schema.additionalProperties) {
@@ -1398,6 +1373,7 @@ class AdaptiveCardGenerator {
1398
1373
  schema.type === "integer" ||
1399
1374
  schema.type === "boolean" ||
1400
1375
  schema.type === "number") {
1376
+ counter.count++;
1401
1377
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1402
1378
  // string in root: "ddd"
1403
1379
  let text = "result: ${$root}";
@@ -1422,24 +1398,17 @@ class AdaptiveCardGenerator {
1422
1398
  ];
1423
1399
  }
1424
1400
  else {
1425
- if (name) {
1426
- return [
1427
- {
1428
- type: "Image",
1429
- url: `\${${name}}`,
1430
- $when: `\${${name} != null && ${name} != ''}`,
1431
- },
1432
- ];
1433
- }
1434
- else {
1435
- return [
1436
- {
1437
- type: "Image",
1438
- url: "${$data}",
1439
- $when: "${$data != null && $data != ''}",
1440
- },
1441
- ];
1442
- }
1401
+ const url = name ? `\${${name}}` : "${$data}";
1402
+ const condition = name
1403
+ ? `\${${name} != null && ${name} != ''}`
1404
+ : "${$data != null && $data != ''}";
1405
+ return [
1406
+ {
1407
+ type: "Image",
1408
+ url,
1409
+ $when: condition,
1410
+ },
1411
+ ];
1443
1412
  }
1444
1413
  }
1445
1414
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1449,7 +1418,7 @@ class AdaptiveCardGenerator {
1449
1418
  }
1450
1419
  // Find the first array property in the response schema object with the well-known name
1451
1420
  static getResponseJsonPathFromSchema(schema) {
1452
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1421
+ if (Utils.isObjectSchema(schema)) {
1453
1422
  const { properties } = schema;
1454
1423
  for (const property in properties) {
1455
1424
  const schema = properties[property];
@@ -1701,7 +1670,7 @@ class ManifestUpdater {
1701
1670
  if (requestBody) {
1702
1671
  const requestJsonBody = requestBody.content["application/json"];
1703
1672
  const requestBodySchema = requestJsonBody.schema;
1704
- if (requestBodySchema.type === "object") {
1673
+ if (Utils.isObjectSchema(requestBodySchema)) {
1705
1674
  for (const property in requestBodySchema.properties) {
1706
1675
  const schema = requestBodySchema.properties[property];
1707
1676
  ManifestUpdater.checkSchema(schema, method, pathUrl);
@@ -1729,8 +1698,7 @@ class ManifestUpdater {
1729
1698
  try {
1730
1699
  const { json } = Utils.getResponseJson(operationItem);
1731
1700
  if (json.schema) {
1732
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem);
1733
- card.body = Utils.limitACBodyProperties(card.body, 5);
1701
+ const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem, false, 5);
1734
1702
  const responseSemantic = wrapResponseSemantics(card, jsonPath);
1735
1703
  funcObj.capabilities = {
1736
1704
  response_semantics: responseSemantic,
@@ -2191,6 +2159,24 @@ class SpecParser {
2191
2159
  const newUnResolvedSpec = newSpecs[0];
2192
2160
  const newSpec = newSpecs[1];
2193
2161
  const authInfo = Utils.getAuthInfo(newSpec);
2162
+ const paths = newUnResolvedSpec.paths;
2163
+ for (const pathUrl in paths) {
2164
+ const operations = paths[pathUrl];
2165
+ for (const method in operations) {
2166
+ const operationItem = operations[method];
2167
+ const operationId = operationItem.operationId;
2168
+ const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
2169
+ if (!containsSpecialCharacters) {
2170
+ continue;
2171
+ }
2172
+ operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
2173
+ result.warnings.push({
2174
+ type: WarningType.OperationIdContainsSpecialCharacters,
2175
+ content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
2176
+ data: operationId,
2177
+ });
2178
+ }
2179
+ }
2194
2180
  await this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
2195
2181
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
2196
2182
  throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);