@microsoft/m365-spec-parser 0.1.1-alpha.cd2ba87f2.0 → 0.1.1-alpha.d1a09e202.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 +300 -67
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +386 -148
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +304 -67
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +392 -147
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/constants.d.ts +4 -1
- package/dist/src/index.browser.d.ts +2 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/interfaces.d.ts +37 -3
- package/dist/src/manifestUpdater.d.ts +8 -4
- package/dist/src/specFilter.d.ts +2 -1
- package/dist/src/specParser.browser.d.ts +15 -1
- package/dist/src/specParser.d.ts +14 -1
- package/dist/src/utils.d.ts +16 -13
- package/package.json +4 -4
package/dist/index.esm5.js
CHANGED
|
@@ -45,7 +45,7 @@ var ErrorType;
|
|
|
45
45
|
ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
|
|
46
46
|
ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
|
|
47
47
|
ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
|
|
48
|
-
ErrorType["
|
|
48
|
+
ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
|
|
49
49
|
ErrorType["ListFailed"] = "list-failed";
|
|
50
50
|
ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
|
|
51
51
|
ErrorType["FilterSpecFailed"] = "filter-spec-failed";
|
|
@@ -53,6 +53,7 @@ var ErrorType;
|
|
|
53
53
|
ErrorType["GenerateAdaptiveCardFailed"] = "generate-adaptive-card-failed";
|
|
54
54
|
ErrorType["GenerateFailed"] = "generate-failed";
|
|
55
55
|
ErrorType["ValidateFailed"] = "validate-failed";
|
|
56
|
+
ErrorType["GetSpecFailed"] = "get-spec-failed";
|
|
56
57
|
ErrorType["Cancelled"] = "cancelled";
|
|
57
58
|
ErrorType["Unknown"] = "unknown";
|
|
58
59
|
})(ErrorType || (ErrorType = {}));
|
|
@@ -75,7 +76,13 @@ var ValidationStatus;
|
|
|
75
76
|
ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
|
|
76
77
|
ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
|
|
77
78
|
ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
|
|
78
|
-
})(ValidationStatus || (ValidationStatus = {}));
|
|
79
|
+
})(ValidationStatus || (ValidationStatus = {}));
|
|
80
|
+
var ProjectType;
|
|
81
|
+
(function (ProjectType) {
|
|
82
|
+
ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
|
|
83
|
+
ProjectType[ProjectType["SME"] = 1] = "SME";
|
|
84
|
+
ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
|
|
85
|
+
})(ProjectType || (ProjectType = {}));
|
|
79
86
|
|
|
80
87
|
// Copyright (c) Microsoft Corporation.
|
|
81
88
|
class SpecParserError extends Error {
|
|
@@ -102,7 +109,8 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
|
|
|
102
109
|
ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
|
|
103
110
|
ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
|
|
104
111
|
ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
|
|
105
|
-
ConstantString.
|
|
112
|
+
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
113
|
+
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
106
114
|
ConstantString.WrappedCardVersion = "devPreview";
|
|
107
115
|
ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
|
|
108
116
|
ConstantString.WrappedCardResponseLayout = "list";
|
|
@@ -114,6 +122,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
|
114
122
|
ConstantString.TextBlockType = "TextBlock";
|
|
115
123
|
ConstantString.ContainerType = "Container";
|
|
116
124
|
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
125
|
+
ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
|
|
117
126
|
ConstantString.ResponseCodeFor20X = [
|
|
118
127
|
"200",
|
|
119
128
|
"201",
|
|
@@ -173,11 +182,23 @@ ConstantString.FullDescriptionMaxLens = 4000;
|
|
|
173
182
|
ConstantString.CommandDescriptionMaxLens = 128;
|
|
174
183
|
ConstantString.ParameterDescriptionMaxLens = 128;
|
|
175
184
|
ConstantString.CommandTitleMaxLens = 32;
|
|
176
|
-
ConstantString.ParameterTitleMaxLens = 32;
|
|
185
|
+
ConstantString.ParameterTitleMaxLens = 32;
|
|
186
|
+
ConstantString.SMERequiredParamsMaxNum = 5;
|
|
177
187
|
|
|
178
188
|
// Copyright (c) Microsoft Corporation.
|
|
179
189
|
class Utils {
|
|
180
|
-
static
|
|
190
|
+
static hasNestedObjectInSchema(schema) {
|
|
191
|
+
if (schema.type === "object") {
|
|
192
|
+
for (const property in schema.properties) {
|
|
193
|
+
const nestedSchema = schema.properties[property];
|
|
194
|
+
if (nestedSchema.type === "object") {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
static checkParameters(paramObject, isCopilot) {
|
|
181
202
|
const paramResult = {
|
|
182
203
|
requiredNum: 0,
|
|
183
204
|
optionalNum: 0,
|
|
@@ -189,7 +210,20 @@ class Utils {
|
|
|
189
210
|
for (let i = 0; i < paramObject.length; i++) {
|
|
190
211
|
const param = paramObject[i];
|
|
191
212
|
const schema = param.schema;
|
|
213
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
214
|
+
paramResult.isValid = false;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
192
217
|
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
218
|
+
if (isCopilot) {
|
|
219
|
+
if (isRequiredWithoutDefault) {
|
|
220
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
224
|
+
}
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
193
227
|
if (param.in === "header" || param.in === "cookie") {
|
|
194
228
|
if (isRequiredWithoutDefault) {
|
|
195
229
|
paramResult.isValid = false;
|
|
@@ -216,7 +250,7 @@ class Utils {
|
|
|
216
250
|
}
|
|
217
251
|
return paramResult;
|
|
218
252
|
}
|
|
219
|
-
static checkPostBody(schema, isRequired = false) {
|
|
253
|
+
static checkPostBody(schema, isRequired = false, isCopilot = false) {
|
|
220
254
|
var _a;
|
|
221
255
|
const paramResult = {
|
|
222
256
|
requiredNum: 0,
|
|
@@ -227,6 +261,10 @@ class Utils {
|
|
|
227
261
|
return paramResult;
|
|
228
262
|
}
|
|
229
263
|
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
264
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
265
|
+
paramResult.isValid = false;
|
|
266
|
+
return paramResult;
|
|
267
|
+
}
|
|
230
268
|
if (schema.type === "string" ||
|
|
231
269
|
schema.type === "integer" ||
|
|
232
270
|
schema.type === "boolean" ||
|
|
@@ -245,19 +283,22 @@ class Utils {
|
|
|
245
283
|
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
246
284
|
isRequired = true;
|
|
247
285
|
}
|
|
248
|
-
const result = Utils.checkPostBody(properties[property], isRequired);
|
|
286
|
+
const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
|
|
249
287
|
paramResult.requiredNum += result.requiredNum;
|
|
250
288
|
paramResult.optionalNum += result.optionalNum;
|
|
251
289
|
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
252
290
|
}
|
|
253
291
|
}
|
|
254
292
|
else {
|
|
255
|
-
if (isRequiredWithoutDefault) {
|
|
293
|
+
if (isRequiredWithoutDefault && !isCopilot) {
|
|
256
294
|
paramResult.isValid = false;
|
|
257
295
|
}
|
|
258
296
|
}
|
|
259
297
|
return paramResult;
|
|
260
298
|
}
|
|
299
|
+
static containMultipleMediaTypes(bodyObject) {
|
|
300
|
+
return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
|
|
301
|
+
}
|
|
261
302
|
/**
|
|
262
303
|
* Checks if the given API is supported.
|
|
263
304
|
* @param {string} method - The HTTP method of the API.
|
|
@@ -272,32 +313,40 @@ class Utils {
|
|
|
272
313
|
* 5. response body should be “application/json” and not empty, and response code should be 20X
|
|
273
314
|
* 6. only support request body with “application/json” content type
|
|
274
315
|
*/
|
|
275
|
-
static isSupportedApi(method, path, spec,
|
|
316
|
+
static isSupportedApi(method, path, spec, options) {
|
|
317
|
+
var _a;
|
|
276
318
|
const pathObj = spec.paths[path];
|
|
277
319
|
method = method.toLocaleLowerCase();
|
|
278
320
|
if (pathObj) {
|
|
279
|
-
if ((
|
|
280
|
-
pathObj[method]) {
|
|
321
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
|
|
281
322
|
const securities = pathObj[method].security;
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
323
|
+
const isTeamsAi = options.projectType === ProjectType.TeamsAi;
|
|
324
|
+
const isCopilot = options.projectType === ProjectType.Copilot;
|
|
325
|
+
// Teams AI project doesn't care about auth, it will use authProvider for user to implement
|
|
326
|
+
if (!isTeamsAi) {
|
|
327
|
+
const authArray = Utils.getAuthArray(securities, spec);
|
|
328
|
+
if (!Utils.isSupportedAuth(authArray, options)) {
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
285
331
|
}
|
|
286
332
|
const operationObject = pathObj[method];
|
|
287
|
-
if (!allowMissingId && !operationObject.operationId) {
|
|
333
|
+
if (!options.allowMissingId && !operationObject.operationId) {
|
|
288
334
|
return false;
|
|
289
335
|
}
|
|
290
336
|
const paramObject = operationObject.parameters;
|
|
291
337
|
const requestBody = operationObject.requestBody;
|
|
292
338
|
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
293
|
-
|
|
294
|
-
if (mediaTypesCount > 1) {
|
|
339
|
+
if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
|
|
295
340
|
return false;
|
|
296
341
|
}
|
|
297
|
-
const responseJson = Utils.getResponseJson(operationObject);
|
|
342
|
+
const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
|
|
298
343
|
if (Object.keys(responseJson).length === 0) {
|
|
299
344
|
return false;
|
|
300
345
|
}
|
|
346
|
+
// Teams AI project doesn't care about request parameters/body
|
|
347
|
+
if (isTeamsAi) {
|
|
348
|
+
return true;
|
|
349
|
+
}
|
|
301
350
|
let requestBodyParamResult = {
|
|
302
351
|
requiredNum: 0,
|
|
303
352
|
optionalNum: 0,
|
|
@@ -305,18 +354,26 @@ class Utils {
|
|
|
305
354
|
};
|
|
306
355
|
if (requestJsonBody) {
|
|
307
356
|
const requestBodySchema = requestJsonBody.schema;
|
|
308
|
-
|
|
357
|
+
if (isCopilot && requestBodySchema.type !== "object") {
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
|
|
309
361
|
}
|
|
310
362
|
if (!requestBodyParamResult.isValid) {
|
|
311
363
|
return false;
|
|
312
364
|
}
|
|
313
|
-
const paramResult = Utils.checkParameters(paramObject);
|
|
365
|
+
const paramResult = Utils.checkParameters(paramObject, isCopilot);
|
|
314
366
|
if (!paramResult.isValid) {
|
|
315
367
|
return false;
|
|
316
368
|
}
|
|
369
|
+
// Copilot support arbitrary parameters
|
|
370
|
+
if (isCopilot) {
|
|
371
|
+
return true;
|
|
372
|
+
}
|
|
317
373
|
if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
|
|
318
|
-
if (allowMultipleParameters &&
|
|
319
|
-
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
374
|
+
if (options.allowMultipleParameters &&
|
|
375
|
+
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
376
|
+
ConstantString.SMERequiredParamsMaxNum) {
|
|
320
377
|
return true;
|
|
321
378
|
}
|
|
322
379
|
return false;
|
|
@@ -335,29 +392,20 @@ class Utils {
|
|
|
335
392
|
}
|
|
336
393
|
return false;
|
|
337
394
|
}
|
|
338
|
-
static isSupportedAuth(
|
|
339
|
-
if (
|
|
395
|
+
static isSupportedAuth(authSchemeArray, options) {
|
|
396
|
+
if (authSchemeArray.length === 0) {
|
|
340
397
|
return true;
|
|
341
398
|
}
|
|
342
|
-
if (allowAPIKeyAuth || allowOauth2) {
|
|
399
|
+
if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
|
|
343
400
|
// Currently we don't support multiple auth in one operation
|
|
344
|
-
if (
|
|
401
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
345
402
|
return false;
|
|
346
403
|
}
|
|
347
|
-
for (const auths of
|
|
404
|
+
for (const auths of authSchemeArray) {
|
|
348
405
|
if (auths.length === 1) {
|
|
349
|
-
if (
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
else if (!allowAPIKeyAuth &&
|
|
353
|
-
allowOauth2 &&
|
|
354
|
-
Utils.isBearerTokenAuth(auths[0].authSchema)) {
|
|
355
|
-
return true;
|
|
356
|
-
}
|
|
357
|
-
else if (allowAPIKeyAuth &&
|
|
358
|
-
allowOauth2 &&
|
|
359
|
-
(Utils.isAPIKeyAuth(auths[0].authSchema) ||
|
|
360
|
-
Utils.isBearerTokenAuth(auths[0].authSchema))) {
|
|
406
|
+
if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
407
|
+
(options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
|
|
408
|
+
(options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
|
|
361
409
|
return true;
|
|
362
410
|
}
|
|
363
411
|
}
|
|
@@ -365,13 +413,17 @@ class Utils {
|
|
|
365
413
|
}
|
|
366
414
|
return false;
|
|
367
415
|
}
|
|
368
|
-
static
|
|
369
|
-
return
|
|
416
|
+
static isBearerTokenAuth(authScheme) {
|
|
417
|
+
return authScheme.type === "http" && authScheme.scheme === "bearer";
|
|
370
418
|
}
|
|
371
|
-
static
|
|
372
|
-
return
|
|
373
|
-
|
|
374
|
-
|
|
419
|
+
static isAPIKeyAuth(authScheme) {
|
|
420
|
+
return authScheme.type === "apiKey";
|
|
421
|
+
}
|
|
422
|
+
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
423
|
+
if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
|
|
424
|
+
return true;
|
|
425
|
+
}
|
|
426
|
+
return false;
|
|
375
427
|
}
|
|
376
428
|
static getAuthArray(securities, spec) {
|
|
377
429
|
var _a;
|
|
@@ -384,7 +436,7 @@ class Utils {
|
|
|
384
436
|
for (const name in security) {
|
|
385
437
|
const auth = securitySchemas[name];
|
|
386
438
|
authArray.push({
|
|
387
|
-
|
|
439
|
+
authScheme: auth,
|
|
388
440
|
name: name,
|
|
389
441
|
});
|
|
390
442
|
}
|
|
@@ -399,18 +451,19 @@ class Utils {
|
|
|
399
451
|
static updateFirstLetter(str) {
|
|
400
452
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
401
453
|
}
|
|
402
|
-
static getResponseJson(operationObject) {
|
|
454
|
+
static getResponseJson(operationObject, isTeamsAiProject = false) {
|
|
403
455
|
var _a, _b;
|
|
404
456
|
let json = {};
|
|
405
457
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
406
458
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
407
|
-
const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
|
|
408
|
-
if (mediaTypesCount > 1) {
|
|
409
|
-
return {};
|
|
410
|
-
}
|
|
411
459
|
if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
|
|
412
460
|
json = responseObject.content["application/json"];
|
|
413
|
-
|
|
461
|
+
if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
|
|
462
|
+
json = {};
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
414
467
|
}
|
|
415
468
|
}
|
|
416
469
|
return json;
|
|
@@ -484,7 +537,7 @@ class Utils {
|
|
|
484
537
|
}
|
|
485
538
|
return errors;
|
|
486
539
|
}
|
|
487
|
-
static validateServer(spec,
|
|
540
|
+
static validateServer(spec, options) {
|
|
488
541
|
const errors = [];
|
|
489
542
|
let hasTopLevelServers = false;
|
|
490
543
|
let hasPathLevelServers = false;
|
|
@@ -505,7 +558,7 @@ class Utils {
|
|
|
505
558
|
}
|
|
506
559
|
for (const method in methods) {
|
|
507
560
|
const operationObject = methods[method];
|
|
508
|
-
if (Utils.isSupportedApi(method, path, spec,
|
|
561
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
509
562
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
510
563
|
hasOperationLevelServers = true;
|
|
511
564
|
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
@@ -592,7 +645,7 @@ class Utils {
|
|
|
592
645
|
param.value = schema.default;
|
|
593
646
|
}
|
|
594
647
|
}
|
|
595
|
-
static parseApiInfo(operationItem,
|
|
648
|
+
static parseApiInfo(operationItem, options) {
|
|
596
649
|
var _a, _b;
|
|
597
650
|
const requiredParams = [];
|
|
598
651
|
const optionalParams = [];
|
|
@@ -606,7 +659,7 @@ class Utils {
|
|
|
606
659
|
description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
|
|
607
660
|
};
|
|
608
661
|
const schema = param.schema;
|
|
609
|
-
if (allowMultipleParameters && schema) {
|
|
662
|
+
if (options.allowMultipleParameters && schema) {
|
|
610
663
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
611
664
|
}
|
|
612
665
|
if (param.in !== "header" && param.in !== "cookie") {
|
|
@@ -624,7 +677,7 @@ class Utils {
|
|
|
624
677
|
const requestJson = requestBody.content["application/json"];
|
|
625
678
|
if (Object.keys(requestJson).length !== 0) {
|
|
626
679
|
const schema = requestJson.schema;
|
|
627
|
-
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
|
|
680
|
+
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
|
|
628
681
|
requiredParams.push(...requiredP);
|
|
629
682
|
optionalParams.push(...optionalP);
|
|
630
683
|
}
|
|
@@ -655,14 +708,13 @@ class Utils {
|
|
|
655
708
|
}
|
|
656
709
|
return [command, warning];
|
|
657
710
|
}
|
|
658
|
-
static listSupportedAPIs(spec,
|
|
711
|
+
static listSupportedAPIs(spec, options) {
|
|
659
712
|
const paths = spec.paths;
|
|
660
713
|
const result = {};
|
|
661
714
|
for (const path in paths) {
|
|
662
715
|
const methods = paths[path];
|
|
663
716
|
for (const method in methods) {
|
|
664
|
-
|
|
665
|
-
if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
|
|
717
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
666
718
|
const operationObject = methods[method];
|
|
667
719
|
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
668
720
|
}
|
|
@@ -670,7 +722,7 @@ class Utils {
|
|
|
670
722
|
}
|
|
671
723
|
return result;
|
|
672
724
|
}
|
|
673
|
-
static validateSpec(spec, parser, isSwaggerFile,
|
|
725
|
+
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
674
726
|
const errors = [];
|
|
675
727
|
const warnings = [];
|
|
676
728
|
if (isSwaggerFile) {
|
|
@@ -680,7 +732,7 @@ class Utils {
|
|
|
680
732
|
});
|
|
681
733
|
}
|
|
682
734
|
// Server validation
|
|
683
|
-
const serverErrors = Utils.validateServer(spec,
|
|
735
|
+
const serverErrors = Utils.validateServer(spec, options);
|
|
684
736
|
errors.push(...serverErrors);
|
|
685
737
|
// Remote reference not supported
|
|
686
738
|
const refPaths = parser.$refs.paths();
|
|
@@ -693,7 +745,7 @@ class Utils {
|
|
|
693
745
|
});
|
|
694
746
|
}
|
|
695
747
|
// No supported API
|
|
696
|
-
const apiMap = Utils.listSupportedAPIs(spec,
|
|
748
|
+
const apiMap = Utils.listSupportedAPIs(spec, options);
|
|
697
749
|
if (Object.keys(apiMap).length === 0) {
|
|
698
750
|
errors.push({
|
|
699
751
|
type: ErrorType.NoSupportedApi,
|
|
@@ -763,7 +815,10 @@ class SpecParser {
|
|
|
763
815
|
allowSwagger: false,
|
|
764
816
|
allowAPIKeyAuth: false,
|
|
765
817
|
allowMultipleParameters: false,
|
|
818
|
+
allowBearerTokenAuth: false,
|
|
766
819
|
allowOauth2: false,
|
|
820
|
+
allowMethods: ["get", "post"],
|
|
821
|
+
projectType: ProjectType.SME,
|
|
767
822
|
};
|
|
768
823
|
this.pathOrSpec = pathOrDoc;
|
|
769
824
|
this.parser = new SwaggerParser();
|
|
@@ -801,7 +856,7 @@ class SpecParser {
|
|
|
801
856
|
],
|
|
802
857
|
};
|
|
803
858
|
}
|
|
804
|
-
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options
|
|
859
|
+
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
|
|
805
860
|
}
|
|
806
861
|
catch (err) {
|
|
807
862
|
throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
|
|
@@ -822,7 +877,7 @@ class SpecParser {
|
|
|
822
877
|
if (!operationId) {
|
|
823
878
|
continue;
|
|
824
879
|
}
|
|
825
|
-
const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options
|
|
880
|
+
const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
|
|
826
881
|
const apiInfo = {
|
|
827
882
|
method: method,
|
|
828
883
|
path: path,
|
|
@@ -854,12 +909,36 @@ class SpecParser {
|
|
|
854
909
|
throw new Error("Method not implemented.");
|
|
855
910
|
});
|
|
856
911
|
}
|
|
912
|
+
/**
|
|
913
|
+
* Generate specs according to the filters.
|
|
914
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
915
|
+
*/
|
|
916
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
917
|
+
getFilteredSpecs(filter, signal) {
|
|
918
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
919
|
+
throw new Error("Method not implemented.");
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
924
|
+
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
925
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
926
|
+
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
927
|
+
* @param pluginFilePath File path of the api plugin file to generate.
|
|
928
|
+
*/
|
|
929
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
930
|
+
generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
|
|
931
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
932
|
+
throw new Error("Method not implemented.");
|
|
933
|
+
});
|
|
934
|
+
}
|
|
857
935
|
/**
|
|
858
936
|
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
859
937
|
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
860
938
|
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
861
939
|
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
862
940
|
* @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
|
|
941
|
+
* @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
|
|
863
942
|
*/
|
|
864
943
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
865
944
|
generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
|
|
@@ -883,11 +962,169 @@ class SpecParser {
|
|
|
883
962
|
if (this.apiMap !== undefined) {
|
|
884
963
|
return this.apiMap;
|
|
885
964
|
}
|
|
886
|
-
const result = Utils.listSupportedAPIs(spec, this.options
|
|
965
|
+
const result = Utils.listSupportedAPIs(spec, this.options);
|
|
887
966
|
this.apiMap = result;
|
|
888
967
|
return result;
|
|
889
968
|
}
|
|
890
969
|
}
|
|
891
970
|
|
|
892
|
-
|
|
971
|
+
// Copyright (c) Microsoft Corporation.
|
|
972
|
+
class AdaptiveCardGenerator {
|
|
973
|
+
static generateAdaptiveCard(operationItem) {
|
|
974
|
+
try {
|
|
975
|
+
const json = Utils.getResponseJson(operationItem);
|
|
976
|
+
let cardBody = [];
|
|
977
|
+
let schema = json.schema;
|
|
978
|
+
let jsonPath = "$";
|
|
979
|
+
if (schema && Object.keys(schema).length > 0) {
|
|
980
|
+
jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
|
|
981
|
+
if (jsonPath !== "$") {
|
|
982
|
+
schema = schema.properties[jsonPath];
|
|
983
|
+
}
|
|
984
|
+
cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
|
|
985
|
+
}
|
|
986
|
+
// if no schema, try to use example value
|
|
987
|
+
if (cardBody.length === 0 && (json.examples || json.example)) {
|
|
988
|
+
cardBody = [
|
|
989
|
+
{
|
|
990
|
+
type: ConstantString.TextBlockType,
|
|
991
|
+
text: "${jsonStringify($root)}",
|
|
992
|
+
wrap: true,
|
|
993
|
+
},
|
|
994
|
+
];
|
|
995
|
+
}
|
|
996
|
+
// if no example value, use default success response
|
|
997
|
+
if (cardBody.length === 0) {
|
|
998
|
+
cardBody = [
|
|
999
|
+
{
|
|
1000
|
+
type: ConstantString.TextBlockType,
|
|
1001
|
+
text: "success",
|
|
1002
|
+
wrap: true,
|
|
1003
|
+
},
|
|
1004
|
+
];
|
|
1005
|
+
}
|
|
1006
|
+
const fullCard = {
|
|
1007
|
+
type: ConstantString.AdaptiveCardType,
|
|
1008
|
+
$schema: ConstantString.AdaptiveCardSchema,
|
|
1009
|
+
version: ConstantString.AdaptiveCardVersion,
|
|
1010
|
+
body: cardBody,
|
|
1011
|
+
};
|
|
1012
|
+
return [fullCard, jsonPath];
|
|
1013
|
+
}
|
|
1014
|
+
catch (err) {
|
|
1015
|
+
throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
static generateCardFromResponse(schema, name, parentArrayName = "") {
|
|
1019
|
+
if (schema.type === "array") {
|
|
1020
|
+
// schema.items can be arbitrary object: schema { type: array, items: {} }
|
|
1021
|
+
if (Object.keys(schema.items).length === 0) {
|
|
1022
|
+
return [
|
|
1023
|
+
{
|
|
1024
|
+
type: ConstantString.TextBlockType,
|
|
1025
|
+
text: name ? `${name}: \${jsonStringify(${name})}` : "result: ${jsonStringify($root)}",
|
|
1026
|
+
wrap: true,
|
|
1027
|
+
},
|
|
1028
|
+
];
|
|
1029
|
+
}
|
|
1030
|
+
const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
|
|
1031
|
+
const template = {
|
|
1032
|
+
type: ConstantString.ContainerType,
|
|
1033
|
+
$data: name ? `\${${name}}` : "${$root}",
|
|
1034
|
+
items: Array(),
|
|
1035
|
+
};
|
|
1036
|
+
template.items.push(...obj);
|
|
1037
|
+
return [template];
|
|
1038
|
+
}
|
|
1039
|
+
// some schema may not contain type but contain properties
|
|
1040
|
+
if (schema.type === "object" || (!schema.type && schema.properties)) {
|
|
1041
|
+
const { properties } = schema;
|
|
1042
|
+
const result = [];
|
|
1043
|
+
for (const property in properties) {
|
|
1044
|
+
const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
|
|
1045
|
+
result.push(...obj);
|
|
1046
|
+
}
|
|
1047
|
+
if (schema.additionalProperties) {
|
|
1048
|
+
// TODO: better ways to handler warnings.
|
|
1049
|
+
console.warn(ConstantString.AdditionalPropertiesNotSupported);
|
|
1050
|
+
}
|
|
1051
|
+
return result;
|
|
1052
|
+
}
|
|
1053
|
+
if (schema.type === "string" ||
|
|
1054
|
+
schema.type === "integer" ||
|
|
1055
|
+
schema.type === "boolean" ||
|
|
1056
|
+
schema.type === "number") {
|
|
1057
|
+
if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
|
|
1058
|
+
// string in root: "ddd"
|
|
1059
|
+
let text = "result: ${$root}";
|
|
1060
|
+
if (name) {
|
|
1061
|
+
// object { id: "1" }
|
|
1062
|
+
text = `${name}: \${if(${name}, ${name}, 'N/A')}`;
|
|
1063
|
+
if (parentArrayName) {
|
|
1064
|
+
// object types inside array: { tags: ["id": 1, "name": "name"] }
|
|
1065
|
+
text = `${parentArrayName}.${text}`;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
else if (parentArrayName) {
|
|
1069
|
+
// string array: photoUrls: ["1", "2"]
|
|
1070
|
+
text = `${parentArrayName}: ` + "${$data}";
|
|
1071
|
+
}
|
|
1072
|
+
return [
|
|
1073
|
+
{
|
|
1074
|
+
type: ConstantString.TextBlockType,
|
|
1075
|
+
text,
|
|
1076
|
+
wrap: true,
|
|
1077
|
+
},
|
|
1078
|
+
];
|
|
1079
|
+
}
|
|
1080
|
+
else {
|
|
1081
|
+
if (name) {
|
|
1082
|
+
return [
|
|
1083
|
+
{
|
|
1084
|
+
type: "Image",
|
|
1085
|
+
url: `\${${name}}`,
|
|
1086
|
+
$when: `\${${name} != null}`,
|
|
1087
|
+
},
|
|
1088
|
+
];
|
|
1089
|
+
}
|
|
1090
|
+
else {
|
|
1091
|
+
return [
|
|
1092
|
+
{
|
|
1093
|
+
type: "Image",
|
|
1094
|
+
url: "${$data}",
|
|
1095
|
+
$when: "${$data != null}",
|
|
1096
|
+
},
|
|
1097
|
+
];
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
|
|
1102
|
+
throw new Error(Utils.format(ConstantString.SchemaNotSupported, JSON.stringify(schema)));
|
|
1103
|
+
}
|
|
1104
|
+
throw new Error(Utils.format(ConstantString.UnknownSchema, JSON.stringify(schema)));
|
|
1105
|
+
}
|
|
1106
|
+
// Find the first array property in the response schema object with the well-known name
|
|
1107
|
+
static getResponseJsonPathFromSchema(schema) {
|
|
1108
|
+
if (schema.type === "object" || (!schema.type && schema.properties)) {
|
|
1109
|
+
const { properties } = schema;
|
|
1110
|
+
for (const property in properties) {
|
|
1111
|
+
const schema = properties[property];
|
|
1112
|
+
if (schema.type === "array" &&
|
|
1113
|
+
Utils.isWellKnownName(property, ConstantString.WellknownResultNames)) {
|
|
1114
|
+
return property;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
return "$";
|
|
1119
|
+
}
|
|
1120
|
+
static isImageUrlProperty(schema, name, parentArrayName) {
|
|
1121
|
+
const propertyName = name ? name : parentArrayName;
|
|
1122
|
+
return (!!propertyName &&
|
|
1123
|
+
schema.type === "string" &&
|
|
1124
|
+
Utils.isWellKnownName(propertyName, ConstantString.WellknownImageName) &&
|
|
1125
|
+
(propertyName.toLocaleLowerCase().indexOf("url") >= 0 || schema.format === "uri"));
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
export { AdaptiveCardGenerator, ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
|
|
893
1130
|
//# sourceMappingURL=index.esm5.js.map
|