@microsoft/m365-spec-parser 0.2.2 → 0.2.3-alpha.07f6df81c.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.
@@ -55,6 +55,8 @@ var WarningType;
55
55
  WarningType["OperationOnlyContainsOptionalParam"] = "operation-only-contains-optional-param";
56
56
  WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
57
57
  WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
58
+ WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
59
+ WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
58
60
  WarningType["Unknown"] = "unknown";
59
61
  })(WarningType || (WarningType = {}));
60
62
  /**
@@ -100,8 +102,10 @@ ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converte
100
102
  ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
101
103
  ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
102
104
  ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
105
+ ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
103
106
  ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
104
107
  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.";
108
+ ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
105
109
  ConstantString.WrappedCardVersion = "devPreview";
106
110
  ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
107
111
  ConstantString.WrappedCardResponseLayout = "list";
@@ -188,16 +192,19 @@ ConstantString.PluginManifestSchema = "https://developer.microsoft.com/json-sche
188
192
  // Copyright (c) Microsoft Corporation.
189
193
  class Utils {
190
194
  static hasNestedObjectInSchema(schema) {
191
- if (schema.type === "object") {
195
+ if (this.isObjectSchema(schema)) {
192
196
  for (const property in schema.properties) {
193
197
  const nestedSchema = schema.properties[property];
194
- if (nestedSchema.type === "object") {
198
+ if (this.isObjectSchema(nestedSchema)) {
195
199
  return true;
196
200
  }
197
201
  }
198
202
  }
199
203
  return false;
200
204
  }
205
+ static isObjectSchema(schema) {
206
+ return schema.type === "object" || (!schema.type && !!schema.properties);
207
+ }
201
208
  static containMultipleMediaTypes(bodyObject) {
202
209
  return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
203
210
  }
@@ -426,7 +433,7 @@ class Utils {
426
433
  optionalParams.push(parameter);
427
434
  }
428
435
  }
429
- else if (schema.type === "object") {
436
+ else if (Utils.isObjectSchema(schema)) {
430
437
  const { properties } = schema;
431
438
  for (const property in properties) {
432
439
  let isRequired = false;
@@ -540,29 +547,6 @@ class Utils {
540
547
  const serverUrl = operationServer || methodServer || rootServer;
541
548
  return serverUrl;
542
549
  }
543
- static limitACBodyProperties(body, maxCount) {
544
- const result = [];
545
- let currentCount = 0;
546
- for (const element of body) {
547
- if (element.type === ConstantString.ContainerType) {
548
- const items = this.limitACBodyProperties(element.items, maxCount - currentCount);
549
- result.push({
550
- type: ConstantString.ContainerType,
551
- $data: element.$data,
552
- items: items,
553
- });
554
- currentCount += items.length;
555
- }
556
- else {
557
- result.push(element);
558
- currentCount++;
559
- }
560
- if (currentCount >= maxCount) {
561
- break;
562
- }
563
- }
564
- return result;
565
- }
566
550
  }
567
551
 
568
552
  // Copyright (c) Microsoft Corporation.
@@ -764,7 +748,7 @@ class Validator {
764
748
  }
765
749
  const isRequiredWithoutDefault = isRequired && schema.default === undefined;
766
750
  const isCopilot = this.projectType === ProjectType.Copilot;
767
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
751
+ if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
768
752
  paramResult.isValid = false;
769
753
  paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
770
754
  return paramResult;
@@ -780,7 +764,7 @@ class Validator {
780
764
  paramResult.optionalNum = paramResult.optionalNum + 1;
781
765
  }
782
766
  }
783
- else if (schema.type === "object") {
767
+ else if (Utils.isObjectSchema(schema)) {
784
768
  const { properties } = schema;
785
769
  for (const property in properties) {
786
770
  let isRequired = false;
@@ -816,7 +800,7 @@ class Validator {
816
800
  for (let i = 0; i < paramObject.length; i++) {
817
801
  const param = paramObject[i];
818
802
  const schema = param.schema;
819
- if (isCopilot && this.hasNestedObjectInSchema(schema)) {
803
+ if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
820
804
  paramResult.isValid = false;
821
805
  paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
822
806
  continue;
@@ -859,17 +843,6 @@ class Validator {
859
843
  }
860
844
  return paramResult;
861
845
  }
862
- hasNestedObjectInSchema(schema) {
863
- if (schema.type === "object") {
864
- for (const property in schema.properties) {
865
- const nestedSchema = schema.properties[property];
866
- if (nestedSchema.type === "object") {
867
- return true;
868
- }
869
- }
870
- }
871
- return false;
872
- }
873
846
  }
874
847
 
875
848
  // Copyright (c) Microsoft Corporation.
@@ -928,7 +901,7 @@ class CopilotValidator extends Validator {
928
901
  const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
929
902
  if (requestJsonBody) {
930
903
  const requestBodySchema = requestJsonBody.schema;
931
- if (requestBodySchema.type !== "object") {
904
+ if (!Utils.isObjectSchema(requestBodySchema)) {
932
905
  result.reason.push(ErrorType.PostBodySchemaIsNotJson);
933
906
  }
934
907
  const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
@@ -1304,20 +1277,157 @@ class SpecParser {
1304
1277
  }
1305
1278
  }
1306
1279
 
1280
+ // Copyright (c) Microsoft Corporation.
1281
+ class JsonDataGenerator {
1282
+ static generate(schema) {
1283
+ return this.generateMockData(schema);
1284
+ }
1285
+ static generateMockData(schema) {
1286
+ if (this.visitedSchemas.has(schema)) {
1287
+ return null; // Prevent circular reference
1288
+ }
1289
+ this.visitedSchemas.add(schema);
1290
+ let result;
1291
+ if (schema.anyOf) {
1292
+ // Select the first schema in anyOf
1293
+ const selectedSchema = schema.anyOf[0];
1294
+ result = this.generateMockData(selectedSchema);
1295
+ }
1296
+ else if (schema.oneOf) {
1297
+ // Select the first schema in oneOf
1298
+ const selectedSchema = schema.oneOf[0];
1299
+ result = this.generateMockData(selectedSchema);
1300
+ }
1301
+ else if (schema.allOf) {
1302
+ // merge all schemas in allOf
1303
+ result = {};
1304
+ for (const subschema of schema.allOf) {
1305
+ const data = this.generateMockData(subschema);
1306
+ result = Object.assign(Object.assign({}, result), data);
1307
+ }
1308
+ }
1309
+ else {
1310
+ switch (schema.type) {
1311
+ case "string":
1312
+ if (schema.example !== undefined) {
1313
+ result = schema.example;
1314
+ }
1315
+ else if (schema.format) {
1316
+ switch (schema.format) {
1317
+ case "date-time":
1318
+ result = "2024-11-01T05:25:43.593Z";
1319
+ break;
1320
+ case "email":
1321
+ result = "example@example.com";
1322
+ break;
1323
+ case "uuid":
1324
+ result = "123e4567-e89b-12d3-a456-426614174000";
1325
+ break;
1326
+ case "ipv4":
1327
+ result = "192.168.0.1";
1328
+ break;
1329
+ case "ipv6":
1330
+ result = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
1331
+ break;
1332
+ default:
1333
+ result = "example string";
1334
+ }
1335
+ }
1336
+ else {
1337
+ result = "example string";
1338
+ }
1339
+ break;
1340
+ case "number":
1341
+ if (schema.example !== undefined) {
1342
+ result = schema.example;
1343
+ }
1344
+ else if (schema.format) {
1345
+ switch (schema.format) {
1346
+ case "float":
1347
+ result = 3.14;
1348
+ break;
1349
+ case "double":
1350
+ result = 3.14159;
1351
+ break;
1352
+ default:
1353
+ result = 123;
1354
+ }
1355
+ }
1356
+ else {
1357
+ result = 123;
1358
+ }
1359
+ break;
1360
+ case "integer":
1361
+ if (schema.example !== undefined) {
1362
+ result = schema.example;
1363
+ }
1364
+ else if (schema.format) {
1365
+ switch (schema.format) {
1366
+ case "int32":
1367
+ result = 123456;
1368
+ break;
1369
+ case "int64":
1370
+ result = 123456789;
1371
+ break;
1372
+ default:
1373
+ result = 123;
1374
+ }
1375
+ }
1376
+ else {
1377
+ result = 123;
1378
+ }
1379
+ break;
1380
+ case "boolean":
1381
+ result = schema.example !== undefined ? schema.example : true;
1382
+ break;
1383
+ case "array":
1384
+ result = [this.generateMockData(schema.items)];
1385
+ break;
1386
+ case "object":
1387
+ result = {};
1388
+ if (schema.properties) {
1389
+ for (const key in schema.properties) {
1390
+ result[key] = this.generateMockData(schema.properties[key]);
1391
+ }
1392
+ }
1393
+ break;
1394
+ default:
1395
+ result = schema.example || null;
1396
+ }
1397
+ }
1398
+ this.visitedSchemas.delete(schema);
1399
+ return result;
1400
+ }
1401
+ }
1402
+ JsonDataGenerator.visitedSchemas = new Set();
1403
+
1307
1404
  // Copyright (c) Microsoft Corporation.
1308
1405
  class AdaptiveCardGenerator {
1309
- static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
1406
+ static generateAdaptiveCard(operationItem, allowMultipleMediaType = false, maxElementCount = Number.MAX_SAFE_INTEGER) {
1310
1407
  try {
1311
1408
  const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
1312
1409
  let cardBody = [];
1410
+ let jsonData = {};
1411
+ const warnings = [];
1412
+ const operationId = operationItem.operationId;
1313
1413
  let schema = json.schema;
1314
1414
  let jsonPath = "$";
1315
1415
  if (schema && Object.keys(schema).length > 0) {
1416
+ try {
1417
+ jsonData = JsonDataGenerator.generate(schema);
1418
+ }
1419
+ catch (err) {
1420
+ warnings.push({
1421
+ type: WarningType.GenerateJsonDataFailed,
1422
+ content: Utils.format(ConstantString.GenerateJsonDataFailed, operationId, err.toString()),
1423
+ data: operationId,
1424
+ });
1425
+ }
1316
1426
  jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
1317
1427
  if (jsonPath !== "$") {
1318
1428
  schema = schema.properties[jsonPath];
1319
1429
  }
1320
- cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
1430
+ cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "", "", maxElementCount);
1321
1431
  }
1322
1432
  // if no schema, try to use example value
1323
1433
  if (cardBody.length === 0 && (json.examples || json.example)) {
@@ -1345,16 +1455,20 @@ class AdaptiveCardGenerator {
1345
1455
  version: ConstantString.AdaptiveCardVersion,
1346
1456
  body: cardBody,
1347
1457
  };
1348
- return [fullCard, jsonPath];
1458
+ return [fullCard, jsonPath, jsonData, warnings];
1349
1459
  }
1350
1460
  catch (err) {
1351
1461
  throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
1352
1462
  }
1353
1463
  }
1354
- static generateCardFromResponse(schema, name, parentArrayName = "") {
1464
+ static generateCardFromResponse(schema, name, parentArrayName = "", maxElementCount = Number.MAX_SAFE_INTEGER, counter = { count: 0 }) {
1465
+ if (counter.count >= maxElementCount) {
1466
+ return [];
1467
+ }
1355
1468
  if (schema.type === "array") {
1356
1469
  // schema.items can be arbitrary object: schema { type: array, items: {} }
1357
1470
  if (Object.keys(schema.items).length === 0) {
1471
+ counter.count++;
1358
1472
  return [
1359
1473
  {
1360
1474
  type: ConstantString.TextBlockType,
@@ -1363,7 +1477,7 @@ class AdaptiveCardGenerator {
1363
1477
  },
1364
1478
  ];
1365
1479
  }
1366
- const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
1480
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name, maxElementCount, counter);
1367
1481
  const template = {
1368
1482
  type: ConstantString.ContainerType,
1369
1483
  $data: name ? `\${${name}}` : "${$root}",
@@ -1373,11 +1487,11 @@ class AdaptiveCardGenerator {
1373
1487
  return [template];
1374
1488
  }
1375
1489
  // some schema may not contain type but contain properties
1376
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1490
+ if (Utils.isObjectSchema(schema)) {
1377
1491
  const { properties } = schema;
1378
1492
  const result = [];
1379
1493
  for (const property in properties) {
1380
- const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
1494
+ const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName, maxElementCount, counter);
1381
1495
  result.push(...obj);
1382
1496
  }
1383
1497
  if (schema.additionalProperties) {
@@ -1390,6 +1504,7 @@ class AdaptiveCardGenerator {
1390
1504
  schema.type === "integer" ||
1391
1505
  schema.type === "boolean" ||
1392
1506
  schema.type === "number") {
1507
+ counter.count++;
1393
1508
  if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
1394
1509
  // string in root: "ddd"
1395
1510
  let text = "result: ${$root}";
@@ -1414,24 +1529,17 @@ class AdaptiveCardGenerator {
1414
1529
  ];
1415
1530
  }
1416
1531
  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
- }
1532
+ const url = name ? `\${${name}}` : "${$data}";
1533
+ const condition = name
1534
+ ? `\${${name} != null && ${name} != ''}`
1535
+ : "${$data != null && $data != ''}";
1536
+ return [
1537
+ {
1538
+ type: "Image",
1539
+ url,
1540
+ $when: condition,
1541
+ },
1542
+ ];
1435
1543
  }
1436
1544
  }
1437
1545
  if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
@@ -1441,7 +1549,7 @@ class AdaptiveCardGenerator {
1441
1549
  }
1442
1550
  // Find the first array property in the response schema object with the well-known name
1443
1551
  static getResponseJsonPathFromSchema(schema) {
1444
- if (schema.type === "object" || (!schema.type && schema.properties)) {
1552
+ if (Utils.isObjectSchema(schema)) {
1445
1553
  const { properties } = schema;
1446
1554
  for (const property in properties) {
1447
1555
  const schema = properties[property];