@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.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
|
-
}
|
|
351
|
-
else if (requestBodyParamResult.requiredNum +
|
|
352
|
-
requestBodyParamResult.optionalNum +
|
|
353
|
-
paramResult.requiredNum +
|
|
354
|
-
paramResult.optionalNum ===
|
|
355
|
-
0) {
|
|
356
|
-
return false;
|
|
357
396
|
}
|
|
358
|
-
else {
|
|
359
|
-
|
|
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] };
|
|
396
430
|
}
|
|
397
|
-
static
|
|
398
|
-
return
|
|
431
|
+
static isBearerTokenAuth(authScheme) {
|
|
432
|
+
return authScheme.type === "http" && authScheme.scheme === "bearer";
|
|
399
433
|
}
|
|
400
|
-
static
|
|
401
|
-
|
|
434
|
+
static isAPIKeyAuth(authScheme) {
|
|
435
|
+
return authScheme.type === "apiKey";
|
|
436
|
+
}
|
|
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 {
|
|
@@ -661,13 +707,7 @@ class Utils {
|
|
|
661
707
|
}
|
|
662
708
|
}
|
|
663
709
|
const operationId = operationItem.operationId;
|
|
664
|
-
const parameters = [];
|
|
665
|
-
if (requiredParams.length !== 0) {
|
|
666
|
-
parameters.push(...requiredParams);
|
|
667
|
-
}
|
|
668
|
-
else {
|
|
669
|
-
parameters.push(optionalParams[0]);
|
|
670
|
-
}
|
|
710
|
+
const parameters = [...requiredParams, ...optionalParams];
|
|
671
711
|
const command = {
|
|
672
712
|
context: ["compose"],
|
|
673
713
|
type: "query",
|
|
@@ -676,25 +716,23 @@ class Utils {
|
|
|
676
716
|
parameters: parameters,
|
|
677
717
|
description: ((_b = operationItem.description) !== null && _b !== void 0 ? _b : "").slice(0, ConstantString.CommandDescriptionMaxLens),
|
|
678
718
|
};
|
|
679
|
-
|
|
680
|
-
if (requiredParams.length === 0 && optionalParams.length > 1) {
|
|
681
|
-
warning = {
|
|
682
|
-
type: WarningType.OperationOnlyContainsOptionalParam,
|
|
683
|
-
content: Utils.format(ConstantString.OperationOnlyContainsOptionalParam, operationId),
|
|
684
|
-
data: operationId,
|
|
685
|
-
};
|
|
686
|
-
}
|
|
687
|
-
return [command, warning];
|
|
719
|
+
return command;
|
|
688
720
|
}
|
|
689
|
-
static
|
|
721
|
+
static listAPIs(spec, options) {
|
|
722
|
+
var _a;
|
|
690
723
|
const paths = spec.paths;
|
|
691
724
|
const result = {};
|
|
692
725
|
for (const path in paths) {
|
|
693
726
|
const methods = paths[path];
|
|
694
727
|
for (const method in methods) {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
728
|
+
const operationObject = methods[method];
|
|
729
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
730
|
+
const validateResult = Utils.isSupportedApi(method, path, spec, options);
|
|
731
|
+
result[`${method.toUpperCase()} ${path}`] = {
|
|
732
|
+
operation: operationObject,
|
|
733
|
+
isValid: validateResult.isValid,
|
|
734
|
+
reason: validateResult.reason,
|
|
735
|
+
};
|
|
698
736
|
}
|
|
699
737
|
}
|
|
700
738
|
}
|
|
@@ -703,13 +741,13 @@ class Utils {
|
|
|
703
741
|
static validateSpec(spec, parser, isSwaggerFile, options) {
|
|
704
742
|
const errors = [];
|
|
705
743
|
const warnings = [];
|
|
744
|
+
const apiMap = Utils.listAPIs(spec, options);
|
|
706
745
|
if (isSwaggerFile) {
|
|
707
746
|
warnings.push({
|
|
708
747
|
type: WarningType.ConvertSwaggerToOpenAPI,
|
|
709
748
|
content: ConstantString.ConvertSwaggerToOpenAPI,
|
|
710
749
|
});
|
|
711
750
|
}
|
|
712
|
-
// Server validation
|
|
713
751
|
const serverErrors = Utils.validateServer(spec, options);
|
|
714
752
|
errors.push(...serverErrors);
|
|
715
753
|
// Remote reference not supported
|
|
@@ -723,8 +761,8 @@ class Utils {
|
|
|
723
761
|
});
|
|
724
762
|
}
|
|
725
763
|
// No supported API
|
|
726
|
-
const
|
|
727
|
-
if (
|
|
764
|
+
const validAPIs = Object.entries(apiMap).filter(([, value]) => value.isValid);
|
|
765
|
+
if (validAPIs.length === 0) {
|
|
728
766
|
errors.push({
|
|
729
767
|
type: ErrorType.NoSupportedApi,
|
|
730
768
|
content: ConstantString.NoSupportedApi,
|
|
@@ -733,8 +771,8 @@ class Utils {
|
|
|
733
771
|
// OperationId missing
|
|
734
772
|
const apisMissingOperationId = [];
|
|
735
773
|
for (const key in apiMap) {
|
|
736
|
-
const
|
|
737
|
-
if (!
|
|
774
|
+
const { operation } = apiMap[key];
|
|
775
|
+
if (!operation.operationId) {
|
|
738
776
|
apisMissingOperationId.push(key);
|
|
739
777
|
}
|
|
740
778
|
}
|
|
@@ -775,6 +813,19 @@ class Utils {
|
|
|
775
813
|
}
|
|
776
814
|
return safeRegistrationIdEnvName;
|
|
777
815
|
}
|
|
816
|
+
static getAllAPICount(spec) {
|
|
817
|
+
let count = 0;
|
|
818
|
+
const paths = spec.paths;
|
|
819
|
+
for (const path in paths) {
|
|
820
|
+
const methods = paths[path];
|
|
821
|
+
for (const method in methods) {
|
|
822
|
+
if (ConstantString.AllOperationMethods.includes(method)) {
|
|
823
|
+
count++;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
return count;
|
|
828
|
+
}
|
|
778
829
|
}
|
|
779
830
|
|
|
780
831
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -793,6 +844,7 @@ class SpecParser {
|
|
|
793
844
|
allowSwagger: false,
|
|
794
845
|
allowAPIKeyAuth: false,
|
|
795
846
|
allowMultipleParameters: false,
|
|
847
|
+
allowBearerTokenAuth: false,
|
|
796
848
|
allowOauth2: false,
|
|
797
849
|
allowMethods: ["get", "post"],
|
|
798
850
|
projectType: ProjectType.SME,
|
|
@@ -851,7 +903,7 @@ class SpecParser {
|
|
|
851
903
|
if (!operationId) {
|
|
852
904
|
continue;
|
|
853
905
|
}
|
|
854
|
-
const
|
|
906
|
+
const command = Utils.parseApiInfo(pathObjectItem, this.options);
|
|
855
907
|
const apiInfo = {
|
|
856
908
|
method: method,
|
|
857
909
|
path: path,
|
|
@@ -860,9 +912,6 @@ class SpecParser {
|
|
|
860
912
|
parameters: command.parameters,
|
|
861
913
|
description: command.description,
|
|
862
914
|
};
|
|
863
|
-
if (warning) {
|
|
864
|
-
apiInfo.warning = warning;
|
|
865
|
-
}
|
|
866
915
|
apiInfos.push(apiInfo);
|
|
867
916
|
}
|
|
868
917
|
return apiInfos;
|
|
@@ -925,17 +974,35 @@ class SpecParser {
|
|
|
925
974
|
if (this.apiMap !== undefined) {
|
|
926
975
|
return this.apiMap;
|
|
927
976
|
}
|
|
928
|
-
const result =
|
|
977
|
+
const result = this.listSupportedAPIs(spec, this.options);
|
|
929
978
|
this.apiMap = result;
|
|
930
979
|
return result;
|
|
931
980
|
}
|
|
981
|
+
listSupportedAPIs(spec, options) {
|
|
982
|
+
var _a;
|
|
983
|
+
const paths = spec.paths;
|
|
984
|
+
const result = {};
|
|
985
|
+
for (const path in paths) {
|
|
986
|
+
const methods = paths[path];
|
|
987
|
+
for (const method in methods) {
|
|
988
|
+
const operationObject = methods[method];
|
|
989
|
+
if (((_a = options.allowMethods) === null || _a === void 0 ? void 0 : _a.includes(method)) && operationObject) {
|
|
990
|
+
const validateResult = Utils.isSupportedApi(method, path, spec, options);
|
|
991
|
+
if (validateResult.isValid) {
|
|
992
|
+
result[`${method.toUpperCase()} ${path}`] = operationObject;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
return result;
|
|
998
|
+
}
|
|
932
999
|
}
|
|
933
1000
|
|
|
934
1001
|
// Copyright (c) Microsoft Corporation.
|
|
935
1002
|
class AdaptiveCardGenerator {
|
|
936
1003
|
static generateAdaptiveCard(operationItem) {
|
|
937
1004
|
try {
|
|
938
|
-
const json = Utils.getResponseJson(operationItem);
|
|
1005
|
+
const { json } = Utils.getResponseJson(operationItem);
|
|
939
1006
|
let cardBody = [];
|
|
940
1007
|
let schema = json.schema;
|
|
941
1008
|
let jsonPath = "$";
|