@microsoft/m365-spec-parser 0.1.1-alpha.8d8f5a0bb.0 → 0.1.1-alpha.a372ccf67.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 +75 -51
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +143 -110
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +75 -51
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +142 -109
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/constants.d.ts +3 -1
- package/dist/src/index.browser.d.ts +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/interfaces.d.ts +31 -3
- package/dist/src/manifestUpdater.d.ts +5 -5
- package/dist/src/specFilter.d.ts +2 -1
- package/dist/src/specParser.browser.d.ts +1 -1
- package/dist/src/specParser.d.ts +1 -2
- package/dist/src/utils.d.ts +11 -10
- package/package.json +3 -3
package/dist/index.node.cjs.js
CHANGED
|
@@ -61,7 +61,7 @@ exports.ErrorType = void 0;
|
|
|
61
61
|
ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
|
|
62
62
|
ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
|
|
63
63
|
ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
|
|
64
|
-
ErrorType["
|
|
64
|
+
ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
|
|
65
65
|
ErrorType["ListFailed"] = "list-failed";
|
|
66
66
|
ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
|
|
67
67
|
ErrorType["FilterSpecFailed"] = "filter-spec-failed";
|
|
@@ -92,7 +92,13 @@ exports.ValidationStatus = void 0;
|
|
|
92
92
|
ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
|
|
93
93
|
ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
|
|
94
94
|
ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
|
|
95
|
-
})(exports.ValidationStatus || (exports.ValidationStatus = {}));
|
|
95
|
+
})(exports.ValidationStatus || (exports.ValidationStatus = {}));
|
|
96
|
+
exports.ProjectType = void 0;
|
|
97
|
+
(function (ProjectType) {
|
|
98
|
+
ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
|
|
99
|
+
ProjectType[ProjectType["SME"] = 1] = "SME";
|
|
100
|
+
ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
|
|
101
|
+
})(exports.ProjectType || (exports.ProjectType = {}));
|
|
96
102
|
|
|
97
103
|
// Copyright (c) Microsoft Corporation.
|
|
98
104
|
class ConstantString {
|
|
@@ -111,7 +117,7 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
|
|
|
111
117
|
ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
|
|
112
118
|
ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
|
|
113
119
|
ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
|
|
114
|
-
ConstantString.
|
|
120
|
+
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
115
121
|
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
116
122
|
ConstantString.WrappedCardVersion = "devPreview";
|
|
117
123
|
ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
|
|
@@ -124,6 +130,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
|
124
130
|
ConstantString.TextBlockType = "TextBlock";
|
|
125
131
|
ConstantString.ContainerType = "Container";
|
|
126
132
|
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
133
|
+
ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
|
|
127
134
|
ConstantString.ResponseCodeFor20X = [
|
|
128
135
|
"200",
|
|
129
136
|
"201",
|
|
@@ -183,7 +190,8 @@ ConstantString.FullDescriptionMaxLens = 4000;
|
|
|
183
190
|
ConstantString.CommandDescriptionMaxLens = 128;
|
|
184
191
|
ConstantString.ParameterDescriptionMaxLens = 128;
|
|
185
192
|
ConstantString.CommandTitleMaxLens = 32;
|
|
186
|
-
ConstantString.ParameterTitleMaxLens = 32;
|
|
193
|
+
ConstantString.ParameterTitleMaxLens = 32;
|
|
194
|
+
ConstantString.SMERequiredParamsMaxNum = 5;
|
|
187
195
|
|
|
188
196
|
// Copyright (c) Microsoft Corporation.
|
|
189
197
|
class SpecParserError extends Error {
|
|
@@ -304,6 +312,9 @@ class Utils {
|
|
|
304
312
|
}
|
|
305
313
|
return paramResult;
|
|
306
314
|
}
|
|
315
|
+
static containMultipleMediaTypes(bodyObject) {
|
|
316
|
+
return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
|
|
317
|
+
}
|
|
307
318
|
/**
|
|
308
319
|
* Checks if the given API is supported.
|
|
309
320
|
* @param {string} method - The HTTP method of the API.
|
|
@@ -318,32 +329,40 @@ class Utils {
|
|
|
318
329
|
* 5. response body should be “application/json” and not empty, and response code should be 20X
|
|
319
330
|
* 6. only support request body with “application/json” content type
|
|
320
331
|
*/
|
|
321
|
-
static isSupportedApi(method, path, spec,
|
|
332
|
+
static isSupportedApi(method, path, spec, options) {
|
|
333
|
+
var _a;
|
|
322
334
|
const pathObj = spec.paths[path];
|
|
323
335
|
method = method.toLocaleLowerCase();
|
|
324
336
|
if (pathObj) {
|
|
325
|
-
if ((
|
|
326
|
-
pathObj[method]) {
|
|
337
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
|
|
327
338
|
const securities = pathObj[method].security;
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
339
|
+
const isTeamsAi = options.projectType === exports.ProjectType.TeamsAi;
|
|
340
|
+
const isCopilot = options.projectType === exports.ProjectType.Copilot;
|
|
341
|
+
// Teams AI project doesn't care about auth, it will use authProvider for user to implement
|
|
342
|
+
if (!isTeamsAi) {
|
|
343
|
+
const authArray = Utils.getAuthArray(securities, spec);
|
|
344
|
+
if (!Utils.isSupportedAuth(authArray, options)) {
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
331
347
|
}
|
|
332
348
|
const operationObject = pathObj[method];
|
|
333
|
-
if (!allowMissingId && !operationObject.operationId) {
|
|
349
|
+
if (!options.allowMissingId && !operationObject.operationId) {
|
|
334
350
|
return false;
|
|
335
351
|
}
|
|
336
352
|
const paramObject = operationObject.parameters;
|
|
337
353
|
const requestBody = operationObject.requestBody;
|
|
338
354
|
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
339
|
-
|
|
340
|
-
if (mediaTypesCount > 1) {
|
|
355
|
+
if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
|
|
341
356
|
return false;
|
|
342
357
|
}
|
|
343
|
-
const responseJson = Utils.getResponseJson(operationObject);
|
|
358
|
+
const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
|
|
344
359
|
if (Object.keys(responseJson).length === 0) {
|
|
345
360
|
return false;
|
|
346
361
|
}
|
|
362
|
+
// Teams AI project doesn't care about request parameters/body
|
|
363
|
+
if (isTeamsAi) {
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
347
366
|
let requestBodyParamResult = {
|
|
348
367
|
requiredNum: 0,
|
|
349
368
|
optionalNum: 0,
|
|
@@ -368,8 +387,9 @@ class Utils {
|
|
|
368
387
|
return true;
|
|
369
388
|
}
|
|
370
389
|
if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
|
|
371
|
-
if (allowMultipleParameters &&
|
|
372
|
-
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
390
|
+
if (options.allowMultipleParameters &&
|
|
391
|
+
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
392
|
+
ConstantString.SMERequiredParamsMaxNum) {
|
|
373
393
|
return true;
|
|
374
394
|
}
|
|
375
395
|
return false;
|
|
@@ -388,29 +408,31 @@ class Utils {
|
|
|
388
408
|
}
|
|
389
409
|
return false;
|
|
390
410
|
}
|
|
391
|
-
static isSupportedAuth(authSchemaArray,
|
|
411
|
+
static isSupportedAuth(authSchemaArray, options) {
|
|
392
412
|
if (authSchemaArray.length === 0) {
|
|
393
413
|
return true;
|
|
394
414
|
}
|
|
395
|
-
if (allowAPIKeyAuth || allowOauth2) {
|
|
415
|
+
if (options.allowAPIKeyAuth || options.allowOauth2) {
|
|
396
416
|
// Currently we don't support multiple auth in one operation
|
|
397
417
|
if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
|
|
398
418
|
return false;
|
|
399
419
|
}
|
|
400
420
|
for (const auths of authSchemaArray) {
|
|
401
421
|
if (auths.length === 1) {
|
|
402
|
-
if (!allowOauth2 &&
|
|
422
|
+
if (!options.allowOauth2 &&
|
|
423
|
+
options.allowAPIKeyAuth &&
|
|
424
|
+
Utils.isAPIKeyAuth(auths[0].authSchema)) {
|
|
403
425
|
return true;
|
|
404
426
|
}
|
|
405
|
-
else if (!allowAPIKeyAuth &&
|
|
406
|
-
allowOauth2 &&
|
|
407
|
-
Utils.
|
|
427
|
+
else if (!options.allowAPIKeyAuth &&
|
|
428
|
+
options.allowOauth2 &&
|
|
429
|
+
Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema)) {
|
|
408
430
|
return true;
|
|
409
431
|
}
|
|
410
|
-
else if (allowAPIKeyAuth &&
|
|
411
|
-
allowOauth2 &&
|
|
432
|
+
else if (options.allowAPIKeyAuth &&
|
|
433
|
+
options.allowOauth2 &&
|
|
412
434
|
(Utils.isAPIKeyAuth(auths[0].authSchema) ||
|
|
413
|
-
Utils.
|
|
435
|
+
Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema))) {
|
|
414
436
|
return true;
|
|
415
437
|
}
|
|
416
438
|
}
|
|
@@ -421,10 +443,11 @@ class Utils {
|
|
|
421
443
|
static isAPIKeyAuth(authSchema) {
|
|
422
444
|
return authSchema.type === "apiKey";
|
|
423
445
|
}
|
|
424
|
-
static
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
446
|
+
static isOAuthWithAuthCodeFlow(authSchema) {
|
|
447
|
+
if (authSchema.type === "oauth2" && authSchema.flows && authSchema.flows.authorizationCode) {
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
450
|
+
return false;
|
|
428
451
|
}
|
|
429
452
|
static getAuthArray(securities, spec) {
|
|
430
453
|
var _a;
|
|
@@ -452,18 +475,19 @@ class Utils {
|
|
|
452
475
|
static updateFirstLetter(str) {
|
|
453
476
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
454
477
|
}
|
|
455
|
-
static getResponseJson(operationObject) {
|
|
478
|
+
static getResponseJson(operationObject, isTeamsAiProject = false) {
|
|
456
479
|
var _a, _b;
|
|
457
480
|
let json = {};
|
|
458
481
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
459
482
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
460
|
-
const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
|
|
461
|
-
if (mediaTypesCount > 1) {
|
|
462
|
-
return {};
|
|
463
|
-
}
|
|
464
483
|
if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
|
|
465
484
|
json = responseObject.content["application/json"];
|
|
466
|
-
|
|
485
|
+
if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
|
|
486
|
+
json = {};
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
467
491
|
}
|
|
468
492
|
}
|
|
469
493
|
return json;
|
|
@@ -537,7 +561,7 @@ class Utils {
|
|
|
537
561
|
}
|
|
538
562
|
return errors;
|
|
539
563
|
}
|
|
540
|
-
static validateServer(spec,
|
|
564
|
+
static validateServer(spec, options) {
|
|
541
565
|
const errors = [];
|
|
542
566
|
let hasTopLevelServers = false;
|
|
543
567
|
let hasPathLevelServers = false;
|
|
@@ -558,7 +582,7 @@ class Utils {
|
|
|
558
582
|
}
|
|
559
583
|
for (const method in methods) {
|
|
560
584
|
const operationObject = methods[method];
|
|
561
|
-
if (Utils.isSupportedApi(method, path, spec,
|
|
585
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
562
586
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
563
587
|
hasOperationLevelServers = true;
|
|
564
588
|
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
@@ -645,7 +669,7 @@ class Utils {
|
|
|
645
669
|
param.value = schema.default;
|
|
646
670
|
}
|
|
647
671
|
}
|
|
648
|
-
static parseApiInfo(operationItem,
|
|
672
|
+
static parseApiInfo(operationItem, options) {
|
|
649
673
|
var _a, _b;
|
|
650
674
|
const requiredParams = [];
|
|
651
675
|
const optionalParams = [];
|
|
@@ -659,7 +683,7 @@ class Utils {
|
|
|
659
683
|
description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
|
|
660
684
|
};
|
|
661
685
|
const schema = param.schema;
|
|
662
|
-
if (allowMultipleParameters && schema) {
|
|
686
|
+
if (options.allowMultipleParameters && schema) {
|
|
663
687
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
664
688
|
}
|
|
665
689
|
if (param.in !== "header" && param.in !== "cookie") {
|
|
@@ -677,7 +701,7 @@ class Utils {
|
|
|
677
701
|
const requestJson = requestBody.content["application/json"];
|
|
678
702
|
if (Object.keys(requestJson).length !== 0) {
|
|
679
703
|
const schema = requestJson.schema;
|
|
680
|
-
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
|
|
704
|
+
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
|
|
681
705
|
requiredParams.push(...requiredP);
|
|
682
706
|
optionalParams.push(...optionalP);
|
|
683
707
|
}
|
|
@@ -708,14 +732,13 @@ class Utils {
|
|
|
708
732
|
}
|
|
709
733
|
return [command, warning];
|
|
710
734
|
}
|
|
711
|
-
static listSupportedAPIs(spec,
|
|
735
|
+
static listSupportedAPIs(spec, options) {
|
|
712
736
|
const paths = spec.paths;
|
|
713
737
|
const result = {};
|
|
714
738
|
for (const path in paths) {
|
|
715
739
|
const methods = paths[path];
|
|
716
740
|
for (const method in methods) {
|
|
717
|
-
|
|
718
|
-
if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2, isCopilot)) {
|
|
741
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
719
742
|
const operationObject = methods[method];
|
|
720
743
|
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
721
744
|
}
|
|
@@ -723,7 +746,7 @@ class Utils {
|
|
|
723
746
|
}
|
|
724
747
|
return result;
|
|
725
748
|
}
|
|
726
|
-
static validateSpec(spec, parser, isSwaggerFile,
|
|
749
|
+
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
727
750
|
const errors = [];
|
|
728
751
|
const warnings = [];
|
|
729
752
|
if (isSwaggerFile) {
|
|
@@ -733,7 +756,7 @@ class Utils {
|
|
|
733
756
|
});
|
|
734
757
|
}
|
|
735
758
|
// Server validation
|
|
736
|
-
const serverErrors = Utils.validateServer(spec,
|
|
759
|
+
const serverErrors = Utils.validateServer(spec, options);
|
|
737
760
|
errors.push(...serverErrors);
|
|
738
761
|
// Remote reference not supported
|
|
739
762
|
const refPaths = parser.$refs.paths();
|
|
@@ -746,7 +769,7 @@ class Utils {
|
|
|
746
769
|
});
|
|
747
770
|
}
|
|
748
771
|
// No supported API
|
|
749
|
-
const apiMap = Utils.listSupportedAPIs(spec,
|
|
772
|
+
const apiMap = Utils.listSupportedAPIs(spec, options);
|
|
750
773
|
if (Object.keys(apiMap).length === 0) {
|
|
751
774
|
errors.push({
|
|
752
775
|
type: exports.ErrorType.NoSupportedApi,
|
|
@@ -802,14 +825,14 @@ class Utils {
|
|
|
802
825
|
|
|
803
826
|
// Copyright (c) Microsoft Corporation.
|
|
804
827
|
class SpecFilter {
|
|
805
|
-
static specFilter(filter, unResolveSpec, resolvedSpec,
|
|
828
|
+
static specFilter(filter, unResolveSpec, resolvedSpec, options) {
|
|
806
829
|
try {
|
|
807
830
|
const newSpec = Object.assign({}, unResolveSpec);
|
|
808
831
|
const newPaths = {};
|
|
809
832
|
for (const filterItem of filter) {
|
|
810
833
|
const [method, path] = filterItem.split(" ");
|
|
811
834
|
const methodName = method.toLowerCase();
|
|
812
|
-
if (!Utils.isSupportedApi(methodName, path, resolvedSpec,
|
|
835
|
+
if (!Utils.isSupportedApi(methodName, path, resolvedSpec, options)) {
|
|
813
836
|
continue;
|
|
814
837
|
}
|
|
815
838
|
if (!newPaths[path]) {
|
|
@@ -835,7 +858,7 @@ class SpecFilter {
|
|
|
835
858
|
|
|
836
859
|
// Copyright (c) Microsoft Corporation.
|
|
837
860
|
class ManifestUpdater {
|
|
838
|
-
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec) {
|
|
861
|
+
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options) {
|
|
839
862
|
return __awaiter(this, void 0, void 0, function* () {
|
|
840
863
|
const manifest = yield fs__default['default'].readJSON(manifestPath);
|
|
841
864
|
const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
|
|
@@ -846,7 +869,7 @@ class ManifestUpdater {
|
|
|
846
869
|
];
|
|
847
870
|
ManifestUpdater.updateManifestDescription(manifest, spec);
|
|
848
871
|
const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
|
|
849
|
-
const apiPlugin = ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath);
|
|
872
|
+
const apiPlugin = ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, options);
|
|
850
873
|
return [manifest, apiPlugin];
|
|
851
874
|
});
|
|
852
875
|
}
|
|
@@ -871,7 +894,7 @@ class ManifestUpdater {
|
|
|
871
894
|
}
|
|
872
895
|
return parameter;
|
|
873
896
|
}
|
|
874
|
-
static generatePluginManifestSchema(spec, specRelativePath) {
|
|
897
|
+
static generatePluginManifestSchema(spec, specRelativePath, options) {
|
|
875
898
|
var _a, _b, _c;
|
|
876
899
|
const functions = [];
|
|
877
900
|
const functionNames = [];
|
|
@@ -881,7 +904,7 @@ class ManifestUpdater {
|
|
|
881
904
|
if (pathItem) {
|
|
882
905
|
const operations = pathItem;
|
|
883
906
|
for (const method in operations) {
|
|
884
|
-
if (
|
|
907
|
+
if (options.allowMethods.includes(method)) {
|
|
885
908
|
const operationItem = operations[method];
|
|
886
909
|
if (operationItem) {
|
|
887
910
|
const operationId = operationItem.operationId;
|
|
@@ -954,44 +977,52 @@ class ManifestUpdater {
|
|
|
954
977
|
};
|
|
955
978
|
return apiPlugin;
|
|
956
979
|
}
|
|
957
|
-
static updateManifest(manifestPath, outputSpecPath,
|
|
980
|
+
static updateManifest(manifestPath, outputSpecPath, spec, options, adaptiveCardFolder, authInfo) {
|
|
958
981
|
return __awaiter(this, void 0, void 0, function* () {
|
|
959
982
|
try {
|
|
960
983
|
const originalManifest = yield fs__default['default'].readJSON(manifestPath);
|
|
961
984
|
const updatedPart = {};
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
commands
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
985
|
+
updatedPart.composeExtensions = [];
|
|
986
|
+
let warnings = [];
|
|
987
|
+
if (options.projectType === exports.ProjectType.SME) {
|
|
988
|
+
const updateResult = yield ManifestUpdater.generateCommands(spec, manifestPath, options, adaptiveCardFolder);
|
|
989
|
+
const commands = updateResult[0];
|
|
990
|
+
warnings = updateResult[1];
|
|
991
|
+
const composeExtension = {
|
|
992
|
+
composeExtensionType: "apiBased",
|
|
993
|
+
apiSpecificationFile: ManifestUpdater.getRelativePath(manifestPath, outputSpecPath),
|
|
994
|
+
commands: commands,
|
|
995
|
+
};
|
|
996
|
+
if (authInfo) {
|
|
997
|
+
let auth = authInfo.authSchema;
|
|
998
|
+
if (Utils.isAPIKeyAuth(auth)) {
|
|
999
|
+
auth = auth;
|
|
1000
|
+
const safeApiSecretRegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
|
|
1001
|
+
composeExtension.authorization = {
|
|
1002
|
+
authType: "apiSecretServiceAuth",
|
|
1003
|
+
apiSecretServiceAuthConfiguration: {
|
|
1004
|
+
apiSecretRegistrationId: `\${{${safeApiSecretRegistrationId}}}`,
|
|
1005
|
+
},
|
|
1006
|
+
};
|
|
1007
|
+
}
|
|
1008
|
+
else if (Utils.isOAuthWithAuthCodeFlow(auth)) {
|
|
1009
|
+
const safeOAuth2RegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.OAuthRegistrationIdPostFix}`);
|
|
1010
|
+
composeExtension.authorization = {
|
|
1011
|
+
authType: "oAuth2.0",
|
|
1012
|
+
oAuthConfiguration: {
|
|
1013
|
+
oauthConfigurationId: `\${{${safeOAuth2RegistrationId}}}`,
|
|
1014
|
+
},
|
|
1015
|
+
};
|
|
1016
|
+
updatedPart.webApplicationInfo = {
|
|
1017
|
+
id: "${{AAD_APP_CLIENT_ID}}",
|
|
1018
|
+
resource: "api://${{DOMAIN}}/${{AAD_APP_CLIENT_ID}}",
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
990
1021
|
}
|
|
1022
|
+
updatedPart.composeExtensions = [composeExtension];
|
|
991
1023
|
}
|
|
992
1024
|
updatedPart.description = originalManifest.description;
|
|
993
1025
|
ManifestUpdater.updateManifestDescription(updatedPart, spec);
|
|
994
|
-
updatedPart.composeExtensions = isMe === undefined || isMe === true ? [composeExtension] : [];
|
|
995
1026
|
const updatedManifest = Object.assign(Object.assign({}, originalManifest), updatedPart);
|
|
996
1027
|
return [updatedManifest, warnings];
|
|
997
1028
|
}
|
|
@@ -1000,7 +1031,8 @@ class ManifestUpdater {
|
|
|
1000
1031
|
}
|
|
1001
1032
|
});
|
|
1002
1033
|
}
|
|
1003
|
-
static generateCommands(spec,
|
|
1034
|
+
static generateCommands(spec, manifestPath, options, adaptiveCardFolder) {
|
|
1035
|
+
var _a;
|
|
1004
1036
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1005
1037
|
const paths = spec.paths;
|
|
1006
1038
|
const commands = [];
|
|
@@ -1012,14 +1044,16 @@ class ManifestUpdater {
|
|
|
1012
1044
|
const operations = pathItem;
|
|
1013
1045
|
// Currently only support GET and POST method
|
|
1014
1046
|
for (const method in operations) {
|
|
1015
|
-
if (
|
|
1047
|
+
if ((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) {
|
|
1016
1048
|
const operationItem = operations[method];
|
|
1017
1049
|
if (operationItem) {
|
|
1018
|
-
const [command, warning] = Utils.parseApiInfo(operationItem,
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1050
|
+
const [command, warning] = Utils.parseApiInfo(operationItem, options);
|
|
1051
|
+
if (adaptiveCardFolder) {
|
|
1052
|
+
const adaptiveCardPath = path__default['default'].join(adaptiveCardFolder, command.id + ".json");
|
|
1053
|
+
command.apiResponseRenderingTemplateFile = (yield fs__default['default'].pathExists(adaptiveCardPath))
|
|
1054
|
+
? ManifestUpdater.getRelativePath(manifestPath, adaptiveCardPath)
|
|
1055
|
+
: "";
|
|
1056
|
+
}
|
|
1023
1057
|
if (warning) {
|
|
1024
1058
|
warnings.push(warning);
|
|
1025
1059
|
}
|
|
@@ -1305,7 +1339,8 @@ class SpecParser {
|
|
|
1305
1339
|
allowAPIKeyAuth: false,
|
|
1306
1340
|
allowMultipleParameters: false,
|
|
1307
1341
|
allowOauth2: false,
|
|
1308
|
-
|
|
1342
|
+
allowMethods: ["get", "post"],
|
|
1343
|
+
projectType: exports.ProjectType.SME,
|
|
1309
1344
|
};
|
|
1310
1345
|
this.pathOrSpec = pathOrDoc;
|
|
1311
1346
|
this.parser = new SwaggerParser__default['default']();
|
|
@@ -1339,7 +1374,7 @@ class SpecParser {
|
|
|
1339
1374
|
],
|
|
1340
1375
|
};
|
|
1341
1376
|
}
|
|
1342
|
-
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options
|
|
1377
|
+
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
|
|
1343
1378
|
}
|
|
1344
1379
|
catch (err) {
|
|
1345
1380
|
throw new SpecParserError(err.toString(), exports.ErrorType.ValidateFailed);
|
|
@@ -1420,7 +1455,7 @@ class SpecParser {
|
|
|
1420
1455
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1421
1456
|
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
1422
1457
|
}
|
|
1423
|
-
const newUnResolvedSpec = SpecFilter.specFilter(filter, this.unResolveSpec, this.spec, this.options
|
|
1458
|
+
const newUnResolvedSpec = SpecFilter.specFilter(filter, this.unResolveSpec, this.spec, this.options);
|
|
1424
1459
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1425
1460
|
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
1426
1461
|
}
|
|
@@ -1463,7 +1498,7 @@ class SpecParser {
|
|
|
1463
1498
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1464
1499
|
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
1465
1500
|
}
|
|
1466
|
-
const [updatedManifest, apiPlugin] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec);
|
|
1501
|
+
const [updatedManifest, apiPlugin] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options);
|
|
1467
1502
|
yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 2 });
|
|
1468
1503
|
yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 2 });
|
|
1469
1504
|
}
|
|
@@ -1482,9 +1517,8 @@ class SpecParser {
|
|
|
1482
1517
|
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
1483
1518
|
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
1484
1519
|
* @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
|
|
1485
|
-
* @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
|
|
1486
1520
|
*/
|
|
1487
|
-
generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal
|
|
1521
|
+
generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
|
|
1488
1522
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1489
1523
|
const result = {
|
|
1490
1524
|
allSuccess: true,
|
|
@@ -1494,23 +1528,23 @@ class SpecParser {
|
|
|
1494
1528
|
const newSpecs = yield this.getFilteredSpecs(filter, signal);
|
|
1495
1529
|
const newUnResolvedSpec = newSpecs[0];
|
|
1496
1530
|
const newSpec = newSpecs[1];
|
|
1497
|
-
const
|
|
1498
|
-
let
|
|
1531
|
+
const authSet = new Set();
|
|
1532
|
+
let hasMultipleAuth = false;
|
|
1499
1533
|
for (const url in newSpec.paths) {
|
|
1500
1534
|
for (const method in newSpec.paths[url]) {
|
|
1501
1535
|
const operation = newSpec.paths[url][method];
|
|
1502
1536
|
const authArray = Utils.getAuthArray(operation.security, newSpec);
|
|
1503
1537
|
if (authArray && authArray.length > 0) {
|
|
1504
|
-
|
|
1505
|
-
if (
|
|
1506
|
-
|
|
1538
|
+
authSet.add(authArray[0][0]);
|
|
1539
|
+
if (authSet.size > 1) {
|
|
1540
|
+
hasMultipleAuth = true;
|
|
1507
1541
|
break;
|
|
1508
1542
|
}
|
|
1509
1543
|
}
|
|
1510
1544
|
}
|
|
1511
1545
|
}
|
|
1512
|
-
if (
|
|
1513
|
-
throw new SpecParserError(ConstantString.
|
|
1546
|
+
if (hasMultipleAuth && this.options.projectType !== exports.ProjectType.TeamsAi) {
|
|
1547
|
+
throw new SpecParserError(ConstantString.MultipleAuthNotSupported, exports.ErrorType.MultipleAuthNotSupported);
|
|
1514
1548
|
}
|
|
1515
1549
|
let resultStr;
|
|
1516
1550
|
if (outputSpecPath.endsWith(".yaml") || outputSpecPath.endsWith(".yml")) {
|
|
@@ -1520,12 +1554,11 @@ class SpecParser {
|
|
|
1520
1554
|
resultStr = JSON.stringify(newUnResolvedSpec, null, 2);
|
|
1521
1555
|
}
|
|
1522
1556
|
yield fs__default['default'].outputFile(outputSpecPath, resultStr);
|
|
1523
|
-
if (
|
|
1524
|
-
// Only generate adaptive card for Messaging Extension
|
|
1557
|
+
if (adaptiveCardFolder) {
|
|
1525
1558
|
for (const url in newSpec.paths) {
|
|
1526
1559
|
for (const method in newSpec.paths[url]) {
|
|
1527
|
-
// paths object may contain description/summary, so we need to check if it is a operation object
|
|
1528
|
-
if (
|
|
1560
|
+
// paths object may contain description/summary which is not a http method, so we need to check if it is a operation object
|
|
1561
|
+
if (this.options.allowMethods.includes(method)) {
|
|
1529
1562
|
const operation = newSpec.paths[url][method];
|
|
1530
1563
|
try {
|
|
1531
1564
|
const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
|
|
@@ -1550,8 +1583,8 @@ class SpecParser {
|
|
|
1550
1583
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1551
1584
|
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
1552
1585
|
}
|
|
1553
|
-
const
|
|
1554
|
-
const [updatedManifest, warnings] = yield ManifestUpdater.updateManifest(manifestPath, outputSpecPath,
|
|
1586
|
+
const authInfo = Array.from(authSet)[0];
|
|
1587
|
+
const [updatedManifest, warnings] = yield ManifestUpdater.updateManifest(manifestPath, outputSpecPath, newSpec, this.options, adaptiveCardFolder, authInfo);
|
|
1555
1588
|
yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 2 });
|
|
1556
1589
|
result.warnings.push(...warnings);
|
|
1557
1590
|
}
|
|
@@ -1583,7 +1616,7 @@ class SpecParser {
|
|
|
1583
1616
|
if (this.apiMap !== undefined) {
|
|
1584
1617
|
return this.apiMap;
|
|
1585
1618
|
}
|
|
1586
|
-
const result = Utils.listSupportedAPIs(spec, this.options
|
|
1619
|
+
const result = Utils.listSupportedAPIs(spec, this.options);
|
|
1587
1620
|
this.apiMap = result;
|
|
1588
1621
|
return result;
|
|
1589
1622
|
}
|