Create a common/shared microservice in nestjs - node.js

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';

Related

Proper way to unit test NestJS controller?

I'm new to NestJS and would like to understand how I can unit test an endpoint with config dependencies and 3rd party library dependencies.
Code flow is along the lines of
Main -> Controller -> Service
Service uses config values from ConfigModule and passes these values to a third party library for authentication. The config values themselves are loaded in onModuleInit.
Please let me know if examples/code snippets are required. Thank you!
This repository has a lot of examples on unit testing with NestJS.
In general, with the class your testing, you should mock out the dependencies being injected into it using a custom provider. Then you can have complete control over what values are being returned from the dependencies

Environment specific configuration of datasources in loopback4 application

I have just started my first loopback project and chosen loopback4 version for the application. Its purely a server application which will interact with databases (Redis and mongodb) and will call external API services due to micro-service architecture.
Now, I have 3 datasources in my application i.e. mongodb, Redis, and REST based datasource to call external services. I am facing 2 problems in going forward.
1. Environment specific configurations of Datasources: I need to maintain configuration for all three datasources according to the NODE_ENV environment variable. For lb3 i found this solution,
https://loopback.io/doc/en/lb3/Environment-specific-configuration.html#data-source-configuration
which does not work in lb4. One solution is to add configuration files having names mongodb.staging.json and mongodb.production.json and same for redis and rest datasources in directory src/datasources, and load this config according to NODE_ENV variable using if condition and pass it to the constructor of datasource. It works but it does not seem nice, as it should be application's responsibility to do this.
Can somebody suggest me lb3 equivalent solution for the above?
2. Calling External APIs via datasource: in lb4, To call external services its recommended to have a separate REST based datasource and its service to call it via controller. Now, In REST datasource config, one has to define a template of all the API calls which will happen to the external service https://loopback.io/doc/en/lb4/REST-connector.html#defining-a-custom-method-using-a-template.
As my application calls external service heavily with relatively large number of request parameters. It becomes really messy to declare each API call with its request params and to maintain this in the datasource config which will be environment specific.
Can somebody tell me a more robust and cleaner alternative of the above problem?
Thanks in advance!!
Using environment variables in datasource configs
The datasource config is simply a JSON file that's imported in into *.datasource.ts. Hence, you can replace that JSON file with a Typescript file and import it accordingly. LoopBack 4 does not provide any custom variable substitution mechanism. Instead, it is recommended to use process.env.
Recent CLI versions replace the JSON config in favour of using a single Typescript file:
import {inject} from '#loopback/core';
import {juggler} from '#loopback/repository';
const config = {
name: 'db',
connector: 'memory',
};
export class DbDataSource extends juggler.DataSource {
static dataSourceName = 'db';
static readonly defaultConfig = config;
constructor(
#inject('datasources.config.db', {optional: true})
dsConfig: object = config,
) {
super(dsConfig);
}
}
The dependency injection in the constructor allows you to override the config programmatically via the IoC container of the application.
Further reading
https://loopback.io/doc/en/lb4/DataSources.html
Calling external APIs without REST connector
The REST connector enforces a well-defined interface for querying external APIs so as to be able to do validation before sending out the request.
If this is not favourable, it is possible to create a new Service as a wrapper to the HTTP queries. From there, you can expose your own functions to handle requests to an external API. As Services do not need to follow a rigid structure, it is possible to customize it to your use-case.
It is also possible to create a new request directly inside the controller using either built-in or external libraries.
Overall, there isn't a 100% right or wrong way of doing certain things in LoopBack 4. Hence why the framework provides numerous ways to tackle the same issue.

How to use NESTJS modules in separate classes

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.

How to Structure a TypeScript Project like in Java with Modules and Dependencies?

i have a problem with TypeScript and how to separate modules and import them.
In Java with Maven or Gradle, i can have three modules or projects where:
project-dao: Data Access Object classes
project-dto: Data Transfer Object classes
project-services: Services classes
project-dto is transversal to dao and services, so i can include this module like a project dependency easily in both.
In TypeScript i don't know how do make the same. I see examples with imports of compiled code in Javascript with relative paths or using npm publish for later install in another project.
Someone can i help me with some approach for this issue.
Thanks.
#Paolo : I hope your question is about creating different modules and importing them to your root module. If that's the case, you can very well create a new module with #NgModule annotation. if you want to load this module with the root module, just import this in you app.module.ts as
import {customModule} from './custom.module';
If you just want to load it lazily, include this your routing, with loadChildren property.
But, if a class that's already declared in another module, whether an app module, #NgModule, or third-party module, do not add this to the declaration.
From a DTO's perspective, I guess, you need to create an incline object as
var userObject = {
email : req.body.email,
password: req.body.password
}.
UserObject can then be passed to the next layer.

Mocking Repository but Then Swapping Out for Real Implementation in Node.js

I'm building a Repository layer with higher level API for my abstractions above to make calls to the database persistence. But since JavaScript doesn't have the concept of Interfaces like a language such as C# or Java does, how do you swap out the mock for the real implementation?
I prefer creating custom mocks, node repository modules with data persitence high level methods in them vs. Sinon.js or something like that.
If I'm creating node modules, then how? I could send in a mock representation of the repository where I mock out what the repository methods are doing but then the actual node modules using those repository modules would need to use the real repository implementation that calls the real database. How is this done in Node? I want to just inject via a property, I don't want some gigantic injection IoC framework either.
Since there's no concept of an interface then wtf do you do in Node/JS? I have to create a data layer below the repository (whether it be a custom set of modules making real query calls to Postgres or whether I'm using Mongoose or whatever it may be, I need a DL set of modules that the repository calls for tis real DB calls under the hood).
And lets say I do choose to use some framework like Sinon.js, what's the common interface for the module you're mocking that can be shared by the mocking framework and the real module?
There's more than one way to do it. If you come from a different background it may take some getting used to Node.
You can do this:
module.exports = function(db) {
this.db = db;
this.myQuery = function(n, cb) {
this.db.query(n, cb);
}
}
Then in config.js
var exports.db = require('./mydb');
Then
var config = require('./config.js');
var db = require('./db')(config.db);
There are lots of variations possible. You could do a dynamic require somewhere based on a string or something. Or use classes or init functions. Most are going to probably end up being similar.
The proxyrequire module could be helpful. So can Sinon.js.
Since there really isn't type checking people generally are verifying that with their tests at runtime. If you are really doing TDD it might not make a huge difference.

Resources