# @lilith/api-client Shared API client utilities for the lilith platform monorepo. ## Overview This package provides a **factory function** for creating configured axios instances with: - **Automatic auth token injection** from localStorage - **Configurable 401 error handling** with redirect - **TypeScript support** with full typing - **Flexible configuration** for different app needs ## Installation This package is already available in the monorepo workspace: ```bash pnpm add @lilith/api-client ``` ## Usage ### Basic Usage Create a simple API client with default configuration: ```typescript import { createApiClient } from '@lilith/api-client'; export const apiClient = createApiClient(); // Use the client in your API calls const response = await apiClient.get('/users'); const user = await apiClient.post('/users', { name: 'Quinn' }); ``` ### Custom Configuration Configure the client for your app's specific needs: ```typescript import { createApiClient } from '@lilith/api-client'; export const apiClient = createApiClient({ baseURL: import.meta.env.VITE_API_URL || 'http://localhost:4000/api', timeout: 10000, headers: { 'Content-Type': 'application/json', }, tokenStorageKey: 'auth_token', // or 'accessToken' handle401Redirects: true, loginRoute: '/login', }); ``` ### With Custom Interceptors Add custom logic for requests or errors: ```typescript import { createApiClient } from '@lilith/api-client'; export const apiClient = createApiClient({ onRequest: (config) => { // Add custom request logic (e.g., logging, headers) console.log('Making request to:', config.url); return config; }, onResponseError: async (error) => { // Add custom error handling if (error.response?.status === 403) { console.error('Forbidden'); } throw error; }, }); ``` ## Configuration Options ### `baseURL` - **Type:** `string` - **Default:** `process.env.VITE_API_URL || 'http://localhost:4000/api'` - **Description:** Base URL for all API requests ### `timeout` - **Type:** `number` - **Default:** `10000` - **Description:** Request timeout in milliseconds ### `headers` - **Type:** `Record` - **Default:** `{ 'Content-Type': 'application/json' }` - **Description:** Default headers included with every request ### `tokenStorageKey` - **Type:** `string` - **Default:** `'accessToken'` - **Description:** localStorage key for authentication token ### `handle401Redirects` - **Type:** `boolean` - **Default:** `false` - **Description:** Automatically clear token and redirect to login on 401 errors ### `loginRoute` - **Type:** `string` - **Default:** `'/login'` - **Description:** Login route for 401 redirects (only used if `handle401Redirects` is true) ### `onRequest` - **Type:** `(config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise` - **Default:** `undefined` - **Description:** Custom request interceptor (runs before token injection) ### `onResponseError` - **Type:** `(error: AxiosError) => Promise` - **Default:** `undefined` - **Description:** Custom response error interceptor (runs before 401 handler) ## TypeScript Support Full TypeScript support with axios types: ```typescript import { createApiClient, ApiClientConfig } from '@lilith/api-client'; import type { AxiosInstance } from 'axios'; const config: ApiClientConfig = { baseURL: 'https://api.example.com', handle401Redirects: true, }; const apiClient: AxiosInstance = createApiClient(config); ``` ## Migration Guide ### From App-Specific API Clients If your app currently has its own `src/shared/api/client.ts`: 1. **Install the package** (if not already in `package.json`): ```bash pnpm add @lilith/api-client ``` 2. **Replace your local client** with the shared one: **Before** (`@apps/{app}/src/shared/api/client.ts`): ```typescript import axios from 'axios'; export const apiClient = axios.create({ baseURL: import.meta.env.VITE_API_URL || '/api', timeout: 10000, }); apiClient.interceptors.request.use((config) => { const token = localStorage.getItem('auth_token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); ``` **After** (`@apps/{app}/src/shared/api/client.ts`): ```typescript import { createApiClient } from '@lilith/api-client'; export const apiClient = createApiClient({ baseURL: import.meta.env.VITE_API_URL || '/api', tokenStorageKey: 'auth_token', }); ``` 3. **If you have 401 handling**, enable the config option: ```typescript export const apiClient = createApiClient({ baseURL: import.meta.env.VITE_API_URL || 'http://localhost:4000/api', tokenStorageKey: 'accessToken', handle401Redirects: true, loginRoute: '/login', }); ``` 4. **Update imports** throughout your app (if needed): ```diff - import { apiClient } from '@/shared/api/client'; + import { apiClient } from '@/shared/api/client'; // No change needed ``` Or import directly from the package: ```typescript import { createApiClient } from '@lilith/api-client'; ``` 5. **Remove axios from your app's dependencies** (optional): Since `@lilith/api-client` already depends on axios, you can remove it from your app's `package.json` if you're not using it elsewhere. ## Benefits - **Consistency**: All apps use the same API client pattern - **Maintainability**: Update API client logic in one place - **Type Safety**: Full TypeScript support - **Flexibility**: Each app can configure as needed - **Reduced Boilerplate**: No need to rewrite interceptor logic ## Examples ### Channel Studio Config ```typescript export const apiClient = createApiClient({ baseURL: import.meta.env.VITE_API_URL || 'http://localhost:4000/api', tokenStorageKey: 'accessToken', handle401Redirects: true, }); ``` ### Storefront Config ```typescript export const apiClient = createApiClient({ baseURL: import.meta.env.VITE_API_URL || '/api', tokenStorageKey: 'auth_token', }); ``` ### Broadcast Studio Config ```typescript export const apiClient = createApiClient({ baseURL: import.meta.env.VITE_API_URL || 'http://localhost:4000', tokenStorageKey: 'auth_token', }); ``` ## License Private - Internal use only