@microsoft/m365-spec-parser 0.2.3-alpha.9432e5ed4.0 → 0.2.3-alpha.9aa2f037e.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,8 @@ 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";
107
+ WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
106
108
  WarningType["Unknown"] = "unknown";
107
109
  })(exports.WarningType || (exports.WarningType = {}));
108
110
  /**
@@ -140,8 +142,10 @@ ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converte
140
142
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
141
143
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
142
144
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
145
+ ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
143
146
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
144
147
  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.";
148
+ ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
145
149
  ConstantString.WrappedCardVersion = "devPreview";
146
150
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
147
151
  ConstantString.WrappedCardResponseLayout = "list";
@@ -591,29 +595,6 @@ class Utils {
591
595
  const serverUrl = operationServer || methodServer || rootServer;
592
596
  return serverUrl;
593
597
  }
594
- static limitACBodyProperties(body, maxCount) {
595
- const result = [];
596
- let currentCount = 0;
597
- for (const element of body) {
598
- if (element.type === ConstantString.ContainerType) {
599
- const items = this.limitACBodyProperties(element.items, maxCount - currentCount);
600
- result.push({
601
- type: ConstantString.ContainerType,
602
- $data: element.$data,
603
- items: items,
604
- });
605
- currentCount += items.length;
606
- }
607
- else {
608
- result.push(element);
609
- currentCount++;
610
- }
611
- if (currentCount >= maxCount) {
612
- break;
613
- }
614
- }
615
- return result;
616
- }
617
598
  }
618
599
 
619
600
  // Copyright (c) Microsoft Corporation.
@@ -1348,7 +1329,7 @@ class SpecFilter {
1348
1329
 
1349
1330
  // Copyright (c) Microsoft Corporation.
1350
1331
  class AdaptiveCardGenerator {
1351
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1332
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1352
1333
  try {
1353
1334
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1354
1335
  let cardBody = [];
@@ -1359,7 +1340,7 @@ class AdaptiveCardGenerator {
1359
1340
  if (jsonPath !== "$") {
1360
1341
  schema = schema.properties[jsonPath];
1361
1342
  }
1362
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1343
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1363
1344
  }
1364
1345
  // if no schema, try to use example value
1365
1346
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1393,10 +1374,14 @@ class AdaptiveCardGenerator {
1393
1374
  throw new SpecParserError(err.toString(), exports.ErrorType.GenerateAdaptiveCardFailed);
1394
1375
  }
1395
1376
  }
1396
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1377
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1378
+ if (counter.count >= maxElementCount) {
1379
+ return [];
1380
+ }
1397
1381
  if (schema.type === "array") {
1398
1382
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1399
1383
  if (Object.keys(schema.items).length === 0) {
1384
+ counter.count++;
1400
1385
  return [
1401
1386
  {
1402
1387
  type: ConstantString.TextBlockType,
@@ -1405,7 +1390,7 @@ class AdaptiveCardGenerator {
1405
1390
  },
1406
1391
  ];
1407
1392
  }
1408
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1393
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1409
1394
  const template = {
1410
1395
  type: ConstantString.ContainerType,
1411
1396
  $data: name ? `\${${name}}` : "${$root}",
@@ -1419,7 +1404,7 @@ class AdaptiveCardGenerator {
1419
1404
  const { properties } = schema;
1420
1405
  const result = [];
1421
1406
  for (const property in properties) {
1422
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1407
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1423
1408
  result.push(...obj);
1424
1409
  }
1425
1410
  if (schema.additionalProperties) {
@@ -1432,6 +1417,7 @@ class AdaptiveCardGenerator {
1432
1417
  schema.type === "integer" ||
1433
1418
  schema.type === "boolean" ||
1434
1419
  schema.type === "number") {
1420
+ counter.count++;
1435
1421
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1436
1422
  // string in root: "ddd"
1437
1423
  let text = "result: ${$root}";
@@ -1456,24 +1442,17 @@ class AdaptiveCardGenerator {
1456
1442
  ];
1457
1443
  }
1458
1444
  else {
1459
- if (name) {
1460
- return [
1461
- {
1462
- type: "Image",
1463
- url: `\${${name}}`,
1464
- $when: `\${${name} != null && ${name} != ''}`,
1465
- },
1466
- ];
1467
- }
1468
- else {
1469
- return [
1470
- {
1471
- type: "Image",
1472
- url: "${$data}",
1473
- $when: "${$data != null && $data != ''}",
1474
- },
1475
- ];
1476
- }
1445
+ const url = name ? `\${${name}}` : "${$data}";
1446
+ const condition = name
1447
+ ? `\${${name} != null && ${name} != ''}`
1448
+ : "${$data != null && $data != ''}";
1449
+ return [
1450
+ {
1451
+ type: "Image",
1452
+ url,
1453
+ $when: condition,
1454
+ },
1455
+ ];
1477
1456
  }
1478
1457
  }
1479
1458
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1766,8 +1745,7 @@ class ManifestUpdater {
1766
1745
  try {
1767
1746
  const { json } = Utils.getResponseJson(operationItem);
1768
1747
  if (json.schema) {
1769
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem);
1770
- card.body = Utils.limitACBodyProperties(card.body, 5);
1748
+ const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem, false, 5);
1771
1749
  const responseSemantic = wrapResponseSemantics(card, jsonPath);
1772
1750
  funcObj.capabilities = {
1773
1751
  response_semantics: responseSemantic,
@@ -2005,6 +1983,130 @@ class ManifestUpdater {
2005
1983
  }
2006
1984
  }
2007
1985
 
1986
+ // Copyright (c) Microsoft Corporation.
1987
+ class JsonDataGenerator {
1988
+ static generate(schema) {
1989
+ return this.generateMockData(schema);
1990
+ }
1991
+ static generateMockData(schema) {
1992
+ if (this.visitedSchemas.has(schema)) {
1993
+ return null; // Prevent circular reference
1994
+ }
1995
+ this.visitedSchemas.add(schema);
1996
+ let result;
1997
+ if (schema.anyOf) {
1998
+ // Select the first schema in anyOf
1999
+ const selectedSchema = schema.anyOf[0];
2000
+ result = this.generateMockData(selectedSchema);
2001
+ }
2002
+ else if (schema.oneOf) {
2003
+ // Select the first schema in oneOf
2004
+ const selectedSchema = schema.oneOf[0];
2005
+ result = this.generateMockData(selectedSchema);
2006
+ }
2007
+ else if (schema.allOf) {
2008
+ // merge all schemas in allOf
2009
+ result = {};
2010
+ for (const subschema of schema.allOf) {
2011
+ const data = this.generateMockData(subschema);
2012
+ result = Object.assign(Object.assign({}, result), data);
2013
+ }
2014
+ }
2015
+ else {
2016
+ switch (schema.type) {
2017
+ case "string":
2018
+ if (schema.example !== undefined) {
2019
+ result = schema.example;
2020
+ }
2021
+ else if (schema.format) {
2022
+ switch (schema.format) {
2023
+ case "date-time":
2024
+ result = "2024-11-01T05:25:43.593Z";
2025
+ break;
2026
+ case "email":
2027
+ result = "example@example.com";
2028
+ break;
2029
+ case "uuid":
2030
+ result = "123e4567-e89b-12d3-a456-426614174000";
2031
+ break;
2032
+ case "ipv4":
2033
+ result = "192.168.0.1";
2034
+ break;
2035
+ case "ipv6":
2036
+ result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
2037
+ break;
2038
+ default:
2039
+ result = "example string";
2040
+ }
2041
+ }
2042
+ else {
2043
+ result = "example string";
2044
+ }
2045
+ break;
2046
+ case "number":
2047
+ if (schema.example !== undefined) {
2048
+ result = schema.example;
2049
+ }
2050
+ else if (schema.format) {
2051
+ switch (schema.format) {
2052
+ case "float":
2053
+ result = 3.14;
2054
+ break;
2055
+ case "double":
2056
+ result = 3.14159;
2057
+ break;
2058
+ default:
2059
+ result = 123;
2060
+ }
2061
+ }
2062
+ else {
2063
+ result = 123;
2064
+ }
2065
+ break;
2066
+ case "integer":
2067
+ if (schema.example !== undefined) {
2068
+ result = schema.example;
2069
+ }
2070
+ else if (schema.format) {
2071
+ switch (schema.format) {
2072
+ case "int32":
2073
+ result = 123456;
2074
+ break;
2075
+ case "int64":
2076
+ result = 123456789;
2077
+ break;
2078
+ default:
2079
+ result = 123;
2080
+ }
2081
+ }
2082
+ else {
2083
+ result = 123;
2084
+ }
2085
+ break;
2086
+ case "boolean":
2087
+ result = schema.example !== undefined ? schema.example : true;
2088
+ break;
2089
+ case "array":
2090
+ result = [this.generateMockData(schema.items)];
2091
+ break;
2092
+ case "object":
2093
+ result = {};
2094
+ if (schema.properties) {
2095
+ for (const key in schema.properties) {
2096
+ result[key] = this.generateMockData(schema.properties[key]);
2097
+ }
2098
+ }
2099
+ break;
2100
+ default:
2101
+ result = schema.example || null;
2102
+ }
2103
+ }
2104
+ this.visitedSchemas.delete(schema);
2105
+ return result;
2106
+ }
2107
+ }
2108
+ JsonDataGenerator.visitedSchemas = new Set();
2109
+
2008
2110
  // Copyright (c) Microsoft Corporation.
2009
2111
  /**
2010
2112
  * A class that parses an OpenAPI specification file and provides methods to validate, list, and generate artifacts.
@@ -2242,6 +2344,24 @@ class SpecParser {
2242
2344
  const newUnResolvedSpec = newSpecs[0];
2243
2345
  const newSpec = newSpecs[1];
2244
2346
  const authInfo = Utils.getAuthInfo(newSpec);
2347
+ const paths = newUnResolvedSpec.paths;
2348
+ for (const pathUrl in paths) {
2349
+ const operations = paths[pathUrl];
2350
+ for (const method in operations) {
2351
+ const operationItem = operations[method];
2352
+ const operationId = operationItem.operationId;
2353
+ const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
2354
+ if (!containsSpecialCharacters) {
2355
+ continue;
2356
+ }
2357
+ operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
2358
+ result.warnings.push({
2359
+ type: exports.WarningType.OperationIdContainsSpecialCharacters,
2360
+ content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
2361
+ data: operationId,
2362
+ });
2363
+ }
2364
+ }
2245
2365
  yield this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
2246
2366
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
2247
2367
  throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
@@ -2299,9 +2419,24 @@ class SpecParser {
2299
2419
  const safeAdaptiveCardName = operation.operationId.replace(/[^a-zA-Z0-9]/g, "_");
2300
2420
  const fileName = path__default['default'].join(adaptiveCardFolder, `${safeAdaptiveCardName}.json`);
2301
2421
  const wrappedCard = wrapAdaptiveCard(card, jsonPath);
2422
+ const { json } = Utils.getResponseJson(operation, false);
2423
+ const schema = json.schema;
2424
+ let jsonData = {};
2425
+ if (schema && Object.keys(schema).length > 0) {
2426
+ try {
2427
+ jsonData = JsonDataGenerator.generate(schema);
2428
+ }
2429
+ catch (err) {
2430
+ result.warnings.push({
2431
+ type: exports.WarningType.GenerateJsonDataFailed,
2432
+ content: Utils.format(ConstantString.GenerateJsonDataFailed, operation.operationId, err.toString()),
2433
+ data: operation.operationId,
2434
+ });
2435
+ }
2436
+ }
2302
2437
  yield fs__default['default'].outputJSON(fileName, wrappedCard, { spaces: 2 });
2303
2438
  const dataFileName = path__default['default'].join(adaptiveCardFolder, `${safeAdaptiveCardName}.data.json`);
2304
- yield fs__default['default'].outputJSON(dataFileName, {}, { spaces: 2 });
2439
+ yield fs__default['default'].outputJSON(dataFileName, jsonData, { spaces: 2 });
2305
2440
  }
2306
2441
  catch (err) {
2307
2442
  result.allSuccess = false;