refactor: replace book details GET route with server action
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 6m16s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 6m16s
This commit is contained in:
@@ -24,7 +24,6 @@ Routes GET actuellement présentes :
|
||||
|
||||
| Route | Utilisation actuelle | Pourquoi garder maintenant | Piste de simplification |
|
||||
|-------|----------------------|----------------------------|-------------------------|
|
||||
| `GET /api/komga/books/[bookId]` | fallback dans `ClientBookPage.tsx`, usage `DownloadManager.tsx` | fallback utile hors flux page SSR | Limiter au fallback strict, éviter le double-fetch |
|
||||
|
||||
### B2. Migrees en Lot 2 (pagination server-first)
|
||||
|
||||
@@ -36,6 +35,7 @@ Routes GET actuellement présentes :
|
||||
| `GET /api/komga/home` | `src/app/page.tsx` consomme déjà `HomeService` côté server | Données agrégées directement via service server | ✅ Supprimée |
|
||||
| `GET /api/user/profile` | aucun consommateur client trouvé, page compte déjà server-first | Profil/statistiques via `UserService` en Server Component | ✅ Supprimée |
|
||||
| `GET /api/komga/series/[seriesId]` | plus de consommateur `fetch('/api/...')` (chargement via `SeriesService`) | Détail série chargé en Server Component | ✅ Supprimée |
|
||||
| `GET /api/komga/books/[bookId]` | fallback client (`ClientBookPage`) et DownloadManager migrés vers server action | Données livre/pages/nextBook via `BookService` et action server | ✅ Supprimée |
|
||||
|
||||
### C. A conserver (API de transport / framework)
|
||||
|
||||
|
||||
36
src/app/actions/books.ts
Normal file
36
src/app/actions/books.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
"use server";
|
||||
|
||||
import { BookService } from "@/lib/services/book.service";
|
||||
import { AppError } from "@/utils/errors";
|
||||
import type { KomgaBook } from "@/types/komga";
|
||||
|
||||
interface BookDataResult {
|
||||
success: boolean;
|
||||
data?: {
|
||||
book: KomgaBook;
|
||||
pages: number[];
|
||||
nextBook: KomgaBook | null;
|
||||
};
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export async function getBookData(bookId: string): Promise<BookDataResult> {
|
||||
try {
|
||||
const data = await BookService.getBook(bookId);
|
||||
const nextBook = await BookService.getNextBook(bookId, data.book.seriesId);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
...data,
|
||||
nextBook,
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
return { success: false, message: error.code };
|
||||
}
|
||||
|
||||
return { success: false, message: "BOOK_DATA_FETCH_ERROR" };
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { BookService } from "@/lib/services/book.service";
|
||||
import { ERROR_CODES } from "@/constants/errorCodes";
|
||||
import { getErrorMessage } from "@/utils/errors";
|
||||
import { AppError } from "@/utils/errors";
|
||||
import type { KomgaBookWithPages } from "@/types/komga";
|
||||
import type { NextRequest } from "next/server";
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
type ErrorWithStatusParams = AppError & { params?: { status?: number } };
|
||||
|
||||
// Cache handled in service via fetchFromApi options
|
||||
|
||||
export async function GET(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ bookId: string }> }
|
||||
) {
|
||||
try {
|
||||
const bookId: string = (await params).bookId;
|
||||
|
||||
const data: KomgaBookWithPages = await BookService.getBook(bookId);
|
||||
const nextBook = await BookService.getNextBook(bookId, data.book.seriesId);
|
||||
|
||||
return NextResponse.json({ ...data, nextBook });
|
||||
} catch (error) {
|
||||
logger.error({ err: error }, "API Books - Erreur:");
|
||||
if (error instanceof AppError) {
|
||||
const isNotFound =
|
||||
error.code === ERROR_CODES.BOOK.NOT_FOUND ||
|
||||
(error.code === ERROR_CODES.KOMGA.HTTP_ERROR &&
|
||||
(error as ErrorWithStatusParams).params?.status === 404);
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: {
|
||||
code: error.code,
|
||||
name: "Book fetch error",
|
||||
message: getErrorMessage(error.code),
|
||||
} as AppError,
|
||||
},
|
||||
{ status: isNotFound ? 404 : 500 }
|
||||
);
|
||||
}
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: {
|
||||
code: ERROR_CODES.BOOK.NOT_FOUND,
|
||||
name: "Book fetch error",
|
||||
message: getErrorMessage(ERROR_CODES.BOOK.NOT_FOUND),
|
||||
} as AppError,
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import { BookOfflineButton } from "@/components/ui/book-offline-button";
|
||||
import { useTranslate } from "@/hooks/useTranslate";
|
||||
import logger from "@/lib/logger";
|
||||
import { Container } from "@/components/ui/container";
|
||||
import { getBookData } from "@/app/actions/books";
|
||||
|
||||
type BookStatus = "idle" | "downloading" | "available" | "error";
|
||||
|
||||
@@ -48,11 +49,12 @@ export function DownloadManager() {
|
||||
const status = JSON.parse(localStorage.getItem(key) || "");
|
||||
if (status.status !== "idle") {
|
||||
try {
|
||||
const response = await fetch(`/api/komga/books/${bookId}`);
|
||||
if (!response.ok) throw new Error("Livre non trouvé");
|
||||
const bookData = await response.json();
|
||||
const result = await getBookData(bookId);
|
||||
if (!result.success || !result.data) {
|
||||
throw new Error("Livre non trouvé");
|
||||
}
|
||||
books.push({
|
||||
book: bookData.book,
|
||||
book: result.data.book,
|
||||
status,
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import { ErrorMessage } from "@/components/ui/ErrorMessage";
|
||||
import { ERROR_CODES } from "@/constants/errorCodes";
|
||||
import type { KomgaBook } from "@/types/komga";
|
||||
import logger from "@/lib/logger";
|
||||
import { getBookData } from "@/app/actions/books";
|
||||
|
||||
interface ClientBookPageProps {
|
||||
bookId: string;
|
||||
@@ -48,15 +49,12 @@ export function ClientBookPage({ bookId, initialData, initialError }: ClientBook
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
const response = await fetch(`/api/komga/books/${bookId}`);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
throw new Error(errorData.error?.code || ERROR_CODES.BOOK.PAGES_FETCH_ERROR);
|
||||
const result = await getBookData(bookId);
|
||||
if (!result.success || !result.data) {
|
||||
throw new Error(result.message || ERROR_CODES.BOOK.PAGES_FETCH_ERROR);
|
||||
}
|
||||
|
||||
const bookData = await response.json();
|
||||
setData(bookData);
|
||||
setData(result.data);
|
||||
} catch (err) {
|
||||
logger.error({ err }, "Error fetching book");
|
||||
setError(err instanceof Error ? err.message : ERROR_CODES.BOOK.PAGES_FETCH_ERROR);
|
||||
|
||||
Reference in New Issue
Block a user