This library implements a strategy pattern and a factory-pattern that allow switching, at runtime, between different API types.
The main use case is to allow developers to implement calls or events in any application without taking care of the underlying implementation. In this way you can switch between different API implementations and protocols without refactoring the entire code.
To inject the API strategy in your NestJS you can create a provider by using one of the following classes within a custom provider useFactory in your Nest Module.
Direct call strategies:
NestLocalCallStrategy
- It uses express/fastify injectNestHttpCallStrategy
- It uses NestJS axiosRef
Event strategies:
NestLocalEventStrategy
- It uses NestJS Event Emitter
NOTE: you can even implement the IApiCallStrategy
, the IEventStrategy
or extends the HttpAbstractStrategy
class to create your own implementation of the strategy. For example, you could implement your own IEventStrategy
to integrate other event-based systems such as Kafka, RabbitMQ etc.
The library also provides a wrapper to define the useFactory by passing typed parameters:
NestLocalCallStrategyProvider('YOUR_LOCAL_CALL_PROVIDER_ID', {
NestLocalStrategy: NestLocalCallStrategy,
baseUrl: '/',
})
NOTE: You need to import the module containing the controller you are calling via the local-strategy to make it work. It's important to understand that the http call is emulated within the same runtime scope, so you will practically import both modules in the same app (the caller and the receiver).
NestHttpCallStrategyProvider('YOUR_HTTP_CALL_PROVIDER_ID', {
NestHttpStrategy: NestHttpCallStrategy,
baseUrl: 'http://youdomain.com/',
});
NOTE: You need to import the HttpModule
from the nestjs library to make it work
NestLocalEventStrategyProvider('YOUR_LOCAL_EVENT_PROVIDER_ID', {
NestLocalStrategy: NestLocalEventStrategy,
});
Once you've injected the provider in your module, you can call it from any other provider/controller by doing:
constructor(
@Inject(YOUR_HTTP_CALL_PROVIDER_ID)
protected readonly serviceCaller: IHttpCallStrategy,
@Inject(YOUR_LOCAL_EVENT_PROVIDER_ID)
protected readonly serviceEvent: IEventStrategy,
) {}
async yourMethod() {
// DIRECT CALL (strong consistency)
await this.serviceCaller.post('/your/endpoint', {
data: { resourceId: userResId },
});
// OR VIA EVENT (eventual consistency)
await this.serviceEvent.emitAsync('your.event.topic', {
resourceId: userResId,
});
}
- You need to start implementing a service-to-service communication using HTTP and switch to gRPC or TCP later on.
- You need to develop and emulate, via code, a microservice architecture before facing the complexity of deploying all the services separately and managing the API/Events infrastructure orchestration. You can then start using the local-call/local-event strategy and then switch to a different one in future.
- You can even switch between different API strategies depending on your environment variables, this can be useful for testing purpose or development.