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