NestJS + mongoose + mongoose-audit-trail - node.js

I'm trying to use the 'mongoose-audit-trail' plugin in nestjs, but I'm getting the following error "Operation 'histories.findOne()' buffering timed out after 10000ms"
export const s = SchemaFactory.createForClass(Product);
s.plugin(require('mongoose-audit-trail').plugin);
Apparently there seems to be something in the connection that you couldn't use!
Or if anyone has any tips on another plugin for #nest to generate change histories I'd appreciate it!

I have recently been working on something similar. I had a problem where I couldn't get existing audit plugins working with nestjs and some of the stuff I have been working on.
I forked an existing library, and my plan is to merge it back and contribute to the original project. However, work has been crazy so not had a chance to finish it.
Maybe this can help you, if you take a look at my recent commits you'll see the modifications I have made.
https://github.com/piercy/mongoose-history-trace/tree/feat/saas
usage wise, you should just be able to use it as a plugin, passing in a few options. From what I can tell, it does work, and does everything you might need for a nestjs, mongoose audit trail.... but it should be noted that while I am working on this, I haven't really tested or put it into a production environment yet.
You are welcome to use this or even finish it off if you want. Sorry I couldn't just give you a plugin to use but hopefully this helps get you in the right direction.
Original Library is here: https://github.com/WelingtonMonteiro/mongoose-history-trace

When you connect to db with MongooseModule.forRoot() or MongooseModule.forRootAsync() It's not the same as mongoose.connect()...
Your plugin tries to get connection from mongoose, but there is not opened one...
So I've Got Solution for this plugin: create mongoose.connection from module like this:
import { Module } from '#nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './services/app.service';
import { MongooseModule } from '#nestjs/mongoose';
import { ConfigService } from './services/config/config.service';
import * as mongoose from 'mongoose';
#Module({
imports: [
MongooseModule.forRootAsync({
imports: [LargeFamilyModule],
useFactory: async (configService: ConfigService) => {
mongoose.set('strictQuery', false);
mongoose.connect(configService.db.uri)
return configService.db
},
inject: [ConfigService],
},),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
It's not a good idea to create to identical db connections, but for this issue it works.

Related

how can i create influxdb with nestjs?

i am a new software developer. I don't have much software background, but I'm trying to learn as much as I can. Is there anyone who has done influxdb operation with nestjs before? If yes, can you share your previous experiences?
Thank you in advance for reading and replying.
Your going to face many hardships if you consider using nestjs... Maybe im wrong and your underselling yourself, but if you are asking if its possible to connect a database to your backend then nest is surly going to be WAYYYYY WAYYYYY WAYYYYY to complex -> to be able to figure stuff out... Not that you CANT but you might want to consider
Express first just to get an understanding of how a backend works -> without having to plan out all your dtos' controllers services yatta yatta yatta.. you can do all of the same stuff with express, infact the developers used express to make next -> and then added a whole lot of enterprise level stuff that doesnt come standard with express.
plus if you are new to coding then typescript might be a bit much. very sorry if this was not what you were looking for Im not trying to steer you in any particular direction. but I spend 12 hours - 36 hours sometimes trying to figure things out that I already had working before ... the injection and all that come with nest is good , but if you dont know why you need it , then its going to be very hard to actually learn the concepts.
its alot easier to teach someone how to drink water if theyre thirsty .
otherwise you are just going to spend alot of time that could of went into learning the things that are a prerequisite of nest
strong es6 / ts is def a must
the es6 part is more important imo because dealing with everything async for instance and the way everything is formatted its very confusing without a strong grasp of whats going on behind the scenes.
--- as im sure your going to want to find out the hard way -> and i dont blame you if you can get through it you will be a much stronger person =) but here try this on for size.
https://www.npmjs.com/package/nest-influxdb
import { Module } from "#nestjs/common";
import { InfluxDbModule, InfluxModuleOptions } from "nest-influxdb";
import { UtilsModule } from "./utils/utils.module";
import { ConfigService } from "./utils/config/config.service";
#Module({
imports: [
InfluxDbModule.forRootAsync({
imports: [UtilsModule],
inject: [ConfigService],
useFactory: async (
config_servie: ConfigService
): Promise<InfluxModuleOptions> => {
return {
host: config_servie.get("INFLUX_HOST")
};
}
}),
BlogModule
],
controllers: [AppController],
providers: [AppService]
})
export class AppModule {}
this will go in your root level module file -> then you will use the for feature method for the specific thing inside your root database
check the nest docs for how it works with other databases then try to connect the dots with that above package

Understanding import, providers,exports and controller in nestjs

Nest can't resolve dependencies of the MailService (MailerService, ?, CreateSendMailDto). Please make sure that the argument EmailRepository at index [1] is available in the MailModule context.
Potential solutions:
- If EmailRepository is a provider, is it part of the current MailModule?
- If EmailRepository is exported from a separate #Module, is that module imported within MailModule?
#Module({
imports: [ /* the Module containing EmailRepository */ ]
})
Error: Nest can't resolve dependencies of the MailService (MailerService, ?, CreateSendMailDto). Please make sure that the argument EmailRepository at index [1] is available in the MailModule context.
Potential solutions:
- If EmailRepository is a provider, is it part of the current MailModule?
- If EmailRepository is exported from a separate #Module, is that module imported within MailModule?
#Module({
imports: [ /* the Module containing EmailRepository */ ]
})
I'm new to nestjs thou not too experienced with nodejs. Pls i need someone to help me understand the context of module export and providers. I don't really know what to export, import, provied or put in controller, i understand some few stuff but i seek full undersanding of how and what is really happening there. Thanks
You didn't add the code producing the error, but I'll try to explain it in simple terms, assuming the following scenario:
You have two resources, Vehicle & Driver, and you want to use DriverService in VehicleService.
Solution:
Export DriverService from driver.module.ts
Then import DriverModule in vehicle.module.ts
#Module({
controllers: [DriverController],
providers: [DriverService],
exports: [DriverService]
})
#Module({
imports:[DriverModule]
controllers: [VehicleController],
providers: [VehicleService],
})
You can visit the NestJs docs for more info.

What are the benefits of using the Nestjs testing module for unit tests?

In the Nestjs documentation, they suggest using their Test module for instantiating any objects used for testing, like so:
const adoptionServiceMock = {
adoptCat: jest.fn()
};
const moduleRef = await Test.createTestingModule({
providers: [CatsService, { provider: AdoptionService, useValue: adoptionServiceMock }],
}).compile();
catsService = moduleRef.get<CatsService>(CatsService);
What is the benefit of doing it this way, as opposed to regular instantiation? Here's an example of the regular way:
const adoptionServiceMock = {
adoptCat: jest.fn()
} as AdoptionService;
catsService = new CatsService(adoptionService);
I'm specifically referring to using catsService = moduleRef.get<CatsService>(CatsService) instead of newing up a CatsService.
The one thing I can think of is that it does object instantiation the same way Nestjs would do it in production - with DI. If you forget to add Inject() on CatsService or AdoptionService, the test will fail.
If you don't find benefit in it, you absolutely can use whatever method you prefer for mocking. The Test.createTestingModule is there to provide uniformity between Nest projects and to provide an easy way to give mocks to the classes without having to use as whatever, but if you prefer that method, then go for it.
It becomes more powerful out at the e2e/integration level where you can mock guards and other enhancers with fluent methods, but again, the final test implementation is absolutely up to you.
I personally like it cause I can delegate Nest to create providers based off of a class and mock things from there, like a TypeORM repository can be created as
{
provide: getRepositoryToken(EntityClass),
useClass: Repository,
}
No need to extensively create a lot of methods, then later I can use jest.spyOn() or jest.fn() to override the default functionality.

How to use global variables in nest.js?

Taking configuration as an example, the Nest.js documentation advocates registering Config Modules and injecting them into other modules in a dependency injection way.
The benefits are obvious, and the dependencies and code are clear, but what if I have a nest.js project that needs to invoke the configuration information at startup? This actually caused me trouble.
My idea is to use a store (actually a closure) to manage all the variables that might be needed globally, the client-side link objects, registered at startup, and introduced when needed.
When corresponding variables are registered in this way, they can be introduced anywhere. The drawback is that you need to manage dependencies yourself.
With the above concept design of demo: https://github.com/sophons-space/nest-server.
Please e help me correct, I am still a rookie.
If you want to use Nest flow it should be defined in the configuration file
// app.module.ts
import configuration from './config/configuration';
imports: [
// first import as first initialization
ConfigModule.forRoot({
isGlobal: true, // to get access to it in every component
load: [configuration],
}),
]
...
// configuration.ts
export default (): any => {
return {
someGlobalConfigVariable: parseInt(process.env.PORT, 10) || 3000,
};
};
Create a file global.service.ts (inside a folder you can name it utils or whatever) & put the code bellow
export class GlobalService{
static globalVar: any;
}
Set value to the globalVar
GlobalService.globalVar = 'some value';
Get value from globalVar
console.log(GlobalService.globalVar);
N.B. Don't forget to import GlobalService wherever you want to use.
The way you can approach this is similar to how NestJS libraries or integrations usually handle configuration; using a method on the base module.
main.ts
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
// Note the `configure`-method
const app = await NestFactory.create(AppModule.configure({
myConfig: 'value',
});
await app.listen(3000);
}
bootstrap();
app.module.ts
import { DynamicModule } from '#nestjs/common';
export class AppModule {
static configure(config): DynamicModule {
return {
module: AppModule,
providers: [{ provide: 'CONFIG', useValue: config }],
// ....
}
}
}
You can use the general NodeJS approach
global.SomeGlobalVariableName = 'SomeGlobalVariableValue';
console.log(SomeGlobalVariableName);
Approach I used is using my config variables in yaml files and then getting those variables or objects wherever I want in my Nestjs project using config package. e.g in default.yml file
key: value
and then in file where I want to use this
import config from 'config';
let value = config.get<string>('key');
you can take this pkg from this npmjs link here
Why not go with more NestJs way i.e. with provide instance scope?
Most of the answers posted here are correct and easy to implement but I have a more generic way to define that variable that fits well in NestJs (Nestjs Scope and Dependency Injection flow). I would be happy to share the sample code, if required
Steps
Create a provider
Add a private instance variable to this provider - instead of a class variable (i.e. static variables) use an instance variable as NestJs automatically (by default) manages the instance of its providers in a singleton way i.e. a single instance of the provider is shared across the entire application. Read more about scopes here
Add get/set and other methods for that variable
Inject that provider wherever you need the global variable (instance variable of the provider(per instance).
Other ways of doing it
Config - preferrable for pre-defined types(like string, number...)
Static variable in util.ts file
Native Global variable - I would not recommend this(explanation is outside the scope of the question)

NestJs: How can I import one repository into another?

I apologize for what is likely a very amateur question. Coming from Laravel, this is still quite confusing to me and I just don't understand what is needed.
I have a user.repository.ts file and a location.repository.ts file. Each have their own modules, controllers and services. I have successfully created CRUD operations for each entity but now am trying to work towards a Many to Many relationship.
In my user.repository.ts file, I am trying to save a related (many to many) repository:
// user.repository.ts
user.locations = await this.locationRepository.findByIds(locations);
...
await user.save();
I am not sure how to inject or import the location.repository.ts file. I have tried numerous variations of importing the service into each module. Or importing each module into the other module. I have tried different versions of this:
#EntityRepository(User)
#EntityRepository(Location)
Or importing the LocationService into the UserService.
In Laravel, this would be as "simple" as $model->sync($relationship);
How can I import/inject the locationRepository into my userRepository? Thank you for any suggestions!
I assume this question is related to your last question, the simplest way to implement it, Add Locationentity to your UserModule
#Module({
imports:[TypeOrmModule.forFeature([UserRepository,LocationRepository])], // or just Location entity [UserRepository,Location] if you didn't setup a custom LocationRepository
After that, inject it in your as what you did for userRepo... service
constructor(
#InjectRepository(LocationRepository)
private locationRepository: LocationRepository,
// or just private locationRepository: Repository<Location>,
) {}
In the create method service get your locations:
async createUser(createUserDto: CreateUserDto) { // usersSrvice
let locations = await this.locationRepository.findByIds(createUserDto.locations);
await this.userRepository.createMethodeName(createUserDto,locations) // add secand
params for your locations
don't hesitate to ask if you have any other questions

Resources