@microsoft/m365-spec-parser 0.2.4 → 0.2.5-alpha.4da5c3b2d.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 +299 -276
- 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 +302 -277
- 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 +2 -0
- package/dist/src/utils.d.ts +6 -3
- package/package.json +4 -4
package/dist/index.node.cjs.js
CHANGED
|
@@ -9,6 +9,7 @@ var fs = require('fs-extra');
|
|
|
9
9
|
var path = require('path');
|
|
10
10
|
var teamsManifest = require('@microsoft/teams-manifest');
|
|
11
11
|
var crypto = require('crypto');
|
|
12
|
+
var jsonSchemaRefParser = require('@apidevtools/json-schema-ref-parser');
|
|
12
13
|
|
|
13
14
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
14
15
|
|
|
@@ -80,11 +81,8 @@ exports.ErrorType = void 0;
|
|
|
80
81
|
ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
|
|
81
82
|
ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
|
|
82
83
|
ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
|
|
83
|
-
ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
|
|
84
84
|
ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
|
|
85
85
|
ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
|
|
86
|
-
ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
|
|
87
|
-
ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
|
|
88
86
|
ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
|
|
89
87
|
ErrorType["NoParameter"] = "no-parameter";
|
|
90
88
|
ErrorType["NoAPIInfo"] = "no-api-info";
|
|
@@ -104,6 +102,7 @@ exports.WarningType = void 0;
|
|
|
104
102
|
WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
|
|
105
103
|
WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
|
|
106
104
|
WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
|
|
105
|
+
WarningType["UnsupportedAuthType"] = "unsupported-auth-type";
|
|
107
106
|
WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
|
|
108
107
|
WarningType["Unknown"] = "unknown";
|
|
109
108
|
})(exports.WarningType || (exports.WarningType = {}));
|
|
@@ -143,6 +142,7 @@ ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please conve
|
|
|
143
142
|
ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
|
|
144
143
|
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
145
144
|
ConstantString.OperationIdContainsSpecialCharacters = "Operation id '%s' in OpenAPI description document contained special characters and was renamed to '%s'.";
|
|
145
|
+
ConstantString.AuthTypeIsNotSupported = "Unsupported authorization type in API '%s'. No authorization will be used.";
|
|
146
146
|
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
147
147
|
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
148
|
ConstantString.GenerateJsonDataFailed = "Failed to generate JSON data for api: %s due to %s.";
|
|
@@ -152,17 +152,12 @@ ConstantString.WrappedCardResponseLayout = "list";
|
|
|
152
152
|
ConstantString.GetMethod = "get";
|
|
153
153
|
ConstantString.PostMethod = "post";
|
|
154
154
|
ConstantString.AdaptiveCardVersion = "1.5";
|
|
155
|
-
ConstantString.AdaptiveCardSchema = "
|
|
155
|
+
ConstantString.AdaptiveCardSchema = "https://adaptivecards.io/schemas/adaptive-card.json";
|
|
156
156
|
ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
157
157
|
ConstantString.TextBlockType = "TextBlock";
|
|
158
158
|
ConstantString.ImageType = "Image";
|
|
159
159
|
ConstantString.ContainerType = "Container";
|
|
160
|
-
ConstantString.RegistrationIdPostfix =
|
|
161
|
-
apiKey: "REGISTRATION_ID",
|
|
162
|
-
oauth2: "CONFIGURATION_ID",
|
|
163
|
-
http: "REGISTRATION_ID",
|
|
164
|
-
openIdConnect: "REGISTRATION_ID",
|
|
165
|
-
};
|
|
160
|
+
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
166
161
|
ConstantString.ResponseCodeFor20X = [
|
|
167
162
|
"200",
|
|
168
163
|
"201",
|
|
@@ -174,6 +169,7 @@ ConstantString.ResponseCodeFor20X = [
|
|
|
174
169
|
"207",
|
|
175
170
|
"208",
|
|
176
171
|
"226",
|
|
172
|
+
"2XX",
|
|
177
173
|
"default",
|
|
178
174
|
];
|
|
179
175
|
ConstantString.AllOperationMethods = [
|
|
@@ -239,17 +235,6 @@ class SpecParserError extends Error {
|
|
|
239
235
|
|
|
240
236
|
// Copyright (c) Microsoft Corporation.
|
|
241
237
|
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
238
|
static isObjectSchema(schema) {
|
|
254
239
|
return schema.type === "object" || (!schema.type && !!schema.properties);
|
|
255
240
|
}
|
|
@@ -262,11 +247,32 @@ class Utils {
|
|
|
262
247
|
static isAPIKeyAuth(authScheme) {
|
|
263
248
|
return authScheme.type === "apiKey";
|
|
264
249
|
}
|
|
250
|
+
static isAPIKeyAuthButNotInCookie(authScheme) {
|
|
251
|
+
return authScheme.type === "apiKey" && authScheme.in !== "cookie";
|
|
252
|
+
}
|
|
265
253
|
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
266
254
|
return !!(authScheme.type === "oauth2" &&
|
|
267
255
|
authScheme.flows &&
|
|
268
256
|
authScheme.flows.authorizationCode);
|
|
269
257
|
}
|
|
258
|
+
static isNotSupportedAuth(authSchemeArray) {
|
|
259
|
+
if (authSchemeArray.length === 0) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
for (const auths of authSchemeArray) {
|
|
266
|
+
if (auths.length === 1) {
|
|
267
|
+
if (Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme) ||
|
|
268
|
+
Utils.isBearerTokenAuth(auths[0].authScheme) ||
|
|
269
|
+
Utils.isAPIKeyAuthButNotInCookie(auths[0].authScheme)) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
270
276
|
static getAuthArray(securities, spec) {
|
|
271
277
|
var _a;
|
|
272
278
|
const result = [];
|
|
@@ -291,6 +297,20 @@ class Utils {
|
|
|
291
297
|
result.sort((a, b) => a[0].name.localeCompare(b[0].name));
|
|
292
298
|
return result;
|
|
293
299
|
}
|
|
300
|
+
static getAuthMap(spec) {
|
|
301
|
+
const authMap = {};
|
|
302
|
+
for (const url in spec.paths) {
|
|
303
|
+
for (const method in spec.paths[url]) {
|
|
304
|
+
const operation = spec.paths[url][method];
|
|
305
|
+
const authArray = Utils.getAuthArray(operation.security, spec);
|
|
306
|
+
if (authArray && authArray.length > 0) {
|
|
307
|
+
const currentAuth = authArray[0][0];
|
|
308
|
+
authMap[operation.operationId] = currentAuth;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return authMap;
|
|
313
|
+
}
|
|
294
314
|
static getAuthInfo(spec) {
|
|
295
315
|
let authInfo = undefined;
|
|
296
316
|
for (const url in spec.paths) {
|
|
@@ -319,27 +339,33 @@ class Utils {
|
|
|
319
339
|
let multipleMediaType = false;
|
|
320
340
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
321
341
|
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
|
-
}
|
|
342
|
+
if (!responseObject) {
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
multipleMediaType = Utils.containMultipleMediaTypes(responseObject);
|
|
346
|
+
if (!allowMultipleMediaType && multipleMediaType) {
|
|
347
|
+
json = {};
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
const mediaObj = Utils.getJsonContentType(responseObject);
|
|
351
|
+
if (Object.keys(mediaObj).length > 0) {
|
|
352
|
+
json = mediaObj;
|
|
353
|
+
return { json, multipleMediaType };
|
|
339
354
|
}
|
|
340
355
|
}
|
|
341
356
|
return { json, multipleMediaType };
|
|
342
357
|
}
|
|
358
|
+
static getJsonContentType(responseObject) {
|
|
359
|
+
if (responseObject.content) {
|
|
360
|
+
for (const contentType of Object.keys(responseObject.content)) {
|
|
361
|
+
// json media type can also be "application/json; charset=utf-8"
|
|
362
|
+
if (contentType.indexOf("application/json") >= 0) {
|
|
363
|
+
return responseObject.content[contentType];
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return {};
|
|
368
|
+
}
|
|
343
369
|
static convertPathToCamelCase(path) {
|
|
344
370
|
const pathSegments = path.split(/[./{]/);
|
|
345
371
|
const camelCaseSegments = pathSegments.map((segment) => {
|
|
@@ -375,7 +401,7 @@ class Utils {
|
|
|
375
401
|
}
|
|
376
402
|
return newStr;
|
|
377
403
|
}
|
|
378
|
-
static checkServerUrl(servers) {
|
|
404
|
+
static checkServerUrl(servers, allowHttp = false) {
|
|
379
405
|
const errors = [];
|
|
380
406
|
let serverUrl;
|
|
381
407
|
try {
|
|
@@ -398,8 +424,7 @@ class Utils {
|
|
|
398
424
|
data: servers,
|
|
399
425
|
});
|
|
400
426
|
}
|
|
401
|
-
else if (protocol !== "https:") {
|
|
402
|
-
// Http server url is not supported
|
|
427
|
+
else if (protocol !== "https:" && !(protocol === "http:" && allowHttp)) {
|
|
403
428
|
const protocolString = protocol.slice(0, -1);
|
|
404
429
|
errors.push({
|
|
405
430
|
type: exports.ErrorType.UrlProtocolNotSupported,
|
|
@@ -415,10 +440,11 @@ class Utils {
|
|
|
415
440
|
let hasTopLevelServers = false;
|
|
416
441
|
let hasPathLevelServers = false;
|
|
417
442
|
let hasOperationLevelServers = false;
|
|
443
|
+
const allowHttp = options.projectType === exports.ProjectType.Copilot;
|
|
418
444
|
if (spec.servers && spec.servers.length >= 1) {
|
|
419
445
|
hasTopLevelServers = true;
|
|
420
446
|
// for multiple server, we only use the first url
|
|
421
|
-
const serverErrors = Utils.checkServerUrl(spec.servers);
|
|
447
|
+
const serverErrors = Utils.checkServerUrl(spec.servers, allowHttp);
|
|
422
448
|
errors.push(...serverErrors);
|
|
423
449
|
}
|
|
424
450
|
const paths = spec.paths;
|
|
@@ -426,7 +452,7 @@ class Utils {
|
|
|
426
452
|
const methods = paths[path];
|
|
427
453
|
if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
|
|
428
454
|
hasPathLevelServers = true;
|
|
429
|
-
const serverErrors = Utils.checkServerUrl(methods.servers);
|
|
455
|
+
const serverErrors = Utils.checkServerUrl(methods.servers, allowHttp);
|
|
430
456
|
errors.push(...serverErrors);
|
|
431
457
|
}
|
|
432
458
|
for (const method in methods) {
|
|
@@ -434,7 +460,7 @@ class Utils {
|
|
|
434
460
|
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
435
461
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
436
462
|
hasOperationLevelServers = true;
|
|
437
|
-
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
463
|
+
const serverErrors = Utils.checkServerUrl(operationObject.servers, allowHttp);
|
|
438
464
|
errors.push(...serverErrors);
|
|
439
465
|
}
|
|
440
466
|
}
|
|
@@ -723,22 +749,6 @@ class Validator {
|
|
|
723
749
|
}
|
|
724
750
|
return result;
|
|
725
751
|
}
|
|
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
752
|
validateServer(method, path) {
|
|
743
753
|
const result = { isValid: true, reason: [] };
|
|
744
754
|
const serverObj = Utils.getServerObject(this.spec, method, path);
|
|
@@ -747,8 +757,8 @@ class Validator {
|
|
|
747
757
|
result.reason.push(exports.ErrorType.NoServerInformation);
|
|
748
758
|
}
|
|
749
759
|
else {
|
|
750
|
-
|
|
751
|
-
const serverValidateResult = Utils.checkServerUrl([serverObj]);
|
|
760
|
+
const allowHttp = this.projectType === exports.ProjectType.Copilot;
|
|
761
|
+
const serverValidateResult = Utils.checkServerUrl([serverObj], allowHttp);
|
|
752
762
|
result.reason.push(...serverValidateResult.map((item) => item.type));
|
|
753
763
|
}
|
|
754
764
|
return result;
|
|
@@ -771,6 +781,9 @@ class Validator {
|
|
|
771
781
|
reason: [exports.ErrorType.MultipleAuthNotSupported],
|
|
772
782
|
};
|
|
773
783
|
}
|
|
784
|
+
if (this.projectType === exports.ProjectType.Copilot) {
|
|
785
|
+
return { isValid: true, reason: [] };
|
|
786
|
+
}
|
|
774
787
|
for (const auths of authSchemeArray) {
|
|
775
788
|
if (auths.length === 1) {
|
|
776
789
|
if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
@@ -783,114 +796,6 @@ class Validator {
|
|
|
783
796
|
}
|
|
784
797
|
return { isValid: false, reason: [exports.ErrorType.AuthTypeIsNotSupported] };
|
|
785
798
|
}
|
|
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
799
|
}
|
|
895
800
|
|
|
896
801
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -900,7 +805,6 @@ class CopilotValidator extends Validator {
|
|
|
900
805
|
this.projectType = exports.ProjectType.Copilot;
|
|
901
806
|
this.options = options;
|
|
902
807
|
this.spec = spec;
|
|
903
|
-
this.checkCircularReference();
|
|
904
808
|
}
|
|
905
809
|
validateSpec() {
|
|
906
810
|
const result = { errors: [], warnings: [] };
|
|
@@ -926,10 +830,6 @@ class CopilotValidator extends Validator {
|
|
|
926
830
|
if (!methodAndPathResult.isValid) {
|
|
927
831
|
return methodAndPathResult;
|
|
928
832
|
}
|
|
929
|
-
const circularReferenceResult = this.validateCircularReference(method, path);
|
|
930
|
-
if (!circularReferenceResult.isValid) {
|
|
931
|
-
return circularReferenceResult;
|
|
932
|
-
}
|
|
933
833
|
const operationObject = this.spec.paths[path][method];
|
|
934
834
|
// validate auth
|
|
935
835
|
const authCheckResult = this.validateAuth(method, path);
|
|
@@ -941,24 +841,6 @@ class CopilotValidator extends Validator {
|
|
|
941
841
|
// validate server
|
|
942
842
|
const validateServerResult = this.validateServer(method, path);
|
|
943
843
|
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
844
|
if (result.reason.length > 0) {
|
|
963
845
|
result.isValid = false;
|
|
964
846
|
}
|
|
@@ -1050,6 +932,108 @@ class SMEValidator extends Validator {
|
|
|
1050
932
|
}
|
|
1051
933
|
return result;
|
|
1052
934
|
}
|
|
935
|
+
validateResponse(method, path) {
|
|
936
|
+
const result = { isValid: true, reason: [] };
|
|
937
|
+
const operationObject = this.spec.paths[path][method];
|
|
938
|
+
const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
|
|
939
|
+
// only support response body only contains “application/json” content type
|
|
940
|
+
if (multipleMediaType) {
|
|
941
|
+
result.reason.push(exports.ErrorType.ResponseContainMultipleMediaTypes);
|
|
942
|
+
}
|
|
943
|
+
else if (Object.keys(json).length === 0) {
|
|
944
|
+
// response body should not be empty
|
|
945
|
+
result.reason.push(exports.ErrorType.ResponseJsonIsEmpty);
|
|
946
|
+
}
|
|
947
|
+
return result;
|
|
948
|
+
}
|
|
949
|
+
checkPostBodySchema(schema, isRequired = false) {
|
|
950
|
+
var _a;
|
|
951
|
+
const paramResult = {
|
|
952
|
+
requiredNum: 0,
|
|
953
|
+
optionalNum: 0,
|
|
954
|
+
isValid: true,
|
|
955
|
+
reason: [],
|
|
956
|
+
};
|
|
957
|
+
if (Object.keys(schema).length === 0) {
|
|
958
|
+
return paramResult;
|
|
959
|
+
}
|
|
960
|
+
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
961
|
+
const isCopilot = this.projectType === exports.ProjectType.Copilot;
|
|
962
|
+
if (schema.type === "string" ||
|
|
963
|
+
schema.type === "integer" ||
|
|
964
|
+
schema.type === "boolean" ||
|
|
965
|
+
schema.type === "number") {
|
|
966
|
+
if (isRequiredWithoutDefault) {
|
|
967
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
968
|
+
}
|
|
969
|
+
else {
|
|
970
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
else if (Utils.isObjectSchema(schema)) {
|
|
974
|
+
const { properties } = schema;
|
|
975
|
+
for (const property in properties) {
|
|
976
|
+
let isRequired = false;
|
|
977
|
+
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
978
|
+
isRequired = true;
|
|
979
|
+
}
|
|
980
|
+
const result = this.checkPostBodySchema(properties[property], isRequired);
|
|
981
|
+
paramResult.requiredNum += result.requiredNum;
|
|
982
|
+
paramResult.optionalNum += result.optionalNum;
|
|
983
|
+
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
984
|
+
paramResult.reason.push(...result.reason);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
else {
|
|
988
|
+
if (isRequiredWithoutDefault && !isCopilot) {
|
|
989
|
+
paramResult.isValid = false;
|
|
990
|
+
paramResult.reason.push(exports.ErrorType.PostBodyContainsRequiredUnsupportedSchema);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
return paramResult;
|
|
994
|
+
}
|
|
995
|
+
checkParamSchema(paramObject) {
|
|
996
|
+
const paramResult = {
|
|
997
|
+
requiredNum: 0,
|
|
998
|
+
optionalNum: 0,
|
|
999
|
+
isValid: true,
|
|
1000
|
+
reason: [],
|
|
1001
|
+
};
|
|
1002
|
+
if (!paramObject) {
|
|
1003
|
+
return paramResult;
|
|
1004
|
+
}
|
|
1005
|
+
for (let i = 0; i < paramObject.length; i++) {
|
|
1006
|
+
const param = paramObject[i];
|
|
1007
|
+
const schema = param.schema;
|
|
1008
|
+
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
1009
|
+
if (param.in === "header" || param.in === "cookie") {
|
|
1010
|
+
if (isRequiredWithoutDefault) {
|
|
1011
|
+
paramResult.isValid = false;
|
|
1012
|
+
paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
1013
|
+
}
|
|
1014
|
+
continue;
|
|
1015
|
+
}
|
|
1016
|
+
if (schema.type !== "boolean" &&
|
|
1017
|
+
schema.type !== "string" &&
|
|
1018
|
+
schema.type !== "number" &&
|
|
1019
|
+
schema.type !== "integer") {
|
|
1020
|
+
if (isRequiredWithoutDefault) {
|
|
1021
|
+
paramResult.isValid = false;
|
|
1022
|
+
paramResult.reason.push(exports.ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
1023
|
+
}
|
|
1024
|
+
continue;
|
|
1025
|
+
}
|
|
1026
|
+
if (param.in === "query" || param.in === "path") {
|
|
1027
|
+
if (isRequiredWithoutDefault) {
|
|
1028
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
1029
|
+
}
|
|
1030
|
+
else {
|
|
1031
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
return paramResult;
|
|
1036
|
+
}
|
|
1053
1037
|
validateParamCount(postBodyResult, paramResult) {
|
|
1054
1038
|
const result = { isValid: true, reason: [] };
|
|
1055
1039
|
const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
|
|
@@ -1751,7 +1735,7 @@ function inferProperties(card) {
|
|
|
1751
1735
|
|
|
1752
1736
|
// Copyright (c) Microsoft Corporation.
|
|
1753
1737
|
class ManifestUpdater {
|
|
1754
|
-
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options,
|
|
1738
|
+
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authMap, existingPluginManifestInfo) {
|
|
1755
1739
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1756
1740
|
const manifest = yield fs__default['default'].readJSON(manifestPath);
|
|
1757
1741
|
const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
|
|
@@ -1782,7 +1766,7 @@ class ManifestUpdater {
|
|
|
1782
1766
|
}
|
|
1783
1767
|
const appName = this.removeEnvs(manifest.name.short);
|
|
1784
1768
|
const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
|
|
1785
|
-
const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName,
|
|
1769
|
+
const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo);
|
|
1786
1770
|
return [manifest, apiPlugin, warnings];
|
|
1787
1771
|
});
|
|
1788
1772
|
}
|
|
@@ -1805,29 +1789,14 @@ class ManifestUpdater {
|
|
|
1805
1789
|
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), exports.ErrorType.UpdateManifestFailed);
|
|
1806
1790
|
}
|
|
1807
1791
|
}
|
|
1808
|
-
static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName,
|
|
1792
|
+
static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authMap, options, existingPluginManifestInfo) {
|
|
1809
1793
|
var _a, _b, _c, _d;
|
|
1810
1794
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1811
1795
|
const warnings = [];
|
|
1812
1796
|
const functions = [];
|
|
1813
|
-
const
|
|
1797
|
+
const functionNamesMap = {};
|
|
1814
1798
|
const conversationStarters = [];
|
|
1815
1799
|
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
1800
|
for (const pathUrl in paths) {
|
|
1832
1801
|
const pathItem = paths[pathUrl];
|
|
1833
1802
|
if (pathItem) {
|
|
@@ -1835,36 +1804,11 @@ class ManifestUpdater {
|
|
|
1835
1804
|
for (const method in operations) {
|
|
1836
1805
|
if (options.allowMethods.includes(method)) {
|
|
1837
1806
|
const operationItem = operations[method];
|
|
1838
|
-
const confirmationBodies = [];
|
|
1839
1807
|
if (operationItem) {
|
|
1840
1808
|
const operationId = operationItem.operationId;
|
|
1841
1809
|
const safeFunctionName = operationId.replace(/[^a-zA-Z0-9]/g, "_");
|
|
1842
1810
|
const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
|
|
1843
1811
|
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
1812
|
let funcDescription = operationItem.description || operationItem.summary || "";
|
|
1869
1813
|
if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
|
|
1870
1814
|
warnings.push({
|
|
@@ -1898,19 +1842,66 @@ class ManifestUpdater {
|
|
|
1898
1842
|
}
|
|
1899
1843
|
}
|
|
1900
1844
|
if (options.allowConfirmation && method !== ConstantString.GetMethod) {
|
|
1901
|
-
|
|
1902
|
-
|
|
1845
|
+
const paramObject = operationItem.parameters;
|
|
1846
|
+
const requestBody = operationItem.requestBody;
|
|
1847
|
+
const confirmationBodies = [];
|
|
1848
|
+
if (paramObject) {
|
|
1849
|
+
for (let i = 0; i < paramObject.length; i++) {
|
|
1850
|
+
const param = paramObject[i];
|
|
1851
|
+
const schema = param.schema;
|
|
1852
|
+
ManifestUpdater.checkSchema(schema, method, pathUrl);
|
|
1853
|
+
confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(param.name));
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
if (requestBody) {
|
|
1857
|
+
const requestJsonBody = Utils.getJsonContentType(requestBody);
|
|
1858
|
+
const requestBodySchema = requestJsonBody.schema;
|
|
1859
|
+
if (Utils.isObjectSchema(requestBodySchema)) {
|
|
1860
|
+
for (const property in requestBodySchema.properties) {
|
|
1861
|
+
const schema = requestBodySchema.properties[property];
|
|
1862
|
+
ManifestUpdater.checkSchema(schema, method, pathUrl);
|
|
1863
|
+
confirmationBodies.push(ManifestUpdater.getConfirmationBodyItem(property));
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
else {
|
|
1867
|
+
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
|
|
1868
|
+
}
|
|
1903
1869
|
}
|
|
1904
|
-
funcObj.capabilities.confirmation = {
|
|
1905
|
-
type: "AdaptiveCard",
|
|
1906
|
-
title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
|
|
1907
|
-
};
|
|
1908
1870
|
if (confirmationBodies.length > 0) {
|
|
1871
|
+
if (!funcObj.capabilities) {
|
|
1872
|
+
funcObj.capabilities = {};
|
|
1873
|
+
}
|
|
1874
|
+
funcObj.capabilities.confirmation = {
|
|
1875
|
+
type: "AdaptiveCard",
|
|
1876
|
+
title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
|
|
1877
|
+
};
|
|
1909
1878
|
funcObj.capabilities.confirmation.body = confirmationBodies.join("\n");
|
|
1910
1879
|
}
|
|
1911
1880
|
}
|
|
1912
1881
|
functions.push(funcObj);
|
|
1913
|
-
|
|
1882
|
+
const authInfo = authMap[operationId];
|
|
1883
|
+
let key = "None";
|
|
1884
|
+
let authName = "None";
|
|
1885
|
+
if (authInfo) {
|
|
1886
|
+
if (Utils.isOAuthWithAuthCodeFlow(authInfo.authScheme)) {
|
|
1887
|
+
key = "OAuthPluginVault";
|
|
1888
|
+
authName = authInfo.name;
|
|
1889
|
+
}
|
|
1890
|
+
else if (Utils.isBearerTokenAuth(authInfo.authScheme) ||
|
|
1891
|
+
Utils.isAPIKeyAuthButNotInCookie(authInfo.authScheme)) {
|
|
1892
|
+
key = "ApiKeyPluginVault";
|
|
1893
|
+
authName = authInfo.name;
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
if (functionNamesMap[key]) {
|
|
1897
|
+
functionNamesMap[key].functionNames.push(safeFunctionName);
|
|
1898
|
+
}
|
|
1899
|
+
else {
|
|
1900
|
+
functionNamesMap[key] = {
|
|
1901
|
+
functionNames: [safeFunctionName],
|
|
1902
|
+
authName: authName,
|
|
1903
|
+
};
|
|
1904
|
+
}
|
|
1914
1905
|
const conversationStarterStr = (summary !== null && summary !== void 0 ? summary : description).slice(0, ConstantString.ConversationStarterMaxLens);
|
|
1915
1906
|
if (conversationStarterStr) {
|
|
1916
1907
|
conversationStarters.push(conversationStarterStr);
|
|
@@ -1920,6 +1911,12 @@ class ManifestUpdater {
|
|
|
1920
1911
|
}
|
|
1921
1912
|
}
|
|
1922
1913
|
}
|
|
1914
|
+
if (Object.keys(functionNamesMap).length === 0) {
|
|
1915
|
+
functionNamesMap["None"] = {
|
|
1916
|
+
functionNames: [],
|
|
1917
|
+
authName: "None",
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1923
1920
|
let apiPlugin;
|
|
1924
1921
|
if (yield fs__default['default'].pathExists(apiPluginFilePath)) {
|
|
1925
1922
|
apiPlugin = yield fs__default['default'].readJSON(apiPluginFilePath);
|
|
@@ -1955,24 +1952,35 @@ class ManifestUpdater {
|
|
|
1955
1952
|
const relativePath = ManifestUpdater.getRelativePath(existingPluginManifestInfo.manifestPath, existingPluginManifestInfo.specPath);
|
|
1956
1953
|
apiPlugin.runtimes = apiPlugin.runtimes.filter((runtime) => runtime.spec.url !== relativePath);
|
|
1957
1954
|
}
|
|
1958
|
-
const
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1955
|
+
for (const authType in functionNamesMap) {
|
|
1956
|
+
const pluginAuthObj = {
|
|
1957
|
+
type: authType,
|
|
1958
|
+
};
|
|
1959
|
+
const authName = functionNamesMap[authType].authName;
|
|
1960
|
+
if (pluginAuthObj.type !== "None") {
|
|
1961
|
+
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authName}_${ConstantString.RegistrationIdPostfix}`);
|
|
1962
|
+
pluginAuthObj.reference_id = `\${{${safeRegistrationIdName}}}`;
|
|
1963
|
+
}
|
|
1964
|
+
const functionNamesInfo = functionNamesMap[authType];
|
|
1965
|
+
const index = apiPlugin.runtimes.findIndex((runtime) => {
|
|
1966
|
+
var _a, _b;
|
|
1967
|
+
return runtime.spec.url === specRelativePath &&
|
|
1968
|
+
runtime.type === "OpenApi" &&
|
|
1969
|
+
((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === authType;
|
|
1972
1970
|
});
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1971
|
+
if (index === -1) {
|
|
1972
|
+
apiPlugin.runtimes.push({
|
|
1973
|
+
type: "OpenApi",
|
|
1974
|
+
auth: pluginAuthObj,
|
|
1975
|
+
spec: {
|
|
1976
|
+
url: specRelativePath,
|
|
1977
|
+
},
|
|
1978
|
+
run_for_functions: functionNamesInfo.functionNames,
|
|
1979
|
+
});
|
|
1980
|
+
}
|
|
1981
|
+
else {
|
|
1982
|
+
apiPlugin.runtimes[index].run_for_functions = functionNamesInfo.functionNames;
|
|
1983
|
+
}
|
|
1976
1984
|
}
|
|
1977
1985
|
if (!apiPlugin.name_for_human) {
|
|
1978
1986
|
apiPlugin.name_for_human = appName;
|
|
@@ -2015,7 +2023,7 @@ class ManifestUpdater {
|
|
|
2015
2023
|
};
|
|
2016
2024
|
if (authInfo) {
|
|
2017
2025
|
const auth = authInfo.authScheme;
|
|
2018
|
-
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix
|
|
2026
|
+
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
|
|
2019
2027
|
if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
|
|
2020
2028
|
composeExtension.authorization = {
|
|
2021
2029
|
authType: "apiSecretServiceAuth",
|
|
@@ -2145,6 +2153,7 @@ class SpecParser {
|
|
|
2145
2153
|
};
|
|
2146
2154
|
this.pathOrSpec = pathOrDoc;
|
|
2147
2155
|
this.parser = new SwaggerParser__default['default']();
|
|
2156
|
+
this.refParser = new jsonSchemaRefParser.$RefParser();
|
|
2148
2157
|
this.options = Object.assign(Object.assign({}, this.defaultOptions), (options !== null && options !== void 0 ? options : {}));
|
|
2149
2158
|
}
|
|
2150
2159
|
/**
|
|
@@ -2158,12 +2167,15 @@ class SpecParser {
|
|
|
2158
2167
|
let hash = "";
|
|
2159
2168
|
try {
|
|
2160
2169
|
yield this.loadSpec();
|
|
2161
|
-
if (!this.
|
|
2170
|
+
if (!this.refParser.$refs.circular) {
|
|
2162
2171
|
yield this.parser.validate(this.spec);
|
|
2163
2172
|
}
|
|
2164
2173
|
else {
|
|
2174
|
+
// The following code hangs for Graph API, support will be added when SwaggerParser is updated.
|
|
2175
|
+
/*
|
|
2165
2176
|
const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
|
|
2166
|
-
|
|
2177
|
+
await this.parser.validate(clonedUnResolveSpec);
|
|
2178
|
+
*/
|
|
2167
2179
|
}
|
|
2168
2180
|
}
|
|
2169
2181
|
catch (e) {
|
|
@@ -2191,7 +2203,7 @@ class SpecParser {
|
|
|
2191
2203
|
};
|
|
2192
2204
|
}
|
|
2193
2205
|
// Remote reference not supported
|
|
2194
|
-
const refPaths = this.
|
|
2206
|
+
const refPaths = this.refParser.$refs.paths();
|
|
2195
2207
|
// refPaths [0] is the current spec file path
|
|
2196
2208
|
if (refPaths.length > 1) {
|
|
2197
2209
|
errors.push({
|
|
@@ -2326,7 +2338,7 @@ class SpecParser {
|
|
|
2326
2338
|
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
2327
2339
|
}
|
|
2328
2340
|
const clonedUnResolveSpec = JSON.parse(JSON.stringify(newUnResolvedSpec));
|
|
2329
|
-
const newSpec =
|
|
2341
|
+
const newSpec = yield this.deReferenceSpec(clonedUnResolveSpec);
|
|
2330
2342
|
return [newUnResolvedSpec, newSpec];
|
|
2331
2343
|
}
|
|
2332
2344
|
catch (err) {
|
|
@@ -2337,6 +2349,12 @@ class SpecParser {
|
|
|
2337
2349
|
}
|
|
2338
2350
|
});
|
|
2339
2351
|
}
|
|
2352
|
+
deReferenceSpec(spec) {
|
|
2353
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2354
|
+
const result = yield this.refParser.dereference(spec);
|
|
2355
|
+
return result;
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2340
2358
|
/**
|
|
2341
2359
|
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
2342
2360
|
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
@@ -2354,7 +2372,6 @@ class SpecParser {
|
|
|
2354
2372
|
const newSpecs = yield this.getFilteredSpecs(filter, signal);
|
|
2355
2373
|
const newUnResolvedSpec = newSpecs[0];
|
|
2356
2374
|
const newSpec = newSpecs[1];
|
|
2357
|
-
const authInfo = Utils.getAuthInfo(newSpec);
|
|
2358
2375
|
const paths = newUnResolvedSpec.paths;
|
|
2359
2376
|
for (const pathUrl in paths) {
|
|
2360
2377
|
const operations = paths[pathUrl];
|
|
@@ -2362,15 +2379,22 @@ class SpecParser {
|
|
|
2362
2379
|
const operationItem = operations[method];
|
|
2363
2380
|
const operationId = operationItem.operationId;
|
|
2364
2381
|
const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
|
|
2365
|
-
if (
|
|
2366
|
-
|
|
2382
|
+
if (containsSpecialCharacters) {
|
|
2383
|
+
operationItem.operationId = operationId.replace(/[^a-zA-Z0-9]/g, "_");
|
|
2384
|
+
result.warnings.push({
|
|
2385
|
+
type: exports.WarningType.OperationIdContainsSpecialCharacters,
|
|
2386
|
+
content: Utils.format(ConstantString.OperationIdContainsSpecialCharacters, operationId, operationItem.operationId),
|
|
2387
|
+
data: operationId,
|
|
2388
|
+
});
|
|
2389
|
+
}
|
|
2390
|
+
const authArray = Utils.getAuthArray(operationItem.security, newSpec);
|
|
2391
|
+
if (Utils.isNotSupportedAuth(authArray)) {
|
|
2392
|
+
result.warnings.push({
|
|
2393
|
+
type: exports.WarningType.UnsupportedAuthType,
|
|
2394
|
+
content: Utils.format(ConstantString.AuthTypeIsNotSupported, operationId),
|
|
2395
|
+
data: operationId,
|
|
2396
|
+
});
|
|
2367
2397
|
}
|
|
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
2398
|
}
|
|
2375
2399
|
}
|
|
2376
2400
|
yield this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
|
|
@@ -2383,7 +2407,8 @@ class SpecParser {
|
|
|
2383
2407
|
specPath: this.pathOrSpec,
|
|
2384
2408
|
}
|
|
2385
2409
|
: undefined;
|
|
2386
|
-
const
|
|
2410
|
+
const authMap = Utils.getAuthMap(newSpec);
|
|
2411
|
+
const [updatedManifest, apiPlugin, warnings] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authMap, existingPluginManifestInfo);
|
|
2387
2412
|
result.warnings.push(...warnings);
|
|
2388
2413
|
yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 4 });
|
|
2389
2414
|
yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });
|
|
@@ -2475,7 +2500,7 @@ class SpecParser {
|
|
|
2475
2500
|
this.isSwaggerFile = true;
|
|
2476
2501
|
}
|
|
2477
2502
|
const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
|
|
2478
|
-
this.spec =
|
|
2503
|
+
this.spec = yield this.deReferenceSpec(clonedUnResolveSpec);
|
|
2479
2504
|
}
|
|
2480
2505
|
});
|
|
2481
2506
|
}
|