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