@microsoft/m365-spec-parser 0.1.1-alpha.cf377d39f.0 → 0.1.1-alpha.f04ac4ba4.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 +96 -36
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +314 -102
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +98 -36
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +317 -101
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/constants.d.ts +2 -0
- package/dist/src/index.browser.d.ts +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/interfaces.d.ts +29 -0
- package/dist/src/manifestUpdater.d.ts +8 -4
- package/dist/src/specFilter.d.ts +2 -1
- package/dist/src/specParser.browser.d.ts +9 -1
- package/dist/src/specParser.d.ts +9 -2
- package/dist/src/utils.d.ts +10 -9
- package/package.json +4 -4
package/dist/index.esm2017.js
CHANGED
|
@@ -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 {
|
|
@@ -74,6 +80,7 @@ ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multi
|
|
|
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
82
|
ConstantString.MultipleAPIKeyNotSupported = "Multiple API keys are not supported. Please make sure that all selected APIs use the same API key.";
|
|
83
|
+
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
77
84
|
ConstantString.WrappedCardVersion = "devPreview";
|
|
78
85
|
ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
|
|
79
86
|
ConstantString.WrappedCardResponseLayout = "list";
|
|
@@ -144,11 +151,23 @@ ConstantString.FullDescriptionMaxLens = 4000;
|
|
|
144
151
|
ConstantString.CommandDescriptionMaxLens = 128;
|
|
145
152
|
ConstantString.ParameterDescriptionMaxLens = 128;
|
|
146
153
|
ConstantString.CommandTitleMaxLens = 32;
|
|
147
|
-
ConstantString.ParameterTitleMaxLens = 32;
|
|
154
|
+
ConstantString.ParameterTitleMaxLens = 32;
|
|
155
|
+
ConstantString.SMERequiredParamsMaxNum = 5;
|
|
148
156
|
|
|
149
157
|
// Copyright (c) Microsoft Corporation.
|
|
150
158
|
class Utils {
|
|
151
|
-
static
|
|
159
|
+
static hasNestedObjectInSchema(schema) {
|
|
160
|
+
if (schema.type === "object") {
|
|
161
|
+
for (const property in schema.properties) {
|
|
162
|
+
const nestedSchema = schema.properties[property];
|
|
163
|
+
if (nestedSchema.type === "object") {
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
static checkParameters(paramObject, isCopilot) {
|
|
152
171
|
const paramResult = {
|
|
153
172
|
requiredNum: 0,
|
|
154
173
|
optionalNum: 0,
|
|
@@ -160,7 +179,20 @@ class Utils {
|
|
|
160
179
|
for (let i = 0; i < paramObject.length; i++) {
|
|
161
180
|
const param = paramObject[i];
|
|
162
181
|
const schema = param.schema;
|
|
182
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
183
|
+
paramResult.isValid = false;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
163
186
|
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
187
|
+
if (isCopilot) {
|
|
188
|
+
if (isRequiredWithoutDefault) {
|
|
189
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
193
|
+
}
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
164
196
|
if (param.in === "header" || param.in === "cookie") {
|
|
165
197
|
if (isRequiredWithoutDefault) {
|
|
166
198
|
paramResult.isValid = false;
|
|
@@ -187,7 +219,7 @@ class Utils {
|
|
|
187
219
|
}
|
|
188
220
|
return paramResult;
|
|
189
221
|
}
|
|
190
|
-
static checkPostBody(schema, isRequired = false) {
|
|
222
|
+
static checkPostBody(schema, isRequired = false, isCopilot = false) {
|
|
191
223
|
var _a;
|
|
192
224
|
const paramResult = {
|
|
193
225
|
requiredNum: 0,
|
|
@@ -198,6 +230,10 @@ class Utils {
|
|
|
198
230
|
return paramResult;
|
|
199
231
|
}
|
|
200
232
|
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
233
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
234
|
+
paramResult.isValid = false;
|
|
235
|
+
return paramResult;
|
|
236
|
+
}
|
|
201
237
|
if (schema.type === "string" ||
|
|
202
238
|
schema.type === "integer" ||
|
|
203
239
|
schema.type === "boolean" ||
|
|
@@ -216,14 +252,14 @@ class Utils {
|
|
|
216
252
|
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
217
253
|
isRequired = true;
|
|
218
254
|
}
|
|
219
|
-
const result = Utils.checkPostBody(properties[property], isRequired);
|
|
255
|
+
const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
|
|
220
256
|
paramResult.requiredNum += result.requiredNum;
|
|
221
257
|
paramResult.optionalNum += result.optionalNum;
|
|
222
258
|
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
223
259
|
}
|
|
224
260
|
}
|
|
225
261
|
else {
|
|
226
|
-
if (isRequiredWithoutDefault) {
|
|
262
|
+
if (isRequiredWithoutDefault && !isCopilot) {
|
|
227
263
|
paramResult.isValid = false;
|
|
228
264
|
}
|
|
229
265
|
}
|
|
@@ -243,19 +279,19 @@ class Utils {
|
|
|
243
279
|
* 5. response body should be “application/json” and not empty, and response code should be 20X
|
|
244
280
|
* 6. only support request body with “application/json” content type
|
|
245
281
|
*/
|
|
246
|
-
static isSupportedApi(method, path, spec,
|
|
282
|
+
static isSupportedApi(method, path, spec, options) {
|
|
283
|
+
var _a;
|
|
247
284
|
const pathObj = spec.paths[path];
|
|
248
285
|
method = method.toLocaleLowerCase();
|
|
249
286
|
if (pathObj) {
|
|
250
|
-
if ((
|
|
251
|
-
pathObj[method]) {
|
|
287
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
|
|
252
288
|
const securities = pathObj[method].security;
|
|
253
289
|
const authArray = Utils.getAuthArray(securities, spec);
|
|
254
|
-
if (!Utils.isSupportedAuth(authArray,
|
|
290
|
+
if (!Utils.isSupportedAuth(authArray, options)) {
|
|
255
291
|
return false;
|
|
256
292
|
}
|
|
257
293
|
const operationObject = pathObj[method];
|
|
258
|
-
if (!allowMissingId && !operationObject.operationId) {
|
|
294
|
+
if (!options.allowMissingId && !operationObject.operationId) {
|
|
259
295
|
return false;
|
|
260
296
|
}
|
|
261
297
|
const paramObject = operationObject.parameters;
|
|
@@ -274,20 +310,29 @@ class Utils {
|
|
|
274
310
|
optionalNum: 0,
|
|
275
311
|
isValid: true,
|
|
276
312
|
};
|
|
313
|
+
const isCopilot = options.projectType === ProjectType.Copilot;
|
|
277
314
|
if (requestJsonBody) {
|
|
278
315
|
const requestBodySchema = requestJsonBody.schema;
|
|
279
|
-
|
|
316
|
+
if (isCopilot && requestBodySchema.type !== "object") {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
|
|
280
320
|
}
|
|
281
321
|
if (!requestBodyParamResult.isValid) {
|
|
282
322
|
return false;
|
|
283
323
|
}
|
|
284
|
-
const paramResult = Utils.checkParameters(paramObject);
|
|
324
|
+
const paramResult = Utils.checkParameters(paramObject, isCopilot);
|
|
285
325
|
if (!paramResult.isValid) {
|
|
286
326
|
return false;
|
|
287
327
|
}
|
|
328
|
+
// Copilot support arbitrary parameters
|
|
329
|
+
if (isCopilot) {
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
288
332
|
if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
|
|
289
|
-
if (allowMultipleParameters &&
|
|
290
|
-
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
333
|
+
if (options.allowMultipleParameters &&
|
|
334
|
+
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
335
|
+
ConstantString.SMERequiredParamsMaxNum) {
|
|
291
336
|
return true;
|
|
292
337
|
}
|
|
293
338
|
return false;
|
|
@@ -306,27 +351,29 @@ class Utils {
|
|
|
306
351
|
}
|
|
307
352
|
return false;
|
|
308
353
|
}
|
|
309
|
-
static isSupportedAuth(authSchemaArray,
|
|
354
|
+
static isSupportedAuth(authSchemaArray, options) {
|
|
310
355
|
if (authSchemaArray.length === 0) {
|
|
311
356
|
return true;
|
|
312
357
|
}
|
|
313
|
-
if (allowAPIKeyAuth || allowOauth2) {
|
|
358
|
+
if (options.allowAPIKeyAuth || options.allowOauth2) {
|
|
314
359
|
// Currently we don't support multiple auth in one operation
|
|
315
360
|
if (authSchemaArray.length > 0 && authSchemaArray.every((auths) => auths.length > 1)) {
|
|
316
361
|
return false;
|
|
317
362
|
}
|
|
318
363
|
for (const auths of authSchemaArray) {
|
|
319
364
|
if (auths.length === 1) {
|
|
320
|
-
if (!allowOauth2 &&
|
|
365
|
+
if (!options.allowOauth2 &&
|
|
366
|
+
options.allowAPIKeyAuth &&
|
|
367
|
+
Utils.isAPIKeyAuth(auths[0].authSchema)) {
|
|
321
368
|
return true;
|
|
322
369
|
}
|
|
323
|
-
else if (!allowAPIKeyAuth &&
|
|
324
|
-
allowOauth2 &&
|
|
370
|
+
else if (!options.allowAPIKeyAuth &&
|
|
371
|
+
options.allowOauth2 &&
|
|
325
372
|
Utils.isBearerTokenAuth(auths[0].authSchema)) {
|
|
326
373
|
return true;
|
|
327
374
|
}
|
|
328
|
-
else if (allowAPIKeyAuth &&
|
|
329
|
-
allowOauth2 &&
|
|
375
|
+
else if (options.allowAPIKeyAuth &&
|
|
376
|
+
options.allowOauth2 &&
|
|
330
377
|
(Utils.isAPIKeyAuth(auths[0].authSchema) ||
|
|
331
378
|
Utils.isBearerTokenAuth(auths[0].authSchema))) {
|
|
332
379
|
return true;
|
|
@@ -455,7 +502,7 @@ class Utils {
|
|
|
455
502
|
}
|
|
456
503
|
return errors;
|
|
457
504
|
}
|
|
458
|
-
static validateServer(spec,
|
|
505
|
+
static validateServer(spec, options) {
|
|
459
506
|
const errors = [];
|
|
460
507
|
let hasTopLevelServers = false;
|
|
461
508
|
let hasPathLevelServers = false;
|
|
@@ -476,7 +523,7 @@ class Utils {
|
|
|
476
523
|
}
|
|
477
524
|
for (const method in methods) {
|
|
478
525
|
const operationObject = methods[method];
|
|
479
|
-
if (Utils.isSupportedApi(method, path, spec,
|
|
526
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
480
527
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
481
528
|
hasOperationLevelServers = true;
|
|
482
529
|
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
@@ -563,7 +610,7 @@ class Utils {
|
|
|
563
610
|
param.value = schema.default;
|
|
564
611
|
}
|
|
565
612
|
}
|
|
566
|
-
static parseApiInfo(operationItem,
|
|
613
|
+
static parseApiInfo(operationItem, options) {
|
|
567
614
|
var _a, _b;
|
|
568
615
|
const requiredParams = [];
|
|
569
616
|
const optionalParams = [];
|
|
@@ -577,7 +624,7 @@ class Utils {
|
|
|
577
624
|
description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
|
|
578
625
|
};
|
|
579
626
|
const schema = param.schema;
|
|
580
|
-
if (allowMultipleParameters && schema) {
|
|
627
|
+
if (options.allowMultipleParameters && schema) {
|
|
581
628
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
582
629
|
}
|
|
583
630
|
if (param.in !== "header" && param.in !== "cookie") {
|
|
@@ -595,7 +642,7 @@ class Utils {
|
|
|
595
642
|
const requestJson = requestBody.content["application/json"];
|
|
596
643
|
if (Object.keys(requestJson).length !== 0) {
|
|
597
644
|
const schema = requestJson.schema;
|
|
598
|
-
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
|
|
645
|
+
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
|
|
599
646
|
requiredParams.push(...requiredP);
|
|
600
647
|
optionalParams.push(...optionalP);
|
|
601
648
|
}
|
|
@@ -626,14 +673,14 @@ class Utils {
|
|
|
626
673
|
}
|
|
627
674
|
return [command, warning];
|
|
628
675
|
}
|
|
629
|
-
static listSupportedAPIs(spec,
|
|
676
|
+
static listSupportedAPIs(spec, options) {
|
|
630
677
|
const paths = spec.paths;
|
|
631
678
|
const result = {};
|
|
632
679
|
for (const path in paths) {
|
|
633
680
|
const methods = paths[path];
|
|
634
681
|
for (const method in methods) {
|
|
635
682
|
// For developer preview, only support GET operation with only 1 parameter without auth
|
|
636
|
-
if (Utils.isSupportedApi(method, path, spec,
|
|
683
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
637
684
|
const operationObject = methods[method];
|
|
638
685
|
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
639
686
|
}
|
|
@@ -641,7 +688,7 @@ class Utils {
|
|
|
641
688
|
}
|
|
642
689
|
return result;
|
|
643
690
|
}
|
|
644
|
-
static validateSpec(spec, parser, isSwaggerFile,
|
|
691
|
+
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
645
692
|
const errors = [];
|
|
646
693
|
const warnings = [];
|
|
647
694
|
if (isSwaggerFile) {
|
|
@@ -651,7 +698,7 @@ class Utils {
|
|
|
651
698
|
});
|
|
652
699
|
}
|
|
653
700
|
// Server validation
|
|
654
|
-
const serverErrors = Utils.validateServer(spec,
|
|
701
|
+
const serverErrors = Utils.validateServer(spec, options);
|
|
655
702
|
errors.push(...serverErrors);
|
|
656
703
|
// Remote reference not supported
|
|
657
704
|
const refPaths = parser.$refs.paths();
|
|
@@ -664,7 +711,7 @@ class Utils {
|
|
|
664
711
|
});
|
|
665
712
|
}
|
|
666
713
|
// No supported API
|
|
667
|
-
const apiMap = Utils.listSupportedAPIs(spec,
|
|
714
|
+
const apiMap = Utils.listSupportedAPIs(spec, options);
|
|
668
715
|
if (Object.keys(apiMap).length === 0) {
|
|
669
716
|
errors.push({
|
|
670
717
|
type: ErrorType.NoSupportedApi,
|
|
@@ -735,6 +782,8 @@ class SpecParser {
|
|
|
735
782
|
allowAPIKeyAuth: false,
|
|
736
783
|
allowMultipleParameters: false,
|
|
737
784
|
allowOauth2: false,
|
|
785
|
+
allowMethods: ["get", "post"],
|
|
786
|
+
projectType: ProjectType.SME,
|
|
738
787
|
};
|
|
739
788
|
this.pathOrSpec = pathOrDoc;
|
|
740
789
|
this.parser = new SwaggerParser();
|
|
@@ -771,7 +820,7 @@ class SpecParser {
|
|
|
771
820
|
],
|
|
772
821
|
};
|
|
773
822
|
}
|
|
774
|
-
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options
|
|
823
|
+
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
|
|
775
824
|
}
|
|
776
825
|
catch (err) {
|
|
777
826
|
throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
|
|
@@ -790,7 +839,7 @@ class SpecParser {
|
|
|
790
839
|
if (!operationId) {
|
|
791
840
|
continue;
|
|
792
841
|
}
|
|
793
|
-
const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options
|
|
842
|
+
const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
|
|
794
843
|
const apiInfo = {
|
|
795
844
|
method: method,
|
|
796
845
|
path: path,
|
|
@@ -827,6 +876,17 @@ class SpecParser {
|
|
|
827
876
|
async getFilteredSpecs(filter, signal) {
|
|
828
877
|
throw new Error("Method not implemented.");
|
|
829
878
|
}
|
|
879
|
+
/**
|
|
880
|
+
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
881
|
+
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
882
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
883
|
+
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
884
|
+
* @param pluginFilePath File path of the api plugin file to generate.
|
|
885
|
+
*/
|
|
886
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
887
|
+
async generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
|
|
888
|
+
throw new Error("Method not implemented.");
|
|
889
|
+
}
|
|
830
890
|
/**
|
|
831
891
|
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
832
892
|
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
@@ -836,7 +896,7 @@ class SpecParser {
|
|
|
836
896
|
* @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
|
|
837
897
|
*/
|
|
838
898
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
839
|
-
async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal
|
|
899
|
+
async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
|
|
840
900
|
throw new Error("Method not implemented.");
|
|
841
901
|
}
|
|
842
902
|
async loadSpec() {
|
|
@@ -853,7 +913,7 @@ class SpecParser {
|
|
|
853
913
|
if (this.apiMap !== undefined) {
|
|
854
914
|
return this.apiMap;
|
|
855
915
|
}
|
|
856
|
-
const result = Utils.listSupportedAPIs(spec, this.options
|
|
916
|
+
const result = Utils.listSupportedAPIs(spec, this.options);
|
|
857
917
|
this.apiMap = result;
|
|
858
918
|
return result;
|
|
859
919
|
}
|