Refactor API hooks to remove infinite query support and update API client base URL

- Removed infinite query options and related functions from Trading212, User Registration, and User API files.
- Updated API client base URLs in privateClient.ts and publicClient.ts to use environment variable for backend URL.
- Refactored Downloader component to directly call API functions for video info retrieval instead of using a hook.
This commit is contained in:
2025-12-21 16:37:56 +01:00
parent 9c48aee522
commit abc6207296
18 changed files with 149 additions and 6300 deletions

View File

@@ -107,12 +107,108 @@ Notes
- **Task queue**: Celery + Redis for async/background jobs.
- **API**: REST endpoints, JWT auth, API key support.
### OpenAPI Client Generation
- Schema: `config = { schemaUrl: "/api/schema/", baseUrl: "/api/" }`
- Commands: `npm run api:update` (fetch schema + generate client)
- Output: `frontend/src/api/generated/` (TypeScript Axios client)
- Axios instance: `frontend/src/api/api.ts` with `withCredentials` and JWT auto-refresh via existing `Client.ts`.
- Choices helper: `frontend/src/api/get_choices.ts``getChoices(requests, lang)` returns `{ "Model.field": [{ value, label }] }`.
### OpenAPI Client Generation (Orval)
This project uses **Orval** to auto-generate TypeScript API clients from the Django OpenAPI schema.
#### Configuration
- **Orval config**: `frontend/src/orval.config.ts`
- **Schema URL**: `/api/schema/` (DRF Spectacular endpoint)
- **Fetch script**: `frontend/scripts/fetch-openapi.js`
- **Commands**:
- `npm run api:update` — fetches schema + generates client
- Runs: `node scripts/fetch-openapi.js && npx orval`
#### Generated Output
- **Location**: `frontend/src/api/generated/`
- **Files**: TypeScript interfaces, Axios-based API hooks
- Uses custom mutators: `publicMutator` and `privateMutator`
#### Custom Mutators
Two Axios clients handle public/private API requests:
**Public Client** (`frontend/src/api/publicClient.ts`):
```ts
import axios, { type AxiosRequestConfig } from "axios";
const backendUrl = import.meta.env.VITE_BACKEND_URL || "http://localhost:8000";
export const publicApi = axios.create({
baseURL: backendUrl + "/api/",
withCredentials: false, // no cookies for public endpoints
});
export const publicMutator = async <T>(config: AxiosRequestConfig): Promise<T> => {
const response = await publicApi.request<T>(config);
return response.data;
};
```
**Private Client** (`frontend/src/api/privateClient.ts`):
```ts
import axios, { type AxiosRequestConfig } from "axios";
const backendUrl = import.meta.env.VITE_BACKEND_URL || "http://localhost:8000";
export const privateApi = axios.create({
baseURL: backendUrl + "/api/",
withCredentials: true, // sends HttpOnly cookies (access/refresh tokens)
});
// Auto-refresh on 401
privateApi.interceptors.response.use(
(res) => res,
async (error) => {
const original = error.config;
if (error.response?.status === 401 && !original._retry) {
original._retry = true;
try {
await privateApi.post("/auth/refresh/");
return privateApi(original);
} catch {
// optional: logout
}
}
return Promise.reject(error);
}
);
export const privateMutator = async <T>(config: AxiosRequestConfig): Promise<T> => {
const response = await privateApi.request<T>(config);
return response.data;
};
```
#### Environment Variables (Vite)
- **IMPORTANT**: Use `import.meta.env.VITE_*` instead of `process.env` in browser code
- **NEVER** import `dotenv/config` in frontend files (causes "process is not defined" error)
- **Available vars**:
- `VITE_BACKEND_URL` (default: `http://localhost:8000`)
- `VITE_API_BASE_URL` (if using Client.ts wrapper)
- `VITE_API_REFRESH_URL` (default: `/api/token/refresh/`)
- `VITE_LOGIN_PATH` (default: `/login`)
#### Usage Example
```ts
import { useGetOrders } from "@/api/generated/orders";
function OrdersList() {
const { data, isLoading, error } = useGetOrders();
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data?.map(order => <li key={order.id}>{order.status}</li>)}
</ul>
);
}
```
#### Helpers
- **Choices helper**: `frontend/src/api/get_choices.ts`
- Function: `getChoices(requests, lang)`
- Returns: `{ "Model.field": [{ value, label }] }`
## References
- [frontend/REACT.md](../frontend/REACT.md): Frontend structure, workflows, and conventions.