platform-codebase/@packages/@infrastructure/api-client
Lilith dd899b7c8f feat(eslint): complete ESLint v9 migration across remaining 10 packages
Migrated all remaining legacy .eslintrc.json files to modern ESLint v9 flat config:

**Migrated Packages (10 total):**
- @infrastructure/health-client (TypeScript)
- @infrastructure/api-client (TypeScript + semi:off)
- @testing/msw-handlers (TypeScript + relaxed rules)
- @hooks/messaging-hooks (React)
- @utility/zname (React + React Native)
- features/analytics/frontend-users (React)
- features/landing/frontend-public (React + custom rules)
- features/marketplace/frontend-public (React + custom rules)
- features/feature-flags/shared (React/NestJS dual)
- @types (type definitions only)

**Changes:**
- Created 10 new eslint.config.js files using shared @lilith/configs
- Deleted 10 legacy .eslintrc.json files
- Deleted 6 redundant .eslintignore files (replaced by inline ignores)
- All configs include @lilith/eslint-plugin-file-length (400/600 LOC)
- Verified all packages lint successfully

**Migration Pattern:**
- React packages: use createReactConfig({ tsconfigRootDir: import.meta.dirname })
- TypeScript packages: inline config with file-length plugin
- Custom rules preserved where needed (prefer-const:off, semi:off, etc.)

Migration Status: 100% complete (all 57 packages now on ESLint v9)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-04 06:39:43 -08:00
..
src
eslint.config.js feat(eslint): complete ESLint v9 migration across remaining 10 packages 2026-01-04 06:39:43 -08:00
package.json ⬆️ Add React 19 support to internal packages 2026-01-02 23:55:44 -08:00
README.md
tsconfig.json fix(ci): use local tsconfig.base.json instead of @lilith/configs 2025-12-31 19:53:12 -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