@microsoft/m365-spec-parser 0.1.1-alpha.54a90c74e.0 → 0.1.1-alpha.6341e718e.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 +456 -274
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +512 -298
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +456 -274
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +512 -298
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/interfaces.d.ts +30 -1
- package/dist/src/manifestUpdater.d.ts +2 -1
- package/dist/src/specParser.browser.d.ts +2 -1
- package/dist/src/specParser.d.ts +2 -1
- package/dist/src/utils.d.ts +8 -26
- package/package.json +3 -3
package/dist/index.esm2017.js
CHANGED
|
@@ -25,6 +25,21 @@ var ErrorType;
|
|
|
25
25
|
ErrorType["GenerateFailed"] = "generate-failed";
|
|
26
26
|
ErrorType["ValidateFailed"] = "validate-failed";
|
|
27
27
|
ErrorType["GetSpecFailed"] = "get-spec-failed";
|
|
28
|
+
ErrorType["AuthTypeIsNotSupported"] = "auth-type-is-not-supported";
|
|
29
|
+
ErrorType["MissingOperationId"] = "missing-operation-id";
|
|
30
|
+
ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
|
|
31
|
+
ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
|
|
32
|
+
ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
|
|
33
|
+
ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
|
|
34
|
+
ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
|
|
35
|
+
ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
|
|
36
|
+
ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
|
|
37
|
+
ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
|
|
38
|
+
ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
|
|
39
|
+
ErrorType["NoParameter"] = "no-parameter";
|
|
40
|
+
ErrorType["NoAPIInfo"] = "no-api-info";
|
|
41
|
+
ErrorType["MethodNotAllowed"] = "method-not-allowed";
|
|
42
|
+
ErrorType["UrlPathNotExist"] = "url-path-not-exist";
|
|
28
43
|
ErrorType["Cancelled"] = "cancelled";
|
|
29
44
|
ErrorType["Unknown"] = "unknown";
|
|
30
45
|
})(ErrorType || (ErrorType = {}));
|
|
@@ -170,221 +185,9 @@ class Utils {
|
|
|
170
185
|
}
|
|
171
186
|
return false;
|
|
172
187
|
}
|
|
173
|
-
static checkParameters(paramObject, isCopilot) {
|
|
174
|
-
const paramResult = {
|
|
175
|
-
requiredNum: 0,
|
|
176
|
-
optionalNum: 0,
|
|
177
|
-
isValid: true,
|
|
178
|
-
};
|
|
179
|
-
if (!paramObject) {
|
|
180
|
-
return paramResult;
|
|
181
|
-
}
|
|
182
|
-
for (let i = 0; i < paramObject.length; i++) {
|
|
183
|
-
const param = paramObject[i];
|
|
184
|
-
const schema = param.schema;
|
|
185
|
-
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
186
|
-
paramResult.isValid = false;
|
|
187
|
-
continue;
|
|
188
|
-
}
|
|
189
|
-
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
190
|
-
if (isCopilot) {
|
|
191
|
-
if (isRequiredWithoutDefault) {
|
|
192
|
-
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
196
|
-
}
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
if (param.in === "header" || param.in === "cookie") {
|
|
200
|
-
if (isRequiredWithoutDefault) {
|
|
201
|
-
paramResult.isValid = false;
|
|
202
|
-
}
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
if (schema.type !== "boolean" &&
|
|
206
|
-
schema.type !== "string" &&
|
|
207
|
-
schema.type !== "number" &&
|
|
208
|
-
schema.type !== "integer") {
|
|
209
|
-
if (isRequiredWithoutDefault) {
|
|
210
|
-
paramResult.isValid = false;
|
|
211
|
-
}
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
if (param.in === "query" || param.in === "path") {
|
|
215
|
-
if (isRequiredWithoutDefault) {
|
|
216
|
-
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
return paramResult;
|
|
224
|
-
}
|
|
225
|
-
static checkPostBody(schema, isRequired = false, isCopilot = false) {
|
|
226
|
-
var _a;
|
|
227
|
-
const paramResult = {
|
|
228
|
-
requiredNum: 0,
|
|
229
|
-
optionalNum: 0,
|
|
230
|
-
isValid: true,
|
|
231
|
-
};
|
|
232
|
-
if (Object.keys(schema).length === 0) {
|
|
233
|
-
return paramResult;
|
|
234
|
-
}
|
|
235
|
-
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
236
|
-
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
237
|
-
paramResult.isValid = false;
|
|
238
|
-
return paramResult;
|
|
239
|
-
}
|
|
240
|
-
if (schema.type === "string" ||
|
|
241
|
-
schema.type === "integer" ||
|
|
242
|
-
schema.type === "boolean" ||
|
|
243
|
-
schema.type === "number") {
|
|
244
|
-
if (isRequiredWithoutDefault) {
|
|
245
|
-
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
else if (schema.type === "object") {
|
|
252
|
-
const { properties } = schema;
|
|
253
|
-
for (const property in properties) {
|
|
254
|
-
let isRequired = false;
|
|
255
|
-
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
256
|
-
isRequired = true;
|
|
257
|
-
}
|
|
258
|
-
const result = Utils.checkPostBody(properties[property], isRequired, isCopilot);
|
|
259
|
-
paramResult.requiredNum += result.requiredNum;
|
|
260
|
-
paramResult.optionalNum += result.optionalNum;
|
|
261
|
-
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
if (isRequiredWithoutDefault && !isCopilot) {
|
|
266
|
-
paramResult.isValid = false;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
return paramResult;
|
|
270
|
-
}
|
|
271
188
|
static containMultipleMediaTypes(bodyObject) {
|
|
272
189
|
return Object.keys((bodyObject === null || bodyObject === void 0 ? void 0 : bodyObject.content) || {}).length > 1;
|
|
273
190
|
}
|
|
274
|
-
/**
|
|
275
|
-
* Checks if the given API is supported.
|
|
276
|
-
* @param {string} method - The HTTP method of the API.
|
|
277
|
-
* @param {string} path - The path of the API.
|
|
278
|
-
* @param {OpenAPIV3.Document} spec - The OpenAPI specification document.
|
|
279
|
-
* @returns {boolean} - Returns true if the API is supported, false otherwise.
|
|
280
|
-
* @description The following APIs are supported:
|
|
281
|
-
* 1. only support Get/Post operation without auth property
|
|
282
|
-
* 2. parameter inside query or path only support string, number, boolean and integer
|
|
283
|
-
* 3. parameter inside post body only support string, number, boolean, integer and object
|
|
284
|
-
* 4. request body + required parameters <= 1
|
|
285
|
-
* 5. response body should be “application/json” and not empty, and response code should be 20X
|
|
286
|
-
* 6. only support request body with “application/json” content type
|
|
287
|
-
*/
|
|
288
|
-
static isSupportedApi(method, path, spec, options) {
|
|
289
|
-
var _a;
|
|
290
|
-
const pathObj = spec.paths[path];
|
|
291
|
-
method = method.toLocaleLowerCase();
|
|
292
|
-
if (pathObj) {
|
|
293
|
-
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && pathObj[method]) {
|
|
294
|
-
const securities = pathObj[method].security;
|
|
295
|
-
const isTeamsAi = options.projectType === ProjectType.TeamsAi;
|
|
296
|
-
const isCopilot = options.projectType === ProjectType.Copilot;
|
|
297
|
-
// Teams AI project doesn't care about auth, it will use authProvider for user to implement
|
|
298
|
-
if (!isTeamsAi) {
|
|
299
|
-
const authArray = Utils.getAuthArray(securities, spec);
|
|
300
|
-
if (!Utils.isSupportedAuth(authArray, options)) {
|
|
301
|
-
return false;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
const operationObject = pathObj[method];
|
|
305
|
-
if (!options.allowMissingId && !operationObject.operationId) {
|
|
306
|
-
return false;
|
|
307
|
-
}
|
|
308
|
-
const paramObject = operationObject.parameters;
|
|
309
|
-
const requestBody = operationObject.requestBody;
|
|
310
|
-
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
311
|
-
if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
|
|
312
|
-
return false;
|
|
313
|
-
}
|
|
314
|
-
const responseJson = Utils.getResponseJson(operationObject, isTeamsAi);
|
|
315
|
-
if (Object.keys(responseJson).length === 0) {
|
|
316
|
-
return false;
|
|
317
|
-
}
|
|
318
|
-
// Teams AI project doesn't care about request parameters/body
|
|
319
|
-
if (isTeamsAi) {
|
|
320
|
-
return true;
|
|
321
|
-
}
|
|
322
|
-
let requestBodyParamResult = {
|
|
323
|
-
requiredNum: 0,
|
|
324
|
-
optionalNum: 0,
|
|
325
|
-
isValid: true,
|
|
326
|
-
};
|
|
327
|
-
if (requestJsonBody) {
|
|
328
|
-
const requestBodySchema = requestJsonBody.schema;
|
|
329
|
-
if (isCopilot && requestBodySchema.type !== "object") {
|
|
330
|
-
return false;
|
|
331
|
-
}
|
|
332
|
-
requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
|
|
333
|
-
}
|
|
334
|
-
if (!requestBodyParamResult.isValid) {
|
|
335
|
-
return false;
|
|
336
|
-
}
|
|
337
|
-
const paramResult = Utils.checkParameters(paramObject, isCopilot);
|
|
338
|
-
if (!paramResult.isValid) {
|
|
339
|
-
return false;
|
|
340
|
-
}
|
|
341
|
-
// Copilot support arbitrary parameters
|
|
342
|
-
if (isCopilot) {
|
|
343
|
-
return true;
|
|
344
|
-
}
|
|
345
|
-
if (requestBodyParamResult.requiredNum + paramResult.requiredNum > 1) {
|
|
346
|
-
if (options.allowMultipleParameters &&
|
|
347
|
-
requestBodyParamResult.requiredNum + paramResult.requiredNum <=
|
|
348
|
-
ConstantString.SMERequiredParamsMaxNum) {
|
|
349
|
-
return true;
|
|
350
|
-
}
|
|
351
|
-
return false;
|
|
352
|
-
}
|
|
353
|
-
else if (requestBodyParamResult.requiredNum +
|
|
354
|
-
requestBodyParamResult.optionalNum +
|
|
355
|
-
paramResult.requiredNum +
|
|
356
|
-
paramResult.optionalNum ===
|
|
357
|
-
0) {
|
|
358
|
-
return false;
|
|
359
|
-
}
|
|
360
|
-
else {
|
|
361
|
-
return true;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
return false;
|
|
366
|
-
}
|
|
367
|
-
static isSupportedAuth(authSchemeArray, options) {
|
|
368
|
-
if (authSchemeArray.length === 0) {
|
|
369
|
-
return true;
|
|
370
|
-
}
|
|
371
|
-
if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
|
|
372
|
-
// Currently we don't support multiple auth in one operation
|
|
373
|
-
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
374
|
-
return false;
|
|
375
|
-
}
|
|
376
|
-
for (const auths of authSchemeArray) {
|
|
377
|
-
if (auths.length === 1) {
|
|
378
|
-
if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
379
|
-
(options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
|
|
380
|
-
(options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
|
|
381
|
-
return true;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
return false;
|
|
387
|
-
}
|
|
388
191
|
static isBearerTokenAuth(authScheme) {
|
|
389
192
|
return authScheme.type === "http" && authScheme.scheme === "bearer";
|
|
390
193
|
}
|
|
@@ -392,10 +195,9 @@ class Utils {
|
|
|
392
195
|
return authScheme.type === "apiKey";
|
|
393
196
|
}
|
|
394
197
|
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
return false;
|
|
198
|
+
return !!(authScheme.type === "oauth2" &&
|
|
199
|
+
authScheme.flows &&
|
|
200
|
+
authScheme.flows.authorizationCode);
|
|
399
201
|
}
|
|
400
202
|
static getAuthArray(securities, spec) {
|
|
401
203
|
var _a;
|
|
@@ -423,14 +225,17 @@ class Utils {
|
|
|
423
225
|
static updateFirstLetter(str) {
|
|
424
226
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
425
227
|
}
|
|
426
|
-
static getResponseJson(operationObject
|
|
228
|
+
static getResponseJson(operationObject) {
|
|
427
229
|
var _a, _b;
|
|
428
230
|
let json = {};
|
|
231
|
+
let multipleMediaType = false;
|
|
429
232
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
430
233
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
431
234
|
if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
|
|
235
|
+
multipleMediaType = false;
|
|
432
236
|
json = responseObject.content["application/json"];
|
|
433
|
-
if (
|
|
237
|
+
if (Utils.containMultipleMediaTypes(responseObject)) {
|
|
238
|
+
multipleMediaType = true;
|
|
434
239
|
json = {};
|
|
435
240
|
}
|
|
436
241
|
else {
|
|
@@ -438,7 +243,7 @@ class Utils {
|
|
|
438
243
|
}
|
|
439
244
|
}
|
|
440
245
|
}
|
|
441
|
-
return json;
|
|
246
|
+
return { json, multipleMediaType };
|
|
442
247
|
}
|
|
443
248
|
static convertPathToCamelCase(path) {
|
|
444
249
|
const pathSegments = path.split(/[./{]/);
|
|
@@ -458,10 +263,10 @@ class Utils {
|
|
|
458
263
|
return undefined;
|
|
459
264
|
}
|
|
460
265
|
}
|
|
461
|
-
static
|
|
266
|
+
static resolveEnv(str) {
|
|
462
267
|
const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
|
|
463
|
-
let matches = placeHolderReg.exec(
|
|
464
|
-
let
|
|
268
|
+
let matches = placeHolderReg.exec(str);
|
|
269
|
+
let newStr = str;
|
|
465
270
|
while (matches != null) {
|
|
466
271
|
const envVar = matches[1];
|
|
467
272
|
const envVal = process.env[envVar];
|
|
@@ -469,17 +274,17 @@ class Utils {
|
|
|
469
274
|
throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
|
|
470
275
|
}
|
|
471
276
|
else {
|
|
472
|
-
|
|
277
|
+
newStr = newStr.replace(matches[0], envVal);
|
|
473
278
|
}
|
|
474
|
-
matches = placeHolderReg.exec(
|
|
279
|
+
matches = placeHolderReg.exec(str);
|
|
475
280
|
}
|
|
476
|
-
return
|
|
281
|
+
return newStr;
|
|
477
282
|
}
|
|
478
283
|
static checkServerUrl(servers) {
|
|
479
284
|
const errors = [];
|
|
480
285
|
let serverUrl;
|
|
481
286
|
try {
|
|
482
|
-
serverUrl = Utils.
|
|
287
|
+
serverUrl = Utils.resolveEnv(servers[0].url);
|
|
483
288
|
}
|
|
484
289
|
catch (err) {
|
|
485
290
|
errors.push({
|
|
@@ -510,6 +315,7 @@ class Utils {
|
|
|
510
315
|
return errors;
|
|
511
316
|
}
|
|
512
317
|
static validateServer(spec, options) {
|
|
318
|
+
var _a;
|
|
513
319
|
const errors = [];
|
|
514
320
|
let hasTopLevelServers = false;
|
|
515
321
|
let hasPathLevelServers = false;
|
|
@@ -530,7 +336,7 @@ class Utils {
|
|
|
530
336
|
}
|
|
531
337
|
for (const method in methods) {
|
|
532
338
|
const operationObject = methods[method];
|
|
533
|
-
if (
|
|
339
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
534
340
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
535
341
|
hasOperationLevelServers = true;
|
|
536
342
|
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
@@ -657,13 +463,7 @@ class Utils {
|
|
|
657
463
|
}
|
|
658
464
|
}
|
|
659
465
|
const operationId = operationItem.operationId;
|
|
660
|
-
const parameters = [];
|
|
661
|
-
if (requiredParams.length !== 0) {
|
|
662
|
-
parameters.push(...requiredParams);
|
|
663
|
-
}
|
|
664
|
-
else {
|
|
665
|
-
parameters.push(optionalParams[0]);
|
|
666
|
-
}
|
|
466
|
+
const parameters = [...requiredParams, ...optionalParams];
|
|
667
467
|
const command = {
|
|
668
468
|
context: ["compose"],
|
|
669
469
|
type: "query",
|
|
@@ -672,31 +472,9 @@ class Utils {
|
|
|
672
472
|
parameters: parameters,
|
|
673
473
|
description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
|
|
674
474
|
};
|
|
675
|
-
|
|
676
|
-
if (requiredParams.length === 0 && optionalParams.length > 1) {
|
|
677
|
-
warning = {
|
|
678
|
-
type: WarningType.OperationOnlyContainsOptionalParam,
|
|
679
|
-
content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, operationId),
|
|
680
|
-
data: operationId,
|
|
681
|
-
};
|
|
682
|
-
}
|
|
683
|
-
return [command, warning];
|
|
684
|
-
}
|
|
685
|
-
static listSupportedAPIs(spec, options) {
|
|
686
|
-
const paths = spec.paths;
|
|
687
|
-
const result = {};
|
|
688
|
-
for (const path in paths) {
|
|
689
|
-
const methods = paths[path];
|
|
690
|
-
for (const method in methods) {
|
|
691
|
-
if (Utils.isSupportedApi(method, path, spec, options)) {
|
|
692
|
-
const operationObject = methods[method];
|
|
693
|
-
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
return result;
|
|
475
|
+
return command;
|
|
698
476
|
}
|
|
699
|
-
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
477
|
+
static validateSpec(spec, parser, apiMap, isSwaggerFile, options) {
|
|
700
478
|
const errors = [];
|
|
701
479
|
const warnings = [];
|
|
702
480
|
if (isSwaggerFile) {
|
|
@@ -705,7 +483,6 @@ class Utils {
|
|
|
705
483
|
content: ConstantString.ConvertSwaggerToOpenAPI,
|
|
706
484
|
});
|
|
707
485
|
}
|
|
708
|
-
// Server validation
|
|
709
486
|
const serverErrors = Utils.validateServer(spec, options);
|
|
710
487
|
errors.push(...serverErrors);
|
|
711
488
|
// Remote reference not supported
|
|
@@ -719,8 +496,8 @@ class Utils {
|
|
|
719
496
|
});
|
|
720
497
|
}
|
|
721
498
|
// No supported API
|
|
722
|
-
const
|
|
723
|
-
if (
|
|
499
|
+
const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
|
|
500
|
+
if (validAPIs.length === 0) {
|
|
724
501
|
errors.push({
|
|
725
502
|
type: ErrorType.NoSupportedApi,
|
|
726
503
|
content: ConstantString.NoSupportedApi,
|
|
@@ -729,8 +506,8 @@ class Utils {
|
|
|
729
506
|
// OperationId missing
|
|
730
507
|
const apisMissingOperationId = [];
|
|
731
508
|
for (const key in apiMap) {
|
|
732
|
-
const
|
|
733
|
-
if (!
|
|
509
|
+
const { operation } = apiMap[key];
|
|
510
|
+
if (!operation.operationId) {
|
|
734
511
|
apisMissingOperationId.push(key);
|
|
735
512
|
}
|
|
736
513
|
}
|
|
@@ -786,6 +563,389 @@ class Utils {
|
|
|
786
563
|
}
|
|
787
564
|
}
|
|
788
565
|
|
|
566
|
+
// Copyright (c) Microsoft Corporation.
|
|
567
|
+
class Validator {
|
|
568
|
+
validateMethodAndPath(method, path) {
|
|
569
|
+
const result = { isValid: true, reason: [] };
|
|
570
|
+
if (this.options.allowMethods && !this.options.allowMethods.includes(method)) {
|
|
571
|
+
result.isValid = false;
|
|
572
|
+
result.reason.push(ErrorType.MethodNotAllowed);
|
|
573
|
+
return result;
|
|
574
|
+
}
|
|
575
|
+
const pathObj = this.spec.paths[path];
|
|
576
|
+
if (!pathObj || !pathObj[method]) {
|
|
577
|
+
result.isValid = false;
|
|
578
|
+
result.reason.push(ErrorType.UrlPathNotExist);
|
|
579
|
+
return result;
|
|
580
|
+
}
|
|
581
|
+
return result;
|
|
582
|
+
}
|
|
583
|
+
validateResponse(method, path) {
|
|
584
|
+
const result = { isValid: true, reason: [] };
|
|
585
|
+
const operationObject = this.spec.paths[path][method];
|
|
586
|
+
const { json, multipleMediaType } = Utils.getResponseJson(operationObject);
|
|
587
|
+
// only support response body only contains “application/json” content type
|
|
588
|
+
if (multipleMediaType) {
|
|
589
|
+
result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
|
|
590
|
+
}
|
|
591
|
+
else if (Object.keys(json).length === 0) {
|
|
592
|
+
// response body should not be empty
|
|
593
|
+
result.reason.push(ErrorType.ResponseJsonIsEmpty);
|
|
594
|
+
}
|
|
595
|
+
return result;
|
|
596
|
+
}
|
|
597
|
+
validateServer(method, path) {
|
|
598
|
+
const pathObj = this.spec.paths[path];
|
|
599
|
+
const result = { isValid: true, reason: [] };
|
|
600
|
+
const operationObject = pathObj[method];
|
|
601
|
+
const rootServer = this.spec.servers && this.spec.servers[0];
|
|
602
|
+
const methodServer = this.spec.paths[path].servers && this.spec.paths[path].servers[0];
|
|
603
|
+
const operationServer = operationObject.servers && operationObject.servers[0];
|
|
604
|
+
const serverUrl = operationServer || methodServer || rootServer;
|
|
605
|
+
if (!serverUrl) {
|
|
606
|
+
// should contain server URL
|
|
607
|
+
result.reason.push(ErrorType.NoServerInformation);
|
|
608
|
+
}
|
|
609
|
+
else {
|
|
610
|
+
// server url should be absolute url with https protocol
|
|
611
|
+
const serverValidateResult = Utils.checkServerUrl([serverUrl]);
|
|
612
|
+
result.reason.push(...serverValidateResult.map((item) => item.type));
|
|
613
|
+
}
|
|
614
|
+
return result;
|
|
615
|
+
}
|
|
616
|
+
validateAuth(method, path) {
|
|
617
|
+
const pathObj = this.spec.paths[path];
|
|
618
|
+
const operationObject = pathObj[method];
|
|
619
|
+
const securities = operationObject.security;
|
|
620
|
+
const authSchemeArray = Utils.getAuthArray(securities, this.spec);
|
|
621
|
+
if (authSchemeArray.length === 0) {
|
|
622
|
+
return { isValid: true, reason: [] };
|
|
623
|
+
}
|
|
624
|
+
if (this.options.allowAPIKeyAuth ||
|
|
625
|
+
this.options.allowOauth2 ||
|
|
626
|
+
this.options.allowBearerTokenAuth) {
|
|
627
|
+
// Currently we don't support multiple auth in one operation
|
|
628
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
629
|
+
return {
|
|
630
|
+
isValid: false,
|
|
631
|
+
reason: [ErrorType.MultipleAuthNotSupported],
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
for (const auths of authSchemeArray) {
|
|
635
|
+
if (auths.length === 1) {
|
|
636
|
+
if ((this.options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
637
|
+
(this.options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
|
|
638
|
+
(this.options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
|
|
639
|
+
return { isValid: true, reason: [] };
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
|
|
645
|
+
}
|
|
646
|
+
checkPostBodySchema(schema, isRequired = false) {
|
|
647
|
+
var _a;
|
|
648
|
+
const paramResult = {
|
|
649
|
+
requiredNum: 0,
|
|
650
|
+
optionalNum: 0,
|
|
651
|
+
isValid: true,
|
|
652
|
+
reason: [],
|
|
653
|
+
};
|
|
654
|
+
if (Object.keys(schema).length === 0) {
|
|
655
|
+
return paramResult;
|
|
656
|
+
}
|
|
657
|
+
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
658
|
+
const isCopilot = this.projectType === ProjectType.Copilot;
|
|
659
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
660
|
+
paramResult.isValid = false;
|
|
661
|
+
paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
|
|
662
|
+
return paramResult;
|
|
663
|
+
}
|
|
664
|
+
if (schema.type === "string" ||
|
|
665
|
+
schema.type === "integer" ||
|
|
666
|
+
schema.type === "boolean" ||
|
|
667
|
+
schema.type === "number") {
|
|
668
|
+
if (isRequiredWithoutDefault) {
|
|
669
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
else if (schema.type === "object") {
|
|
676
|
+
const { properties } = schema;
|
|
677
|
+
for (const property in properties) {
|
|
678
|
+
let isRequired = false;
|
|
679
|
+
if (schema.required && ((_a = schema.required) === null || _a === void 0 ? void 0 : _a.indexOf(property)) >= 0) {
|
|
680
|
+
isRequired = true;
|
|
681
|
+
}
|
|
682
|
+
const result = this.checkPostBodySchema(properties[property], isRequired);
|
|
683
|
+
paramResult.requiredNum += result.requiredNum;
|
|
684
|
+
paramResult.optionalNum += result.optionalNum;
|
|
685
|
+
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
686
|
+
paramResult.reason.push(...result.reason);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
else {
|
|
690
|
+
if (isRequiredWithoutDefault && !isCopilot) {
|
|
691
|
+
paramResult.isValid = false;
|
|
692
|
+
paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
return paramResult;
|
|
696
|
+
}
|
|
697
|
+
checkParamSchema(paramObject) {
|
|
698
|
+
const paramResult = {
|
|
699
|
+
requiredNum: 0,
|
|
700
|
+
optionalNum: 0,
|
|
701
|
+
isValid: true,
|
|
702
|
+
reason: [],
|
|
703
|
+
};
|
|
704
|
+
if (!paramObject) {
|
|
705
|
+
return paramResult;
|
|
706
|
+
}
|
|
707
|
+
const isCopilot = this.projectType === ProjectType.Copilot;
|
|
708
|
+
for (let i = 0; i < paramObject.length; i++) {
|
|
709
|
+
const param = paramObject[i];
|
|
710
|
+
const schema = param.schema;
|
|
711
|
+
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
712
|
+
paramResult.isValid = false;
|
|
713
|
+
paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
|
|
714
|
+
continue;
|
|
715
|
+
}
|
|
716
|
+
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
717
|
+
if (isCopilot) {
|
|
718
|
+
if (isRequiredWithoutDefault) {
|
|
719
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
720
|
+
}
|
|
721
|
+
else {
|
|
722
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
723
|
+
}
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
726
|
+
if (param.in === "header" || param.in === "cookie") {
|
|
727
|
+
if (isRequiredWithoutDefault) {
|
|
728
|
+
paramResult.isValid = false;
|
|
729
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
730
|
+
}
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
if (schema.type !== "boolean" &&
|
|
734
|
+
schema.type !== "string" &&
|
|
735
|
+
schema.type !== "number" &&
|
|
736
|
+
schema.type !== "integer") {
|
|
737
|
+
if (isRequiredWithoutDefault) {
|
|
738
|
+
paramResult.isValid = false;
|
|
739
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
740
|
+
}
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
if (param.in === "query" || param.in === "path") {
|
|
744
|
+
if (isRequiredWithoutDefault) {
|
|
745
|
+
paramResult.requiredNum = paramResult.requiredNum + 1;
|
|
746
|
+
}
|
|
747
|
+
else {
|
|
748
|
+
paramResult.optionalNum = paramResult.optionalNum + 1;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
return paramResult;
|
|
753
|
+
}
|
|
754
|
+
hasNestedObjectInSchema(schema) {
|
|
755
|
+
if (schema.type === "object") {
|
|
756
|
+
for (const property in schema.properties) {
|
|
757
|
+
const nestedSchema = schema.properties[property];
|
|
758
|
+
if (nestedSchema.type === "object") {
|
|
759
|
+
return true;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
return false;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// Copyright (c) Microsoft Corporation.
|
|
768
|
+
class CopilotValidator extends Validator {
|
|
769
|
+
constructor(spec, options) {
|
|
770
|
+
super();
|
|
771
|
+
this.projectType = ProjectType.Copilot;
|
|
772
|
+
this.options = options;
|
|
773
|
+
this.spec = spec;
|
|
774
|
+
}
|
|
775
|
+
validateAPI(method, path) {
|
|
776
|
+
const result = { isValid: true, reason: [] };
|
|
777
|
+
method = method.toLocaleLowerCase();
|
|
778
|
+
// validate method and path
|
|
779
|
+
const methodAndPathResult = this.validateMethodAndPath(method, path);
|
|
780
|
+
if (!methodAndPathResult.isValid) {
|
|
781
|
+
return methodAndPathResult;
|
|
782
|
+
}
|
|
783
|
+
const operationObject = this.spec.paths[path][method];
|
|
784
|
+
// validate auth
|
|
785
|
+
const authCheckResult = this.validateAuth(method, path);
|
|
786
|
+
result.reason.push(...authCheckResult.reason);
|
|
787
|
+
// validate operationId
|
|
788
|
+
if (!this.options.allowMissingId && !operationObject.operationId) {
|
|
789
|
+
result.reason.push(ErrorType.MissingOperationId);
|
|
790
|
+
}
|
|
791
|
+
// validate server
|
|
792
|
+
const validateServerResult = this.validateServer(method, path);
|
|
793
|
+
result.reason.push(...validateServerResult.reason);
|
|
794
|
+
// validate response
|
|
795
|
+
const validateResponseResult = this.validateResponse(method, path);
|
|
796
|
+
result.reason.push(...validateResponseResult.reason);
|
|
797
|
+
// validate requestBody
|
|
798
|
+
const requestBody = operationObject.requestBody;
|
|
799
|
+
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
800
|
+
if (Utils.containMultipleMediaTypes(requestBody)) {
|
|
801
|
+
result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
|
|
802
|
+
}
|
|
803
|
+
if (requestJsonBody) {
|
|
804
|
+
const requestBodySchema = requestJsonBody.schema;
|
|
805
|
+
if (requestBodySchema.type !== "object") {
|
|
806
|
+
result.reason.push(ErrorType.PostBodySchemaIsNotJson);
|
|
807
|
+
}
|
|
808
|
+
const requestBodyParamResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
|
|
809
|
+
result.reason.push(...requestBodyParamResult.reason);
|
|
810
|
+
}
|
|
811
|
+
// validate parameters
|
|
812
|
+
const paramObject = operationObject.parameters;
|
|
813
|
+
const paramResult = this.checkParamSchema(paramObject);
|
|
814
|
+
result.reason.push(...paramResult.reason);
|
|
815
|
+
if (result.reason.length > 0) {
|
|
816
|
+
result.isValid = false;
|
|
817
|
+
}
|
|
818
|
+
return result;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Copyright (c) Microsoft Corporation.
|
|
823
|
+
class SMEValidator extends Validator {
|
|
824
|
+
constructor(spec, options) {
|
|
825
|
+
super();
|
|
826
|
+
this.projectType = ProjectType.SME;
|
|
827
|
+
this.options = options;
|
|
828
|
+
this.spec = spec;
|
|
829
|
+
}
|
|
830
|
+
validateAPI(method, path) {
|
|
831
|
+
const result = { isValid: true, reason: [] };
|
|
832
|
+
method = method.toLocaleLowerCase();
|
|
833
|
+
// validate method and path
|
|
834
|
+
const methodAndPathResult = this.validateMethodAndPath(method, path);
|
|
835
|
+
if (!methodAndPathResult.isValid) {
|
|
836
|
+
return methodAndPathResult;
|
|
837
|
+
}
|
|
838
|
+
const operationObject = this.spec.paths[path][method];
|
|
839
|
+
// validate auth
|
|
840
|
+
const authCheckResult = this.validateAuth(method, path);
|
|
841
|
+
result.reason.push(...authCheckResult.reason);
|
|
842
|
+
// validate operationId
|
|
843
|
+
if (!this.options.allowMissingId && !operationObject.operationId) {
|
|
844
|
+
result.reason.push(ErrorType.MissingOperationId);
|
|
845
|
+
}
|
|
846
|
+
// validate server
|
|
847
|
+
const validateServerResult = this.validateServer(method, path);
|
|
848
|
+
result.reason.push(...validateServerResult.reason);
|
|
849
|
+
// validate response
|
|
850
|
+
const validateResponseResult = this.validateResponse(method, path);
|
|
851
|
+
result.reason.push(...validateResponseResult.reason);
|
|
852
|
+
let postBodyResult = {
|
|
853
|
+
requiredNum: 0,
|
|
854
|
+
optionalNum: 0,
|
|
855
|
+
isValid: true,
|
|
856
|
+
reason: [],
|
|
857
|
+
};
|
|
858
|
+
// validate requestBody
|
|
859
|
+
const requestBody = operationObject.requestBody;
|
|
860
|
+
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
861
|
+
if (Utils.containMultipleMediaTypes(requestBody)) {
|
|
862
|
+
result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
|
|
863
|
+
}
|
|
864
|
+
if (requestJsonBody) {
|
|
865
|
+
const requestBodySchema = requestJsonBody.schema;
|
|
866
|
+
postBodyResult = this.checkPostBodySchema(requestBodySchema, requestBody.required);
|
|
867
|
+
result.reason.push(...postBodyResult.reason);
|
|
868
|
+
}
|
|
869
|
+
// validate parameters
|
|
870
|
+
const paramObject = operationObject.parameters;
|
|
871
|
+
const paramResult = this.checkParamSchema(paramObject);
|
|
872
|
+
result.reason.push(...paramResult.reason);
|
|
873
|
+
// validate total parameters count
|
|
874
|
+
if (paramResult.isValid && postBodyResult.isValid) {
|
|
875
|
+
const paramCountResult = this.validateParamCount(postBodyResult, paramResult);
|
|
876
|
+
result.reason.push(...paramCountResult.reason);
|
|
877
|
+
}
|
|
878
|
+
if (result.reason.length > 0) {
|
|
879
|
+
result.isValid = false;
|
|
880
|
+
}
|
|
881
|
+
return result;
|
|
882
|
+
}
|
|
883
|
+
validateParamCount(postBodyResult, paramResult) {
|
|
884
|
+
const result = { isValid: true, reason: [] };
|
|
885
|
+
const totalRequiredParams = postBodyResult.requiredNum + paramResult.requiredNum;
|
|
886
|
+
const totalParams = totalRequiredParams + postBodyResult.optionalNum + paramResult.optionalNum;
|
|
887
|
+
if (totalRequiredParams > 1) {
|
|
888
|
+
if (!this.options.allowMultipleParameters ||
|
|
889
|
+
totalRequiredParams > SMEValidator.SMERequiredParamsMaxNum) {
|
|
890
|
+
result.reason.push(ErrorType.ExceededRequiredParamsLimit);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
else if (totalParams === 0) {
|
|
894
|
+
result.reason.push(ErrorType.NoParameter);
|
|
895
|
+
}
|
|
896
|
+
return result;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
SMEValidator.SMERequiredParamsMaxNum = 5;
|
|
900
|
+
|
|
901
|
+
// Copyright (c) Microsoft Corporation.
|
|
902
|
+
class TeamsAIValidator extends Validator {
|
|
903
|
+
constructor(spec, options) {
|
|
904
|
+
super();
|
|
905
|
+
this.projectType = ProjectType.TeamsAi;
|
|
906
|
+
this.options = options;
|
|
907
|
+
this.spec = spec;
|
|
908
|
+
}
|
|
909
|
+
validateAPI(method, path) {
|
|
910
|
+
const result = { isValid: true, reason: [] };
|
|
911
|
+
method = method.toLocaleLowerCase();
|
|
912
|
+
// validate method and path
|
|
913
|
+
const methodAndPathResult = this.validateMethodAndPath(method, path);
|
|
914
|
+
if (!methodAndPathResult.isValid) {
|
|
915
|
+
return methodAndPathResult;
|
|
916
|
+
}
|
|
917
|
+
const operationObject = this.spec.paths[path][method];
|
|
918
|
+
// validate operationId
|
|
919
|
+
if (!this.options.allowMissingId && !operationObject.operationId) {
|
|
920
|
+
result.reason.push(ErrorType.MissingOperationId);
|
|
921
|
+
}
|
|
922
|
+
// validate server
|
|
923
|
+
const validateServerResult = this.validateServer(method, path);
|
|
924
|
+
result.reason.push(...validateServerResult.reason);
|
|
925
|
+
if (result.reason.length > 0) {
|
|
926
|
+
result.isValid = false;
|
|
927
|
+
}
|
|
928
|
+
return result;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
class ValidatorFactory {
|
|
933
|
+
static create(spec, options) {
|
|
934
|
+
var _a;
|
|
935
|
+
const type = (_a = options.projectType) !== null && _a !== void 0 ? _a : ProjectType.SME;
|
|
936
|
+
switch (type) {
|
|
937
|
+
case ProjectType.SME:
|
|
938
|
+
return new SMEValidator(spec, options);
|
|
939
|
+
case ProjectType.Copilot:
|
|
940
|
+
return new CopilotValidator(spec, options);
|
|
941
|
+
case ProjectType.TeamsAi:
|
|
942
|
+
return new TeamsAIValidator(spec, options);
|
|
943
|
+
default:
|
|
944
|
+
throw new Error(`Invalid project type: ${type}`);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
|
|
789
949
|
// Copyright (c) Microsoft Corporation.
|
|
790
950
|
/**
|
|
791
951
|
* A class that parses an OpenAPI specification file and provides methods to validate, list, and generate artifacts.
|
|
@@ -842,7 +1002,8 @@ class SpecParser {
|
|
|
842
1002
|
],
|
|
843
1003
|
};
|
|
844
1004
|
}
|
|
845
|
-
|
|
1005
|
+
const apiMap = this.getAPIs(this.spec);
|
|
1006
|
+
return Utils.validateSpec(this.spec, this.parser, apiMap, !!this.isSwaggerFile, this.options);
|
|
846
1007
|
}
|
|
847
1008
|
catch (err) {
|
|
848
1009
|
throw new SpecParserError(err.toString(), ErrorType.ValidateFailed);
|
|
@@ -851,17 +1012,20 @@ class SpecParser {
|
|
|
851
1012
|
async listSupportedAPIInfo() {
|
|
852
1013
|
try {
|
|
853
1014
|
await this.loadSpec();
|
|
854
|
-
const apiMap = this.
|
|
1015
|
+
const apiMap = this.getAPIs(this.spec);
|
|
855
1016
|
const apiInfos = [];
|
|
856
1017
|
for (const key in apiMap) {
|
|
857
|
-
const
|
|
1018
|
+
const { operation, isValid } = apiMap[key];
|
|
1019
|
+
if (!isValid) {
|
|
1020
|
+
continue;
|
|
1021
|
+
}
|
|
858
1022
|
const [method, path] = key.split(" ");
|
|
859
|
-
const operationId =
|
|
1023
|
+
const operationId = operation.operationId;
|
|
860
1024
|
// In Browser environment, this api is by default not support api without operationId
|
|
861
1025
|
if (!operationId) {
|
|
862
1026
|
continue;
|
|
863
1027
|
}
|
|
864
|
-
const
|
|
1028
|
+
const command = Utils.parseApiInfo(operation, this.options);
|
|
865
1029
|
const apiInfo = {
|
|
866
1030
|
method: method,
|
|
867
1031
|
path: path,
|
|
@@ -870,9 +1034,6 @@ class SpecParser {
|
|
|
870
1034
|
parameters: command.parameters,
|
|
871
1035
|
description: command.description,
|
|
872
1036
|
};
|
|
873
|
-
if (warning) {
|
|
874
|
-
apiInfo.warning = warning;
|
|
875
|
-
}
|
|
876
1037
|
apiInfos.push(apiInfo);
|
|
877
1038
|
}
|
|
878
1039
|
return apiInfos;
|
|
@@ -931,21 +1092,42 @@ class SpecParser {
|
|
|
931
1092
|
this.spec = (await this.parser.dereference(clonedUnResolveSpec));
|
|
932
1093
|
}
|
|
933
1094
|
}
|
|
934
|
-
|
|
1095
|
+
getAPIs(spec) {
|
|
935
1096
|
if (this.apiMap !== undefined) {
|
|
936
1097
|
return this.apiMap;
|
|
937
1098
|
}
|
|
938
|
-
const result =
|
|
1099
|
+
const result = this.listAPIs(spec);
|
|
939
1100
|
this.apiMap = result;
|
|
940
1101
|
return result;
|
|
941
1102
|
}
|
|
1103
|
+
listAPIs(spec) {
|
|
1104
|
+
var _a;
|
|
1105
|
+
const paths = spec.paths;
|
|
1106
|
+
const result = {};
|
|
1107
|
+
for (const path in paths) {
|
|
1108
|
+
const methods = paths[path];
|
|
1109
|
+
for (const method in methods) {
|
|
1110
|
+
const operationObject = methods[method];
|
|
1111
|
+
if (((_a = this.options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
1112
|
+
const validator = ValidatorFactory.create(spec, this.options);
|
|
1113
|
+
const validateResult = validator.validateAPI(method, path);
|
|
1114
|
+
result[`${method.toUpperCase()} ${path}`] = {
|
|
1115
|
+
operation: operationObject,
|
|
1116
|
+
isValid: validateResult.isValid,
|
|
1117
|
+
reason: validateResult.reason,
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
return result;
|
|
1123
|
+
}
|
|
942
1124
|
}
|
|
943
1125
|
|
|
944
1126
|
// Copyright (c) Microsoft Corporation.
|
|
945
1127
|
class AdaptiveCardGenerator {
|
|
946
1128
|
static generateAdaptiveCard(operationItem) {
|
|
947
1129
|
try {
|
|
948
|
-
const json = Utils.getResponseJson(operationItem);
|
|
1130
|
+
const { json } = Utils.getResponseJson(operationItem);
|
|
949
1131
|
let cardBody = [];
|
|
950
1132
|
let schema = json.schema;
|
|
951
1133
|
let jsonPath = "$";
|