@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.mjs
CHANGED
|
@@ -19,7 +19,7 @@ var ErrorType;
|
|
|
19
19
|
ErrorType["NoExtraAPICanBeAdded"] = "no-extra-api-can-be-added";
|
|
20
20
|
ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
|
|
21
21
|
ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
|
|
22
|
-
ErrorType["
|
|
22
|
+
ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
|
|
23
23
|
ErrorType["ListFailed"] = "list-failed";
|
|
24
24
|
ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
|
|
25
25
|
ErrorType["FilterSpecFailed"] = "filter-spec-failed";
|
|
@@ -27,6 +27,7 @@ var ErrorType;
|
|
|
27
27
|
ErrorType["GenerateAdaptiveCardFailed"] = "generate-adaptive-card-failed";
|
|
28
28
|
ErrorType["GenerateFailed"] = "generate-failed";
|
|
29
29
|
ErrorType["ValidateFailed"] = "validate-failed";
|
|
30
|
+
ErrorType["GetSpecFailed"] = "get-spec-failed";
|
|
30
31
|
ErrorType["Cancelled"] = "cancelled";
|
|
31
32
|
ErrorType["Unknown"] = "unknown";
|
|
32
33
|
})(ErrorType || (ErrorType = {}));
|
|
@@ -49,7 +50,13 @@ var ValidationStatus;
|
|
|
49
50
|
ValidationStatus[ValidationStatus["Valid"] = 0] = "Valid";
|
|
50
51
|
ValidationStatus[ValidationStatus["Warning"] = 1] = "Warning";
|
|
51
52
|
ValidationStatus[ValidationStatus["Error"] = 2] = "Error";
|
|
52
|
-
})(ValidationStatus || (ValidationStatus = {}));
|
|
53
|
+
})(ValidationStatus || (ValidationStatus = {}));
|
|
54
|
+
var ProjectType;
|
|
55
|
+
(function (ProjectType) {
|
|
56
|
+
ProjectType[ProjectType["Copilot"] = 0] = "Copilot";
|
|
57
|
+
ProjectType[ProjectType["SME"] = 1] = "SME";
|
|
58
|
+
ProjectType[ProjectType["TeamsAi"] = 2] = "TeamsAi";
|
|
59
|
+
})(ProjectType || (ProjectType = {}));
|
|
53
60
|
|
|
54
61
|
// Copyright (c) Microsoft Corporation.
|
|
55
62
|
class ConstantString {
|
|
@@ -68,7 +75,8 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
|
|
|
68
75
|
ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
|
|
69
76
|
ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
|
|
70
77
|
ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
|
|
71
|
-
ConstantString.
|
|
78
|
+
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
79
|
+
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
72
80
|
ConstantString.WrappedCardVersion = "devPreview";
|
|
73
81
|
ConstantString.WrappedCardSchema = "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.ResponseRenderingTemplate.schema.json";
|
|
74
82
|
ConstantString.WrappedCardResponseLayout = "list";
|
|
@@ -80,6 +88,7 @@ ConstantString.AdaptiveCardType = "AdaptiveCard";
|
|
|
80
88
|
ConstantString.TextBlockType = "TextBlock";
|
|
81
89
|
ConstantString.ContainerType = "Container";
|
|
82
90
|
ConstantString.RegistrationIdPostfix = "REGISTRATION_ID";
|
|
91
|
+
ConstantString.OAuthRegistrationIdPostFix = "OAUTH_REGISTRATION_ID";
|
|
83
92
|
ConstantString.ResponseCodeFor20X = [
|
|
84
93
|
"200",
|
|
85
94
|
"201",
|
|
@@ -139,7 +148,8 @@ ConstantString.FullDescriptionMaxLens = 4000;
|
|
|
139
148
|
ConstantString.CommandDescriptionMaxLens = 128;
|
|
140
149
|
ConstantString.ParameterDescriptionMaxLens = 128;
|
|
141
150
|
ConstantString.CommandTitleMaxLens = 32;
|
|
142
|
-
ConstantString.ParameterTitleMaxLens = 32;
|
|
151
|
+
ConstantString.ParameterTitleMaxLens = 32;
|
|
152
|
+
ConstantString.SMERequiredParamsMaxNum = 5;
|
|
143
153
|
|
|
144
154
|
// Copyright (c) Microsoft Corporation.
|
|
145
155
|
class SpecParserError extends Error {
|
|
@@ -151,7 +161,18 @@ class SpecParserError extends Error {
|
|
|
151
161
|
|
|
152
162
|
// Copyright (c) Microsoft Corporation.
|
|
153
163
|
class Utils {
|
|
154
|
-
static
|
|
164
|
+
static hasNestedObjectInSchema(schema) {
|
|
165
|
+
if (schema.type === "object") {
|
|
166
|
+
for (const property in schema.properties) {
|
|
167
|
+
const nestedSchema = schema.properties[property];
|
|
168
|
+
if (nestedSchema.type === "object") {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
static checkParameters(paramObject, isCopilot) {
|
|
155
176
|
const paramResult = {
|
|
156
177
|
requiredNum: 0,
|
|
157
178
|
optionalNum: 0,
|
|
@@ -163,7 +184,20 @@ class Utils {
|
|
|
163
184
|
for (let i = 0; i < paramObject.length; i++) {
|
|
164
185
|
const param = paramObject[i];
|
|
165
186
|
const schema = param.schema;
|
|
187
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
188
|
+
paramResult.isValid = false;
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
166
191
|
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
192
|
+
if (isCopilot) {
|
|
193
|
+
if (isRequiredWithoutDefault) {
|
|
194
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
198
|
+
}
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
167
201
|
if (param.in === "header" || param.in === "cookie") {
|
|
168
202
|
if (isRequiredWithoutDefault) {
|
|
169
203
|
paramResult.isValid = false;
|
|
@@ -190,7 +224,7 @@ class Utils {
|
|
|
190
224
|
}
|
|
191
225
|
return paramResult;
|
|
192
226
|
}
|
|
193
|
-
static checkPostBody(schema, isRequired = false) {
|
|
227
|
+
static checkPostBody(schema, isRequired = false, isCopilot = false) {
|
|
194
228
|
var _a;
|
|
195
229
|
const paramResult = {
|
|
196
230
|
requiredNum: 0,
|
|
@@ -201,6 +235,10 @@ class Utils {
|
|
|
201
235
|
return paramResult;
|
|
202
236
|
}
|
|
203
237
|
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
238
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
239
|
+
paramResult.isValid = false;
|
|
240
|
+
return paramResult;
|
|
241
|
+
}
|
|
204
242
|
if (schema.type === "string" ||
|
|
205
243
|
schema.type === "integer" ||
|
|
206
244
|
schema.type === "boolean" ||
|
|
@@ -219,19 +257,22 @@ class Utils {
|
|
|
219
257
|
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
220
258
|
isRequired = true;
|
|
221
259
|
}
|
|
222
|
-
const result = Utils.checkPostBody(properties[property], isRequired);
|
|
260
|
+
const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
|
|
223
261
|
paramResult.requiredNum += result.requiredNum;
|
|
224
262
|
paramResult.optionalNum += result.optionalNum;
|
|
225
263
|
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
226
264
|
}
|
|
227
265
|
}
|
|
228
266
|
else {
|
|
229
|
-
if (isRequiredWithoutDefault) {
|
|
267
|
+
if (isRequiredWithoutDefault && !isCopilot) {
|
|
230
268
|
paramResult.isValid = false;
|
|
231
269
|
}
|
|
232
270
|
}
|
|
233
271
|
return paramResult;
|
|
234
272
|
}
|
|
273
|
+
static containMultipleMediaTypes(bodyObject) {
|
|
274
|
+
return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
|
|
275
|
+
}
|
|
235
276
|
/**
|
|
236
277
|
* Checks if the given API is supported.
|
|
237
278
|
* @param {string} method - The HTTP method of the API.
|
|
@@ -246,32 +287,40 @@ class Utils {
|
|
|
246
287
|
* 5. response body should be “application/json” and not empty, and response code should be 20X
|
|
247
288
|
* 6. only support request body with “application/json” content type
|
|
248
289
|
*/
|
|
249
|
-
static isSupportedApi(method, path, spec,
|
|
290
|
+
static isSupportedApi(method, path, spec, options) {
|
|
291
|
+
var _a;
|
|
250
292
|
const pathObj = spec.paths[path];
|
|
251
293
|
method = method.toLocaleLowerCase();
|
|
252
294
|
if (pathObj) {
|
|
253
|
-
if ((
|
|
254
|
-
pathObj[method]) {
|
|
295
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
|
|
255
296
|
const securities = pathObj[method].security;
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
|
|
297
|
+
const isTeamsAi = options.projectType === ProjectType.TeamsAi;
|
|
298
|
+
const isCopilot = options.projectType === ProjectType.Copilot;
|
|
299
|
+
// Teams AI project doesn't care about auth, it will use authProvider for user to implement
|
|
300
|
+
if (!isTeamsAi) {
|
|
301
|
+
const authArray = Utils.getAuthArray(securities, spec);
|
|
302
|
+
if (!Utils.isSupportedAuth(authArray, options)) {
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
259
305
|
}
|
|
260
306
|
const operationObject = pathObj[method];
|
|
261
|
-
if (!allowMissingId && !operationObject.operationId) {
|
|
307
|
+
if (!options.allowMissingId && !operationObject.operationId) {
|
|
262
308
|
return false;
|
|
263
309
|
}
|
|
264
310
|
const paramObject = operationObject.parameters;
|
|
265
311
|
const requestBody = operationObject.requestBody;
|
|
266
312
|
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
267
|
-
|
|
268
|
-
if (mediaTypesCount > 1) {
|
|
313
|
+
if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
|
|
269
314
|
return false;
|
|
270
315
|
}
|
|
271
|
-
const responseJson = Utils.getResponseJson(operationObject);
|
|
316
|
+
const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
|
|
272
317
|
if (Object.keys(responseJson).length === 0) {
|
|
273
318
|
return false;
|
|
274
319
|
}
|
|
320
|
+
// Teams AI project doesn't care about request parameters/body
|
|
321
|
+
if (isTeamsAi) {
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
275
324
|
let requestBodyParamResult = {
|
|
276
325
|
requiredNum: 0,
|
|
277
326
|
optionalNum: 0,
|
|
@@ -279,18 +328,26 @@ class Utils {
|
|
|
279
328
|
};
|
|
280
329
|
if (requestJsonBody) {
|
|
281
330
|
const requestBodySchema = requestJsonBody.schema;
|
|
282
|
-
|
|
331
|
+
if (isCopilot && requestBodySchema.type !== "object") {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
|
|
283
335
|
}
|
|
284
336
|
if (!requestBodyParamResult.isValid) {
|
|
285
337
|
return false;
|
|
286
338
|
}
|
|
287
|
-
const paramResult = Utils.checkParameters(paramObject);
|
|
339
|
+
const paramResult = Utils.checkParameters(paramObject, isCopilot);
|
|
288
340
|
if (!paramResult.isValid) {
|
|
289
341
|
return false;
|
|
290
342
|
}
|
|
343
|
+
// Copilot support arbitrary parameters
|
|
344
|
+
if (isCopilot) {
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
291
347
|
if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
|
|
292
|
-
if (allowMultipleParameters &&
|
|
293
|
-
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
348
|
+
if (options.allowMultipleParameters &&
|
|
349
|
+
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
350
|
+
ConstantString.SMERequiredParamsMaxNum) {
|
|
294
351
|
return true;
|
|
295
352
|
}
|
|
296
353
|
return false;
|
|
@@ -309,29 +366,20 @@ class Utils {
|
|
|
309
366
|
}
|
|
310
367
|
return false;
|
|
311
368
|
}
|
|
312
|
-
static isSupportedAuth(
|
|
313
|
-
if (
|
|
369
|
+
static isSupportedAuth(authSchemeArray, options) {
|
|
370
|
+
if (authSchemeArray.length === 0) {
|
|
314
371
|
return true;
|
|
315
372
|
}
|
|
316
|
-
if (allowAPIKeyAuth || allowOauth2) {
|
|
373
|
+
if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
|
|
317
374
|
// Currently we don't support multiple auth in one operation
|
|
318
|
-
if (
|
|
375
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
319
376
|
return false;
|
|
320
377
|
}
|
|
321
|
-
for (const auths of
|
|
378
|
+
for (const auths of authSchemeArray) {
|
|
322
379
|
if (auths.length === 1) {
|
|
323
|
-
if (
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
else if (!allowAPIKeyAuth &&
|
|
327
|
-
allowOauth2 &&
|
|
328
|
-
Utils.isBearerTokenAuth(auths[0].authSchema)) {
|
|
329
|
-
return true;
|
|
330
|
-
}
|
|
331
|
-
else if (allowAPIKeyAuth &&
|
|
332
|
-
allowOauth2 &&
|
|
333
|
-
(Utils.isAPIKeyAuth(auths[0].authSchema) ||
|
|
334
|
-
Utils.isBearerTokenAuth(auths[0].authSchema))) {
|
|
380
|
+
if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
381
|
+
(options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
|
|
382
|
+
(options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
|
|
335
383
|
return true;
|
|
336
384
|
}
|
|
337
385
|
}
|
|
@@ -339,13 +387,17 @@ class Utils {
|
|
|
339
387
|
}
|
|
340
388
|
return false;
|
|
341
389
|
}
|
|
342
|
-
static
|
|
343
|
-
return
|
|
390
|
+
static isBearerTokenAuth(authScheme) {
|
|
391
|
+
return authScheme.type === "http" && authScheme.scheme === "bearer";
|
|
344
392
|
}
|
|
345
|
-
static
|
|
346
|
-
return
|
|
347
|
-
|
|
348
|
-
|
|
393
|
+
static isAPIKeyAuth(authScheme) {
|
|
394
|
+
return authScheme.type === "apiKey";
|
|
395
|
+
}
|
|
396
|
+
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
397
|
+
if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
return false;
|
|
349
401
|
}
|
|
350
402
|
static getAuthArray(securities, spec) {
|
|
351
403
|
var _a;
|
|
@@ -358,7 +410,7 @@ class Utils {
|
|
|
358
410
|
for (const name in security) {
|
|
359
411
|
const auth = securitySchemas[name];
|
|
360
412
|
authArray.push({
|
|
361
|
-
|
|
413
|
+
authScheme: auth,
|
|
362
414
|
name: name,
|
|
363
415
|
});
|
|
364
416
|
}
|
|
@@ -373,18 +425,19 @@ class Utils {
|
|
|
373
425
|
static updateFirstLetter(str) {
|
|
374
426
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
375
427
|
}
|
|
376
|
-
static getResponseJson(operationObject) {
|
|
428
|
+
static getResponseJson(operationObject, isTeamsAiProject = false) {
|
|
377
429
|
var _a, _b;
|
|
378
430
|
let json = {};
|
|
379
431
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
380
432
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
381
|
-
const mediaTypesCount = Object.keys((responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) || {}).length;
|
|
382
|
-
if (mediaTypesCount > 1) {
|
|
383
|
-
return {};
|
|
384
|
-
}
|
|
385
433
|
if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
|
|
386
434
|
json = responseObject.content["application/json"];
|
|
387
|
-
|
|
435
|
+
if (!isTeamsAiProject && Utils.containMultipleMediaTypes(responseObject)) {
|
|
436
|
+
json = {};
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
388
441
|
}
|
|
389
442
|
}
|
|
390
443
|
return json;
|
|
@@ -458,7 +511,7 @@ class Utils {
|
|
|
458
511
|
}
|
|
459
512
|
return errors;
|
|
460
513
|
}
|
|
461
|
-
static validateServer(spec,
|
|
514
|
+
static validateServer(spec, options) {
|
|
462
515
|
const errors = [];
|
|
463
516
|
let hasTopLevelServers = false;
|
|
464
517
|
let hasPathLevelServers = false;
|
|
@@ -479,7 +532,7 @@ class Utils {
|
|
|
479
532
|
}
|
|
480
533
|
for (const method in methods) {
|
|
481
534
|
const operationObject = methods[method];
|
|
482
|
-
if (Utils.isSupportedApi(method, path, spec,
|
|
535
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
483
536
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
484
537
|
hasOperationLevelServers = true;
|
|
485
538
|
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
@@ -566,7 +619,7 @@ class Utils {
|
|
|
566
619
|
param.value = schema.default;
|
|
567
620
|
}
|
|
568
621
|
}
|
|
569
|
-
static parseApiInfo(operationItem,
|
|
622
|
+
static parseApiInfo(operationItem, options) {
|
|
570
623
|
var _a, _b;
|
|
571
624
|
const requiredParams = [];
|
|
572
625
|
const optionalParams = [];
|
|
@@ -580,7 +633,7 @@ class Utils {
|
|
|
580
633
|
description: ((_a = param.description) !== null && _a !== void 0 ? _a : "").slice(0, ConstantString.ParameterDescriptionMaxLens),
|
|
581
634
|
};
|
|
582
635
|
const schema = param.schema;
|
|
583
|
-
if (allowMultipleParameters && schema) {
|
|
636
|
+
if (options.allowMultipleParameters && schema) {
|
|
584
637
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
585
638
|
}
|
|
586
639
|
if (param.in !== "header" && param.in !== "cookie") {
|
|
@@ -598,7 +651,7 @@ class Utils {
|
|
|
598
651
|
const requestJson = requestBody.content["application/json"];
|
|
599
652
|
if (Object.keys(requestJson).length !== 0) {
|
|
600
653
|
const schema = requestJson.schema;
|
|
601
|
-
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", allowMultipleParameters, requestBody.required);
|
|
654
|
+
const [requiredP, optionalP] = Utils.generateParametersFromSchema(schema, "requestBody", !!options.allowMultipleParameters, requestBody.required);
|
|
602
655
|
requiredParams.push(...requiredP);
|
|
603
656
|
optionalParams.push(...optionalP);
|
|
604
657
|
}
|
|
@@ -629,14 +682,13 @@ class Utils {
|
|
|
629
682
|
}
|
|
630
683
|
return [command, warning];
|
|
631
684
|
}
|
|
632
|
-
static listSupportedAPIs(spec,
|
|
685
|
+
static listSupportedAPIs(spec, options) {
|
|
633
686
|
const paths = spec.paths;
|
|
634
687
|
const result = {};
|
|
635
688
|
for (const path in paths) {
|
|
636
689
|
const methods = paths[path];
|
|
637
690
|
for (const method in methods) {
|
|
638
|
-
|
|
639
|
-
if (Utils.isSupportedApi(method, path, spec, allowMissingId, allowAPIKeyAuth, allowMultipleParameters, allowOauth2)) {
|
|
691
|
+
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
640
692
|
const operationObject = methods[method];
|
|
641
693
|
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
642
694
|
}
|
|
@@ -644,7 +696,7 @@ class Utils {
|
|
|
644
696
|
}
|
|
645
697
|
return result;
|
|
646
698
|
}
|
|
647
|
-
static validateSpec(spec, parser, isSwaggerFile,
|
|
699
|
+
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
648
700
|
const errors = [];
|
|
649
701
|
const warnings = [];
|
|
650
702
|
if (isSwaggerFile) {
|
|
@@ -654,7 +706,7 @@ class Utils {
|
|
|
654
706
|
});
|
|
655
707
|
}
|
|
656
708
|
// Server validation
|
|
657
|
-
const serverErrors = Utils.validateServer(spec,
|
|
709
|
+
const serverErrors = Utils.validateServer(spec, options);
|
|
658
710
|
errors.push(...serverErrors);
|
|
659
711
|
// Remote reference not supported
|
|
660
712
|
const refPaths = parser.$refs.paths();
|
|
@@ -667,7 +719,7 @@ class Utils {
|
|
|
667
719
|
});
|
|
668
720
|
}
|
|
669
721
|
// No supported API
|
|
670
|
-
const apiMap = Utils.listSupportedAPIs(spec,
|
|
722
|
+
const apiMap = Utils.listSupportedAPIs(spec, options);
|
|
671
723
|
if (Object.keys(apiMap).length === 0) {
|
|
672
724
|
errors.push({
|
|
673
725
|
type: ErrorType.NoSupportedApi,
|
|
@@ -723,14 +775,14 @@ class Utils {
|
|
|
723
775
|
|
|
724
776
|
// Copyright (c) Microsoft Corporation.
|
|
725
777
|
class SpecFilter {
|
|
726
|
-
static specFilter(filter, unResolveSpec, resolvedSpec,
|
|
778
|
+
static specFilter(filter, unResolveSpec, resolvedSpec, options) {
|
|
727
779
|
try {
|
|
728
780
|
const newSpec = Object.assign({}, unResolveSpec);
|
|
729
781
|
const newPaths = {};
|
|
730
782
|
for (const filterItem of filter) {
|
|
731
783
|
const [method, path] = filterItem.split(" ");
|
|
732
784
|
const methodName = method.toLowerCase();
|
|
733
|
-
if (!Utils.isSupportedApi(methodName, path, resolvedSpec,
|
|
785
|
+
if (!Utils.isSupportedApi(methodName, path, resolvedSpec, options)) {
|
|
734
786
|
continue;
|
|
735
787
|
}
|
|
736
788
|
if (!newPaths[path]) {
|
|
@@ -756,46 +808,167 @@ class SpecFilter {
|
|
|
756
808
|
|
|
757
809
|
// Copyright (c) Microsoft Corporation.
|
|
758
810
|
class ManifestUpdater {
|
|
759
|
-
static async
|
|
811
|
+
static async updateManifestWithAiPlugin(manifestPath, outputSpecPath, apiPluginFilePath, spec, options) {
|
|
812
|
+
const manifest = await fs.readJSON(manifestPath);
|
|
813
|
+
const apiPluginRelativePath = ManifestUpdater.getRelativePath(manifestPath, apiPluginFilePath);
|
|
814
|
+
manifest.plugins = [
|
|
815
|
+
{
|
|
816
|
+
pluginFile: apiPluginRelativePath,
|
|
817
|
+
},
|
|
818
|
+
];
|
|
819
|
+
ManifestUpdater.updateManifestDescription(manifest, spec);
|
|
820
|
+
const specRelativePath = ManifestUpdater.getRelativePath(manifestPath, outputSpecPath);
|
|
821
|
+
const apiPlugin = ManifestUpdater.generatePluginManifestSchema(spec, specRelativePath, options);
|
|
822
|
+
return [manifest, apiPlugin];
|
|
823
|
+
}
|
|
824
|
+
static updateManifestDescription(manifest, spec) {
|
|
760
825
|
var _a, _b;
|
|
826
|
+
manifest.description = {
|
|
827
|
+
short: spec.info.title.slice(0, ConstantString.ShortDescriptionMaxLens),
|
|
828
|
+
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),
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
static mapOpenAPISchemaToFuncParam(schema, method, pathUrl) {
|
|
832
|
+
let parameter;
|
|
833
|
+
if (schema.type === "string" ||
|
|
834
|
+
schema.type === "boolean" ||
|
|
835
|
+
schema.type === "integer" ||
|
|
836
|
+
schema.type === "number" ||
|
|
837
|
+
schema.type === "array") {
|
|
838
|
+
parameter = schema;
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(schema)), ErrorType.UpdateManifestFailed);
|
|
842
|
+
}
|
|
843
|
+
return parameter;
|
|
844
|
+
}
|
|
845
|
+
static generatePluginManifestSchema(spec, specRelativePath, options) {
|
|
846
|
+
var _a, _b, _c;
|
|
847
|
+
const functions = [];
|
|
848
|
+
const functionNames = [];
|
|
849
|
+
const paths = spec.paths;
|
|
850
|
+
for (const pathUrl in paths) {
|
|
851
|
+
const pathItem = paths[pathUrl];
|
|
852
|
+
if (pathItem) {
|
|
853
|
+
const operations = pathItem;
|
|
854
|
+
for (const method in operations) {
|
|
855
|
+
if (options.allowMethods.includes(method)) {
|
|
856
|
+
const operationItem = operations[method];
|
|
857
|
+
if (operationItem) {
|
|
858
|
+
const operationId = operationItem.operationId;
|
|
859
|
+
const description = (_a = operationItem.description) !== null && _a !== void 0 ? _a : "";
|
|
860
|
+
const paramObject = operationItem.parameters;
|
|
861
|
+
const requestBody = operationItem.requestBody;
|
|
862
|
+
const parameters = {
|
|
863
|
+
type: "object",
|
|
864
|
+
properties: {},
|
|
865
|
+
required: [],
|
|
866
|
+
};
|
|
867
|
+
if (paramObject) {
|
|
868
|
+
for (let i = 0; i < paramObject.length; i++) {
|
|
869
|
+
const param = paramObject[i];
|
|
870
|
+
const schema = param.schema;
|
|
871
|
+
parameters.properties[param.name] = ManifestUpdater.mapOpenAPISchemaToFuncParam(schema, method, pathUrl);
|
|
872
|
+
if (param.required) {
|
|
873
|
+
parameters.required.push(param.name);
|
|
874
|
+
}
|
|
875
|
+
if (!parameters.properties[param.name].description) {
|
|
876
|
+
parameters.properties[param.name].description = (_b = param.description) !== null && _b !== void 0 ? _b : "";
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
if (requestBody) {
|
|
881
|
+
const requestJsonBody = requestBody.content["application/json"];
|
|
882
|
+
const requestBodySchema = requestJsonBody.schema;
|
|
883
|
+
if (requestBodySchema.type === "object") {
|
|
884
|
+
if (requestBodySchema.required) {
|
|
885
|
+
parameters.required.push(...requestBodySchema.required);
|
|
886
|
+
}
|
|
887
|
+
for (const property in requestBodySchema.properties) {
|
|
888
|
+
const schema = requestBodySchema.properties[property];
|
|
889
|
+
parameters.properties[property] = ManifestUpdater.mapOpenAPISchemaToFuncParam(schema, method, pathUrl);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
else {
|
|
893
|
+
throw new SpecParserError(Utils.format(ConstantString.UnsupportedSchema, method, pathUrl, JSON.stringify(requestBodySchema)), ErrorType.UpdateManifestFailed);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
const funcObj = {
|
|
897
|
+
name: operationId,
|
|
898
|
+
description: description,
|
|
899
|
+
parameters: parameters,
|
|
900
|
+
};
|
|
901
|
+
functions.push(funcObj);
|
|
902
|
+
functionNames.push(operationId);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
const apiPlugin = {
|
|
909
|
+
schema_version: "v2",
|
|
910
|
+
name_for_human: spec.info.title,
|
|
911
|
+
description_for_human: (_c = spec.info.description) !== null && _c !== void 0 ? _c : "<Please add description of the plugin>",
|
|
912
|
+
functions: functions,
|
|
913
|
+
runtimes: [
|
|
914
|
+
{
|
|
915
|
+
type: "OpenApi",
|
|
916
|
+
auth: {
|
|
917
|
+
type: "none", // TODO, support auth in the future
|
|
918
|
+
},
|
|
919
|
+
spec: {
|
|
920
|
+
url: specRelativePath,
|
|
921
|
+
},
|
|
922
|
+
run_for_functions: functionNames,
|
|
923
|
+
},
|
|
924
|
+
],
|
|
925
|
+
};
|
|
926
|
+
return apiPlugin;
|
|
927
|
+
}
|
|
928
|
+
static async updateManifest(manifestPath, outputSpecPath, spec, options, adaptiveCardFolder, authInfo) {
|
|
761
929
|
try {
|
|
762
930
|
const originalManifest = await fs.readJSON(manifestPath);
|
|
763
931
|
const updatedPart = {};
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
commands
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
932
|
+
updatedPart.composeExtensions = [];
|
|
933
|
+
let warnings = [];
|
|
934
|
+
if (options.projectType === ProjectType.SME) {
|
|
935
|
+
const updateResult = await ManifestUpdater.generateCommands(spec, manifestPath, options, adaptiveCardFolder);
|
|
936
|
+
const commands = updateResult[0];
|
|
937
|
+
warnings = updateResult[1];
|
|
938
|
+
const composeExtension = {
|
|
939
|
+
composeExtensionType: "apiBased",
|
|
940
|
+
apiSpecificationFile: ManifestUpdater.getRelativePath(manifestPath, outputSpecPath),
|
|
941
|
+
commands: commands,
|
|
942
|
+
};
|
|
943
|
+
if (authInfo) {
|
|
944
|
+
const auth = authInfo.authScheme;
|
|
945
|
+
if (Utils.isAPIKeyAuth(auth) || Utils.isBearerTokenAuth(auth)) {
|
|
946
|
+
const safeApiSecretRegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.RegistrationIdPostfix}`);
|
|
947
|
+
composeExtension.authorization = {
|
|
948
|
+
authType: "apiSecretServiceAuth",
|
|
949
|
+
apiSecretServiceAuthConfiguration: {
|
|
950
|
+
apiSecretRegistrationId: `\${{${safeApiSecretRegistrationId}}}`,
|
|
951
|
+
},
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
else if (Utils.isOAuthWithAuthCodeFlow(auth)) {
|
|
955
|
+
const safeOAuth2RegistrationId = Utils.getSafeRegistrationIdEnvName(`${authInfo.name}_${ConstantString.OAuthRegistrationIdPostFix}`);
|
|
956
|
+
composeExtension.authorization = {
|
|
957
|
+
authType: "oAuth2.0",
|
|
958
|
+
oAuthConfiguration: {
|
|
959
|
+
oauthConfigurationId: `\${{${safeOAuth2RegistrationId}}}`,
|
|
960
|
+
},
|
|
961
|
+
};
|
|
962
|
+
updatedPart.webApplicationInfo = {
|
|
963
|
+
id: "${{AAD_APP_CLIENT_ID}}",
|
|
964
|
+
resource: "api://${{DOMAIN}}/${{AAD_APP_CLIENT_ID}}",
|
|
965
|
+
};
|
|
966
|
+
}
|
|
792
967
|
}
|
|
968
|
+
updatedPart.composeExtensions = [composeExtension];
|
|
793
969
|
}
|
|
794
|
-
updatedPart.description =
|
|
795
|
-
|
|
796
|
-
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),
|
|
797
|
-
};
|
|
798
|
-
updatedPart.composeExtensions = [composeExtension];
|
|
970
|
+
updatedPart.description = originalManifest.description;
|
|
971
|
+
ManifestUpdater.updateManifestDescription(updatedPart, spec);
|
|
799
972
|
const updatedManifest = Object.assign(Object.assign({}, originalManifest), updatedPart);
|
|
800
973
|
return [updatedManifest, warnings];
|
|
801
974
|
}
|
|
@@ -803,7 +976,8 @@ class ManifestUpdater {
|
|
|
803
976
|
throw new SpecParserError(err.toString(), ErrorType.UpdateManifestFailed);
|
|
804
977
|
}
|
|
805
978
|
}
|
|
806
|
-
static async generateCommands(spec,
|
|
979
|
+
static async generateCommands(spec, manifestPath, options, adaptiveCardFolder) {
|
|
980
|
+
var _a;
|
|
807
981
|
const paths = spec.paths;
|
|
808
982
|
const commands = [];
|
|
809
983
|
const warnings = [];
|
|
@@ -814,14 +988,16 @@ class ManifestUpdater {
|
|
|
814
988
|
const operations = pathItem;
|
|
815
989
|
// Currently only support GET and POST method
|
|
816
990
|
for (const method in operations) {
|
|
817
|
-
if (
|
|
991
|
+
if ((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) {
|
|
818
992
|
const operationItem = operations[method];
|
|
819
993
|
if (operationItem) {
|
|
820
|
-
const [command, warning] = Utils.parseApiInfo(operationItem,
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
994
|
+
const [command, warning] = Utils.parseApiInfo(operationItem, options);
|
|
995
|
+
if (adaptiveCardFolder) {
|
|
996
|
+
const adaptiveCardPath = path.join(adaptiveCardFolder, command.id + ".json");
|
|
997
|
+
command.apiResponseRenderingTemplateFile = (await fs.pathExists(adaptiveCardPath))
|
|
998
|
+
? ManifestUpdater.getRelativePath(manifestPath, adaptiveCardPath)
|
|
999
|
+
: "";
|
|
1000
|
+
}
|
|
825
1001
|
if (warning) {
|
|
826
1002
|
warnings.push(warning);
|
|
827
1003
|
}
|
|
@@ -1104,8 +1280,11 @@ class SpecParser {
|
|
|
1104
1280
|
allowMissingId: true,
|
|
1105
1281
|
allowSwagger: true,
|
|
1106
1282
|
allowAPIKeyAuth: false,
|
|
1283
|
+
allowBearerTokenAuth: false,
|
|
1107
1284
|
allowMultipleParameters: false,
|
|
1108
1285
|
allowOauth2: false,
|
|
1286
|
+
allowMethods: ["get", "post"],
|
|
1287
|
+
projectType: ProjectType.SME,
|
|
1109
1288
|
};
|
|
1110
1289
|
this.pathOrSpec = pathOrDoc;
|
|
1111
1290
|
this.parser = new SwaggerParser();
|
|
@@ -1138,7 +1317,7 @@ class SpecParser {
|
|
|
1138
1317
|
],
|
|
1139
1318
|
};
|
|
1140
1319
|
}
|
|
1141
|
-
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options
|
|
1320
|
+
return Utils.validateSpec(this.spec, this.parser, !!this.isSwaggerFile, this.options);
|
|
1142
1321
|
}
|
|
1143
1322
|
catch (err) {
|
|
1144
1323
|
throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
|
|
@@ -1184,7 +1363,7 @@ class SpecParser {
|
|
|
1184
1363
|
const authArray = Utils.getAuthArray(operation.security, spec);
|
|
1185
1364
|
for (const auths of authArray) {
|
|
1186
1365
|
if (auths.length === 1) {
|
|
1187
|
-
apiResult.auth = auths[0].
|
|
1366
|
+
apiResult.auth = auths[0].authScheme;
|
|
1188
1367
|
break;
|
|
1189
1368
|
}
|
|
1190
1369
|
}
|
|
@@ -1200,48 +1379,105 @@ class SpecParser {
|
|
|
1200
1379
|
throw new SpecParserError(err.toString(), ErrorType.ListFailed);
|
|
1201
1380
|
}
|
|
1202
1381
|
}
|
|
1382
|
+
/**
|
|
1383
|
+
* Generate specs according to the filters.
|
|
1384
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
1385
|
+
*/
|
|
1386
|
+
async getFilteredSpecs(filter, signal) {
|
|
1387
|
+
try {
|
|
1388
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1389
|
+
throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
|
|
1390
|
+
}
|
|
1391
|
+
await this.loadSpec();
|
|
1392
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1393
|
+
throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
|
|
1394
|
+
}
|
|
1395
|
+
const newUnResolvedSpec = SpecFilter.specFilter(filter, this.unResolveSpec, this.spec, this.options);
|
|
1396
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1397
|
+
throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
|
|
1398
|
+
}
|
|
1399
|
+
const newSpec = (await this.parser.dereference(newUnResolvedSpec));
|
|
1400
|
+
return [newUnResolvedSpec, newSpec];
|
|
1401
|
+
}
|
|
1402
|
+
catch (err) {
|
|
1403
|
+
if (err instanceof SpecParserError) {
|
|
1404
|
+
throw err;
|
|
1405
|
+
}
|
|
1406
|
+
throw new SpecParserError(err.toString(), ErrorType.GetSpecFailed);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1203
1409
|
/**
|
|
1204
1410
|
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
1205
1411
|
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
1206
1412
|
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
1207
1413
|
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
1208
|
-
* @param
|
|
1414
|
+
* @param pluginFilePath File path of the api plugin file to generate.
|
|
1209
1415
|
*/
|
|
1210
|
-
async
|
|
1416
|
+
async generateForCopilot(manifestPath, filter, outputSpecPath, pluginFilePath, signal) {
|
|
1211
1417
|
const result = {
|
|
1212
1418
|
allSuccess: true,
|
|
1213
1419
|
warnings: [],
|
|
1214
1420
|
};
|
|
1215
1421
|
try {
|
|
1216
|
-
|
|
1217
|
-
|
|
1422
|
+
const newSpecs = await this.getFilteredSpecs(filter, signal);
|
|
1423
|
+
const newUnResolvedSpec = newSpecs[0];
|
|
1424
|
+
const newSpec = newSpecs[1];
|
|
1425
|
+
let resultStr;
|
|
1426
|
+
if (outputSpecPath.endsWith(".yaml") || outputSpecPath.endsWith(".yml")) {
|
|
1427
|
+
resultStr = jsyaml.dump(newUnResolvedSpec);
|
|
1218
1428
|
}
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
|
|
1429
|
+
else {
|
|
1430
|
+
resultStr = JSON.stringify(newUnResolvedSpec, null, 2);
|
|
1222
1431
|
}
|
|
1223
|
-
|
|
1432
|
+
await fs.outputFile(outputSpecPath, resultStr);
|
|
1224
1433
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1225
1434
|
throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
|
|
1226
1435
|
}
|
|
1227
|
-
const
|
|
1228
|
-
|
|
1229
|
-
|
|
1436
|
+
const [updatedManifest, apiPlugin] = await ManifestUpdater.updateManifestWithAiPlugin(manifestPath, outputSpecPath, pluginFilePath, newSpec, this.options);
|
|
1437
|
+
await fs.outputJSON(manifestPath, updatedManifest, { spaces: 2 });
|
|
1438
|
+
await fs.outputJSON(pluginFilePath, apiPlugin, { spaces: 2 });
|
|
1439
|
+
}
|
|
1440
|
+
catch (err) {
|
|
1441
|
+
if (err instanceof SpecParserError) {
|
|
1442
|
+
throw err;
|
|
1443
|
+
}
|
|
1444
|
+
throw new SpecParserError(err.toString(), ErrorType.GenerateFailed);
|
|
1445
|
+
}
|
|
1446
|
+
return result;
|
|
1447
|
+
}
|
|
1448
|
+
/**
|
|
1449
|
+
* Generates and update artifacts from the OpenAPI specification file. Generate Adaptive Cards, update Teams app manifest, and generate a new OpenAPI specification file.
|
|
1450
|
+
* @param manifestPath A file path of the Teams app manifest file to update.
|
|
1451
|
+
* @param filter An array of strings that represent the filters to apply when generating the artifacts. If filter is empty, it would process nothing.
|
|
1452
|
+
* @param outputSpecPath File path of the new OpenAPI specification file to generate. If not specified or empty, no spec file will be generated.
|
|
1453
|
+
* @param adaptiveCardFolder Folder path where the Adaptive Card files will be generated. If not specified or empty, Adaptive Card files will not be generated.
|
|
1454
|
+
*/
|
|
1455
|
+
async generate(manifestPath, filter, outputSpecPath, adaptiveCardFolder, signal) {
|
|
1456
|
+
const result = {
|
|
1457
|
+
allSuccess: true,
|
|
1458
|
+
warnings: [],
|
|
1459
|
+
};
|
|
1460
|
+
try {
|
|
1461
|
+
const newSpecs = await this.getFilteredSpecs(filter, signal);
|
|
1462
|
+
const newUnResolvedSpec = newSpecs[0];
|
|
1463
|
+
const newSpec = newSpecs[1];
|
|
1464
|
+
const authSet = new Set();
|
|
1465
|
+
let hasMultipleAuth = false;
|
|
1230
1466
|
for (const url in newSpec.paths) {
|
|
1231
1467
|
for (const method in newSpec.paths[url]) {
|
|
1232
1468
|
const operation = newSpec.paths[url][method];
|
|
1233
1469
|
const authArray = Utils.getAuthArray(operation.security, newSpec);
|
|
1234
1470
|
if (authArray && authArray.length > 0) {
|
|
1235
|
-
|
|
1236
|
-
if (
|
|
1237
|
-
|
|
1471
|
+
authSet.add(authArray[0][0]);
|
|
1472
|
+
if (authSet.size > 1) {
|
|
1473
|
+
hasMultipleAuth = true;
|
|
1238
1474
|
break;
|
|
1239
1475
|
}
|
|
1240
1476
|
}
|
|
1241
1477
|
}
|
|
1242
1478
|
}
|
|
1243
|
-
if (
|
|
1244
|
-
throw new SpecParserError(ConstantString.
|
|
1479
|
+
if (hasMultipleAuth && this.options.projectType !== ProjectType.TeamsAi) {
|
|
1480
|
+
throw new SpecParserError(ConstantString.MultipleAuthNotSupported, ErrorType.MultipleAuthNotSupported);
|
|
1245
1481
|
}
|
|
1246
1482
|
let resultStr;
|
|
1247
1483
|
if (outputSpecPath.endsWith(".yaml") || outputSpecPath.endsWith(".yml")) {
|
|
@@ -1251,26 +1487,28 @@ class SpecParser {
|
|
|
1251
1487
|
resultStr = JSON.stringify(newUnResolvedSpec, null, 2);
|
|
1252
1488
|
}
|
|
1253
1489
|
await fs.outputFile(outputSpecPath, resultStr);
|
|
1254
|
-
|
|
1255
|
-
for (const
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1490
|
+
if (adaptiveCardFolder) {
|
|
1491
|
+
for (const url in newSpec.paths) {
|
|
1492
|
+
for (const method in newSpec.paths[url]) {
|
|
1493
|
+
// paths object may contain description/summary which is not a http method, so we need to check if it is a operation object
|
|
1494
|
+
if (this.options.allowMethods.includes(method)) {
|
|
1495
|
+
const operation = newSpec.paths[url][method];
|
|
1496
|
+
try {
|
|
1497
|
+
const [card, jsonPath] = AdaptiveCardGenerator.generateAdaptiveCard(operation);
|
|
1498
|
+
const fileName = path.join(adaptiveCardFolder, `${operation.operationId}.json`);
|
|
1499
|
+
const wrappedCard = wrapAdaptiveCard(card, jsonPath);
|
|
1500
|
+
await fs.outputJSON(fileName, wrappedCard, { spaces: 2 });
|
|
1501
|
+
const dataFileName = path.join(adaptiveCardFolder, `${operation.operationId}.data.json`);
|
|
1502
|
+
await fs.outputJSON(dataFileName, {}, { spaces: 2 });
|
|
1503
|
+
}
|
|
1504
|
+
catch (err) {
|
|
1505
|
+
result.allSuccess = false;
|
|
1506
|
+
result.warnings.push({
|
|
1507
|
+
type: WarningType.GenerateCardFailed,
|
|
1508
|
+
content: err.toString(),
|
|
1509
|
+
data: operation.operationId,
|
|
1510
|
+
});
|
|
1511
|
+
}
|
|
1274
1512
|
}
|
|
1275
1513
|
}
|
|
1276
1514
|
}
|
|
@@ -1278,8 +1516,8 @@ class SpecParser {
|
|
|
1278
1516
|
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
|
|
1279
1517
|
throw new SpecParserError(ConstantString.CancelledMessage, ErrorType.Cancelled);
|
|
1280
1518
|
}
|
|
1281
|
-
const
|
|
1282
|
-
const [updatedManifest, warnings] = await ManifestUpdater.updateManifest(manifestPath, outputSpecPath,
|
|
1519
|
+
const authInfo = Array.from(authSet)[0];
|
|
1520
|
+
const [updatedManifest, warnings] = await ManifestUpdater.updateManifest(manifestPath, outputSpecPath, newSpec, this.options, adaptiveCardFolder, authInfo);
|
|
1283
1521
|
await fs.outputJSON(manifestPath, updatedManifest, { spaces: 2 });
|
|
1284
1522
|
result.warnings.push(...warnings);
|
|
1285
1523
|
}
|
|
@@ -1308,11 +1546,11 @@ class SpecParser {
|
|
|
1308
1546
|
if (this.apiMap !== undefined) {
|
|
1309
1547
|
return this.apiMap;
|
|
1310
1548
|
}
|
|
1311
|
-
const result = Utils.listSupportedAPIs(spec, this.options
|
|
1549
|
+
const result = Utils.listSupportedAPIs(spec, this.options);
|
|
1312
1550
|
this.apiMap = result;
|
|
1313
1551
|
return result;
|
|
1314
1552
|
}
|
|
1315
1553
|
}
|
|
1316
1554
|
|
|
1317
|
-
export { ConstantString, ErrorType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
|
|
1555
|
+
export { AdaptiveCardGenerator, ConstantString, ErrorType, ProjectType, SpecParser, SpecParserError, Utils, ValidationStatus, WarningType };
|
|
1318
1556
|
//# sourceMappingURL=index.esm2017.mjs.map
|