@microsoft/m365-spec-parser 0.1.1-alpha.a372ccf67.0 → 0.1.1-alpha.b54a7ba8f.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 +201 -117
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +255 -147
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +201 -117
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +255 -147
- 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 +16 -13
- package/package.json +3 -3
package/dist/index.esm2017.js
CHANGED
|
@@ -16,6 +16,7 @@ var ErrorType;
|
|
|
16
16
|
ErrorType["ResolveServerUrlFailed"] = "resolve-server-url-failed";
|
|
17
17
|
ErrorType["SwaggerNotSupported"] = "swagger-not-supported";
|
|
18
18
|
ErrorType["MultipleAuthNotSupported"] = "multiple-auth-not-supported";
|
|
19
|
+
ErrorType["SpecVersionNotSupported"] = "spec-version-not-supported";
|
|
19
20
|
ErrorType["ListFailed"] = "list-failed";
|
|
20
21
|
ErrorType["listSupportedAPIInfoFailed"] = "list-supported-api-info-failed";
|
|
21
22
|
ErrorType["FilterSpecFailed"] = "filter-spec-failed";
|
|
@@ -24,6 +25,21 @@ var ErrorType;
|
|
|
24
25
|
ErrorType["GenerateFailed"] = "generate-failed";
|
|
25
26
|
ErrorType["ValidateFailed"] = "validate-failed";
|
|
26
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";
|
|
27
43
|
ErrorType["Cancelled"] = "cancelled";
|
|
28
44
|
ErrorType["Unknown"] = "unknown";
|
|
29
45
|
})(ErrorType || (ErrorType = {}));
|
|
@@ -79,6 +95,7 @@ ConstantString.ResolveServerUrlFailed = "Unable to resolve the server URL: pleas
|
|
|
79
95
|
ConstantString.OperationOnlyContainsOptionalParam = "Operation %s contains multiple optional parameters. The first optional parameter is used for this command.";
|
|
80
96
|
ConstantString.ConvertSwaggerToOpenAPI = "The Swagger 2.0 file has been converted to OpenAPI 3.0.";
|
|
81
97
|
ConstantString.SwaggerNotSupported = "Swagger 2.0 is not supported. Please convert to OpenAPI 3.0 manually before proceeding.";
|
|
98
|
+
ConstantString.SpecVersionNotSupported = "Unsupported OpenAPI version %s. Please use version 3.0.x.";
|
|
82
99
|
ConstantString.MultipleAuthNotSupported = "Multiple authentication methods are unsupported. Ensure all selected APIs use identical authentication.";
|
|
83
100
|
ConstantString.UnsupportedSchema = "Unsupported schema in %s %s: %s";
|
|
84
101
|
ConstantString.WrappedCardVersion = "devPreview";
|
|
@@ -173,6 +190,7 @@ class Utils {
|
|
|
173
190
|
requiredNum: 0,
|
|
174
191
|
optionalNum: 0,
|
|
175
192
|
isValid: true,
|
|
193
|
+
reason: [],
|
|
176
194
|
};
|
|
177
195
|
if (!paramObject) {
|
|
178
196
|
return paramResult;
|
|
@@ -182,6 +200,7 @@ class Utils {
|
|
|
182
200
|
const schema = param.schema;
|
|
183
201
|
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
184
202
|
paramResult.isValid = false;
|
|
203
|
+
paramResult.reason.push(ErrorType.ParamsContainsNestedObject);
|
|
185
204
|
continue;
|
|
186
205
|
}
|
|
187
206
|
const isRequiredWithoutDefault = param.required && schema.default === undefined;
|
|
@@ -197,6 +216,7 @@ class Utils {
|
|
|
197
216
|
if (param.in === "header" || param.in === "cookie") {
|
|
198
217
|
if (isRequiredWithoutDefault) {
|
|
199
218
|
paramResult.isValid = false;
|
|
219
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
200
220
|
}
|
|
201
221
|
continue;
|
|
202
222
|
}
|
|
@@ -206,6 +226,7 @@ class Utils {
|
|
|
206
226
|
schema.type !== "integer") {
|
|
207
227
|
if (isRequiredWithoutDefault) {
|
|
208
228
|
paramResult.isValid = false;
|
|
229
|
+
paramResult.reason.push(ErrorType.ParamsContainRequiredUnsupportedSchema);
|
|
209
230
|
}
|
|
210
231
|
continue;
|
|
211
232
|
}
|
|
@@ -226,6 +247,7 @@ class Utils {
|
|
|
226
247
|
requiredNum: 0,
|
|
227
248
|
optionalNum: 0,
|
|
228
249
|
isValid: true,
|
|
250
|
+
reason: [],
|
|
229
251
|
};
|
|
230
252
|
if (Object.keys(schema).length === 0) {
|
|
231
253
|
return paramResult;
|
|
@@ -233,6 +255,7 @@ class Utils {
|
|
|
233
255
|
const isRequiredWithoutDefault = isRequired && schema.default === undefined;
|
|
234
256
|
if (isCopilot && this.hasNestedObjectInSchema(schema)) {
|
|
235
257
|
paramResult.isValid = false;
|
|
258
|
+
paramResult.reason = [ErrorType.RequestBodyContainsNestedObject];
|
|
236
259
|
return paramResult;
|
|
237
260
|
}
|
|
238
261
|
if (schema.type === "string" ||
|
|
@@ -257,11 +280,13 @@ class Utils {
|
|
|
257
280
|
paramResult.requiredNum += result.requiredNum;
|
|
258
281
|
paramResult.optionalNum += result.optionalNum;
|
|
259
282
|
paramResult.isValid = paramResult.isValid && result.isValid;
|
|
283
|
+
paramResult.reason.push(...result.reason);
|
|
260
284
|
}
|
|
261
285
|
}
|
|
262
286
|
else {
|
|
263
287
|
if (isRequiredWithoutDefault && !isCopilot) {
|
|
264
288
|
paramResult.isValid = false;
|
|
289
|
+
paramResult.reason.push(ErrorType.PostBodyContainsRequiredUnsupportedSchema);
|
|
265
290
|
}
|
|
266
291
|
}
|
|
267
292
|
return paramResult;
|
|
@@ -285,120 +310,132 @@ class Utils {
|
|
|
285
310
|
*/
|
|
286
311
|
static isSupportedApi(method, path, spec, options) {
|
|
287
312
|
var _a;
|
|
288
|
-
const
|
|
313
|
+
const result = { isValid: true, reason: [] };
|
|
289
314
|
method = method.toLocaleLowerCase();
|
|
290
|
-
if (
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
315
|
+
if (options.allowMethods && !options.allowMethods.includes(method)) {
|
|
316
|
+
result.isValid = false;
|
|
317
|
+
result.reason.push(ErrorType.MethodNotAllowed);
|
|
318
|
+
return result;
|
|
319
|
+
}
|
|
320
|
+
const pathObj = spec.paths[path];
|
|
321
|
+
if (!pathObj || !pathObj[method]) {
|
|
322
|
+
result.isValid = false;
|
|
323
|
+
result.reason.push(ErrorType.UrlPathNotExist);
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
326
|
+
const securities = pathObj[method].security;
|
|
327
|
+
const isTeamsAi = options.projectType === ProjectType.TeamsAi;
|
|
328
|
+
const isCopilot = options.projectType === ProjectType.Copilot;
|
|
329
|
+
// Teams AI project doesn't care about auth, it will use authProvider for user to implement
|
|
330
|
+
if (!isTeamsAi) {
|
|
331
|
+
const authArray = Utils.getAuthArray(securities, spec);
|
|
332
|
+
const authCheckResult = Utils.isSupportedAuth(authArray, options);
|
|
333
|
+
if (!authCheckResult.isValid) {
|
|
334
|
+
result.reason.push(...authCheckResult.reason);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const operationObject = pathObj[method];
|
|
338
|
+
if (!options.allowMissingId && !operationObject.operationId) {
|
|
339
|
+
result.reason.push(ErrorType.MissingOperationId);
|
|
340
|
+
}
|
|
341
|
+
const rootServer = spec.servers && spec.servers[0];
|
|
342
|
+
const methodServer = spec.paths[path].servers && ((_a = spec.paths[path]) === null || _a === void 0 ? void 0 : _a.servers[0]);
|
|
343
|
+
const operationServer = operationObject.servers && operationObject.servers[0];
|
|
344
|
+
const serverUrl = operationServer || methodServer || rootServer;
|
|
345
|
+
if (!serverUrl) {
|
|
346
|
+
result.reason.push(ErrorType.NoServerInformation);
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
const serverValidateResult = Utils.checkServerUrl([serverUrl]);
|
|
350
|
+
result.reason.push(...serverValidateResult.map((item) => item.type));
|
|
351
|
+
}
|
|
352
|
+
const paramObject = operationObject.parameters;
|
|
353
|
+
const requestBody = operationObject.requestBody;
|
|
354
|
+
const requestJsonBody = requestBody === null || requestBody === void 0 ? void 0 : requestBody.content["application/json"];
|
|
355
|
+
if (!isTeamsAi && Utils.containMultipleMediaTypes(requestBody)) {
|
|
356
|
+
result.reason.push(ErrorType.PostBodyContainMultipleMediaTypes);
|
|
357
|
+
}
|
|
358
|
+
const { json, multipleMediaType } = Utils.getResponseJson(operationObject, isTeamsAi);
|
|
359
|
+
if (multipleMediaType && !isTeamsAi) {
|
|
360
|
+
result.reason.push(ErrorType.ResponseContainMultipleMediaTypes);
|
|
361
|
+
}
|
|
362
|
+
else if (Object.keys(json).length === 0) {
|
|
363
|
+
result.reason.push(ErrorType.ResponseJsonIsEmpty);
|
|
364
|
+
}
|
|
365
|
+
// Teams AI project doesn't care about request parameters/body
|
|
366
|
+
if (!isTeamsAi) {
|
|
367
|
+
let requestBodyParamResult = {
|
|
368
|
+
requiredNum: 0,
|
|
369
|
+
optionalNum: 0,
|
|
370
|
+
isValid: true,
|
|
371
|
+
reason: [],
|
|
372
|
+
};
|
|
373
|
+
if (requestJsonBody) {
|
|
374
|
+
const requestBodySchema = requestJsonBody.schema;
|
|
375
|
+
if (isCopilot && requestBodySchema.type !== "object") {
|
|
376
|
+
result.reason.push(ErrorType.PostBodySchemaIsNotJson);
|
|
338
377
|
}
|
|
339
|
-
|
|
340
|
-
if (
|
|
341
|
-
|
|
378
|
+
requestBodyParamResult = Utils.checkPostBody(requestBodySchema, requestBody.required, isCopilot);
|
|
379
|
+
if (!requestBodyParamResult.isValid && requestBodyParamResult.reason) {
|
|
380
|
+
result.reason.push(...requestBodyParamResult.reason);
|
|
342
381
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
382
|
+
}
|
|
383
|
+
const paramResult = Utils.checkParameters(paramObject, isCopilot);
|
|
384
|
+
if (!paramResult.isValid && paramResult.reason) {
|
|
385
|
+
result.reason.push(...paramResult.reason);
|
|
386
|
+
}
|
|
387
|
+
// Copilot support arbitrary parameters
|
|
388
|
+
if (!isCopilot && paramResult.isValid && requestBodyParamResult.isValid) {
|
|
389
|
+
const totalRequiredParams = requestBodyParamResult.requiredNum + paramResult.requiredNum;
|
|
390
|
+
const totalParams = totalRequiredParams + requestBodyParamResult.optionalNum + paramResult.optionalNum;
|
|
391
|
+
if (totalRequiredParams > 1) {
|
|
392
|
+
if (!options.allowMultipleParameters ||
|
|
393
|
+
totalRequiredParams > ConstantString.SMERequiredParamsMaxNum) {
|
|
394
|
+
result.reason.push(ErrorType.ExceededRequiredParamsLimit);
|
|
348
395
|
}
|
|
349
|
-
return false;
|
|
350
396
|
}
|
|
351
|
-
else if (
|
|
352
|
-
|
|
353
|
-
paramResult.requiredNum +
|
|
354
|
-
paramResult.optionalNum ===
|
|
355
|
-
0) {
|
|
356
|
-
return false;
|
|
357
|
-
}
|
|
358
|
-
else {
|
|
359
|
-
return true;
|
|
397
|
+
else if (totalParams === 0) {
|
|
398
|
+
result.reason.push(ErrorType.NoParameter);
|
|
360
399
|
}
|
|
361
400
|
}
|
|
362
401
|
}
|
|
363
|
-
|
|
402
|
+
if (result.reason.length > 0) {
|
|
403
|
+
result.isValid = false;
|
|
404
|
+
}
|
|
405
|
+
return result;
|
|
364
406
|
}
|
|
365
|
-
static isSupportedAuth(
|
|
366
|
-
if (
|
|
367
|
-
return true;
|
|
407
|
+
static isSupportedAuth(authSchemeArray, options) {
|
|
408
|
+
if (authSchemeArray.length === 0) {
|
|
409
|
+
return { isValid: true, reason: [] };
|
|
368
410
|
}
|
|
369
|
-
if (options.allowAPIKeyAuth || options.allowOauth2) {
|
|
411
|
+
if (options.allowAPIKeyAuth || options.allowOauth2 || options.allowBearerTokenAuth) {
|
|
370
412
|
// Currently we don't support multiple auth in one operation
|
|
371
|
-
if (
|
|
372
|
-
return
|
|
413
|
+
if (authSchemeArray.length > 0 && authSchemeArray.every((auths) => auths.length > 1)) {
|
|
414
|
+
return {
|
|
415
|
+
isValid: false,
|
|
416
|
+
reason: [ErrorType.MultipleAuthNotSupported],
|
|
417
|
+
};
|
|
373
418
|
}
|
|
374
|
-
for (const auths of
|
|
419
|
+
for (const auths of authSchemeArray) {
|
|
375
420
|
if (auths.length === 1) {
|
|
376
|
-
if (
|
|
377
|
-
options.
|
|
378
|
-
Utils.
|
|
379
|
-
return true;
|
|
380
|
-
}
|
|
381
|
-
else if (!options.allowAPIKeyAuth &&
|
|
382
|
-
options.allowOauth2 &&
|
|
383
|
-
Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema)) {
|
|
384
|
-
return true;
|
|
385
|
-
}
|
|
386
|
-
else if (options.allowAPIKeyAuth &&
|
|
387
|
-
options.allowOauth2 &&
|
|
388
|
-
(Utils.isAPIKeyAuth(auths[0].authSchema) ||
|
|
389
|
-
Utils.isOAuthWithAuthCodeFlow(auths[0].authSchema))) {
|
|
390
|
-
return true;
|
|
421
|
+
if ((options.allowAPIKeyAuth && Utils.isAPIKeyAuth(auths[0].authScheme)) ||
|
|
422
|
+
(options.allowOauth2 && Utils.isOAuthWithAuthCodeFlow(auths[0].authScheme)) ||
|
|
423
|
+
(options.allowBearerTokenAuth && Utils.isBearerTokenAuth(auths[0].authScheme))) {
|
|
424
|
+
return { isValid: true, reason: [] };
|
|
391
425
|
}
|
|
392
426
|
}
|
|
393
427
|
}
|
|
394
428
|
}
|
|
395
|
-
return false;
|
|
429
|
+
return { isValid: false, reason: [ErrorType.AuthTypeIsNotSupported] };
|
|
430
|
+
}
|
|
431
|
+
static isBearerTokenAuth(authScheme) {
|
|
432
|
+
return authScheme.type === "http" && authScheme.scheme === "bearer";
|
|
396
433
|
}
|
|
397
|
-
static isAPIKeyAuth(
|
|
398
|
-
return
|
|
434
|
+
static isAPIKeyAuth(authScheme) {
|
|
435
|
+
return authScheme.type === "apiKey";
|
|
399
436
|
}
|
|
400
|
-
static isOAuthWithAuthCodeFlow(
|
|
401
|
-
if (
|
|
437
|
+
static isOAuthWithAuthCodeFlow(authScheme) {
|
|
438
|
+
if (authScheme.type === "oauth2" && authScheme.flows && authScheme.flows.authorizationCode) {
|
|
402
439
|
return true;
|
|
403
440
|
}
|
|
404
441
|
return false;
|
|
@@ -414,7 +451,7 @@ class Utils {
|
|
|
414
451
|
for (const name in security) {
|
|
415
452
|
const auth = securitySchemas[name];
|
|
416
453
|
authArray.push({
|
|
417
|
-
|
|
454
|
+
authScheme: auth,
|
|
418
455
|
name: name,
|
|
419
456
|
});
|
|
420
457
|
}
|
|
@@ -432,11 +469,17 @@ class Utils {
|
|
|
432
469
|
static getResponseJson(operationObject, isTeamsAiProject = false) {
|
|
433
470
|
var _a, _b;
|
|
434
471
|
let json = {};
|
|
472
|
+
let multipleMediaType = false;
|
|
435
473
|
for (const code of ConstantString.ResponseCodeFor20X) {
|
|
436
474
|
const responseObject = (_a = operationObject === null || operationObject === void 0 ? void 0 : operationObject.responses) === null || _a === void 0 ? void 0 : _a[code];
|
|
437
475
|
if ((_b = responseObject === null || responseObject === void 0 ? void 0 : responseObject.content) === null || _b === void 0 ? void 0 : _b["application/json"]) {
|
|
476
|
+
multipleMediaType = false;
|
|
438
477
|
json = responseObject.content["application/json"];
|
|
439
|
-
if (
|
|
478
|
+
if (Utils.containMultipleMediaTypes(responseObject)) {
|
|
479
|
+
multipleMediaType = true;
|
|
480
|
+
if (isTeamsAiProject) {
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
440
483
|
json = {};
|
|
441
484
|
}
|
|
442
485
|
else {
|
|
@@ -444,7 +487,7 @@ class Utils {
|
|
|
444
487
|
}
|
|
445
488
|
}
|
|
446
489
|
}
|
|
447
|
-
return json;
|
|
490
|
+
return { json, multipleMediaType };
|
|
448
491
|
}
|
|
449
492
|
static convertPathToCamelCase(path) {
|
|
450
493
|
const pathSegments = path.split(/[./{]/);
|
|
@@ -464,10 +507,10 @@ class Utils {
|
|
|
464
507
|
return undefined;
|
|
465
508
|
}
|
|
466
509
|
}
|
|
467
|
-
static
|
|
510
|
+
static resolveEnv(str) {
|
|
468
511
|
const placeHolderReg = /\${{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*}}/g;
|
|
469
|
-
let matches = placeHolderReg.exec(
|
|
470
|
-
let
|
|
512
|
+
let matches = placeHolderReg.exec(str);
|
|
513
|
+
let newStr = str;
|
|
471
514
|
while (matches != null) {
|
|
472
515
|
const envVar = matches[1];
|
|
473
516
|
const envVal = process.env[envVar];
|
|
@@ -475,17 +518,17 @@ class Utils {
|
|
|
475
518
|
throw new Error(Utils.format(ConstantString.ResolveServerUrlFailed, envVar));
|
|
476
519
|
}
|
|
477
520
|
else {
|
|
478
|
-
|
|
521
|
+
newStr = newStr.replace(matches[0], envVal);
|
|
479
522
|
}
|
|
480
|
-
matches = placeHolderReg.exec(
|
|
523
|
+
matches = placeHolderReg.exec(str);
|
|
481
524
|
}
|
|
482
|
-
return
|
|
525
|
+
return newStr;
|
|
483
526
|
}
|
|
484
527
|
static checkServerUrl(servers) {
|
|
485
528
|
const errors = [];
|
|
486
529
|
let serverUrl;
|
|
487
530
|
try {
|
|
488
|
-
serverUrl = Utils.
|
|
531
|
+
serverUrl = Utils.resolveEnv(servers[0].url);
|
|
489
532
|
}
|
|
490
533
|
catch (err) {
|
|
491
534
|
errors.push({
|
|
@@ -516,6 +559,7 @@ class Utils {
|
|
|
516
559
|
return errors;
|
|
517
560
|
}
|
|
518
561
|
static validateServer(spec, options) {
|
|
562
|
+
var _a;
|
|
519
563
|
const errors = [];
|
|
520
564
|
let hasTopLevelServers = false;
|
|
521
565
|
let hasPathLevelServers = false;
|
|
@@ -536,7 +580,7 @@ class Utils {
|
|
|
536
580
|
}
|
|
537
581
|
for (const method in methods) {
|
|
538
582
|
const operationObject = methods[method];
|
|
539
|
-
if (
|
|
583
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
540
584
|
if ((operationObject === null || operationObject === void 0 ? void 0 : operationObject.servers) && operationObject.servers.length >= 1) {
|
|
541
585
|
hasOperationLevelServers = true;
|
|
542
586
|
const serverErrors = Utils.checkServerUrl(operationObject.servers);
|
|
@@ -579,6 +623,7 @@ class Utils {
|
|
|
579
623
|
Utils.updateParameterWithInputType(schema, parameter);
|
|
580
624
|
}
|
|
581
625
|
if (isRequired && schema.default === undefined) {
|
|
626
|
+
parameter.isRequired = true;
|
|
582
627
|
requiredParams.push(parameter);
|
|
583
628
|
}
|
|
584
629
|
else {
|
|
@@ -642,6 +687,7 @@ class Utils {
|
|
|
642
687
|
}
|
|
643
688
|
if (param.in !== "header" && param.in !== "cookie") {
|
|
644
689
|
if (param.required && (schema === null || schema === void 0 ? void 0 : schema.default) === undefined) {
|
|
690
|
+
parameter.isRequired = true;
|
|
645
691
|
requiredParams.push(parameter);
|
|
646
692
|
}
|
|
647
693
|
else {
|
|
@@ -686,15 +732,21 @@ class Utils {
|
|
|
686
732
|
}
|
|
687
733
|
return [command, warning];
|
|
688
734
|
}
|
|
689
|
-
static
|
|
735
|
+
static listAPIs(spec, options) {
|
|
736
|
+
var _a;
|
|
690
737
|
const paths = spec.paths;
|
|
691
738
|
const result = {};
|
|
692
739
|
for (const path in paths) {
|
|
693
740
|
const methods = paths[path];
|
|
694
741
|
for (const method in methods) {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
742
|
+
const operationObject = methods[method];
|
|
743
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
744
|
+
const validateResult = Utils.isSupportedApi(method, path, spec, options);
|
|
745
|
+
result[`${method.toUpperCase()} ${path}`] = {
|
|
746
|
+
operation: operationObject,
|
|
747
|
+
isValid: validateResult.isValid,
|
|
748
|
+
reason: validateResult.reason,
|
|
749
|
+
};
|
|
698
750
|
}
|
|
699
751
|
}
|
|
700
752
|
}
|
|
@@ -703,13 +755,13 @@ class Utils {
|
|
|
703
755
|
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
704
756
|
const errors = [];
|
|
705
757
|
const warnings = [];
|
|
758
|
+
const apiMap = Utils.listAPIs(spec, options);
|
|
706
759
|
if (isSwaggerFile) {
|
|
707
760
|
warnings.push({
|
|
708
761
|
type: WarningType.ConvertSwaggerToOpenAPI,
|
|
709
762
|
content: ConstantString.ConvertSwaggerToOpenAPI,
|
|
710
763
|
});
|
|
711
764
|
}
|
|
712
|
-
// Server validation
|
|
713
765
|
const serverErrors = Utils.validateServer(spec, options);
|
|
714
766
|
errors.push(...serverErrors);
|
|
715
767
|
// Remote reference not supported
|
|
@@ -723,8 +775,8 @@ class Utils {
|
|
|
723
775
|
});
|
|
724
776
|
}
|
|
725
777
|
// No supported API
|
|
726
|
-
const
|
|
727
|
-
if (
|
|
778
|
+
const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
|
|
779
|
+
if (validAPIs.length === 0) {
|
|
728
780
|
errors.push({
|
|
729
781
|
type: ErrorType.NoSupportedApi,
|
|
730
782
|
content: ConstantString.NoSupportedApi,
|
|
@@ -733,8 +785,8 @@ class Utils {
|
|
|
733
785
|
// OperationId missing
|
|
734
786
|
const apisMissingOperationId = [];
|
|
735
787
|
for (const key in apiMap) {
|
|
736
|
-
const
|
|
737
|
-
if (!
|
|
788
|
+
const { operation } = apiMap[key];
|
|
789
|
+
if (!operation.operationId) {
|
|
738
790
|
apisMissingOperationId.push(key);
|
|
739
791
|
}
|
|
740
792
|
}
|
|
@@ -775,6 +827,19 @@ class Utils {
|
|
|
775
827
|
}
|
|
776
828
|
return safeRegistrationIdEnvName;
|
|
777
829
|
}
|
|
830
|
+
static getAllAPICount(spec) {
|
|
831
|
+
let count = 0;
|
|
832
|
+
const paths = spec.paths;
|
|
833
|
+
for (const path in paths) {
|
|
834
|
+
const methods = paths[path];
|
|
835
|
+
for (const method in methods) {
|
|
836
|
+
if (ConstantString.AllOperationMethods.includes(method)) {
|
|
837
|
+
count++;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
return count;
|
|
842
|
+
}
|
|
778
843
|
}
|
|
779
844
|
|
|
780
845
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -793,6 +858,7 @@ class SpecParser {
|
|
|
793
858
|
allowSwagger: false,
|
|
794
859
|
allowAPIKeyAuth: false,
|
|
795
860
|
allowMultipleParameters: false,
|
|
861
|
+
allowBearerTokenAuth: false,
|
|
796
862
|
allowOauth2: false,
|
|
797
863
|
allowMethods: ["get", "post"],
|
|
798
864
|
projectType: ProjectType.SME,
|
|
@@ -925,17 +991,35 @@ class SpecParser {
|
|
|
925
991
|
if (this.apiMap !== undefined) {
|
|
926
992
|
return this.apiMap;
|
|
927
993
|
}
|
|
928
|
-
const result =
|
|
994
|
+
const result = this.listSupportedAPIs(spec, this.options);
|
|
929
995
|
this.apiMap = result;
|
|
930
996
|
return result;
|
|
931
997
|
}
|
|
998
|
+
listSupportedAPIs(spec, options) {
|
|
999
|
+
var _a;
|
|
1000
|
+
const paths = spec.paths;
|
|
1001
|
+
const result = {};
|
|
1002
|
+
for (const path in paths) {
|
|
1003
|
+
const methods = paths[path];
|
|
1004
|
+
for (const method in methods) {
|
|
1005
|
+
const operationObject = methods[method];
|
|
1006
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
1007
|
+
const validateResult = Utils.isSupportedApi(method, path, spec, options);
|
|
1008
|
+
if (validateResult.isValid) {
|
|
1009
|
+
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
return result;
|
|
1015
|
+
}
|
|
932
1016
|
}
|
|
933
1017
|
|
|
934
1018
|
// Copyright (c) Microsoft Corporation.
|
|
935
1019
|
class AdaptiveCardGenerator {
|
|
936
1020
|
static generateAdaptiveCard(operationItem) {
|
|
937
1021
|
try {
|
|
938
|
-
const json = Utils.getResponseJson(operationItem);
|
|
1022
|
+
const { json } = Utils.getResponseJson(operationItem);
|
|
939
1023
|
let cardBody = [];
|
|
940
1024
|
let schema = json.schema;
|
|
941
1025
|
let jsonPath = "$";
|