@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.esm2017.js
CHANGED
|
@@ -15,7 +15,7 @@ var ErrorType;
|
|
|
15
15
|
ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
|
|
16
16
|
ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
|
|
17
17
|
ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
|
|
18
|
-
ErrorType["
|
|
18
|
+
ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
|
|
19
19
|
ErrorType["ListFailed"] = "list-failed";
|
|
20
20
|
ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
|
|
21
21
|
ErrorType["FilterSpecFailed"] = "filter-spec-failed";
|
|
@@ -46,7 +46,13 @@ var ValidationStatus;
|
|
|
46
46
|
ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
|
|
47
47
|
ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
|
|
48
48
|
ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
|
|
49
|
-
})(ValidationStatus || (ValidationStatus = {}));
|
|
49
|
+
})(ValidationStatus || (ValidationStatus = {}));
|
|
50
|
+
var ProjectType;
|
|
51
|
+
(function (ProjectType) {
|
|
52
|
+
ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
|
|
53
|
+
ProjectType[ProjectType["SME"] = 1] = "SME";
|
|
54
|
+
ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
|
|
55
|
+
})(ProjectType || (ProjectType = {}));
|
|
50
56
|
|
|
51
57
|
// Copyright (c) Microsoft Corporation.
|
|
52
58
|
class SpecParserError extends Error {
|
|
@@ -73,7 +79,7 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
|
|
|
73
79
|
ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
|
|
74
80
|
ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
|
|
75
81
|
ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
|
|
76
|
-
ConstantString.
|
|
82
|
+
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
77
83
|
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
78
84
|
ConstantString.WrappedCardVersion = "devPreview";
|
|
79
85
|
ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
|
|
@@ -86,6 +92,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
|
86
92
|
ConstantString.TextBlockType = "TextBlock";
|
|
87
93
|
ConstantString.ContainerType = "Container";
|
|
88
94
|
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
95
|
+
ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
|
|
89
96
|
ConstantString.ResponseCodeFor20X = [
|
|
90
97
|
"200",
|
|
91
98
|
"201",
|
|
@@ -145,7 +152,8 @@ ConstantString.FullDescriptionMaxLens = 4000;
|
|
|
145
152
|
ConstantString.CommandDescriptionMaxLens = 128;
|
|
146
153
|
ConstantString.ParameterDescriptionMaxLens = 128;
|
|
147
154
|
ConstantString.CommandTitleMaxLens = 32;
|
|
148
|
-
ConstantString.ParameterTitleMaxLens = 32;
|
|
155
|
+
ConstantString.ParameterTitleMaxLens = 32;
|
|
156
|
+
ConstantString.SMERequiredParamsMaxNum = 5;
|
|
149
157
|
|
|
150
158
|
// Copyright (c) Microsoft Corporation.
|
|
151
159
|
class Utils {
|
|
@@ -258,6 +266,9 @@ class Utils {
|
|
|
258
266
|
}
|
|
259
267
|
return paramResult;
|
|
260
268
|
}
|
|
269
|
+
static containMultipleMediaTypes(bodyObject) {
|
|
270
|
+
return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
|
|
271
|
+
}
|
|
261
272
|
/**
|
|
262
273
|
* Checks if the given API is supported.
|
|
263
274
|
* @param {string} method - The HTTP method of the API.
|
|
@@ -272,32 +283,40 @@ class Utils {
|
|
|
272
283
|
* 5. response body should be “application/json” and not empty, and response code should be 20X
|
|
273
284
|
* 6. only support request body with “application/json” content type
|
|
274
285
|
*/
|
|
275
|
-
static isSupportedApi(method, path, spec,
|
|
286
|
+
static isSupportedApi(method, path, spec, options) {
|
|
287
|
+
var _a;
|
|
276
288
|
const pathObj = spec.paths[path];
|
|
277
289
|
method = method.toLocaleLowerCase();
|
|
278
290
|
if (pathObj) {
|
|
279
|
-
if ((
|
|
280
|
-
pathObj[method]) {
|
|
291
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
|
|
281
292
|
const securities = pathObj[method].security;
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
293
|
+
const isTeamsAi = options.projectType === ProjectType.TeamsAi;
|
|
294
|
+
const isCopilot = options.projectType === ProjectType.Copilot;
|
|
295
|
+
// Teams AI project doesn't care about auth, it will use authProvider for user to implement
|
|
296
|
+
if (!isTeamsAi) {
|
|
297
|
+
const authArray = Utils.getAuthArray(securities, spec);
|
|
298
|
+
if (!Utils.isSupportedAuth(authArray, options)) {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
285
301
|
}
|
|
286
302
|
const operationObject = pathObj[method];
|
|
287
|
-
if (!allowMissingId && !operationObject.operationId) {
|
|
303
|
+
if (!options.allowMissingId && !operationObject.operationId) {
|
|
288
304
|
return false;
|
|
289
305
|
}
|
|
290
306
|
const paramObject = operationObject.parameters;
|
|
291
307
|
const requestBody = operationObject.requestBody;
|
|
292
308
|
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
293
|
-
|
|
294
|
-
if (mediaTypesCount > 1) {
|
|
309
|
+
if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
|
|
295
310
|
return false;
|
|
296
311
|
}
|
|
297
|
-
const responseJson = Utils.getResponseJson(operationObject);
|
|
312
|
+
const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
|
|
298
313
|
if (Object.keys(responseJson).length === 0) {
|
|
299
314
|
return false;
|
|
300
315
|
}
|
|
316
|
+
// Teams AI project doesn't care about request parameters/body
|
|
317
|
+
if (isTeamsAi) {
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
301
320
|
let requestBodyParamResult = {
|
|
302
321
|
requiredNum: 0,
|
|
303
322
|
optionalNum: 0,
|
|
@@ -322,8 +341,9 @@ class Utils {
|
|
|
322
341
|
return true;
|
|
323
342
|
}
|
|
324
343
|
if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
|
|
325
|
-
if (allowMultipleParameters &&
|
|
326
|
-
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
344
|
+
if (options.allowMultipleParameters &&
|
|
345
|
+
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
346
|
+
ConstantString.SMERequiredParamsMaxNum) {
|
|
327
347
|
return true;
|
|
328
348
|
}
|
|
329
349
|
return false;
|
|
@@ -342,29 +362,31 @@ class Utils {
|
|
|
342
362
|
}
|
|
343
363
|
return false;
|
|
344
364
|
}
|
|
345
|
-
static isSupportedAuth(authSchemaArray,
|
|
365
|
+
static isSupportedAuth(authSchemaArray, options) {
|
|
346
366
|
if (authSchemaArray.length === 0) {
|
|
347
367
|
return true;
|
|
348
368
|
}
|
|
349
|
-
if (allowAPIKeyAuth || allowOauth2) {
|
|
369
|
+
if (options.allowAPIKeyAuth || options.allowOauth2) {
|
|
350
370
|
// Currently we don't support multiple auth in one operation
|
|
351
371
|
if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
|
|
352
372
|
return false;
|
|
353
373
|
}
|
|
354
374
|
for (const auths of authSchemaArray) {
|
|
355
375
|
if (auths.length === 1) {
|
|
356
|
-
if (!allowOauth2 &&
|
|
376
|
+
if (!options.allowOauth2 &&
|
|
377
|
+
options.allowAPIKeyAuth &&
|
|
378
|
+
Utils.isAPIKeyAuth(auths[0].authSchema)) {
|
|
357
379
|
return true;
|
|
358
380
|
}
|
|
359
|
-
else if (!allowAPIKeyAuth &&
|
|
360
|
-
allowOauth2 &&
|
|
361
|
-
Utils.
|
|
381
|
+
else if (!options.allowAPIKeyAuth &&
|
|
382
|
+
options.allowOauth2 &&
|
|
383
|
+
Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema)) {
|
|
362
384
|
return true;
|
|
363
385
|
}
|
|
364
|
-
else if (allowAPIKeyAuth &&
|
|
365
|
-
allowOauth2 &&
|
|
386
|
+
else if (options.allowAPIKeyAuth &&
|
|
387
|
+
options.allowOauth2 &&
|
|
366
388
|
(Utils.isAPIKeyAuth(auths[0].authSchema) ||
|
|
367
|
-
Utils.
|
|
389
|
+
Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema))) {
|
|
368
390
|
return true;
|
|
369
391
|
}
|
|
370
392
|
}
|
|
@@ -375,10 +397,11 @@ class Utils {
|
|
|
375
397
|
static isAPIKeyAuth(authSchema) {
|
|
376
398
|
return authSchema.type === "apiKey";
|
|
377
399
|
}
|
|
378
|
-
static
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
400
|
+
static isOAuthWithAuthCodeFlow(authSchema) {
|
|
401
|
+
if (authSchema.type === "oauth2" && authSchema.flows && authSchema.flows.authorizationCode) {
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
return false;
|
|
382
405
|
}
|
|
383
406
|
static getAuthArray(securities, spec) {
|
|
384
407
|
var _a;
|
|
@@ -406,18 +429,19 @@ class Utils {
|
|
|
406
429
|
static updateFirstLetter(str) {
|
|
407
430
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
408
431
|
}
|
|
409
|
-
static getResponseJson(operationObject) {
|
|
432
|
+
static getResponseJson(operationObject, isTeamsAiProject = false) {
|
|
410
433
|
var _a, _b;
|
|
411
434
|
let json = {};
|
|
412
435
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
413
436
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
414
|
-
const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
|
|
415
|
-
if (mediaTypesCount > 1) {
|
|
416
|
-
return {};
|
|
417
|
-
}
|
|
418
437
|
if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
|
|
419
438
|
json = responseObject.content["application/json"];
|
|
420
|
-
|
|
439
|
+
if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
|
|
440
|
+
json = {};
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
break;
|
|
444
|
+
}
|
|
421
445
|
}
|
|
422
446
|
}
|
|
423
447
|
return json;
|
|
@@ -491,7 +515,7 @@ class Utils {
|
|
|
491
515
|
}
|
|
492
516
|
return errors;
|
|
493
517
|
}
|
|
494
|
-
static validateServer(spec,
|
|
518
|
+
static validateServer(spec, options) {
|
|
495
519
|
const errors = [];
|
|
496
520
|
let hasTopLevelServers = false;
|
|
497
521
|
let hasPathLevelServers = false;
|
|
@@ -512,7 +536,7 @@ class Utils {
|
|
|
512
536
|
}
|
|
513
537
|
for (const method in methods) {
|
|
514
538
|
const operationObject = methods[method];
|
|
515
|
-
if (Utils.isSupportedApi(method, path, spec,
|
|
539
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
516
540
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
517
541
|
hasOperationLevelServers = true;
|
|
518
542
|
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
@@ -599,7 +623,7 @@ class Utils {
|
|
|
599
623
|
param.value = schema.default;
|
|
600
624
|
}
|
|
601
625
|
}
|
|
602
|
-
static parseApiInfo(operationItem,
|
|
626
|
+
static parseApiInfo(operationItem, options) {
|
|
603
627
|
var _a, _b;
|
|
604
628
|
const requiredParams = [];
|
|
605
629
|
const optionalParams = [];
|
|
@@ -613,7 +637,7 @@ class Utils {
|
|
|
613
637
|
description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
|
|
614
638
|
};
|
|
615
639
|
const schema = param.schema;
|
|
616
|
-
if (allowMultipleParameters && schema) {
|
|
640
|
+
if (options.allowMultipleParameters && schema) {
|
|
617
641
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
618
642
|
}
|
|
619
643
|
if (param.in !== "header" && param.in !== "cookie") {
|
|
@@ -631,7 +655,7 @@ class Utils {
|
|
|
631
655
|
const requestJson = requestBody.content["application/json"];
|
|
632
656
|
if (Object.keys(requestJson).length !== 0) {
|
|
633
657
|
const schema = requestJson.schema;
|
|
634
|
-
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
|
|
658
|
+
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
|
|
635
659
|
requiredParams.push(...requiredP);
|
|
636
660
|
optionalParams.push(...optionalP);
|
|
637
661
|
}
|
|
@@ -662,14 +686,13 @@ class Utils {
|
|
|
662
686
|
}
|
|
663
687
|
return [command, warning];
|
|
664
688
|
}
|
|
665
|
-
static listSupportedAPIs(spec,
|
|
689
|
+
static listSupportedAPIs(spec, options) {
|
|
666
690
|
const paths = spec.paths;
|
|
667
691
|
const result = {};
|
|
668
692
|
for (const path in paths) {
|
|
669
693
|
const methods = paths[path];
|
|
670
694
|
for (const method in methods) {
|
|
671
|
-
|
|
672
|
-
if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2, isCopilot)) {
|
|
695
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
673
696
|
const operationObject = methods[method];
|
|
674
697
|
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
675
698
|
}
|
|
@@ -677,7 +700,7 @@ class Utils {
|
|
|
677
700
|
}
|
|
678
701
|
return result;
|
|
679
702
|
}
|
|
680
|
-
static validateSpec(spec, parser, isSwaggerFile,
|
|
703
|
+
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
681
704
|
const errors = [];
|
|
682
705
|
const warnings = [];
|
|
683
706
|
if (isSwaggerFile) {
|
|
@@ -687,7 +710,7 @@ class Utils {
|
|
|
687
710
|
});
|
|
688
711
|
}
|
|
689
712
|
// Server validation
|
|
690
|
-
const serverErrors = Utils.validateServer(spec,
|
|
713
|
+
const serverErrors = Utils.validateServer(spec, options);
|
|
691
714
|
errors.push(...serverErrors);
|
|
692
715
|
// Remote reference not supported
|
|
693
716
|
const refPaths = parser.$refs.paths();
|
|
@@ -700,7 +723,7 @@ class Utils {
|
|
|
700
723
|
});
|
|
701
724
|
}
|
|
702
725
|
// No supported API
|
|
703
|
-
const apiMap = Utils.listSupportedAPIs(spec,
|
|
726
|
+
const apiMap = Utils.listSupportedAPIs(spec, options);
|
|
704
727
|
if (Object.keys(apiMap).length === 0) {
|
|
705
728
|
errors.push({
|
|
706
729
|
type: ErrorType.NoSupportedApi,
|
|
@@ -771,7 +794,8 @@ class SpecParser {
|
|
|
771
794
|
allowAPIKeyAuth: false,
|
|
772
795
|
allowMultipleParameters: false,
|
|
773
796
|
allowOauth2: false,
|
|
774
|
-
|
|
797
|
+
allowMethods: ["get", "post"],
|
|
798
|
+
projectType: ProjectType.SME,
|
|
775
799
|
};
|
|
776
800
|
this.pathOrSpec = pathOrDoc;
|
|
777
801
|
this.parser = new SwaggerParser();
|
|
@@ -808,7 +832,7 @@ class SpecParser {
|
|
|
808
832
|
],
|
|
809
833
|
};
|
|
810
834
|
}
|
|
811
|
-
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options
|
|
835
|
+
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
|
|
812
836
|
}
|
|
813
837
|
catch (err) {
|
|
814
838
|
throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
|
|
@@ -827,7 +851,7 @@ class SpecParser {
|
|
|
827
851
|
if (!operationId) {
|
|
828
852
|
continue;
|
|
829
853
|
}
|
|
830
|
-
const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options
|
|
854
|
+
const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
|
|
831
855
|
const apiInfo = {
|
|
832
856
|
method: method,
|
|
833
857
|
path: path,
|
|
@@ -884,7 +908,7 @@ class SpecParser {
|
|
|
884
908
|
* @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
|
|
885
909
|
*/
|
|
886
910
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
887
|
-
async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal
|
|
911
|
+
async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
|
|
888
912
|
throw new Error("Method not implemented.");
|
|
889
913
|
}
|
|
890
914
|
async loadSpec() {
|
|
@@ -901,7 +925,7 @@ class SpecParser {
|
|
|
901
925
|
if (this.apiMap !== undefined) {
|
|
902
926
|
return this.apiMap;
|
|
903
927
|
}
|
|
904
|
-
const result = Utils.listSupportedAPIs(spec, this.options
|
|
928
|
+
const result = Utils.listSupportedAPIs(spec, this.options);
|
|
905
929
|
this.apiMap = result;
|
|
906
930
|
return result;
|
|
907
931
|
}
|