feat: add logging enhancements by integrating pino and pino-pretty for improved error tracking and debugging across the application

This commit is contained in:
Julien Froidefond
2025-10-26 06:15:47 +01:00
parent 7cc72dc13d
commit 52350a43d9
84 changed files with 455 additions and 177 deletions

View File

@@ -2,6 +2,7 @@ import { UserProfileCard } from "@/components/account/UserProfileCard";
import { ChangePasswordForm } from "@/components/account/ChangePasswordForm";
import { UserService } from "@/lib/services/user.service";
import { redirect } from "next/navigation";
import logger from "@/lib/logger";
export const dynamic = 'force-dynamic';
@@ -30,7 +31,7 @@ export default async function AccountPage() {
</div>
);
} catch (error) {
console.error("Erreur lors du chargement du compte:", error);
logger.error({ err: error }, "Erreur lors du chargement du compte:");
redirect("/login");
}
}

View File

@@ -2,6 +2,7 @@ import { AdminService } from "@/lib/services/admin.service";
import { redirect } from "next/navigation";
import { isAdmin } from "@/lib/auth-utils";
import { AdminContent } from "@/components/admin/AdminContent";
import logger from "@/lib/logger";
export const dynamic = 'force-dynamic';
@@ -20,7 +21,7 @@ export default async function AdminPage() {
return <AdminContent initialUsers={users} initialStats={stats} />;
} catch (error) {
console.error("Erreur lors du chargement de la page admin:", error);
logger.error({ err: error }, "Erreur lors du chargement de la page admin:");
redirect("/");
}
}

View File

@@ -1,13 +1,14 @@
import { NextResponse } from "next/server";
import { AdminService } from "@/lib/services/admin.service";
import { AppError } from "@/utils/errors";
import logger from "@/lib/logger";
export async function GET() {
try {
const stats = await AdminService.getUserStats();
return NextResponse.json(stats);
} catch (error) {
console.error("Erreur lors de la récupération des stats:", error);
logger.error({ err: error }, "Erreur lors de la récupération des stats:");
if (error instanceof AppError) {
return NextResponse.json(

View File

@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from "next/server";
import { AdminService } from "@/lib/services/admin.service";
import { AppError } from "@/utils/errors";
import { AuthServerService } from "@/lib/services/auth-server.service";
import logger from "@/lib/logger";
export async function PUT(
request: NextRequest,
@@ -33,7 +34,7 @@ export async function PUT(
return NextResponse.json({ success: true });
} catch (error) {
console.error("Erreur lors de la réinitialisation du mot de passe:", error);
logger.error({ err: error }, "Erreur lors de la réinitialisation du mot de passe:");
if (error instanceof AppError) {
return NextResponse.json(

View File

@@ -1,6 +1,7 @@
import { NextRequest, NextResponse } from "next/server";
import { AdminService } from "@/lib/services/admin.service";
import { AppError } from "@/utils/errors";
import logger from "@/lib/logger";
export async function PATCH(
request: NextRequest,
@@ -22,7 +23,7 @@ export async function PATCH(
return NextResponse.json({ success: true });
} catch (error) {
console.error("Erreur lors de la mise à jour de l'utilisateur:", error);
logger.error({ err: error }, "Erreur lors de la mise à jour de l'utilisateur:");
if (error instanceof AppError) {
return NextResponse.json(
@@ -52,7 +53,7 @@ export async function DELETE(
return NextResponse.json({ success: true });
} catch (error) {
console.error("Erreur lors de la suppression de l'utilisateur:", error);
logger.error({ err: error }, "Erreur lors de la suppression de l'utilisateur:");
if (error instanceof AppError) {
return NextResponse.json(

View File

@@ -1,13 +1,14 @@
import { NextResponse } from "next/server";
import { AdminService } from "@/lib/services/admin.service";
import { AppError } from "@/utils/errors";
import logger from "@/lib/logger";
export async function GET() {
try {
const users = await AdminService.getAllUsers();
return NextResponse.json(users);
} catch (error) {
console.error("Erreur lors de la récupération des utilisateurs:", error);
logger.error({ err: error }, "Erreur lors de la récupération des utilisateurs:");
if (error instanceof AppError) {
return NextResponse.json(

View File

@@ -3,6 +3,7 @@ import { AuthServerService } from "@/lib/services/auth-server.service";
import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages";
import { AppError } from "@/utils/errors";
import logger from "@/lib/logger";
export async function POST(request: NextRequest) {
try {
@@ -25,7 +26,7 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ success: true, user: userData });
} catch (error) {
console.error("Registration error:", error);
logger.error({ err: error }, "Registration error:");
if (error instanceof AppError) {
return NextResponse.json(

View File

@@ -4,6 +4,7 @@ import { BookService } from "@/lib/services/book.service";
import { ERROR_CODES } from "@/constants/errorCodes";
import { getErrorMessage } from "@/utils/errors";
import { AppError } from "@/utils/errors";
import logger from "@/lib/logger";
export const dynamic = "force-dynamic";
@@ -39,7 +40,7 @@ export async function GET(
headers,
});
} catch (error) {
console.error("Erreur lors de la récupération de la page:", error);
logger.error({ err: error }, "Erreur lors de la récupération de la page:");
if (error instanceof AppError) {
return NextResponse.json(
{

View File

@@ -4,6 +4,7 @@ import { BookService } from "@/lib/services/book.service";
import { ERROR_CODES } from "@/constants/errorCodes";
import { getErrorMessage } from "@/utils/errors";
import { AppError } from "@/utils/errors";
import logger from "@/lib/logger";
export async function PATCH(
request: NextRequest,
@@ -29,7 +30,7 @@ export async function PATCH(
await BookService.updateReadProgress(bookId, page, completed);
return NextResponse.json({ message: "📖 Progression mise à jour avec succès" });
} catch (error) {
console.error("Erreur lors de la mise à jour de la progression:", error);
logger.error({ err: error }, "Erreur lors de la mise à jour de la progression:");
if (error instanceof AppError) {
return NextResponse.json(
{
@@ -65,7 +66,7 @@ export async function DELETE(
await BookService.deleteReadProgress(bookId);
return NextResponse.json({ message: "🗑️ Progression supprimée avec succès" });
} catch (error) {
console.error("Erreur lors de la suppression de la progression:", error);
logger.error({ err: error }, "Erreur lors de la suppression de la progression:");
if (error instanceof AppError) {
return NextResponse.json(
{

View File

@@ -5,6 +5,7 @@ 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";
export async function GET(
request: NextRequest,
@@ -18,7 +19,7 @@ export async function GET(
return NextResponse.json({ ...data, nextBook });
} catch (error) {
console.error("API Books - Erreur:", error);
logger.error({ err: error }, "API Books - Erreur:");
if (error instanceof AppError) {
return NextResponse.json(
{

View File

@@ -6,6 +6,7 @@ import { HomeService } from "@/lib/services/home.service";
import { SeriesService } from "@/lib/services/series.service";
import { revalidatePath } from "next/cache";
import type { NextRequest } from "next/server";
import logger from "@/lib/logger";
export async function POST(
request: NextRequest,
@@ -30,7 +31,7 @@ export async function POST(
return NextResponse.json({ message: "🧹 Cache vidé avec succès" });
} catch (error) {
console.error("Erreur lors de la suppression du cache:", error);
logger.error({ err: error }, "Erreur lors de la suppression du cache:");
return NextResponse.json(
{
error: {

View File

@@ -4,6 +4,7 @@ import { getServerCacheService } from "@/lib/services/server-cache.service";
import { ERROR_CODES } from "@/constants/errorCodes";
import { getErrorMessage } from "@/utils/errors";
import { revalidatePath } from "next/cache";
import logger from "@/lib/logger";
export async function POST() {
try {
@@ -18,7 +19,7 @@ export async function POST() {
return NextResponse.json({ message: "🧹 Cache vidé avec succès" });
} catch (error) {
console.error("Erreur lors de la suppression du cache:", error);
logger.error({ err: error }, "Erreur lors de la suppression du cache:");
return NextResponse.json(
{
error: {

View File

@@ -3,6 +3,7 @@ import type { ServerCacheService } from "@/lib/services/server-cache.service";
import { getServerCacheService } from "@/lib/services/server-cache.service";
import { ERROR_CODES } from "@/constants/errorCodes";
import { getErrorMessage } from "@/utils/errors";
import logger from "@/lib/logger";
export async function GET() {
try {
@@ -11,7 +12,7 @@ export async function GET() {
return NextResponse.json({ entries });
} catch (error) {
console.error("Erreur lors de la récupération des entrées du cache:", error);
logger.error({ err: error }, "Erreur lors de la récupération des entrées du cache");
return NextResponse.json(
{
error: {

View File

@@ -4,13 +4,14 @@ import { getServerCacheService } from "@/lib/services/server-cache.service";
import { ERROR_CODES } from "@/constants/errorCodes";
import { getErrorMessage } from "@/utils/errors";
import type { NextRequest } from "next/server";
import logger from "@/lib/logger";
export async function GET() {
try {
const cacheService: ServerCacheService = await getServerCacheService();
return NextResponse.json({ mode: cacheService.getCacheMode() });
} catch (error) {
console.error("Erreur lors de la récupération du mode de cache:", error);
logger.error({ err: error }, "Erreur lors de la récupération du mode de cache:");
return NextResponse.json(
{
error: {
@@ -44,7 +45,7 @@ export async function POST(request: NextRequest) {
cacheService.setCacheMode(mode);
return NextResponse.json({ mode: cacheService.getCacheMode() });
} catch (error) {
console.error("Erreur lors de la mise à jour du mode de cache:", error);
logger.error({ err: error }, "Erreur lors de la mise à jour du mode de cache:");
return NextResponse.json(
{
error: {

View File

@@ -3,6 +3,7 @@ import type { ServerCacheService } from "@/lib/services/server-cache.service";
import { getServerCacheService } from "@/lib/services/server-cache.service";
import { ERROR_CODES } from "@/constants/errorCodes";
import { getErrorMessage } from "@/utils/errors";
import logger from "@/lib/logger";
export async function GET() {
try {
@@ -15,7 +16,7 @@ export async function GET() {
mode: cacheService.getCacheMode()
});
} catch (error) {
console.error("Erreur lors de la récupération de la taille du cache:", error);
logger.error({ err: error }, "Erreur lors de la récupération de la taille du cache:");
return NextResponse.json(
{
error: {

View File

@@ -4,6 +4,7 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import type { KomgaConfig, KomgaConfigData } from "@/types/komga";
import { getErrorMessage } from "@/utils/errors";
import type { NextRequest } from "next/server";
import logger from "@/lib/logger";
export const dynamic = "force-dynamic";
@@ -17,7 +18,7 @@ export async function POST(request: NextRequest) {
{ status: 200 }
);
} catch (error) {
console.error("Erreur lors de la sauvegarde de la configuration:", error);
logger.error({ err: error }, "Erreur lors de la sauvegarde de la configuration:");
if (error instanceof Error && error.message === "Utilisateur non authentifié") {
return NextResponse.json(
{
@@ -49,7 +50,7 @@ export async function GET() {
return NextResponse.json(mongoConfig, { status: 200 });
} catch (error) {
console.error("Erreur lors de la récupération de la configuration:", error);
logger.error({ err: error }, "Erreur lors de la récupération de la configuration:");
if (error instanceof Error) {
if (error.message === "Utilisateur non authentifié") {
return NextResponse.json(

View File

@@ -5,6 +5,7 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import { getErrorMessage } from "@/utils/errors";
import type { NextRequest } from "next/server";
import logger from "@/lib/logger";
export async function GET() {
try {
@@ -35,7 +36,7 @@ export async function GET() {
return NextResponse.json([]);
}
}
console.error("Erreur lors de la récupération des favoris:", error);
logger.error({ err: error }, "Erreur lors de la récupération des favoris:");
if (error instanceof AppError) {
return NextResponse.json(
{
@@ -67,7 +68,7 @@ export async function POST(request: NextRequest) {
await FavoriteService.addToFavorites(seriesId);
return NextResponse.json({ message: "⭐️ Série ajoutée aux favoris" });
} catch (error) {
console.error("Erreur lors de l'ajout du favori:", error);
logger.error({ err: error }, "Erreur lors de l'ajout du favori:");
if (error instanceof AppError) {
return NextResponse.json(
{
@@ -99,7 +100,7 @@ export async function DELETE(request: NextRequest) {
await FavoriteService.removeFromFavorites(seriesId);
return NextResponse.json({ message: "💔 Série retirée des favoris" });
} catch (error) {
console.error("Erreur lors de la suppression du favori:", error);
logger.error({ err: error }, "Erreur lors de la suppression du favori:");
if (error instanceof AppError) {
return NextResponse.json(
{

View File

@@ -3,6 +3,7 @@ import { HomeService } from "@/lib/services/home.service";
import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import { getErrorMessage } from "@/utils/errors";
import logger from "@/lib/logger";
export const revalidate = 60;
export async function GET() {
@@ -10,7 +11,7 @@ export async function GET() {
const data = await HomeService.getHomeData();
return NextResponse.json(data);
} catch (error) {
console.error("API Home - Erreur:", error);
logger.error({ err: error }, "API Home - Erreur:");
if (error instanceof AppError) {
return NextResponse.json(
{
@@ -41,7 +42,7 @@ export async function DELETE() {
await HomeService.invalidateHomeCache();
return NextResponse.json({ success: true });
} catch (error) {
console.error("API Home - Erreur lors de l'invalidation du cache:", error);
logger.error({ err: error }, "API Home - Erreur lors de l'invalidation du cache:");
if (error instanceof AppError) {
return NextResponse.json(
{

View File

@@ -5,6 +5,7 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import { getErrorMessage } from "@/utils/errors";
import { findHttpStatus } from "@/utils/image-errors";
import logger from "@/lib/logger";
export const dynamic = "force-dynamic";
@@ -18,7 +19,7 @@ export async function GET(
const response = await BookService.getPage(bookId, parseInt(pageNumber));
return response;
} catch (error) {
console.error("Erreur lors de la récupération de la page du livre:", error);
logger.error({ err: error }, "Erreur lors de la récupération de la page du livre:");
// Chercher un status HTTP 404 dans la chaîne d'erreurs
const httpStatus = findHttpStatus(error);
@@ -26,7 +27,7 @@ export async function GET(
if (httpStatus === 404) {
const { bookId, pageNumber } = await params;
// eslint-disable-next-line no-console
console.log(`📷 Page ${pageNumber} not found for book: ${bookId}`);
logger.info(`📷 Page ${pageNumber} not found for book: ${bookId}`);
return NextResponse.json(
{
error: {

View File

@@ -5,6 +5,7 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import { getErrorMessage } from "@/utils/errors";
import { findHttpStatus } from "@/utils/image-errors";
import logger from "@/lib/logger";
export const dynamic = "force-dynamic";
@@ -32,7 +33,7 @@ export async function GET(
const response = await BookService.getPageThumbnail(bookId, pageNumber);
return response;
} catch (error) {
console.error("Erreur lors de la récupération de la miniature de la page:", error);
logger.error({ err: error }, "Erreur lors de la récupération de la miniature de la page:");
// Chercher un status HTTP 404 dans la chaîne d'erreurs
const httpStatus = findHttpStatus(error);
@@ -41,7 +42,7 @@ export async function GET(
const { bookId, pageNumber: pageNumberParam } = await params;
const pageNumber: number = parseInt(pageNumberParam);
// eslint-disable-next-line no-console
console.log(`📷 Page ${pageNumber} thumbnail not found for book: ${bookId}`);
logger.info(`📷 Page ${pageNumber} thumbnail not found for book: ${bookId}`);
return NextResponse.json(
{
error: {

View File

@@ -5,6 +5,7 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import { getErrorMessage } from "@/utils/errors";
import { findHttpStatus } from "@/utils/image-errors";
import logger from "@/lib/logger";
export async function GET(
request: NextRequest,
@@ -16,7 +17,7 @@ export async function GET(
const response = await BookService.getCover(bookId);
return response;
} catch (error) {
console.error("Erreur lors de la récupération de la miniature du livre:", error);
logger.error({ err: error }, "Erreur lors de la récupération de la miniature du livre:");
// Chercher un status HTTP 404 dans la chaîne d'erreurs
const httpStatus = findHttpStatus(error);
@@ -24,7 +25,7 @@ export async function GET(
if (httpStatus === 404) {
const bookId: string = (await params).bookId;
// eslint-disable-next-line no-console
console.log(`📷 Thumbnail not found for book: ${bookId}`);
logger.info(`📷 Thumbnail not found for book: ${bookId}`);
return NextResponse.json(
{
error: {

View File

@@ -5,6 +5,7 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import { getErrorMessage } from "@/utils/errors";
import { findHttpStatus } from "@/utils/image-errors";
import logger from "@/lib/logger";
export const dynamic = "force-dynamic";
@@ -18,7 +19,7 @@ export async function GET(
const response = await SeriesService.getCover(seriesId);
return response;
} catch (error) {
console.error("Erreur lors de la récupération de la couverture de la série:", error);
logger.error({ err: error }, "Erreur lors de la récupération de la couverture de la série:");
// Chercher un status HTTP 404 dans la chaîne d'erreurs
const httpStatus = findHttpStatus(error);
@@ -26,7 +27,7 @@ export async function GET(
if (httpStatus === 404) {
const seriesId: string = (await params).seriesId;
// eslint-disable-next-line no-console
console.log(`📷 First page image not found for series: ${seriesId}`);
logger.info(`📷 First page image not found for series: ${seriesId}`);
return NextResponse.json(
{
error: {

View File

@@ -5,6 +5,7 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import { getErrorMessage } from "@/utils/errors";
import { findHttpStatus } from "@/utils/image-errors";
import logger from "@/lib/logger";
export async function GET(
request: NextRequest,
@@ -15,15 +16,14 @@ export async function GET(
const response = await SeriesService.getCover(seriesId);
return response;
} catch (error) {
console.error("Erreur lors de la récupération de la miniature de la série:", error);
logger.error({ err: error }, "Erreur lors de la récupération de la miniature de la série");
// Chercher un status HTTP 404 dans la chaîne d'erreurs
const httpStatus = findHttpStatus(error);
if (httpStatus === 404) {
const seriesId: string = (await params).seriesId;
// eslint-disable-next-line no-console
console.log(`📷 Image not found for series: ${seriesId}`);
logger.info(`📷 Image not found for series: ${seriesId}`);
return NextResponse.json(
{
error: {

View File

@@ -4,6 +4,7 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import { getErrorMessage } from "@/utils/errors";
import type { NextRequest } from "next/server";
import logger from "@/lib/logger";
export async function POST(
request: NextRequest,
@@ -17,7 +18,7 @@ export async function POST(
return NextResponse.json({ success: true });
} catch (error) {
console.error("API Library Scan - Erreur:", error);
logger.error({ err: error }, "API Library Scan - Erreur");
if (error instanceof AppError) {
return NextResponse.json(
{

View File

@@ -4,6 +4,7 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import { getErrorMessage } from "@/utils/errors";
import type { NextRequest } from "next/server";
import logger from "@/lib/logger";
export const revalidate = 60;
const DEFAULT_PAGE_SIZE = 20;
@@ -35,7 +36,7 @@ export async function GET(
}
);
} catch (error) {
console.error("API Library Series - Erreur:", error);
logger.error({ err: error }, "API Library Series - Erreur:");
if (error instanceof AppError) {
return NextResponse.json(
{
@@ -72,7 +73,7 @@ export async function DELETE(
return NextResponse.json({ success: true });
} catch (error) {
console.error("API Library Cache Invalidation - Erreur:", error);
logger.error({ err: error }, "API Library Cache Invalidation - Erreur:");
if (error instanceof AppError) {
return NextResponse.json(
{

View File

@@ -4,6 +4,7 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import type { KomgaLibrary } from "@/types/komga";
import { getErrorMessage } from "@/utils/errors";
import logger from "@/lib/logger";
export const dynamic = "force-dynamic";
export async function GET() {
@@ -17,7 +18,7 @@ export async function GET() {
return NextResponse.json([]);
}
}
console.error("API Libraries - Erreur:", error);
logger.error({ err: error }, "API Libraries - Erreur:");
if (error instanceof AppError) {
return NextResponse.json(
{

View File

@@ -4,6 +4,7 @@ import { BookService } from "@/lib/services/book.service";
import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import { getErrorMessage } from "@/utils/errors";
import logger from "@/lib/logger";
export const dynamic = "force-dynamic";
@@ -27,7 +28,7 @@ export async function GET(request: NextRequest) {
const bookId = await BookService.getRandomBookFromLibraries(libraryIds);
return NextResponse.json({ bookId });
} catch (error) {
console.error("Erreur lors de la récupération d'un livre aléatoire:", error);
logger.error({ err: error }, "Erreur lors de la récupération d'un livre aléatoire");
if (error instanceof AppError) {
return NextResponse.json(
{

View File

@@ -4,6 +4,7 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import { getErrorMessage } from "@/utils/errors";
import type { NextRequest } from "next/server";
import logger from "@/lib/logger";
export const revalidate = 60;
const DEFAULT_PAGE_SIZE = 20;
@@ -34,7 +35,7 @@ export async function GET(
}
);
} catch (error) {
console.error("API Series Books - Erreur:", error);
logger.error({ err: error }, "API Series Books - Erreur:");
if (error instanceof AppError) {
return NextResponse.json(
{
@@ -74,7 +75,7 @@ export async function DELETE(
return NextResponse.json({ success: true });
} catch (error) {
console.error("API Series Cache Invalidation - Erreur:", error);
logger.error({ err: error }, "API Series Cache Invalidation - Erreur:");
if (error instanceof AppError) {
return NextResponse.json(
{

View File

@@ -5,6 +5,7 @@ import { AppError } from "@/utils/errors";
import type { KomgaSeries } from "@/types/komga";
import { getErrorMessage } from "@/utils/errors";
import type { NextRequest } from "next/server";
import logger from "@/lib/logger";
export const revalidate = 60;
export async function GET(
@@ -21,7 +22,7 @@ export async function GET(
}
});
} catch (error) {
console.error("API Series - Erreur:", error);
logger.error({ err: error }, "API Series - Erreur:");
if (error instanceof AppError) {
return NextResponse.json(
{

View File

@@ -4,6 +4,7 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import { getErrorMessage } from "@/utils/errors";
import type { KomgaLibrary } from "@/types/komga";
import type { NextRequest } from "next/server";
import logger from "@/lib/logger";
export async function POST(request: NextRequest) {
try {
@@ -21,7 +22,7 @@ export async function POST(request: NextRequest) {
} trouvée${libraries.length > 1 ? "s" : ""}`,
});
} catch (error) {
console.error("Erreur lors du test de connexion:", error);
logger.error({ err: error }, "Erreur lors du test de connexion:");
return NextResponse.json(
{
error: {

View File

@@ -4,13 +4,14 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import type { TTLConfig } from "@/types/komga";
import { getErrorMessage } from "@/utils/errors";
import type { NextRequest } from "next/server";
import logger from "@/lib/logger";
export async function GET() {
try {
const config: TTLConfig | null = await ConfigDBService.getTTLConfig();
return NextResponse.json(config);
} catch (error) {
console.error("Erreur lors de la récupération de la configuration TTL:", error);
logger.error({ err: error }, "Erreur lors de la récupération de la configuration TTL");
if (error instanceof Error) {
if (error.message === getErrorMessage(ERROR_CODES.MIDDLEWARE.UNAUTHORIZED)) {
return NextResponse.json(
@@ -56,7 +57,7 @@ export async function POST(request: NextRequest) {
},
});
} catch (error) {
console.error("Erreur lors de la sauvegarde de la configuration TTL:", error);
logger.error({ err: error }, "Erreur lors de la sauvegarde de la configuration TTL");
if (
error instanceof Error &&
error.message === getErrorMessage(ERROR_CODES.MIDDLEWARE.UNAUTHORIZED)

View File

@@ -5,13 +5,14 @@ import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import type { UserPreferences } from "@/types/preferences";
import { getErrorMessage } from "@/utils/errors";
import logger from "@/lib/logger";
export async function GET() {
try {
const preferences: UserPreferences = await PreferencesService.getPreferences();
return NextResponse.json(preferences);
} catch (error) {
console.error("Erreur lors de la récupération des préférences:", error);
logger.error({ err: error }, "Erreur lors de la récupération des préférences:");
if (error instanceof AppError) {
return NextResponse.json(
{
@@ -45,7 +46,7 @@ export async function PUT(request: NextRequest) {
);
return NextResponse.json(updatedPreferences);
} catch (error) {
console.error("Erreur lors de la mise à jour des préférences:", error);
logger.error({ err: error }, "Erreur lors de la mise à jour des préférences:");
if (error instanceof AppError) {
return NextResponse.json(
{

View File

@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from "next/server";
import { UserService } from "@/lib/services/user.service";
import { AppError } from "@/utils/errors";
import { AuthServerService } from "@/lib/services/auth-server.service";
import logger from "@/lib/logger";
export async function PUT(request: NextRequest) {
try {
@@ -29,7 +30,7 @@ export async function PUT(request: NextRequest) {
return NextResponse.json({ success: true });
} catch (error) {
console.error("Erreur lors du changement de mot de passe:", error);
logger.error({ err: error }, "Erreur lors du changement de mot de passe:");
if (error instanceof AppError) {
return NextResponse.json(

View File

@@ -1,6 +1,7 @@
import { NextResponse } from "next/server";
import { UserService } from "@/lib/services/user.service";
import { AppError } from "@/utils/errors";
import logger from "@/lib/logger";
export async function GET() {
try {
@@ -11,7 +12,7 @@ export async function GET() {
return NextResponse.json({ ...profile, stats });
} catch (error) {
console.error("Erreur lors de la récupération du profil:", error);
logger.error({ err: error }, "Erreur lors de la récupération du profil:");
if (error instanceof AppError) {
return NextResponse.json(

View File

@@ -10,6 +10,7 @@ import { AuthProvider } from "@/components/providers/AuthProvider";
import { cookies } from "next/headers";
import { defaultPreferences } from "@/types/preferences";
import type { UserPreferences } from "@/types/preferences";
import logger from "@/lib/logger";
const inter = Inter({ subsets: ["latin"], display: "swap", adjustFontFallback: false, preload: false });
@@ -83,7 +84,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
userIsAdmin = isAdminCheck.value;
}
} catch (error) {
console.error("Erreur lors du chargement des préférences:", error);
logger.error({ err: error }, "Erreur lors du chargement des préférences:");
}
return (

View File

@@ -14,6 +14,7 @@ import type { KomgaSeries, KomgaLibrary } from "@/types/komga";
import type { UserPreferences } from "@/types/preferences";
import { Container } from "@/components/ui/container";
import { Section } from "@/components/ui/section";
import logger from "@/lib/logger";
interface ClientLibraryPageProps {
currentPage: number;
@@ -71,7 +72,7 @@ export function ClientLibraryPage({
setLibrary(data.library);
setSeries(data.series);
} catch (err) {
console.error("Error fetching library series:", err);
logger.error({ err }, "Error fetching library series");
setError(err instanceof Error ? err.message : "SERIES_FETCH_ERROR");
} finally {
setLoading(false);
@@ -117,7 +118,7 @@ export function ClientLibraryPage({
return { success: true };
} catch (error) {
console.error("Error during refresh:", error);
logger.error({ err: error }, "Error during refresh:");
return { success: false, error: "Error refreshing library" };
}
};
@@ -150,7 +151,7 @@ export function ClientLibraryPage({
setLibrary(data.library);
setSeries(data.series);
} catch (err) {
console.error("Error fetching library series:", err);
logger.error({ err }, "Error fetching library series");
setError(err instanceof Error ? err.message : "SERIES_FETCH_ERROR");
} finally {
setLoading(false);

View File

@@ -11,6 +11,7 @@ import type { LibraryResponse } from "@/types/library";
import type { KomgaBook, KomgaSeries } from "@/types/komga";
import type { UserPreferences } from "@/types/preferences";
import { ERROR_CODES } from "@/constants/errorCodes";
import logger from "@/lib/logger";
interface ClientSeriesPageProps {
seriesId: string;
@@ -61,7 +62,7 @@ export function ClientSeriesPage({
setSeries(data.series);
setBooks(data.books);
} catch (err) {
console.error("Error fetching series books:", err);
logger.error({ err }, "Error fetching series books");
setError(err instanceof Error ? err.message : ERROR_CODES.BOOK.PAGES_FETCH_ERROR);
} finally {
setLoading(false);
@@ -103,7 +104,7 @@ export function ClientSeriesPage({
return { success: true };
} catch (error) {
console.error("Erreur lors du rafraîchissement:", error);
logger.error({ err: error }, "Erreur lors du rafraîchissement:");
return { success: false, error: "Erreur lors du rafraîchissement de la série" };
}
};
@@ -132,7 +133,7 @@ export function ClientSeriesPage({
setSeries(data.series);
setBooks(data.books);
} catch (err) {
console.error("Error fetching series books:", err);
logger.error({ err }, "Error fetching series books");
setError(err instanceof Error ? err.message : ERROR_CODES.BOOK.PAGES_FETCH_ERROR);
} finally {
setLoading(false);

View File

@@ -2,6 +2,7 @@ import { ConfigDBService } from "@/lib/services/config-db.service";
import { ClientSettings } from "@/components/settings/ClientSettings";
import type { Metadata } from "next";
import type { KomgaConfig, TTLConfig } from "@/types/komga";
import logger from "@/lib/logger";
export const dynamic = 'force-dynamic';
@@ -30,7 +31,7 @@ export default async function SettingsPage() {
// Récupérer la configuration TTL
ttlConfig = await ConfigDBService.getTTLConfig();
} catch (error) {
console.error("Erreur lors de la récupération de la configuration:", error);
logger.error({ err: error }, "Erreur lors de la récupération de la configuration:");
// On ne fait rien si la config n'existe pas, on laissera le composant client gérer l'état initial
}

View File

@@ -12,6 +12,7 @@ import Image from "next/image";
import Link from "next/link";
import { BookOfflineButton } from "@/components/ui/book-offline-button";
import { useTranslate } from "@/hooks/useTranslate";
import logger from "@/lib/logger";
type BookStatus = "idle" | "downloading" | "available" | "error";
@@ -54,7 +55,7 @@ export function DownloadManager() {
status,
});
} catch (error) {
console.error(`Erreur lors de la récupération du livre ${bookId}:`, error);
logger.error({ err: error }, `Erreur lors de la récupération du livre ${bookId}:`);
localStorage.removeItem(key);
}
}
@@ -62,7 +63,7 @@ export function DownloadManager() {
}
setDownloadedBooks(books);
} catch (error) {
console.error("Erreur lors du chargement des livres:", error);
logger.error({ err: error }, "Erreur lors du chargement des livres:");
toast({
title: "Erreur",
description: "Impossible de charger les livres téléchargés",
@@ -122,7 +123,7 @@ export function DownloadManager() {
description: t("downloads.toast.deletedDesc"),
});
} catch (error) {
console.error("Erreur lors de la suppression du livre:", error);
logger.error({ err: error }, "Erreur lors de la suppression du livre:");
toast({
title: t("downloads.toast.error"),
description: t("downloads.toast.errorDesc"),

View File

@@ -9,6 +9,7 @@ import { PullToRefreshIndicator } from "@/components/common/PullToRefreshIndicat
import { usePullToRefresh } from "@/hooks/usePullToRefresh";
import { ERROR_CODES } from "@/constants/errorCodes";
import type { HomeData } from "@/types/home";
import logger from "@/lib/logger";
export function ClientHomePage() {
const router = useRouter();
@@ -41,7 +42,7 @@ export function ClientHomePage() {
const homeData = await response.json();
setData(homeData);
} catch (err) {
console.error("Error fetching home data:", err);
logger.error({ err }, "Error fetching home data");
setError(err instanceof Error ? err.message : ERROR_CODES.KOMGA.SERVER_UNREACHABLE);
} finally {
setLoading(false);
@@ -78,7 +79,7 @@ export function ClientHomePage() {
return { success: true };
} catch (error) {
console.error("Erreur lors du rafraîchissement:", error);
logger.error({ err: error }, "Erreur lors du rafraîchissement:");
return { success: false, error: "Erreur lors du rafraîchissement de la page d'accueil" };
}
};

View File

@@ -18,7 +18,7 @@ interface HeroSectionProps {
export function HeroSection({ series }: HeroSectionProps) {
const { t } = useTranslate();
// console.log("HeroSection - Séries reçues:", {
// logger.info("HeroSection - Séries reçues:", {
// count: series?.length || 0,
// firstSeries: series?.[0],
// });

View File

@@ -28,7 +28,7 @@ export function HomeContent({ data, refreshHome }: HomeContentProps) {
}, [data.ongoing]);
// Vérification des données pour le debug
// console.log("HomeContent - Données reçues:", {
// logger.info("HomeContent - Données reçues:", {
// ongoingCount: data.ongoing?.length || 0,
// recentlyReadCount: data.recentlyRead?.length || 0,
// onDeckCount: data.onDeck?.length || 0,

View File

@@ -12,6 +12,7 @@ import { NetworkStatus } from "../ui/NetworkStatus";
import { usePreferences } from "@/contexts/PreferencesContext";
import { ImageCacheProvider } from "@/contexts/ImageCacheContext";
import type { KomgaLibrary, KomgaSeries } from "@/types/komga";
import logger from "@/lib/logger";
// Routes qui ne nécessitent pas d'authentification
const publicRoutes = ["/login", "/register"];
@@ -52,7 +53,7 @@ export default function ClientLayout({ children, initialLibraries = [], initialF
setRandomBookId(data.bookId);
}
} catch (error) {
console.error("Erreur lors de la récupération d'un book aléatoire:", error);
logger.error({ err: error }, "Erreur lors de la récupération d'un book aléatoire:");
}
}
}, [backgroundType, libraryIdsString]);

View File

@@ -14,6 +14,7 @@ import { useToast } from "@/components/ui/use-toast";
import { useTranslate } from "@/hooks/useTranslate";
import { NavButton } from "@/components/ui/nav-button";
import { IconButton } from "@/components/ui/icon-button";
import logger from "@/lib/logger";
interface SidebarProps {
isOpen: boolean;
@@ -44,7 +45,7 @@ export function Sidebar({ isOpen, onClose, initialLibraries, initialFavorites, u
const data = await response.json();
setLibraries(data);
} catch (error) {
console.error("Erreur de chargement des bibliothèques:", error);
logger.error({ err: error }, "Erreur de chargement des bibliothèques:");
toast({
title: "Erreur",
description:
@@ -82,7 +83,7 @@ export function Sidebar({ isOpen, onClose, initialLibraries, initialFavorites, u
const results = await Promise.all(promises);
setFavorites(results.filter((series): series is KomgaSeries => series !== null));
} catch (error) {
console.error("Erreur de chargement des favoris:", error);
logger.error({ err: error }, "Erreur de chargement des favoris:");
toast({
title: "Erreur",
description:
@@ -126,7 +127,7 @@ export function Sidebar({ isOpen, onClose, initialLibraries, initialFavorites, u
setFavorites([]);
onClose();
} catch (error) {
console.error("Erreur lors de la déconnexion:", error);
logger.error({ err: error }, "Erreur lors de la déconnexion:");
toast({
title: "Erreur",
description: "Une erreur est survenue lors de la déconnexion",

View File

@@ -7,6 +7,7 @@ import { useToast } from "@/components/ui/use-toast";
import { cn } from "@/lib/utils";
import { useTranslation } from "react-i18next";
import { useRouter } from "next/navigation";
import logger from "@/lib/logger";
interface ScanButtonProps {
libraryId: string;
@@ -51,7 +52,7 @@ export function ScanButton({ libraryId }: ScanButtonProps) {
description: t("library.scan.complete.description"),
});
} catch (error) {
console.error("Error invalidating cache after scan:", error);
logger.error({ err: error }, "Error invalidating cache after scan:");
toast({
variant: "destructive",
title: t("library.scan.error.title"),

View File

@@ -6,6 +6,7 @@ import { BookSkeleton } from "@/components/skeletons/BookSkeleton";
import { ErrorMessage } from "@/components/ui/ErrorMessage";
import { ERROR_CODES } from "@/constants/errorCodes";
import type { KomgaBook } from "@/types/komga";
import logger from "@/lib/logger";
interface ClientBookPageProps {
bookId: string;
@@ -35,7 +36,7 @@ export function ClientBookPage({ bookId }: ClientBookPageProps) {
const bookData = await response.json();
setData(bookData);
} catch (err) {
console.error("Error fetching book:", err);
logger.error({ err }, "Error fetching book");
setError(err instanceof Error ? err.message : ERROR_CODES.BOOK.PAGES_FETCH_ERROR);
} finally {
setLoading(false);

View File

@@ -2,6 +2,7 @@ import type { ThumbnailProps } from "../types";
import { ImageLoader } from "@/components/ui/image-loader";
import { cn } from "@/lib/utils";
import { forwardRef, useEffect, useState, useCallback, useRef, useImperativeHandle } from "react";
import logger from "@/lib/logger";
export const Thumbnail = forwardRef<HTMLButtonElement, ThumbnailProps>(
(
@@ -73,7 +74,7 @@ export const Thumbnail = forwardRef<HTMLButtonElement, ThumbnailProps>(
setIsLoading(false);
}
} catch (error) {
console.error(`Erreur lors du chargement de la miniature ${pageNumber}:`, error);
logger.error({ err: error }, `Erreur lors du chargement de la miniature ${pageNumber}:`);
setHasError(true);
setIsLoading(false);
}
@@ -103,7 +104,7 @@ export const Thumbnail = forwardRef<HTMLButtonElement, ThumbnailProps>(
});
}, delay);
} else {
console.error(
logger.error(
`Échec du chargement de l'image pour la page ${pageNumber} après ${maxAttempts} tentatives`
);
setHasError(true);

View File

@@ -1,4 +1,5 @@
import { useState, useEffect } from "react";
import logger from "@/lib/logger";
export const useFullscreen = () => {
const [isFullscreen, setIsFullscreen] = useState(false);
@@ -13,7 +14,7 @@ export const useFullscreen = () => {
return () => {
document.removeEventListener("fullscreenchange", handleFullscreenChange);
if (document.fullscreenElement) {
document.exitFullscreen().catch(console.error);
document.exitFullscreen().catch(err => logger.error({ err }, "Erreur lors de la sortie du mode plein écran"));
}
};
}, []);
@@ -26,7 +27,7 @@ export const useFullscreen = () => {
await element.requestFullscreen();
}
} catch (error) {
console.error("Erreur lors du changement de mode plein écran:", error);
logger.error({ err: error }, "Erreur lors du changement de mode plein écran:");
}
};

View File

@@ -1,4 +1,5 @@
import { useState, useCallback, useEffect, useRef } from "react";
import logger from "@/lib/logger";
interface ImageDimensions {
width: number;
@@ -200,7 +201,7 @@ export function useImageLoader({ bookId, pages: _pages, prefetchCount = 5, nextB
setImageBlobUrls(newUrls);
} catch (error) {
console.error('Error reloading images:', error);
logger.error({ err: error }, 'Error reloading images:');
throw error;
}
}, [imageBlobUrls, getPageUrl]);

View File

@@ -2,6 +2,7 @@ import { useState, useCallback, useRef, useEffect } from "react";
import { useRouter } from "next/navigation";
import { ClientOfflineBookService } from "@/lib/services/client-offlinebook.service";
import type { KomgaBook } from "@/types/komga";
import logger from "@/lib/logger";
interface UsePageNavigationProps {
book: KomgaBook;
@@ -46,7 +47,7 @@ export function usePageNavigation({
body: JSON.stringify({ page, completed }),
});
} catch (error) {
console.error("Sync error:", error);
logger.error({ err: error }, "Sync error:");
}
},
[book, pages.length]

View File

@@ -12,6 +12,7 @@ import { useTranslate } from "@/hooks/useTranslate";
import { SeriesCover } from "@/components/ui/series-cover";
import { StatusBadge } from "@/components/ui/status-badge";
import { IconButton } from "@/components/ui/icon-button";
import logger from "@/lib/logger";
interface SeriesHeaderProps {
series: KomgaSeries;
@@ -33,7 +34,7 @@ export const SeriesHeader = ({ series, refreshSeries }: SeriesHeaderProps) => {
const favoriteIds = await response.json();
setIsFavorite(favoriteIds.includes(series.id));
} catch (error) {
console.error("Erreur lors de la vérification des favoris:", error);
logger.error({ err: error }, "Erreur lors de la vérification des favoris:");
toast({
title: "Erreur",
description:
@@ -75,7 +76,7 @@ export const SeriesHeader = ({ series, refreshSeries }: SeriesHeaderProps) => {
);
}
} catch (error) {
console.error("Erreur lors de la modification des favoris:", error);
logger.error({ err: error }, "Erreur lors de la modification des favoris:");
toast({
title: "Erreur",
description:

View File

@@ -6,6 +6,7 @@ import { useToast } from "@/components/ui/use-toast";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Activity, ImageIcon, Shield, Info } from "lucide-react";
import { Badge } from "@/components/ui/badge";
import logger from "@/lib/logger";
export function AdvancedSettings() {
const { t } = useTranslate();
@@ -22,7 +23,7 @@ export function AdvancedSettings() {
description: t("settings.komga.messages.configSaved"),
});
} catch (error) {
console.error("Erreur:", error);
logger.error({ err: error }, "Erreur:");
toast({
variant: "destructive",
title: t("settings.error.title"),
@@ -41,7 +42,7 @@ export function AdvancedSettings() {
description: t("settings.komga.messages.configSaved"),
});
} catch (error) {
console.error("Erreur:", error);
logger.error({ err: error }, "Erreur:");
toast({
variant: "destructive",
title: t("settings.error.title"),
@@ -63,7 +64,7 @@ export function AdvancedSettings() {
description: t("settings.komga.messages.configSaved"),
});
} catch (error) {
console.error("Erreur:", error);
logger.error({ err: error }, "Erreur:");
toast({
variant: "destructive",
title: t("settings.error.title"),

View File

@@ -15,6 +15,7 @@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/com
import { Slider } from "@/components/ui/slider";
import { Checkbox } from "@/components/ui/checkbox";
import type { KomgaLibrary } from "@/types/komga";
import logger from "@/lib/logger";
export function BackgroundSettings() {
const { t } = useTranslate();
@@ -38,7 +39,7 @@ export function BackgroundSettings() {
setKomgaConfigValid(libs.length > 0);
}
} catch (error) {
console.error("Erreur lors de la vérification de la config Komga:", error);
logger.error({ err: error }, "Erreur lors de la vérification de la config Komga:");
setKomgaConfigValid(false);
}
};
@@ -58,7 +59,7 @@ export function BackgroundSettings() {
description: t("settings.komga.messages.configSaved"),
});
} catch (error) {
console.error("Erreur:", error);
logger.error({ err: error }, "Erreur:");
toast({
variant: "destructive",
title: t("settings.error.title"),
@@ -80,7 +81,7 @@ export function BackgroundSettings() {
description: t("settings.komga.messages.configSaved"),
});
} catch (error) {
console.error("Erreur:", error);
logger.error({ err: error }, "Erreur:");
toast({
variant: "destructive",
title: t("settings.error.title"),
@@ -111,7 +112,7 @@ export function BackgroundSettings() {
description: t("settings.komga.messages.configSaved"),
});
} catch (error) {
console.error("Erreur:", error);
logger.error({ err: error }, "Erreur:");
toast({
variant: "destructive",
title: t("settings.error.title"),
@@ -129,7 +130,7 @@ export function BackgroundSettings() {
},
});
} catch (error) {
console.error("Erreur:", error);
logger.error({ err: error }, "Erreur:");
}
};
@@ -142,7 +143,7 @@ export function BackgroundSettings() {
},
});
} catch (error) {
console.error("Erreur:", error);
logger.error({ err: error }, "Erreur:");
}
};
@@ -152,7 +153,7 @@ export function BackgroundSettings() {
const newOpacity = Math.max(0, Math.min(100, currentOpacity + delta));
await handleOpacityChange([newOpacity]);
} catch (error) {
console.error("Erreur ajustement opacité:", error);
logger.error({ err: error }, "Erreur ajustement opacité:");
}
};
@@ -162,7 +163,7 @@ export function BackgroundSettings() {
const newBlur = Math.max(0, Math.min(20, currentBlur + delta));
await handleBlurChange([newBlur]);
} catch (error) {
console.error("Erreur ajustement flou:", error);
logger.error({ err: error }, "Erreur ajustement flou:");
}
};
@@ -181,7 +182,7 @@ export function BackgroundSettings() {
},
});
} catch (error) {
console.error("Erreur:", error);
logger.error({ err: error }, "Erreur:");
}
};

View File

@@ -5,6 +5,7 @@ import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { useToast } from "@/components/ui/use-toast";
import { usePreferences } from "@/contexts/PreferencesContext";
import logger from "@/lib/logger";
export function CacheModeSwitch() {
const [isLoading, setIsLoading] = useState(false);
@@ -33,7 +34,7 @@ export function CacheModeSwitch() {
description: `Le cache est maintenant en mode ${checked ? "mémoire" : "fichier"}`,
});
} catch (error) {
console.error("Erreur lors de la modification du mode de cache:", error);
logger.error({ err: error }, "Erreur lors de la modification du mode de cache:");
toast({
variant: "destructive",
title: "Erreur",

View File

@@ -10,6 +10,7 @@ import type { TTLConfigData } from "@/types/komga";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { useImageCache } from "@/contexts/ImageCacheContext";
import logger from "@/lib/logger";
interface CacheSettingsProps {
initialTTLConfig: TTLConfigData | null;
@@ -141,7 +142,7 @@ export function CacheSettings({ initialTTLConfig }: CacheSettingsProps) {
setApiCacheSize(apiSize);
}
} catch (error) {
console.error("Erreur lors de la récupération de la taille du cache:", error);
logger.error({ err: error }, "Erreur lors de la récupération de la taille du cache:");
} finally {
setIsLoadingCacheSize(false);
}
@@ -156,7 +157,7 @@ export function CacheSettings({ initialTTLConfig }: CacheSettingsProps) {
setCacheEntries(data.entries);
}
} catch (error) {
console.error("Erreur lors de la récupération des entrées du cache:", error);
logger.error({ err: error }, "Erreur lors de la récupération des entrées du cache:");
} finally {
setIsLoadingEntries(false);
}
@@ -196,7 +197,7 @@ export function CacheSettings({ initialTTLConfig }: CacheSettingsProps) {
setSwCacheEntries(entries);
}
} catch (error) {
console.error("Erreur lors de la récupération des entrées du cache SW:", error);
logger.error({ err: error }, "Erreur lors de la récupération des entrées du cache SW:");
} finally {
setIsLoadingSwEntries(false);
}
@@ -345,7 +346,7 @@ export function CacheSettings({ initialTTLConfig }: CacheSettingsProps) {
await fetchSwCacheEntries();
}
} catch (error) {
console.error("Erreur:", error);
logger.error({ err: error }, "Erreur:");
toast({
variant: "destructive",
title: t("settings.cache.error.title"),
@@ -389,7 +390,7 @@ export function CacheSettings({ initialTTLConfig }: CacheSettingsProps) {
}, 1000);
}
} catch (error) {
console.error("Erreur lors de la suppression des caches:", error);
logger.error({ err: error }, "Erreur lors de la suppression des caches:");
toast({
variant: "destructive",
title: t("settings.cache.error.title"),
@@ -438,7 +439,7 @@ export function CacheSettings({ initialTTLConfig }: CacheSettingsProps) {
description: t("settings.cache.messages.ttlSaved"),
});
} catch (error) {
console.error("Erreur lors de la sauvegarde:", error);
logger.error({ err: error }, "Erreur lors de la sauvegarde:");
toast({
variant: "destructive",
title: t("settings.cache.error.title"),

View File

@@ -4,6 +4,7 @@ import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";
import { useToast } from "@/components/ui/use-toast";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import logger from "@/lib/logger";
export function DisplaySettings() {
const { t } = useTranslate();
@@ -18,7 +19,7 @@ export function DisplaySettings() {
description: t("settings.komga.messages.configSaved"),
});
} catch (error) {
console.error("Erreur détaillée:", error);
logger.error({ err: error }, "Erreur détaillée:");
toast({
variant: "destructive",
title: t("settings.error.title"),
@@ -65,7 +66,7 @@ export function DisplaySettings() {
description: t("settings.komga.messages.configSaved"),
});
} catch (error) {
console.error("Erreur détaillée:", error);
logger.error({ err: error }, "Erreur détaillée:");
toast({
variant: "destructive",
title: t("settings.error.title"),

View File

@@ -6,6 +6,7 @@ import { useToast } from "@/components/ui/use-toast";
import { Network, Loader2 } from "lucide-react";
import type { KomgaConfig } from "@/types/komga";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import logger from "@/lib/logger";
interface KomgaSettingsProps {
initialConfig: KomgaConfig | null;
@@ -61,7 +62,7 @@ export function KomgaSettings({ initialConfig }: KomgaSettingsProps) {
description: t("settings.komga.messages.connectionSuccess"),
});
} catch (error) {
console.error("Erreur:", error);
logger.error({ err: error }, "Erreur:");
toast({
variant: "destructive",
title: t("settings.komga.error.title"),
@@ -125,7 +126,7 @@ export function KomgaSettings({ initialConfig }: KomgaSettingsProps) {
// Forcer un rechargement complet de la page
window.location.reload();
} catch (error) {
console.error("Erreur lors de la sauvegarde:", error);
logger.error({ err: error }, "Erreur lors de la sauvegarde:");
toast({
variant: "destructive",
title: t("settings.komga.error.title"),

View File

@@ -3,6 +3,7 @@
import { AlertCircle, RefreshCw } from "lucide-react";
import { useTranslate } from "@/hooks/useTranslate";
import { Button } from "@/components/ui/button";
import logger from "@/lib/logger";
interface ErrorMessageProps {
errorCode: string;
@@ -23,7 +24,7 @@ export const ErrorMessage = ({
const message = t(`errors.${errorCode}`);
if (error) {
console.error(error);
logger.error(error);
}
if (variant === "form") {

View File

@@ -2,6 +2,7 @@
import { useEffect, useState } from "react";
import { Download, X } from "lucide-react";
import logger from "@/lib/logger";
interface BeforeInstallPromptEvent extends Event {
prompt: () => Promise<void>;
@@ -83,7 +84,7 @@ export function InstallPWA() {
setIsInstallable(false);
}
} catch (error) {
console.error("Erreur lors de l'installation:", error);
logger.error({ err: error }, "Erreur lors de l'installation:");
}
setDeferredPrompt(null);

View File

@@ -5,6 +5,7 @@ import { Download, Check, Loader2 } from "lucide-react";
import { Button } from "./button";
import { useToast } from "./use-toast";
import type { KomgaBook } from "@/types/komga";
import logger from "@/lib/logger";
interface BookOfflineButtonProps {
book: KomgaBook;
@@ -81,7 +82,7 @@ export function BookOfflineButton({ book, className }: BookOfflineButtonProps) {
retryCount++;
if (retryCount === maxRetries) {
failedPages++;
console.error(
logger.error(
`Échec du téléchargement de la page ${i} après ${maxRetries} tentatives`
);
}
@@ -97,7 +98,7 @@ export function BookOfflineButton({ book, className }: BookOfflineButtonProps) {
retryCount++;
if (retryCount === maxRetries) {
failedPages++;
console.error(`Erreur lors du téléchargement de la page ${i}:`, error);
logger.error({ err: error }, `Erreur lors du téléchargement de la page ${i}:`);
}
await new Promise((resolve) => setTimeout(resolve, 1000));
}
@@ -143,7 +144,7 @@ export function BookOfflineButton({ book, className }: BookOfflineButtonProps) {
});
}
} catch (error) {
console.error("Erreur lors du téléchargement:", error);
logger.error({ err: error }, "Erreur lors du téléchargement:");
// Ne pas changer le statut si le téléchargement a été volontairement annulé
if ((error as Error)?.message !== "Téléchargement annulé") {
setBookStatus(book.id, { status: "error", progress: 0, timestamp: Date.now() });
@@ -191,7 +192,7 @@ export function BookOfflineButton({ book, className }: BookOfflineButtonProps) {
timestamp: Date.now(),
});
} catch (error) {
console.error("Erreur lors de la vérification du cache:", error);
logger.error({ err: error }, "Erreur lors de la vérification du cache:");
setBookStatus(book.id, { status: "error", progress: 0, timestamp: Date.now() });
}
}, [book.id, book.media.pagesCount, setBookStatus]);
@@ -255,7 +256,7 @@ export function BookOfflineButton({ book, className }: BookOfflineButtonProps) {
await downloadBook();
}
} catch (error) {
console.error("Erreur lors de la gestion du cache:", error);
logger.error({ err: error }, "Erreur lors de la gestion du cache:");
setBookStatus(book.id, { status: "error", progress: 0, timestamp: Date.now() });
toast({
title: "Erreur",

View File

@@ -6,6 +6,7 @@ import { useToast } from "./use-toast";
import { ClientOfflineBookService } from "@/lib/services/client-offlinebook.service";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import logger from "@/lib/logger";
interface MarkAsReadButtonProps {
bookId: string;
@@ -49,7 +50,7 @@ export function MarkAsReadButton({
});
onSuccess?.();
} catch (error) {
console.error("Erreur lors de la mise à jour du progresseur de lecture:", error);
logger.error({ err: error }, "Erreur lors de la mise à jour du progresseur de lecture:");
toast({
title: t("books.actions.markAsRead.error.title"),
description: t("books.actions.markAsRead.error.description"),

View File

@@ -6,6 +6,7 @@ import { useToast } from "./use-toast";
import { ClientOfflineBookService } from "@/lib/services/client-offlinebook.service";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import logger from "@/lib/logger";
interface MarkAsUnreadButtonProps {
bookId: string;
@@ -39,7 +40,7 @@ export function MarkAsUnreadButton({ bookId, onSuccess, className }: MarkAsUnrea
});
onSuccess?.();
} catch (error) {
console.error("Erreur lors de la mise à jour du progresseur de lecture:", error);
logger.error({ err: error }, "Erreur lors de la mise à jour du progresseur de lecture:");
toast({
title: t("books.actions.markAsUnread.error.title"),
description: t("books.actions.markAsUnread.error.description"),

View File

@@ -1,6 +1,7 @@
"use client";
import React, { createContext, useContext, useState, useCallback, useEffect } from "react";
import logger from "@/lib/logger";
interface ImageCacheContextType {
cacheVersion: string;
@@ -29,8 +30,7 @@ export function ImageCacheProvider({ children }: { children: React.ReactNode })
const newVersion = Date.now().toString();
setCacheVersion(newVersion);
localStorage.setItem("imageCacheVersion", newVersion);
// eslint-disable-next-line no-console
console.log("🗑️ Image cache flushed - new version:", newVersion);
logger.info(`🗑️ Image cache flushed - new version: ${newVersion}`);
}, []);
const getImageUrl = useCallback(

View File

@@ -6,6 +6,7 @@ import { ERROR_CODES } from "../constants/errorCodes";
import { AppError } from "../utils/errors";
import type { UserPreferences } from "@/types/preferences";
import { defaultPreferences } from "@/types/preferences";
import logger from "@/lib/logger";
interface PreferencesContextType {
preferences: UserPreferences;
@@ -42,7 +43,7 @@ export function PreferencesProvider({
});
setHasLoadedPrefs(true);
} catch (error) {
console.error("Erreur lors de la récupération des préférences:", error);
logger.error({ err: error }, "Erreur lors de la récupération des préférences");
setPreferences(defaultPreferences);
} finally {
setIsLoading(false);
@@ -83,7 +84,7 @@ export function PreferencesProvider({
return updatedPreferences;
} catch (error) {
console.error("Erreur lors de la mise à jour des préférences:", error);
logger.error({ err: error }, "Erreur lors de la mise à jour des préférences");
throw error;
}
}, []);

View File

@@ -2,6 +2,7 @@
import { useState, useEffect, useCallback } from "react";
import { useNetworkStatus } from "./useNetworkStatus";
import logger from "@/lib/logger";
type BookStatus = "idle" | "downloading" | "available" | "error";
@@ -47,7 +48,7 @@ export function useBookOfflineStatus(bookId: string) {
const bookPages = await cache.match(`/api/komga/images/books/${bookId}/pages`);
setIsAvailableOffline(!!bookPages);
} catch (error) {
console.error("Erreur lors de la vérification du cache:", error);
logger.error({ err: error, bookId }, "Erreur lors de la vérification du cache");
setIsAvailableOffline(false);
} finally {
setIsChecking(false);

View File

@@ -1,4 +1,5 @@
import { usePreferences } from "@/contexts/PreferencesContext";
import logger from "@/lib/logger";
export function useDisplayPreferences() {
const { preferences, updatePreferences } = usePreferences();
@@ -12,7 +13,7 @@ export function useDisplayPreferences() {
},
});
} catch (error) {
console.error("Erreur lors de la mise à jour du mode compact:", error);
logger.error({ err: error }, "Erreur lors de la mise à jour du mode compact");
}
};
@@ -25,7 +26,7 @@ export function useDisplayPreferences() {
},
});
} catch (error) {
console.error("Erreur lors de la mise à jour de la taille de page:", error);
logger.error({ err: error }, "Erreur lors de la mise à jour de la taille de page");
}
};

View File

@@ -1,6 +1,7 @@
"use client";
import { useEffect, useRef, useState } from "react";
import logger from "@/lib/logger";
interface UsePullToRefreshOptions {
onRefresh: () => Promise<void>;
@@ -135,7 +136,7 @@ export function usePullToRefresh({
try {
await onRefresh();
} catch (error) {
console.error("Pull to refresh error:", error);
logger.error({ err: error }, "Pull to refresh error");
} finally {
isRefreshingRef.current = false;
// Activer l'animation de disparition

View File

@@ -1,6 +1,7 @@
import NextAuth from "next-auth";
import Credentials from "next-auth/providers/credentials";
import { AuthServerService } from "@/lib/services/auth-server.service";
import logger from "@/lib/logger";
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
@@ -28,7 +29,7 @@ export const { handlers, auth, signIn, signOut } = NextAuth({
roles: userData.roles,
};
} catch (error) {
console.error("Auth error:", error);
logger.error({ err: error }, "Auth error");
return null;
}
},

34
src/lib/logger.ts Normal file
View File

@@ -0,0 +1,34 @@
import pino from 'pino';
const isProduction = process.env.NODE_ENV === 'production';
const logger = pino({
level: isProduction ? 'info' : 'debug',
...(isProduction
? {}
: {
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'SYS:dd/mm/yyyy HH:MM:ss',
ignore: 'pid,hostname',
singleLine: true,
},
},
}),
formatters: {
level: (label) => {
return { level: label.toUpperCase() };
},
},
});
// Prevent memory leaks in development (Node.js runtime only)
if (!isProduction && typeof process.stdout !== 'undefined') {
process.stdout.setMaxListeners?.(20);
process.stderr.setMaxListeners?.(20);
}
export default logger;

View File

@@ -1,5 +1,6 @@
import { NextRequest } from "next/server";
import { getToken } from "next-auth/jwt";
import logger from "@/lib/logger";
export async function getAuthSession(request: NextRequest) {
try {
@@ -20,7 +21,7 @@ export async function getAuthSession(request: NextRequest) {
}
};
} catch (error) {
console.error("Auth error in middleware:", error);
logger.error({ err: error }, "Auth error in middleware");
return null;
}
}

View File

@@ -1,3 +1,5 @@
import logger from "@/lib/logger";
export const registerServiceWorker = async () => {
if (typeof window === "undefined" || !("serviceWorker" in navigator)) {
return;
@@ -5,8 +7,8 @@ export const registerServiceWorker = async () => {
try {
await navigator.serviceWorker.register("/sw.js");
// console.log("Service Worker registered with scope:", registration.scope);
// logger.info("Service Worker registered with scope:", registration.scope);
} catch (error) {
console.error("Service Worker registration failed:", error);
logger.error({ err: error }, "Service Worker registration failed:");
}
};

View File

@@ -10,6 +10,7 @@ import { RequestMonitorService } from "./request-monitor.service";
import { RequestQueueService } from "./request-queue.service";
import { CircuitBreakerService } from "./circuit-breaker.service";
import { PreferencesService } from "./preferences.service";
import logger from "@/lib/logger";
export type { CacheType };
@@ -42,14 +43,14 @@ export abstract class BaseApiService {
const preferences = await PreferencesService.getPreferences();
return preferences.komgaMaxConcurrentRequests;
} catch (error) {
console.error('Failed to get preferences for request queue:', error);
logger.error({ err: error }, 'Failed to get preferences for request queue');
return 5; // Valeur par défaut
}
});
this.requestQueueInitialized = true;
} catch (error) {
console.error('Failed to initialize request queue:', error);
logger.error({ err: error }, 'Failed to initialize request queue');
}
}
@@ -68,7 +69,7 @@ export abstract class BaseApiService {
const preferences = await PreferencesService.getPreferences();
return preferences.circuitBreakerConfig;
} catch (error) {
console.error('Failed to get preferences for circuit breaker:', error);
logger.error({ err: error }, 'Failed to get preferences for circuit breaker');
return {
threshold: 5,
timeout: 30000,
@@ -79,7 +80,7 @@ export abstract class BaseApiService {
this.circuitBreakerInitialized = true;
} catch (error) {
console.error('Failed to initialize circuit breaker:', error);
logger.error({ err: error }, 'Failed to initialize circuit breaker');
}
}
@@ -103,7 +104,7 @@ export abstract class BaseApiService {
if (error instanceof AppError && error.code === ERROR_CODES.KOMGA.MISSING_CONFIG) {
throw error;
}
console.error("Erreur lors de la récupération de la configuration:", error);
logger.error({ err: error }, "Erreur lors de la récupération de la configuration");
throw new AppError(ERROR_CODES.KOMGA.MISSING_CONFIG, {}, error);
}
}
@@ -199,7 +200,7 @@ export abstract class BaseApiService {
} catch (fetchError: any) {
// Gestion spécifique des erreurs DNS
if (fetchError?.cause?.code === 'EAI_AGAIN' || fetchError?.code === 'EAI_AGAIN') {
console.error(`DNS resolution failed for ${url}. Retrying with different DNS settings...`);
logger.error(`DNS resolution failed for ${url}. Retrying with different DNS settings...`);
// Retry avec des paramètres DNS différents
return await fetch(url, {
@@ -218,8 +219,7 @@ export abstract class BaseApiService {
// Retry automatique sur timeout de connexion (cold start)
if (fetchError?.cause?.code === 'UND_ERR_CONNECT_TIMEOUT') {
// eslint-disable-next-line no-console
console.log(`⏱️ Connection timeout for ${url}. Retrying once (cold start)...`);
logger.info(`⏱️ Connection timeout for ${url}. Retrying once (cold start)...`);
return await fetch(url, {
headers,

View File

@@ -8,6 +8,7 @@ import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors";
import { SeriesService } from "./series.service";
import type { Series } from "@/types/series";
import logger from "@/lib/logger";
export class BookService extends BaseApiService {
private static async getImageCacheMaxAge(): Promise<number> {
@@ -16,7 +17,7 @@ export class BookService extends BaseApiService {
const maxAge = ttlConfig?.imageCacheMaxAge ?? 2592000;
return maxAge;
} catch (error) {
console.error('[ImageCache] Error fetching TTL config:', error);
logger.error({ err: error }, '[ImageCache] Error fetching TTL config');
return 2592000; // 30 jours par défaut en cas d'erreur
}
}

View File

@@ -3,6 +3,7 @@
* Évite l'effet avalanche en coupant les requêtes vers un service défaillant
*/
import type { CircuitBreakerConfig } from "@/types/preferences";
import logger from "@/lib/logger";
interface CircuitBreakerState {
state: 'CLOSED' | 'OPEN' | 'HALF_OPEN';
@@ -47,7 +48,7 @@ class CircuitBreaker {
resetTimeout: prefConfig.resetTimeout ?? 60000,
};
} catch (error) {
console.error('Error getting circuit breaker config from preferences:', error);
logger.error({ err: error }, 'Error getting circuit breaker config from preferences');
return this.config;
}
}
@@ -78,8 +79,7 @@ class CircuitBreaker {
if (this.state.state === 'HALF_OPEN') {
this.state.failureCount = 0;
this.state.state = 'CLOSED';
// eslint-disable-next-line no-console
console.log('[CIRCUIT-BREAKER] ✅ Circuit closed - Komga recovered');
logger.info('[CIRCUIT-BREAKER] ✅ Circuit closed - Komga recovered');
}
}
@@ -90,7 +90,7 @@ class CircuitBreaker {
if (this.state.failureCount >= config.failureThreshold) {
this.state.state = 'OPEN';
this.state.nextAttemptTime = Date.now() + config.resetTimeout;
console.warn(`[CIRCUIT-BREAKER] 🔴 Circuit OPEN - Komga failing (${this.state.failureCount} failures, reset in ${config.resetTimeout}ms)`);
logger.warn(`[CIRCUIT-BREAKER] 🔴 Circuit OPEN - Komga failing (${this.state.failureCount} failures, reset in ${config.resetTimeout}ms)`);
}
}
@@ -105,8 +105,7 @@ class CircuitBreaker {
lastFailureTime: 0,
nextAttemptTime: 0,
};
// eslint-disable-next-line no-console
console.log('[CIRCUIT-BREAKER] 🔄 Circuit reset');
logger.info('[CIRCUIT-BREAKER] 🔄 Circuit reset');
}
}

View File

@@ -3,6 +3,7 @@ import { getCurrentUser } from "../auth-utils";
import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors";
import type { User } from "@/types/komga";
import logger from "@/lib/logger";
export class FavoriteService {
private static readonly FAVORITES_CHANGE_EVENT = "favoritesChanged";
@@ -38,7 +39,7 @@ export class FavoriteService {
});
return !!favorite;
} catch (error) {
console.error("Erreur lors de la vérification du favori:", error);
logger.error({ err: error, seriesId }, "Erreur lors de la vérification du favori");
return false;
}
}

View File

@@ -1,6 +1,7 @@
import { BaseApiService } from "./base-api.service";
import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors";
import logger from "@/lib/logger";
export interface ImageResponse {
buffer: Buffer;
@@ -23,7 +24,7 @@ export class ImageService extends BaseApiService {
contentType,
};
} catch (error) {
console.error("Erreur lors de la récupération de l'image:", error);
logger.error({ err: error }, "Erreur lors de la récupération de l'image");
throw new AppError(ERROR_CODES.IMAGE.FETCH_ERROR, {}, error);
}
}

View File

@@ -2,6 +2,8 @@
* Service de monitoring des requêtes concurrentes vers Komga
* Permet de tracker le nombre de requêtes actives et d'alerter en cas de charge élevée
*/
import logger from "@/lib/logger";
class RequestMonitor {
private activeRequests = 0;
private readonly thresholds = {
@@ -29,12 +31,11 @@ class RequestMonitor {
const count = this.activeRequests;
if (count >= this.thresholds.critical) {
console.warn(`[REQUEST-MONITOR] 🔴 CRITICAL concurrency: ${count} active requests`);
logger.warn(`[REQUEST-MONITOR] 🔴 CRITICAL concurrency: ${count} active requests`);
} else if (count >= this.thresholds.high) {
console.warn(`[REQUEST-MONITOR] ⚠️ HIGH concurrency: ${count} active requests`);
logger.warn(`[REQUEST-MONITOR] ⚠️ HIGH concurrency: ${count} active requests`);
} else if (count >= this.thresholds.warning) {
// eslint-disable-next-line no-console
console.log(`[REQUEST-MONITOR] ⚡ Warning concurrency: ${count} active requests`);
logger.info(`[REQUEST-MONITOR] ⚡ Warning concurrency: ${count} active requests`);
}
}
}

View File

@@ -2,6 +2,7 @@
* Service de gestion de queue pour limiter les requêtes concurrentes vers Komga
* Évite de surcharger Komga avec trop de requêtes simultanées
*/
import logger from "@/lib/logger";
interface QueuedRequest<T> {
execute: () => Promise<T>;
@@ -35,7 +36,7 @@ class RequestQueue {
try {
return await this.getMaxConcurrent();
} catch (error) {
console.error('Error getting maxConcurrent from preferences, using default:', error);
logger.error({ err: error }, 'Error getting maxConcurrent from preferences, using default');
return this.maxConcurrent;
}
}

View File

@@ -11,6 +11,7 @@ import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors";
import type { UserPreferences } from "@/types/preferences";
import type { ServerCacheService } from "./server-cache.service";
import logger from "@/lib/logger";
export class SeriesService extends BaseApiService {
private static async getImageCacheMaxAge(): Promise<number> {
@@ -19,7 +20,7 @@ export class SeriesService extends BaseApiService {
const maxAge = ttlConfig?.imageCacheMaxAge ?? 2592000;
return maxAge;
} catch (error) {
console.error('[ImageCache] Error fetching TTL config:', error);
logger.error({ err: error }, '[ImageCache] Error fetching TTL config');
return 2592000; // 30 jours par défaut en cas d'erreur
}
}
@@ -181,7 +182,7 @@ export class SeriesService extends BaseApiService {
"SERIES"
);
} catch (error) {
console.error("Erreur lors de la récupération du premier livre:", error);
logger.error({ err: error }, "Erreur lors de la récupération du premier livre");
throw new AppError(ERROR_CODES.SERIES.FETCH_ERROR, {}, error);
}
}

View File

@@ -2,6 +2,7 @@ import fs from "fs";
import path from "path";
import { PreferencesService } from "./preferences.service";
import { getCurrentUser } from "../auth-utils";
import logger from "@/lib/logger";
export type CacheMode = "file" | "memory";
@@ -52,7 +53,7 @@ class ServerCacheService {
const preferences = await PreferencesService.getPreferences();
this.setCacheMode(preferences.cacheMode);
} catch (error) {
console.error("Error initializing cache mode from preferences:", error);
logger.error({ err: error }, "Error initializing cache mode from preferences");
// Keep default memory mode if preferences can't be loaded
}
}
@@ -93,7 +94,7 @@ class ServerCacheService {
try {
fs.rmdirSync(itemPath);
} catch (error) {
console.error(`Could not remove directory ${itemPath}:`, error);
logger.error({ err: error, path: itemPath }, `Could not remove directory ${itemPath}`);
isEmpty = false;
}
} else {
@@ -109,12 +110,12 @@ class ServerCacheService {
isEmpty = false;
}
} catch (error) {
console.error(`Could not parse file ${itemPath}:`, error);
logger.error({ err: error, path: itemPath }, `Could not parse file ${itemPath}`);
// Si le fichier est corrompu, on le supprime
try {
fs.unlinkSync(itemPath);
} catch (error) {
console.error(`Could not remove file ${itemPath}:`, error);
logger.error({ err: error, path: itemPath }, `Could not remove file ${itemPath}`);
isEmpty = false;
}
}
@@ -122,7 +123,7 @@ class ServerCacheService {
isEmpty = false;
}
} catch (error) {
console.error(`Could not access ${itemPath}:`, error);
logger.error({ err: error, path: itemPath }, `Could not access ${itemPath}`);
// En cas d'erreur sur le fichier/dossier, on continue
isEmpty = false;
continue;
@@ -197,12 +198,12 @@ class ServerCacheService {
this.memoryCache.set(key, cached);
}
} catch (error) {
console.error(`Could not parse file ${itemPath}:`, error);
logger.error({ err: error, path: itemPath }, `Could not parse file ${itemPath}`);
// Ignore les fichiers corrompus
}
}
} catch (error) {
console.error(`Could not access ${itemPath}:`, error);
logger.error({ err: error, path: itemPath }, `Could not access ${itemPath}`);
// Ignore les erreurs d'accès
}
}
@@ -221,7 +222,7 @@ class ServerCacheService {
}
fs.writeFileSync(filePath, JSON.stringify(value), "utf-8");
} catch (error) {
console.error(`Could not write cache file ${filePath}:`, error);
logger.error({ err: error, path: filePath }, `Could not write cache file ${filePath}`);
}
}
@@ -246,7 +247,7 @@ class ServerCacheService {
}
fs.writeFileSync(filePath, JSON.stringify(cacheData), "utf-8");
} catch (error) {
console.error(`Error writing cache file ${filePath}:`, error);
logger.error({ err: error, path: filePath }, `Error writing cache file ${filePath}`);
}
}
}
@@ -283,7 +284,7 @@ class ServerCacheService {
fs.unlinkSync(filePath);
return null;
} catch (error) {
console.error(`Error reading cache file ${filePath}:`, error);
logger.error({ err: error, path: filePath }, `Error reading cache file ${filePath}`);
return null;
}
}
@@ -317,7 +318,7 @@ class ServerCacheService {
isStale: cached.expiry <= Date.now(),
};
} catch (error) {
console.error(`Error reading cache file ${filePath}:`, error);
logger.error({ err: error, path: filePath }, `Error reading cache file ${filePath}`);
return null;
}
}
@@ -392,17 +393,17 @@ class ServerCacheService {
try {
fs.rmdirSync(itemPath);
} catch (error) {
console.error(`Could not remove directory ${itemPath}:`, error);
logger.error({ err: error, path: itemPath }, `Could not remove directory ${itemPath}`);
}
} else {
try {
fs.unlinkSync(itemPath);
} catch (error) {
console.error(`Could not remove file ${itemPath}:`, error);
logger.error({ err: error, path: itemPath }, `Could not remove file ${itemPath}`);
}
}
} catch (error) {
console.error(`Error accessing ${itemPath}:`, error);
logger.error({ err: error, path: itemPath }, `Error accessing ${itemPath}`);
}
}
};
@@ -410,7 +411,7 @@ class ServerCacheService {
try {
removeDirectory(this.cacheDir);
} catch (error) {
console.error("Error clearing cache:", error);
logger.error({ err: error }, "Error clearing cache");
}
}
@@ -443,8 +444,7 @@ class ServerCacheService {
if (process.env.CACHE_DEBUG === 'true') {
const icon = isStale ? '⚠️' : '✅';
const status = isStale ? 'STALE' : 'HIT';
// eslint-disable-next-line no-console
console.log(`${icon} [CACHE ${status}] ${key} | ${type} | ${(endTime - startTime).toFixed(2)}ms`);
logger.debug(`${icon} [CACHE ${status}] ${key} | ${type} | ${(endTime - startTime).toFixed(2)}ms`);
}
// Si le cache est expiré, revalider en background sans bloquer la réponse
@@ -458,8 +458,7 @@ class ServerCacheService {
// Pas de cache du tout, fetch normalement
if (process.env.CACHE_DEBUG === 'true') {
// eslint-disable-next-line no-console
console.log(`❌ [CACHE MISS] ${key} | ${type}`);
logger.debug(`❌ [CACHE MISS] ${key} | ${type}`);
}
try {
@@ -468,8 +467,7 @@ class ServerCacheService {
const endTime = performance.now();
if (process.env.CACHE_DEBUG === 'true') {
// eslint-disable-next-line no-console
console.log(`💾 [CACHE SET] ${key} | ${type} | ${(endTime - startTime).toFixed(2)}ms`);
logger.debug(`💾 [CACHE SET] ${key} | ${type} | ${(endTime - startTime).toFixed(2)}ms`);
}
return data;
@@ -494,11 +492,10 @@ class ServerCacheService {
if (process.env.CACHE_DEBUG === 'true') {
const endTime = performance.now();
// eslint-disable-next-line no-console
console.log(`🔄 [CACHE REVALIDATE] ${debugKey} | ${type} | ${(endTime - startTime).toFixed(2)}ms`);
logger.debug(`🔄 [CACHE REVALIDATE] ${debugKey} | ${type} | ${(endTime - startTime).toFixed(2)}ms`);
}
} catch (error) {
console.error(`🔴 [CACHE REVALIDATE ERROR] ${debugKey}:`, error);
logger.error({ err: error, key: debugKey }, `🔴 [CACHE REVALIDATE ERROR] ${debugKey}`);
// Ne pas relancer l'erreur car c'est en background
}
}
@@ -582,7 +579,7 @@ class ServerCacheService {
itemCount++;
}
} catch (error) {
console.error(`Could not access ${itemPath}:`, error);
logger.error({ err: error, path: itemPath }, `Could not access ${itemPath}`);
}
}
};
@@ -648,11 +645,11 @@ class ServerCacheService {
isExpired: cached.expiry <= Date.now(),
});
} catch (error) {
console.error(`Could not parse file ${itemPath}:`, error);
logger.error({ err: error, path: itemPath }, `Could not parse file ${itemPath}`);
}
}
} catch (error) {
console.error(`Could not access ${itemPath}:`, error);
logger.error({ err: error, path: itemPath }, `Could not access ${itemPath}`);
}
}
};

View File

@@ -3,6 +3,7 @@ import type { AuthConfig } from "@/types/auth";
import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors";
import type { KomgaLibrary } from "@/types/komga";
import logger from "@/lib/logger";
export class TestService extends BaseApiService {
static async testConnection(config: AuthConfig): Promise<{ libraries: KomgaLibrary[] }> {
@@ -20,7 +21,7 @@ export class TestService extends BaseApiService {
const libraries = await response.json();
return { libraries };
} catch (error) {
console.error("Erreur lors du test de connexion:", error);
logger.error({ err: error }, "Erreur lors du test de connexion");
if (error instanceof AppError) {
throw error;
}