Phani
Phani

Reputation: 861

Node typescript library environment specific configuration

I am new to node and typescript. I am working on developing a node library that reaches out to another rest API to get and post data. This library is consumed by a/any UI application to send and receive data from the API service. Now my question is, how do I maintain environment specific configuration within the library? Like for ex:

Consumer calls GET /user user end point on the consumer side calls a method in the library to get data

But if the consumer is calling the user end point in test environment I want the library to hit the following API Url

for test http://api.test.userinformation.company.com/user
for beta http://api.beta.userinformation.company.com/user

As far as I understand the library is just a reference and is running within the consumer application. Library can for sure get the environment from the consumer, but I do not want the consumer having to specify the full URL that needs to be hit, since that would be the responsibility of the library to figure out.

Note: URL is not the only problem, I can solve that with environment switch within the library, I have some client secrets based on environments which I can neither store in the code nor checkin to source control.

Additional Information

(as per jfriend00's request in comments)

My library has a LibExecutionEngine class and one method in it, which is the entry point of the library:

export class LibExecutionEngine implements ExecutionEngine {
    constructor(private environment: Environments, private trailLoader: 
    TrailLoader) {}

        async GetUserInfo(
            userId: string,
            userGroupVersion: string
            ): Promise<UserInfo> {
               return this.userLoader.loadUserInfo(userId, userGroupVersion)
        }
}

export interface ExecutionEngine {
    GetUserInfo(userId: string, userGroupVersion: string): Promise<UserInfo>

}

The consumer starts to use the library by creating an instance of the LibraryExecution then calling the getuserinfo for example. As you see the constructor for the class accepts an environment. Once I have the environment in the library, I need to somehow load the values for keys API Url, APIClientId and APIClientSecret from within the constructor. I know of two ways to do this:

Option 1

I could do something like this._configLoader.SetConfigVariables(environment) where configLoader.ts is a class that loads the specific configuration values from files({environment}.json), but this would mean I maintain the above mentioned URL variables and the respective clientid, clientsecret to be able to hit the URL in a json file, which I should not be checking in to source control.

Option 2

I could use dotenv npm package, and create one .env file where I define the three keys, and then the values are stored in the deployment configuration which works perfectly for an independently deployable application, but this is a library and doesn't run by itself in any environment.

Option 3

Accept a configuration object from the consumer, which means that the consumer of the library provides the URL, clientId, and clientSecret based on the environment for the library to access, but why should the responsibility of maintaining the necessary variables for library be put on the consumer?

Please suggest on how best to implement this.

Upvotes: 0

Views: 451

Answers (1)

jfriend00
jfriend00

Reputation: 707686

So, I think I got some clarity. Lets call my Library L, and consuming app C1 and the API that the library makes a call out to get user info as A. All are internal applications in our org and have a OAuth setup to be able to communicate, our infosec team provides those clientids and secrets to individual applications, so I think my clarity here is: C1 would request their own clientid and clientsecret to hit A's URL, C1 would then pass in the three config values to the library, which the library uses to communicate with A. Same applies for some C2 in the future.

Which would mean that L somehow needs to accept a full configuration object with all required config values from its consumers C1, C2 etc.

Yes, that sounds like the proper approach. The library is just some code doing what it's told. It's the client in this case that had to fetch the clientid and clientsecret from the infosec team and maintain them and keep them safe and the client also has the URL that goes with them. So, the client passes all this into your library, ideally just once per instance and you then keep it in your instance data for the duration of that instance

Upvotes: 1

Related Questions