i want run a nestjs service funtion in grpc interceptors definitions, grpc service client register file, my service module class where i register the grpc service to invoke
@Module({
imports: [
ConfigModule,
ClientsModule.registerAsync([
{
name: 'tokenvalidator',
imports: [ConfigModule, ClsModule],
useFactory: async (configService: ConfigService) => ({
transport: Transport.GRPC,
options: {
package: 'br',
protoPath: join(__dirname, '../../protos/tokenvalidator.proto'),
url: configService.get('GRPC_TOKEN_VALIDATOR_HOST'),
channelOptions: {
interceptors: [(options, nextCall) => {
new GRPCInterceptor().interceptGrpcCall(options, nextCall)
}]
}
},
}) as any,
inject: [ConfigService],
},
interceptors are described in "channelOptions" object, inside the array "interceptors" you can pass a function with params (options,next) a typical middleware function, the problem GRPCInterceptor is a NestJS service class
import {InterceptingCall} from "@grpc/grpc-js";
import {Injectable, NestInterceptor, ExecutionContext, CallHandler} from '@nestjs/common';
import {ClsService} from "nestjs-cls";
@Injectable()
export class GRPCInterceptor {
constructor(
private readonly cls: ClsService,
) {
}
interceptGrpcCall(options, nextCall): any {
const requester:any = {
start: (metadata, listener, next) => {
const newListener = {
onReceiveMetadata: (metadata, next) => {
next(metadata);
},
onReceiveMessage: (message, next) => {
next(message);
},
onReceiveStatus: (status, next) => {
this.cls.set('grpcStatus', status)
console.log(this.cls.get("grpcStatus"))
console.log('onReceiveStatus');
console.log(options?.method_definition?.path);
console.log(status);
next(status);
}
};
next(metadata, newListener);
},
sendMessage: function (message, next) {
next(message);
},
halfClose: function (next) {
next();
},
cancel: (message, next) => {
return new InterceptingCall(nextCall(options), requester);
}
};
return new InterceptingCall(nextCall(options), requester);
}
}
and it is waiting a clsService constructor param
error TS2554: Expected 1 arguments, but got 0.
32 new GRPCInterceptor().interceptGrpcCall(options, nextCall)
~~~~~~~~~~~~~~~~~~~~~
src/GRPCInterceptor.ts:9:9
9 private readonly cls: ClsService,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An argument for 'cls' was not provided.
I know you cant do "new NestJSClass().myFunction()", so the problem is how i can run the function inside of my nestjsClass in a module context
i use clsModule because i have a logic with some varaibles on runtime so i use it, but i dont know how instantiate a new class and pass it to nestjs class
As GRPCInterceptor
is a provider class, you should be able to provide it to the inject
array like you do the ConfigService
and make it a parameter of the useFactory
.
@Module({
imports: [
ConfigModule,
ClientsModule.registerAsync([
{
name: 'tokenvalidator',
imports: [ConfigModule, ClsModule],
useFactory: async (configService: ConfigService, grpcInterceptor: GRPCInterceptor) => ({
transport: Transport.GRPC,
options: {
package: 'br',
protoPath: join(__dirname, '../../protos/tokenvalidator.proto'),
url: configService.get('GRPC_TOKEN_VALIDATOR_HOST'),
channelOptions: {
interceptors: [(options, nextCall) => {
grpcInterceptor.interceptGrpcCall(options, nextCall)
}]
}
},
}) as any,
inject: [ConfigService, GRPCInterceptor],
},