Uğur İLTER
Uğur İLTER

Reputation: 1

How to reach class metadata from a parameter decorator inside it?

I want to reach UserEntity class which is sent from PostsController's decorator using HashedRouteParam decorator. Here is my current code example:

Custom Controller Decorator:

import { ControllerOptions as NestControllerOptions } from '@nestjs/common/decorators/core/controller.decorator';
import { Controller as NestController } from '@nestjs/common';
import { Entity } from '../../config/mikro-orm.config';
import { BaseEntity } from '../../database/entities';

export const ENTITY_KEY = Symbol('entity');

interface ControllerOptions extends NestControllerOptions {
    entity?: Entity;
}

type ControllerParams = ControllerOptions | string | string[] | Entity;

export function Controller<TFunction extends Function>(
    prefixOrOptionsOrEntity?: ControllerParams,
): ClassDecorator {
    if (
        typeof prefixOrOptionsOrEntity === 'undefined' ||
        typeof prefixOrOptionsOrEntity === 'string' ||
        Array.isArray(prefixOrOptionsOrEntity)
    ) {
        return NestController(prefixOrOptionsOrEntity);
    }

    let entity: Entity;
    if ((prefixOrOptionsOrEntity as Entity).prototype instanceof BaseEntity) {
        entity = prefixOrOptionsOrEntity as Entity;
    } else if ((prefixOrOptionsOrEntity as ControllerOptions).entity) {
        entity = (prefixOrOptionsOrEntity as ControllerOptions).entity;
        delete (prefixOrOptionsOrEntity as ControllerOptions).entity;
    }

    return ((target: TFunction) => {
        Reflect.defineMetadata(ENTITY_KEY, entity, target.constructor);
        return NestController(prefixOrOptionsOrEntity as any)(target);
    }) as any;
}

PostsController:

import { Controller } from '../common/decorators';

@Controller(PostEntity)
    export class PostsController {
    ...
     @Get(':id')
     async findOne(@HashedRouteParam('id') id: number) {
       ...
     }
}

HashedRouteParam decorator:

export function HashedRouteParam(
    payload: IHashedRoutePayload,
    ...pipes: (Type<PipeTransform> | PipeTransform)[]
) {
    return (
        target: Object,
        propertyKey: string | symbol,
        parameterIndex: number,
    ) => {
        const entity = Reflect.getMetadata(ENTITY_KEY, target.constructor);
        
        ...

        const extendedPipes = [decodePipe, ...pipes];

        return Param(property, ...extendedPipes)(
            target,
            propertyKey,
            parameterIndex,
        );
    };
}

It's not working.

entity object on Controller Decorator function is not defining an undefined entity as metadata. It's fine, i've logged it.

But when i try to get metadata on HashedRouteParam decorator, entity seems to be undefined.

What am i doing wrong and is there any alternative solutions? I want to specify entity type on my controllers to use them later on specific cases.

If i use SetMetadata (from '@nestjs/common') on custom Controller decorator, how can i reach it from HashedRouteParam decorator? I can't use this.reflector on HashedRouteParam function. Or can i somehow?

Upvotes: 0

Views: 439

Answers (1)

TaekYoung
TaekYoung

Reputation: 110

You can try "OnModuleInit" interface. Make a class implements OnModuleInit and import this class. At the class that implements OnModuleInit you can inject provided instances and use it inside "onModuleInit" method.

Upvotes: 0

Related Questions