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:
@@ -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];
|
||||
}
|
||||
@@ -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",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user