@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.
@@ -61,6 +61,8 @@ 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";
65
+ WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
64
66
  WarningType["Unknown"] = "unknown";
65
67
  })(WarningType || (WarningType = {}));
66
68
  /**
@@ -98,8 +100,10 @@ ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converte
98
100
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
99
101
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
100
102
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
103
+ ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
101
104
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
102
105
  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.";
106
+ ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
103
107
  ConstantString.WrappedCardVersion = "devPreview";
104
108
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
105
109
  ConstantString.WrappedCardResponseLayout = "list";
@@ -549,29 +553,6 @@ class Utils {
549
553
  const serverUrl = operationServer || methodServer || rootServer;
550
554
  return serverUrl;
551
555
  }
552
- static limitACBodyProperties(body, maxCount) {
553
- const result = [];
554
- let currentCount = 0;
555
- for (const element of body) {
556
- if (element.type === ConstantString.ContainerType) {
557
- const items = this.limitACBodyProperties(element.items, maxCount - currentCount);
558
- result.push({
559
- type: ConstantString.ContainerType,
560
- $data: element.$data,
561
- items: items,
562
- });
563
- currentCount += items.length;
564
- }
565
- else {
566
- result.push(element);
567
- currentCount++;
568
- }
569
- if (currentCount >= maxCount) {
570
- break;
571
- }
572
- }
573
- return result;
574
- }
575
556
  }
576
557
 
577
558
  // Copyright (c) Microsoft Corporation.
@@ -1306,7 +1287,7 @@ class SpecFilter {
1306
1287
 
1307
1288
  // Copyright (c) Microsoft Corporation.
1308
1289
  class AdaptiveCardGenerator {
1309
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1290
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1310
1291
  try {
1311
1292
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1312
1293
  let cardBody = [];
@@ -1317,7 +1298,7 @@ class AdaptiveCardGenerator {
1317
1298
  if (jsonPath !== "$") {
1318
1299
  schema = schema.properties[jsonPath];
1319
1300
  }
1320
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1301
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1321
1302
  }
1322
1303
  // if no schema, try to use example value
1323
1304
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1351,10 +1332,14 @@ class AdaptiveCardGenerator {
1351
1332
  throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
1352
1333
  }
1353
1334
  }
1354
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1335
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1336
+ if (counter.count >= maxElementCount) {
1337
+ return [];
1338
+ }
1355
1339
  if (schema.type === "array") {
1356
1340
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1357
1341
  if (Object.keys(schema.items).length === 0) {
1342
+ counter.count++;
1358
1343
  return [
1359
1344
  {
1360
1345
  type: ConstantString.TextBlockType,
@@ -1363,7 +1348,7 @@ class AdaptiveCardGenerator {
1363
1348
  },
1364
1349
  ];
1365
1350
  }
1366
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1351
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1367
1352
  const template = {
1368
1353
  type: ConstantString.ContainerType,
1369
1354
  $data: name ? `\${${name}}` : "${$root}",
@@ -1377,7 +1362,7 @@ class AdaptiveCardGenerator {
1377
1362
  const { properties } = schema;
1378
1363
  const result = [];
1379
1364
  for (const property in properties) {
1380
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1365
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1381
1366
  result.push(...obj);
1382
1367
  }
1383
1368
  if (schema.additionalProperties) {
@@ -1390,6 +1375,7 @@ class AdaptiveCardGenerator {
1390
1375
  schema.type === "integer" ||
1391
1376
  schema.type === "boolean" ||
1392
1377
  schema.type === "number") {
1378
+ counter.count++;
1393
1379
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1394
1380
  // string in root: "ddd"
1395
1381
  let text = "result: ${$root}";
@@ -1414,24 +1400,17 @@ class AdaptiveCardGenerator {
1414
1400
  ];
1415
1401
  }
1416
1402
  else {
1417
- if (name) {
1418
- return [
1419
- {
1420
- type: "Image",
1421
- url: `\${${name}}`,
1422
- $when: `\${${name} != null && ${name} != ''}`,
1423
- },
1424
- ];
1425
- }
1426
- else {
1427
- return [
1428
- {
1429
- type: "Image",
1430
- url: "${$data}",
1431
- $when: "${$data != null && $data != ''}",
1432
- },
1433
- ];
1434
- }
1403
+ const url = name ? `\${${name}}` : "${$data}";
1404
+ const condition = name
1405
+ ? `\${${name} != null && ${name} != ''}`
1406
+ : "${$data != null && $data != ''}";
1407
+ return [
1408
+ {
1409
+ type: "Image",
1410
+ url,
1411
+ $when: condition,
1412
+ },
1413
+ ];
1435
1414
  }
1436
1415
  }
1437
1416
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1721,8 +1700,7 @@ class ManifestUpdater {
1721
1700
  try {
1722
1701
  const { json } = Utils.getResponseJson(operationItem);
1723
1702
  if (json.schema) {
1724
- const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem);
1725
- card.body = Utils.limitACBodyProperties(card.body, 5);
1703
+ const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem, false, 5);
1726
1704
  const responseSemantic = wrapResponseSemantics(card, jsonPath);
1727
1705
  funcObj.capabilities = {
1728
1706
  response_semantics: responseSemantic,
@@ -1955,6 +1933,130 @@ class ManifestUpdater {
1955
1933
  }
1956
1934
  }
1957
1935
 
1936
+ // Copyright (c) Microsoft Corporation.
1937
+ class JsonDataGenerator {
1938
+ static generate(schema) {
1939
+ return this.generateMockData(schema);
1940
+ }
1941
+ static generateMockData(schema) {
1942
+ if (this.visitedSchemas.has(schema)) {
1943
+ return null; // Prevent circular reference
1944
+ }
1945
+ this.visitedSchemas.add(schema);
1946
+ let result;
1947
+ if (schema.anyOf) {
1948
+ // Select the first schema in anyOf
1949
+ const selectedSchema = schema.anyOf[0];
1950
+ result = this.generateMockData(selectedSchema);
1951
+ }
1952
+ else if (schema.oneOf) {
1953
+ // Select the first schema in oneOf
1954
+ const selectedSchema = schema.oneOf[0];
1955
+ result = this.generateMockData(selectedSchema);
1956
+ }
1957
+ else if (schema.allOf) {
1958
+ // merge all schemas in allOf
1959
+ result = {};
1960
+ for (const subschema of schema.allOf) {
1961
+ const data = this.generateMockData(subschema);
1962
+ result = Object.assign(Object.assign({}, result), data);
1963
+ }
1964
+ }
1965
+ else {
1966
+ switch (schema.type) {
1967
+ case "string":
1968
+ if (schema.example !== undefined) {
1969
+ result = schema.example;
1970
+ }
1971
+ else if (schema.format) {
1972
+ switch (schema.format) {
1973
+ case "date-time":
1974
+ result = "2024-11-01T05:25:43.593Z";
1975
+ break;
1976
+ case "email":
1977
+ result = "example@example.com";
1978
+ break;
1979
+ case "uuid":
1980
+ result = "123e4567-e89b-12d3-a456-426614174000";
1981
+ break;
1982
+ case "ipv4":
1983
+ result = "192.168.0.1";
1984
+ break;
1985
+ case "ipv6":
1986
+ result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
1987
+ break;
1988
+ default:
1989
+ result = "example string";
1990
+ }
1991
+ }
1992
+ else {
1993
+ result = "example string";
1994
+ }
1995
+ break;
1996
+ case "number":
1997
+ if (schema.example !== undefined) {
1998
+ result = schema.example;
1999
+ }
2000
+ else if (schema.format) {
2001
+ switch (schema.format) {
2002
+ case "float":
2003
+ result = 3.14;
2004
+ break;
2005
+ case "double":
2006
+ result = 3.14159;
2007
+ break;
2008
+ default:
2009
+ result = 123;
2010
+ }
2011
+ }
2012
+ else {
2013
+ result = 123;
2014
+ }
2015
+ break;
2016
+ case "integer":
2017
+ if (schema.example !== undefined) {
2018
+ result = schema.example;
2019
+ }
2020
+ else if (schema.format) {
2021
+ switch (schema.format) {
2022
+ case "int32":
2023
+ result = 123456;
2024
+ break;
2025
+ case "int64":
2026
+ result = 123456789;
2027
+ break;
2028
+ default:
2029
+ result = 123;
2030
+ }
2031
+ }
2032
+ else {
2033
+ result = 123;
2034
+ }
2035
+ break;
2036
+ case "boolean":
2037
+ result = schema.example !== undefined ? schema.example : true;
2038
+ break;
2039
+ case "array":
2040
+ result = [this.generateMockData(schema.items)];
2041
+ break;
2042
+ case "object":
2043
+ result = {};
2044
+ if (schema.properties) {
2045
+ for (const key in schema.properties) {
2046
+ result[key] = this.generateMockData(schema.properties[key]);
2047
+ }
2048
+ }
2049
+ break;
2050
+ default:
2051
+ result = schema.example || null;
2052
+ }
2053
+ }
2054
+ this.visitedSchemas.delete(schema);
2055
+ return result;
2056
+ }
2057
+ }
2058
+ JsonDataGenerator.visitedSchemas = new Set();
2059
+
1958
2060
  // Copyright (c) Microsoft Corporation.
1959
2061
  /**
1960
2062
  * A class that parses an OpenAPI specification file and provides methods to validate, list, and generate artifacts.
@@ -2183,6 +2285,24 @@ class SpecParser {
2183
2285
  const newUnResolvedSpec = newSpecs[0];
2184
2286
  const newSpec = newSpecs[1];
2185
2287
  const authInfo = Utils.getAuthInfo(newSpec);
2288
+ const paths = newUnResolvedSpec.paths;
2289
+ for (const pathUrl in paths) {
2290
+ const operations = paths[pathUrl];
2291
+ for (const method in operations) {
2292
+ const operationItem = operations[method];
2293
+ const operationId = operationItem.operationId;
2294
+ const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
2295
+ if (!containsSpecialCharacters) {
2296
+ continue;
2297
+ }
2298
+ operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
2299
+ result.warnings.push({
2300
+ type: WarningType.OperationIdContainsSpecialCharacters,
2301
+ content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
2302
+ data: operationId,
2303
+ });
2304
+ }
2305
+ }
2186
2306
  await this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
2187
2307
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
2188
2308
  throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
@@ -2238,9 +2358,24 @@ class SpecParser {
2238
2358
  const safeAdaptiveCardName = operation.operationId.replace(/[^a-zA-Z0-9]/g, "_");
2239
2359
  const fileName = path.join(adaptiveCardFolder, `${safeAdaptiveCardName}.json`);
2240
2360
  const wrappedCard = wrapAdaptiveCard(card, jsonPath);
2361
+ const { json } = Utils.getResponseJson(operation, false);
2362
+ const schema = json.schema;
2363
+ let jsonData = {};
2364
+ if (schema && Object.keys(schema).length > 0) {
2365
+ try {
2366
+ jsonData = JsonDataGenerator.generate(schema);
2367
+ }
2368
+ catch (err) {
2369
+ result.warnings.push({
2370
+ type: WarningType.GenerateJsonDataFailed,
2371
+ content: Utils.format(ConstantString.GenerateJsonDataFailed, operation.operationId, err.toString()),
2372
+ data: operation.operationId,
2373
+ });
2374
+ }
2375
+ }
2241
2376
  await fs.outputJSON(fileName, wrappedCard, { spaces: 2 });
2242
2377
  const dataFileName = path.join(adaptiveCardFolder, `${safeAdaptiveCardName}.data.json`);
2243
- await fs.outputJSON(dataFileName, {}, { spaces: 2 });
2378
+ await fs.outputJSON(dataFileName, jsonData, { spaces: 2 });
2244
2379
  }
2245
2380
  catch (err) {
2246
2381
  result.allSuccess = false;