Pipes can be used 2 ways
@Param('foo', MyPipe) which creates MyPipe in the framework
or I can do @Param('foo', new MyPipe()).
Solution 1 gives me ability to use @Injectable which I need (eg I inject db to resolve user from database)
However, I can't access constructor, so I cant configure the pipe.
In scenario 2 I can configure it, but I can't use Injectable
Is there a way to e.g use some factory in this scope, so I can construct pipe just like I would create it in Module?
Let say you have a route 'users/:userId' and you want to auto-cast the userId to user model.
Create a Pipe through command
nest g pipe your-module/pipes/pipe-name/pipe-name
The pipe is created but the pipe would not be full part of the Dependency Injection system of your Nest application.
Make pipe part of DI system by adding it to provider list of the module of the controller is part of.
Let's say its UserModule
@Module({
imports: [],
constrollers: [UserController]
providers: [PipeNamePipe]
})
class UserModule {}
Inject any service that the pipe needs in in it's constructor also part of UserModule or make sure the provider is available globally in the application
For example let's take AuthService originally part of AuthModule and is not avialable in the UserModule, so we will inject it through providers array.
@Module({
imports: [],
constrollers: [UserController]
providers: [PipeNamePipe, AuthService]
})
class UserModule {}
Lets complete the implementation of PipeNamePipe.
Remember the pipe can return any value. It could be Promise, an Observable or a static value. For the example we are returning the promise.
@Injectable()
class PipeNamePipe implments PipeTransform {
construtor(private authService: AuthService){}
transform(value: any): Promise<User> {
return this.authService.findUser(value);
}
}
In your controller just pass the pipe to param
@Controller('users')
class UserController {
@Get(':userId')
show(
@Param('userId', PipeNamePipe) user: User
) {
// the value of userId will be converted to user instance through auth service.
}
}