Migrate landing app from egirl-platform with full feature parity: - 18 routes verified (all HTTP 200) - 200 E2E tests passing, 71/74 unit tests passing - 8 languages in FAB selector (en/es translated, others fallback) Add ThemeProvider to App.tsx for styled-components theme context. Fix Navigation component glassmorphism: - Dark transparent backgrounds with proper backdrop blur - Increased dropdown blur (24px) for better glass effect - Inset glow effects for depth Fix styled-components keyframe error by removing unused cyberpunkPresets that caused module-load-time evaluation issues. Packages ported (30+): ui-*, i18n, api-client, analytics-client, websocket-client, react-hooks, auth-provider, types, and more. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
6.2 KiB
@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:
pnpm add @lilith/api-client
Usage
Basic Usage
Create a simple API client with default configuration:
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:
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:
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<string, string> - 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
handle401Redirectsis true)
onRequest
- Type:
(config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig> - Default:
undefined - Description: Custom request interceptor (runs before token injection)
onResponseError
- Type:
(error: AxiosError) => Promise<never> - Default:
undefined - Description: Custom response error interceptor (runs before 401 handler)
TypeScript Support
Full TypeScript support with axios types:
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:
-
Install the package (if not already in
package.json):pnpm add @lilith/api-client -
Replace your local client with the shared one:
Before (
@apps/{app}/src/shared/api/client.ts):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):import { createApiClient } from '@lilith/api-client'; export const apiClient = createApiClient({ baseURL: import.meta.env.VITE_API_URL || '/api', tokenStorageKey: 'auth_token', }); -
If you have 401 handling, enable the config option:
export const apiClient = createApiClient({ baseURL: import.meta.env.VITE_API_URL || 'http://localhost:4000/api', tokenStorageKey: 'accessToken', handle401Redirects: true, loginRoute: '/login', }); -
Update imports throughout your app (if needed):
- import { apiClient } from '@/shared/api/client'; + import { apiClient } from '@/shared/api/client'; // No change neededOr import directly from the package:
import { createApiClient } from '@lilith/api-client'; -
Remove axios from your app's dependencies (optional): Since
@lilith/api-clientalready depends on axios, you can remove it from your app'spackage.jsonif 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
export const apiClient = createApiClient({
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:4000/api',
tokenStorageKey: 'accessToken',
handle401Redirects: true,
});
Storefront Config
export const apiClient = createApiClient({
baseURL: import.meta.env.VITE_API_URL || '/api',
tokenStorageKey: 'auth_token',
});
Broadcast Studio Config
export const apiClient = createApiClient({
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:4000',
tokenStorageKey: 'auth_token',
});
License
Private - Internal use only