Files
api-codegen/example-hooks.tsx
S.Gromov 15ed8c8b8d feat: инициализация API CodeGen
CLI утилита для генерации TypeScript API клиента из OpenAPI спецификации.
- Поддержка локальных файлов и URL для спецификаций
- Кастомизация имени выходного файла через флаг --name
- Генерация типизированного клиента с SWR хуками
- Минимальный вывод логов для лучшего UX
2025-10-26 22:30:58 +03:00

283 lines
7.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Примеры использования сгенерированных use* функций
* с SWR и React Query
*/
import { Api, HttpClient } from './output/Api';
import useSWR from 'swr';
import { useQuery } from '@tanstack/react-query';
// ============================================
// НАСТРОЙКА API КЛИЕНТА
// ============================================
const httpClient = new HttpClient({
baseUrl: 'https://cdn.example.com',
});
// Устанавливаем токен (например, из localStorage)
if (typeof window !== 'undefined') {
const token = localStorage.getItem('auth_token');
if (token) {
httpClient.setSecurityData({ token });
}
}
const api = new Api(httpClient);
// ============================================
// ПРИМЕР 1: ИСПОЛЬЗОВАНИЕ С SWR
// ============================================
// Простой GET запрос без параметров
function UserProfile() {
const profileConfig = api.auth.useGetProfile();
const { data, error, isLoading } = useSWR(
profileConfig.path, // Ключ для кеша
() => api.auth.getProfile() // Функция для загрузки данных
);
if (isLoading) return <div>Загрузка...</div>;
if (error) return <div>Ошибка: {error.message}</div>;
if (!data) return null;
return (
<div>
<h1>Профиль пользователя</h1>
<p>Email: {data.email}</p>
<p>Имя: {data.firstName} {data.lastName}</p>
<p>Email подтверждён: {data.isEmailVerified ? 'Да' : 'Нет'}</p>
</div>
);
}
// GET запрос с параметрами
function ProjectDetails({ projectId }: { projectId: string }) {
const projectConfig = api.projects.useFindOne({ id: projectId });
const { data: project, error, isLoading } = useSWR(
[projectConfig.path, projectId], // Составной ключ
() => api.projects.findOne({ id: projectId })
);
if (isLoading) return <div>Загрузка проекта...</div>;
if (error) return <div>Ошибка: {error.message}</div>;
if (!project) return null;
return (
<div>
<h2>{project.name}</h2>
<p>{project.description}</p>
<p>Bucket: {project.s3Bucket}</p>
<p>Region: {project.s3Region}</p>
</div>
);
}
// Список с автоматической ревалидацией
function ProjectsList() {
const projectsConfig = api.projects.useFindAll();
const { data: projects, error, isLoading, mutate } = useSWR(
projectsConfig.path,
() => api.projects.findAll(),
{
refreshInterval: 5000, // Обновлять каждые 5 секунд
revalidateOnFocus: true, // Обновлять при фокусе на окно
}
);
const handleCreateProject = async () => {
await api.projects.create({
name: 'Новый проект',
description: 'Описание',
});
// Обновляем список
mutate();
};
if (isLoading) return <div>Загрузка списка...</div>;
if (error) return <div>Ошибка: {error.message}</div>;
return (
<div>
<h2>Мои проекты ({projects?.length || 0})</h2>
<button onClick={handleCreateProject}>Создать проект</button>
<ul>
{projects?.map((project) => (
<li key={project.id}>
{project.name} - {project.slug}
</li>
))}
</ul>
</div>
);
}
// ============================================
// ПРИМЕР 2: ИСПОЛЬЗОВАНИЕ С REACT QUERY
// ============================================
function UserProfileWithReactQuery() {
const profileConfig = api.auth.useGetProfile();
const { data, error, isLoading } = useQuery({
queryKey: [profileConfig.path],
queryFn: () => api.auth.getProfile(),
});
if (isLoading) return <div>Загрузка...</div>;
if (error) return <div>Ошибка</div>;
return (
<div>
<h1>{data?.firstName} {data?.lastName}</h1>
<p>{data?.email}</p>
</div>
);
}
function ProjectsListWithReactQuery() {
const projectsConfig = api.projects.useFindAll();
const { data: projects, isLoading } = useQuery({
queryKey: [projectsConfig.path],
queryFn: () => api.projects.findAll(),
staleTime: 5 * 60 * 1000, // 5 минут
refetchInterval: 30000, // Обновлять каждые 30 секунд
});
if (isLoading) return <div>Загрузка...</div>;
return (
<div>
<h2>Проекты</h2>
{projects?.map((p) => (
<div key={p.id}>{p.name}</div>
))}
</div>
);
}
// ============================================
// ПРИМЕР 3: УСЛОВНАЯ ЗАГРУЗКА
// ============================================
function ConditionalProfile({ userId }: { userId?: string }) {
const profileConfig = api.auth.useGetProfile();
const { data } = useSWR(
// Загружаем только если есть userId
userId ? profileConfig.path : null,
() => api.auth.getProfile()
);
return data ? <div>{data.email}</div> : null;
}
// ============================================
// ПРИМЕР 4: ЗАВИСИМЫЕ ЗАПРОСЫ
// ============================================
function DependentQueries() {
// Сначала получаем список проектов
const projectsConfig = api.projects.useFindAll();
const { data: projects } = useSWR(
projectsConfig.path,
() => api.projects.findAll()
);
// Затем получаем первый проект (только когда список загружен)
const firstProjectId = projects?.[0]?.id;
const projectConfig = firstProjectId
? api.projects.useFindOne({ id: firstProjectId })
: null;
const { data: firstProject } = useSWR(
projectConfig ? [projectConfig.path, firstProjectId] : null,
() => firstProjectId ? api.projects.findOne({ id: firstProjectId }) : null
);
return (
<div>
<h3>Всего проектов: {projects?.length || 0}</h3>
{firstProject && (
<div>
<h4>Первый проект:</h4>
<p>{firstProject.name}</p>
</div>
)}
</div>
);
}
// ============================================
// ПРИМЕР 5: СОЗДАНИЕ ХУКА-ОБЁРТКИ
// ============================================
// Универсальный хук для всех GET запросов
function useApiQuery<T>(
useConfigFn: () => { path: string; method: 'GET'; secure?: boolean },
apiFn: () => Promise<T>,
options?: Parameters<typeof useSWR>[2]
) {
const config = useConfigFn();
return useSWR<T>(config.path, apiFn, options);
}
// Использование
function MyComponent() {
const { data, error, isLoading } = useApiQuery(
api.auth.useGetProfile,
api.auth.getProfile,
{ revalidateOnFocus: true }
);
// ...
}
// ============================================
// ПРИМЕР 6: ПОЛЬЗОВАТЕЛЬСКИЙ FETCHER ДЛЯ SWR
// ============================================
// Создаём универсальный fetcher
const apiFetcher = async (key: string | string[]) => {
const path = Array.isArray(key) ? key[0] : key;
// Находим соответствующий метод API
// В реальном приложении можно использовать маппинг
return api.auth.getProfile(); // пример
};
// SWRConfig для всего приложения
import { SWRConfig } from 'swr';
function App() {
return (
<SWRConfig
value={{
fetcher: apiFetcher,
revalidateOnFocus: false,
dedupingInterval: 2000,
}}
>
<UserProfile />
<ProjectsList />
</SWRConfig>
);
}
export {
UserProfile,
ProjectDetails,
ProjectsList,
UserProfileWithReactQuery,
ProjectsListWithReactQuery,
ConditionalProfile,
DependentQueries,
useApiQuery,
};