@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.
- package/dist/index.esm2017.js +175 -67
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +198 -72
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +175 -67
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +198 -72
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/adaptiveCardGenerator.d.ts +5 -3
- package/dist/src/constants.d.ts +2 -0
- package/dist/src/interfaces.d.ts +2 -0
- package/dist/src/jsonDataGenerator.d.ts +6 -0
- package/dist/src/utils.d.ts +2 -2
- package/package.json +3 -3
package/dist/index.esm2017.js
CHANGED
|
@@ -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
|
|
195
|
+
if (this.isObjectSchema(schema)) {
|
|
192
196
|
for (const property in schema.properties) {
|
|
193
197
|
const nestedSchema = schema.properties[property];
|
|
194
|
-
if (nestedSchema
|
|
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
|
|
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 &&
|
|
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
|
|
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 &&
|
|
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
|
|
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 (
|
|
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
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
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 (
|
|
1552
|
+
if (Utils.isObjectSchema(schema)) {
|
|
1445
1553
|
const { properties } = schema;
|
|
1446
1554
|
for (const property in properties) {
|
|
1447
1555
|
const schema = properties[property];
|