The TokenService and the TokenInterceptor have been added to the ngx-simple-charts library to be used in the AngularAndSpring and the AngularPortfolioMgr projects. The feature has its own entry point to make sure Angular includes the code only in projects that use this entry point.

Module with forRoot to take the parameters

The NgxServiceModule provides the forRoot method to get config values:

@NgModule({
  imports: [CommonModule, RouterModule],
})
export class NgxServiceModule {
  static forRoot(
    config: SimpleChartsConfig
  ): ModuleWithProviders<NgxServiceModule> {
    return {
      ngModule: NgxServiceModule,
      providers: [
        TokenService,
        { provide: MODULE_CONFIG, useValue: config },
        {
          provide: HTTP_INTERCEPTORS,
          useClass: TokenInterceptor,
          multi: true,
        },
      ],
    };
  }
}

The NgxServiceModule provides the forRoot(…) method to enable the module user to provide the required config values in the SimpleChartsConfig interface. The method returns the module with the providers that include the TokenService, the ‘MODULE_CONFIG’ for the config values and the ‘HTTP_INTERCEPTORS’ that include the TokenInterceptor.

Config values in the TokenService

The TokenService injects the SimpleChartsConfig values with the ‘MODULE_CONFIG’:

@Injectable()
export class TokenService {
  private myTokenCache!: Observable<RefreshTokenResponse>;
  private readonly CACHE_SIZE = 1;
  private readonly REFRESH_INTERVAL = 45000; //45 sec
  private myToken!: string;
  private myUserId!: number | string;
  private myTokenSubscription!: Subscription;
  private stopTimer!: Subject<boolean>;
  public secUntilNextLogin = 0;

  constructor(
    private http: HttpClient,
    private router: Router,
    @Inject(MODULE_CONFIG) private moduleConfig: SimpleChartsConfig
  ) {}

  private refreshToken(): Observable<RefreshTokenResponse> {
    const path = !this.moduleConfig?.tokenRefreshPath
      ? '/rest/auth/refreshToken'
      : this.moduleConfig?.tokenRefreshPath;
    return this.http.get<RefreshTokenResponse>(path, {
      headers: this.createTokenHeader(),
    });
  }
...
}

The TokenService is a injectable service that injects the SimpleChartsConfig in the constructor with the ‘MODULE_CONFIG’ of the module.

The ‘moduleConfig’ property is used in the ‘refreshToken()’ method. It is checked if the ‘tokenRefreshPath’ is available and then it is used for http token refresh requests.

The other config values are used in a similar manner in the methods ‘logout()’ and ‘clear()’.

Using the library services

The AngularPortfolioMgr project uses the library services for the token handling. To do that the library services have to be included and configured in the AppModule:

import { NgxServiceModule,SimpleChartsConfig } from 'ngx-simple-charts/base-service';

@NgModule({
  declarations: [
    AppComponent,
    SpinnerComponent    
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    AppRoutingModule,
    MatProgressSpinnerModule,
    BrowserAnimationsModule,
    NgxServiceModule.forRoot({tokenRefreshPath: '/rest/auth/refreshToken', 
       logoutPath: '/rest/auth/logout', loginRoute: '/login'})
  ],  
  bootstrap: [AppComponent]
})
export class AppModule { }

The AppModule imports the NgxServiceModule and the SimpleChartsConfig for the import.

The NgxServiceModule is imported with the ‘forRoot(…)’ method that provides a object with the config values that are specified in the SimpleChartsConfig interface.

The NgxServiceModule then provides the TokenService and configures the ‘HTTP_PROVIDERS’ to include the TokenInterceptor for the AppModule.

Services in child modules

The PortfoliosModule provides 2 services. The TokenService is available for injection. The TokenInterceptor needs to be configured for the 2 services:

@NgModule({
    declarations: [OverviewComponent, 
...
       PortfolioSectorsComponent],
    imports: [
        BaseModule,
...
        PortfoliosRoutingModule,
    ],
    providers: [DevAppInfoService, ProdAppInfoService, 
       { provide: HTTP_INTERCEPTORS, 
         useClass: TokenInterceptor, multi: true }]
})
export class PortfoliosModule { }

The PortfoliosModule declares the 2 services in ‘providers’ and adds the TokenInterceptor to the ‘HTTP_INTERCEPTORS’. The TokenInterceptor gets the TokenService of the AppModule injected.

Conclusion

The Angular support for multiple entry points is very valuable. The config values can be supplied with a ‘forRoot(…)’ method. That enables configurable services and components in libraries. Services for central/common services can be provided by a library where the endpoints to use can be configured.