I have a BaseRepository
abstract class in my code which contains client instance and some general functions. The AuthRepository
class inherits from BaseRepository
. And I have an AuthService
module which uses AuthRepository
to login and/or check login status. When I open a route I send a request to my API. I use AuthService
to check and get token for authorization in client request interceptor. If I can get token for request I add it to headers and continue with request. If I cannot I redirect to login page to login again. It works fine when I first login from my login page and continue using web app but I get the error "ReferenceError: can't access lexical declaration 'BaseRepository' before initialization" if I refresh the page.
BaseRepository
import { BackendClient } from "@/repositories/clients";
import type { AxiosError, AxiosInstance, AxiosResponse } from "axios";
// other imports
export default abstract class BaseRepository {
protected readonly client: AxiosInstance = BackendClient;
// general functions
}
AuthRepository
import { BaseRepository } from "@/repositories/base";
class AuthRepository extends BaseRepository {
constructor() {
super()
}
// other functions
}
const authRepository = new AuthRepository();
export default authRepository;
Axios client
import axios, { type AxiosInstance } from "axios";
import { AuthService } from "@/modules/auth";
import router from "@/router";
import appConfig from "@/config";
const client: AxiosInstance = axios.create({
baseURL: appConfig.backendClient.baseUrl,
headers: {
"Access-Control-Allow-Origin": "*",
},
validateStatus: (status: number): boolean => {
var isValid = (status < 400 || status == 401);
console.log("requestvalidatestatus", isValid);
return isValid;
}
})
const TOKEN_EXCLUDE_ENDPOINTS = [
'Auth/Login',
'Auth/Register',
'Auth/RefreshAccessToken'
]
client.interceptors.request.use(async (config) => {
var requestUrl = config.url;
for(var excludeEndpoint of TOKEN_EXCLUDE_ENDPOINTS) {
if(requestUrl?.startsWith(excludeEndpoint)){
return config;
}
}
var token = await AuthService.getAccessToken();
if(!token) {
router.push('/login');
}
console.log("token",token);
config.headers.Authorization = `Bearer ${token}`;
return config;
})
export default client;
AuthService
import { AuthRepository } from "@/repositories";
class AuthService {
async login(request: LoginRequest, rememberMe: boolean, forceLogin: boolean = false) {
// other logic
return await AuthRepository.login(request);
}
// other functions
}
const authService = new AuthService();
export default authService;
What might be the problem here?
It was a circular dependency issue. I solved it by implementing request interceptor in main.ts.
main.ts
import { BackendClient } from './repositories/clients'
import { AuthService } from './modules/auth'
const TOKEN_EXCLUDE_ENDPOINTS = [
'Auth/Login',
'Auth/Register',
'Auth/RefreshAccessToken'
]
BackendClient.interceptors.request.use(async (config) => {
var requestUrl = config.url;
for (var excludeEndpoint of TOKEN_EXCLUDE_ENDPOINTS) { // Token istemeyen endpoint ise devam et
if (requestUrl?.startsWith(excludeEndpoint)) {
return config;
}
}
var token = await AuthService.getAccessToken();
if (!token) {
router.push('/login');
}
console.log("token", token);
config.headers.Authorization = `Bearer ${token}`;
return config;
})
BackendClient.ts
import axios, { type AxiosInstance } from "axios";
import appConfig from "@/config";
const client: AxiosInstance = axios.create({
baseURL: appConfig.backendClient.baseUrl,
headers: {
"Access-Control-Allow-Origin": "*",
},
validateStatus: (status: number): boolean => {
var isValid = (status < 400 || status == 401);
console.log("requestvalidatestatus", isValid);
return isValid;
}
})
export default client;