Search code examples
node.jstypescriptloopbackjsloopback4

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!!


Solution

  • 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

    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.