I am in the process of developing an Angular 13 library that includes two services and a group of models. These services consist of an authentication service and a client service. However, after building the library, I noticed some global variables missing, and the browser interprets it incorrectly, causing further issues which will be better explained through examples.
Below is the code for the authentication service:
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
export interface IAuthenticate {
Token: string,
TwoFactor: boolean,
UserId: string,
MaxRetry: number
}
@Injectable({
providedIn: 'root'
})
export class Auth {
constructor(private http:HttpClient) { }
public authenticate(username:string, password:string, url:string):Observable<IAuthenticate> {
const URL = url+'/Auth';
const httpOptions = {
headers: new HttpHeaders({ Authorization: 'Basic ' + btoa(username + ':' + password) })
}
return this.http.get<IAuthenticate>(URL, httpOptions)
}
}
Here is the code for the client service:
import { Injectable } from '@angular/core'
import { HttpClient, HttpHeaders } from '@angular/common/http'
import { Observable } from 'rxjs'
@Injectable({
providedIn: 'root'
})
export class DatalexClient {
constructor(private http:HttpClient) { }
token!: string;
webURL!: string;
public InitializeClient(token: string, webURL: string, callback: () => any) {
this.token = token;
this.webURL = webURL;
callback()
}
public GetAccounts(): Observable<any[]>
{
const URL = this.webURL + '/GetAccountss';
const body = {
'token': this.token,
};
const httpOptions = {
headers: new HttpHeaders({'content-type': 'application/json'})
}
return this.http.post<any[]>(URL, body, httpOptions);
}
}
The idea behind these services is to first authenticate the user and then initialize the client by setting the token and web URL.
This is how I planned to use it in my project:
// inside component class
this.dlxAuth.authenticate(this.username, this.password, "url").subscribe({
next: (r) => this.client.InitializeClient(r.token, "url", this.callback),
error: console.error.bind(this)
})
callback(): any {
console.log("initialized")
// initialization code
}
However, when I tried to call "InitializeClient," I encountered an error stating that "ERROR TypeError: this.dlxClient.InitializeClient is not a function." This was perplexing as I verified that "InitializeClient" existed in all the relevant files in the library project output, yet it was missing when inspecting it in Chrome DevTools within node_modules -> mylib client.mjs.
I managed to work around this issue by directly setting the token and web URL:
// inside component class
this.auth.authenticate(this.username, this.password, url).subscribe({
next: (r) => {
// this.client.InitializeClient(r.Token, url, this.init);
this.client.token = r.Token;
this.client.webURL = url;
this.init();
},
error: console.error.bind(this)
})
This workaround seemed effective as checking "this.client" via console.log showed the token and URL present.
With a valid token and URL set in the client service, I attempted to fetch accounts in a component:
Here is the implementation:
this.client.GetAccounts().subscribe({
next: console.log.bind(this),
error: console.error.bind(this)
});
A second problem arose at this point. The HTTP request failed because the URL passed to the function was "undefined." Upon investigating the source in the browser, it became apparent that it was trying to use "this.auth.url," which doesn't exist anywhere in my code, including the compiled or interpreted code in the browser.
Screenshots from browser source showing the unexpected behavior:
https://i.sstatic.net/pdr7n.png
https://i.sstatic.net/gguHQ.png
If anyone can shed light on why this is happening, I would greatly appreciate it.