Skip to content

Commit

Permalink
feat(schema): Add JsonOperationRoute.has() to determine if the method…
Browse files Browse the repository at this point in the history
… consume Files/Body etc...
  • Loading branch information
Romakita committed Jan 2, 2022
1 parent 3f405d1 commit ea3f8dd
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Type} from "@tsed/core";
import {GlobalProviders, InjectorService, ProviderType} from "@tsed/di";
import {getOperationsRoutes, OperationMethods, EndpointMetadata} from "@tsed/schema";
import {getOperationsRoutes, OperationMethods} from "@tsed/schema";
import {ControllerProvider} from "../domain/ControllerProvider";
import {PlatformRouter} from "../services/PlatformRouter";
import {PlatformMiddlewaresChain} from "../services/PlatformMiddlewaresChain";
Expand Down Expand Up @@ -71,7 +71,7 @@ export function buildRouter(injector: InjectorService, provider: ControllerProvi
});

// build all endpoints and his middlewares
getOperationsRoutes<EndpointMetadata>(provider.token).forEach((operationRoute) => {
getOperationsRoutes(provider.token).forEach((operationRoute) => {
const handlers = platformMiddlewaresChain?.get(provider, operationRoute);

router.addRoute({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,11 @@ describe("PlatformMiddlewaresChain", () => {
const chain = platformMiddlewaresChain.get(provider, operationRoutes[1]);

expect(chain[0].type).to.eq("context");
expect(chain[1]).to.eq(PlatformAcceptMimesMiddleware);
expect(chain[2]).to.eq(endpoint.beforeMiddlewares[0]);
expect(chain[3]).to.eq(provider.middlewares.use[0]);
expect(chain[4]).to.eq(endpoint.middlewares[0]);
expect(chain[5]).to.eq(endpoint);
expect(chain[6]).to.eq(endpoint.afterMiddlewares[0]);
expect(chain[7]).to.eq(provider.middlewares.useAfter[0]);
expect(chain[1]).to.eq(endpoint.beforeMiddlewares[0]);
expect(chain[2]).to.eq(provider.middlewares.use[0]);
expect(chain[3]).to.eq(endpoint.middlewares[0]);
expect(chain[4]).to.eq(endpoint);
expect(chain[5]).to.eq(endpoint.afterMiddlewares[0]);
expect(chain[6]).to.eq(provider.middlewares.useAfter[0]);
});
});
17 changes: 10 additions & 7 deletions packages/platform/common/src/services/PlatformMiddlewaresChain.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Injectable} from "@tsed/di";
import {Constant, Injectable} from "@tsed/di";
import {ParamTypes} from "@tsed/platform-params";
import {EndpointMetadata, JsonOperationRoute} from "@tsed/schema";
import {JsonMethodStore, JsonOperationRoute} from "@tsed/schema";
import {ControllerProvider} from "../domain/ControllerProvider";
import {bindEndpointMiddleware} from "../middlewares/bindEndpointMiddleware";
import {PlatformAcceptMimesMiddleware} from "../middlewares/PlatformAcceptMimesMiddleware";
Expand All @@ -9,7 +9,10 @@ import {useCtxHandler} from "../utils/useCtxHandler";

@Injectable()
export class PlatformMiddlewaresChain {
get(provider: ControllerProvider, operationRoute: JsonOperationRoute<EndpointMetadata>) {
@Constant("acceptMimes", [])
protected acceptMimes: string[];

get(provider: ControllerProvider, operationRoute: JsonOperationRoute) {
const {endpoint} = operationRoute;
const {beforeMiddlewares, middlewares: mldwrs, afterMiddlewares} = endpoint;

Expand All @@ -19,8 +22,8 @@ export class PlatformMiddlewaresChain {

return [
useCtxHandler(bindEndpointMiddleware(endpoint)),
PlatformAcceptMimesMiddleware,
this.uploadFile(operationRoute) && PlatformMulterMiddleware,
this.hasAcceptMimes(operationRoute) && PlatformAcceptMimesMiddleware,
operationRoute.has(ParamTypes.FILES) && PlatformMulterMiddleware,
...beforeMiddlewares,
...use,
...mldwrs,
Expand All @@ -30,7 +33,7 @@ export class PlatformMiddlewaresChain {
].filter((item: any) => !!item);
}

private uploadFile(operationRoute: JsonOperationRoute<EndpointMetadata>) {
return [...operationRoute.endpoint.children.values()].find((item) => item.paramType === ParamTypes.FILES);
protected hasAcceptMimes(operationRoute: JsonOperationRoute) {
return operationRoute.endpoint.acceptMimes.length || this.acceptMimes.length;
}
}
38 changes: 38 additions & 0 deletions packages/specs/schema/src/domain/JsonOperationRoute.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Get, JsonEntityStore, JsonOperation, JsonOperationRoute, Name} from "@tsed/schema";
import {BodyParams} from "@tsed/platform-params";

describe("JsonOperationRoute", () => {
it("should create JsonOperationRoute instance", () => {
Expand Down Expand Up @@ -66,4 +67,41 @@ describe("JsonOperationRoute", () => {
expect(operationRoute.operation).toBeInstanceOf(JsonOperation);
expect(operationRoute.operationId).toBe("get");
});
it("should create operation with parameter", () => {
@Name("Testify")
class Test {
@Get("/")
@Name("getify")
get(@BodyParams() body: string) {}
}

const endpoint = JsonEntityStore.fromMethod(Test, "get");
const operationRoute = new JsonOperationRoute({
token: Test,
endpoint,
operationPath: {method: "GET", path: "/"},
basePath: "/base"
});

expect(operationRoute.operationPath).toEqual({
method: "GET",
path: "/"
});
expect(operationRoute.method).toEqual("GET");
expect(operationRoute.path).toEqual("/");
expect(operationRoute.fullPath).toEqual("/base/");
expect(operationRoute.url).toEqual("/base/");
expect(operationRoute.isFinal).toEqual(false);
expect(operationRoute.name).toEqual("Test.get()");
expect(operationRoute.className).toEqual("Test");
expect(operationRoute.methodClassName).toEqual("get");
expect(operationRoute.propertyKey).toEqual("get");
expect(operationRoute.propertyName).toEqual("get");
expect(operationRoute.operation).toBeInstanceOf(JsonOperation);
expect(operationRoute.operationId).toBe("get");
expect(operationRoute.paramsTypes).toEqual({
BODY: true
});
expect(operationRoute.has("BODY")).toEqual(true);
});
});
18 changes: 15 additions & 3 deletions packages/specs/schema/src/domain/JsonOperationRoute.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import {Type} from "@tsed/core";
import {JsonMethodStore} from "./JsonMethodStore";
import {JsonMethodPath, JsonOperation} from "./JsonOperation";
import {JsonEntityStore} from "./JsonEntityStore";
import {concatPath} from "../utils/concatPath";
import {JsonParameterStore} from "./JsonParameterStore";

export class JsonOperationRoute<Entity extends JsonEntityStore = JsonEntityStore> {
export class JsonOperationRoute<Entity extends JsonMethodStore = JsonMethodStore> {
readonly token: Type<any>;
readonly endpoint: Entity;
readonly operationPath?: JsonMethodPath;
readonly basePath?: string;
readonly paramsTypes: Record<string, boolean>;

constructor(options: Partial<JsonOperationRoute>) {
Object.assign(this, options);

this.paramsTypes = [...this.endpoint.children.values()].reduce(
(obj, item) => ({
...obj,
[item.paramType]: true
}),
{}
);
}

get url() {
Expand Down Expand Up @@ -69,4 +77,8 @@ export class JsonOperationRoute<Entity extends JsonEntityStore = JsonEntityStore
get operationId() {
return this.operation.get("operationId") || this.endpoint.propertyKey;
}

has(key: string) {
return this.paramsTypes[key];
}
}
3 changes: 2 additions & 1 deletion packages/specs/schema/src/utils/getOperationsRoutes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {Type} from "@tsed/core";
import {JsonMethodStore} from "../domain/JsonMethodStore";
import {getOperationsStores} from "./getOperationsStores";
import {JsonOperationRoute} from "../domain/JsonOperationRoute";
import {JsonEntityStore} from "../domain/JsonEntityStore";
Expand All @@ -9,7 +10,7 @@ export interface GetOperationsRoutesOptions {
basePath?: string;
}

export function getOperationsRoutes<Entity extends JsonEntityStore = JsonEntityStore>(
export function getOperationsRoutes<Entity extends JsonMethodStore = JsonMethodStore>(
token: Type<any> | any,
options: GetOperationsRoutesOptions = {}
): JsonOperationRoute<Entity>[] {
Expand Down

0 comments on commit ea3f8dd

Please sign in to comment.