@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.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";
|
|
@@ -23,6 +23,7 @@ var ErrorType;
|
|
|
23
23
|
ErrorType["GenerateAdaptiveCardFailed"] = "generate-adaptive-card-failed";
|
|
24
24
|
ErrorType["GenerateFailed"] = "generate-failed";
|
|
25
25
|
ErrorType["ValidateFailed"] = "validate-failed";
|
|
26
|
+
ErrorType["GetSpecFailed"] = "get-spec-failed";
|
|
26
27
|
ErrorType["Cancelled"] = "cancelled";
|
|
27
28
|
ErrorType["Unknown"] = "unknown";
|
|
28
29
|
})(ErrorType || (ErrorType = {}));
|
|
@@ -45,7 +46,13 @@ var ValidationStatus;
|
|
|
45
46
|
ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
|
|
46
47
|
ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
|
|
47
48
|
ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
|
|
48
|
-
})(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 = {}));
|
|
49
56
|
|
|
50
57
|
// Copyright (c) Microsoft Corporation.
|
|
51
58
|
class SpecParserError extends Error {
|
|
@@ -72,7 +79,8 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
|
|
|
72
79
|
ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
|
|
73
80
|
ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
|
|
74
81
|
ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
|
|
75
|
-
ConstantString.
|
|
82
|
+
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
83
|
+
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
76
84
|
ConstantString.WrappedCardVersion = "devPreview";
|
|
77
85
|
ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
|
|
78
86
|
ConstantString.WrappedCardResponseLayout = "list";
|
|
@@ -84,6 +92,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
|
84
92
|
ConstantString.TextBlockType = "TextBlock";
|
|
85
93
|
ConstantString.ContainerType = "Container";
|
|
86
94
|
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
95
|
+
ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
|
|
87
96
|
ConstantString.ResponseCodeFor20X = [
|
|
88
97
|
"200",
|
|
89
98
|
"201",
|
|
@@ -143,11 +152,23 @@ ConstantString.FullDescriptionMaxLens = 4000;
|
|
|
143
152
|
ConstantString.CommandDescriptionMaxLens = 128;
|
|
144
153
|
ConstantString.ParameterDescriptionMaxLens = 128;
|
|
145
154
|
ConstantString.CommandTitleMaxLens = 32;
|
|
146
|
-
ConstantString.ParameterTitleMaxLens = 32;
|
|
155
|
+
ConstantString.ParameterTitleMaxLens = 32;
|
|
156
|
+
ConstantString.SMERequiredParamsMaxNum = 5;
|
|
147
157
|
|
|
148
158
|
// Copyright (c) Microsoft Corporation.
|
|
149
159
|
class Utils {
|
|
150
|
-
static
|
|
160
|
+
static hasNestedObjectInSchema(schema) {
|
|
161
|
+
if (schema.type === "object") {
|
|
162
|
+
for (const property in schema.properties) {
|
|
163
|
+
const nestedSchema = schema.properties[property];
|
|
164
|
+
if (nestedSchema.type === "object") {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
static checkParameters(paramObject, isCopilot) {
|
|
151
172
|
const paramResult = {
|
|
152
173
|
requiredNum: 0,
|
|
153
174
|
optionalNum: 0,
|
|
@@ -159,7 +180,20 @@ class Utils {
|
|
|
159
180
|
for (let i = 0; i < paramObject.length; i++) {
|
|
160
181
|
const param = paramObject[i];
|
|
161
182
|
const schema = param.schema;
|
|
183
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
184
|
+
paramResult.isValid = false;
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
162
187
|
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
188
|
+
if (isCopilot) {
|
|
189
|
+
if (isRequiredWithoutDefault) {
|
|
190
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
194
|
+
}
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
163
197
|
if (param.in === "header" || param.in === "cookie") {
|
|
164
198
|
if (isRequiredWithoutDefault) {
|
|
165
199
|
paramResult.isValid = false;
|
|
@@ -186,7 +220,7 @@ class Utils {
|
|
|
186
220
|
}
|
|
187
221
|
return paramResult;
|
|
188
222
|
}
|
|
189
|
-
static checkPostBody(schema, isRequired = false) {
|
|
223
|
+
static checkPostBody(schema, isRequired = false, isCopilot = false) {
|
|
190
224
|
var _a;
|
|
191
225
|
const paramResult = {
|
|
192
226
|
requiredNum: 0,
|
|
@@ -197,6 +231,10 @@ class Utils {
|
|
|
197
231
|
return paramResult;
|
|
198
232
|
}
|
|
199
233
|
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
234
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
235
|
+
paramResult.isValid = false;
|
|
236
|
+
return paramResult;
|
|
237
|
+
}
|
|
200
238
|
if (schema.type === "string" ||
|
|
201
239
|
schema.type === "integer" ||
|
|
202
240
|
schema.type === "boolean" ||
|
|
@@ -215,19 +253,22 @@ class Utils {
|
|
|
215
253
|
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
216
254
|
isRequired = true;
|
|
217
255
|
}
|
|
218
|
-
const result = Utils.checkPostBody(properties[property], isRequired);
|
|
256
|
+
const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
|
|
219
257
|
paramResult.requiredNum += result.requiredNum;
|
|
220
258
|
paramResult.optionalNum += result.optionalNum;
|
|
221
259
|
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
222
260
|
}
|
|
223
261
|
}
|
|
224
262
|
else {
|
|
225
|
-
if (isRequiredWithoutDefault) {
|
|
263
|
+
if (isRequiredWithoutDefault && !isCopilot) {
|
|
226
264
|
paramResult.isValid = false;
|
|
227
265
|
}
|
|
228
266
|
}
|
|
229
267
|
return paramResult;
|
|
230
268
|
}
|
|
269
|
+
static containMultipleMediaTypes(bodyObject) {
|
|
270
|
+
return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
|
|
271
|
+
}
|
|
231
272
|
/**
|
|
232
273
|
* Checks if the given API is supported.
|
|
233
274
|
* @param {string} method - The HTTP method of the API.
|
|
@@ -242,32 +283,40 @@ class Utils {
|
|
|
242
283
|
* 5. response body should be “application/json” and not empty, and response code should be 20X
|
|
243
284
|
* 6. only support request body with “application/json” content type
|
|
244
285
|
*/
|
|
245
|
-
static isSupportedApi(method, path, spec,
|
|
286
|
+
static isSupportedApi(method, path, spec, options) {
|
|
287
|
+
var _a;
|
|
246
288
|
const pathObj = spec.paths[path];
|
|
247
289
|
method = method.toLocaleLowerCase();
|
|
248
290
|
if (pathObj) {
|
|
249
|
-
if ((
|
|
250
|
-
pathObj[method]) {
|
|
291
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
|
|
251
292
|
const securities = pathObj[method].security;
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
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
|
+
}
|
|
255
301
|
}
|
|
256
302
|
const operationObject = pathObj[method];
|
|
257
|
-
if (!allowMissingId && !operationObject.operationId) {
|
|
303
|
+
if (!options.allowMissingId && !operationObject.operationId) {
|
|
258
304
|
return false;
|
|
259
305
|
}
|
|
260
306
|
const paramObject = operationObject.parameters;
|
|
261
307
|
const requestBody = operationObject.requestBody;
|
|
262
308
|
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
263
|
-
|
|
264
|
-
if (mediaTypesCount > 1) {
|
|
309
|
+
if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
|
|
265
310
|
return false;
|
|
266
311
|
}
|
|
267
|
-
const responseJson = Utils.getResponseJson(operationObject);
|
|
312
|
+
const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
|
|
268
313
|
if (Object.keys(responseJson).length === 0) {
|
|
269
314
|
return false;
|
|
270
315
|
}
|
|
316
|
+
// Teams AI project doesn't care about request parameters/body
|
|
317
|
+
if (isTeamsAi) {
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
271
320
|
let requestBodyParamResult = {
|
|
272
321
|
requiredNum: 0,
|
|
273
322
|
optionalNum: 0,
|
|
@@ -275,18 +324,26 @@ class Utils {
|
|
|
275
324
|
};
|
|
276
325
|
if (requestJsonBody) {
|
|
277
326
|
const requestBodySchema = requestJsonBody.schema;
|
|
278
|
-
|
|
327
|
+
if (isCopilot && requestBodySchema.type !== "object") {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
|
|
279
331
|
}
|
|
280
332
|
if (!requestBodyParamResult.isValid) {
|
|
281
333
|
return false;
|
|
282
334
|
}
|
|
283
|
-
const paramResult = Utils.checkParameters(paramObject);
|
|
335
|
+
const paramResult = Utils.checkParameters(paramObject, isCopilot);
|
|
284
336
|
if (!paramResult.isValid) {
|
|
285
337
|
return false;
|
|
286
338
|
}
|
|
339
|
+
// Copilot support arbitrary parameters
|
|
340
|
+
if (isCopilot) {
|
|
341
|
+
return true;
|
|
342
|
+
}
|
|
287
343
|
if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
|
|
288
|
-
if (allowMultipleParameters &&
|
|
289
|
-
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
344
|
+
if (options.allowMultipleParameters &&
|
|
345
|
+
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
346
|
+
ConstantString.SMERequiredParamsMaxNum) {
|
|
290
347
|
return true;
|
|
291
348
|
}
|
|
292
349
|
return false;
|
|
@@ -305,29 +362,20 @@ class Utils {
|
|
|
305
362
|
}
|
|
306
363
|
return false;
|
|
307
364
|
}
|
|
308
|
-
static isSupportedAuth(
|
|
309
|
-
if (
|
|
365
|
+
static isSupportedAuth(authSchemeArray, options) {
|
|
366
|
+
if (authSchemeArray.length === 0) {
|
|
310
367
|
return true;
|
|
311
368
|
}
|
|
312
|
-
if (allowAPIKeyAuth || allowOauth2) {
|
|
369
|
+
if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
|
|
313
370
|
// Currently we don't support multiple auth in one operation
|
|
314
|
-
if (
|
|
371
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
315
372
|
return false;
|
|
316
373
|
}
|
|
317
|
-
for (const auths of
|
|
374
|
+
for (const auths of authSchemeArray) {
|
|
318
375
|
if (auths.length === 1) {
|
|
319
|
-
if (
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
else if (!allowAPIKeyAuth &&
|
|
323
|
-
allowOauth2 &&
|
|
324
|
-
Utils.isBearerTokenAuth(auths[0].authSchema)) {
|
|
325
|
-
return true;
|
|
326
|
-
}
|
|
327
|
-
else if (allowAPIKeyAuth &&
|
|
328
|
-
allowOauth2 &&
|
|
329
|
-
(Utils.isAPIKeyAuth(auths[0].authSchema) ||
|
|
330
|
-
Utils.isBearerTokenAuth(auths[0].authSchema))) {
|
|
376
|
+
if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
377
|
+
(options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
|
|
378
|
+
(options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
|
|
331
379
|
return true;
|
|
332
380
|
}
|
|
333
381
|
}
|
|
@@ -335,13 +383,17 @@ class Utils {
|
|
|
335
383
|
}
|
|
336
384
|
return false;
|
|
337
385
|
}
|
|
338
|
-
static
|
|
339
|
-
return
|
|
386
|
+
static isBearerTokenAuth(authScheme) {
|
|
387
|
+
return authScheme.type === "http" && authScheme.scheme === "bearer";
|
|
340
388
|
}
|
|
341
|
-
static
|
|
342
|
-
return
|
|
343
|
-
|
|
344
|
-
|
|
389
|
+
static isAPIKeyAuth(authScheme) {
|
|
390
|
+
return authScheme.type === "apiKey";
|
|
391
|
+
}
|
|
392
|
+
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
393
|
+
if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
return false;
|
|
345
397
|
}
|
|
346
398
|
static getAuthArray(securities, spec) {
|
|
347
399
|
var _a;
|
|
@@ -354,7 +406,7 @@ class Utils {
|
|
|
354
406
|
for (const name in security) {
|
|
355
407
|
const auth = securitySchemas[name];
|
|
356
408
|
authArray.push({
|
|
357
|
-
|
|
409
|
+
authScheme: auth,
|
|
358
410
|
name: name,
|
|
359
411
|
});
|
|
360
412
|
}
|
|
@@ -369,18 +421,19 @@ class Utils {
|
|
|
369
421
|
static updateFirstLetter(str) {
|
|
370
422
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
371
423
|
}
|
|
372
|
-
static getResponseJson(operationObject) {
|
|
424
|
+
static getResponseJson(operationObject, isTeamsAiProject = false) {
|
|
373
425
|
var _a, _b;
|
|
374
426
|
let json = {};
|
|
375
427
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
376
428
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
377
|
-
const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
|
|
378
|
-
if (mediaTypesCount > 1) {
|
|
379
|
-
return {};
|
|
380
|
-
}
|
|
381
429
|
if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
|
|
382
430
|
json = responseObject.content["application/json"];
|
|
383
|
-
|
|
431
|
+
if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
|
|
432
|
+
json = {};
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
break;
|
|
436
|
+
}
|
|
384
437
|
}
|
|
385
438
|
}
|
|
386
439
|
return json;
|
|
@@ -454,7 +507,7 @@ class Utils {
|
|
|
454
507
|
}
|
|
455
508
|
return errors;
|
|
456
509
|
}
|
|
457
|
-
static validateServer(spec,
|
|
510
|
+
static validateServer(spec, options) {
|
|
458
511
|
const errors = [];
|
|
459
512
|
let hasTopLevelServers = false;
|
|
460
513
|
let hasPathLevelServers = false;
|
|
@@ -475,7 +528,7 @@ class Utils {
|
|
|
475
528
|
}
|
|
476
529
|
for (const method in methods) {
|
|
477
530
|
const operationObject = methods[method];
|
|
478
|
-
if (Utils.isSupportedApi(method, path, spec,
|
|
531
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
479
532
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
480
533
|
hasOperationLevelServers = true;
|
|
481
534
|
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
@@ -562,7 +615,7 @@ class Utils {
|
|
|
562
615
|
param.value = schema.default;
|
|
563
616
|
}
|
|
564
617
|
}
|
|
565
|
-
static parseApiInfo(operationItem,
|
|
618
|
+
static parseApiInfo(operationItem, options) {
|
|
566
619
|
var _a, _b;
|
|
567
620
|
const requiredParams = [];
|
|
568
621
|
const optionalParams = [];
|
|
@@ -576,7 +629,7 @@ class Utils {
|
|
|
576
629
|
description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
|
|
577
630
|
};
|
|
578
631
|
const schema = param.schema;
|
|
579
|
-
if (allowMultipleParameters && schema) {
|
|
632
|
+
if (options.allowMultipleParameters && schema) {
|
|
580
633
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
581
634
|
}
|
|
582
635
|
if (param.in !== "header" && param.in !== "cookie") {
|
|
@@ -594,7 +647,7 @@ class Utils {
|
|
|
594
647
|
const requestJson = requestBody.content["application/json"];
|
|
595
648
|
if (Object.keys(requestJson).length !== 0) {
|
|
596
649
|
const schema = requestJson.schema;
|
|
597
|
-
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
|
|
650
|
+
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
|
|
598
651
|
requiredParams.push(...requiredP);
|
|
599
652
|
optionalParams.push(...optionalP);
|
|
600
653
|
}
|
|
@@ -625,14 +678,13 @@ class Utils {
|
|
|
625
678
|
}
|
|
626
679
|
return [command, warning];
|
|
627
680
|
}
|
|
628
|
-
static listSupportedAPIs(spec,
|
|
681
|
+
static listSupportedAPIs(spec, options) {
|
|
629
682
|
const paths = spec.paths;
|
|
630
683
|
const result = {};
|
|
631
684
|
for (const path in paths) {
|
|
632
685
|
const methods = paths[path];
|
|
633
686
|
for (const method in methods) {
|
|
634
|
-
|
|
635
|
-
if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
|
|
687
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
636
688
|
const operationObject = methods[method];
|
|
637
689
|
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
638
690
|
}
|
|
@@ -640,7 +692,7 @@ class Utils {
|
|
|
640
692
|
}
|
|
641
693
|
return result;
|
|
642
694
|
}
|
|
643
|
-
static validateSpec(spec, parser, isSwaggerFile,
|
|
695
|
+
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
644
696
|
const errors = [];
|
|
645
697
|
const warnings = [];
|
|
646
698
|
if (isSwaggerFile) {
|
|
@@ -650,7 +702,7 @@ class Utils {
|
|
|
650
702
|
});
|
|
651
703
|
}
|
|
652
704
|
// Server validation
|
|
653
|
-
const serverErrors = Utils.validateServer(spec,
|
|
705
|
+
const serverErrors = Utils.validateServer(spec, options);
|
|
654
706
|
errors.push(...serverErrors);
|
|
655
707
|
// Remote reference not supported
|
|
656
708
|
const refPaths = parser.$refs.paths();
|
|
@@ -663,7 +715,7 @@ class Utils {
|
|
|
663
715
|
});
|
|
664
716
|
}
|
|
665
717
|
// No supported API
|
|
666
|
-
const apiMap = Utils.listSupportedAPIs(spec,
|
|
718
|
+
const apiMap = Utils.listSupportedAPIs(spec, options);
|
|
667
719
|
if (Object.keys(apiMap).length === 0) {
|
|
668
720
|
errors.push({
|
|
669
721
|
type: ErrorType.NoSupportedApi,
|
|
@@ -733,7 +785,10 @@ class SpecParser {
|
|
|
733
785
|
allowSwagger: false,
|
|
734
786
|
allowAPIKeyAuth: false,
|
|
735
787
|
allowMultipleParameters: false,
|
|
788
|
+
allowBearerTokenAuth: false,
|
|
736
789
|
allowOauth2: false,
|
|
790
|
+
allowMethods: ["get", "post"],
|
|
791
|
+
projectType: ProjectType.SME,
|
|
737
792
|
};
|
|
738
793
|
this.pathOrSpec = pathOrDoc;
|
|
739
794
|
this.parser = new SwaggerParser();
|
|
@@ -770,7 +825,7 @@ class SpecParser {
|
|
|
770
825
|
],
|
|
771
826
|
};
|
|
772
827
|
}
|
|
773
|
-
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options
|
|
828
|
+
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
|
|
774
829
|
}
|
|
775
830
|
catch (err) {
|
|
776
831
|
throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
|
|
@@ -789,7 +844,7 @@ class SpecParser {
|
|
|
789
844
|
if (!operationId) {
|
|
790
845
|
continue;
|
|
791
846
|
}
|
|
792
|
-
const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options
|
|
847
|
+
const [command, warning] = Utils.parseApiInfo(pathObjectItem, this.options);
|
|
793
848
|
const apiInfo = {
|
|
794
849
|
method: method,
|
|
795
850
|
path: path,
|
|
@@ -818,12 +873,32 @@ class SpecParser {
|
|
|
818
873
|
async list() {
|
|
819
874
|
throw new Error("Method not implemented.");
|
|
820
875
|
}
|
|
876
|
+
/**
|
|
877
|
+
* Generate specs according to the filters.
|
|
878
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
879
|
+
*/
|
|
880
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
881
|
+
async getFilteredSpecs(filter, signal) {
|
|
882
|
+
throw new Error("Method not implemented.");
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
886
|
+
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
887
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
888
|
+
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
889
|
+
* @param pluginFilePath File path of the api plugin file to generate.
|
|
890
|
+
*/
|
|
891
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
892
|
+
async generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
|
|
893
|
+
throw new Error("Method not implemented.");
|
|
894
|
+
}
|
|
821
895
|
/**
|
|
822
896
|
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
823
897
|
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
824
898
|
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
825
899
|
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
826
900
|
* @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
|
|
901
|
+
* @param isMe Boolean that indicates whether the project is an Messaging Extension. For Messaging Extension, composeExtensions will be added in Teams app manifest.
|
|
827
902
|
*/
|
|
828
903
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
829
904
|
async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
|
|
@@ -843,11 +918,169 @@ class SpecParser {
|
|
|
843
918
|
if (this.apiMap !== undefined) {
|
|
844
919
|
return this.apiMap;
|
|
845
920
|
}
|
|
846
|
-
const result = Utils.listSupportedAPIs(spec, this.options
|
|
921
|
+
const result = Utils.listSupportedAPIs(spec, this.options);
|
|
847
922
|
this.apiMap = result;
|
|
848
923
|
return result;
|
|
849
924
|
}
|
|
850
925
|
}
|
|
851
926
|
|
|
852
|
-
|
|
927
|
+
// Copyright (c) Microsoft Corporation.
|
|
928
|
+
class AdaptiveCardGenerator {
|
|
929
|
+
static generateAdaptiveCard(operationItem) {
|
|
930
|
+
try {
|
|
931
|
+
const json = Utils.getResponseJson(operationItem);
|
|
932
|
+
let cardBody = [];
|
|
933
|
+
let schema = json.schema;
|
|
934
|
+
let jsonPath = "$";
|
|
935
|
+
if (schema && Object.keys(schema).length > 0) {
|
|
936
|
+
jsonPath = AdaptiveCardGenerator.getResponseJsonPathFromSchema(schema);
|
|
937
|
+
if (jsonPath !== "$") {
|
|
938
|
+
schema = schema.properties[jsonPath];
|
|
939
|
+
}
|
|
940
|
+
cardBody = AdaptiveCardGenerator.generateCardFromResponse(schema, "");
|
|
941
|
+
}
|
|
942
|
+
// if no schema, try to use example value
|
|
943
|
+
if (cardBody.length === 0 && (json.examples || json.example)) {
|
|
944
|
+
cardBody = [
|
|
945
|
+
{
|
|
946
|
+
type: ConstantString.TextBlockType,
|
|
947
|
+
text: "${jsonStringify($root)}",
|
|
948
|
+
wrap: true,
|
|
949
|
+
},
|
|
950
|
+
];
|
|
951
|
+
}
|
|
952
|
+
// if no example value, use default success response
|
|
953
|
+
if (cardBody.length === 0) {
|
|
954
|
+
cardBody = [
|
|
955
|
+
{
|
|
956
|
+
type: ConstantString.TextBlockType,
|
|
957
|
+
text: "success",
|
|
958
|
+
wrap: true,
|
|
959
|
+
},
|
|
960
|
+
];
|
|
961
|
+
}
|
|
962
|
+
const fullCard = {
|
|
963
|
+
type: ConstantString.AdaptiveCardType,
|
|
964
|
+
$schema: ConstantString.AdaptiveCardSchema,
|
|
965
|
+
version: ConstantString.AdaptiveCardVersion,
|
|
966
|
+
body: cardBody,
|
|
967
|
+
};
|
|
968
|
+
return [fullCard, jsonPath];
|
|
969
|
+
}
|
|
970
|
+
catch (err) {
|
|
971
|
+
throw new SpecParserError(err.toString(), ErrorType.GenerateAdaptiveCardFailed);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
static generateCardFromResponse(schema, name, parentArrayName = "") {
|
|
975
|
+
if (schema.type === "array") {
|
|
976
|
+
// schema.items can be arbitrary object: schema { type: array, items: {} }
|
|
977
|
+
if (Object.keys(schema.items).length === 0) {
|
|
978
|
+
return [
|
|
979
|
+
{
|
|
980
|
+
type: ConstantString.TextBlockType,
|
|
981
|
+
text: name ? `${name}: \${jsonStringify(${name})}` : "result: ${jsonStringify($root)}",
|
|
982
|
+
wrap: true,
|
|
983
|
+
},
|
|
984
|
+
];
|
|
985
|
+
}
|
|
986
|
+
const obj = AdaptiveCardGenerator.generateCardFromResponse(schema.items, "", name);
|
|
987
|
+
const template = {
|
|
988
|
+
type: ConstantString.ContainerType,
|
|
989
|
+
$data: name ? `\${${name}}` : "${$root}",
|
|
990
|
+
items: Array(),
|
|
991
|
+
};
|
|
992
|
+
template.items.push(...obj);
|
|
993
|
+
return [template];
|
|
994
|
+
}
|
|
995
|
+
// some schema may not contain type but contain properties
|
|
996
|
+
if (schema.type === "object" || (!schema.type && schema.properties)) {
|
|
997
|
+
const { properties } = schema;
|
|
998
|
+
const result = [];
|
|
999
|
+
for (const property in properties) {
|
|
1000
|
+
const obj = AdaptiveCardGenerator.generateCardFromResponse(properties[property], name ? `${name}.${property}` : property, parentArrayName);
|
|
1001
|
+
result.push(...obj);
|
|
1002
|
+
}
|
|
1003
|
+
if (schema.additionalProperties) {
|
|
1004
|
+
// TODO: better ways to handler warnings.
|
|
1005
|
+
console.warn(ConstantString.AdditionalPropertiesNotSupported);
|
|
1006
|
+
}
|
|
1007
|
+
return result;
|
|
1008
|
+
}
|
|
1009
|
+
if (schema.type === "string" ||
|
|
1010
|
+
schema.type === "integer" ||
|
|
1011
|
+
schema.type === "boolean" ||
|
|
1012
|
+
schema.type === "number") {
|
|
1013
|
+
if (!AdaptiveCardGenerator.isImageUrlProperty(schema, name, parentArrayName)) {
|
|
1014
|
+
// string in root: "ddd"
|
|
1015
|
+
let text = "result: ${$root}";
|
|
1016
|
+
if (name) {
|
|
1017
|
+
// object { id: "1" }
|
|
1018
|
+
text = `${name}: \${if(${name}, ${name}, 'N/A')}`;
|
|
1019
|
+
if (parentArrayName) {
|
|
1020
|
+
// object types inside array: { tags: ["id": 1, "name": "name"] }
|
|
1021
|
+
text = `${parentArrayName}.${text}`;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
else if (parentArrayName) {
|
|
1025
|
+
// string array: photoUrls: ["1", "2"]
|
|
1026
|
+
text = `${parentArrayName}: ` + "${$data}";
|
|
1027
|
+
}
|
|
1028
|
+
return [
|
|
1029
|
+
{
|
|
1030
|
+
type: ConstantString.TextBlockType,
|
|
1031
|
+
text,
|
|
1032
|
+
wrap: true,
|
|
1033
|
+
},
|
|
1034
|
+
];
|
|
1035
|
+
}
|
|
1036
|
+
else {
|
|
1037
|
+
if (name) {
|
|
1038
|
+
return [
|
|
1039
|
+
{
|
|
1040
|
+
type: "Image",
|
|
1041
|
+
url: `\${${name}}`,
|
|
1042
|
+
$when: `\${${name} != null}`,
|
|
1043
|
+
},
|
|
1044
|
+
];
|
|
1045
|
+
}
|
|
1046
|
+
else {
|
|
1047
|
+
return [
|
|
1048
|
+
{
|
|
1049
|
+
type: "Image",
|
|
1050
|
+
url: "${$data}",
|
|
1051
|
+
$when: "${$data != null}",
|
|
1052
|
+
},
|
|
1053
|
+
];
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
if (schema.oneOf || schema.anyOf || schema.not || schema.allOf) {
|
|
1058
|
+
throw new Error(Utils.format(ConstantString.SchemaNotSupported, JSON.stringify(schema)));
|
|
1059
|
+
}
|
|
1060
|
+
throw new Error(Utils.format(ConstantString.UnknownSchema, JSON.stringify(schema)));
|
|
1061
|
+
}
|
|
1062
|
+
// Find the first array property in the response schema object with the well-known name
|
|
1063
|
+
static getResponseJsonPathFromSchema(schema) {
|
|
1064
|
+
if (schema.type === "object" || (!schema.type && schema.properties)) {
|
|
1065
|
+
const { properties } = schema;
|
|
1066
|
+
for (const property in properties) {
|
|
1067
|
+
const schema = properties[property];
|
|
1068
|
+
if (schema.type === "array" &&
|
|
1069
|
+
Utils.isWellKnownName(property, ConstantString.WellknownResultNames)) {
|
|
1070
|
+
return property;
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
return "$";
|
|
1075
|
+
}
|
|
1076
|
+
static isImageUrlProperty(schema, name, parentArrayName) {
|
|
1077
|
+
const propertyName = name ? name : parentArrayName;
|
|
1078
|
+
return (!!propertyName &&
|
|
1079
|
+
schema.type === "string" &&
|
|
1080
|
+
Utils.isWellKnownName(propertyName, ConstantString.WellknownImageName) &&
|
|
1081
|
+
(propertyName.toLocaleLowerCase().indexOf("url") >= 0 || schema.format === "uri"));
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
export { AdaptiveCardGenerator, ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
|
|
853
1086
|
//# sourceMappingURL=index.esm2017.js.map
|