53 lines
2.1 KiB
TypeScript
53 lines
2.1 KiB
TypeScript
import { createHttpClient } from '@repo/core-api/http-client';
|
|
import { faroAdapter } from '@repo/core-api/observability';
|
|
import { ENV } from '../environment';
|
|
import { AppDatabaseKey, AppStorageKey, appDatabase, appStorage } from '../storage/local';
|
|
import { terminateAuthSession } from './auth.helper';
|
|
|
|
/**
|
|
* Enterprise HTTP client for `apps/web`.
|
|
*
|
|
* - Full Faro observability via the shared `faroAdapter`
|
|
* - Automatic Bearer token injection from localStorage
|
|
* - 401 redirect to `/auth/login`
|
|
* - Supports per-request `telemetryContext` for custom spans/tags
|
|
*
|
|
* All interceptors (auth, observability, error normalization)
|
|
* are baked into this instance. Import this singleton throughout
|
|
* the web application — never create raw axios instances.
|
|
*/
|
|
export const apiClient = createHttpClient(
|
|
{
|
|
baseURL: ENV.API_BASE_URL,
|
|
timeout: 15000,
|
|
observability: faroAdapter,
|
|
},
|
|
{
|
|
// ── Auth Interceptor ──────────────────────────────────────────
|
|
onRequest: async (config) => {
|
|
config.headers['ex-app-name'] = ENV.APP_NAME;
|
|
config.headers['ex-app-version'] = ENV.APP_VERSION;
|
|
config.headers['ex-timezone-offset-minutes'] = new Date().getTimezoneOffset();
|
|
config.headers['ex-timezone-offset-hours'] = Math.floor(new Date().getTimezoneOffset() / 60);
|
|
|
|
const language = await appStorage.getItem<string>(AppStorageKey.LANGUAGE);
|
|
config.headers['ex-language'] = language ?? ENV.DEFAULT_LANGUAGE;
|
|
|
|
const token = await appDatabase.getItem<string>(AppDatabaseKey.ACCESS_TOKEN);
|
|
if (token) config.headers.Authorization = `Bearer ${token}`;
|
|
|
|
return config;
|
|
},
|
|
|
|
// ── Error Interceptor ─────────────────────────────────────────
|
|
onResponseError: async (error) => {
|
|
const status = error.response?.status;
|
|
|
|
// Catch 401 (Unauthorized) on request
|
|
if (status === 401) if (status === 401) await terminateAuthSession({ preserveRedirect: true });
|
|
|
|
throw error;
|
|
},
|
|
},
|
|
);
|