@microsoft/m365-spec-parser 0.1.1-alpha.a372ccf67.0 → 0.1.1-alpha.b015b287e.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 +204 -137
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +271 -167
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +204 -137
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +271 -167
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/interfaces.d.ts +44 -16
- package/dist/src/manifestUpdater.d.ts +2 -1
- package/dist/src/specParser.browser.d.ts +1 -0
- package/dist/src/specParser.d.ts +2 -2
- package/dist/src/utils.d.ts +17 -14
- package/package.json +3 -3
package/dist/index.esm5.js
CHANGED
|
@@ -46,6 +46,7 @@ var ErrorType;
|
|
|
46
46
|
ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
|
|
47
47
|
ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
|
|
48
48
|
ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
|
|
49
|
+
ErrorType["SpecVersionNotSupported"] = "spec-version-not-supported";
|
|
49
50
|
ErrorType["ListFailed"] = "list-failed";
|
|
50
51
|
ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
|
|
51
52
|
ErrorType["FilterSpecFailed"] = "filter-spec-failed";
|
|
@@ -54,6 +55,21 @@ var ErrorType;
|
|
|
54
55
|
ErrorType["GenerateFailed"] = "generate-failed";
|
|
55
56
|
ErrorType["ValidateFailed"] = "validate-failed";
|
|
56
57
|
ErrorType["GetSpecFailed"] = "get-spec-failed";
|
|
58
|
+
ErrorType["AuthTypeIsNotSupported"] = "auth-type-is-not-supported";
|
|
59
|
+
ErrorType["MissingOperationId"] = "missing-operation-id";
|
|
60
|
+
ErrorType["PostBodyContainMultipleMediaTypes"] = "post-body-contain-multiple-media-types";
|
|
61
|
+
ErrorType["ResponseContainMultipleMediaTypes"] = "response-contain-multiple-media-types";
|
|
62
|
+
ErrorType["ResponseJsonIsEmpty"] = "response-json-is-empty";
|
|
63
|
+
ErrorType["PostBodySchemaIsNotJson"] = "post-body-schema-is-not-json";
|
|
64
|
+
ErrorType["PostBodyContainsRequiredUnsupportedSchema"] = "post-body-contains-required-unsupported-schema";
|
|
65
|
+
ErrorType["ParamsContainRequiredUnsupportedSchema"] = "params-contain-required-unsupported-schema";
|
|
66
|
+
ErrorType["ParamsContainsNestedObject"] = "params-contains-nested-object";
|
|
67
|
+
ErrorType["RequestBodyContainsNestedObject"] = "request-body-contains-nested-object";
|
|
68
|
+
ErrorType["ExceededRequiredParamsLimit"] = "exceeded-required-params-limit";
|
|
69
|
+
ErrorType["NoParameter"] = "no-parameter";
|
|
70
|
+
ErrorType["NoAPIInfo"] = "no-api-info";
|
|
71
|
+
ErrorType["MethodNotAllowed"] = "method-not-allowed";
|
|
72
|
+
ErrorType["UrlPathNotExist"] = "url-path-not-exist";
|
|
57
73
|
ErrorType["Cancelled"] = "cancelled";
|
|
58
74
|
ErrorType["Unknown"] = "unknown";
|
|
59
75
|
})(ErrorType || (ErrorType = {}));
|
|
@@ -109,6 +125,7 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
|
|
|
109
125
|
ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
|
|
110
126
|
ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
|
|
111
127
|
ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
|
|
128
|
+
ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
|
|
112
129
|
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
113
130
|
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
114
131
|
ConstantString.WrappedCardVersion = "devPreview";
|
|
@@ -203,6 +220,7 @@ class Utils {
|
|
|
203
220
|
requiredNum: 0,
|
|
204
221
|
optionalNum: 0,
|
|
205
222
|
isValid: true,
|
|
223
|
+
reason: [],
|
|
206
224
|
};
|
|
207
225
|
if (!paramObject) {
|
|
208
226
|
return paramResult;
|
|
@@ -212,6 +230,7 @@ class Utils {
|
|
|
212
230
|
const schema = param.schema;
|
|
213
231
|
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
214
232
|
paramResult.isValid = false;
|
|
233
|
+
paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
|
|
215
234
|
continue;
|
|
216
235
|
}
|
|
217
236
|
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
@@ -227,6 +246,7 @@ class Utils {
|
|
|
227
246
|
if (param.in === "header" || param.in === "cookie") {
|
|
228
247
|
if (isRequiredWithoutDefault) {
|
|
229
248
|
paramResult.isValid = false;
|
|
249
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
230
250
|
}
|
|
231
251
|
continue;
|
|
232
252
|
}
|
|
@@ -236,6 +256,7 @@ class Utils {
|
|
|
236
256
|
schema.type !== "integer") {
|
|
237
257
|
if (isRequiredWithoutDefault) {
|
|
238
258
|
paramResult.isValid = false;
|
|
259
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
239
260
|
}
|
|
240
261
|
continue;
|
|
241
262
|
}
|
|
@@ -256,6 +277,7 @@ class Utils {
|
|
|
256
277
|
requiredNum: 0,
|
|
257
278
|
optionalNum: 0,
|
|
258
279
|
isValid: true,
|
|
280
|
+
reason: [],
|
|
259
281
|
};
|
|
260
282
|
if (Object.keys(schema).length === 0) {
|
|
261
283
|
return paramResult;
|
|
@@ -263,6 +285,7 @@ class Utils {
|
|
|
263
285
|
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
264
286
|
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
265
287
|
paramResult.isValid = false;
|
|
288
|
+
paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
|
|
266
289
|
return paramResult;
|
|
267
290
|
}
|
|
268
291
|
if (schema.type === "string" ||
|
|
@@ -287,11 +310,13 @@ class Utils {
|
|
|
287
310
|
paramResult.requiredNum += result.requiredNum;
|
|
288
311
|
paramResult.optionalNum += result.optionalNum;
|
|
289
312
|
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
313
|
+
paramResult.reason.push(...result.reason);
|
|
290
314
|
}
|
|
291
315
|
}
|
|
292
316
|
else {
|
|
293
317
|
if (isRequiredWithoutDefault && !isCopilot) {
|
|
294
318
|
paramResult.isValid = false;
|
|
319
|
+
paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
|
|
295
320
|
}
|
|
296
321
|
}
|
|
297
322
|
return paramResult;
|
|
@@ -315,120 +340,132 @@ class Utils {
|
|
|
315
340
|
*/
|
|
316
341
|
static isSupportedApi(method, path, spec, options) {
|
|
317
342
|
var _a;
|
|
318
|
-
const
|
|
343
|
+
const result = { isValid: true, reason: [] };
|
|
319
344
|
method = method.toLocaleLowerCase();
|
|
320
|
-
if (
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
345
|
+
if (options.allowMethods && !options.allowMethods.includes(method)) {
|
|
346
|
+
result.isValid = false;
|
|
347
|
+
result.reason.push(ErrorType.MethodNotAllowed);
|
|
348
|
+
return result;
|
|
349
|
+
}
|
|
350
|
+
const pathObj = spec.paths[path];
|
|
351
|
+
if (!pathObj || !pathObj[method]) {
|
|
352
|
+
result.isValid = false;
|
|
353
|
+
result.reason.push(ErrorType.UrlPathNotExist);
|
|
354
|
+
return result;
|
|
355
|
+
}
|
|
356
|
+
const securities = pathObj[method].security;
|
|
357
|
+
const isTeamsAi = options.projectType === ProjectType.TeamsAi;
|
|
358
|
+
const isCopilot = options.projectType === ProjectType.Copilot;
|
|
359
|
+
// Teams AI project doesn't care about auth, it will use authProvider for user to implement
|
|
360
|
+
if (!isTeamsAi) {
|
|
361
|
+
const authArray = Utils.getAuthArray(securities, spec);
|
|
362
|
+
const authCheckResult = Utils.isSupportedAuth(authArray, options);
|
|
363
|
+
if (!authCheckResult.isValid) {
|
|
364
|
+
result.reason.push(...authCheckResult.reason);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const operationObject = pathObj[method];
|
|
368
|
+
if (!options.allowMissingId && !operationObject.operationId) {
|
|
369
|
+
result.reason.push(ErrorType.MissingOperationId);
|
|
370
|
+
}
|
|
371
|
+
const rootServer = spec.servers && spec.servers[0];
|
|
372
|
+
const methodServer = spec.paths[path].servers && ((_a = spec.paths[path]) === null || _a === void 0 ? void 0 : _a.servers[0]);
|
|
373
|
+
const operationServer = operationObject.servers && operationObject.servers[0];
|
|
374
|
+
const serverUrl = operationServer || methodServer || rootServer;
|
|
375
|
+
if (!serverUrl) {
|
|
376
|
+
result.reason.push(ErrorType.NoServerInformation);
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
const serverValidateResult = Utils.checkServerUrl([serverUrl]);
|
|
380
|
+
result.reason.push(...serverValidateResult.map((item) => item.type));
|
|
381
|
+
}
|
|
382
|
+
const paramObject = operationObject.parameters;
|
|
383
|
+
const requestBody = operationObject.requestBody;
|
|
384
|
+
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
385
|
+
if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
|
|
386
|
+
result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
|
|
387
|
+
}
|
|
388
|
+
const { json, multipleMediaType } = Utils.getResponseJson(operationObject, isTeamsAi);
|
|
389
|
+
if (multipleMediaType && !isTeamsAi) {
|
|
390
|
+
result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
|
|
391
|
+
}
|
|
392
|
+
else if (Object.keys(json).length === 0) {
|
|
393
|
+
result.reason.push(ErrorType.ResponseJsonIsEmpty);
|
|
394
|
+
}
|
|
395
|
+
// Teams AI project doesn't care about request parameters/body
|
|
396
|
+
if (!isTeamsAi) {
|
|
397
|
+
let requestBodyParamResult = {
|
|
398
|
+
requiredNum: 0,
|
|
399
|
+
optionalNum: 0,
|
|
400
|
+
isValid: true,
|
|
401
|
+
reason: [],
|
|
402
|
+
};
|
|
403
|
+
if (requestJsonBody) {
|
|
404
|
+
const requestBodySchema = requestJsonBody.schema;
|
|
405
|
+
if (isCopilot && requestBodySchema.type !== "object") {
|
|
406
|
+
result.reason.push(ErrorType.PostBodySchemaIsNotJson);
|
|
368
407
|
}
|
|
369
|
-
|
|
370
|
-
if (
|
|
371
|
-
|
|
408
|
+
requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
|
|
409
|
+
if (!requestBodyParamResult.isValid && requestBodyParamResult.reason) {
|
|
410
|
+
result.reason.push(...requestBodyParamResult.reason);
|
|
372
411
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
412
|
+
}
|
|
413
|
+
const paramResult = Utils.checkParameters(paramObject, isCopilot);
|
|
414
|
+
if (!paramResult.isValid && paramResult.reason) {
|
|
415
|
+
result.reason.push(...paramResult.reason);
|
|
416
|
+
}
|
|
417
|
+
// Copilot support arbitrary parameters
|
|
418
|
+
if (!isCopilot && paramResult.isValid && requestBodyParamResult.isValid) {
|
|
419
|
+
const totalRequiredParams = requestBodyParamResult.requiredNum + paramResult.requiredNum;
|
|
420
|
+
const totalParams = totalRequiredParams + requestBodyParamResult.optionalNum + paramResult.optionalNum;
|
|
421
|
+
if (totalRequiredParams > 1) {
|
|
422
|
+
if (!options.allowMultipleParameters ||
|
|
423
|
+
totalRequiredParams > ConstantString.SMERequiredParamsMaxNum) {
|
|
424
|
+
result.reason.push(ErrorType.ExceededRequiredParamsLimit);
|
|
378
425
|
}
|
|
379
|
-
return false;
|
|
380
|
-
}
|
|
381
|
-
else if (requestBodyParamResult.requiredNum +
|
|
382
|
-
requestBodyParamResult.optionalNum +
|
|
383
|
-
paramResult.requiredNum +
|
|
384
|
-
paramResult.optionalNum ===
|
|
385
|
-
0) {
|
|
386
|
-
return false;
|
|
387
426
|
}
|
|
388
|
-
else {
|
|
389
|
-
|
|
427
|
+
else if (totalParams === 0) {
|
|
428
|
+
result.reason.push(ErrorType.NoParameter);
|
|
390
429
|
}
|
|
391
430
|
}
|
|
392
431
|
}
|
|
393
|
-
|
|
432
|
+
if (result.reason.length > 0) {
|
|
433
|
+
result.isValid = false;
|
|
434
|
+
}
|
|
435
|
+
return result;
|
|
394
436
|
}
|
|
395
|
-
static isSupportedAuth(
|
|
396
|
-
if (
|
|
397
|
-
return true;
|
|
437
|
+
static isSupportedAuth(authSchemeArray, options) {
|
|
438
|
+
if (authSchemeArray.length === 0) {
|
|
439
|
+
return { isValid: true, reason: [] };
|
|
398
440
|
}
|
|
399
|
-
if (options.allowAPIKeyAuth || options.allowOauth2) {
|
|
441
|
+
if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
|
|
400
442
|
// Currently we don't support multiple auth in one operation
|
|
401
|
-
if (
|
|
402
|
-
return
|
|
443
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
444
|
+
return {
|
|
445
|
+
isValid: false,
|
|
446
|
+
reason: [ErrorType.MultipleAuthNotSupported],
|
|
447
|
+
};
|
|
403
448
|
}
|
|
404
|
-
for (const auths of
|
|
449
|
+
for (const auths of authSchemeArray) {
|
|
405
450
|
if (auths.length === 1) {
|
|
406
|
-
if (
|
|
407
|
-
options.
|
|
408
|
-
Utils.
|
|
409
|
-
return true;
|
|
410
|
-
}
|
|
411
|
-
else if (!options.allowAPIKeyAuth &&
|
|
412
|
-
options.allowOauth2 &&
|
|
413
|
-
Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema)) {
|
|
414
|
-
return true;
|
|
415
|
-
}
|
|
416
|
-
else if (options.allowAPIKeyAuth &&
|
|
417
|
-
options.allowOauth2 &&
|
|
418
|
-
(Utils.isAPIKeyAuth(auths[0].authSchema) ||
|
|
419
|
-
Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema))) {
|
|
420
|
-
return true;
|
|
451
|
+
if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
452
|
+
(options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
|
|
453
|
+
(options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
|
|
454
|
+
return { isValid: true, reason: [] };
|
|
421
455
|
}
|
|
422
456
|
}
|
|
423
457
|
}
|
|
424
458
|
}
|
|
425
|
-
return false;
|
|
459
|
+
return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
|
|
460
|
+
}
|
|
461
|
+
static isBearerTokenAuth(authScheme) {
|
|
462
|
+
return authScheme.type === "http" && authScheme.scheme === "bearer";
|
|
426
463
|
}
|
|
427
|
-
static isAPIKeyAuth(
|
|
428
|
-
return
|
|
464
|
+
static isAPIKeyAuth(authScheme) {
|
|
465
|
+
return authScheme.type === "apiKey";
|
|
429
466
|
}
|
|
430
|
-
static isOAuthWithAuthCodeFlow(
|
|
431
|
-
if (
|
|
467
|
+
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
468
|
+
if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
|
|
432
469
|
return true;
|
|
433
470
|
}
|
|
434
471
|
return false;
|
|
@@ -444,7 +481,7 @@ class Utils {
|
|
|
444
481
|
for (const name in security) {
|
|
445
482
|
const auth = securitySchemas[name];
|
|
446
483
|
authArray.push({
|
|
447
|
-
|
|
484
|
+
authScheme: auth,
|
|
448
485
|
name: name,
|
|
449
486
|
});
|
|
450
487
|
}
|
|
@@ -462,11 +499,17 @@ class Utils {
|
|
|
462
499
|
static getResponseJson(operationObject, isTeamsAiProject = false) {
|
|
463
500
|
var _a, _b;
|
|
464
501
|
let json = {};
|
|
502
|
+
let multipleMediaType = false;
|
|
465
503
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
466
504
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
467
505
|
if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
|
|
506
|
+
multipleMediaType = false;
|
|
468
507
|
json = responseObject.content["application/json"];
|
|
469
|
-
if (
|
|
508
|
+
if (Utils.containMultipleMediaTypes(responseObject)) {
|
|
509
|
+
multipleMediaType = true;
|
|
510
|
+
if (isTeamsAiProject) {
|
|
511
|
+
break;
|
|
512
|
+
}
|
|
470
513
|
json = {};
|
|
471
514
|
}
|
|
472
515
|
else {
|
|
@@ -474,7 +517,7 @@ class Utils {
|
|
|
474
517
|
}
|
|
475
518
|
}
|
|
476
519
|
}
|
|
477
|
-
return json;
|
|
520
|
+
return { json, multipleMediaType };
|
|
478
521
|
}
|
|
479
522
|
static convertPathToCamelCase(path) {
|
|
480
523
|
const pathSegments = path.split(/[./{]/);
|
|
@@ -494,10 +537,10 @@ class Utils {
|
|
|
494
537
|
return undefined;
|
|
495
538
|
}
|
|
496
539
|
}
|
|
497
|
-
static
|
|
540
|
+
static resolveEnv(str) {
|
|
498
541
|
const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
|
|
499
|
-
let matches = placeHolderReg.exec(
|
|
500
|
-
let
|
|
542
|
+
let matches = placeHolderReg.exec(str);
|
|
543
|
+
let newStr = str;
|
|
501
544
|
while (matches != null) {
|
|
502
545
|
const envVar = matches[1];
|
|
503
546
|
const envVal = process.env[envVar];
|
|
@@ -505,17 +548,17 @@ class Utils {
|
|
|
505
548
|
throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
|
|
506
549
|
}
|
|
507
550
|
else {
|
|
508
|
-
|
|
551
|
+
newStr = newStr.replace(matches[0], envVal);
|
|
509
552
|
}
|
|
510
|
-
matches = placeHolderReg.exec(
|
|
553
|
+
matches = placeHolderReg.exec(str);
|
|
511
554
|
}
|
|
512
|
-
return
|
|
555
|
+
return newStr;
|
|
513
556
|
}
|
|
514
557
|
static checkServerUrl(servers) {
|
|
515
558
|
const errors = [];
|
|
516
559
|
let serverUrl;
|
|
517
560
|
try {
|
|
518
|
-
serverUrl = Utils.
|
|
561
|
+
serverUrl = Utils.resolveEnv(servers[0].url);
|
|
519
562
|
}
|
|
520
563
|
catch (err) {
|
|
521
564
|
errors.push({
|
|
@@ -546,6 +589,7 @@ class Utils {
|
|
|
546
589
|
return errors;
|
|
547
590
|
}
|
|
548
591
|
static validateServer(spec, options) {
|
|
592
|
+
var _a;
|
|
549
593
|
const errors = [];
|
|
550
594
|
let hasTopLevelServers = false;
|
|
551
595
|
let hasPathLevelServers = false;
|
|
@@ -566,7 +610,7 @@ class Utils {
|
|
|
566
610
|
}
|
|
567
611
|
for (const method in methods) {
|
|
568
612
|
const operationObject = methods[method];
|
|
569
|
-
if (
|
|
613
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
570
614
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
571
615
|
hasOperationLevelServers = true;
|
|
572
616
|
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
@@ -609,6 +653,7 @@ class Utils {
|
|
|
609
653
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
610
654
|
}
|
|
611
655
|
if (isRequired && schema.default === undefined) {
|
|
656
|
+
parameter.isRequired = true;
|
|
612
657
|
requiredParams.push(parameter);
|
|
613
658
|
}
|
|
614
659
|
else {
|
|
@@ -672,6 +717,7 @@ class Utils {
|
|
|
672
717
|
}
|
|
673
718
|
if (param.in !== "header" && param.in !== "cookie") {
|
|
674
719
|
if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
|
|
720
|
+
parameter.isRequired = true;
|
|
675
721
|
requiredParams.push(parameter);
|
|
676
722
|
}
|
|
677
723
|
else {
|
|
@@ -691,13 +737,7 @@ class Utils {
|
|
|
691
737
|
}
|
|
692
738
|
}
|
|
693
739
|
const operationId = operationItem.operationId;
|
|
694
|
-
const parameters = [];
|
|
695
|
-
if (requiredParams.length !== 0) {
|
|
696
|
-
parameters.push(...requiredParams);
|
|
697
|
-
}
|
|
698
|
-
else {
|
|
699
|
-
parameters.push(optionalParams[0]);
|
|
700
|
-
}
|
|
740
|
+
const parameters = [...requiredParams, ...optionalParams];
|
|
701
741
|
const command = {
|
|
702
742
|
context: ["compose"],
|
|
703
743
|
type: "query",
|
|
@@ -706,25 +746,23 @@ class Utils {
|
|
|
706
746
|
parameters: parameters,
|
|
707
747
|
description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
|
|
708
748
|
};
|
|
709
|
-
|
|
710
|
-
if (requiredParams.length === 0 && optionalParams.length > 1) {
|
|
711
|
-
warning = {
|
|
712
|
-
type: WarningType.OperationOnlyContainsOptionalParam,
|
|
713
|
-
content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, operationId),
|
|
714
|
-
data: operationId,
|
|
715
|
-
};
|
|
716
|
-
}
|
|
717
|
-
return [command, warning];
|
|
749
|
+
return command;
|
|
718
750
|
}
|
|
719
|
-
static
|
|
751
|
+
static listAPIs(spec, options) {
|
|
752
|
+
var _a;
|
|
720
753
|
const paths = spec.paths;
|
|
721
754
|
const result = {};
|
|
722
755
|
for (const path in paths) {
|
|
723
756
|
const methods = paths[path];
|
|
724
757
|
for (const method in methods) {
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
758
|
+
const operationObject = methods[method];
|
|
759
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
760
|
+
const validateResult = Utils.isSupportedApi(method, path, spec, options);
|
|
761
|
+
result[`${method.toUpperCase()} ${path}`] = {
|
|
762
|
+
operation: operationObject,
|
|
763
|
+
isValid: validateResult.isValid,
|
|
764
|
+
reason: validateResult.reason,
|
|
765
|
+
};
|
|
728
766
|
}
|
|
729
767
|
}
|
|
730
768
|
}
|
|
@@ -733,13 +771,13 @@ class Utils {
|
|
|
733
771
|
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
734
772
|
const errors = [];
|
|
735
773
|
const warnings = [];
|
|
774
|
+
const apiMap = Utils.listAPIs(spec, options);
|
|
736
775
|
if (isSwaggerFile) {
|
|
737
776
|
warnings.push({
|
|
738
777
|
type: WarningType.ConvertSwaggerToOpenAPI,
|
|
739
778
|
content: ConstantString.ConvertSwaggerToOpenAPI,
|
|
740
779
|
});
|
|
741
780
|
}
|
|
742
|
-
// Server validation
|
|
743
781
|
const serverErrors = Utils.validateServer(spec, options);
|
|
744
782
|
errors.push(...serverErrors);
|
|
745
783
|
// Remote reference not supported
|
|
@@ -753,8 +791,8 @@ class Utils {
|
|
|
753
791
|
});
|
|
754
792
|
}
|
|
755
793
|
// No supported API
|
|
756
|
-
const
|
|
757
|
-
if (
|
|
794
|
+
const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
|
|
795
|
+
if (validAPIs.length === 0) {
|
|
758
796
|
errors.push({
|
|
759
797
|
type: ErrorType.NoSupportedApi,
|
|
760
798
|
content: ConstantString.NoSupportedApi,
|
|
@@ -763,8 +801,8 @@ class Utils {
|
|
|
763
801
|
// OperationId missing
|
|
764
802
|
const apisMissingOperationId = [];
|
|
765
803
|
for (const key in apiMap) {
|
|
766
|
-
const
|
|
767
|
-
if (!
|
|
804
|
+
const { operation } = apiMap[key];
|
|
805
|
+
if (!operation.operationId) {
|
|
768
806
|
apisMissingOperationId.push(key);
|
|
769
807
|
}
|
|
770
808
|
}
|
|
@@ -805,6 +843,19 @@ class Utils {
|
|
|
805
843
|
}
|
|
806
844
|
return safeRegistrationIdEnvName;
|
|
807
845
|
}
|
|
846
|
+
static getAllAPICount(spec) {
|
|
847
|
+
let count = 0;
|
|
848
|
+
const paths = spec.paths;
|
|
849
|
+
for (const path in paths) {
|
|
850
|
+
const methods = paths[path];
|
|
851
|
+
for (const method in methods) {
|
|
852
|
+
if (ConstantString.AllOperationMethods.includes(method)) {
|
|
853
|
+
count++;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
return count;
|
|
858
|
+
}
|
|
808
859
|
}
|
|
809
860
|
|
|
810
861
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -823,6 +874,7 @@ class SpecParser {
|
|
|
823
874
|
allowSwagger: false,
|
|
824
875
|
allowAPIKeyAuth: false,
|
|
825
876
|
allowMultipleParameters: false,
|
|
877
|
+
allowBearerTokenAuth: false,
|
|
826
878
|
allowOauth2: false,
|
|
827
879
|
allowMethods: ["get", "post"],
|
|
828
880
|
projectType: ProjectType.SME,
|
|
@@ -884,7 +936,7 @@ class SpecParser {
|
|
|
884
936
|
if (!operationId) {
|
|
885
937
|
continue;
|
|
886
938
|
}
|
|
887
|
-
const
|
|
939
|
+
const command = Utils.parseApiInfo(pathObjectItem, this.options);
|
|
888
940
|
const apiInfo = {
|
|
889
941
|
method: method,
|
|
890
942
|
path: path,
|
|
@@ -893,9 +945,6 @@ class SpecParser {
|
|
|
893
945
|
parameters: command.parameters,
|
|
894
946
|
description: command.description,
|
|
895
947
|
};
|
|
896
|
-
if (warning) {
|
|
897
|
-
apiInfo.warning = warning;
|
|
898
|
-
}
|
|
899
948
|
apiInfos.push(apiInfo);
|
|
900
949
|
}
|
|
901
950
|
return apiInfos;
|
|
@@ -969,17 +1018,35 @@ class SpecParser {
|
|
|
969
1018
|
if (this.apiMap !== undefined) {
|
|
970
1019
|
return this.apiMap;
|
|
971
1020
|
}
|
|
972
|
-
const result =
|
|
1021
|
+
const result = this.listSupportedAPIs(spec, this.options);
|
|
973
1022
|
this.apiMap = result;
|
|
974
1023
|
return result;
|
|
975
1024
|
}
|
|
1025
|
+
listSupportedAPIs(spec, options) {
|
|
1026
|
+
var _a;
|
|
1027
|
+
const paths = spec.paths;
|
|
1028
|
+
const result = {};
|
|
1029
|
+
for (const path in paths) {
|
|
1030
|
+
const methods = paths[path];
|
|
1031
|
+
for (const method in methods) {
|
|
1032
|
+
const operationObject = methods[method];
|
|
1033
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
1034
|
+
const validateResult = Utils.isSupportedApi(method, path, spec, options);
|
|
1035
|
+
if (validateResult.isValid) {
|
|
1036
|
+
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
return result;
|
|
1042
|
+
}
|
|
976
1043
|
}
|
|
977
1044
|
|
|
978
1045
|
// Copyright (c) Microsoft Corporation.
|
|
979
1046
|
class AdaptiveCardGenerator {
|
|
980
1047
|
static generateAdaptiveCard(operationItem) {
|
|
981
1048
|
try {
|
|
982
|
-
const json = Utils.getResponseJson(operationItem);
|
|
1049
|
+
const { json } = Utils.getResponseJson(operationItem);
|
|
983
1050
|
let cardBody = [];
|
|
984
1051
|
let schema = json.schema;
|
|
985
1052
|
let jsonPath = "$";
|