Skip to main content

Global Client Configuration

To configure the API client globally for your application, you must modify the OpenAPI singleton instance. This configuration controls the base URL, authentication tokens, and request/response interceptors for all generated services.

Basic Configuration

The most common setup involves setting the BASE URL and a dynamic TOKEN resolver. This is typically done in the application entry point, such as frontend/src/main.tsx.

import { OpenAPI } from "./client"

// Set the base URL from environment variables
OpenAPI.BASE = import.meta.env.VITE_API_URL

// Configure a dynamic token resolver
OpenAPI.TOKEN = async () => {
return localStorage.getItem("access_token") || ""
}

Key Configuration Properties

The OpenAPI object is an instance of OpenAPIConfig defined in frontend/src/client/core/OpenAPI.ts. Key properties include:

  • BASE: The root URL for all API requests.
  • TOKEN: Can be a static string or a Resolver<string>. If a function is provided, it is executed before every request.
  • HEADERS: A Record<string, string> or a Resolver<Headers> for adding global HTTP headers.
  • WITH_CREDENTIALS: A boolean indicating whether to include cookies in cross-site requests.

Using Resolvers for Dynamic Values

The Resolver<T> type allows you to provide values that are determined at runtime, such as authentication tokens stored in localStorage.

import { OpenAPI, type Resolver } from "./client/core/OpenAPI"

// Example of a custom header resolver
OpenAPI.HEADERS = async (options) => {
return {
'X-Custom-Header': 'custom-value',
'X-Request-ID': crypto.randomUUID(),
}
}

The Resolver function receives ApiRequestOptions as an argument, which contains details about the specific request being made, allowing for conditional logic based on the endpoint or method.

Request and Response Interceptors

You can use the interceptors property to register middleware that transforms Axios request configurations or responses. This is useful for logging, global error handling, or modifying request payloads.

Adding a Request Interceptor

import { OpenAPI } from "./client"

OpenAPI.interceptors.request.use((config) => {
console.log(`Starting request to: ${config.url}`)
return config
})

Adding a Response Interceptor

import { OpenAPI } from "./client"

OpenAPI.interceptors.response.use((response) => {
// Modify the response data before it reaches the service
if (response.data?.data) {
return response.data.data
}
return response
})

Interceptors are managed by the Interceptors<T> class in frontend/src/client/core/OpenAPI.ts, which provides use() to add and eject() to remove middleware.

Troubleshooting

Singleton Scope

The OpenAPI object is a global singleton. Any changes made to it will persist for the lifetime of the application and affect every service call (e.g., ItemsService, UsersService). If you need to change configuration for a specific test or environment, ensure you reset or update the OpenAPI object accordingly.

Async Resolution

When using a Resolver for TOKEN or HEADERS, the client will await the result before sending the request. If your resolver is slow (e.g., waiting for a refresh token), it will delay every API call. Ensure your resolvers are optimized and handle errors gracefully.

Environment Variables

If OpenAPI.BASE is undefined or incorrect, verify that VITE_API_URL is correctly set in your .env file and that you are using import.meta.env to access it in a Vite environment.