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.