Хорошо, нашел решение. На случай, если кто-то еще наткнется на это. Прежде всего, имейте в виду, как работают декораторы - они основаны на конструкторах классов, а не на экземплярах.
В моем случае я хотел, чтобы моя служба логгера была внедрена в экземпляр класса. Таким образом, решение состоит в том, чтобы сказать Nest в декораторе, чтобы он вставлял LoggerService в экземпляр класса, который содержит декорированный метод.
import { Inject } from '@nestjs/common';
import { LoggerService } from '../../logger/logger.service';
export function logErrorDecorator(bubble = true) {
const injectLogger = Inject(LoggerService);
return (target: any, propertyKey: string, propertyDescriptor: PropertyDescriptor) => {
injectLogger(target, 'logger'); // this is the same as using constructor(private readonly logger: LoggerService) in a class
//get original method
const originalMethod = propertyDescriptor.value;
//redefine descriptor value within own function block
propertyDescriptor.value = async function(...args: any[]) {
try {
return await originalMethod.apply(this, args);
} catch (error) {
const logger: LoggerService = this.logger;
logger.setContext(target.constructor.name);
logger.error(error.message, error.stack);
// rethrow error, so it can bubble up
if (bubble) {
throw error;
}
}
};
};
}
Это дает возможность отлавливать ошибки в методе, регистрировать их в контекст службы, и либо перебрасывать их (чтобы ваши контроллеры могли обрабатывать пользователей соответственно), либо нет. В моем случае мне также пришлось реализовать некоторые логики транзакций c здесь.
export class FoobarService implements OnModuleInit {
onModuleInit() {
this.test();
}
@logErrorDecorator()
test() {
throw new Error('Oh my');
}
}