Skip to content

Commit

Permalink
minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
jfrconley committed Dec 21, 2023
1 parent 30acf8a commit 6f5cd97
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 35 deletions.
64 changes: 33 additions & 31 deletions packages/rest/src/transform/controller-meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export class ControllerMeta {

public static clearCache() {
this.cache.clear();
this.routes.clear();
}

public static create(
Expand Down Expand Up @@ -190,18 +191,18 @@ export class ControllerMeta {
return ts.factory.createExpressionStatement(callExpression);
}

public getRouteIndex(info: RouteIndex) {
public getRouteIndex(method: string, path: string) {
return {
method: info.method,
path: this.basePath + info.path.toLowerCase(),
method,
path: normalizeHttpPath(this.basePath + path.toLowerCase()),
};
}

public registerRoute(node: ts.Node, routeInfo: RouteInfo) {
public registerRoute(method: string, path: string, info: Omit<RouteInfo, "index">) {
if (this.project.transformOnly) {
return;
}
const index = this.getRouteIndex(routeInfo);
const index = this.getRouteIndex(method, path);
const methods = ControllerMeta.routes.get(index.path) || new Map<string, RouteInfo>();
ControllerMeta.routes.set(index.path, methods);
const route = methods.get(index.method);
Expand All @@ -210,19 +211,16 @@ export class ControllerMeta {
}

const modifiedRouteInfo = {
method: routeInfo.method,
path: this.basePath + routeInfo.path.toLowerCase(),
description: routeInfo.description,
// requestInfo: this.buildRequestInfo(index, routeInfo.input),
// responseInfo: this.buildResponseInfo(index, routeInfo.output),
outputSchema: routeInfo.outputSchema,
inputSchema: routeInfo.inputSchema,
filePath: routeInfo.filePath,
summary: routeInfo.summary,
deprecated: routeInfo.deprecated,
operationId: routeInfo.operationId,
tags: routeInfo.tags,
input: routeInfo.input,
index,
description: info.description,
outputSchema: info.outputSchema,
inputSchema: info.inputSchema,
filePath: info.filePath,
summary: info.summary,
deprecated: info.deprecated,
operationId: info.operationId,
tags: info.tags,
input: info.input,
};

try {
Expand All @@ -232,7 +230,7 @@ export class ControllerMeta {
throw e;
}
console.error(e);
throw new TransformationError("Could not generate OpenAPI spec for route", modifiedRouteInfo);
throw new TransformationError("Could not generate OpenAPI spec for route", index);
}
methods.set(index.method, modifiedRouteInfo);
}
Expand All @@ -249,15 +247,15 @@ export class ControllerMeta {
version: "1.0.0",
},
paths: {
[route.path]: {
[route.method.toLowerCase()]: {
[route.index.path]: {
[route.index.method.toLowerCase()]: {
deprecated: route.deprecated,
tags: route.tags,
operationId: route.operationId,
summary: route.summary,
description: route.description,
responses: this.generateOutputType(route, dereferencedOutputSchema),
requestBody: this.generateRequestBody(route, dereferencedInputSchema),
responses: this.generateOutputType(route.index, dereferencedOutputSchema),
requestBody: this.generateRequestBody(route.index, dereferencedInputSchema),
parameters: [
...this.generateParametersForSchemaPath(dereferencedInputSchema, "/pathParams", "path"),
...this.generateParametersForSchemaPath(dereferencedInputSchema, "/query", "query"),
Expand Down Expand Up @@ -314,20 +312,20 @@ export class ControllerMeta {
});
}

private generateOutputType(routeInfo: RouteInfo, outputSchema: JSONSchema7): OpenAPIV3_1.ResponsesObject {
private generateOutputType(routeIndex: RouteIndex, outputSchema: JSONSchema7): OpenAPIV3_1.ResponsesObject {
const responses: OpenAPIV3_1.ResponsesObject = {};
const statusCodeDiscriminatedSchemas = resolveDiscriminantProperty(outputSchema, "/statusCode");

if (statusCodeDiscriminatedSchemas == null) {
throw new TransformationError("Could not resolve status codes for some responses", routeInfo);
throw new TransformationError("Could not resolve status codes for some responses", routeIndex);
}

for (const [statusCode, schema] of Object.entries(statusCodeDiscriminatedSchemas)) {
const headers = this.generateParametersForSchemaPath(schema, "/headers", "header");
const contentTypeDiscriminatedSchemas = resolveDiscriminantProperty(schema, "/headers/content-type");
const bodySchema = getUnifiedPropertySchemas(schema, "/")["body"];
if (contentTypeDiscriminatedSchemas == null && bodySchema != null) {
throw new TransformationError(`Could not resolve content types for "${statusCode}" responses`, routeInfo);
throw new TransformationError(`Could not resolve content types for "${statusCode}" responses`, routeIndex);
}

const content = contentTypeDiscriminatedSchemas == null ? undefined : Object.fromEntries(
Expand Down Expand Up @@ -400,13 +398,14 @@ export class ControllerMeta {
}
}

function deparameterizePath(path: string) {
return path.replaceAll(/:[^/]+/g, ":param");
function normalizeHttpPath(path: string) {
const doubleSlashRemoved = path.replace(/\/\//g, "/");
const endingSlashRemoved = doubleSlashRemoved.endsWith("/") ? doubleSlashRemoved.slice(0, -1) : doubleSlashRemoved;
return endingSlashRemoved.trim();
}

export interface RouteInfo {
method: string;
path: string;
index: RouteIndex;
description?: string;
summary?: string;
input: ts.TypeNode;
Expand All @@ -418,4 +417,7 @@ export interface RouteInfo {
operationId?: string;
}

export type RouteIndex = Pick<RouteInfo, "method" | "path">;
export interface RouteIndex {
method: string;
path: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export abstract class ChainRouteProcessor {
const path = ChainRouteProcessor.getPath(project, methodDecorator);
const method = ChainRouteProcessor.getMethod(project, methodDecorator);

const routeIndex = controller.getRouteIndex({ method, path });
const routeIndex = controller.getRouteIndex(method, path);

const { typeNode: inputTypeNode } = ChainRouteProcessor.resolveInputType(project, node, routeIndex);

Expand All @@ -63,9 +63,7 @@ export abstract class ChainRouteProcessor {

const parsedDocComments = ChainRouteProcessor.parseJSDoc(project, node);

controller.registerRoute(node, {
method,
path,
controller.registerRoute(method, path, {
input: inputTypeNode,
inputSchema,
outputSchema: outputSchema,
Expand Down
2 changes: 2 additions & 0 deletions packages/test/src/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ interface RoutePostBodyInput {
* @minLength 5
*/
cool: string;

omitted: boolean;
}

/**
Expand Down

0 comments on commit 6f5cd97

Please sign in to comment.