Files
profile-front/src/lib/api/authors.ts
2026-03-05 00:23:51 +03:00

281 lines
7.6 KiB
TypeScript
Raw 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.

import { fetchGraphQL } from './graphql-client.js';
//кэширование
import { cache } from '@lib/cache/manager.js';
import { CACHE_TTL } from '@lib/cache/cache-ttl';
// lib/api/authors.js
export async function getPostsByCoauthorLogin(coauthorLogin, perLoad = 14, after = null) {
const cacheKey = `coauthor-posts:${coauthorLogin}:${perLoad}:${after || 'first-page'}`;
return await cache.wrap(
cacheKey,
async () => {
try {
const baseUrl = import.meta.env.WP_REST_BASE_URL?.replace(/\/$/, '');
// Формируем URL
const url = `${baseUrl}/author/${coauthorLogin}/posts?per_page=${perLoad}${
after ? `&cursor=${encodeURIComponent(after)}` : ''
}`;
const response = await fetch(url);
if (!response.ok) {
if (response.status === 404) {
return { posts: [], pageInfo: { hasNextPage: false, endCursor: null } };
}
throw new Error(`HTTP error: ${response.status}`);
}
const data = await response.json();
// Преобразуем данные для компонента
const posts = (data.data || []).map(post => ({
// ID и ссылки
databaseId: post.id,
uri: post.link, // компонент использует uri
// Основные поля
title: post.title,
date: post.date,
// Картинка - приводим к формату GraphQL
featuredImage: post.featured_image?.medium ? {
node: {
sourceUrl: post.featured_image.medium,
altText: post.title
}
} : null,
// Категории - приводим к формату nodes
categories: {
nodes: (post.categories || []).map(cat => ({
name: cat.name,
slug: cat.slug,
color: cat.color || null
}))
},
// Соавторы - компонент ожидает массив с name и nickname
coauthors: (post.coauthors || []).map(coauthor => ({
name: coauthor.name,
nickname: coauthor.id, // id используем как nickname для ссылки
node: {
name: coauthor.name,
nickname: coauthor.id
}
}))
}));
return {
posts,
pageInfo: {
hasNextPage: data.pagination?.has_next || false,
endCursor: data.pagination?.next_cursor || null
}
};
} catch (error) {
console.error(`❌ Error fetching author posts:`, error);
return { posts: [], pageInfo: { hasNextPage: false, endCursor: null } };
}
},
{ ttl: 3600 }
);
}
// все посты автора
export async function getPostsByCoauthorLoginQL(login, first = 14, after = null) {
// Создаем уникальный ключ для кэша
const cacheKey = `coauthor-posts-by-login:${login}:${first}:${after || 'first-page'}`;
return await cache.wrap(
cacheKey,
async () => {
const query = `
query GetPostsByCoauthorLogin($first: Int!, $after: String, $login: String!) {
contentNodes(
first: $first
after: $after
where: {
contentTypes: [PROFILE_ARTICLE, ANEW]
coauthorLogin: $login
orderby: { field: DATE, order: DESC }
}
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
__typename
id
databaseId
uri
date
... on NodeWithTitle {
title
}
... on NodeWithFeaturedImage {
featuredImage {
node {
sourceUrl(size: LARGE)
altText
}
}
}
# Для ваших кастомных типов
... on ProfileArticle {
categories {
nodes {
name
slug
color
}
}
}
... on ANew {
categories {
nodes {
name
slug
color
}
}
}
... on NodeWithAuthor {
author {
node {
name
avatar {
url
}
}
}
}
# Coauthors для ProfileArticle
... on ProfileArticle {
coauthors {
id
name
firstName
lastName
url
nicename # Добавляем nicename (login)
}
}
# Coauthors для ANew
... on ANew {
coauthors {
id
name
firstName
lastName
url
nicename # Добавляем nicename (login)
}
}
}
}
}
`;
const data = await fetchGraphQL(query, {
first,
after,
login
});
// Обрабатываем посты
const posts = data.contentNodes?.nodes?.map(node => {
// Приводим coauthors к единому формату
if (node.coauthors) {
node.coauthors = node.coauthors.map(author => ({
id: author.id,
name: author.name || '',
firstName: author.firstName || '',
lastName: author.lastName || '',
url: author.url || '',
nicename: author.nicename || '' // Добавляем login
}));
}
return node;
}) || [];
return {
posts,
pageInfo: data.contentNodes?.pageInfo || {
hasNextPage: false,
endCursor: null
},
authorLogin: login
};
},
{ ttl: CACHE_TTL.POSTS }
);
}
export async function getAuthorData(slug) {
const cacheKey = `author-data:slug:${slug}`;
return await cache.wrap(
cacheKey,
async () => {
const baseUrl = import.meta.env.WP_REST_BASE_URL.replace(/\/$/, '');
try {
const response = await fetch(`${baseUrl}/author/${slug}`);
if (!response.ok) {
if (response.status === 404) {
return null;
}
throw new Error(`HTTP error: ${response.status}`);
}
const author = await response.json();
// Форматируем ответ
return {
id: author.slug || author.id,
name: author.name,
firstName: author.firstName,
lastName: author.lastName,
avatar: author.photo || author.avatar,
avatar_sizes: author.photo_sizes || {},
bio: author.description,
social: author.social || {},
url: author.url,
type: author.type,
};
} catch (error) {
console.error(`❌ Failed to fetch author ${slug}:`, error);
return null;
}
},
{ ttl: CACHE_TTL.AUTHOR }
);
}