@microsoft/m365-spec-parser 0.2.1-rc-hotfix.0 → 0.2.2-alpha.02a122217.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 +91 -15
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +306 -42
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +91 -15
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +306 -42
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/adaptiveCardGenerator.d.ts +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/interfaces.d.ts +9 -3
- package/dist/src/specOptimizer.d.ts +18 -0
- package/dist/src/specParser.d.ts +1 -0
- package/dist/src/utils.d.ts +6 -5
- package/package.json +3 -3
package/dist/index.esm2017.mjs
CHANGED
|
@@ -17,10 +17,12 @@ var ErrorType;
|
|
|
17
17
|
ErrorType["RelativeServerUrlNotSupported"] = "relative-server-url-not-supported";
|
|
18
18
|
ErrorType["NoSupportedApi"] = "no-supported-api";
|
|
19
19
|
ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
|
|
20
|
+
ErrorType["AddedAPINotInOriginalSpec"] = "added-api-not-in-original-spec";
|
|
20
21
|
ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
|
|
21
22
|
ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
|
|
22
23
|
ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
|
|
23
24
|
ErrorType["SpecVersionNotSupported"] = "spec-version-not-supported";
|
|
25
|
+
ErrorType["CircularReferenceNotSupported"] = "circular-reference-not-supported";
|
|
24
26
|
ErrorType["ListFailed"] = "list-failed";
|
|
25
27
|
ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
|
|
26
28
|
ErrorType["FilterSpecFailed"] = "filter-spec-failed";
|
|
@@ -257,21 +259,28 @@ class Utils {
|
|
|
257
259
|
static updateFirstLetter(str) {
|
|
258
260
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
259
261
|
}
|
|
260
|
-
static getResponseJson(operationObject) {
|
|
261
|
-
var _a
|
|
262
|
+
static getResponseJson(operationObject, allowMultipleMediaType = false) {
|
|
263
|
+
var _a;
|
|
262
264
|
let json = {};
|
|
263
265
|
let multipleMediaType = false;
|
|
264
266
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
265
267
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
268
|
+
if (responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) {
|
|
269
|
+
for (const contentType of Object.keys(responseObject.content)) {
|
|
270
|
+
// json media type can also be "application/json; charset=utf-8"
|
|
271
|
+
if (contentType.indexOf("application/json") >= 0) {
|
|
272
|
+
multipleMediaType = false;
|
|
273
|
+
json = responseObject.content[contentType];
|
|
274
|
+
if (Utils.containMultipleMediaTypes(responseObject)) {
|
|
275
|
+
multipleMediaType = true;
|
|
276
|
+
if (!allowMultipleMediaType) {
|
|
277
|
+
json = {};
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
return { json, multipleMediaType };
|
|
282
|
+
}
|
|
283
|
+
}
|
|
275
284
|
}
|
|
276
285
|
}
|
|
277
286
|
}
|
|
@@ -532,10 +541,46 @@ class Utils {
|
|
|
532
541
|
const serverUrl = operationServer || methodServer || rootServer;
|
|
533
542
|
return serverUrl;
|
|
534
543
|
}
|
|
544
|
+
static limitACBodyProperties(body, maxCount) {
|
|
545
|
+
const result = [];
|
|
546
|
+
let currentCount = 0;
|
|
547
|
+
for (const element of body) {
|
|
548
|
+
if (element.type === ConstantString.ContainerType) {
|
|
549
|
+
const items = this.limitACBodyProperties(element.items, maxCount - currentCount);
|
|
550
|
+
result.push({
|
|
551
|
+
type: ConstantString.ContainerType,
|
|
552
|
+
$data: element.$data,
|
|
553
|
+
items: items,
|
|
554
|
+
});
|
|
555
|
+
currentCount += items.length;
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
result.push(element);
|
|
559
|
+
currentCount++;
|
|
560
|
+
}
|
|
561
|
+
if (currentCount >= maxCount) {
|
|
562
|
+
break;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return result;
|
|
566
|
+
}
|
|
535
567
|
}
|
|
536
568
|
|
|
537
569
|
// Copyright (c) Microsoft Corporation.
|
|
538
570
|
class Validator {
|
|
571
|
+
constructor() {
|
|
572
|
+
this.hasCircularReference = false;
|
|
573
|
+
}
|
|
574
|
+
checkCircularReference() {
|
|
575
|
+
try {
|
|
576
|
+
JSON.stringify(this.spec);
|
|
577
|
+
}
|
|
578
|
+
catch (e) {
|
|
579
|
+
if (e.message.includes("Converting circular structure to JSON")) {
|
|
580
|
+
this.hasCircularReference = true;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
539
584
|
listAPIs() {
|
|
540
585
|
var _a;
|
|
541
586
|
if (this.apiMap) {
|
|
@@ -631,6 +676,22 @@ class Validator {
|
|
|
631
676
|
}
|
|
632
677
|
return result;
|
|
633
678
|
}
|
|
679
|
+
validateCircularReference(method, path) {
|
|
680
|
+
const result = { isValid: true, reason: [] };
|
|
681
|
+
if (this.hasCircularReference) {
|
|
682
|
+
const operationObject = this.spec.paths[path][method];
|
|
683
|
+
try {
|
|
684
|
+
JSON.stringify(operationObject);
|
|
685
|
+
}
|
|
686
|
+
catch (e) {
|
|
687
|
+
if (e.message.includes("Converting circular structure to JSON")) {
|
|
688
|
+
result.isValid = false;
|
|
689
|
+
result.reason.push(ErrorType.CircularReferenceNotSupported);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
return result;
|
|
694
|
+
}
|
|
634
695
|
validateResponse(method, path) {
|
|
635
696
|
const result = { isValid: true, reason: [] };
|
|
636
697
|
const operationObject = this.spec.paths[path][method];
|
|
@@ -819,6 +880,7 @@ class CopilotValidator extends Validator {
|
|
|
819
880
|
this.projectType = ProjectType.Copilot;
|
|
820
881
|
this.options = options;
|
|
821
882
|
this.spec = spec;
|
|
883
|
+
this.checkCircularReference();
|
|
822
884
|
}
|
|
823
885
|
validateSpec() {
|
|
824
886
|
const result = { errors: [], warnings: [] };
|
|
@@ -844,6 +906,10 @@ class CopilotValidator extends Validator {
|
|
|
844
906
|
if (!methodAndPathResult.isValid) {
|
|
845
907
|
return methodAndPathResult;
|
|
846
908
|
}
|
|
909
|
+
const circularReferenceResult = this.validateCircularReference(method, path);
|
|
910
|
+
if (!circularReferenceResult.isValid) {
|
|
911
|
+
return circularReferenceResult;
|
|
912
|
+
}
|
|
847
913
|
const operationObject = this.spec.paths[path][method];
|
|
848
914
|
// validate auth
|
|
849
915
|
const authCheckResult = this.validateAuth(method, path);
|
|
@@ -887,6 +953,7 @@ class SMEValidator extends Validator {
|
|
|
887
953
|
this.projectType = ProjectType.SME;
|
|
888
954
|
this.options = options;
|
|
889
955
|
this.spec = spec;
|
|
956
|
+
this.checkCircularReference();
|
|
890
957
|
}
|
|
891
958
|
validateSpec() {
|
|
892
959
|
const result = { errors: [], warnings: [] };
|
|
@@ -914,6 +981,10 @@ class SMEValidator extends Validator {
|
|
|
914
981
|
if (!methodAndPathResult.isValid) {
|
|
915
982
|
return methodAndPathResult;
|
|
916
983
|
}
|
|
984
|
+
const circularReferenceResult = this.validateCircularReference(method, path);
|
|
985
|
+
if (!circularReferenceResult.isValid) {
|
|
986
|
+
return circularReferenceResult;
|
|
987
|
+
}
|
|
917
988
|
const operationObject = this.spec.paths[path][method];
|
|
918
989
|
// validate auth
|
|
919
990
|
const authCheckResult = this.validateAuth(method, path);
|
|
@@ -984,6 +1055,7 @@ class TeamsAIValidator extends Validator {
|
|
|
984
1055
|
this.projectType = ProjectType.TeamsAi;
|
|
985
1056
|
this.options = options;
|
|
986
1057
|
this.spec = spec;
|
|
1058
|
+
this.checkCircularReference();
|
|
987
1059
|
}
|
|
988
1060
|
validateSpec() {
|
|
989
1061
|
const result = { errors: [], warnings: [] };
|
|
@@ -1003,6 +1075,10 @@ class TeamsAIValidator extends Validator {
|
|
|
1003
1075
|
if (!methodAndPathResult.isValid) {
|
|
1004
1076
|
return methodAndPathResult;
|
|
1005
1077
|
}
|
|
1078
|
+
const circularReferenceResult = this.validateCircularReference(method, path);
|
|
1079
|
+
if (!circularReferenceResult.isValid) {
|
|
1080
|
+
return circularReferenceResult;
|
|
1081
|
+
}
|
|
1006
1082
|
const operationObject = this.spec.paths[path][method];
|
|
1007
1083
|
// validate operationId
|
|
1008
1084
|
if (!this.options.allowMissingId && !operationObject.operationId) {
|
|
@@ -1035,6 +1111,161 @@ class ValidatorFactory {
|
|
|
1035
1111
|
}
|
|
1036
1112
|
}
|
|
1037
1113
|
|
|
1114
|
+
// Copyright (c) Microsoft Corporation.
|
|
1115
|
+
class SpecOptimizer {
|
|
1116
|
+
static optimize(spec, options) {
|
|
1117
|
+
const mergedOptions = Object.assign(Object.assign({}, SpecOptimizer.defaultOptions), (options !== null && options !== void 0 ? options : {}));
|
|
1118
|
+
const newSpec = JSON.parse(JSON.stringify(spec));
|
|
1119
|
+
if (mergedOptions.removeUserDefinedRootProperty) {
|
|
1120
|
+
SpecOptimizer.removeUserDefinedRootProperty(newSpec);
|
|
1121
|
+
}
|
|
1122
|
+
if (mergedOptions.removeUnusedComponents) {
|
|
1123
|
+
SpecOptimizer.removeUnusedComponents(newSpec);
|
|
1124
|
+
}
|
|
1125
|
+
if (mergedOptions.removeUnusedTags) {
|
|
1126
|
+
SpecOptimizer.removeUnusedTags(newSpec);
|
|
1127
|
+
}
|
|
1128
|
+
if (mergedOptions.removeUnusedSecuritySchemas) {
|
|
1129
|
+
SpecOptimizer.removeUnusedSecuritySchemas(newSpec);
|
|
1130
|
+
}
|
|
1131
|
+
return newSpec;
|
|
1132
|
+
}
|
|
1133
|
+
static removeUnusedSecuritySchemas(spec) {
|
|
1134
|
+
if (!spec.components || !spec.components.securitySchemes) {
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1137
|
+
const usedSecuritySchemas = new Set();
|
|
1138
|
+
for (const pathKey in spec.paths) {
|
|
1139
|
+
for (const methodKey in spec.paths[pathKey]) {
|
|
1140
|
+
const operation = spec.paths[pathKey][methodKey];
|
|
1141
|
+
if (operation.security) {
|
|
1142
|
+
operation.security.forEach((securityReq) => {
|
|
1143
|
+
for (const schemaKey in securityReq) {
|
|
1144
|
+
usedSecuritySchemas.add(schemaKey);
|
|
1145
|
+
}
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
if (spec.security) {
|
|
1151
|
+
spec.security.forEach((securityReq) => {
|
|
1152
|
+
for (const schemaKey in securityReq) {
|
|
1153
|
+
usedSecuritySchemas.add(schemaKey);
|
|
1154
|
+
}
|
|
1155
|
+
});
|
|
1156
|
+
}
|
|
1157
|
+
for (const schemaKey in spec.components.securitySchemes) {
|
|
1158
|
+
if (!usedSecuritySchemas.has(schemaKey)) {
|
|
1159
|
+
delete spec.components.securitySchemes[schemaKey];
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
if (Object.keys(spec.components.securitySchemes).length === 0) {
|
|
1163
|
+
delete spec.components.securitySchemes;
|
|
1164
|
+
}
|
|
1165
|
+
if (Object.keys(spec.components).length === 0) {
|
|
1166
|
+
delete spec.components;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
static removeUnusedTags(spec) {
|
|
1170
|
+
if (!spec.tags) {
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
const usedTags = new Set();
|
|
1174
|
+
for (const pathKey in spec.paths) {
|
|
1175
|
+
for (const methodKey in spec.paths[pathKey]) {
|
|
1176
|
+
const operation = spec.paths[pathKey][methodKey];
|
|
1177
|
+
if (operation.tags) {
|
|
1178
|
+
operation.tags.forEach((tag) => usedTags.add(tag));
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
spec.tags = spec.tags.filter((tagObj) => usedTags.has(tagObj.name));
|
|
1183
|
+
}
|
|
1184
|
+
static removeUserDefinedRootProperty(spec) {
|
|
1185
|
+
for (const key in spec) {
|
|
1186
|
+
if (key.startsWith("x-")) {
|
|
1187
|
+
delete spec[key];
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
static removeUnusedComponents(spec) {
|
|
1192
|
+
const components = spec.components;
|
|
1193
|
+
if (!components) {
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
delete spec.components;
|
|
1197
|
+
const usedComponentsSet = new Set();
|
|
1198
|
+
const specString = JSON.stringify(spec);
|
|
1199
|
+
const componentReferences = SpecOptimizer.getComponentReferences(specString);
|
|
1200
|
+
for (const reference of componentReferences) {
|
|
1201
|
+
this.addComponent(reference, usedComponentsSet, components);
|
|
1202
|
+
}
|
|
1203
|
+
const newComponents = {};
|
|
1204
|
+
for (const componentName of usedComponentsSet) {
|
|
1205
|
+
const parts = componentName.split("/");
|
|
1206
|
+
const component = this.getComponent(componentName, components);
|
|
1207
|
+
if (component) {
|
|
1208
|
+
let current = newComponents;
|
|
1209
|
+
for (let i = 2; i < parts.length; i++) {
|
|
1210
|
+
if (i === parts.length - 1) {
|
|
1211
|
+
current[parts[i]] = component;
|
|
1212
|
+
}
|
|
1213
|
+
else if (!current[parts[i]]) {
|
|
1214
|
+
current[parts[i]] = {};
|
|
1215
|
+
}
|
|
1216
|
+
current = current[parts[i]];
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
// securitySchemes are referenced directly by name, to void issue, just keep them all and use removeUnusedSecuritySchemas to remove unused ones
|
|
1221
|
+
if (components.securitySchemes) {
|
|
1222
|
+
newComponents.securitySchemes = components.securitySchemes;
|
|
1223
|
+
}
|
|
1224
|
+
if (Object.keys(newComponents).length !== 0) {
|
|
1225
|
+
spec.components = newComponents;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
static getComponentReferences(specString) {
|
|
1229
|
+
const matches = Array.from(specString.matchAll(/['"](#\/components\/.+?)['"]/g));
|
|
1230
|
+
const matchResult = matches.map((match) => match[1]);
|
|
1231
|
+
return matchResult;
|
|
1232
|
+
}
|
|
1233
|
+
static getComponent(componentPath, components) {
|
|
1234
|
+
const parts = componentPath.split("/");
|
|
1235
|
+
let current = components;
|
|
1236
|
+
for (const part of parts) {
|
|
1237
|
+
if (part === "#" || part === "components") {
|
|
1238
|
+
continue;
|
|
1239
|
+
}
|
|
1240
|
+
current = current[part];
|
|
1241
|
+
if (!current) {
|
|
1242
|
+
return null;
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
return current;
|
|
1246
|
+
}
|
|
1247
|
+
static addComponent(componentName, usedComponentsSet, components) {
|
|
1248
|
+
if (usedComponentsSet.has(componentName)) {
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
usedComponentsSet.add(componentName);
|
|
1252
|
+
const component = this.getComponent(componentName, components);
|
|
1253
|
+
if (component) {
|
|
1254
|
+
const componentString = JSON.stringify(component);
|
|
1255
|
+
const componentReferences = SpecOptimizer.getComponentReferences(componentString);
|
|
1256
|
+
for (const reference of componentReferences) {
|
|
1257
|
+
this.addComponent(reference, usedComponentsSet, components);
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
SpecOptimizer.defaultOptions = {
|
|
1263
|
+
removeUnusedComponents: true,
|
|
1264
|
+
removeUnusedTags: true,
|
|
1265
|
+
removeUserDefinedRootProperty: true,
|
|
1266
|
+
removeUnusedSecuritySchemas: true,
|
|
1267
|
+
};
|
|
1268
|
+
|
|
1038
1269
|
// Copyright (c) Microsoft Corporation.
|
|
1039
1270
|
class SpecFilter {
|
|
1040
1271
|
static specFilter(filter, unResolveSpec, resolvedSpec, options) {
|
|
@@ -1068,7 +1299,7 @@ class SpecFilter {
|
|
|
1068
1299
|
}
|
|
1069
1300
|
}
|
|
1070
1301
|
newSpec.paths = newPaths;
|
|
1071
|
-
return newSpec;
|
|
1302
|
+
return SpecOptimizer.optimize(newSpec);
|
|
1072
1303
|
}
|
|
1073
1304
|
catch (err) {
|
|
1074
1305
|
throw new SpecParserError(err.toString(), ErrorType.FilterSpecFailed);
|
|
@@ -1078,9 +1309,9 @@ class SpecFilter {
|
|
|
1078
1309
|
|
|
1079
1310
|
// Copyright (c) Microsoft Corporation.
|
|
1080
1311
|
class AdaptiveCardGenerator {
|
|
1081
|
-
static generateAdaptiveCard(operationItem) {
|
|
1312
|
+
static generateAdaptiveCard(operationItem, allowMultipleMediaType = false) {
|
|
1082
1313
|
try {
|
|
1083
|
-
const { json } = Utils.getResponseJson(operationItem);
|
|
1314
|
+
const { json } = Utils.getResponseJson(operationItem, allowMultipleMediaType);
|
|
1084
1315
|
let cardBody = [];
|
|
1085
1316
|
let schema = json.schema;
|
|
1086
1317
|
let jsonPath = "$";
|
|
@@ -1191,7 +1422,7 @@ class AdaptiveCardGenerator {
|
|
|
1191
1422
|
{
|
|
1192
1423
|
type: "Image",
|
|
1193
1424
|
url: `\${${name}}`,
|
|
1194
|
-
$when: `\${${name} != null}`,
|
|
1425
|
+
$when: `\${${name} != null && ${name} != ''}`,
|
|
1195
1426
|
},
|
|
1196
1427
|
];
|
|
1197
1428
|
}
|
|
@@ -1200,7 +1431,7 @@ class AdaptiveCardGenerator {
|
|
|
1200
1431
|
{
|
|
1201
1432
|
type: "Image",
|
|
1202
1433
|
url: "${$data}",
|
|
1203
|
-
$when: "${$data != null}",
|
|
1434
|
+
$when: "${$data != null && $data != ''}",
|
|
1204
1435
|
},
|
|
1205
1436
|
];
|
|
1206
1437
|
}
|
|
@@ -1293,7 +1524,7 @@ function inferPreviewCardTemplate(card) {
|
|
|
1293
1524
|
result.image = {
|
|
1294
1525
|
url: `\${${inferredProperties.imageUrl}}`,
|
|
1295
1526
|
alt: `\${if(${inferredProperties.imageUrl}, ${inferredProperties.imageUrl}, 'N/A')}`,
|
|
1296
|
-
$when: `\${${inferredProperties.imageUrl} != null}`,
|
|
1527
|
+
$when: `\${${inferredProperties.imageUrl} != null && ${inferredProperties.imageUrl} != ''}`,
|
|
1297
1528
|
};
|
|
1298
1529
|
}
|
|
1299
1530
|
return result;
|
|
@@ -1435,6 +1666,7 @@ class ManifestUpdater {
|
|
|
1435
1666
|
const confirmationBodies = [];
|
|
1436
1667
|
if (operationItem) {
|
|
1437
1668
|
const operationId = operationItem.operationId;
|
|
1669
|
+
const safeFunctionName = operationId.replace(/[^a-zA-Z0-9]/g, "_");
|
|
1438
1670
|
const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
|
|
1439
1671
|
const summary = operationItem.summary;
|
|
1440
1672
|
const paramObject = operationItem.parameters;
|
|
@@ -1462,7 +1694,7 @@ class ManifestUpdater {
|
|
|
1462
1694
|
}
|
|
1463
1695
|
}
|
|
1464
1696
|
const funcObj = {
|
|
1465
|
-
name:
|
|
1697
|
+
name: safeFunctionName,
|
|
1466
1698
|
description: description,
|
|
1467
1699
|
};
|
|
1468
1700
|
if (options.allowResponseSemantics) {
|
|
@@ -1470,7 +1702,7 @@ class ManifestUpdater {
|
|
|
1470
1702
|
const { json } = Utils.getResponseJson(operationItem);
|
|
1471
1703
|
if (json.schema) {
|
|
1472
1704
|
const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem);
|
|
1473
|
-
card.body = card.body
|
|
1705
|
+
card.body = Utils.limitACBodyProperties(card.body, 5);
|
|
1474
1706
|
const responseSemantic = wrapResponseSemantics(card, jsonPath);
|
|
1475
1707
|
funcObj.capabilities = {
|
|
1476
1708
|
response_semantics: responseSemantic,
|
|
@@ -1498,7 +1730,7 @@ class ManifestUpdater {
|
|
|
1498
1730
|
}
|
|
1499
1731
|
}
|
|
1500
1732
|
functions.push(funcObj);
|
|
1501
|
-
functionNames.push(
|
|
1733
|
+
functionNames.push(safeFunctionName);
|
|
1502
1734
|
const conversationStarterStr = (summary !== null && summary !== void 0 ? summary : description).slice(0, ConstantString.ConversationStarterMaxLens);
|
|
1503
1735
|
if (conversationStarterStr) {
|
|
1504
1736
|
conversationStarters.push(conversationStarterStr);
|
|
@@ -1596,7 +1828,6 @@ class ManifestUpdater {
|
|
|
1596
1828
|
const auth = authInfo.authScheme;
|
|
1597
1829
|
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
|
|
1598
1830
|
if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
|
|
1599
|
-
const safeApiSecretRegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
|
|
1600
1831
|
composeExtension.authorization = {
|
|
1601
1832
|
authType: "apiSecretServiceAuth",
|
|
1602
1833
|
apiSecretServiceAuthConfiguration: {
|
|
@@ -1605,16 +1836,13 @@ class ManifestUpdater {
|
|
|
1605
1836
|
};
|
|
1606
1837
|
}
|
|
1607
1838
|
else if (Utils.isOAuthWithAuthCodeFlow(auth)) {
|
|
1839
|
+
// TODO: below schema is coming from design doc, may need to update when shcema is finalized
|
|
1608
1840
|
composeExtension.authorization = {
|
|
1609
1841
|
authType: "oAuth2.0",
|
|
1610
1842
|
oAuthConfiguration: {
|
|
1611
1843
|
oauthConfigurationId: `\${{${safeRegistrationIdName}}}`,
|
|
1612
1844
|
},
|
|
1613
1845
|
};
|
|
1614
|
-
updatedPart.webApplicationInfo = {
|
|
1615
|
-
id: "${{AAD_APP_CLIENT_ID}}",
|
|
1616
|
-
resource: "api://${{DOMAIN}}/${{AAD_APP_CLIENT_ID}}",
|
|
1617
|
-
};
|
|
1618
1846
|
}
|
|
1619
1847
|
}
|
|
1620
1848
|
updatedPart.composeExtensions = [composeExtension];
|
|
@@ -1650,12 +1878,17 @@ class ManifestUpdater {
|
|
|
1650
1878
|
command.parameters = command.parameters.filter((param) => param.isRequired);
|
|
1651
1879
|
}
|
|
1652
1880
|
else if (command.parameters && command.parameters.length > 0) {
|
|
1653
|
-
command.parameters
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1881
|
+
if (command.parameters.length > 1) {
|
|
1882
|
+
command.parameters = [command.parameters[0]];
|
|
1883
|
+
warnings.push({
|
|
1884
|
+
type: WarningType.OperationOnlyContainsOptionalParam,
|
|
1885
|
+
content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, command.id),
|
|
1886
|
+
data: {
|
|
1887
|
+
commandId: command.id,
|
|
1888
|
+
parameterName: command.parameters[0].name,
|
|
1889
|
+
},
|
|
1890
|
+
});
|
|
1891
|
+
}
|
|
1659
1892
|
}
|
|
1660
1893
|
if (adaptiveCardFolder) {
|
|
1661
1894
|
const adaptiveCardPath = path.join(adaptiveCardFolder, command.id + ".json");
|
|
@@ -1731,7 +1964,13 @@ class SpecParser {
|
|
|
1731
1964
|
try {
|
|
1732
1965
|
try {
|
|
1733
1966
|
await this.loadSpec();
|
|
1734
|
-
|
|
1967
|
+
if (!this.parser.$refs.circular) {
|
|
1968
|
+
await this.parser.validate(this.spec);
|
|
1969
|
+
}
|
|
1970
|
+
else {
|
|
1971
|
+
const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
|
|
1972
|
+
await this.parser.validate(clonedUnResolveSpec);
|
|
1973
|
+
}
|
|
1735
1974
|
}
|
|
1736
1975
|
catch (e) {
|
|
1737
1976
|
return {
|
|
@@ -1819,19 +2058,36 @@ class SpecParser {
|
|
|
1819
2058
|
isValid: isValid,
|
|
1820
2059
|
reason: reason,
|
|
1821
2060
|
};
|
|
1822
|
-
|
|
2061
|
+
// Try best to parse server url and auth type
|
|
2062
|
+
try {
|
|
1823
2063
|
const serverObj = Utils.getServerObject(spec, method.toLocaleLowerCase(), path);
|
|
1824
2064
|
if (serverObj) {
|
|
1825
|
-
apiResult.server =
|
|
2065
|
+
apiResult.server = serverObj.url;
|
|
1826
2066
|
}
|
|
2067
|
+
}
|
|
2068
|
+
catch (err) {
|
|
2069
|
+
// ignore
|
|
2070
|
+
}
|
|
2071
|
+
try {
|
|
1827
2072
|
const authArray = Utils.getAuthArray(operation.security, spec);
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
2073
|
+
if (authArray.length !== 0) {
|
|
2074
|
+
for (const auths of authArray) {
|
|
2075
|
+
if (auths.length === 1) {
|
|
2076
|
+
apiResult.auth = auths[0];
|
|
2077
|
+
break;
|
|
2078
|
+
}
|
|
2079
|
+
else {
|
|
2080
|
+
apiResult.auth = {
|
|
2081
|
+
authScheme: { type: "multipleAuth" },
|
|
2082
|
+
name: auths.map((auth) => auth.name).join(", "),
|
|
2083
|
+
};
|
|
2084
|
+
}
|
|
1832
2085
|
}
|
|
1833
2086
|
}
|
|
1834
2087
|
}
|
|
2088
|
+
catch (err) {
|
|
2089
|
+
// ignore
|
|
2090
|
+
}
|
|
1835
2091
|
result.APIs.push(apiResult);
|
|
1836
2092
|
}
|
|
1837
2093
|
result.allAPICount = result.APIs.length;
|
|
@@ -1862,7 +2118,8 @@ class SpecParser {
|
|
|
1862
2118
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1863
2119
|
throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
|
|
1864
2120
|
}
|
|
1865
|
-
const
|
|
2121
|
+
const clonedUnResolveSpec = JSON.parse(JSON.stringify(newUnResolvedSpec));
|
|
2122
|
+
const newSpec = (await this.parser.dereference(clonedUnResolveSpec));
|
|
1866
2123
|
return [newUnResolvedSpec, newSpec];
|
|
1867
2124
|
}
|
|
1868
2125
|
catch (err) {
|
|
@@ -1935,10 +2192,11 @@ class SpecParser {
|
|
|
1935
2192
|
const operation = newSpec.paths[url][method];
|
|
1936
2193
|
try {
|
|
1937
2194
|
const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
|
|
1938
|
-
const
|
|
2195
|
+
const safeAdaptiveCardName = operation.operationId.replace(/[^a-zA-Z0-9]/g, "_");
|
|
2196
|
+
const fileName = path.join(adaptiveCardFolder, `${safeAdaptiveCardName}.json`);
|
|
1939
2197
|
const wrappedCard = wrapAdaptiveCard(card, jsonPath);
|
|
1940
2198
|
await fs.outputJSON(fileName, wrappedCard, { spaces: 2 });
|
|
1941
|
-
const dataFileName = path.join(adaptiveCardFolder, `${
|
|
2199
|
+
const dataFileName = path.join(adaptiveCardFolder, `${safeAdaptiveCardName}.data.json`);
|
|
1942
2200
|
await fs.outputJSON(dataFileName, {}, { spaces: 2 });
|
|
1943
2201
|
}
|
|
1944
2202
|
catch (err) {
|
|
@@ -1970,7 +2228,8 @@ class SpecParser {
|
|
|
1970
2228
|
}
|
|
1971
2229
|
async loadSpec() {
|
|
1972
2230
|
if (!this.spec) {
|
|
1973
|
-
|
|
2231
|
+
const spec = (await this.parser.parse(this.pathOrSpec));
|
|
2232
|
+
this.unResolveSpec = this.resolveEnvForSpec(spec);
|
|
1974
2233
|
// Convert swagger 2.0 to openapi 3.0
|
|
1975
2234
|
if (!this.unResolveSpec.openapi && this.unResolveSpec.swagger === "2.0") {
|
|
1976
2235
|
const specObj = await converter.convert(this.unResolveSpec, {});
|
|
@@ -2004,6 +2263,11 @@ class SpecParser {
|
|
|
2004
2263
|
}
|
|
2005
2264
|
await fs.outputFile(outputSpecPath, resultStr);
|
|
2006
2265
|
}
|
|
2266
|
+
resolveEnvForSpec(spec) {
|
|
2267
|
+
const specString = JSON.stringify(spec);
|
|
2268
|
+
const specResolved = Utils.resolveEnv(specString);
|
|
2269
|
+
return JSON.parse(specResolved);
|
|
2270
|
+
}
|
|
2007
2271
|
}
|
|
2008
2272
|
|
|
2009
2273
|
export { AdaptiveCardGenerator, ConstantString, ErrorType, ProjectType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
|