Added releases changed the way apis work underneath to give more room for caching, i.e remove unneeded crap when it is unneeded

This commit is contained in:
2025-01-21 00:43:14 -05:00
parent 9baa792111
commit 52b2301fc1
8 changed files with 343 additions and 59 deletions

View File

@@ -1,19 +1,13 @@
import { subDays } from "date-fns";
import { Book, Chapter, Editor } from "./types";
import { addDays, subDays } from "date-fns";
import { Book, Chapter, Editor, Announcement } from "./types";
const API_URL = process.env.NEXT_PUBLIC_API_URL as string;
const API_TOKEN = process.env.STRAPI_API_TOKEN as string;
/**
* Centralized API fetch function with TypeScript support.
* Handles GET, POST, PUT, DELETE methods and includes headers by default.
*/
export async function fetchFromAPI<T>(
endpoint: string,
options: RequestInit = {}
): Promise<T> {
const url = `${API_URL}${endpoint}`;
): Promise<T[]> {
const headers: HeadersInit = {
Authorization: `Bearer ${API_TOKEN}`,
"Content-Type": "application/json",
@@ -25,19 +19,32 @@ export async function fetchFromAPI<T>(
...options,
};
let results: T[] = [];
let currentPage = 1;
let totalPages = 1;
try {
const response = await fetch(url, {...config, next: {revalidate:30}});
do{
const url = `${API_URL}${endpoint}&pagination[page]=${currentPage}&pagination[pageSize]=25`;
const response = await fetch(url, {...config, next: {revalidate:30}});
if (!response.ok) {
const errorData = await response.json();
console.error(`Error fetching ${url}:`, errorData);
throw new Error(errorData.message || `API fetch error (status: ${response.status})`);
}
const responseJson = await response.json();
return responseJson;
results = results.concat(responseJson.data);
totalPages = responseJson.meta?.pagination?.pageCount;
currentPage += 1;
}while(currentPage <= totalPages)
} catch (error) {
console.error("Fetch error:", error);
throw error;
}
return results;
}
/**
@@ -45,22 +52,27 @@ export async function fetchFromAPI<T>(
* Populates optional fields like Chapters or Editors based on requirements.
*/
export async function fetchBooks(): Promise<Book[]> {
const data = await fetchFromAPI<{ data: Book[] }>("/api/books?populate=*&chapters.sort=number:desc");
return data.data;
const data = await fetchFromAPI<Book>("/api/books?populate=cover&sort[title]=asc");
return data;
}
export async function fetchAnnouncements(): Promise<Announcement[]> {
const data = await fetchFromAPI<Announcement>("/api/announcements?");
return data;
}
export async function fetchChaptersRSS(): Promise<Chapter[]> {
const currentDateTime = new Date()
const yesterday = subDays(currentDateTime, 1);
const data = await fetchFromAPI<{ data: Chapter[] }>
const data = await fetchFromAPI<Chapter>
(`/api/chapters?populate=book&filters[release_datetime][$lte]=${currentDateTime.toISOString()}&filters[release_datetime][$gte]=${yesterday.toISOString()}`);
return data.data;
return data;
}
export async function fetchBookChapterLinks(bookId: string): Promise<Book> {
const currentDateTime = new Date().toISOString();
const data = await fetchFromAPI<{ data: Book }>(`/api/books/${bookId}?populate[chapters][filters][release_datetime][$lte]=${currentDateTime}`);
return data.data
const data = await fetchFromAPI<Book>(`/api/books/${bookId}?populate[chapters][filters][release_datetime][$lte]=${currentDateTime}`);
return data[0]
}
/**
@@ -69,25 +81,49 @@ export async function fetchBookChapterLinks(bookId: string): Promise<Book> {
*/
export async function fetchBookById(bookId: string): Promise<Book> {
const currentDateTime = new Date().toISOString();
const data = await fetchFromAPI<{ data: Book }>(
const data = await fetchFromAPI<Book>(
`/api/books/${bookId}?populate[chapters][filters][release_datetime][$lte]=${currentDateTime}&populate=cover`
);
data.data.chapters = data.data.chapters.sort((a, b) => a.number - b.number);
return data.data;
data[0].chapters = data[0].chapters.sort((a, b) => a.number - b.number);
return data[0];
}
/**
* Fetches a specific chapter by ID.
*/
export async function fetchChapterById(chapterId: string): Promise<Chapter> {
const data = await fetchFromAPI<{ data: Chapter }>(`/api/chapters/${chapterId}?populate[book][fields]=documentId`);
return data.data;
export async function fetchChapterByBookId(bookId: string, chapterId: string): Promise<Chapter[]> {
const currentChapter = await fetchFromAPI<Chapter>(`/api/chapters/${chapterId}?populate[book][fields][0]=title&filters[book][documentId]=${bookId}`);
const bookWithAllChapters = await fetchFromAPI<Book>( `/api/books/${bookId}?populate[chapters][filters][number][$gte]=${
currentChapter[0].number - 1
}&populate[chapters][filters][number][$lte]=${
currentChapter[0].number + 1
}`);
//const nextChapter = await fetchFromAPI<Chapter>(`/api/chapters?populate[book]&filters[book][id]=${bookId}&sort[number]=asc`);
return bookWithAllChapters[0].chapters;
}
/**
* Fetches all editors.
*/
export async function fetchEditors(): Promise<Editor[]> {
const data = await fetchFromAPI<{ data: Editor[] }>("/api/editors");
return data.data;
const data = await fetchFromAPI<Editor>("/api/editors");
return data;
}
export type ChapterRelease = {current_chapters:Chapter[],future_chapters:Chapter[]}
export async function fetchReleases(): Promise<{current_chapters:Chapter[],future_chapters:Chapter[]}> {
const current_datetime = new Date()
const previous_week = subDays(current_datetime, 3);
const next_week = addDays(current_datetime, 3);
const data = await fetchFromAPI<Chapter>(`/api/chapters/?populate[book][fields][0]=title&fields[0]=number&fields[1]=title&fields[2]=release_datetime&filters[release_datetime][$gte]=${previous_week.toISOString()}&filters[release_datetime][$lte]=${next_week.toISOString()}`);
const chapters: Chapter[] = data;
const future_chapters = chapters.filter(chapter => new Date(chapter.release_datetime) > new Date());
const current_chapters = chapters.filter(chapter => new Date(chapter.release_datetime) <= new Date());
return {current_chapters,future_chapters}
}
export async function fetchAnnouncementById(announcementId: string): Promise<Announcement> {
const data = await fetchFromAPI<Announcement>(`/api/announcements/${announcementId}`);
return data[0];
}

View File

@@ -63,6 +63,19 @@ export interface Book {
glossary: Glossary;
}
export interface Announcement {
id: number;
title: string;
content: string;
datetime: string;
}
export interface Release {
book_title: string;
chapter: string;
datetime: string;
url: string;
}
export const Ad = {
patreon: "https://patreon.com/nulltranslationgroup/membership",
}