refacto: types big review

This commit is contained in:
Julien Froidefond
2025-02-27 08:29:08 +01:00
parent 3b2d4cb0d5
commit 3c46afb294
39 changed files with 209 additions and 178 deletions

View File

@@ -166,7 +166,7 @@ Service de test de connexion
### Méthodes ### Méthodes
- `testConnection(config: AuthConfig): Promise<{ libraries: Library[] }>` - `testConnection(config: AuthConfig): Promise<{ libraries: KomgaLibrary[] }>`
- Teste la connexion au serveur Komga - Teste la connexion au serveur Komga
- Retourne les bibliothèques si succès - Retourne les bibliothèques si succès

View File

@@ -3,13 +3,14 @@ import { AuthServerService } from "@/lib/services/auth-server.service";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { ERROR_MESSAGES } from "@/constants/errorMessages";
import { AppError } from "@/utils/errors"; import { AppError } from "@/utils/errors";
import { UserData } from "@/lib/services/auth-server.service";
export async function POST(request: Request) { export async function POST(request: Request) {
try { try {
const { email, password } = await request.json(); const { email, password } = await request.json();
try { try {
const userData = await AuthServerService.loginUser(email, password); const userData: UserData = await AuthServerService.loginUser(email, password);
AuthServerService.setUserCookie(userData); AuthServerService.setUserCookie(userData);
return NextResponse.json({ return NextResponse.json({

View File

@@ -1,5 +1,5 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { AuthServerService } from "@/lib/services/auth-server.service"; import { AuthServerService, UserData } from "@/lib/services/auth-server.service";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { ERROR_MESSAGES } from "@/constants/errorMessages";
import { AppError } from "@/utils/errors"; import { AppError } from "@/utils/errors";
@@ -9,7 +9,7 @@ export async function POST(request: Request) {
const { email, password } = await request.json(); const { email, password } = await request.json();
try { try {
const userData = await AuthServerService.createUser(email, password); const userData: UserData = await AuthServerService.createUser(email, password);
AuthServerService.setUserCookie(userData); AuthServerService.setUserCookie(userData);
return NextResponse.json({ return NextResponse.json({

View File

@@ -1,12 +1,12 @@
import { NextRequest, NextResponse } from "next/server"; import { NextRequest, NextResponse } from "next/server";
import { DebugService } from "@/lib/services/debug.service"; import { DebugService, RequestTiming } from "@/lib/services/debug.service";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { ERROR_MESSAGES } from "@/constants/errorMessages";
import { AppError } from "@/utils/errors"; import { AppError } from "@/utils/errors";
export async function GET() { export async function GET() {
try { try {
const logs = await DebugService.getRequestLogs(); const logs: RequestTiming[] = await DebugService.getRequestLogs();
return NextResponse.json(logs); return NextResponse.json(logs);
} catch (error) { } catch (error) {
console.error("Erreur lors de la récupération des logs:", error); console.error("Erreur lors de la récupération des logs:", error);
@@ -35,7 +35,7 @@ export async function GET() {
export async function POST(request: NextRequest) { export async function POST(request: NextRequest) {
try { try {
const timing = await request.json(); const timing: RequestTiming = await request.json();
await DebugService.logRequest(timing); await DebugService.logRequest(timing);
return NextResponse.json({ return NextResponse.json({
message: "✅ Log enregistré avec succès", message: "✅ Log enregistré avec succès",

View File

@@ -11,7 +11,7 @@ export async function GET(
{ params }: { params: { bookId: string; pageNumber: string } } { params }: { params: { bookId: string; pageNumber: string } }
) { ) {
try { try {
const pageNumber = parseInt(params.pageNumber); const pageNumber: number = parseInt(params.pageNumber);
if (isNaN(pageNumber) || pageNumber < 0) { if (isNaN(pageNumber) || pageNumber < 0) {
return NextResponse.json( return NextResponse.json(
{ {

View File

@@ -3,10 +3,10 @@ import { BookService } from "@/lib/services/book.service";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { ERROR_MESSAGES } from "@/constants/errorMessages";
import { AppError } from "@/utils/errors"; import { AppError } from "@/utils/errors";
import { KomgaBookWithPages } from "@/types/komga";
export async function GET(request: Request, { params }: { params: { bookId: string } }) { export async function GET(request: Request, { params }: { params: { bookId: string } }) {
try { try {
const data = await BookService.getBook(params.bookId); const data: KomgaBookWithPages = await BookService.getBook(params.bookId);
return NextResponse.json(data); return NextResponse.json(data);
} catch (error) { } catch (error) {
console.error("API Books - Erreur:", error); console.error("API Books - Erreur:", error);

View File

@@ -1,11 +1,11 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { getServerCacheService } from "@/lib/services/server-cache.service"; import { getServerCacheService, ServerCacheService } from "@/lib/services/server-cache.service";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { ERROR_MESSAGES } from "@/constants/errorMessages";
export async function POST() { export async function POST() {
try { try {
const cacheService = await getServerCacheService(); const cacheService: ServerCacheService = await getServerCacheService();
cacheService.clear(); cacheService.clear();
return NextResponse.json({ message: "🧹 Cache vidé avec succès" }); return NextResponse.json({ message: "🧹 Cache vidé avec succès" });
} catch (error) { } catch (error) {

View File

@@ -1,11 +1,15 @@
import { NextResponse } from "next/server"; import { NextResponse } from "next/server";
import { getServerCacheService } from "@/lib/services/server-cache.service"; import {
CacheMode,
getServerCacheService,
ServerCacheService,
} from "@/lib/services/server-cache.service";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { ERROR_MESSAGES } from "@/constants/errorMessages";
export async function GET() { export async function GET() {
try { try {
const cacheService = await getServerCacheService(); const cacheService: ServerCacheService = await getServerCacheService();
return NextResponse.json({ mode: cacheService.getCacheMode() }); return NextResponse.json({ mode: cacheService.getCacheMode() });
} catch (error) { } catch (error) {
console.error("Erreur lors de la récupération du mode de cache:", error); console.error("Erreur lors de la récupération du mode de cache:", error);
@@ -23,7 +27,7 @@ export async function GET() {
export async function POST(request: Request) { export async function POST(request: Request) {
try { try {
const { mode } = await request.json(); const { mode }: { mode: CacheMode } = await request.json();
if (mode !== "file" && mode !== "memory") { if (mode !== "file" && mode !== "memory") {
return NextResponse.json( return NextResponse.json(
{ {
@@ -36,7 +40,7 @@ export async function POST(request: Request) {
); );
} }
const cacheService = await getServerCacheService(); const cacheService: ServerCacheService = await getServerCacheService();
cacheService.setCacheMode(mode); cacheService.setCacheMode(mode);
return NextResponse.json({ mode: cacheService.getCacheMode() }); return NextResponse.json({ mode: cacheService.getCacheMode() });
} catch (error) { } catch (error) {

View File

@@ -2,22 +2,17 @@ import { NextResponse } from "next/server";
import { ConfigDBService } from "@/lib/services/config-db.service"; import { ConfigDBService } from "@/lib/services/config-db.service";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { ERROR_MESSAGES } from "@/constants/errorMessages";
import { KomgaConfig, KomgaConfigData } from "@/types/komga";
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
export async function POST(request: Request) { export async function POST(request: Request) {
try { try {
const data = await request.json(); const data: KomgaConfigData = await request.json();
const mongoConfig = await ConfigDBService.saveConfig(data); const mongoConfig: KomgaConfig = await ConfigDBService.saveConfig(data);
// Convertir le document Mongoose en objet simple
const config = {
url: mongoConfig.url,
username: mongoConfig.username,
password: mongoConfig.password,
userId: mongoConfig.userId,
};
return NextResponse.json( return NextResponse.json(
{ message: "⚙️ Configuration sauvegardée avec succès", config }, { message: "⚙️ Configuration sauvegardée avec succès", mongoConfig },
{ status: 200 } { status: 200 }
); );
} catch (error) { } catch (error) {
@@ -47,15 +42,9 @@ export async function POST(request: Request) {
export async function GET() { export async function GET() {
try { try {
const mongoConfig = await ConfigDBService.getConfig(); const mongoConfig: KomgaConfig | null = await ConfigDBService.getConfig();
// Convertir le document Mongoose en objet simple
const config = { return NextResponse.json(mongoConfig, { status: 200 });
url: mongoConfig.url,
username: mongoConfig.username,
password: mongoConfig.password,
userId: mongoConfig.userId,
};
return NextResponse.json(config, { status: 200 });
} catch (error) { } catch (error) {
console.error("Erreur lors de la récupération de la configuration:", error); console.error("Erreur lors de la récupération de la configuration:", error);
if (error instanceof Error) { if (error instanceof Error) {

View File

@@ -6,7 +6,7 @@ import { AppError } from "@/utils/errors";
export async function GET() { export async function GET() {
try { try {
const favoriteIds = await FavoriteService.getAllFavoriteIds(); const favoriteIds: string[] = await FavoriteService.getAllFavoriteIds();
return NextResponse.json(favoriteIds); return NextResponse.json(favoriteIds);
} catch (error) { } catch (error) {
console.error("Erreur lors de la récupération des favoris:", error); console.error("Erreur lors de la récupération des favoris:", error);
@@ -35,7 +35,7 @@ export async function GET() {
export async function POST(request: Request) { export async function POST(request: Request) {
try { try {
const { seriesId } = await request.json(); const { seriesId }: { seriesId: string } = await request.json();
await FavoriteService.addToFavorites(seriesId); await FavoriteService.addToFavorites(seriesId);
return NextResponse.json({ message: "⭐️ Série ajoutée aux favoris" }); return NextResponse.json({ message: "⭐️ Série ajoutée aux favoris" });
} catch (error) { } catch (error) {
@@ -65,7 +65,7 @@ export async function POST(request: Request) {
export async function DELETE(request: Request) { export async function DELETE(request: Request) {
try { try {
const { seriesId } = await request.json(); const { seriesId }: { seriesId: string } = await request.json();
await FavoriteService.removeFromFavorites(seriesId); await FavoriteService.removeFromFavorites(seriesId);
return NextResponse.json({ message: "💔 Série retirée des favoris" }); return NextResponse.json({ message: "💔 Série retirée des favoris" });
} catch (error) { } catch (error) {

View File

@@ -12,7 +12,7 @@ export async function GET(
) { ) {
try { try {
// Convertir le numéro de page en nombre // Convertir le numéro de page en nombre
const pageNumber = parseInt(params.pageNumber); const pageNumber: number = parseInt(params.pageNumber);
if (isNaN(pageNumber) || pageNumber < 0) { if (isNaN(pageNumber) || pageNumber < 0) {
return NextResponse.json( return NextResponse.json(
{ {

View File

@@ -3,12 +3,12 @@ import { LibraryService } from "@/lib/services/library.service";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { ERROR_MESSAGES } from "@/constants/errorMessages";
import { AppError } from "@/utils/errors"; import { AppError } from "@/utils/errors";
import { KomgaLibrary } from "@/types/komga";
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
export async function GET() { export async function GET() {
try { try {
const libraries = await LibraryService.getLibraries(); const libraries: KomgaLibrary[] = await LibraryService.getLibraries();
return NextResponse.json(libraries); return NextResponse.json(libraries);
} catch (error) { } catch (error) {
console.error("API Libraries - Erreur:", error); console.error("API Libraries - Erreur:", error);

View File

@@ -3,12 +3,13 @@ import { SeriesService } from "@/lib/services/series.service";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { ERROR_MESSAGES } from "@/constants/errorMessages";
import { AppError } from "@/utils/errors"; import { AppError } from "@/utils/errors";
import { KomgaSeries } from "@/types/komga";
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
export async function GET(request: Request, { params }: { params: { seriesId: string } }) { export async function GET(request: Request, { params }: { params: { seriesId: string } }) {
try { try {
const series = await SeriesService.getSeries(params.seriesId); const series: KomgaSeries = await SeriesService.getSeries(params.seriesId);
return NextResponse.json(series); return NextResponse.json(series);
} catch (error) { } catch (error) {
console.error("API Series - Erreur:", error); console.error("API Series - Erreur:", error);

View File

@@ -2,13 +2,14 @@ import { NextResponse } from "next/server";
import { TestService } from "@/lib/services/test.service"; import { TestService } from "@/lib/services/test.service";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { ERROR_MESSAGES } from "@/constants/errorMessages";
import { KomgaLibrary } from "@/types/komga";
export async function POST(request: Request) { export async function POST(request: Request) {
try { try {
const { serverUrl, username, password } = await request.json(); const { serverUrl, username, password } = await request.json();
const authHeader = Buffer.from(`${username}:${password}`).toString("base64"); const authHeader = Buffer.from(`${username}:${password}`).toString("base64");
const { libraries } = await TestService.testConnection({ const { libraries }: { libraries: KomgaLibrary[] } = await TestService.testConnection({
serverUrl, serverUrl,
authHeader, authHeader,
}); });

View File

@@ -2,10 +2,11 @@ import { NextResponse } from "next/server";
import { ConfigDBService } from "@/lib/services/config-db.service"; import { ConfigDBService } from "@/lib/services/config-db.service";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { ERROR_MESSAGES } from "@/constants/errorMessages";
import { TTLConfig } from "@/types/komga";
export async function GET() { export async function GET() {
try { try {
const config = await ConfigDBService.getTTLConfig(); const config: TTLConfig | null = await ConfigDBService.getTTLConfig();
return NextResponse.json(config); return NextResponse.json(config);
} catch (error) { } catch (error) {
console.error("Erreur lors de la récupération de la configuration TTL:", error); console.error("Erreur lors de la récupération de la configuration TTL:", error);
@@ -37,7 +38,8 @@ export async function GET() {
export async function POST(request: Request) { export async function POST(request: Request) {
try { try {
const data = await request.json(); const data = await request.json();
const config = await ConfigDBService.saveTTLConfig(data); const config: TTLConfig = await ConfigDBService.saveTTLConfig(data);
return NextResponse.json({ return NextResponse.json({
message: "⏱️ Configuration TTL sauvegardée avec succès", message: "⏱️ Configuration TTL sauvegardée avec succès",
config: { config: {

View File

@@ -3,10 +3,11 @@ import { PreferencesService } from "@/lib/services/preferences.service";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages"; import { ERROR_MESSAGES } from "@/constants/errorMessages";
import { AppError } from "@/utils/errors"; import { AppError } from "@/utils/errors";
import { UserPreferences } from "@/types/preferences";
export async function GET() { export async function GET() {
try { try {
const preferences = await PreferencesService.getPreferences(); const preferences: UserPreferences = await PreferencesService.getPreferences();
return NextResponse.json(preferences); return NextResponse.json(preferences);
} catch (error) { } catch (error) {
console.error("Erreur lors de la récupération des préférences:", error); console.error("Erreur lors de la récupération des préférences:", error);
@@ -35,8 +36,10 @@ export async function GET() {
export async function PUT(request: NextRequest) { export async function PUT(request: NextRequest) {
try { try {
const preferences = await request.json(); const preferences: UserPreferences = await request.json();
const updatedPreferences = await PreferencesService.updatePreferences(preferences); const updatedPreferences: UserPreferences = await PreferencesService.updatePreferences(
preferences
);
return NextResponse.json(updatedPreferences); return NextResponse.json(updatedPreferences);
} catch (error) { } catch (error) {
console.error("Erreur lors de la mise à jour des préférences:", error); console.error("Erreur lors de la mise à jour des préférences:", error);

View File

@@ -4,10 +4,11 @@ import { BookSkeleton } from "@/components/skeletons/BookSkeleton";
import { BookService } from "@/lib/services/book.service"; import { BookService } from "@/lib/services/book.service";
import { notFound } from "next/navigation"; import { notFound } from "next/navigation";
import { withPageTiming } from "@/lib/hoc/withPageTiming"; import { withPageTiming } from "@/lib/hoc/withPageTiming";
import { KomgaBookWithPages } from "@/types/komga";
async function BookPage({ params }: { params: { bookId: string } }) { async function BookPage({ params }: { params: { bookId: string } }) {
try { try {
const data = await BookService.getBook(params.bookId); const data: KomgaBookWithPages = await BookService.getBook(params.bookId);
return ( return (
<Suspense fallback={<BookSkeleton />}> <Suspense fallback={<BookSkeleton />}>

View File

@@ -5,7 +5,9 @@ import { revalidatePath } from "next/cache";
import { RefreshButton } from "@/components/library/RefreshButton"; import { RefreshButton } from "@/components/library/RefreshButton";
import { withPageTiming } from "@/lib/hoc/withPageTiming"; import { withPageTiming } from "@/lib/hoc/withPageTiming";
import { ErrorMessage } from "@/components/ui/ErrorMessage"; import { ErrorMessage } from "@/components/ui/ErrorMessage";
import { LibraryResponse } from "@/types/library";
import { KomgaSeries, KomgaLibrary } from "@/types/komga";
import { UserPreferences } from "@/types/preferences";
interface PageProps { interface PageProps {
params: { libraryId: string }; params: { libraryId: string };
searchParams: { page?: string; unread?: string; search?: string }; searchParams: { page?: string; unread?: string; search?: string };
@@ -36,14 +38,14 @@ async function getLibrarySeries(
try { try {
const pageIndex = page - 1; const pageIndex = page - 1;
const series = await LibraryService.getLibrarySeries( const series: LibraryResponse<KomgaSeries> = await LibraryService.getLibrarySeries(
libraryId, libraryId,
pageIndex, pageIndex,
PAGE_SIZE, PAGE_SIZE,
unreadOnly, unreadOnly,
search search
); );
const library = await LibraryService.getLibrary(libraryId); const library: KomgaLibrary = await LibraryService.getLibrary(libraryId);
return { data: series, library }; return { data: series, library };
} catch (error) { } catch (error) {
@@ -53,19 +55,15 @@ async function getLibrarySeries(
async function LibraryPage({ params, searchParams }: PageProps) { async function LibraryPage({ params, searchParams }: PageProps) {
const currentPage = searchParams.page ? parseInt(searchParams.page) : 1; const currentPage = searchParams.page ? parseInt(searchParams.page) : 1;
const preferences = await PreferencesService.getPreferences(); const preferences: UserPreferences = await PreferencesService.getPreferences();
// Utiliser le paramètre d'URL s'il existe, sinon utiliser la préférence utilisateur // Utiliser le paramètre d'URL s'il existe, sinon utiliser la préférence utilisateur
const unreadOnly = const unreadOnly =
searchParams.unread !== undefined ? searchParams.unread === "true" : preferences.showOnlyUnread; searchParams.unread !== undefined ? searchParams.unread === "true" : preferences.showOnlyUnread;
try { try {
const { data: series, library } = await getLibrarySeries( const { data: series, library }: { data: LibraryResponse<KomgaSeries>; library: KomgaLibrary } =
params.libraryId, await getLibrarySeries(params.libraryId, currentPage, unreadOnly, searchParams.search);
currentPage,
unreadOnly,
searchParams.search
);
return ( return (
<div className="container py-8 space-y-8"> <div className="container py-8 space-y-8">

View File

@@ -5,6 +5,9 @@ import { PreferencesService } from "@/lib/services/preferences.service";
import { revalidatePath } from "next/cache"; import { revalidatePath } from "next/cache";
import { withPageTiming } from "@/lib/hoc/withPageTiming"; import { withPageTiming } from "@/lib/hoc/withPageTiming";
import { ErrorMessage } from "@/components/ui/ErrorMessage"; import { ErrorMessage } from "@/components/ui/ErrorMessage";
import { LibraryResponse } from "@/types/library";
import { KomgaBook, KomgaSeries } from "@/types/komga";
import { UserPreferences } from "@/types/preferences";
interface PageProps { interface PageProps {
params: { seriesId: string }; params: { seriesId: string };
@@ -17,8 +20,13 @@ async function getSeriesBooks(seriesId: string, page: number = 1, unreadOnly: bo
try { try {
const pageIndex = page - 1; const pageIndex = page - 1;
const books = await SeriesService.getSeriesBooks(seriesId, pageIndex, PAGE_SIZE, unreadOnly); const books: LibraryResponse<KomgaBook> = await SeriesService.getSeriesBooks(
const series = await SeriesService.getSeries(seriesId); seriesId,
pageIndex,
PAGE_SIZE,
unreadOnly
);
const series: KomgaSeries = await SeriesService.getSeries(seriesId);
return { data: books, series }; return { data: books, series };
} catch (error) { } catch (error) {
@@ -42,14 +50,15 @@ async function refreshSeries(seriesId: string) {
async function SeriesPage({ params, searchParams }: PageProps) { async function SeriesPage({ params, searchParams }: PageProps) {
const currentPage = searchParams.page ? parseInt(searchParams.page) : 1; const currentPage = searchParams.page ? parseInt(searchParams.page) : 1;
const preferences = await PreferencesService.getPreferences(); const preferences: UserPreferences = await PreferencesService.getPreferences();
// Utiliser le paramètre d'URL s'il existe, sinon utiliser la préférence utilisateur // Utiliser le paramètre d'URL s'il existe, sinon utiliser la préférence utilisateur
const unreadOnly = const unreadOnly =
searchParams.unread !== undefined ? searchParams.unread === "true" : preferences.showOnlyUnread; searchParams.unread !== undefined ? searchParams.unread === "true" : preferences.showOnlyUnread;
try { try {
const { data: books, series } = await getSeriesBooks(params.seriesId, currentPage, unreadOnly); const { data: books, series }: { data: LibraryResponse<KomgaBook>; series: KomgaSeries } =
await getSeriesBooks(params.seriesId, currentPage, unreadOnly);
return ( return (
<div className="container py-8 space-y-8"> <div className="container py-8 space-y-8">

View File

@@ -1,6 +1,7 @@
import { ConfigDBService } from "@/lib/services/config-db.service"; import { ConfigDBService } from "@/lib/services/config-db.service";
import { ClientSettings } from "@/components/settings/ClientSettings"; import { ClientSettings } from "@/components/settings/ClientSettings";
import { Metadata } from "next"; import { Metadata } from "next";
import { KomgaConfig, TTLConfig } from "@/types/komga";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Préférences", title: "Préférences",
@@ -8,18 +9,19 @@ export const metadata: Metadata = {
}; };
export default async function SettingsPage() { export default async function SettingsPage() {
let config = null; let config: KomgaConfig | null = null;
let ttlConfig = null; let ttlConfig: TTLConfig | null = null;
try { try {
// Récupérer la configuration Komga // Récupérer la configuration Komga
const mongoConfig = await ConfigDBService.getConfig(); const mongoConfig: KomgaConfig | null = await ConfigDBService.getConfig();
if (mongoConfig) { if (mongoConfig) {
config = { config = {
url: mongoConfig.url, url: mongoConfig.url,
username: mongoConfig.username, username: mongoConfig.username,
userId: mongoConfig.userId, userId: mongoConfig.userId,
authHeader: mongoConfig.authHeader, authHeader: mongoConfig.authHeader,
password: null,
}; };
} }

View File

@@ -42,7 +42,10 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) {
console.error("Erreur de chargement des bibliothèques:", error); console.error("Erreur de chargement des bibliothèques:", error);
toast({ toast({
title: "Erreur", title: "Erreur",
description: error instanceof AppError ? error.message : ERROR_MESSAGES[ERROR_CODES.LIBRARY.FETCH_ERROR], description:
error instanceof AppError
? error.message
: ERROR_MESSAGES[ERROR_CODES.LIBRARY.FETCH_ERROR],
variant: "destructive", variant: "destructive",
}); });
setLibraries([]); setLibraries([]);
@@ -80,7 +83,10 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) {
console.error("Erreur de chargement des favoris:", error); console.error("Erreur de chargement des favoris:", error);
toast({ toast({
title: "Erreur", title: "Erreur",
description: error instanceof AppError ? error.message : ERROR_MESSAGES[ERROR_CODES.FAVORITE.FETCH_ERROR], description:
error instanceof AppError
? error.message
: ERROR_MESSAGES[ERROR_CODES.FAVORITE.FETCH_ERROR],
variant: "destructive", variant: "destructive",
}); });
setFavorites([]); setFavorites([]);
@@ -130,7 +136,8 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) {
console.error("Erreur lors de la déconnexion:", error); console.error("Erreur lors de la déconnexion:", error);
toast({ toast({
title: "Erreur", title: "Erreur",
description: error instanceof AppError ? error.message : ERROR_MESSAGES[ERROR_CODES.AUTH.LOGOUT_ERROR], description:
error instanceof AppError ? error.message : ERROR_MESSAGES[ERROR_CODES.AUTH.LOGOUT_ERROR],
variant: "destructive", variant: "destructive",
}); });
} }

View File

@@ -1,6 +1,6 @@
import { KomgaLibrary } from "@/types/komga";
import { Book } from "lucide-react"; import { Book } from "lucide-react";
import { Cover } from "@/components/ui/cover"; import { Cover } from "@/components/ui/cover";
import { KomgaLibrary } from "@/types/komga";
interface LibraryGridProps { interface LibraryGridProps {
libraries: KomgaLibrary[]; libraries: KomgaLibrary[];

View File

@@ -9,6 +9,7 @@ import { Cover } from "@/components/ui/cover";
import { RefreshButton } from "@/components/library/RefreshButton"; import { RefreshButton } from "@/components/library/RefreshButton";
import { AppError } from "@/utils/errors"; import { AppError } from "@/utils/errors";
import { ERROR_CODES } from "@/constants/errorCodes"; import { ERROR_CODES } from "@/constants/errorCodes";
import { ERROR_MESSAGES } from "@/constants/errorMessages";
interface SeriesHeaderProps { interface SeriesHeaderProps {
series: KomgaSeries; series: KomgaSeries;
@@ -32,7 +33,10 @@ export const SeriesHeader = ({ series, refreshSeries }: SeriesHeaderProps) => {
console.error("Erreur lors de la vérification des favoris:", error); console.error("Erreur lors de la vérification des favoris:", error);
toast({ toast({
title: "Erreur", title: "Erreur",
description: error instanceof AppError ? error.message : ERROR_MESSAGES[ERROR_CODES.FAVORITE.NETWORK_ERROR], description:
error instanceof AppError
? error.message
: ERROR_MESSAGES[ERROR_CODES.FAVORITE.NETWORK_ERROR],
variant: "destructive", variant: "destructive",
}); });
} }
@@ -71,7 +75,10 @@ export const SeriesHeader = ({ series, refreshSeries }: SeriesHeaderProps) => {
console.error("Erreur lors de la modification des favoris:", error); console.error("Erreur lors de la modification des favoris:", error);
toast({ toast({
title: "Erreur", title: "Erreur",
description: error instanceof AppError ? error.message : ERROR_MESSAGES[ERROR_CODES.FAVORITE.NETWORK_ERROR], description:
error instanceof AppError
? error.message
: ERROR_MESSAGES[ERROR_CODES.FAVORITE.NETWORK_ERROR],
variant: "destructive", variant: "destructive",
}); });
} }

View File

@@ -9,23 +9,7 @@ import { usePreferences } from "@/contexts/PreferencesContext";
import { Switch } from "@/components/ui/switch"; import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { CacheModeSwitch } from "@/components/settings/CacheModeSwitch"; import { CacheModeSwitch } from "@/components/settings/CacheModeSwitch";
import { KomgaConfig, TTLConfigData } from "@/types/komga";
interface KomgaConfig {
url: string;
username: string;
userId: string;
password?: string;
authHeader: string;
}
interface TTLConfigData {
defaultTTL: number;
homeTTL: number;
librariesTTL: number;
seriesTTL: number;
booksTTL: number;
imagesTTL: number;
}
interface ClientSettingsProps { interface ClientSettingsProps {
initialConfig: KomgaConfig | null; initialConfig: KomgaConfig | null;

View File

@@ -5,7 +5,7 @@ import bcrypt from "bcrypt";
import { ERROR_CODES } from "../../constants/errorCodes"; import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors"; import { AppError } from "../../utils/errors";
interface UserData { export interface UserData {
id: string; id: string;
email: string; email: string;
roles: string[]; roles: string[];

View File

@@ -4,7 +4,8 @@ import { ConfigDBService } from "./config-db.service";
import { DebugService } from "./debug.service"; import { DebugService } from "./debug.service";
import { ERROR_CODES } from "../../constants/errorCodes"; import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors"; import { AppError } from "../../utils/errors";
import { KomgaConfig } from "@/types/komga";
import { ServerCacheService } from "./server-cache.service";
// Types de cache disponibles // Types de cache disponibles
export type CacheType = "DEFAULT" | "HOME" | "LIBRARIES" | "SERIES" | "BOOKS" | "IMAGES"; export type CacheType = "DEFAULT" | "HOME" | "LIBRARIES" | "SERIES" | "BOOKS" | "IMAGES";
@@ -20,7 +21,11 @@ interface KomgaUrlBuilder {
export abstract class BaseApiService { export abstract class BaseApiService {
protected static async getKomgaConfig(): Promise<AuthConfig> { protected static async getKomgaConfig(): Promise<AuthConfig> {
try { try {
const config = await ConfigDBService.getConfig(); const config: KomgaConfig | null = await ConfigDBService.getConfig();
if (!config) {
throw new AppError(ERROR_CODES.KOMGA.MISSING_CONFIG);
}
return { return {
serverUrl: config.url, serverUrl: config.url,
authHeader: config.authHeader, authHeader: config.authHeader,
@@ -47,7 +52,7 @@ export abstract class BaseApiService {
fetcher: () => Promise<T>, fetcher: () => Promise<T>,
type: CacheType = "DEFAULT" type: CacheType = "DEFAULT"
): Promise<T> { ): Promise<T> {
const cacheService = await getServerCacheService(); const cacheService: ServerCacheService = await getServerCacheService();
try { try {
const result = await cacheService.getOrSet(key, fetcher, type); const result = await cacheService.getOrSet(key, fetcher, type);
@@ -82,11 +87,11 @@ export abstract class BaseApiService {
options: KomgaRequestInit = {} options: KomgaRequestInit = {}
): Promise<T> { ): Promise<T> {
const startTime = performance.now(); const startTime = performance.now();
const config = await this.getKomgaConfig(); const config: AuthConfig = await this.getKomgaConfig();
const { path, params } = urlBuilder; const { path, params } = urlBuilder;
const url = this.buildUrl(config, path, params); const url = this.buildUrl(config, path, params);
const headers = this.getAuthHeaders(config); const headers: Headers = this.getAuthHeaders(config);
if (headersOptions) { if (headersOptions) {
for (const [key, value] of Object.entries(headersOptions)) { for (const [key, value] of Object.entries(headersOptions)) {
headers.set(key as string, value as string); headers.set(key as string, value as string);

View File

@@ -1,14 +1,14 @@
import { BaseApiService } from "./base-api.service"; import { BaseApiService } from "./base-api.service";
import { KomgaBook } from "@/types/komga"; import { KomgaBook, KomgaBookWithPages } from "@/types/komga";
import { ImageService } from "./image.service"; import { ImageService, ImageResponse } from "./image.service";
import { PreferencesService } from "./preferences.service"; import { PreferencesService } from "./preferences.service";
import { ERROR_CODES } from "../../constants/errorCodes"; import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors"; import { AppError } from "../../utils/errors";
export class BookService extends BaseApiService { export class BookService extends BaseApiService {
static async getBook(bookId: string): Promise<{ book: KomgaBook; pages: number[] }> { static async getBook(bookId: string): Promise<KomgaBookWithPages> {
try { try {
return this.fetchWithCache<{ book: KomgaBook; pages: number[] }>( return this.fetchWithCache<KomgaBookWithPages>(
`book-${bookId}`, `book-${bookId}`,
async () => { async () => {
// Récupération des détails du tome // Récupération des détails du tome
@@ -86,7 +86,7 @@ export class BookService extends BaseApiService {
try { try {
// Ajuster le numéro de page pour l'API Komga (zero-based) // Ajuster le numéro de page pour l'API Komga (zero-based)
const adjustedPageNumber = pageNumber - 1; const adjustedPageNumber = pageNumber - 1;
const response = await ImageService.getImage( const response: ImageResponse = await ImageService.getImage(
`books/${bookId}/pages/${adjustedPageNumber}?zero_based=true` `books/${bookId}/pages/${adjustedPageNumber}?zero_based=true`
); );
return new Response(response.buffer, { return new Response(response.buffer, {
@@ -107,7 +107,7 @@ export class BookService extends BaseApiService {
// Si l'utilisateur préfère les vignettes, utiliser la miniature // Si l'utilisateur préfère les vignettes, utiliser la miniature
if (preferences.showThumbnails) { if (preferences.showThumbnails) {
const response = await ImageService.getImage(`books/${bookId}/thumbnail`); const response: ImageResponse = await ImageService.getImage(`books/${bookId}/thumbnail`);
return new Response(response.buffer, { return new Response(response.buffer, {
headers: { headers: {
"Content-Type": response.contentType || "image/jpeg", "Content-Type": response.contentType || "image/jpeg",
@@ -133,7 +133,7 @@ export class BookService extends BaseApiService {
static async getPageThumbnail(bookId: string, pageNumber: number): Promise<Response> { static async getPageThumbnail(bookId: string, pageNumber: number): Promise<Response> {
try { try {
const response = await ImageService.getImage( const response: ImageResponse = await ImageService.getImage(
`books/${bookId}/pages/${pageNumber}/thumbnail?zero_based=true` `books/${bookId}/pages/${pageNumber}/thumbnail?zero_based=true`
); );
return new Response(response.buffer, { return new Response(response.buffer, {

View File

@@ -1,49 +1,31 @@
import connectDB from "@/lib/mongodb"; import connectDB from "@/lib/mongodb";
import { KomgaConfig } from "@/lib/models/config.model"; import { KomgaConfig as KomgaConfigModel } from "@/lib/models/config.model";
import { TTLConfig } from "@/lib/models/ttl-config.model"; import { TTLConfig as TTLConfigModel } from "@/lib/models/ttl-config.model";
import { DebugService } from "./debug.service"; import { DebugService } from "./debug.service";
import { AuthServerService } from "./auth-server.service"; import { AuthServerService } from "./auth-server.service";
import { ERROR_CODES } from "../../constants/errorCodes"; import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors"; import { AppError } from "../../utils/errors";
import { User, KomgaConfigData, TTLConfigData, KomgaConfig, TTLConfig } from "@/types/komga";
interface User {
id: string;
email: string;
}
interface KomgaConfigData {
url: string;
username: string;
password: string;
authHeader: string;
}
interface TTLConfigData {
defaultTTL: number;
homeTTL: number;
librariesTTL: number;
seriesTTL: number;
booksTTL: number;
imagesTTL: number;
}
export class ConfigDBService { export class ConfigDBService {
private static getCurrentUser(): User { private static getCurrentUser(): User {
const user = AuthServerService.getCurrentUser(); const user: User | null = AuthServerService.getCurrentUser();
if (!user) { if (!user) {
throw new AppError(ERROR_CODES.AUTH.UNAUTHENTICATED); throw new AppError(ERROR_CODES.AUTH.UNAUTHENTICATED);
} }
return user; return user;
} }
static async saveConfig(data: KomgaConfigData) { static async saveConfig(data: KomgaConfigData): Promise<KomgaConfig> {
try { try {
const user = this.getCurrentUser(); const user: User | null = this.getCurrentUser();
await connectDB(); await connectDB();
const authHeader = Buffer.from(`${data.username}:${data.password}`).toString("base64"); const authHeader: string = Buffer.from(`${data.username}:${data.password}`).toString(
"base64"
);
const config = await KomgaConfig.findOneAndUpdate( const config: KomgaConfig | null = await KomgaConfigModel.findOneAndUpdate(
{ userId: user.id }, { userId: user.id },
{ {
userId: user.id, userId: user.id,
@@ -54,6 +36,9 @@ export class ConfigDBService {
}, },
{ upsert: true, new: true } { upsert: true, new: true }
); );
if (!config) {
throw new AppError(ERROR_CODES.CONFIG.SAVE_ERROR);
}
return config; return config;
} catch (error) { } catch (error) {
@@ -64,13 +49,13 @@ export class ConfigDBService {
} }
} }
static async getConfig() { static async getConfig(): Promise<KomgaConfig | null> {
try { try {
const user = this.getCurrentUser(); const user: User | null = this.getCurrentUser();
await connectDB(); await connectDB();
return DebugService.measureMongoOperation("getConfig", async () => { return DebugService.measureMongoOperation("getConfig", async () => {
const config = await KomgaConfig.findOne({ userId: user.id }); const config: KomgaConfig | null = await KomgaConfigModel.findOne({ userId: user.id });
return config; return config;
}); });
} catch (error) { } catch (error) {
@@ -81,13 +66,13 @@ export class ConfigDBService {
} }
} }
static async getTTLConfig() { static async getTTLConfig(): Promise<TTLConfig | null> {
try { try {
const user = this.getCurrentUser(); const user: User | null = this.getCurrentUser();
await connectDB(); await connectDB();
return DebugService.measureMongoOperation("getTTLConfig", async () => { return DebugService.measureMongoOperation("getTTLConfig", async () => {
const config = await TTLConfig.findOne({ userId: user.id }); const config: TTLConfig | null = await TTLConfigModel.findOne({ userId: user.id });
return config; return config;
}); });
} catch (error) { } catch (error) {
@@ -98,13 +83,13 @@ export class ConfigDBService {
} }
} }
static async saveTTLConfig(data: TTLConfigData) { static async saveTTLConfig(data: TTLConfigData): Promise<TTLConfig> {
try { try {
const user = this.getCurrentUser(); const user: User | null = this.getCurrentUser();
await connectDB(); await connectDB();
return DebugService.measureMongoOperation("saveTTLConfig", async () => { return DebugService.measureMongoOperation("saveTTLConfig", async () => {
const config = await TTLConfig.findOneAndUpdate( const config: TTLConfig | null = await TTLConfigModel.findOneAndUpdate(
{ userId: user.id }, { userId: user.id },
{ {
userId: user.id, userId: user.id,
@@ -112,6 +97,11 @@ export class ConfigDBService {
}, },
{ upsert: true, new: true } { upsert: true, new: true }
); );
if (!config) {
throw new AppError(ERROR_CODES.CONFIG.TTL_SAVE_ERROR);
}
return config; return config;
}); });
} catch (error) { } catch (error) {

View File

@@ -6,7 +6,7 @@ import { PreferencesService } from "./preferences.service";
import { ERROR_CODES } from "../../constants/errorCodes"; import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors"; import { AppError } from "../../utils/errors";
interface RequestTiming { export interface RequestTiming {
url: string; url: string;
startTime: number; startTime: number;
endTime: number; endTime: number;

View File

@@ -4,11 +4,7 @@ import { DebugService } from "./debug.service";
import { AuthServerService } from "./auth-server.service"; import { AuthServerService } from "./auth-server.service";
import { ERROR_CODES } from "../../constants/errorCodes"; import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors"; import { AppError } from "../../utils/errors";
import { User } from "@/types/komga";
interface User {
id: string;
email: string;
}
export class FavoriteService { export class FavoriteService {
private static readonly FAVORITES_CHANGE_EVENT = "favoritesChanged"; private static readonly FAVORITES_CHANGE_EVENT = "favoritesChanged";

View File

@@ -2,7 +2,7 @@ import { BaseApiService } from "./base-api.service";
import { ERROR_CODES } from "../../constants/errorCodes"; import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors"; import { AppError } from "../../utils/errors";
interface ImageResponse { export interface ImageResponse {
buffer: Buffer; buffer: Buffer;
contentType: string | null; contentType: string | null;
} }

View File

@@ -1,16 +1,17 @@
import { BaseApiService } from "./base-api.service"; import { BaseApiService } from "./base-api.service";
import { Library, LibraryResponse } from "@/types/library"; import { LibraryResponse } from "@/types/library";
import { Series } from "@/types/series"; import { Series } from "@/types/series";
import { getServerCacheService } from "./server-cache.service"; import { getServerCacheService } from "./server-cache.service";
import { ERROR_CODES } from "../../constants/errorCodes"; import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors"; import { AppError } from "../../utils/errors";
import { KomgaLibrary } from "@/types/komga";
export class LibraryService extends BaseApiService { export class LibraryService extends BaseApiService {
static async getLibraries(): Promise<Library[]> { static async getLibraries(): Promise<KomgaLibrary[]> {
try { try {
return this.fetchWithCache<Library[]>( return this.fetchWithCache<KomgaLibrary[]>(
"libraries", "libraries",
async () => this.fetchFromApi<Library[]>({ path: "libraries" }), async () => this.fetchFromApi<KomgaLibrary[]>({ path: "libraries" }),
"LIBRARIES" "LIBRARIES"
); );
} catch (error) { } catch (error) {
@@ -18,7 +19,7 @@ export class LibraryService extends BaseApiService {
} }
} }
static async getLibrary(libraryId: string): Promise<Library> { static async getLibrary(libraryId: string): Promise<KomgaLibrary> {
try { try {
const libraries = await this.getLibraries(); const libraries = await this.getLibraries();
const library = libraries.find((library) => library.id === libraryId); const library = libraries.find((library) => library.id === libraryId);

View File

@@ -3,11 +3,7 @@ import { AuthServerService } from "./auth-server.service";
import { ERROR_CODES } from "../../constants/errorCodes"; import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors"; import { AppError } from "../../utils/errors";
import { UserPreferences, defaultPreferences } from "@/types/preferences"; import { UserPreferences, defaultPreferences } from "@/types/preferences";
import { User } from "@/types/komga";
interface User {
id: string;
email: string;
}
export class PreferencesService { export class PreferencesService {
static getCurrentUser(): User { static getCurrentUser(): User {

View File

@@ -2,11 +2,13 @@ import { BaseApiService } from "./base-api.service";
import { LibraryResponse } from "@/types/library"; import { LibraryResponse } from "@/types/library";
import { KomgaBook, KomgaSeries } from "@/types/komga"; import { KomgaBook, KomgaSeries } from "@/types/komga";
import { BookService } from "./book.service"; import { BookService } from "./book.service";
import { ImageService } from "./image.service"; import { ImageService, ImageResponse } from "./image.service";
import { PreferencesService } from "./preferences.service"; import { PreferencesService } from "./preferences.service";
import { getServerCacheService } from "./server-cache.service"; import { getServerCacheService } from "./server-cache.service";
import { ERROR_CODES } from "../../constants/errorCodes"; import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors"; import { AppError } from "../../utils/errors";
import { UserPreferences } from "@/types/preferences";
import { ServerCacheService } from "./server-cache.service";
export class SeriesService extends BaseApiService { export class SeriesService extends BaseApiService {
static async getSeries(seriesId: string): Promise<KomgaSeries> { static async getSeries(seriesId: string): Promise<KomgaSeries> {
@@ -84,19 +86,19 @@ export class SeriesService extends BaseApiService {
): Promise<LibraryResponse<KomgaBook>> { ): Promise<LibraryResponse<KomgaBook>> {
try { try {
// Récupérer tous les livres depuis le cache // Récupérer tous les livres depuis le cache
const allBooks = await this.getAllSeriesBooks(seriesId); const allBooks: KomgaBook[] = await this.getAllSeriesBooks(seriesId);
// Filtrer les livres // Filtrer les livres
let filteredBooks = allBooks; let filteredBooks = allBooks;
if (unreadOnly) { if (unreadOnly) {
filteredBooks = filteredBooks.filter( filteredBooks = filteredBooks.filter(
(book) => !book.readProgress || !book.readProgress.completed (book: KomgaBook) => !book.readProgress || !book.readProgress.completed
); );
} }
// Trier les livres par numéro // Trier les livres par numéro
filteredBooks.sort((a, b) => a.number - b.number); filteredBooks.sort((a: KomgaBook, b: KomgaBook) => a.number - b.number);
// Calculer la pagination // Calculer la pagination
const totalElements = filteredBooks.length; const totalElements = filteredBooks.length;
@@ -140,7 +142,7 @@ export class SeriesService extends BaseApiService {
} }
static async invalidateSeriesBooksCache(seriesId: string): Promise<void> { static async invalidateSeriesBooksCache(seriesId: string): Promise<void> {
const cacheService = await getServerCacheService(); const cacheService: ServerCacheService = await getServerCacheService();
await cacheService.delete(`series-${seriesId}-all-books`); await cacheService.delete(`series-${seriesId}-all-books`);
} }
@@ -149,7 +151,9 @@ export class SeriesService extends BaseApiService {
return this.fetchWithCache<string>( return this.fetchWithCache<string>(
`series-first-book-${seriesId}`, `series-first-book-${seriesId}`,
async () => { async () => {
const data = await this.fetchFromApi<LibraryResponse<KomgaBook>>({ const data: LibraryResponse<KomgaBook> = await this.fetchFromApi<
LibraryResponse<KomgaBook>
>({
path: `series/${seriesId}/books`, path: `series/${seriesId}/books`,
params: { page: "0", size: "1" }, params: { page: "0", size: "1" },
}); });
@@ -170,11 +174,11 @@ export class SeriesService extends BaseApiService {
static async getCover(seriesId: string): Promise<Response> { static async getCover(seriesId: string): Promise<Response> {
try { try {
// Récupérer les préférences de l'utilisateur // Récupérer les préférences de l'utilisateur
const preferences = await PreferencesService.getPreferences(); const preferences: UserPreferences = await PreferencesService.getPreferences();
// Si l'utilisateur préfère les vignettes, utiliser la miniature // Si l'utilisateur préfère les vignettes, utiliser la miniature
if (preferences.showThumbnails) { if (preferences.showThumbnails) {
const response = await ImageService.getImage(`series/${seriesId}/thumbnail`); const response: ImageResponse = await ImageService.getImage(`series/${seriesId}/thumbnail`);
return new Response(response.buffer, { return new Response(response.buffer, {
headers: { headers: {
"Content-Type": response.contentType || "image/jpeg", "Content-Type": response.contentType || "image/jpeg",
@@ -198,8 +202,10 @@ export class SeriesService extends BaseApiService {
static async getMultipleSeries(seriesIds: string[]): Promise<KomgaSeries[]> { static async getMultipleSeries(seriesIds: string[]): Promise<KomgaSeries[]> {
try { try {
const seriesPromises = seriesIds.map((id) => this.getSeries(id)); const seriesPromises: Promise<KomgaSeries>[] = seriesIds.map((id: string) =>
const series = await Promise.all(seriesPromises); this.getSeries(id)
);
const series: KomgaSeries[] = await Promise.all(seriesPromises);
return series.filter(Boolean); return series.filter(Boolean);
} catch (error) { } catch (error) {
throw new AppError(ERROR_CODES.SERIES.FETCH_ERROR, {}, error); throw new AppError(ERROR_CODES.SERIES.FETCH_ERROR, {}, error);

View File

@@ -4,7 +4,7 @@ import { PreferencesService } from "./preferences.service";
import { DebugService } from "./debug.service"; import { DebugService } from "./debug.service";
import { AuthServerService } from "./auth-server.service"; import { AuthServerService } from "./auth-server.service";
type CacheMode = "file" | "memory"; export type CacheMode = "file" | "memory";
interface CacheConfig { interface CacheConfig {
mode: CacheMode; mode: CacheMode;

View File

@@ -1,8 +1,8 @@
import { BaseApiService } from "./base-api.service"; import { BaseApiService } from "./base-api.service";
import { AuthConfig } from "@/types/auth"; import { AuthConfig } from "@/types/auth";
import { KomgaLibrary } from "@/types/komga";
import { ERROR_CODES } from "../../constants/errorCodes"; import { ERROR_CODES } from "../../constants/errorCodes";
import { AppError } from "../../utils/errors"; import { AppError } from "../../utils/errors";
import { KomgaLibrary } from "@/types/komga";
export class TestService extends BaseApiService { export class TestService extends BaseApiService {
static async testConnection(config: AuthConfig): Promise<{ libraries: KomgaLibrary[] }> { static async testConnection(config: AuthConfig): Promise<{ libraries: KomgaLibrary[] }> {

View File

@@ -2,6 +2,7 @@ import { NextResponse } from "next/server";
import type { NextRequest } from "next/server"; import type { NextRequest } from "next/server";
import { ERROR_CODES } from "./constants/errorCodes"; import { ERROR_CODES } from "./constants/errorCodes";
import { ERROR_MESSAGES } from "./constants/errorMessages"; import { ERROR_MESSAGES } from "./constants/errorMessages";
import { UserData } from "./lib/services/auth-server.service";
// Routes qui ne nécessitent pas d'authentification // Routes qui ne nécessitent pas d'authentification
const publicRoutes = ["/login", "/register", "/images"]; const publicRoutes = ["/login", "/register", "/images"];
@@ -43,7 +44,7 @@ export function middleware(request: NextRequest) {
} }
try { try {
const userData = JSON.parse(atob(user.value)); const userData: UserData = JSON.parse(atob(user.value));
if (!userData || !userData.authenticated || !userData.id || !userData.email) { if (!userData || !userData.authenticated || !userData.id || !userData.email) {
throw new Error(ERROR_MESSAGES[ERROR_CODES.MIDDLEWARE.INVALID_SESSION]); throw new Error(ERROR_MESSAGES[ERROR_CODES.MIDDLEWARE.INVALID_SESSION]);
} }

View File

@@ -1,3 +1,34 @@
// Types liés à la configuration
export interface User {
id: string;
email: string;
}
export interface KomgaConfigData {
url: string;
username: string;
password?: string | null;
authHeader: string;
}
export interface KomgaConfig extends KomgaConfigData {
userId: string;
}
export interface TTLConfigData {
defaultTTL: number;
homeTTL: number;
librariesTTL: number;
seriesTTL: number;
booksTTL: number;
imagesTTL: number;
}
export interface TTLConfig extends TTLConfigData {
userId: string;
}
// Types liés à l'API Komga
export interface KomgaUser { export interface KomgaUser {
id: string; id: string;
email: string; email: string;
@@ -107,3 +138,8 @@ export interface BookMetadata {
releaseDate: string; releaseDate: string;
isbn: string; isbn: string;
} }
export interface KomgaBookWithPages {
book: KomgaBook;
pages: number[];
}

View File

@@ -1,12 +1,3 @@
export interface Library {
id: string;
name: string;
root: string;
importLastModified: string;
lastModified: string;
unavailable: boolean;
}
export interface LibraryResponse<T> { export interface LibraryResponse<T> {
content: T[]; content: T[];
empty: boolean; empty: boolean;