How to use app environment.ts in libs in nrwl/nx workspace?
Asked Answered
C

2

29

If I have an Authentication lib, with components, service, ngrx, etc... How I can access the environment of the app implementing Authentication lib? So the Auth service should knows the backend url to make the sign in stuff. So:

import { environment as env } from "@env";
@Injectable()
class AuthService {
    private endpoint = '/v1/auth';
    private backendHost = env.backendHost;

    authenticateUser(credentials) {
        return makeHttpRequestHereToBackend(this.backendHost.this.endpoint, credentials);
    }
}

No matters where the Authentication lib is implemented, the lib service knows what server to hit from the app environment who implements said lib.

Thanks!!

Club answered 15/9, 2018 at 17:6 Comment(2)
I am also kinda stuck at this point. I have a library to do all the common tasks and it has authentication service. To use the firebase auth (api and keys), recommended way to add it to the environments which is in the application. How to use the api keys for the library and services in the library then. Confused. feel like nrwl/nx is tricky....Tuition
From this comment on Github Issue Victor Savkin recommends ussing dependency injection to solve this problemClub
C
47

A solution that worked for me

Create a folder named app-config under libs and add an 'index.ts` file inside app-config folder. This lib can be shared across all your apps. Add the following content inside the index.ts file

import { InjectionToken } from '@angular/core';

export const APP_CONFIG = new InjectionToken('Application config');

Open base tsconfig.json file and add the path for app-config so that it can be useful for importing into your app with @app-workspace/app-config

"paths": {
      "@app-workspace/ui": ["libs/ui/src/index.ts"],
      "@app-workspace/auth": ["libs/auth/src/index.ts"],
      "@app-workspace/utils": ["libs/utils/src/index.ts"],
      "@app-workspace/app-config": ["libs/app-config/index.ts"]
    }

Now inside your apps open the file under apps/app1/src/app/app.module.ts and make the following changes for the providers array

import { APP_CONFIG } from '@app-workspace/app-config';
import { environment } from '../environments/environment';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
  ],
  providers: [
    { provide: APP_CONFIG, useValue: environment}
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Here is the sample environment.ts file that is residing under app1

export const environment = {
  production: false,
  apiUrl: 'http://localhost:3000/api',
};

You can use app-config inside your shared libs as-well, for example lets say you are making api calls from within your shared lib libs/auth/src/lib/services/auth.service.ts

import { APP_CONFIG } from '@app-workspace/app-config';
import { Inject, Injectable } from '@angular/core';

@Injectable()
export class AuthService {

  constructor(
    @Inject(APP_CONFIG) private appConfig: any
  ) {
        console.log(this.appConfig.apiUrl); // This will print `http://localhost:3000/api`
    }
}

Hope this is helpful :) Also on a sidenote, you may have to restart your application if you get any error while using the imports.

Corinecorinna answered 16/7, 2019 at 17:33 Comment(4)
This works perfectly and should really be used as an accepted answerCroaky
Such an elegant solution! thxSino
What I like about this way of configuration, is that the env files can remain within each application with little boiler plate or additional environment libraries.Windbroken
I received an NullInjectorError with this one. "No provider for InjectionToken Application config!"Cham
H
25

The superior approach in my opinion is to create an @environments lib. The token approach does not allow tree shaking and seems so foreign. The lib solution is relatively easy to get.

Environments workspace library

  1. nx generate library environments --directory=shared --tags="scope:shared,type:environments" --style=scss
  2. npx rimraf ./libs/shared/environments/src/lib/*.*
  3. mv ./apps/tiny-app/src/environments/*.* ./libs/shared/environments/src/lib
  4. "export * from './lib/environment';" > ./libs/shared/environments/src/index.ts
  5. npx rimraf ./apps/tiny-app/src/environments
  6. In the build architect target of the tiny-app project in angular.json (or project.json if using latest nx), replace the fileReplacements option in the production configuration with this entry:
{
  "projects": {
    "tiny-app": {
      "architect": {
        "build": {
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "libs/shared/environments/src/lib/environment.ts",
                  "with": "libs/shared/environments/src/lib/environment.prod.ts"
                }
              ]
            }
          }
        }
      }
    }
  }
}
  1. In main.ts, replace the environment import statement with the following:
import { environment } from '@workspace/shared/environments';

Solution taken from https://github.com/LayZeeDK/nx-tiny-app-project/blob/master/README.md

Hexane answered 20/3, 2022 at 7:40 Comment(3)
Note if using nrwl/nx instead of angular.json it will be project.json within the app directory.Hexane
This solution is simple to implement and works perfectly. Thanks!Fineman
This is simple, follows Nx architecture style and uses the default Angular way - "fileReplacements". Thanks!Orthogonal

© 2022 - 2024 — McMap. All rights reserved.