Using a Decorator
The @UseCls()
decorator can be used at a method level to declaratively wrap the method with a cls.run()
call. This method should only be used outside of the context of a web request.
Please keep in mind, that since the CLS context initialization can be async, the @UseCls()
decorator can only be used on async function (those that return a Promise
).
Since there is no request, the setup
function will not receive a Request
object. Instead, it will receive the this
context of the class instance (this also applies to the idGenerator
), the ClsService
reference and all the arguments passed to the decorated method.
@Injectable()
class SomeService {
constructor(
private readonly cls: ClsService,
private readonly otherService: OtherService,
) {}
@UseCls<[string]>({
generateId: true,
idGenerator: function (this: SomeService) {
return this.generateId();
},
setup: function (this: SomeService, cls: ClsService, value: string) {
cls.set('some-key', 'some-value');
},
})
async startContextualWorkflow(value: string) {
return this.otherService.doSomething(value);
}
private generateId() {
return Math.random();
}
}
It is important to define the setup
and idGenerator
functions as function
s, not arrow functions, so that the this
context is properly bound.
Gotchas
Since the @UseCls()
decorator operates on the method's parameters, it must be type-safe. In order to support this, it requires a generic type parameter, which is a tuple of the types of the method's arguments.
If there's a mismatch between the generic argument and the actual method signature, typescript will complain.
This also means that the decorator is not inherently compatible with Nest's applyDecorators
function for decorator composition, because it would lose the type safety.
If you need to use @UseCls()
with applyDecorators
, you have to cast it to to MethodDecorator
, knowing that type-safety will be lost, e.g.:
export const ProcessWithCls = (queue: string) => {
return applyDecorators(
UseCls({
/* options */
}) as MethodDecorator,
Process(queue),
);
};