@microsoft/m365-spec-parser 0.2.4-rc.0 → 0.2.4
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 +193 -176
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +276 -299
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +193 -176
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +277 -302
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/constants.d.ts +4 -3
- package/dist/src/interfaces.d.ts +3 -10
- package/dist/src/manifestUpdater.d.ts +3 -3
- package/dist/src/specParser.d.ts +0 -2
- package/dist/src/utils.d.ts +3 -6
- package/package.json +4 -4
package/dist/index.node.cjs.js
CHANGED
|
@@ -9,7 +9,6 @@ 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');
|
|
13
12
|
|
|
14
13
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
15
14
|
|
|
@@ -81,8 +80,11 @@ exports.ErrorType = void 0;
|
|
|
81
80
|
ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
|
|
82
81
|
ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
|
|
83
82
|
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";
|
|
86
88
|
ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
|
|
87
89
|
ErrorType["NoParameter"] = "no-parameter";
|
|
88
90
|
ErrorType["NoAPIInfo"] = "no-api-info";
|
|
@@ -102,7 +104,6 @@ exports.WarningType = void 0;
|
|
|
102
104
|
WarningType["ConvertSwaggerToOpenAPI"] = "convert-swagger-to-openapi";
|
|
103
105
|
WarningType["FuncDescriptionTooLong"] = "function-description-too-long";
|
|
104
106
|
WarningType["OperationIdContainsSpecialCharacters"] = "operationid-contains-special-characters";
|
|
105
|
-
WarningType["UnsupportedAuthType"] = "unsupported-auth-type";
|
|
106
107
|
WarningType["GenerateJsonDataFailed"] = "generate-json-data-failed";
|
|
107
108
|
WarningType["Unknown"] = "unknown";
|
|
108
109
|
})(exports.WarningType || (exports.WarningType = {}));
|
|
@@ -142,7 +143,6 @@ ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please conve
|
|
|
142
143
|
ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
|
|
143
144
|
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
144
145
|
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,12 +152,17 @@ 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 = "http://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 =
|
|
160
|
+
ConstantString.RegistrationIdPostfix = {
|
|
161
|
+
apiKey: "REGISTRATION_ID",
|
|
162
|
+
oauth2: "CONFIGURATION_ID",
|
|
163
|
+
http: "REGISTRATION_ID",
|
|
164
|
+
openIdConnect: "REGISTRATION_ID",
|
|
165
|
+
};
|
|
161
166
|
ConstantString.ResponseCodeFor20X = [
|
|
162
167
|
"200",
|
|
163
168
|
"201",
|
|
@@ -169,7 +174,6 @@ ConstantString.ResponseCodeFor20X = [
|
|
|
169
174
|
"207",
|
|
170
175
|
"208",
|
|
171
176
|
"226",
|
|
172
|
-
"2XX",
|
|
173
177
|
"default",
|
|
174
178
|
];
|
|
175
179
|
ConstantString.AllOperationMethods = [
|
|
@@ -235,6 +239,17 @@ class SpecParserError extends Error {
|
|
|
235
239
|
|
|
236
240
|
// Copyright (c) Microsoft Corporation.
|
|
237
241
|
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
|
+
}
|
|
238
253
|
static isObjectSchema(schema) {
|
|
239
254
|
return schema.type === "object" || (!schema.type && !!schema.properties);
|
|
240
255
|
}
|
|
@@ -247,32 +262,11 @@ class Utils {
|
|
|
247
262
|
static isAPIKeyAuth(authScheme) {
|
|
248
263
|
return authScheme.type === "apiKey";
|
|
249
264
|
}
|
|
250
|
-
static isAPIKeyAuthButNotInCookie(authScheme) {
|
|
251
|
-
return authScheme.type === "apiKey" && authScheme.in !== "cookie";
|
|
252
|
-
}
|
|
253
265
|
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
254
266
|
return !!(authScheme.type === "oauth2" &&
|
|
255
267
|
authScheme.flows &&
|
|
256
268
|
authScheme.flows.authorizationCode);
|
|
257
269
|
}
|
|
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
|
-
}
|
|
276
270
|
static getAuthArray(securities, spec) {
|
|
277
271
|
var _a;
|
|
278
272
|
const result = [];
|
|
@@ -297,20 +291,6 @@ class Utils {
|
|
|
297
291
|
result.sort((a, b) => a[0].name.localeCompare(b[0].name));
|
|
298
292
|
return result;
|
|
299
293
|
}
|
|
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
|
-
}
|
|
314
294
|
static getAuthInfo(spec) {
|
|
315
295
|
let authInfo = undefined;
|
|
316
296
|
for (const url in spec.paths) {
|
|
@@ -339,32 +319,26 @@ class Utils {
|
|
|
339
319
|
let multipleMediaType = false;
|
|
340
320
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
341
321
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
342
|
-
if (
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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];
|
|
322
|
+
if (responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) {
|
|
323
|
+
for (const contentType of Object.keys(responseObject.content)) {
|
|
324
|
+
// json media type can also be "application/json; charset=utf-8"
|
|
325
|
+
if (contentType.indexOf("application/json") >= 0) {
|
|
326
|
+
multipleMediaType = false;
|
|
327
|
+
json = responseObject.content[contentType];
|
|
328
|
+
if (Utils.containMultipleMediaTypes(responseObject)) {
|
|
329
|
+
multipleMediaType = true;
|
|
330
|
+
if (!allowMultipleMediaType) {
|
|
331
|
+
json = {};
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
return { json, multipleMediaType };
|
|
336
|
+
}
|
|
337
|
+
}
|
|
364
338
|
}
|
|
365
339
|
}
|
|
366
340
|
}
|
|
367
|
-
return {};
|
|
341
|
+
return { json, multipleMediaType };
|
|
368
342
|
}
|
|
369
343
|
static convertPathToCamelCase(path) {
|
|
370
344
|
const pathSegments = path.split(/[./{]/);
|
|
@@ -401,7 +375,7 @@ class Utils {
|
|
|
401
375
|
}
|
|
402
376
|
return newStr;
|
|
403
377
|
}
|
|
404
|
-
static checkServerUrl(servers
|
|
378
|
+
static checkServerUrl(servers) {
|
|
405
379
|
const errors = [];
|
|
406
380
|
let serverUrl;
|
|
407
381
|
try {
|
|
@@ -424,7 +398,8 @@ class Utils {
|
|
|
424
398
|
data: servers,
|
|
425
399
|
});
|
|
426
400
|
}
|
|
427
|
-
else if (protocol !== "https:"
|
|
401
|
+
else if (protocol !== "https:") {
|
|
402
|
+
// Http server url is not supported
|
|
428
403
|
const protocolString = protocol.slice(0, -1);
|
|
429
404
|
errors.push({
|
|
430
405
|
type: exports.ErrorType.UrlProtocolNotSupported,
|
|
@@ -440,11 +415,10 @@ class Utils {
|
|
|
440
415
|
let hasTopLevelServers = false;
|
|
441
416
|
let hasPathLevelServers = false;
|
|
442
417
|
let hasOperationLevelServers = false;
|
|
443
|
-
const allowHttp = options.projectType === exports.ProjectType.Copilot;
|
|
444
418
|
if (spec.servers && spec.servers.length >= 1) {
|
|
445
419
|
hasTopLevelServers = true;
|
|
446
420
|
// for multiple server, we only use the first url
|
|
447
|
-
const serverErrors = Utils.checkServerUrl(spec.servers
|
|
421
|
+
const serverErrors = Utils.checkServerUrl(spec.servers);
|
|
448
422
|
errors.push(...serverErrors);
|
|
449
423
|
}
|
|
450
424
|
const paths = spec.paths;
|
|
@@ -452,7 +426,7 @@ class Utils {
|
|
|
452
426
|
const methods = paths[path];
|
|
453
427
|
if ((methods === null || methods === void 0 ? void 0 : methods.servers) && methods.servers.length >= 1) {
|
|
454
428
|
hasPathLevelServers = true;
|
|
455
|
-
const serverErrors = Utils.checkServerUrl(methods.servers
|
|
429
|
+
const serverErrors = Utils.checkServerUrl(methods.servers);
|
|
456
430
|
errors.push(...serverErrors);
|
|
457
431
|
}
|
|
458
432
|
for (const method in methods) {
|
|
@@ -460,7 +434,7 @@ class Utils {
|
|
|
460
434
|
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
461
435
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
462
436
|
hasOperationLevelServers = true;
|
|
463
|
-
const serverErrors = Utils.checkServerUrl(operationObject.servers
|
|
437
|
+
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
464
438
|
errors.push(...serverErrors);
|
|
465
439
|
}
|
|
466
440
|
}
|
|
@@ -749,6 +723,22 @@ class Validator {
|
|
|
749
723
|
}
|
|
750
724
|
return result;
|
|
751
725
|
}
|
|
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
|
+
}
|
|
752
742
|
validateServer(method, path) {
|
|
753
743
|
const result = { isValid: true, reason: [] };
|
|
754
744
|
const serverObj = Utils.getServerObject(this.spec, method, path);
|
|
@@ -757,8 +747,8 @@ class Validator {
|
|
|
757
747
|
result.reason.push(exports.ErrorType.NoServerInformation);
|
|
758
748
|
}
|
|
759
749
|
else {
|
|
760
|
-
|
|
761
|
-
const serverValidateResult = Utils.checkServerUrl([serverObj]
|
|
750
|
+
// server url should be absolute url with https protocol
|
|
751
|
+
const serverValidateResult = Utils.checkServerUrl([serverObj]);
|
|
762
752
|
result.reason.push(...serverValidateResult.map((item) => item.type));
|
|
763
753
|
}
|
|
764
754
|
return result;
|
|
@@ -781,9 +771,6 @@ class Validator {
|
|
|
781
771
|
reason: [exports.ErrorType.MultipleAuthNotSupported],
|
|
782
772
|
};
|
|
783
773
|
}
|
|
784
|
-
if (this.projectType === exports.ProjectType.Copilot) {
|
|
785
|
-
return { isValid: true, reason: [] };
|
|
786
|
-
}
|
|
787
774
|
for (const auths of authSchemeArray) {
|
|
788
775
|
if (auths.length === 1) {
|
|
789
776
|
if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
@@ -796,6 +783,114 @@ class Validator {
|
|
|
796
783
|
}
|
|
797
784
|
return { isValid: false, reason: [exports.ErrorType.AuthTypeIsNotSupported] };
|
|
798
785
|
}
|
|
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
|
+
}
|
|
799
894
|
}
|
|
800
895
|
|
|
801
896
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -805,6 +900,7 @@ class CopilotValidator extends Validator {
|
|
|
805
900
|
this.projectType = exports.ProjectType.Copilot;
|
|
806
901
|
this.options = options;
|
|
807
902
|
this.spec = spec;
|
|
903
|
+
this.checkCircularReference();
|
|
808
904
|
}
|
|
809
905
|
validateSpec() {
|
|
810
906
|
const result = { errors: [], warnings: [] };
|
|
@@ -830,6 +926,10 @@ class CopilotValidator extends Validator {
|
|
|
830
926
|
if (!methodAndPathResult.isValid) {
|
|
831
927
|
return methodAndPathResult;
|
|
832
928
|
}
|
|
929
|
+
const circularReferenceResult = this.validateCircularReference(method, path);
|
|
930
|
+
if (!circularReferenceResult.isValid) {
|
|
931
|
+
return circularReferenceResult;
|
|
932
|
+
}
|
|
833
933
|
const operationObject = this.spec.paths[path][method];
|
|
834
934
|
// validate auth
|
|
835
935
|
const authCheckResult = this.validateAuth(method, path);
|
|
@@ -841,6 +941,24 @@ class CopilotValidator extends Validator {
|
|
|
841
941
|
// validate server
|
|
842
942
|
const validateServerResult = this.validateServer(method, path);
|
|
843
943
|
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);
|
|
844
962
|
if (result.reason.length > 0) {
|
|
845
963
|
result.isValid = false;
|
|
846
964
|
}
|
|
@@ -932,108 +1050,6 @@ class SMEValidator extends Validator {
|
|
|
932
1050
|
}
|
|
933
1051
|
return result;
|
|
934
1052
|
}
|
|
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
|
-
}
|
|
1037
1053
|
validateParamCount(postBodyResult, paramResult) {
|
|
1038
1054
|
const result = { isValid: true, reason: [] };
|
|
1039
1055
|
const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
|
|
@@ -1735,7 +1751,7 @@ function inferProperties(card) {
|
|
|
1735
1751
|
|
|
1736
1752
|
// Copyright (c) Microsoft Corporation.
|
|
1737
1753
|
class ManifestUpdater {
|
|
1738
|
-
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options,
|
|
1754
|
+
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options, authInfo, existingPluginManifestInfo) {
|
|
1739
1755
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1740
1756
|
const manifest = yield fs__default['default'].readJSON(manifestPath);
|
|
1741
1757
|
const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
|
|
@@ -1766,7 +1782,7 @@ class ManifestUpdater {
|
|
|
1766
1782
|
}
|
|
1767
1783
|
const appName = this.removeEnvs(manifest.name.short);
|
|
1768
1784
|
const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
|
|
1769
|
-
const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName,
|
|
1785
|
+
const [apiPlugin, warnings] = yield ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo);
|
|
1770
1786
|
return [manifest, apiPlugin, warnings];
|
|
1771
1787
|
});
|
|
1772
1788
|
}
|
|
@@ -1789,14 +1805,29 @@ class ManifestUpdater {
|
|
|
1789
1805
|
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), exports.ErrorType.UpdateManifestFailed);
|
|
1790
1806
|
}
|
|
1791
1807
|
}
|
|
1792
|
-
static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName,
|
|
1808
|
+
static generatePluginManifestSchema(spec, specRelativePath, apiPluginFilePath, appName, authInfo, options, existingPluginManifestInfo) {
|
|
1793
1809
|
var _a, _b, _c, _d;
|
|
1794
1810
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1795
1811
|
const warnings = [];
|
|
1796
1812
|
const functions = [];
|
|
1797
|
-
const
|
|
1813
|
+
const functionNames = [];
|
|
1798
1814
|
const conversationStarters = [];
|
|
1799
1815
|
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
|
+
}
|
|
1800
1831
|
for (const pathUrl in paths) {
|
|
1801
1832
|
const pathItem = paths[pathUrl];
|
|
1802
1833
|
if (pathItem) {
|
|
@@ -1804,11 +1835,36 @@ class ManifestUpdater {
|
|
|
1804
1835
|
for (const method in operations) {
|
|
1805
1836
|
if (options.allowMethods.includes(method)) {
|
|
1806
1837
|
const operationItem = operations[method];
|
|
1838
|
+
const confirmationBodies = [];
|
|
1807
1839
|
if (operationItem) {
|
|
1808
1840
|
const operationId = operationItem.operationId;
|
|
1809
1841
|
const safeFunctionName = operationId.replace(/[^a-zA-Z0-9]/g, "_");
|
|
1810
1842
|
const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
|
|
1811
1843
|
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
|
+
}
|
|
1812
1868
|
let funcDescription = operationItem.description || operationItem.summary || "";
|
|
1813
1869
|
if (funcDescription.length > ConstantString.FunctionDescriptionMaxLens) {
|
|
1814
1870
|
warnings.push({
|
|
@@ -1842,66 +1898,19 @@ class ManifestUpdater {
|
|
|
1842
1898
|
}
|
|
1843
1899
|
}
|
|
1844
1900
|
if (options.allowConfirmation && method !== ConstantString.GetMethod) {
|
|
1845
|
-
|
|
1846
|
-
|
|
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
|
-
}
|
|
1901
|
+
if (!funcObj.capabilities) {
|
|
1902
|
+
funcObj.capabilities = {};
|
|
1869
1903
|
}
|
|
1904
|
+
funcObj.capabilities.confirmation = {
|
|
1905
|
+
type: "AdaptiveCard",
|
|
1906
|
+
title: (_b = operationItem.summary) !== null && _b !== void 0 ? _b : description,
|
|
1907
|
+
};
|
|
1870
1908
|
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
|
-
};
|
|
1878
1909
|
funcObj.capabilities.confirmation.body = confirmationBodies.join("\n");
|
|
1879
1910
|
}
|
|
1880
1911
|
}
|
|
1881
1912
|
functions.push(funcObj);
|
|
1882
|
-
|
|
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
|
-
}
|
|
1913
|
+
functionNames.push(safeFunctionName);
|
|
1905
1914
|
const conversationStarterStr = (summary !== null && summary !== void 0 ? summary : description).slice(0, ConstantString.ConversationStarterMaxLens);
|
|
1906
1915
|
if (conversationStarterStr) {
|
|
1907
1916
|
conversationStarters.push(conversationStarterStr);
|
|
@@ -1911,12 +1920,6 @@ class ManifestUpdater {
|
|
|
1911
1920
|
}
|
|
1912
1921
|
}
|
|
1913
1922
|
}
|
|
1914
|
-
if (Object.keys(functionNamesMap).length === 0) {
|
|
1915
|
-
functionNamesMap["None"] = {
|
|
1916
|
-
functionNames: [],
|
|
1917
|
-
authName: "None",
|
|
1918
|
-
};
|
|
1919
|
-
}
|
|
1920
1923
|
let apiPlugin;
|
|
1921
1924
|
if (yield fs__default['default'].pathExists(apiPluginFilePath)) {
|
|
1922
1925
|
apiPlugin = yield fs__default['default'].readJSON(apiPluginFilePath);
|
|
@@ -1952,35 +1955,24 @@ class ManifestUpdater {
|
|
|
1952
1955
|
const relativePath = ManifestUpdater.getRelativePath(existingPluginManifestInfo.manifestPath, existingPluginManifestInfo.specPath);
|
|
1953
1956
|
apiPlugin.runtimes = apiPlugin.runtimes.filter((runtime) => runtime.spec.url !== relativePath);
|
|
1954
1957
|
}
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === authType;
|
|
1958
|
+
const index = apiPlugin.runtimes.findIndex((runtime) => {
|
|
1959
|
+
var _a, _b;
|
|
1960
|
+
return runtime.spec.url === specRelativePath &&
|
|
1961
|
+
runtime.type === "OpenApi" &&
|
|
1962
|
+
((_b = (_a = runtime.auth) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : "None") === pluginAuthObj.type;
|
|
1963
|
+
});
|
|
1964
|
+
if (index === -1) {
|
|
1965
|
+
apiPlugin.runtimes.push({
|
|
1966
|
+
type: "OpenApi",
|
|
1967
|
+
auth: pluginAuthObj,
|
|
1968
|
+
spec: {
|
|
1969
|
+
url: specRelativePath,
|
|
1970
|
+
},
|
|
1971
|
+
run_for_functions: functionNames,
|
|
1970
1972
|
});
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
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
|
-
}
|
|
1973
|
+
}
|
|
1974
|
+
else {
|
|
1975
|
+
apiPlugin.runtimes[index].run_for_functions = functionNames;
|
|
1984
1976
|
}
|
|
1985
1977
|
if (!apiPlugin.name_for_human) {
|
|
1986
1978
|
apiPlugin.name_for_human = appName;
|
|
@@ -2023,7 +2015,7 @@ class ManifestUpdater {
|
|
|
2023
2015
|
};
|
|
2024
2016
|
if (authInfo) {
|
|
2025
2017
|
const auth = authInfo.authScheme;
|
|
2026
|
-
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
|
|
2018
|
+
const safeRegistrationIdName = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix[authInfo.authScheme.type]}`);
|
|
2027
2019
|
if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
|
|
2028
2020
|
composeExtension.authorization = {
|
|
2029
2021
|
authType: "apiSecretServiceAuth",
|
|
@@ -2153,7 +2145,6 @@ class SpecParser {
|
|
|
2153
2145
|
};
|
|
2154
2146
|
this.pathOrSpec = pathOrDoc;
|
|
2155
2147
|
this.parser = new SwaggerParser__default['default']();
|
|
2156
|
-
this.refParser = new jsonSchemaRefParser.$RefParser();
|
|
2157
2148
|
this.options = Object.assign(Object.assign({}, this.defaultOptions), (options !== null && options !== void 0 ? options : {}));
|
|
2158
2149
|
}
|
|
2159
2150
|
/**
|
|
@@ -2167,15 +2158,12 @@ class SpecParser {
|
|
|
2167
2158
|
let hash = "";
|
|
2168
2159
|
try {
|
|
2169
2160
|
yield this.loadSpec();
|
|
2170
|
-
if (!this.
|
|
2161
|
+
if (!this.parser.$refs.circular) {
|
|
2171
2162
|
yield this.parser.validate(this.spec);
|
|
2172
2163
|
}
|
|
2173
2164
|
else {
|
|
2174
|
-
// The following code hangs for Graph API, support will be added when SwaggerParser is updated.
|
|
2175
|
-
/*
|
|
2176
2165
|
const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
|
|
2177
|
-
|
|
2178
|
-
*/
|
|
2166
|
+
yield this.parser.validate(clonedUnResolveSpec);
|
|
2179
2167
|
}
|
|
2180
2168
|
}
|
|
2181
2169
|
catch (e) {
|
|
@@ -2203,7 +2191,7 @@ class SpecParser {
|
|
|
2203
2191
|
};
|
|
2204
2192
|
}
|
|
2205
2193
|
// Remote reference not supported
|
|
2206
|
-
const refPaths = this.
|
|
2194
|
+
const refPaths = this.parser.$refs.paths();
|
|
2207
2195
|
// refPaths [0] is the current spec file path
|
|
2208
2196
|
if (refPaths.length > 1) {
|
|
2209
2197
|
errors.push({
|
|
@@ -2338,7 +2326,7 @@ class SpecParser {
|
|
|
2338
2326
|
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
2339
2327
|
}
|
|
2340
2328
|
const clonedUnResolveSpec = JSON.parse(JSON.stringify(newUnResolvedSpec));
|
|
2341
|
-
const newSpec = yield this.
|
|
2329
|
+
const newSpec = (yield this.parser.dereference(clonedUnResolveSpec));
|
|
2342
2330
|
return [newUnResolvedSpec, newSpec];
|
|
2343
2331
|
}
|
|
2344
2332
|
catch (err) {
|
|
@@ -2349,12 +2337,6 @@ class SpecParser {
|
|
|
2349
2337
|
}
|
|
2350
2338
|
});
|
|
2351
2339
|
}
|
|
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
|
-
}
|
|
2358
2340
|
/**
|
|
2359
2341
|
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
2360
2342
|
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
@@ -2372,6 +2354,7 @@ class SpecParser {
|
|
|
2372
2354
|
const newSpecs = yield this.getFilteredSpecs(filter, signal);
|
|
2373
2355
|
const newUnResolvedSpec = newSpecs[0];
|
|
2374
2356
|
const newSpec = newSpecs[1];
|
|
2357
|
+
const authInfo = Utils.getAuthInfo(newSpec);
|
|
2375
2358
|
const paths = newUnResolvedSpec.paths;
|
|
2376
2359
|
for (const pathUrl in paths) {
|
|
2377
2360
|
const operations = paths[pathUrl];
|
|
@@ -2379,22 +2362,15 @@ class SpecParser {
|
|
|
2379
2362
|
const operationItem = operations[method];
|
|
2380
2363
|
const operationId = operationItem.operationId;
|
|
2381
2364
|
const containsSpecialCharacters = /[^a-zA-Z0-9_]/.test(operationId);
|
|
2382
|
-
if (containsSpecialCharacters) {
|
|
2383
|
-
|
|
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
|
-
});
|
|
2365
|
+
if (!containsSpecialCharacters) {
|
|
2366
|
+
continue;
|
|
2397
2367
|
}
|
|
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
|
+
});
|
|
2398
2374
|
}
|
|
2399
2375
|
}
|
|
2400
2376
|
yield this.saveFilterSpec(outputSpecPath, newUnResolvedSpec);
|
|
@@ -2407,8 +2383,7 @@ class SpecParser {
|
|
|
2407
2383
|
specPath: this.pathOrSpec,
|
|
2408
2384
|
}
|
|
2409
2385
|
: undefined;
|
|
2410
|
-
const
|
|
2411
|
-
const [updatedManifest, apiPlugin, warnings] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authMap, existingPluginManifestInfo);
|
|
2386
|
+
const [updatedManifest, apiPlugin, warnings] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options, authInfo, existingPluginManifestInfo);
|
|
2412
2387
|
result.warnings.push(...warnings);
|
|
2413
2388
|
yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 4 });
|
|
2414
2389
|
yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 4 });
|
|
@@ -2500,7 +2475,7 @@ class SpecParser {
|
|
|
2500
2475
|
this.isSwaggerFile = true;
|
|
2501
2476
|
}
|
|
2502
2477
|
const clonedUnResolveSpec = JSON.parse(JSON.stringify(this.unResolveSpec));
|
|
2503
|
-
this.spec = yield this.
|
|
2478
|
+
this.spec = (yield this.parser.dereference(clonedUnResolveSpec));
|
|
2504
2479
|
}
|
|
2505
2480
|
});
|
|
2506
2481
|
}
|