feat: инициализация API CodeGen
CLI утилита для генерации TypeScript API клиента из OpenAPI спецификации. - Поддержка локальных файлов и URL для спецификаций - Кастомизация имени выходного файла через флаг --name - Генерация типизированного клиента с SWR хуками - Минимальный вывод логов для лучшего UX
This commit is contained in:
282
example-hooks.tsx
Normal file
282
example-hooks.tsx
Normal file
@@ -0,0 +1,282 @@
|
||||
/**
|
||||
* Примеры использования сгенерированных 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,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user