dotenv-run icon indicating copy to clipboard operation
dotenv-run copied to clipboard

Usage in app.config.ts for standalone components

Open facusantillo opened this issue 1 year ago • 7 comments

I have followed the entire documentation without success.

My angular application can't solve the environment variables from import.meta.env in my app.config.ts file.

The error in the console is:

TypeError: Cannot read properties of undefined (reading 'NG_APP_CLIENT_ID')
    at Object.useFactory (app.config.ts:57:21)
    at Object.factory (core.mjs:9553:38)
    at core.mjs:9454:43
    at runInInjectorProfilerContext (core.mjs:798:9)
    at R3Injector.hydrate (core.mjs:9453:17)
    at R3Injector.get (core.mjs:9323:33)
    at injectInjectorOnly (core.mjs:842:40)
    at ɵɵinject (core.mjs:848:60)
    at injectArgs (core.mjs:977:23)
    at Object.factory (core.mjs:9553:52)

I have created a env.d.ts file in the /src folder like this:

declare interface Env {
  readonly NODE_ENV: string;
  NG_APP_CLIENT_ID: string;
  NG_APP_CLIENT_SECRET: string;
  NG_APP_ENDPOINT: string;
  NG_APP_REDIRECT_URI: string;
  NG_APP_API_URL: string;
  [key: string]: any;
}

declare interface ImportMeta {
  readonly env: Env;
}

I have at root level a .env file that has all the information.

The I'm trying to setup my provider reading the configuration from the environment variables without success:

 {
      provide: NB_AUTH_OPTIONS,
      useFactory: () => {
        console.log(import.meta.env.NG_APP_CLIENT_ID);
        return {
          strategies: [AzureADB2CAuthStrategy.setup({
            name: 'azure',
            clientId: import.meta.env.NG_APP_CLIENT_ID,
            clientSecret: import.meta.env.NG_APP_CLIENT_SECRET,
            authorize: {
              endpoint: import.meta.env.NG_APPE_ENDPOINT,
              responseType: 'id_token',
              scope: 'openid',
              redirectUri: import.meta.env.NG_APP_REDIRECT_URI,
              params: {
                nonce: 'default_nonce'
              },
            },
            token: {
              class: AuthAzureToken,
            },
            redirect: {
              success: '/',
            },
          })],
          forms: {}
        };
      }

What am I doing wrong?

facusantillo avatar Aug 01 '24 15:08 facusantillo

did you ng add @ngx-env/builder or just installed it using npm?

chihab avatar Aug 01 '24 15:08 chihab

I did the ng add @ngx-env/builder, I tested and the only place where I can't use the envs are in the app.config.ts.

Maybe I'm missing a step while bootstraping the application?

facusantillo avatar Aug 01 '24 16:08 facusantillo

npm create @angular ng-app-18
cd ng-app-18 && npx ng add @ngx-env/builder
# add `console.log(import.meta.env.NODE_ENV)` to app.config.ts
NODE_ENV=dev npm start

You should see dev displayed in the console.

If you get a different result, could you please share a repo or a stackbliz?

chihab avatar Aug 02 '24 08:08 chihab

It will work in that example because the configuration has been already initialized.

Please, can you add this to your app.config.ts? You should see an exception when trying to access the environment from there.

import { APP_INITIALIZER, ApplicationConfig, Injectable, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { Observable, of } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ConfigService {
  private config: any;

  loadConfig(): Observable<any> {
    this.config = {
      ENVIRONMENT: import.meta.env.NODE_ENV,

    };
    return of(this.config);
  }

  get(key: string): string | undefined {
    return this.config[key];
  }
}

export function initializeApp(configService: ConfigService) {
  return (): Observable<void> => {
    console.log(configService.get('ENVIRONMENT'))
    return configService.loadConfig();
  };
}

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes),
    {
      provide: APP_INITIALIZER,
      useFactory: initializeApp,
      deps: [ConfigService],
      multi: true
    },
  ],
};

facusantillo avatar Aug 02 '24 12:08 facusantillo

UPDATE

@chihab I completely missed that in my angular I wasn't configuring the regex for the environment variables, nor was I initializing with the loadConfig() first. I knew I was missing something!

The only thing I can't make it work now is the runtime=true in the config.

The documentation says that should create a js file in my dist folder with all my environment variables.

But the ngx-env.js it's not being created.

Here is my angular json:

"ngxEnv": {
              "verbose": true,
              "runtime": true,
              "root": "../..",
              "prefix": "^SITHSYNC_"
            },

If y put the runtime=false, everything works fine by using the .env variables

facusantillo avatar Aug 02 '24 14:08 facusantillo

UPDATE II

I found the issue is reproducible when the type is

"builder": "@ngx-env/builder:browser"

Instead of

"builder": "@ngx-env/builder:application",

facusantillo avatar Aug 02 '24 15:08 facusantillo

UPDATE II

I found the issue is reproducible when the type is

"builder": "@ngx-env/builder:browser"

Instead of

"builder": "@ngx-env/builder:application",

@facusantillo, did you ever resolve this? I have the same issue.

chwalker-fadv avatar Sep 09 '24 11:09 chwalker-fadv

is it possible that it has been implemented only for esbuild and not for webpack?

Because I have the same issue using @ngx-env/builder:browser, and I found ngx-env.js related code only in the esbuild part of the project

maybe that "experimental" tag about that feature is a reference to "esbuild" (??)

bitbangx avatar Nov 07 '24 17:11 bitbangx

You're right @bitbangx, for now, the runtime option has only been implemented for application and browser-esbuild builders.

Update: Webpack support is soon to be added (next release v19)

chihab avatar Nov 07 '24 18:11 chihab

v19 published, feel free to give it a try.

chihab avatar Nov 21 '24 14:11 chihab