Added openapi based api client
This commit is contained in:
94
apps/frontend/app/lib/api.ts
Normal file
94
apps/frontend/app/lib/api.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import type { AxiosInstance, AxiosResponse } from 'axios';
|
||||
import { type Fetcher, type Method, createApiClient } from '../generated/api-client';
|
||||
import { TanstackQueryApiClient } from '../generated/tanstack-client';
|
||||
|
||||
const API_BASE_URL: string | undefined = import.meta.env.VITE_API_BASE_URL;
|
||||
|
||||
const get_fetch: (axios: AxiosInstance) => Fetcher['fetch'] =
|
||||
(axios) =>
|
||||
async ({ method, url: incomingUrl, parameters: params }) => {
|
||||
// Use a plain object for Axios headers
|
||||
const headers: Record<string, string> = {};
|
||||
|
||||
// Replace path parameters (supports both {param} and :param formats)
|
||||
const actualUrl = replacePathParams(incomingUrl.toString(), (params?.path ?? {}) as Record<string, string>);
|
||||
const url = new URL(actualUrl);
|
||||
|
||||
// Handle query parameters
|
||||
if (params?.query) {
|
||||
const searchParams = new URLSearchParams();
|
||||
Object.entries(params.query).forEach(([key, value]) => {
|
||||
if (value != null) {
|
||||
// Skip null/undefined values
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach((val) => val != null && searchParams.append(key, String(val)));
|
||||
} else {
|
||||
searchParams.append(key, String(value));
|
||||
}
|
||||
}
|
||||
});
|
||||
url.search = searchParams.toString();
|
||||
}
|
||||
|
||||
// Handle request body for mutation methods (use Axios `data`)
|
||||
const data = (['post', 'put', 'patch', 'delete'] satisfies Method[] as string[]).includes(method.toLowerCase()) ? params?.body : undefined;
|
||||
|
||||
if (data != null) {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
// Add custom headers
|
||||
if (params?.header) {
|
||||
Object.entries(params.header).forEach(([key, value]) => {
|
||||
if (value != null) {
|
||||
headers[key] = String(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const response = await axios(url.toString(), {
|
||||
method: method.toUpperCase(),
|
||||
...(data !== undefined && { data }),
|
||||
headers: headers,
|
||||
});
|
||||
|
||||
return axiosResponseToFetchResponse(response);
|
||||
};
|
||||
|
||||
function axiosResponseToFetchResponse(response: AxiosResponse): Response {
|
||||
const headers = new Headers();
|
||||
Object.entries(response.headers).forEach(([key, value]) => {
|
||||
if (Array.isArray(value)) {
|
||||
value.forEach((val) => headers.append(key, val));
|
||||
} else {
|
||||
headers.append(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return new Response(response.data, {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
headers: headers,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace path parameters in URL
|
||||
* Supports both OpenAPI format {param} and Express format :param
|
||||
*/
|
||||
function replacePathParams(url: string, params: Record<string, string>): string {
|
||||
return url.replace(/{(\w+)}/g, (_, key: string) => params[key] || `{${key}}`).replace(/:([a-zA-Z0-9_]+)/g, (_, key: string) => params[key] || `:${key}`);
|
||||
}
|
||||
|
||||
export function createApi(axios: AxiosInstance) {
|
||||
return createApiClient(
|
||||
{
|
||||
fetch: get_fetch(axios),
|
||||
},
|
||||
API_BASE_URL ?? window.location.origin
|
||||
);
|
||||
}
|
||||
|
||||
export function createTanstackApi(axios: AxiosInstance) {
|
||||
return new TanstackQueryApiClient(createApi(axios));
|
||||
}
|
||||
Reference in New Issue
Block a user