Jeremy
Jeremy

Reputation: 3548

angular 4 static analysis fails for 'useValue' provider

I'm getting this error -

Error: Error: Error encountered resolving symbol values statically. Calling function 'SecurityModule', function calls are not supported. Consider replacing the function or lambda with a reference to an exported function ...

I've read that the function calls cannot be too complex for the static analyzer to process, but you can see this should be straight forward. I'm not sure why this fails.
I've looked at several examples of using the long-form provider objects, and from my understanding this should be acceptable.

Here is the project -
https://github.com/savantly-net/ngx-security

Any thoughts?

SecurityModule -

import { ISecurityService } from './ISecurity.service';
import { NgModule, ModuleWithProviders, Optional, SkipSelf, InjectionToken } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UserComponent } from './user/user.component';

export const SECURITY_SERVICE = new InjectionToken<ISecurityService>('security.service');

@NgModule({
  imports: [
    CommonModule
  ],
  exports: [ UserComponent ],
  declarations: [ UserComponent ]
})
export class SecurityModule {

  static forRoot(securityService: ISecurityService): ModuleWithProviders {
    return {
      ngModule: SecurityModule,
      providers: [{
        provide: SECURITY_SERVICE,
        useValue: securityService
      }]
    };
  }

  constructor (@Optional() @SkipSelf() parentModule: SecurityModule) {
    if (parentModule) {
      throw new Error(
        'SecurityModule is already loaded. Import it in the AppModule only');
    }
  }
}

AppModule -

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { SecurityModule, SecurityMockService } from '@savantly/ngx-security';

export const mockSecurity = new SecurityMockService();

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    SecurityModule.forRoot(mockSecurity)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

SecurityMockService -

@Injectable()
export class SecurityMockService implements ISecurityService {
  logout: () => void;
  login: (username: string, password: string) => boolean;
  user: IUser;

  constructor() {
    this.user = {
      principal: 'demoUser',
      displayName: 'Demo User',
      authenticated: false,
      roles: ['ADMIN', 'USER']
    };

    this.login = (_username: string, _password: string) => {
      this.user.authenticated = true;
      return true;
    };

    this.logout = () => {
      this.user.authenticated = false;
    };
  }
}

Upvotes: 2

Views: 305

Answers (3)

Jeremy
Jeremy

Reputation: 3548

In my case it turned out to be related to using the InjectionToken, rather than using "ISecurityService" as the provide value.

I'm not sure why this was an issue.
Unfortunately, I don't have time to dig further.

Upvotes: 0

chaosmonster
chaosmonster

Reputation: 46

Okay here is the easy fix:

Use SecurityModule.forRoot(new SecurityMockService()) instead of

export const mockSecurity = new SecurityMockService();
SecurityModule.forRoot(mockSecurity)

Here comes the but. You really should use useClass like Graham said, because that would leave the instantiation of your service to angular.

Upvotes: 1

Graham Fowles
Graham Fowles

Reputation: 449

If you're providing a class you should use 'useClass' instead of 'useValue'

Upvotes: 0

Related Questions