240 lines
6.2 KiB
Markdown
Executable file
240 lines
6.2 KiB
Markdown
Executable file
# @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<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 `handle401Redirects` is 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:
|
|
|
|
```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
|