Skip to content

Commit

Permalink
perf(spec-parser): separate api validation logic (#11250)
Browse files Browse the repository at this point in the history
* perf(spec-parser): separate api validation logic

* perf: remove unused code, add missing test file

* perf: remove unused import

---------

Co-authored-by: turenlong <[email protected]>
  • Loading branch information
SLdragon and SLdragon authored Apr 2, 2024
1 parent 5b8de10 commit 0de595a
Show file tree
Hide file tree
Showing 13 changed files with 3,351 additions and 3,297 deletions.
5 changes: 4 additions & 1 deletion packages/spec-parser/src/specFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Utils } from "./utils";
import { SpecParserError } from "./specParserError";
import { ErrorType, ParseOptions } from "./interfaces";
import { ConstantString } from "./constants";
import { ValidatorFactory } from "./validators/validatorFactory";

export class SpecFilter {
static specFilter(
Expand All @@ -28,7 +29,9 @@ export class SpecFilter {
pathObj &&
pathObj[methodName]
) {
const validateResult = Utils.isSupportedApi(methodName, path, resolvedSpec, options);
const validator = ValidatorFactory.create(resolvedSpec, options);
const validateResult = validator.validateAPI(methodName, path);

if (!validateResult.isValid) {
continue;
}
Expand Down
56 changes: 33 additions & 23 deletions packages/spec-parser/src/specParser.browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import {
ValidationStatus,
ListAPIResult,
ProjectType,
APIMap,
} from "./interfaces";
import { SpecParserError } from "./specParserError";
import { Utils } from "./utils";
import { ConstantString } from "./constants";
import { ValidatorFactory } from "./validators/validatorFactory";

/**
* A class that parses an OpenAPI specification file and provides methods to validate, list, and generate artifacts.
Expand All @@ -26,7 +28,7 @@ export class SpecParser {
public readonly parser: SwaggerParser;
public readonly options: Required<ParseOptions>;

private apiMap: { [key: string]: OpenAPIV3.PathItemObject } | undefined;
private apiMap: APIMap | undefined;
private spec: OpenAPIV3.Document | undefined;
private unResolveSpec: OpenAPIV3.Document | undefined;
private isSwaggerFile: boolean | undefined;
Expand Down Expand Up @@ -87,8 +89,15 @@ export class SpecParser {
],
};
}

return Utils.validateSpec(this.spec!, this.parser, !!this.isSwaggerFile, this.options);
const apiMap = this.getAPIs(this.spec!);

return Utils.validateSpec(
this.spec!,
this.parser,
apiMap,
!!this.isSwaggerFile,
this.options
);
} catch (err) {
throw new SpecParserError((err as Error).toString(), ErrorType.ValidateFailed);
}
Expand All @@ -97,19 +106,24 @@ export class SpecParser {
async listSupportedAPIInfo(): Promise<APIInfo[]> {
try {
await this.loadSpec();
const apiMap = this.getAllSupportedAPIs(this.spec!);
const apiMap = this.getAPIs(this.spec!);
const apiInfos: APIInfo[] = [];
for (const key in apiMap) {
const pathObjectItem = apiMap[key];
const { operation, isValid } = apiMap[key];

if (!isValid) {
continue;
}

const [method, path] = key.split(" ");
const operationId = pathObjectItem.operationId;
const operationId = operation.operationId;

// In Browser environment, this api is by default not support api without operationId
if (!operationId) {
continue;
}

const command = Utils.parseApiInfo(pathObjectItem, this.options);
const command = Utils.parseApiInfo(operation, this.options);

const apiInfo: APIInfo = {
method: method,
Expand Down Expand Up @@ -199,34 +213,30 @@ export class SpecParser {
}
}

private getAllSupportedAPIs(spec: OpenAPIV3.Document): {
[key: string]: OpenAPIV3.OperationObject;
} {
private getAPIs(spec: OpenAPIV3.Document): APIMap {
if (this.apiMap !== undefined) {
return this.apiMap;
}
const result = this.listSupportedAPIs(spec, this.options);
const result = this.listAPIs(spec);
this.apiMap = result;
return result;
}

private listSupportedAPIs(
spec: OpenAPIV3.Document,
options: ParseOptions
): {
[key: string]: OpenAPIV3.OperationObject;
} {
private listAPIs(spec: OpenAPIV3.Document): APIMap {
const paths = spec.paths;
const result: { [key: string]: OpenAPIV3.OperationObject } = {};
const result: APIMap = {};
for (const path in paths) {
const methods = paths[path];
for (const method in methods) {
const operationObject = (methods as any)[method] as OpenAPIV3.OperationObject;
if (options.allowMethods?.includes(method) && operationObject) {
const validateResult = Utils.isSupportedApi(method, path, spec, options);
if (validateResult.isValid) {
result[`${method.toUpperCase()} ${path}`] = operationObject;
}
if (this.options.allowMethods?.includes(method) && operationObject) {
const validator = ValidatorFactory.create(spec, this.options);
const validateResult = validator.validateAPI(method, path);
result[`${method.toUpperCase()} ${path}`] = {
operation: operationObject,
isValid: validateResult.isValid,
reason: validateResult.reason,
};
}
}
}
Expand Down
35 changes: 33 additions & 2 deletions packages/spec-parser/src/specParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
ProjectType,
ValidateResult,
ValidationStatus,
WarningResult,
WarningType,
} from "./interfaces";
import { ConstantString } from "./constants";
Expand All @@ -29,6 +30,7 @@ import { Utils } from "./utils";
import { ManifestUpdater } from "./manifestUpdater";
import { AdaptiveCardGenerator } from "./adaptiveCardGenerator";
import { wrapAdaptiveCard } from "./adaptiveCardWrapper";
import { ValidatorFactory } from "./validators/validatorFactory";

/**
* A class that parses an OpenAPI specification file and provides methods to validate, list, and generate artifacts.
Expand Down Expand Up @@ -115,7 +117,15 @@ export class SpecParser {
}
}

return Utils.validateSpec(this.spec!, this.parser, !!this.isSwaggerFile, this.options);
const apiMap = this.getAPIs(this.spec!);

return Utils.validateSpec(
this.spec!,
this.parser,
apiMap,
!!this.isSwaggerFile,
this.options
);
} catch (err) {
throw new SpecParserError((err as Error).toString(), ErrorType.ValidateFailed);
}
Expand Down Expand Up @@ -426,8 +436,29 @@ export class SpecParser {
if (this.apiMap !== undefined) {
return this.apiMap;
}
const result = Utils.listAPIs(spec, this.options);
const result = this.listAPIs(spec, this.options);
this.apiMap = result;
return result;
}

private listAPIs(spec: OpenAPIV3.Document, options: ParseOptions): APIMap {
const paths = spec.paths;
const result: APIMap = {};
for (const path in paths) {
const methods = paths[path];
for (const method in methods) {
const operationObject = (methods as any)[method] as OpenAPIV3.OperationObject;
if (options.allowMethods?.includes(method) && operationObject) {
const validator = ValidatorFactory.create(spec, options);
const validateResult = validator.validateAPI(method, path);
result[`${method.toUpperCase()} ${path}`] = {
operation: operationObject,
isValid: validateResult.isValid,
reason: validateResult.reason,
};
}
}
}
return result;
}
}
Loading

0 comments on commit 0de595a

Please sign in to comment.