@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.node.cjs.js
CHANGED
|
@@ -61,7 +61,7 @@ exports.ErrorType = void 0;
|
|
|
61
61
|
ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
|
|
62
62
|
ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
|
|
63
63
|
ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
|
|
64
|
-
ErrorType["
|
|
64
|
+
ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
|
|
65
65
|
ErrorType["ListFailed"] = "list-failed";
|
|
66
66
|
ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
|
|
67
67
|
ErrorType["FilterSpecFailed"] = "filter-spec-failed";
|
|
@@ -69,6 +69,7 @@ exports.ErrorType = void 0;
|
|
|
69
69
|
ErrorType["GenerateAdaptiveCardFailed"] = "generate-adaptive-card-failed";
|
|
70
70
|
ErrorType["GenerateFailed"] = "generate-failed";
|
|
71
71
|
ErrorType["ValidateFailed"] = "validate-failed";
|
|
72
|
+
ErrorType["GetSpecFailed"] = "get-spec-failed";
|
|
72
73
|
ErrorType["Cancelled"] = "cancelled";
|
|
73
74
|
ErrorType["Unknown"] = "unknown";
|
|
74
75
|
})(exports.ErrorType || (exports.ErrorType = {}));
|
|
@@ -91,7 +92,13 @@ exports.ValidationStatus = void 0;
|
|
|
91
92
|
ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
|
|
92
93
|
ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
|
|
93
94
|
ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
|
|
94
|
-
})(exports.ValidationStatus || (exports.ValidationStatus = {}));
|
|
95
|
+
})(exports.ValidationStatus || (exports.ValidationStatus = {}));
|
|
96
|
+
exports.ProjectType = void 0;
|
|
97
|
+
(function (ProjectType) {
|
|
98
|
+
ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
|
|
99
|
+
ProjectType[ProjectType["SME"] = 1] = "SME";
|
|
100
|
+
ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
|
|
101
|
+
})(exports.ProjectType || (exports.ProjectType = {}));
|
|
95
102
|
|
|
96
103
|
// Copyright (c) Microsoft Corporation.
|
|
97
104
|
class ConstantString {
|
|
@@ -110,7 +117,8 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
|
|
|
110
117
|
ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
|
|
111
118
|
ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
|
|
112
119
|
ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
|
|
113
|
-
ConstantString.
|
|
120
|
+
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
121
|
+
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
114
122
|
ConstantString.WrappedCardVersion = "devPreview";
|
|
115
123
|
ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
|
|
116
124
|
ConstantString.WrappedCardResponseLayout = "list";
|
|
@@ -122,6 +130,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
|
122
130
|
ConstantString.TextBlockType = "TextBlock";
|
|
123
131
|
ConstantString.ContainerType = "Container";
|
|
124
132
|
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
133
|
+
ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
|
|
125
134
|
ConstantString.ResponseCodeFor20X = [
|
|
126
135
|
"200",
|
|
127
136
|
"201",
|
|
@@ -181,7 +190,8 @@ ConstantString.FullDescriptionMaxLens = 4000;
|
|
|
181
190
|
ConstantString.CommandDescriptionMaxLens = 128;
|
|
182
191
|
ConstantString.ParameterDescriptionMaxLens = 128;
|
|
183
192
|
ConstantString.CommandTitleMaxLens = 32;
|
|
184
|
-
ConstantString.ParameterTitleMaxLens = 32;
|
|
193
|
+
ConstantString.ParameterTitleMaxLens = 32;
|
|
194
|
+
ConstantString.SMERequiredParamsMaxNum = 5;
|
|
185
195
|
|
|
186
196
|
// Copyright (c) Microsoft Corporation.
|
|
187
197
|
class SpecParserError extends Error {
|
|
@@ -193,7 +203,18 @@ class SpecParserError extends Error {
|
|
|
193
203
|
|
|
194
204
|
// Copyright (c) Microsoft Corporation.
|
|
195
205
|
class Utils {
|
|
196
|
-
static
|
|
206
|
+
static hasNestedObjectInSchema(schema) {
|
|
207
|
+
if (schema.type === "object") {
|
|
208
|
+
for (const property in schema.properties) {
|
|
209
|
+
const nestedSchema = schema.properties[property];
|
|
210
|
+
if (nestedSchema.type === "object") {
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
static checkParameters(paramObject, isCopilot) {
|
|
197
218
|
const paramResult = {
|
|
198
219
|
requiredNum: 0,
|
|
199
220
|
optionalNum: 0,
|
|
@@ -205,7 +226,20 @@ class Utils {
|
|
|
205
226
|
for (let i = 0; i < paramObject.length; i++) {
|
|
206
227
|
const param = paramObject[i];
|
|
207
228
|
const schema = param.schema;
|
|
229
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
230
|
+
paramResult.isValid = false;
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
208
233
|
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
234
|
+
if (isCopilot) {
|
|
235
|
+
if (isRequiredWithoutDefault) {
|
|
236
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
240
|
+
}
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
209
243
|
if (param.in === "header" || param.in === "cookie") {
|
|
210
244
|
if (isRequiredWithoutDefault) {
|
|
211
245
|
paramResult.isValid = false;
|
|
@@ -232,7 +266,7 @@ class Utils {
|
|
|
232
266
|
}
|
|
233
267
|
return paramResult;
|
|
234
268
|
}
|
|
235
|
-
static checkPostBody(schema, isRequired = false) {
|
|
269
|
+
static checkPostBody(schema, isRequired = false, isCopilot = false) {
|
|
236
270
|
var _a;
|
|
237
271
|
const paramResult = {
|
|
238
272
|
requiredNum: 0,
|
|
@@ -243,6 +277,10 @@ class Utils {
|
|
|
243
277
|
return paramResult;
|
|
244
278
|
}
|
|
245
279
|
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
280
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
281
|
+
paramResult.isValid = false;
|
|
282
|
+
return paramResult;
|
|
283
|
+
}
|
|
246
284
|
if (schema.type === "string" ||
|
|
247
285
|
schema.type === "integer" ||
|
|
248
286
|
schema.type === "boolean" ||
|
|
@@ -261,19 +299,22 @@ class Utils {
|
|
|
261
299
|
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
262
300
|
isRequired = true;
|
|
263
301
|
}
|
|
264
|
-
const result = Utils.checkPostBody(properties[property], isRequired);
|
|
302
|
+
const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
|
|
265
303
|
paramResult.requiredNum += result.requiredNum;
|
|
266
304
|
paramResult.optionalNum += result.optionalNum;
|
|
267
305
|
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
268
306
|
}
|
|
269
307
|
}
|
|
270
308
|
else {
|
|
271
|
-
if (isRequiredWithoutDefault) {
|
|
309
|
+
if (isRequiredWithoutDefault && !isCopilot) {
|
|
272
310
|
paramResult.isValid = false;
|
|
273
311
|
}
|
|
274
312
|
}
|
|
275
313
|
return paramResult;
|
|
276
314
|
}
|
|
315
|
+
static containMultipleMediaTypes(bodyObject) {
|
|
316
|
+
return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
|
|
317
|
+
}
|
|
277
318
|
/**
|
|
278
319
|
* Checks if the given API is supported.
|
|
279
320
|
* @param {string} method - The HTTP method of the API.
|
|
@@ -288,32 +329,40 @@ class Utils {
|
|
|
288
329
|
* 5. response body should be “application/json” and not empty, and response code should be 20X
|
|
289
330
|
* 6. only support request body with “application/json” content type
|
|
290
331
|
*/
|
|
291
|
-
static isSupportedApi(method, path, spec,
|
|
332
|
+
static isSupportedApi(method, path, spec, options) {
|
|
333
|
+
var _a;
|
|
292
334
|
const pathObj = spec.paths[path];
|
|
293
335
|
method = method.toLocaleLowerCase();
|
|
294
336
|
if (pathObj) {
|
|
295
|
-
if ((
|
|
296
|
-
pathObj[method]) {
|
|
337
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
|
|
297
338
|
const securities = pathObj[method].security;
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
339
|
+
const isTeamsAi = options.projectType === exports.ProjectType.TeamsAi;
|
|
340
|
+
const isCopilot = options.projectType === exports.ProjectType.Copilot;
|
|
341
|
+
// Teams AI project doesn't care about auth, it will use authProvider for user to implement
|
|
342
|
+
if (!isTeamsAi) {
|
|
343
|
+
const authArray = Utils.getAuthArray(securities, spec);
|
|
344
|
+
if (!Utils.isSupportedAuth(authArray, options)) {
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
301
347
|
}
|
|
302
348
|
const operationObject = pathObj[method];
|
|
303
|
-
if (!allowMissingId && !operationObject.operationId) {
|
|
349
|
+
if (!options.allowMissingId && !operationObject.operationId) {
|
|
304
350
|
return false;
|
|
305
351
|
}
|
|
306
352
|
const paramObject = operationObject.parameters;
|
|
307
353
|
const requestBody = operationObject.requestBody;
|
|
308
354
|
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
309
|
-
|
|
310
|
-
if (mediaTypesCount > 1) {
|
|
355
|
+
if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
|
|
311
356
|
return false;
|
|
312
357
|
}
|
|
313
|
-
const responseJson = Utils.getResponseJson(operationObject);
|
|
358
|
+
const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
|
|
314
359
|
if (Object.keys(responseJson).length === 0) {
|
|
315
360
|
return false;
|
|
316
361
|
}
|
|
362
|
+
// Teams AI project doesn't care about request parameters/body
|
|
363
|
+
if (isTeamsAi) {
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
317
366
|
let requestBodyParamResult = {
|
|
318
367
|
requiredNum: 0,
|
|
319
368
|
optionalNum: 0,
|
|
@@ -321,18 +370,26 @@ class Utils {
|
|
|
321
370
|
};
|
|
322
371
|
if (requestJsonBody) {
|
|
323
372
|
const requestBodySchema = requestJsonBody.schema;
|
|
324
|
-
|
|
373
|
+
if (isCopilot && requestBodySchema.type !== "object") {
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
|
|
325
377
|
}
|
|
326
378
|
if (!requestBodyParamResult.isValid) {
|
|
327
379
|
return false;
|
|
328
380
|
}
|
|
329
|
-
const paramResult = Utils.checkParameters(paramObject);
|
|
381
|
+
const paramResult = Utils.checkParameters(paramObject, isCopilot);
|
|
330
382
|
if (!paramResult.isValid) {
|
|
331
383
|
return false;
|
|
332
384
|
}
|
|
385
|
+
// Copilot support arbitrary parameters
|
|
386
|
+
if (isCopilot) {
|
|
387
|
+
return true;
|
|
388
|
+
}
|
|
333
389
|
if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
|
|
334
|
-
if (allowMultipleParameters &&
|
|
335
|
-
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
390
|
+
if (options.allowMultipleParameters &&
|
|
391
|
+
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
392
|
+
ConstantString.SMERequiredParamsMaxNum) {
|
|
336
393
|
return true;
|
|
337
394
|
}
|
|
338
395
|
return false;
|
|
@@ -351,29 +408,20 @@ class Utils {
|
|
|
351
408
|
}
|
|
352
409
|
return false;
|
|
353
410
|
}
|
|
354
|
-
static isSupportedAuth(
|
|
355
|
-
if (
|
|
411
|
+
static isSupportedAuth(authSchemeArray, options) {
|
|
412
|
+
if (authSchemeArray.length === 0) {
|
|
356
413
|
return true;
|
|
357
414
|
}
|
|
358
|
-
if (allowAPIKeyAuth || allowOauth2) {
|
|
415
|
+
if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
|
|
359
416
|
// Currently we don't support multiple auth in one operation
|
|
360
|
-
if (
|
|
417
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
361
418
|
return false;
|
|
362
419
|
}
|
|
363
|
-
for (const auths of
|
|
420
|
+
for (const auths of authSchemeArray) {
|
|
364
421
|
if (auths.length === 1) {
|
|
365
|
-
if (
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
else if (!allowAPIKeyAuth &&
|
|
369
|
-
allowOauth2 &&
|
|
370
|
-
Utils.isBearerTokenAuth(auths[0].authSchema)) {
|
|
371
|
-
return true;
|
|
372
|
-
}
|
|
373
|
-
else if (allowAPIKeyAuth &&
|
|
374
|
-
allowOauth2 &&
|
|
375
|
-
(Utils.isAPIKeyAuth(auths[0].authSchema) ||
|
|
376
|
-
Utils.isBearerTokenAuth(auths[0].authSchema))) {
|
|
422
|
+
if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
423
|
+
(options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
|
|
424
|
+
(options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
|
|
377
425
|
return true;
|
|
378
426
|
}
|
|
379
427
|
}
|
|
@@ -381,13 +429,17 @@ class Utils {
|
|
|
381
429
|
}
|
|
382
430
|
return false;
|
|
383
431
|
}
|
|
384
|
-
static
|
|
385
|
-
return
|
|
432
|
+
static isBearerTokenAuth(authScheme) {
|
|
433
|
+
return authScheme.type === "http" && authScheme.scheme === "bearer";
|
|
386
434
|
}
|
|
387
|
-
static
|
|
388
|
-
return
|
|
389
|
-
|
|
390
|
-
|
|
435
|
+
static isAPIKeyAuth(authScheme) {
|
|
436
|
+
return authScheme.type === "apiKey";
|
|
437
|
+
}
|
|
438
|
+
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
439
|
+
if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
return false;
|
|
391
443
|
}
|
|
392
444
|
static getAuthArray(securities, spec) {
|
|
393
445
|
var _a;
|
|
@@ -400,7 +452,7 @@ class Utils {
|
|
|
400
452
|
for (const name in security) {
|
|
401
453
|
const auth = securitySchemas[name];
|
|
402
454
|
authArray.push({
|
|
403
|
-
|
|
455
|
+
authScheme: auth,
|
|
404
456
|
name: name,
|
|
405
457
|
});
|
|
406
458
|
}
|
|
@@ -415,18 +467,19 @@ class Utils {
|
|
|
415
467
|
static updateFirstLetter(str) {
|
|
416
468
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
417
469
|
}
|
|
418
|
-
static getResponseJson(operationObject) {
|
|
470
|
+
static getResponseJson(operationObject, isTeamsAiProject = false) {
|
|
419
471
|
var _a, _b;
|
|
420
472
|
let json = {};
|
|
421
473
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
422
474
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
423
|
-
const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
|
|
424
|
-
if (mediaTypesCount > 1) {
|
|
425
|
-
return {};
|
|
426
|
-
}
|
|
427
475
|
if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
|
|
428
476
|
json = responseObject.content["application/json"];
|
|
429
|
-
|
|
477
|
+
if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
|
|
478
|
+
json = {};
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
430
483
|
}
|
|
431
484
|
}
|
|
432
485
|
return json;
|
|
@@ -500,7 +553,7 @@ class Utils {
|
|
|
500
553
|
}
|
|
501
554
|
return errors;
|
|
502
555
|
}
|
|
503
|
-
static validateServer(spec,
|
|
556
|
+
static validateServer(spec, options) {
|
|
504
557
|
const errors = [];
|
|
505
558
|
let hasTopLevelServers = false;
|
|
506
559
|
let hasPathLevelServers = false;
|
|
@@ -521,7 +574,7 @@ class Utils {
|
|
|
521
574
|
}
|
|
522
575
|
for (const method in methods) {
|
|
523
576
|
const operationObject = methods[method];
|
|
524
|
-
if (Utils.isSupportedApi(method, path, spec,
|
|
577
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
525
578
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
526
579
|
hasOperationLevelServers = true;
|
|
527
580
|
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
@@ -608,7 +661,7 @@ class Utils {
|
|
|
608
661
|
param.value = schema.default;
|
|
609
662
|
}
|
|
610
663
|
}
|
|
611
|
-
static parseApiInfo(operationItem,
|
|
664
|
+
static parseApiInfo(operationItem, options) {
|
|
612
665
|
var _a, _b;
|
|
613
666
|
const requiredParams = [];
|
|
614
667
|
const optionalParams = [];
|
|
@@ -622,7 +675,7 @@ class Utils {
|
|
|
622
675
|
description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
|
|
623
676
|
};
|
|
624
677
|
const schema = param.schema;
|
|
625
|
-
if (allowMultipleParameters && schema) {
|
|
678
|
+
if (options.allowMultipleParameters && schema) {
|
|
626
679
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
627
680
|
}
|
|
628
681
|
if (param.in !== "header" && param.in !== "cookie") {
|
|
@@ -640,7 +693,7 @@ class Utils {
|
|
|
640
693
|
const requestJson = requestBody.content["application/json"];
|
|
641
694
|
if (Object.keys(requestJson).length !== 0) {
|
|
642
695
|
const schema = requestJson.schema;
|
|
643
|
-
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
|
|
696
|
+
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
|
|
644
697
|
requiredParams.push(...requiredP);
|
|
645
698
|
optionalParams.push(...optionalP);
|
|
646
699
|
}
|
|
@@ -671,14 +724,13 @@ class Utils {
|
|
|
671
724
|
}
|
|
672
725
|
return [command, warning];
|
|
673
726
|
}
|
|
674
|
-
static listSupportedAPIs(spec,
|
|
727
|
+
static listSupportedAPIs(spec, options) {
|
|
675
728
|
const paths = spec.paths;
|
|
676
729
|
const result = {};
|
|
677
730
|
for (const path in paths) {
|
|
678
731
|
const methods = paths[path];
|
|
679
732
|
for (const method in methods) {
|
|
680
|
-
|
|
681
|
-
if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
|
|
733
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
682
734
|
const operationObject = methods[method];
|
|
683
735
|
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
684
736
|
}
|
|
@@ -686,7 +738,7 @@ class Utils {
|
|
|
686
738
|
}
|
|
687
739
|
return result;
|
|
688
740
|
}
|
|
689
|
-
static validateSpec(spec, parser, isSwaggerFile,
|
|
741
|
+
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
690
742
|
const errors = [];
|
|
691
743
|
const warnings = [];
|
|
692
744
|
if (isSwaggerFile) {
|
|
@@ -696,7 +748,7 @@ class Utils {
|
|
|
696
748
|
});
|
|
697
749
|
}
|
|
698
750
|
// Server validation
|
|
699
|
-
const serverErrors = Utils.validateServer(spec,
|
|
751
|
+
const serverErrors = Utils.validateServer(spec, options);
|
|
700
752
|
errors.push(...serverErrors);
|
|
701
753
|
// Remote reference not supported
|
|
702
754
|
const refPaths = parser.$refs.paths();
|
|
@@ -709,7 +761,7 @@ class Utils {
|
|
|
709
761
|
});
|
|
710
762
|
}
|
|
711
763
|
// No supported API
|
|
712
|
-
const apiMap = Utils.listSupportedAPIs(spec,
|
|
764
|
+
const apiMap = Utils.listSupportedAPIs(spec, options);
|
|
713
765
|
if (Object.keys(apiMap).length === 0) {
|
|
714
766
|
errors.push({
|
|
715
767
|
type: exports.ErrorType.NoSupportedApi,
|
|
@@ -765,14 +817,14 @@ class Utils {
|
|
|
765
817
|
|
|
766
818
|
// Copyright (c) Microsoft Corporation.
|
|
767
819
|
class SpecFilter {
|
|
768
|
-
static specFilter(filter, unResolveSpec, resolvedSpec,
|
|
820
|
+
static specFilter(filter, unResolveSpec, resolvedSpec, options) {
|
|
769
821
|
try {
|
|
770
822
|
const newSpec = Object.assign({}, unResolveSpec);
|
|
771
823
|
const newPaths = {};
|
|
772
824
|
for (const filterItem of filter) {
|
|
773
825
|
const [method, path] = filterItem.split(" ");
|
|
774
826
|
const methodName = method.toLowerCase();
|
|
775
|
-
if (!Utils.isSupportedApi(methodName, path, resolvedSpec,
|
|
827
|
+
if (!Utils.isSupportedApi(methodName, path, resolvedSpec, options)) {
|
|
776
828
|
continue;
|
|
777
829
|
}
|
|
778
830
|
if (!newPaths[path]) {
|
|
@@ -798,47 +850,170 @@ class SpecFilter {
|
|
|
798
850
|
|
|
799
851
|
// Copyright (c) Microsoft Corporation.
|
|
800
852
|
class ManifestUpdater {
|
|
801
|
-
static
|
|
853
|
+
static updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options) {
|
|
854
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
855
|
+
const manifest = yield fs__default['default'].readJSON(manifestPath);
|
|
856
|
+
const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
|
|
857
|
+
manifest.plugins = [
|
|
858
|
+
{
|
|
859
|
+
pluginFile: apiPluginRelativePath,
|
|
860
|
+
},
|
|
861
|
+
];
|
|
862
|
+
ManifestUpdater.updateManifestDescription(manifest, spec);
|
|
863
|
+
const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
|
|
864
|
+
const apiPlugin = ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, options);
|
|
865
|
+
return [manifest, apiPlugin];
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
static updateManifestDescription(manifest, spec) {
|
|
802
869
|
var _a, _b;
|
|
870
|
+
manifest.description = {
|
|
871
|
+
short: spec.info.title.slice(0, ConstantString.ShortDescriptionMaxLens),
|
|
872
|
+
full: (_b = ((_a = spec.info.description) !== null && _a !== void 0 ? _a : manifest.description.full)) === null || _b === void 0 ? void 0 : _b.slice(0, ConstantString.FullDescriptionMaxLens),
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
static mapOpenAPISchemaToFuncParam(schema, method, pathUrl) {
|
|
876
|
+
let parameter;
|
|
877
|
+
if (schema.type === "string" ||
|
|
878
|
+
schema.type === "boolean" ||
|
|
879
|
+
schema.type === "integer" ||
|
|
880
|
+
schema.type === "number" ||
|
|
881
|
+
schema.type === "array") {
|
|
882
|
+
parameter = schema;
|
|
883
|
+
}
|
|
884
|
+
else {
|
|
885
|
+
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), exports.ErrorType.UpdateManifestFailed);
|
|
886
|
+
}
|
|
887
|
+
return parameter;
|
|
888
|
+
}
|
|
889
|
+
static generatePluginManifestSchema(spec, specRelativePath, options) {
|
|
890
|
+
var _a, _b, _c;
|
|
891
|
+
const functions = [];
|
|
892
|
+
const functionNames = [];
|
|
893
|
+
const paths = spec.paths;
|
|
894
|
+
for (const pathUrl in paths) {
|
|
895
|
+
const pathItem = paths[pathUrl];
|
|
896
|
+
if (pathItem) {
|
|
897
|
+
const operations = pathItem;
|
|
898
|
+
for (const method in operations) {
|
|
899
|
+
if (options.allowMethods.includes(method)) {
|
|
900
|
+
const operationItem = operations[method];
|
|
901
|
+
if (operationItem) {
|
|
902
|
+
const operationId = operationItem.operationId;
|
|
903
|
+
const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
|
|
904
|
+
const paramObject = operationItem.parameters;
|
|
905
|
+
const requestBody = operationItem.requestBody;
|
|
906
|
+
const parameters = {
|
|
907
|
+
type: "object",
|
|
908
|
+
properties: {},
|
|
909
|
+
required: [],
|
|
910
|
+
};
|
|
911
|
+
if (paramObject) {
|
|
912
|
+
for (let i = 0; i < paramObject.length; i++) {
|
|
913
|
+
const param = paramObject[i];
|
|
914
|
+
const schema = param.schema;
|
|
915
|
+
parameters.properties[param.name] = ManifestUpdater.mapOpenAPISchemaToFuncParam(schema, method, pathUrl);
|
|
916
|
+
if (param.required) {
|
|
917
|
+
parameters.required.push(param.name);
|
|
918
|
+
}
|
|
919
|
+
if (!parameters.properties[param.name].description) {
|
|
920
|
+
parameters.properties[param.name].description = (_b = param.description) !== null && _b !== void 0 ? _b : "";
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
if (requestBody) {
|
|
925
|
+
const requestJsonBody = requestBody.content["application/json"];
|
|
926
|
+
const requestBodySchema = requestJsonBody.schema;
|
|
927
|
+
if (requestBodySchema.type === "object") {
|
|
928
|
+
if (requestBodySchema.required) {
|
|
929
|
+
parameters.required.push(...requestBodySchema.required);
|
|
930
|
+
}
|
|
931
|
+
for (const property in requestBodySchema.properties) {
|
|
932
|
+
const schema = requestBodySchema.properties[property];
|
|
933
|
+
parameters.properties[property] = ManifestUpdater.mapOpenAPISchemaToFuncParam(schema, method, pathUrl);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
else {
|
|
937
|
+
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), exports.ErrorType.UpdateManifestFailed);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
const funcObj = {
|
|
941
|
+
name: operationId,
|
|
942
|
+
description: description,
|
|
943
|
+
parameters: parameters,
|
|
944
|
+
};
|
|
945
|
+
functions.push(funcObj);
|
|
946
|
+
functionNames.push(operationId);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
const apiPlugin = {
|
|
953
|
+
schema_version: "v2",
|
|
954
|
+
name_for_human: spec.info.title,
|
|
955
|
+
description_for_human: (_c = spec.info.description) !== null && _c !== void 0 ? _c : "<Please add description of the plugin>",
|
|
956
|
+
functions: functions,
|
|
957
|
+
runtimes: [
|
|
958
|
+
{
|
|
959
|
+
type: "OpenApi",
|
|
960
|
+
auth: {
|
|
961
|
+
type: "none", // TODO, support auth in the future
|
|
962
|
+
},
|
|
963
|
+
spec: {
|
|
964
|
+
url: specRelativePath,
|
|
965
|
+
},
|
|
966
|
+
run_for_functions: functionNames,
|
|
967
|
+
},
|
|
968
|
+
],
|
|
969
|
+
};
|
|
970
|
+
return apiPlugin;
|
|
971
|
+
}
|
|
972
|
+
static updateManifest(manifestPath, outputSpecPath, spec, options, adaptiveCardFolder, authInfo) {
|
|
803
973
|
return __awaiter(this, void 0, void 0, function* () {
|
|
804
974
|
try {
|
|
805
975
|
const originalManifest = yield fs__default['default'].readJSON(manifestPath);
|
|
806
976
|
const updatedPart = {};
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
commands
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
977
|
+
updatedPart.composeExtensions = [];
|
|
978
|
+
let warnings = [];
|
|
979
|
+
if (options.projectType === exports.ProjectType.SME) {
|
|
980
|
+
const updateResult = yield ManifestUpdater.generateCommands(spec, manifestPath, options, adaptiveCardFolder);
|
|
981
|
+
const commands = updateResult[0];
|
|
982
|
+
warnings = updateResult[1];
|
|
983
|
+
const composeExtension = {
|
|
984
|
+
composeExtensionType: "apiBased",
|
|
985
|
+
apiSpecificationFile: ManifestUpdater.getRelativePath(manifestPath, outputSpecPath),
|
|
986
|
+
commands: commands,
|
|
987
|
+
};
|
|
988
|
+
if (authInfo) {
|
|
989
|
+
const auth = authInfo.authScheme;
|
|
990
|
+
if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
|
|
991
|
+
const safeApiSecretRegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
|
|
992
|
+
composeExtension.authorization = {
|
|
993
|
+
authType: "apiSecretServiceAuth",
|
|
994
|
+
apiSecretServiceAuthConfiguration: {
|
|
995
|
+
apiSecretRegistrationId: `\${{${safeApiSecretRegistrationId}}}`,
|
|
996
|
+
},
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
else if (Utils.isOAuthWithAuthCodeFlow(auth)) {
|
|
1000
|
+
const safeOAuth2RegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.OAuthRegistrationIdPostFix}`);
|
|
1001
|
+
composeExtension.authorization = {
|
|
1002
|
+
authType: "oAuth2.0",
|
|
1003
|
+
oAuthConfiguration: {
|
|
1004
|
+
oauthConfigurationId: `\${{${safeOAuth2RegistrationId}}}`,
|
|
1005
|
+
},
|
|
1006
|
+
};
|
|
1007
|
+
updatedPart.webApplicationInfo = {
|
|
1008
|
+
id: "${{AAD_APP_CLIENT_ID}}",
|
|
1009
|
+
resource: "api://${{DOMAIN}}/${{AAD_APP_CLIENT_ID}}",
|
|
1010
|
+
};
|
|
1011
|
+
}
|
|
835
1012
|
}
|
|
1013
|
+
updatedPart.composeExtensions = [composeExtension];
|
|
836
1014
|
}
|
|
837
|
-
updatedPart.description =
|
|
838
|
-
|
|
839
|
-
full: (_b = ((_a = spec.info.description) !== null && _a !== void 0 ? _a : originalManifest.description.full)) === null || _b === void 0 ? void 0 : _b.slice(0, ConstantString.FullDescriptionMaxLens),
|
|
840
|
-
};
|
|
841
|
-
updatedPart.composeExtensions = [composeExtension];
|
|
1015
|
+
updatedPart.description = originalManifest.description;
|
|
1016
|
+
ManifestUpdater.updateManifestDescription(updatedPart, spec);
|
|
842
1017
|
const updatedManifest = Object.assign(Object.assign({}, originalManifest), updatedPart);
|
|
843
1018
|
return [updatedManifest, warnings];
|
|
844
1019
|
}
|
|
@@ -847,7 +1022,8 @@ class ManifestUpdater {
|
|
|
847
1022
|
}
|
|
848
1023
|
});
|
|
849
1024
|
}
|
|
850
|
-
static generateCommands(spec,
|
|
1025
|
+
static generateCommands(spec, manifestPath, options, adaptiveCardFolder) {
|
|
1026
|
+
var _a;
|
|
851
1027
|
return __awaiter(this, void 0, void 0, function* () {
|
|
852
1028
|
const paths = spec.paths;
|
|
853
1029
|
const commands = [];
|
|
@@ -859,14 +1035,16 @@ class ManifestUpdater {
|
|
|
859
1035
|
const operations = pathItem;
|
|
860
1036
|
// Currently only support GET and POST method
|
|
861
1037
|
for (const method in operations) {
|
|
862
|
-
if (
|
|
1038
|
+
if ((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) {
|
|
863
1039
|
const operationItem = operations[method];
|
|
864
1040
|
if (operationItem) {
|
|
865
|
-
const [command, warning] = Utils.parseApiInfo(operationItem,
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
1041
|
+
const [command, warning] = Utils.parseApiInfo(operationItem, options);
|
|
1042
|
+
if (adaptiveCardFolder) {
|
|
1043
|
+
const adaptiveCardPath = path__default['default'].join(adaptiveCardFolder, command.id + ".json");
|
|
1044
|
+
command.apiResponseRenderingTemplateFile = (yield fs__default['default'].pathExists(adaptiveCardPath))
|
|
1045
|
+
? ManifestUpdater.getRelativePath(manifestPath, adaptiveCardPath)
|
|
1046
|
+
: "";
|
|
1047
|
+
}
|
|
870
1048
|
if (warning) {
|
|
871
1049
|
warnings.push(warning);
|
|
872
1050
|
}
|
|
@@ -1150,8 +1328,11 @@ class SpecParser {
|
|
|
1150
1328
|
allowMissingId: true,
|
|
1151
1329
|
allowSwagger: true,
|
|
1152
1330
|
allowAPIKeyAuth: false,
|
|
1331
|
+
allowBearerTokenAuth: false,
|
|
1153
1332
|
allowMultipleParameters: false,
|
|
1154
1333
|
allowOauth2: false,
|
|
1334
|
+
allowMethods: ["get", "post"],
|
|
1335
|
+
projectType: exports.ProjectType.SME,
|
|
1155
1336
|
};
|
|
1156
1337
|
this.pathOrSpec = pathOrDoc;
|
|
1157
1338
|
this.parser = new SwaggerParser__default['default']();
|
|
@@ -1185,7 +1366,7 @@ class SpecParser {
|
|
|
1185
1366
|
],
|
|
1186
1367
|
};
|
|
1187
1368
|
}
|
|
1188
|
-
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options
|
|
1369
|
+
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
|
|
1189
1370
|
}
|
|
1190
1371
|
catch (err) {
|
|
1191
1372
|
throw new SpecParserError(err.toString(), exports.ErrorType.ValidateFailed);
|
|
@@ -1235,7 +1416,7 @@ class SpecParser {
|
|
|
1235
1416
|
const authArray = Utils.getAuthArray(operation.security, spec);
|
|
1236
1417
|
for (const auths of authArray) {
|
|
1237
1418
|
if (auths.length === 1) {
|
|
1238
|
-
apiResult.auth = auths[0].
|
|
1419
|
+
apiResult.auth = auths[0].authScheme;
|
|
1239
1420
|
break;
|
|
1240
1421
|
}
|
|
1241
1422
|
}
|
|
@@ -1252,49 +1433,110 @@ class SpecParser {
|
|
|
1252
1433
|
}
|
|
1253
1434
|
});
|
|
1254
1435
|
}
|
|
1436
|
+
/**
|
|
1437
|
+
* Generate specs according to the filters.
|
|
1438
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
1439
|
+
*/
|
|
1440
|
+
getFilteredSpecs(filter, signal) {
|
|
1441
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1442
|
+
try {
|
|
1443
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1444
|
+
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
1445
|
+
}
|
|
1446
|
+
yield this.loadSpec();
|
|
1447
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1448
|
+
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
1449
|
+
}
|
|
1450
|
+
const newUnResolvedSpec = SpecFilter.specFilter(filter, this.unResolveSpec, this.spec, this.options);
|
|
1451
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1452
|
+
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
1453
|
+
}
|
|
1454
|
+
const newSpec = (yield this.parser.dereference(newUnResolvedSpec));
|
|
1455
|
+
return [newUnResolvedSpec, newSpec];
|
|
1456
|
+
}
|
|
1457
|
+
catch (err) {
|
|
1458
|
+
if (err instanceof SpecParserError) {
|
|
1459
|
+
throw err;
|
|
1460
|
+
}
|
|
1461
|
+
throw new SpecParserError(err.toString(), exports.ErrorType.GetSpecFailed);
|
|
1462
|
+
}
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
1255
1465
|
/**
|
|
1256
1466
|
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
1257
1467
|
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
1258
1468
|
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
1259
1469
|
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
1260
|
-
* @param
|
|
1470
|
+
* @param pluginFilePath File path of the api plugin file to generate.
|
|
1261
1471
|
*/
|
|
1262
|
-
|
|
1472
|
+
generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
|
|
1263
1473
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1264
1474
|
const result = {
|
|
1265
1475
|
allSuccess: true,
|
|
1266
1476
|
warnings: [],
|
|
1267
1477
|
};
|
|
1268
1478
|
try {
|
|
1269
|
-
|
|
1270
|
-
|
|
1479
|
+
const newSpecs = yield this.getFilteredSpecs(filter, signal);
|
|
1480
|
+
const newUnResolvedSpec = newSpecs[0];
|
|
1481
|
+
const newSpec = newSpecs[1];
|
|
1482
|
+
let resultStr;
|
|
1483
|
+
if (outputSpecPath.endsWith(".yaml") || outputSpecPath.endsWith(".yml")) {
|
|
1484
|
+
resultStr = jsyaml__default['default'].dump(newUnResolvedSpec);
|
|
1271
1485
|
}
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
1486
|
+
else {
|
|
1487
|
+
resultStr = JSON.stringify(newUnResolvedSpec, null, 2);
|
|
1275
1488
|
}
|
|
1276
|
-
|
|
1489
|
+
yield fs__default['default'].outputFile(outputSpecPath, resultStr);
|
|
1277
1490
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1278
1491
|
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
1279
1492
|
}
|
|
1280
|
-
const
|
|
1281
|
-
|
|
1282
|
-
|
|
1493
|
+
const [updatedManifest, apiPlugin] = yield ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options);
|
|
1494
|
+
yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 2 });
|
|
1495
|
+
yield fs__default['default'].outputJSON(pluginFilePath, apiPlugin, { spaces: 2 });
|
|
1496
|
+
}
|
|
1497
|
+
catch (err) {
|
|
1498
|
+
if (err instanceof SpecParserError) {
|
|
1499
|
+
throw err;
|
|
1500
|
+
}
|
|
1501
|
+
throw new SpecParserError(err.toString(), exports.ErrorType.GenerateFailed);
|
|
1502
|
+
}
|
|
1503
|
+
return result;
|
|
1504
|
+
});
|
|
1505
|
+
}
|
|
1506
|
+
/**
|
|
1507
|
+
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
1508
|
+
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
1509
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
1510
|
+
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
1511
|
+
* @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
|
|
1512
|
+
*/
|
|
1513
|
+
generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
|
|
1514
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1515
|
+
const result = {
|
|
1516
|
+
allSuccess: true,
|
|
1517
|
+
warnings: [],
|
|
1518
|
+
};
|
|
1519
|
+
try {
|
|
1520
|
+
const newSpecs = yield this.getFilteredSpecs(filter, signal);
|
|
1521
|
+
const newUnResolvedSpec = newSpecs[0];
|
|
1522
|
+
const newSpec = newSpecs[1];
|
|
1523
|
+
const authSet = new Set();
|
|
1524
|
+
let hasMultipleAuth = false;
|
|
1283
1525
|
for (const url in newSpec.paths) {
|
|
1284
1526
|
for (const method in newSpec.paths[url]) {
|
|
1285
1527
|
const operation = newSpec.paths[url][method];
|
|
1286
1528
|
const authArray = Utils.getAuthArray(operation.security, newSpec);
|
|
1287
1529
|
if (authArray && authArray.length > 0) {
|
|
1288
|
-
|
|
1289
|
-
if (
|
|
1290
|
-
|
|
1530
|
+
authSet.add(authArray[0][0]);
|
|
1531
|
+
if (authSet.size > 1) {
|
|
1532
|
+
hasMultipleAuth = true;
|
|
1291
1533
|
break;
|
|
1292
1534
|
}
|
|
1293
1535
|
}
|
|
1294
1536
|
}
|
|
1295
1537
|
}
|
|
1296
|
-
if (
|
|
1297
|
-
throw new SpecParserError(ConstantString.
|
|
1538
|
+
if (hasMultipleAuth && this.options.projectType !== exports.ProjectType.TeamsAi) {
|
|
1539
|
+
throw new SpecParserError(ConstantString.MultipleAuthNotSupported, exports.ErrorType.MultipleAuthNotSupported);
|
|
1298
1540
|
}
|
|
1299
1541
|
let resultStr;
|
|
1300
1542
|
if (outputSpecPath.endsWith(".yaml") || outputSpecPath.endsWith(".yml")) {
|
|
@@ -1304,26 +1546,28 @@ class SpecParser {
|
|
|
1304
1546
|
resultStr = JSON.stringify(newUnResolvedSpec, null, 2);
|
|
1305
1547
|
}
|
|
1306
1548
|
yield fs__default['default'].outputFile(outputSpecPath, resultStr);
|
|
1307
|
-
|
|
1308
|
-
for (const
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1549
|
+
if (adaptiveCardFolder) {
|
|
1550
|
+
for (const url in newSpec.paths) {
|
|
1551
|
+
for (const method in newSpec.paths[url]) {
|
|
1552
|
+
// paths object may contain description/summary which is not a http method, so we need to check if it is a operation object
|
|
1553
|
+
if (this.options.allowMethods.includes(method)) {
|
|
1554
|
+
const operation = newSpec.paths[url][method];
|
|
1555
|
+
try {
|
|
1556
|
+
const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
|
|
1557
|
+
const fileName = path__default['default'].join(adaptiveCardFolder, `${operation.operationId}.json`);
|
|
1558
|
+
const wrappedCard = wrapAdaptiveCard(card, jsonPath);
|
|
1559
|
+
yield fs__default['default'].outputJSON(fileName, wrappedCard, { spaces: 2 });
|
|
1560
|
+
const dataFileName = path__default['default'].join(adaptiveCardFolder, `${operation.operationId}.data.json`);
|
|
1561
|
+
yield fs__default['default'].outputJSON(dataFileName, {}, { spaces: 2 });
|
|
1562
|
+
}
|
|
1563
|
+
catch (err) {
|
|
1564
|
+
result.allSuccess = false;
|
|
1565
|
+
result.warnings.push({
|
|
1566
|
+
type: exports.WarningType.GenerateCardFailed,
|
|
1567
|
+
content: err.toString(),
|
|
1568
|
+
data: operation.operationId,
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1327
1571
|
}
|
|
1328
1572
|
}
|
|
1329
1573
|
}
|
|
@@ -1331,8 +1575,8 @@ class SpecParser {
|
|
|
1331
1575
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1332
1576
|
throw new SpecParserError(ConstantString.CancelledMessage, exports.ErrorType.Cancelled);
|
|
1333
1577
|
}
|
|
1334
|
-
const
|
|
1335
|
-
const [updatedManifest, warnings] = yield ManifestUpdater.updateManifest(manifestPath, outputSpecPath,
|
|
1578
|
+
const authInfo = Array.from(authSet)[0];
|
|
1579
|
+
const [updatedManifest, warnings] = yield ManifestUpdater.updateManifest(manifestPath, outputSpecPath, newSpec, this.options, adaptiveCardFolder, authInfo);
|
|
1336
1580
|
yield fs__default['default'].outputJSON(manifestPath, updatedManifest, { spaces: 2 });
|
|
1337
1581
|
result.warnings.push(...warnings);
|
|
1338
1582
|
}
|
|
@@ -1364,12 +1608,13 @@ class SpecParser {
|
|
|
1364
1608
|
if (this.apiMap !== undefined) {
|
|
1365
1609
|
return this.apiMap;
|
|
1366
1610
|
}
|
|
1367
|
-
const result = Utils.listSupportedAPIs(spec, this.options
|
|
1611
|
+
const result = Utils.listSupportedAPIs(spec, this.options);
|
|
1368
1612
|
this.apiMap = result;
|
|
1369
1613
|
return result;
|
|
1370
1614
|
}
|
|
1371
1615
|
}
|
|
1372
1616
|
|
|
1617
|
+
exports.AdaptiveCardGenerator = AdaptiveCardGenerator;
|
|
1373
1618
|
exports.ConstantString = ConstantString;
|
|
1374
1619
|
exports.SpecParser = SpecParser;
|
|
1375
1620
|
exports.SpecParserError = SpecParserError;
|