# Синхронизировать типы из Strapi
npm run synctypesnuxt-frontend/
├── shared-types/
│ └── index.ts # Автоматически генерируемые типы
├── scripts/
│ └── synctypes.js # Скрипт генерации типов
└── .cursorrules-types # Правила работы с типами
import type { StrapiArticle, StrapiCollectionData } from '~/shared-types';const { data: articles } = await useAsyncData('articles', () =>
find('articles', { populate: '*' })
) as { data: StrapiCollectionData<StrapiArticle> | null; error: any };// Получить атрибут статьи
const getArticleAttr = (article: any, attr: string) => {
if (!article) return '';
return article[attr] || article.attributes?.[attr] || '';
};
// Использование в шаблоне
{{ getArticleAttr(article, 'title') }}
{{ formatDate(getArticleAttr(article, 'publishedAt')) }}- Откройте
scripts/synctypes.js - Найдите функцию
generateTypes() - Добавьте новый интерфейс перед закрывающим backtick:
export interface StrapiProduct {
id: number;
attributes: {
name: string;
price: number;
description: string;
image?: StrapiMediaData | null;
createdAt: string;
updatedAt: string;
[key: string]: any;
};
}- Запустите
npm run synctypes - Импортируйте и используйте новый тип
- Откройте
scripts/synctypes.js - Найдите нужный интерфейс (например,
StrapiArticleAttributes) - Измените поля
- Запустите
npm run synctypes - Проверьте результат в
shared-types/index.ts
const getImageUrl = (article: StrapiArticle) => {
const cover = article.attributes?.cover;
if (!cover?.attributes?.url) return null;
return cover.attributes.url;
};const articles = await find('articles', { populate: '*' });
// articles.data - массив StrapiArticleconst article = await findOne('articles', id);
// article.data - StrapiArticle | nullПроект использует Vue Query для продвинутого кэширования и управления состоянием запросов.
// composables/useArticlesQuery.ts
export const useArticlesQuery = () => {
const { find } = useStrapi();
return useQuery({
queryKey: ['articles'],
queryFn: async () => find('articles', { populate: '*' }),
staleTime: 1000 * 60 * 5, // 5 минут
gcTime: 1000 * 60 * 30, // 30 минут
refetchOnWindowFocus: true,
});
};<script setup lang="ts">
const { data, isLoading, isError, error, refetch } = useArticlesQuery();
// Доступны состояния:
// isLoading - идет загрузка
// isError - произошла ошибка
// error - объект ошибки
// data - данные
// refetch - функция повтора запроса
</script>
<template>
<div v-if="isLoading">Загрузка...</div>
<div v-else-if="isError">Ошибка: {{ error.message }}</div>
<div v-else-if="data">{{ data }}</div>
</template>import { useQueryClient } from '@tanstack/vue-query';
const queryClient = useQueryClient();
// Инвалидировать кэш
queryClient.invalidateQueries({ queryKey: ['articles'] });
// Получить данные из кэша
const articles = queryClient.getQueryData(['articles']);Скорее всего, нужно обновить тип или использовать getArticleAttr() helper
Добавьте проверку на существование объекта:
if (!article?.attributes?.title) return '';Запустите npm run synctypes вручную
Проверьте, что модуль @hebilicious/vue-query-nuxt добавлен в nuxt.config.ts