Skip to content

Commit

Permalink
Fix controller inheritance (#339)
Browse files Browse the repository at this point in the history
* Fix controller inheritance

* Fix error when methodMetadata undefined

* Fix error when methodMetadata undefined

Co-authored-by: Dan Cavanagh <djcavanagh@gmail.com>
  • Loading branch information
DamienSynthesis and dcavanagh committed Oct 4, 2021
1 parent ecf552f commit 9a9ac5f
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 9 deletions.
11 changes: 7 additions & 4 deletions src/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,13 @@ export function httpMethod(

let metadataList: Array<ControllerMethodMetadata> = [];

if (!Reflect.hasMetadata(METADATA_KEY.controllerMethod, target.constructor)) {
if (!Reflect.hasOwnMetadata(METADATA_KEY.controllerMethod, target.constructor)) {
Reflect.defineMetadata(METADATA_KEY.controllerMethod, metadataList, target.constructor);
} else {
metadataList = Reflect.getMetadata(METADATA_KEY.controllerMethod, target.constructor);
metadataList = Reflect.getOwnMetadata(
METADATA_KEY.controllerMethod,
target.constructor,
);
}

metadataList.push(metadata);
Expand Down Expand Up @@ -137,10 +140,10 @@ export function params(type: PARAMETER_TYPE, parameterName?: string) {
parameterName,
type,
};
if (!Reflect.hasMetadata(METADATA_KEY.controllerParameter, target.constructor)) {
if (!Reflect.hasOwnMetadata(METADATA_KEY.controllerParameter, target.constructor)) {
parameterMetadataList.unshift(parameterMetadata);
} else {
metadataList = Reflect.getMetadata(
metadataList = Reflect.getOwnMetadata(
METADATA_KEY.controllerParameter,
target.constructor,
);
Expand Down
24 changes: 21 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export function getControllersFromMetadata(): Array<new() => Controller> {
}

export function getControllerMetadata(constructor: any): ControllerMetadata {
const controllerMetadata: ControllerMetadata = Reflect.getMetadata(
const controllerMetadata: ControllerMetadata = Reflect.getOwnMetadata(
METADATA_KEY.controller,
constructor,
);
Expand All @@ -40,20 +40,38 @@ export function getControllerMetadata(constructor: any): ControllerMetadata {
export function getControllerMethodMetadata(
constructor: any,
): Array<ControllerMethodMetadata> {
const methodMetadata: Array<ControllerMethodMetadata> = Reflect.getMetadata(
const methodMetadata: Array<ControllerMethodMetadata> = Reflect.getOwnMetadata(
METADATA_KEY.controllerMethod,
constructor,
);
const genericMetadata = Reflect.getMetadata(
METADATA_KEY.controllerMethod,
Reflect.getPrototypeOf(constructor) as any,
);
if (genericMetadata !== undefined && methodMetadata !== undefined) {
return methodMetadata.concat(genericMetadata);
} if (genericMetadata !== undefined) {
return genericMetadata;
}
return methodMetadata;
}

export function getControllerParameterMetadata(
constructor: any,
): ControllerParameterMetadata {
const parameterMetadata: ControllerParameterMetadata = Reflect.getMetadata(
const parameterMetadata: ControllerParameterMetadata = Reflect.getOwnMetadata(
METADATA_KEY.controllerParameter,
constructor,
);
const genericMetadata: ControllerParameterMetadata = Reflect.getMetadata(
METADATA_KEY.controllerParameter,
Reflect.getPrototypeOf(constructor) as any,
);
if (genericMetadata !== undefined && parameterMetadata !== undefined) {
return {...parameterMetadata, ...genericMetadata};
} if (genericMetadata !== undefined) {
return genericMetadata;
}
return parameterMetadata;
}

Expand Down
53 changes: 51 additions & 2 deletions test/fetures/controller_inheritance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
httpDelete, httpPost, httpPut, requestBody,
} from '../../src/decorators';
import {cleanUpMetadata} from '../../src/utils';
import {getRouteInfo} from '../../src';

function getDemoServer() {
interface Movie {
Expand Down Expand Up @@ -65,7 +66,29 @@ function getDemoServer() {
@requestParam('movieId') movieId: string,
@requestParam('actorId') actorId: string,
) {
return {status: `DERIVED DELETE ACTOR! ${ movieId } ${ actorId }`};
return {status: `DERIVED DELETE ACTOR! MOVIECONTROLLER1 ${ movieId } ${ actorId }`};
}
}

@controller('/api/v1/movies2')
class MoviesController2 extends GenericController<Movie> {
@httpDelete('/:movieId2/actors/:actorId2')
public deleteActor(
@requestParam('movieId2') movieId: string,
@requestParam('actorId2') actorId: string,
) {
return {status: `DERIVED DELETE ACTOR! MOVIECONTROLLER2 ${ movieId } ${ actorId }`};
}
}

@controller('/api/v1/movies3')
class MoviesController3 extends GenericController<Movie> {
@httpDelete('/:movieId3/actors/:actorId3')
public deleteActor(
@requestParam('movieId3') movieId: string,
@requestParam('actorId3') actorId: string,
) {
return {status: `DERIVED DELETE ACTOR! MOVIECONTROLLER3 ${ movieId } ${ actorId }`};
}
}

Expand Down Expand Up @@ -164,7 +187,33 @@ describe('Derived controller', () => {
supertest(server).delete(`/api/v1/movies/${ movieId }/actors/${ actorId }`)
.expect(200)
.then(res => {
expect(res.body.status).toEqual(`DERIVED DELETE ACTOR! ${ movieId } ${ actorId }`);
expect(res.body.status).toEqual(`DERIVED DELETE ACTOR! MOVIECONTROLLER1 ${ movieId } ${ actorId }`);
done();
});
});

it('Derived controller 2 can have its own methods', done => {
const server = getDemoServer();
const movieId = 5;
const actorId = 3;

supertest(server).delete(`/api/v1/movies2/${ movieId }/actors/${ actorId }`)
.expect(200)
.then(res => {
expect(res.body.status).toEqual(`DERIVED DELETE ACTOR! MOVIECONTROLLER2 ${ movieId } ${ actorId }`);
done();
});
});

it('Derived controller 3 can have its own methods', done => {
const server = getDemoServer();
const movieId = 5;
const actorId = 3;

supertest(server).delete(`/api/v1/movies3/${ movieId }/actors/${ actorId }`)
.expect(200)
.then(res => {
expect(res.body.status).toEqual(`DERIVED DELETE ACTOR! MOVIECONTROLLER3 ${ movieId } ${ actorId }`);
done();
});
});
Expand Down

0 comments on commit 9a9ac5f

Please sign in to comment.