3

I have found a lot of resources on how to switch between using angular-in-memory-web-api or real API depending on the environment (dev or prod) but what I'm trying to do is quite different.

I want people to be able to try out the product without creating any account and by using in-memory-web-api so that anonymous users can't interact with the real API.

They would use a demo account with dummy data already available to play with and in their own isolated environment. I was thinking of injecting into services a real http service AND a one that uses in-memory-web-api (named mockAPI) and each service would rely on a UserService property to select which service to use (which would be at execution time, not compiling).

I'm learning Angular on my free time and I have no idea on how to inject two instances of the same service, with one being bypassed by in-memory-web-api.

How could it be done this way or is there a better way of solving this problem?

Thank you for your help.

user3803848
  • 179
  • 1
  • 13

1 Answers1

1

I've found a way of reaching my goal though I don't really like it :

So I still import HttpClientInMemoryWebApiModule in app.module.ts but I use the passThruUnknownUrl parameter, like so :

HttpClientInMemoryWebApiModule.forRoot(
  InMemoryDataService, { dataEncapsulation: false, passThruUnknownUrl: true }
)

The passThruUnknownUrl allows the HttpClient to send request to the real API for paths not declared in the object returned by CreateDb method, so the solution here is to give different names for mocked paths.

export class InMemoryDataService implements InMemoryDbService {
  createDb() {
    const ACCOUNTS = [
      { id: 11, name: 'BOC' },
      { id: 12, name: 'CCB' },
      { id: 13, name: 'HSBC' }
    ];

    return {mock_accounts: ACCOUNTS};
  }
}

InMemoryWebApi will send me the dummy data if I call the mock_accounts path. I then create a getApi method on the user service :

private apiUrl = 'api/';
private mockApiUrl = 'api/mock_';
getApi() {
  return this.loggedInUser === 'demo' ? this.mockApiUrl : this.apiUrl;
}

And return a different base path whether the logged in user is demo or not. Then in my account service I make the calls as follows:

private accountsPath = 'accounts';
getAccounts(): Observable<Account[]> {
  this.log('AccountService: fetched accounts');
  return this.http.get<Account[]>(this.userService.getApi() + this.accountsPath).pipe(
    tap(_ => this.log('fetched accounts')),
    catchError(this.handleError('getAccounts', []))
  );
}

For real users the call for retrieving user accounts will go to api/accounts whereas for demo user it will go to api/mock_accounts which will be intercepted by InMemoryWebApi.

It works but I'm not satisfied with this approach, if anyone knows a better solution I'd be glad to hear about it.

user3803848
  • 179
  • 1
  • 13