@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.
- package/dist/index.esm2017.js +35 -66
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +55 -69
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +35 -66
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +55 -69
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/adaptiveCardGenerator.d.ts +4 -2
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/interfaces.d.ts +1 -0
- package/dist/src/utils.d.ts +2 -2
- package/package.json +3 -3
package/dist/index.esm2017.mjs
CHANGED
|
@@ -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
|
|
199
|
+
if (this.isObjectSchema(schema)) {
|
|
198
200
|
for (const property in schema.properties) {
|
|
199
201
|
const nestedSchema = schema.properties[property];
|
|
200
|
-
if (nestedSchema
|
|
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
|
|
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 &&
|
|
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
|
|
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 &&
|
|
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
|
|
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 (
|
|
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
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
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 (
|
|
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
|
|
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);
|