@microsoft/m365-spec-parser 0.2.4 → 0.2.5-alpha.08a6629d5.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 +176 -193
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +341 -274
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +176 -193
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +346 -275
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/constants.d.ts +3 -4
- package/dist/src/interfaces.d.ts +10 -3
- package/dist/src/manifestUpdater.d.ts +3 -3
- package/dist/src/specParser.d.ts +7 -0
- package/dist/src/utils.d.ts +6 -3
- package/package.json +5 -5
package/dist/index.node.cjs.js
CHANGED
|
@@ -80,11 +80,8 @@ exports.ErrorType = void 0;
|
|
|
80
80
|
ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
|
|
81
81
|
ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
|
|
82
82
|
ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
|
|
83
|
-
ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
|
|
84
83
|
ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
|
|
85
84
|
ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
|
|
86
|
-
ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
|
|
87
|
-
ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
|
|
88
85
|
ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
|
|
89
86
|
ErrorType["NoParameter"] = "no-parameter";
|
|
90
87
|
ErrorType["NoAPIInfo"] = "no-api-info";
|
|
@@ -104,6 +101,7 @@ exports.WarningType = void 0;
|
|
|
104
101
|
WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
|
|
105
102
|
WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
|
|
106
103
|
WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
|
|
104
|
+
WarningType["UnsupportedAuthType"] = "unsupported-auth-type";
|
|
107
105
|
WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
|
|
108
106
|
WarningType["Unknown"] = "unknown";
|
|
109
107
|
})(exports.WarningType || (exports.WarningType = {}));
|
|
@@ -143,6 +141,7 @@ ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please conve
|
|
|
143
141
|
ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
|
|
144
142
|
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
145
143
|
ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
|
|
144
|
+
ConstantString.AuthTypeIsNotSupported = "Unsupported authorization type in API '%s'. No authorization will be used.";
|
|
146
145
|
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
147
146
|
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.";
|
|
148
147
|
ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
|
|
@@ -152,17 +151,12 @@ ConstantString.WrappedCardResponseLayout = "list";
|
|
|
152
151
|
ConstantString.GetMethod = "get";
|
|
153
152
|
ConstantString.PostMethod = "post";
|
|
154
153
|
ConstantString.AdaptiveCardVersion = "1.5";
|
|
155
|
-
ConstantString.AdaptiveCardSchema = "
|
|
154
|
+
ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
|
|
156
155
|
ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
157
156
|
ConstantString.TextBlockType = "TextBlock";
|
|
158
157
|
ConstantString.ImageType = "Image";
|
|
159
158
|
ConstantString.ContainerType = "Container";
|
|
160
|
-
ConstantString.RegistrationIdPostfix =
|
|
161
|
-
apiKey: "REGISTRATION_ID",
|
|
162
|
-
oauth2: "CONFIGURATION_ID",
|
|
163
|
-
http: "REGISTRATION_ID",
|
|
164
|
-
openIdConnect: "REGISTRATION_ID",
|
|
165
|
-
};
|
|
159
|
+
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
166
160
|
ConstantString.ResponseCodeFor20X = [
|
|
167
161
|
"200",
|
|
168
162
|
"201",
|
|
@@ -174,6 +168,7 @@ ConstantString.ResponseCodeFor20X = [
|
|
|
174
168
|
"207",
|
|
175
169
|
"208",
|
|
176
170
|
"226",
|
|
171
|
+
"2XX",
|
|
177
172
|
"default",
|
|
178
173
|
];
|
|
179
174
|
ConstantString.AllOperationMethods = [
|
|
@@ -239,17 +234,6 @@ class SpecParserError extends Error {
|
|
|
239
234
|
|
|
240
235
|
// Copyright (c) Microsoft Corporation.
|
|
241
236
|
class Utils {
|
|
242
|
-
static hasNestedObjectInSchema(schema) {
|
|
243
|
-
if (this.isObjectSchema(schema)) {
|
|
244
|
-
for (const property in schema.properties) {
|
|
245
|
-
const nestedSchema = schema.properties[property];
|
|
246
|
-
if (this.isObjectSchema(nestedSchema)) {
|
|
247
|
-
return true;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
return false;
|
|
252
|
-
}
|
|
253
237
|
static isObjectSchema(schema) {
|
|
254
238
|
return schema.type === "object" || (!schema.type && !!schema.properties);
|
|
255
239
|
}
|
|
@@ -262,11 +246,32 @@ class Utils {
|
|
|
262
246
|
static isAPIKeyAuth(authScheme) {
|
|
263
247
|
return authScheme.type === "apiKey";
|
|
264
248
|
}
|
|
249
|
+
static isAPIKeyAuthButNotInCookie(authScheme) {
|
|
250
|
+
return authScheme.type === "apiKey" && authScheme.in !== "cookie";
|
|
251
|
+
}
|
|
265
252
|
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
266
253
|
return !!(authScheme.type === "oauth2" &&
|
|
267
254
|
authScheme.flows &&
|
|
268
255
|
authScheme.flows.authorizationCode);
|
|
269
256
|
}
|
|
257
|
+
static isNotSupportedAuth(authSchemeArray) {
|
|
258
|
+
if (authSchemeArray.length === 0) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
for (const auths of authSchemeArray) {
|
|
265
|
+
if (auths.length === 1) {
|
|
266
|
+
if (Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme) ||
|
|
267
|
+
Utils.isBearerTokenAuth(auths[0].authScheme) ||
|
|
268
|
+
Utils.isAPIKeyAuthButNotInCookie(auths[0].authScheme)) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
270
275
|
static getAuthArray(securities, spec) {
|
|
271
276
|
var _a;
|
|
272
277
|
const result = [];
|
|
@@ -291,6 +296,20 @@ class Utils {
|
|
|
291
296
|
result.sort((a, b) => a[0].name.localeCompare(b[0].name));
|
|
292
297
|
return result;
|
|
293
298
|
}
|
|
299
|
+
static getAuthMap(spec) {
|
|
300
|
+
const authMap = {};
|
|
301
|
+
for (const url in spec.paths) {
|
|
302
|
+
for (const method in spec.paths[url]) {
|
|
303
|
+
const operation = spec.paths[url][method];
|
|
304
|
+
const authArray = Utils.getAuthArray(operation.security, spec);
|
|
305
|
+
if (authArray && authArray.length > 0) {
|
|
306
|
+
const currentAuth = authArray[0][0];
|
|
307
|
+
authMap[operation.operationId] = currentAuth;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return authMap;
|
|
312
|
+
}
|
|
294
313
|
static getAuthInfo(spec) {
|
|
295
314
|
let authInfo = undefined;
|
|
296
315
|
for (const url in spec.paths) {
|
|
@@ -319,27 +338,33 @@ class Utils {
|
|
|
319
338
|
let multipleMediaType = false;
|
|
320
339
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
321
340
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
322
|
-
if (responseObject
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
else {
|
|
335
|
-
return { json, multipleMediaType };
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
}
|
|
341
|
+
if (!responseObject) {
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
|
|
345
|
+
if (!allowMultipleMediaType && multipleMediaType) {
|
|
346
|
+
json = {};
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
const mediaObj = Utils.getJsonContentType(responseObject);
|
|
350
|
+
if (Object.keys(mediaObj).length > 0) {
|
|
351
|
+
json = mediaObj;
|
|
352
|
+
return { json, multipleMediaType };
|
|
339
353
|
}
|
|
340
354
|
}
|
|
341
355
|
return { json, multipleMediaType };
|
|
342
356
|
}
|
|
357
|
+
static getJsonContentType(responseObject) {
|
|
358
|
+
if (responseObject.content) {
|
|
359
|
+
for (const contentType of Object.keys(responseObject.content)) {
|
|
360
|
+
// json media type can also be "application/json; charset=utf-8"
|
|
361
|
+
if (contentType.indexOf("application/json") >= 0) {
|
|
362
|
+
return responseObject.content[contentType];
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return {};
|
|
367
|
+
}
|
|
343
368
|
static convertPathToCamelCase(path) {
|
|
344
369
|
const pathSegments = path.split(/[./{]/);
|
|
345
370
|
const camelCaseSegments = pathSegments.map((segment) => {
|
|
@@ -375,7 +400,7 @@ class Utils {
|
|
|
375
400
|
}
|
|
376
401
|
return newStr;
|
|
377
402
|
}
|
|
378
|
-
static checkServerUrl(servers) {
|
|
403
|
+
static checkServerUrl(servers, allowHttp = false) {
|
|
379
404
|
const errors = [];
|
|
380
405
|
let serverUrl;
|
|
381
406
|
try {
|
|
@@ -398,8 +423,7 @@ class Utils {
|
|
|
398
423
|
data: servers,
|
|
399
424
|
});
|
|
400
425
|
}
|
|
401
|
-
else if (protocol !== "https:") {
|
|
402
|
-
// Http server url is not supported
|
|
426
|
+
else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
|
|
403
427
|
const protocolString = protocol.slice(0, -1);
|
|
404
428
|
errors.push({
|
|
405
429
|
type: exports.ErrorType.UrlProtocolNotSupported,
|
|
@@ -415,10 +439,11 @@ class Utils {
|
|
|
415
439
|
let hasTopLevelServers = false;
|
|
416
440
|
let hasPathLevelServers = false;
|
|
417
441
|
let hasOperationLevelServers = false;
|
|
442
|
+
const allowHttp = options.projectType === exports.ProjectType.Copilot;
|
|
418
443
|
if (spec.servers && spec.servers.length >= 1) {
|
|
419
444
|
hasTopLevelServers = true;
|
|
420
445
|
// for multiple server, we only use the first url
|
|
421
|
-
const serverErrors = Utils.checkServerUrl(spec.servers);
|
|
446
|
+
const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
|
|
422
447
|
errors.push(...serverErrors);
|
|
423
448
|
}
|
|
424
449
|
const paths = spec.paths;
|
|
@@ -426,7 +451,7 @@ class Utils {
|
|
|
426
451
|
const methods = paths[path];
|
|
427
452
|
if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
|
|
428
453
|
hasPathLevelServers = true;
|
|
429
|
-
const serverErrors = Utils.checkServerUrl(methods.servers);
|
|
454
|
+
const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
|
|
430
455
|
errors.push(...serverErrors);
|
|
431
456
|
}
|
|
432
457
|
for (const method in methods) {
|
|
@@ -434,7 +459,7 @@ class Utils {
|
|
|
434
459
|
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
435
460
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
436
461
|
hasOperationLevelServers = true;
|
|
437
|
-
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
462
|
+
const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
|
|
438
463
|
errors.push(...serverErrors);
|
|
439
464
|
}
|
|
440
465
|
}
|
|
@@ -723,22 +748,6 @@ class Validator {
|
|
|
723
748
|
}
|
|
724
749
|
return result;
|
|
725
750
|
}
|
|
726
|
-
validateResponse(method, path) {
|
|
727
|
-
const result = { isValid: true, reason: [] };
|
|
728
|
-
const operationObject = this.spec.paths[path][method];
|
|
729
|
-
const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
|
|
730
|
-
if (this.options.projectType === exports.ProjectType.SME) {
|
|
731
|
-
// only support response body only contains “application/json” content type
|
|
732
|
-
if (multipleMediaType) {
|
|
733
|
-
result.reason.push(exports.ErrorType.ResponseContainMultipleMediaTypes);
|
|
734
|
-
}
|
|
735
|
-
else if (Object.keys(json).length === 0) {
|
|
736
|
-
// response body should not be empty
|
|
737
|
-
result.reason.push(exports.ErrorType.ResponseJsonIsEmpty);
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
return result;
|
|
741
|
-
}
|
|
742
751
|
validateServer(method, path) {
|
|
743
752
|
const result = { isValid: true, reason: [] };
|
|
744
753
|
const serverObj = Utils.getServerObject(this.spec, method, path);
|
|
@@ -747,8 +756,8 @@ class Validator {
|
|
|
747
756
|
result.reason.push(exports.ErrorType.NoServerInformation);
|
|
748
757
|
}
|
|
749
758
|
else {
|
|
750
|
-
|
|
751
|
-
const serverValidateResult = Utils.checkServerUrl([serverObj]);
|
|
759
|
+
const allowHttp = this.projectType === exports.ProjectType.Copilot;
|
|
760
|
+
const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
|
|
752
761
|
result.reason.push(...serverValidateResult.map((item) => item.type));
|
|
753
762
|
}
|
|
754
763
|
return result;
|
|
@@ -771,6 +780,9 @@ class Validator {
|
|
|
771
780
|
reason: [exports.ErrorType.MultipleAuthNotSupported],
|
|
772
781
|
};
|
|
773
782
|
}
|
|
783
|
+
if (this.projectType === exports.ProjectType.Copilot) {
|
|
784
|
+
return { isValid: true, reason: [] };
|
|
785
|
+
}
|
|
774
786
|
for (const auths of authSchemeArray) {
|
|
775
787
|
if (auths.length === 1) {
|
|
776
788
|
if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
@@ -783,114 +795,6 @@ class Validator {
|
|
|
783
795
|
}
|
|
784
796
|
return { isValid: false, reason: [exports.ErrorType.AuthTypeIsNotSupported] };
|
|
785
797
|
}
|
|
786
|
-
checkPostBodySchema(schema, isRequired = false) {
|
|
787
|
-
var _a;
|
|
788
|
-
const paramResult = {
|
|
789
|
-
requiredNum: 0,
|
|
790
|
-
optionalNum: 0,
|
|
791
|
-
isValid: true,
|
|
792
|
-
reason: [],
|
|
793
|
-
};
|
|
794
|
-
if (Object.keys(schema).length === 0) {
|
|
795
|
-
return paramResult;
|
|
796
|
-
}
|
|
797
|
-
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
798
|
-
const isCopilot = this.projectType === exports.ProjectType.Copilot;
|
|
799
|
-
if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
|
|
800
|
-
paramResult.isValid = false;
|
|
801
|
-
paramResult.reason = [exports.ErrorType.RequestBodyContainsNestedObject];
|
|
802
|
-
return paramResult;
|
|
803
|
-
}
|
|
804
|
-
if (schema.type === "string" ||
|
|
805
|
-
schema.type === "integer" ||
|
|
806
|
-
schema.type === "boolean" ||
|
|
807
|
-
schema.type === "number") {
|
|
808
|
-
if (isRequiredWithoutDefault) {
|
|
809
|
-
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
810
|
-
}
|
|
811
|
-
else {
|
|
812
|
-
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
else if (Utils.isObjectSchema(schema)) {
|
|
816
|
-
const { properties } = schema;
|
|
817
|
-
for (const property in properties) {
|
|
818
|
-
let isRequired = false;
|
|
819
|
-
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
820
|
-
isRequired = true;
|
|
821
|
-
}
|
|
822
|
-
const result = this.checkPostBodySchema(properties[property], isRequired);
|
|
823
|
-
paramResult.requiredNum += result.requiredNum;
|
|
824
|
-
paramResult.optionalNum += result.optionalNum;
|
|
825
|
-
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
826
|
-
paramResult.reason.push(...result.reason);
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
else {
|
|
830
|
-
if (isRequiredWithoutDefault && !isCopilot) {
|
|
831
|
-
paramResult.isValid = false;
|
|
832
|
-
paramResult.reason.push(exports.ErrorType.PostBodyContainsRequiredUnsupportedSchema);
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
return paramResult;
|
|
836
|
-
}
|
|
837
|
-
checkParamSchema(paramObject) {
|
|
838
|
-
const paramResult = {
|
|
839
|
-
requiredNum: 0,
|
|
840
|
-
optionalNum: 0,
|
|
841
|
-
isValid: true,
|
|
842
|
-
reason: [],
|
|
843
|
-
};
|
|
844
|
-
if (!paramObject) {
|
|
845
|
-
return paramResult;
|
|
846
|
-
}
|
|
847
|
-
const isCopilot = this.projectType === exports.ProjectType.Copilot;
|
|
848
|
-
for (let i = 0; i < paramObject.length; i++) {
|
|
849
|
-
const param = paramObject[i];
|
|
850
|
-
const schema = param.schema;
|
|
851
|
-
if (isCopilot && Utils.hasNestedObjectInSchema(schema)) {
|
|
852
|
-
paramResult.isValid = false;
|
|
853
|
-
paramResult.reason.push(exports.ErrorType.ParamsContainsNestedObject);
|
|
854
|
-
continue;
|
|
855
|
-
}
|
|
856
|
-
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
857
|
-
if (isCopilot) {
|
|
858
|
-
if (isRequiredWithoutDefault) {
|
|
859
|
-
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
860
|
-
}
|
|
861
|
-
else {
|
|
862
|
-
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
863
|
-
}
|
|
864
|
-
continue;
|
|
865
|
-
}
|
|
866
|
-
if (param.in === "header" || param.in === "cookie") {
|
|
867
|
-
if (isRequiredWithoutDefault) {
|
|
868
|
-
paramResult.isValid = false;
|
|
869
|
-
paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
870
|
-
}
|
|
871
|
-
continue;
|
|
872
|
-
}
|
|
873
|
-
if (schema.type !== "boolean" &&
|
|
874
|
-
schema.type !== "string" &&
|
|
875
|
-
schema.type !== "number" &&
|
|
876
|
-
schema.type !== "integer") {
|
|
877
|
-
if (isRequiredWithoutDefault) {
|
|
878
|
-
paramResult.isValid = false;
|
|
879
|
-
paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
880
|
-
}
|
|
881
|
-
continue;
|
|
882
|
-
}
|
|
883
|
-
if (param.in === "query" || param.in === "path") {
|
|
884
|
-
if (isRequiredWithoutDefault) {
|
|
885
|
-
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
886
|
-
}
|
|
887
|
-
else {
|
|
888
|
-
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
return paramResult;
|
|
893
|
-
}
|
|
894
798
|
}
|
|
895
799
|
|
|
896
800
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -900,7 +804,6 @@ class CopilotValidator extends Validator {
|
|
|
900
804
|
this.projectType = exports.ProjectType.Copilot;
|
|
901
805
|
this.options = options;
|
|
902
806
|
this.spec = spec;
|
|
903
|
-
this.checkCircularReference();
|
|
904
807
|
}
|
|
905
808
|
validateSpec() {
|
|
906
809
|
const result = { errors: [], warnings: [] };
|
|
@@ -926,10 +829,6 @@ class CopilotValidator extends Validator {
|
|
|
926
829
|
if (!methodAndPathResult.isValid) {
|
|
927
830
|
return methodAndPathResult;
|
|
928
831
|
}
|
|
929
|
-
const circularReferenceResult = this.validateCircularReference(method, path);
|
|
930
|
-
if (!circularReferenceResult.isValid) {
|
|
931
|
-
return circularReferenceResult;
|
|
932
|
-
}
|
|
933
832
|
const operationObject = this.spec.paths[path][method];
|
|
934
833
|
// validate auth
|
|
935
834
|
const authCheckResult = this.validateAuth(method, path);
|
|
@@ -941,24 +840,6 @@ class CopilotValidator extends Validator {
|
|
|
941
840
|
// validate server
|
|
942
841
|
const validateServerResult = this.validateServer(method, path);
|
|
943
842
|
result.reason.push(...validateServerResult.reason);
|
|
944
|
-
// validate response
|
|
945
|
-
const validateResponseResult = this.validateResponse(method, path);
|
|
946
|
-
result.reason.push(...validateResponseResult.reason);
|
|
947
|
-
// validate requestBody
|
|
948
|
-
const requestBody = operationObject.requestBody;
|
|
949
|
-
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
950
|
-
if (requestJsonBody) {
|
|
951
|
-
const requestBodySchema = requestJsonBody.schema;
|
|
952
|
-
if (!Utils.isObjectSchema(requestBodySchema)) {
|
|
953
|
-
result.reason.push(exports.ErrorType.PostBodySchemaIsNotJson);
|
|
954
|
-
}
|
|
955
|
-
const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
|
|
956
|
-
result.reason.push(...requestBodyParamResult.reason);
|
|
957
|
-
}
|
|
958
|
-
// validate parameters
|
|
959
|
-
const paramObject = operationObject.parameters;
|
|
960
|
-
const paramResult = this.checkParamSchema(paramObject);
|
|
961
|
-
result.reason.push(...paramResult.reason);
|
|
962
843
|
if (result.reason.length > 0) {
|
|
963
844
|
result.isValid = false;
|
|
964
845
|
}
|
|
@@ -1050,6 +931,108 @@ class SMEValidator extends Validator {
|
|
|
1050
931
|
}
|
|
1051
932
|
return result;
|
|
1052
933
|
}
|
|
934
|
+
validateResponse(method, path) {
|
|
935
|
+
const result = { isValid: true, reason: [] };
|
|
936
|
+
const operationObject = this.spec.paths[path][method];
|
|
937
|
+
const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
|
|
938
|
+
// only support response body only contains “application/json” content type
|
|
939
|
+
if (multipleMediaType) {
|
|
940
|
+
result.reason.push(exports.ErrorType.ResponseContainMultipleMediaTypes);
|
|
941
|
+
}
|
|
942
|
+
else if (Object.keys(json).length === 0) {
|
|
943
|
+
// response body should not be empty
|
|
944
|
+
result.reason.push(exports.ErrorType.ResponseJsonIsEmpty);
|
|
945
|
+
}
|
|
946
|
+
return result;
|
|
947
|
+
}
|
|
948
|
+
checkPostBodySchema(schema, isRequired = false) {
|
|
949
|
+
var _a;
|
|
950
|
+
const paramResult = {
|
|
951
|
+
requiredNum: 0,
|
|
952
|
+
optionalNum: 0,
|
|
953
|
+
isValid: true,
|
|
954
|
+
reason: [],
|
|
955
|
+
};
|
|
956
|
+
if (Object.keys(schema).length === 0) {
|
|
957
|
+
return paramResult;
|
|
958
|
+
}
|
|
959
|
+
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
960
|
+
const isCopilot = this.projectType === exports.ProjectType.Copilot;
|
|
961
|
+
if (schema.type === "string" ||
|
|
962
|
+
schema.type === "integer" ||
|
|
963
|
+
schema.type === "boolean" ||
|
|
964
|
+
schema.type === "number") {
|
|
965
|
+
if (isRequiredWithoutDefault) {
|
|
966
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
967
|
+
}
|
|
968
|
+
else {
|
|
969
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
else if (Utils.isObjectSchema(schema)) {
|
|
973
|
+
const { properties } = schema;
|
|
974
|
+
for (const property in properties) {
|
|
975
|
+
let isRequired = false;
|
|
976
|
+
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
977
|
+
isRequired = true;
|
|
978
|
+
}
|
|
979
|
+
const result = this.checkPostBodySchema(properties[property], isRequired);
|
|
980
|
+
paramResult.requiredNum += result.requiredNum;
|
|
981
|
+
paramResult.optionalNum += result.optionalNum;
|
|
982
|
+
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
983
|
+
paramResult.reason.push(...result.reason);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
else {
|
|
987
|
+
if (isRequiredWithoutDefault && !isCopilot) {
|
|
988
|
+
paramResult.isValid = false;
|
|
989
|
+
paramResult.reason.push(exports.ErrorType.PostBodyContainsRequiredUnsupportedSchema);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
return paramResult;
|
|
993
|
+
}
|
|
994
|
+
checkParamSchema(paramObject) {
|
|
995
|
+
const paramResult = {
|
|
996
|
+
requiredNum: 0,
|
|
997
|
+
optionalNum: 0,
|
|
998
|
+
isValid: true,
|
|
999
|
+
reason: [],
|
|
1000
|
+
};
|
|
1001
|
+
if (!paramObject) {
|
|
1002
|
+
return paramResult;
|
|
1003
|
+
}
|
|
1004
|
+
for (let i = 0; i < paramObject.length; i++) {
|
|
1005
|
+
const param = paramObject[i];
|
|
1006
|
+
const schema = param.schema;
|
|
1007
|
+
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
1008
|
+
if (param.in === "header" || param.in === "cookie") {
|
|
1009
|
+
if (isRequiredWithoutDefault) {
|
|
1010
|
+
paramResult.isValid = false;
|
|
1011
|
+
paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
1012
|
+
}
|
|
1013
|
+
continue;
|
|
1014
|
+
}
|
|
1015
|
+
if (schema.type !== "boolean" &&
|
|
1016
|
+
schema.type !== "string" &&
|
|
1017
|
+
schema.type !== "number" &&
|
|
1018
|
+
schema.type !== "integer") {
|
|
1019
|
+
if (isRequiredWithoutDefault) {
|
|
1020
|
+
paramResult.isValid = false;
|
|
1021
|
+
paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
1022
|
+
}
|
|
1023
|
+
continue;
|
|
1024
|
+
}
|
|
1025
|
+
if (param.in === "query" || param.in === "path") {
|
|
1026
|
+
if (isRequiredWithoutDefault) {
|
|
1027
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
1028
|
+
}
|
|
1029
|
+
else {
|
|
1030
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
return paramResult;
|
|
1035
|
+
}
|
|
1053
1036
|
validateParamCount(postBodyResult, paramResult) {
|
|
1054
1037
|
const result = { isValid: true, reason: [] };
|
|
1055
1038
|
const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
|
|
@@ -1751,7 +1734,7 @@ function inferProperties(card) {
|
|
|
1751
1734
|
|
|
1752
1735
|
// Copyright (c) Microsoft Corporation.
|
|
1753
1736
|
class ManifestUpdater {
|
|
1754
|
-
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options,
|
|
1737
|
+
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authMap, existingPluginManifestInfo) {
|
|
1755
1738
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1756
1739
|
const manifest = yield fs__default['default'].readJSON(manifestPath);
|
|
1757
1740
|
const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
|
|
@@ -1782,7 +1765,7 @@ class ManifestUpdater {
|
|
|
1782
1765
|
}
|
|
1783
1766
|
const appName = this.removeEnvs(manifest.name.short);
|
|
1784
1767
|
const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
|
|
1785
|
-
const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName,
|
|
1768
|
+
const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo);
|
|
1786
1769
|
return [manifest, apiPlugin, warnings];
|
|
1787
1770
|
});
|
|
1788
1771
|
}
|
|
@@ -1805,29 +1788,14 @@ class ManifestUpdater {
|
|
|
1805
1788
|
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), exports.ErrorType.UpdateManifestFailed);
|
|
1806
1789
|
}
|
|
1807
1790
|
}
|
|
1808
|
-
static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName,
|
|
1791
|
+
static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo) {
|
|
1809
1792
|
var _a, _b, _c, _d;
|
|
1810
1793
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1811
1794
|
const warnings = [];
|
|
1812
1795
|
const functions = [];
|
|
1813
|
-
const
|
|
1796
|
+
const functionNamesMap = {};
|
|
1814
1797
|
const conversationStarters = [];
|
|
1815
1798
|
const paths = spec.paths;
|
|
1816
|
-
const pluginAuthObj = {
|
|
1817
|
-
type: "None",
|
|
1818
|
-
};
|
|
1819
|
-
if (authInfo) {
|
|
1820
|
-
if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
|
|
1821
|
-
pluginAuthObj.type = "OAuthPluginVault";
|
|
1822
|
-
}
|
|
1823
|
-
else if (Utils.isBearerTokenAuth(authInfo.authScheme)) {
|
|
1824
|
-
pluginAuthObj.type = "ApiKeyPluginVault";
|
|
1825
|
-
}
|
|
1826
|
-
if (pluginAuthObj.type !== "None") {
|
|
1827
|
-
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
|
|
1828
|
-
pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
|
|
1829
|
-
}
|
|
1830
|
-
}
|
|
1831
1799
|
for (const pathUrl in paths) {
|
|
1832
1800
|
const pathItem = paths[pathUrl];
|
|
1833
1801
|
if (pathItem) {
|
|
@@ -1835,36 +1803,11 @@ class ManifestUpdater {
|
|
|
1835
1803
|
for (const method in operations) {
|
|
1836
1804
|
if (options.allowMethods.includes(method)) {
|
|
1837
1805
|
const operationItem = operations[method];
|
|
1838
|
-
const confirmationBodies = [];
|
|
1839
1806
|
if (operationItem) {
|
|
1840
1807
|
const operationId = operationItem.operationId;
|
|
1841
1808
|
const safeFunctionName = operationId.replace(/[^a-zA-Z0-9]/g, "_");
|
|
1842
1809
|
const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
|
|
1843
1810
|
const summary = operationItem.summary;
|
|
1844
|
-
const paramObject = operationItem.parameters;
|
|
1845
|
-
const requestBody = operationItem.requestBody;
|
|
1846
|
-
if (paramObject) {
|
|
1847
|
-
for (let i = 0; i < paramObject.length; i++) {
|
|
1848
|
-
const param = paramObject[i];
|
|
1849
|
-
const schema = param.schema;
|
|
1850
|
-
ManifestUpdater.checkSchema(schema, method, pathUrl);
|
|
1851
|
-
confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
|
|
1852
|
-
}
|
|
1853
|
-
}
|
|
1854
|
-
if (requestBody) {
|
|
1855
|
-
const requestJsonBody = requestBody.content["application/json"];
|
|
1856
|
-
const requestBodySchema = requestJsonBody.schema;
|
|
1857
|
-
if (Utils.isObjectSchema(requestBodySchema)) {
|
|
1858
|
-
for (const property in requestBodySchema.properties) {
|
|
1859
|
-
const schema = requestBodySchema.properties[property];
|
|
1860
|
-
ManifestUpdater.checkSchema(schema, method, pathUrl);
|
|
1861
|
-
confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
|
|
1862
|
-
}
|
|
1863
|
-
}
|
|
1864
|
-
else {
|
|
1865
|
-
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
|
|
1866
|
-
}
|
|
1867
|
-
}
|
|
1868
1811
|
let funcDescription = operationItem.description || operationItem.summary || "";
|
|
1869
1812
|
if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
|
|
1870
1813
|
warnings.push({
|
|
@@ -1898,19 +1841,66 @@ class ManifestUpdater {
|
|
|
1898
1841
|
}
|
|
1899
1842
|
}
|
|
1900
1843
|
if (options.allowConfirmation && method !== ConstantString.GetMethod) {
|
|
1901
|
-
|
|
1902
|
-
|
|
1844
|
+
const paramObject = operationItem.parameters;
|
|
1845
|
+
const requestBody = operationItem.requestBody;
|
|
1846
|
+
const confirmationBodies = [];
|
|
1847
|
+
if (paramObject) {
|
|
1848
|
+
for (let i = 0; i < paramObject.length; i++) {
|
|
1849
|
+
const param = paramObject[i];
|
|
1850
|
+
const schema = param.schema;
|
|
1851
|
+
ManifestUpdater.checkSchema(schema, method, pathUrl);
|
|
1852
|
+
confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
if (requestBody) {
|
|
1856
|
+
const requestJsonBody = Utils.getJsonContentType(requestBody);
|
|
1857
|
+
const requestBodySchema = requestJsonBody.schema;
|
|
1858
|
+
if (Utils.isObjectSchema(requestBodySchema)) {
|
|
1859
|
+
for (const property in requestBodySchema.properties) {
|
|
1860
|
+
const schema = requestBodySchema.properties[property];
|
|
1861
|
+
ManifestUpdater.checkSchema(schema, method, pathUrl);
|
|
1862
|
+
confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
else {
|
|
1866
|
+
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
|
|
1867
|
+
}
|
|
1903
1868
|
}
|
|
1904
|
-
funcObj.capabilities.confirmation = {
|
|
1905
|
-
type: "AdaptiveCard",
|
|
1906
|
-
title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
|
|
1907
|
-
};
|
|
1908
1869
|
if (confirmationBodies.length > 0) {
|
|
1870
|
+
if (!funcObj.capabilities) {
|
|
1871
|
+
funcObj.capabilities = {};
|
|
1872
|
+
}
|
|
1873
|
+
funcObj.capabilities.confirmation = {
|
|
1874
|
+
type: "AdaptiveCard",
|
|
1875
|
+
title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
|
|
1876
|
+
};
|
|
1909
1877
|
funcObj.capabilities.confirmation.body = confirmationBodies.join("\n");
|
|
1910
1878
|
}
|
|
1911
1879
|
}
|
|
1912
1880
|
functions.push(funcObj);
|
|
1913
|
-
|
|
1881
|
+
const authInfo = authMap[operationId];
|
|
1882
|
+
let key = "None";
|
|
1883
|
+
let authName = "None";
|
|
1884
|
+
if (authInfo) {
|
|
1885
|
+
if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
|
|
1886
|
+
key = "OAuthPluginVault";
|
|
1887
|
+
authName = authInfo.name;
|
|
1888
|
+
}
|
|
1889
|
+
else if (Utils.isBearerTokenAuth(authInfo.authScheme) ||
|
|
1890
|
+
Utils.isAPIKeyAuthButNotInCookie(authInfo.authScheme)) {
|
|
1891
|
+
key = "ApiKeyPluginVault";
|
|
1892
|
+
authName = authInfo.name;
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
if (functionNamesMap[key]) {
|
|
1896
|
+
functionNamesMap[key].functionNames.push(safeFunctionName);
|
|
1897
|
+
}
|
|
1898
|
+
else {
|
|
1899
|
+
functionNamesMap[key] = {
|
|
1900
|
+
functionNames: [safeFunctionName],
|
|
1901
|
+
authName: authName,
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1914
1904
|
const conversationStarterStr = (summary !== null && summary !== void 0 ? summary : description).slice(0, ConstantString.ConversationStarterMaxLens);
|
|
1915
1905
|
if (conversationStarterStr) {
|
|
1916
1906
|
conversationStarters.push(conversationStarterStr);
|
|
@@ -1920,6 +1910,12 @@ class ManifestUpdater {
|
|
|
1920
1910
|
}
|
|
1921
1911
|
}
|
|
1922
1912
|
}
|
|
1913
|
+
if (Object.keys(functionNamesMap).length === 0) {
|
|
1914
|
+
functionNamesMap["None"] = {
|
|
1915
|
+
functionNames: [],
|
|
1916
|
+
authName: "None",
|
|
1917
|
+
};
|
|
1918
|
+
}
|
|
1923
1919
|
let apiPlugin;
|
|
1924
1920
|
if (yield fs__default['default'].pathExists(apiPluginFilePath)) {
|
|
1925
1921
|
apiPlugin = yield fs__default['default'].readJSON(apiPluginFilePath);
|
|
@@ -1955,24 +1951,35 @@ class ManifestUpdater {
|
|
|
1955
1951
|
const relativePath = ManifestUpdater.getRelativePath(existingPluginManifestInfo.manifestPath, existingPluginManifestInfo.specPath);
|
|
1956
1952
|
apiPlugin.runtimes = apiPlugin.runtimes.filter((runtime) => runtime.spec.url !== relativePath);
|
|
1957
1953
|
}
|
|
1958
|
-
const
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1954
|
+
for (const authType in functionNamesMap) {
|
|
1955
|
+
const pluginAuthObj = {
|
|
1956
|
+
type: authType,
|
|
1957
|
+
};
|
|
1958
|
+
const authName = functionNamesMap[authType].authName;
|
|
1959
|
+
if (pluginAuthObj.type !== "None") {
|
|
1960
|
+
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authName}_${ConstantString.RegistrationIdPostfix}`);
|
|
1961
|
+
pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
|
|
1962
|
+
}
|
|
1963
|
+
const functionNamesInfo = functionNamesMap[authType];
|
|
1964
|
+
const index = apiPlugin.runtimes.findIndex((runtime) => {
|
|
1965
|
+
var _a, _b;
|
|
1966
|
+
return runtime.spec.url === specRelativePath &&
|
|
1967
|
+
runtime.type === "OpenApi" &&
|
|
1968
|
+
((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === authType;
|
|
1972
1969
|
});
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1970
|
+
if (index === -1) {
|
|
1971
|
+
apiPlugin.runtimes.push({
|
|
1972
|
+
type: "OpenApi",
|
|
1973
|
+
auth: pluginAuthObj,
|
|
1974
|
+
spec: {
|
|
1975
|
+
url: specRelativePath,
|
|
1976
|
+
},
|
|
1977
|
+
run_for_functions: functionNamesInfo.functionNames,
|
|
1978
|
+
});
|
|
1979
|
+
}
|
|
1980
|
+
else {
|
|
1981
|
+
apiPlugin.runtimes[index].run_for_functions = functionNamesInfo.functionNames;
|
|
1982
|
+
}
|
|
1976
1983
|
}
|
|
1977
1984
|
if (!apiPlugin.name_for_human) {
|
|
1978
1985
|
apiPlugin.name_for_human = appName;
|
|
@@ -2015,7 +2022,7 @@ class ManifestUpdater {
|
|
|
2015
2022
|
};
|
|
2016
2023
|
if (authInfo) {
|
|
2017
2024
|
const auth = authInfo.authScheme;
|
|
2018
|
-
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix
|
|
2025
|
+
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
|
|
2019
2026
|
if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
|
|
2020
2027
|
composeExtension.authorization = {
|
|
2021
2028
|
authType: "apiSecretServiceAuth",
|
|
@@ -2162,8 +2169,11 @@ class SpecParser {
|
|
|
2162
2169
|
yield this.parser.validate(this.spec);
|
|
2163
2170
|
}
|
|
2164
2171
|
else {
|
|
2172
|
+
// The following code still hangs for Graph API, support will be added when SwaggerParser is updated.
|
|
2173
|
+
/*
|
|
2165
2174
|
const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
|
|
2166
|
-
|
|
2175
|
+
await this.parser.validate(clonedUnResolveSpec);
|
|
2176
|
+
*/
|
|
2167
2177
|
}
|
|
2168
2178
|
}
|
|
2169
2179
|
catch (e) {
|
|
@@ -2326,7 +2336,7 @@ class SpecParser {
|
|
|
2326
2336
|
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
2327
2337
|
}
|
|
2328
2338
|
const clonedUnResolveSpec = JSON.parse(JSON.stringify(newUnResolvedSpec));
|
|
2329
|
-
const newSpec =
|
|
2339
|
+
const newSpec = yield this.deReferenceSpec(clonedUnResolveSpec);
|
|
2330
2340
|
return [newUnResolvedSpec, newSpec];
|
|
2331
2341
|
}
|
|
2332
2342
|
catch (err) {
|
|
@@ -2337,6 +2347,12 @@ class SpecParser {
|
|
|
2337
2347
|
}
|
|
2338
2348
|
});
|
|
2339
2349
|
}
|
|
2350
|
+
deReferenceSpec(spec) {
|
|
2351
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2352
|
+
const result = yield this.parser.dereference(spec);
|
|
2353
|
+
return result;
|
|
2354
|
+
});
|
|
2355
|
+
}
|
|
2340
2356
|
/**
|
|
2341
2357
|
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
2342
2358
|
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
@@ -2354,7 +2370,6 @@ class SpecParser {
|
|
|
2354
2370
|
const newSpecs = yield this.getFilteredSpecs(filter, signal);
|
|
2355
2371
|
const newUnResolvedSpec = newSpecs[0];
|
|
2356
2372
|
const newSpec = newSpecs[1];
|
|
2357
|
-
const authInfo = Utils.getAuthInfo(newSpec);
|
|
2358
2373
|
const paths = newUnResolvedSpec.paths;
|
|
2359
2374
|
for (const pathUrl in paths) {
|
|
2360
2375
|
const operations = paths[pathUrl];
|
|
@@ -2362,15 +2377,22 @@ class SpecParser {
|
|
|
2362
2377
|
const operationItem = operations[method];
|
|
2363
2378
|
const operationId = operationItem.operationId;
|
|
2364
2379
|
const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
|
|
2365
|
-
if (
|
|
2366
|
-
|
|
2380
|
+
if (containsSpecialCharacters) {
|
|
2381
|
+
operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
|
|
2382
|
+
result.warnings.push({
|
|
2383
|
+
type: exports.WarningType.OperationIdContainsSpecialCharacters,
|
|
2384
|
+
content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
|
|
2385
|
+
data: operationId,
|
|
2386
|
+
});
|
|
2387
|
+
}
|
|
2388
|
+
const authArray = Utils.getAuthArray(operationItem.security, newSpec);
|
|
2389
|
+
if (Utils.isNotSupportedAuth(authArray)) {
|
|
2390
|
+
result.warnings.push({
|
|
2391
|
+
type: exports.WarningType.UnsupportedAuthType,
|
|
2392
|
+
content: Utils.format(ConstantString.AuthTypeIsNotSupported, operationId),
|
|
2393
|
+
data: operationId,
|
|
2394
|
+
});
|
|
2367
2395
|
}
|
|
2368
|
-
operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
|
|
2369
|
-
result.warnings.push({
|
|
2370
|
-
type: exports.WarningType.OperationIdContainsSpecialCharacters,
|
|
2371
|
-
content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
|
|
2372
|
-
data: operationId,
|
|
2373
|
-
});
|
|
2374
2396
|
}
|
|
2375
2397
|
}
|
|
2376
2398
|
yield this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
|
|
@@ -2383,7 +2405,8 @@ class SpecParser {
|
|
|
2383
2405
|
specPath: this.pathOrSpec,
|
|
2384
2406
|
}
|
|
2385
2407
|
: undefined;
|
|
2386
|
-
const
|
|
2408
|
+
const authMap = Utils.getAuthMap(newSpec);
|
|
2409
|
+
const [updatedManifest, apiPlugin, warnings] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authMap, existingPluginManifestInfo);
|
|
2387
2410
|
result.warnings.push(...warnings);
|
|
2388
2411
|
yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 4 });
|
|
2389
2412
|
yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });
|
|
@@ -2463,6 +2486,54 @@ class SpecParser {
|
|
|
2463
2486
|
return result;
|
|
2464
2487
|
});
|
|
2465
2488
|
}
|
|
2489
|
+
/**
|
|
2490
|
+
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
2491
|
+
* @param pluginFilePath A file path of the plugin manifest file to update.
|
|
2492
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
2493
|
+
*/
|
|
2494
|
+
generateAdaptiveCardInPlugin(pluginFilePath, filter, signal) {
|
|
2495
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2496
|
+
if (!this.options.allowResponseSemantics) {
|
|
2497
|
+
return;
|
|
2498
|
+
}
|
|
2499
|
+
const newSpecs = yield this.getFilteredSpecs(filter, signal);
|
|
2500
|
+
const newSpec = newSpecs[1];
|
|
2501
|
+
const apiPlugin = (yield fs__default['default'].readJSON(pluginFilePath));
|
|
2502
|
+
const paths = newSpec.paths;
|
|
2503
|
+
for (const pathUrl in paths) {
|
|
2504
|
+
const pathItem = paths[pathUrl];
|
|
2505
|
+
if (pathItem) {
|
|
2506
|
+
const operations = pathItem;
|
|
2507
|
+
for (const method in operations) {
|
|
2508
|
+
if (this.options.allowMethods.includes(method)) {
|
|
2509
|
+
const operationItem = operations[method];
|
|
2510
|
+
if (operationItem) {
|
|
2511
|
+
try {
|
|
2512
|
+
const operationId = operationItem.operationId;
|
|
2513
|
+
const safeFunctionName = operationId.replace(/[^a-zA-Z0-9]/g, "_");
|
|
2514
|
+
if (apiPlugin.functions.findIndex((func) => func.name === safeFunctionName) === -1) {
|
|
2515
|
+
continue;
|
|
2516
|
+
}
|
|
2517
|
+
const { json } = Utils.getResponseJson(operationItem);
|
|
2518
|
+
if (json.schema) {
|
|
2519
|
+
const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operationItem, false, 5);
|
|
2520
|
+
const responseSemantic = wrapResponseSemantics(card, jsonPath);
|
|
2521
|
+
apiPlugin.functions.find((func) => func.name === safeFunctionName).capabilities = {
|
|
2522
|
+
response_semantics: responseSemantic,
|
|
2523
|
+
};
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
catch (err) {
|
|
2527
|
+
throw new SpecParserError(err.toString(), exports.ErrorType.GenerateAdaptiveCardFailed);
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });
|
|
2535
|
+
});
|
|
2536
|
+
}
|
|
2466
2537
|
loadSpec() {
|
|
2467
2538
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2468
2539
|
if (!this.spec) {
|
|
@@ -2475,7 +2546,7 @@ class SpecParser {
|
|
|
2475
2546
|
this.isSwaggerFile = true;
|
|
2476
2547
|
}
|
|
2477
2548
|
const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
|
|
2478
|
-
this.spec =
|
|
2549
|
+
this.spec = yield this.deReferenceSpec(clonedUnResolveSpec);
|
|
2479
2550
|
}
|
|
2480
2551
|
});
|
|
2481
2552
|
}
|