platform-codebase/@packages/@infrastructure/api-client
Quinn Ftw 84d1333284 feat(landing): complete migration with glassmorphism navigation
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>
2025-12-26 17:11:07 -08:00
..
src feat(landing): complete migration with glassmorphism navigation 2025-12-26 17:11:07 -08:00
.eslintignore feat(landing): complete migration with glassmorphism navigation 2025-12-26 17:11:07 -08:00
.eslintrc.json feat(landing): complete migration with glassmorphism navigation 2025-12-26 17:11:07 -08:00
package.json feat(landing): complete migration with glassmorphism navigation 2025-12-26 17:11:07 -08:00
README.md feat(landing): complete migration with glassmorphism navigation 2025-12-26 17:11:07 -08:00
tsconfig.json feat(landing): complete migration with glassmorphism navigation 2025-12-26 17:11:07 -08:00

@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