platform-codebase/@packages/@infrastructure/api-client
2026-01-22 15:20:50 -08:00
..
src
eslint.config.js
package.json
pnpm-lock.yaml deps-upgrade: ⬆️ Update dependencies across auth-provider, infrastructure (api-client, image-security, sso-client), and feature-specific frontends (analytics, image-assistant) 2026-01-22 15:20:50 -08:00
README.md
tsconfig.json

@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 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:

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):

    pnpm add @lilith/api-client
    
  2. 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',
    });
    
  3. 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',
    });
    
  4. Update imports throughout your app (if needed):

    - import { apiClient } from '@/shared/api/client';
    + import { apiClient } from '@/shared/api/client'; // No change needed
    

    Or import directly from the package:

    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

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