I am importing a class from an external library to my NestJS app. I want to create one instance with a couple of environment variables and have that instance available to use across the whole application.
In a regular Node.js app, I would import the lib and initialize the instance in a separate module (file) and then just import it wherever I would need it.
What would be the best practice of doing this in NestJS?
You need to use DI to solve the problem. So you need to define your class or service in some module and export it. Then you can have some custom logic defined for its creation in providers e.g.
{
provide: SomeClass,
useFactory: () => { ... }
}
You can have any custom logic in the useFactory to create an instance. Than once you import your module to other modules the same instance of a class will be available.
UPD: You can read more about custom providers here https://docs.nestjs.com/fundamentals/custom-providers#factory-providers-usefactory
Related
I have 2 modules. One (payment) is responsible for payments. The second (auth) should send a verification request to a third-party server.
I wanted to make the (auth) module global so that I can freely inject its methods and not use "export" and "import" for my "providers".
But for some reason this doesn't work, the #Global decorator seems to be simply ignored.
What am I doing wrong?
Example on codebox: https://codesandbox.io/s/nest-forked-gsy160?file=/src/auth/auth.module.ts
You still need to use exports to allow access to the module's public providers. Once you add in exports this will work fine.
You can think of a module like a container with its private API (non-exported providers), public API (exported providers), entrypoints (controllers, resolvers, gateways) and configurations (imports). You need to export the providers to make them public and available. The #Global() will just mean you don't need to add the AuthModule to other module's imports (besides your root module)
How can i create a microservice that contains all the shared/common login/classes between projects?
I have a gateway, and different microservices, let say auth and account.
How can I share the user.model for example, considering that both services will use that entity?
Also considering that some common methods can be located in this common microservices in order to not have the code duplicated.
Check out the library module of microservice in Nestjs
https://docs.nestjs.com/cli/libraries
Here you can create a library module with the command
nest g library my-library
Then in that module, you can put the shared module like constant, util, etc which are common in all microservices.
To use that module import like this
import { MyLibraryModule } from '#app/my-library';
Plugin system for a nestjs app.
I have some kind of service that lives on "core" module.
This module is supposed to be a black box, completely sealed.
The only way to add new feature is to inject new modules on the system and, eventually,
replace some services of the core module.
The problem:
Ho do i replace a service at runtime? (#Injectable)
The idea is to replace the old class with a new one with enhanced feature.
#Module({
providers: [{provide: OldServiceClass, useClass: NewServiceClass}]
})
export class FeatureModule {}
Sometimes I need to use some methods which implemented in nestjs code structure in separate from this classes
For example we have such architecture:
entities
-entity.entity.ts
-entity.module.ts
-entity.service.ts
-entity.providers.ts
So how Can I use method or property from entity.service in separate class? Such like this:
import EntityService from './entities.entity.service'
export class SeparateClass{
propertyFromEntityService: string
constructor() {
this.propertyFromEntityService = EntityService.propertyFromEntityService
}
}
And one more important point. I don’t want to implement this separate class in the nestjs structure, I just want to use it as a regular class. Thank you
If you are not wanting to use dependency injection via Nest, but you still want to use a property from a class in the Nest application, you'll need to manually instantiate the class, providing whatever dependencies that class has, and then pulling the property from the service. The other option, if this class will be used outside of the Nest context, but still while the Nest application is running, is you can use the Nest application to get the service via app.get(EntityService), but this does require you to have access to app after the NestFactory has created the application.
Newbie question:
When working with NestJS and TypeORM, and one has created a custom repository (which extends the standard repository), is a seperate service class needed anymore?
At the moment, I'm working only with the custom Repository class and it works fine, but I'm not sure if this is correct and perhaps has some side effects.
Btw, in another project i have no custom repo, only a service which get's two standard repo's injected, and this works also fine.
Regards,
sagerobert
I think it's up to you how much you want to add layers between typeORM and your most "front-office" code (that would be the controllers in a typical nest application).
I explain myself:
If you want, you could typically inject directly the built-in typeORM repositories into your controllers:
import {Controller, Get} from '#nestjs/common';
import {InjectRepository} from '#nestjs/typeorm';
import {Repository} from 'typeorm';
import {User} from './entities/User.entity';
#Controller()
export class AppController {
constructor(
#InjectRepository(User)
private readonly userRepository: Repository<User>,
) {
}
#Get()
async root(): Promise<User> {
return await this.userRepository.find(1);
}
}
So this would be the less layered implementation of how to retrieve the user with ID = 1.
Now, the documentation of NEST recommends to abstract this repository and inject it into a service rather than in a controller directly. This allows you to have less binding between your controller and TypeORM. Instead, it's your service that has this binding. If you have many controllers that use this repository, and you decide that you want to change TypeORM and use the new fancy ORM, you'll have to change every controller.
Now, if you just inject the repository inside your service and use this service into all your controllers, you will just have to change the implementation of your service and all the controllers will remain the same.
Secondly, imagine that you want to test your application. You will face the same problem. How can you run your tests without an SQL connection? I suppose that your unit tests are not created to test the TypeORM behaviour, but instead written to test YOUR code behavior.
It will be much easier to mock a repository injected in a service than mock all repositories injected in your controllers.
So to conclude this answer, I think that this question should be closed because it is primarily opinion-based. But IMO, the dreamed architecture is the following:
Create a Custom Repository that extends the TypeORM Repository.
Inside the Custom Repository, add methods that use the Query Builder.
Inject this Custom Repository into your services
Inject the services into your controllers.
Don't ever use the query builder into controllers because it is hard to mock.
I hope this answers to your question: A service class is not needed. But it will help you keep your code clean.