refactor: remove client-only GET API routes for lot 1

This commit is contained in:
2026-02-28 11:43:11 +01:00
parent 7f361ce0a2
commit 29f5324bd7
17 changed files with 214 additions and 430 deletions

View File

@@ -1,10 +1,36 @@
"use server";
import { AdminService } from "@/lib/services/admin.service";
import { ERROR_CODES } from "@/constants/errorCodes";
import type { AdminUserData } from "@/lib/services/admin.service";
import { AppError } from "@/utils/errors";
import { AuthServerService } from "@/lib/services/auth-server.service";
export interface AdminStatsData {
totalUsers: number;
totalAdmins: number;
usersWithKomga: number;
usersWithPreferences: number;
}
export async function getAdminDashboardData(): Promise<{
success: boolean;
users?: AdminUserData[];
stats?: AdminStatsData;
message?: string;
}> {
try {
const [users, stats] = await Promise.all([AdminService.getAllUsers(), AdminService.getUserStats()]);
return { success: true, users, stats };
} catch (error) {
if (error instanceof AppError) {
return { success: false, message: error.message };
}
return { success: false, message: "Erreur lors de la récupération des données admin" };
}
}
/**
* Met à jour les rôles d'un utilisateur
*/

View File

@@ -1,32 +0,0 @@
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) {
logger.error({ err: error }, "Erreur lors de la récupération des stats:");
if (error instanceof AppError) {
return NextResponse.json(
{ error: error.message, code: error.code },
{
status:
error.code === "AUTH_FORBIDDEN"
? 403
: error.code === "AUTH_UNAUTHENTICATED"
? 401
: 500,
}
);
}
return NextResponse.json(
{ error: "Erreur lors de la récupération des stats" },
{ status: 500 }
);
}
}

View File

@@ -1,32 +0,0 @@
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) {
logger.error({ err: error }, "Erreur lors de la récupération des utilisateurs:");
if (error instanceof AppError) {
return NextResponse.json(
{ error: error.message, code: error.code },
{
status:
error.code === "AUTH_FORBIDDEN"
? 403
: error.code === "AUTH_UNAUTHENTICATED"
? 401
: 500,
}
);
}
return NextResponse.json(
{ error: "Erreur lors de la récupération des utilisateurs" },
{ status: 500 }
);
}
}

View File

@@ -1,63 +0,0 @@
import { NextResponse } from "next/server";
import { FavoriteService } from "@/lib/services/favorite.service";
import { SeriesService } from "@/lib/services/series.service";
import { ERROR_CODES } from "@/constants/errorCodes";
import { AppError } from "@/utils/errors";
import { getErrorMessage } from "@/utils/errors";
import logger from "@/lib/logger";
// GET reste utilisé par Sidebar et SeriesHeader pour récupérer la liste des favoris
export async function GET() {
try {
const favoriteIds: string[] = await FavoriteService.getAllFavoriteIds();
// Valider que chaque série existe encore dans Komga
const validFavoriteIds: string[] = [];
for (const seriesId of favoriteIds) {
try {
await SeriesService.getSeries(seriesId);
validFavoriteIds.push(seriesId);
} catch {
// Si la série n'existe plus dans Komga, on la retire des favoris
try {
await FavoriteService.removeFromFavorites(seriesId);
} catch {
// Erreur silencieuse, la série reste dans les favoris
}
}
}
return NextResponse.json(validFavoriteIds);
} catch (error) {
if (error instanceof AppError) {
// Si la config Komga n'existe pas, retourner un tableau vide au lieu d'une erreur
if (error.code === ERROR_CODES.KOMGA.MISSING_CONFIG) {
return NextResponse.json([]);
}
}
logger.error({ err: error }, "Erreur lors de la récupération des favoris:");
if (error instanceof AppError) {
return NextResponse.json(
{
error: {
code: error.code,
name: "Favorite fetch error",
message: getErrorMessage(error.code),
},
},
{ status: 500 }
);
}
return NextResponse.json(
{
error: {
code: ERROR_CODES.FAVORITE.FETCH_ERROR,
name: "Favorite fetch error",
message: getErrorMessage(ERROR_CODES.FAVORITE.FETCH_ERROR),
},
},
{ status: 500 }
);
}
}

View File

@@ -1,46 +0,0 @@
import { NextResponse } from "next/server";
import { LibraryService } from "@/lib/services/library.service";
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";
// Cache handled in service via fetchFromApi options
export async function GET() {
try {
const libraries: KomgaLibrary[] = await LibraryService.getLibraries();
return NextResponse.json(libraries);
} catch (error) {
if (error instanceof AppError) {
// Si la config Komga n'existe pas, retourner un tableau vide au lieu d'une erreur
if (error.code === ERROR_CODES.KOMGA.MISSING_CONFIG) {
return NextResponse.json([]);
}
}
logger.error({ err: error }, "API Libraries - Erreur:");
if (error instanceof AppError) {
return NextResponse.json(
{
error: {
code: error.code,
name: "Library fetch error",
message: getErrorMessage(error.code),
},
},
{ status: 500 }
);
}
return NextResponse.json(
{
error: {
code: ERROR_CODES.LIBRARY.FETCH_ERROR,
name: "Library fetch error",
message: getErrorMessage(ERROR_CODES.LIBRARY.FETCH_ERROR),
},
},
{ status: 500 }
);
}
}

View File

@@ -1,40 +0,0 @@
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { PreferencesService } from "@/lib/services/preferences.service";
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";
// GET reste utilisé par PreferencesContext pour récupérer les préférences
export async function GET() {
try {
const preferences: UserPreferences = await PreferencesService.getPreferences();
return NextResponse.json(preferences);
} catch (error) {
logger.error({ err: error }, "Erreur lors de la récupération des préférences:");
if (error instanceof AppError) {
return NextResponse.json(
{
error: {
name: "Preferences fetch error",
code: error.code,
message: getErrorMessage(error.code),
},
},
{ status: 500 }
);
}
return NextResponse.json(
{
error: {
name: "Preferences fetch error",
code: ERROR_CODES.PREFERENCES.FETCH_ERROR,
message: getErrorMessage(ERROR_CODES.PREFERENCES.FETCH_ERROR),
},
},
{ status: 500 }
);
}
}

View File

@@ -15,6 +15,7 @@ interface SeriesContentProps {
preferences: UserPreferences;
unreadOnly: boolean;
pageSize: number;
initialIsFavorite: boolean;
}
export function SeriesContent({
@@ -23,6 +24,7 @@ export function SeriesContent({
currentPage,
preferences,
unreadOnly,
initialIsFavorite,
}: SeriesContentProps) {
const { refreshSeries } = useRefresh();
@@ -31,6 +33,7 @@ export function SeriesContent({
<SeriesHeader
series={series}
refreshSeries={refreshSeries || (async () => ({ success: false }))}
initialIsFavorite={initialIsFavorite}
/>
<Container>
<PaginatedBookGrid
@@ -45,4 +48,3 @@ export function SeriesContent({
</>
);
}

View File

@@ -1,5 +1,6 @@
import { PreferencesService } from "@/lib/services/preferences.service";
import { SeriesService } from "@/lib/services/series.service";
import { FavoriteService } from "@/lib/services/favorite.service";
import { SeriesClientWrapper } from "./SeriesClientWrapper";
import { SeriesContent } from "./SeriesContent";
import { ErrorMessage } from "@/components/ui/ErrorMessage";
@@ -28,9 +29,10 @@ export default async function SeriesPage({ params, searchParams }: PageProps) {
const effectivePageSize = size ? parseInt(size) : preferences.displayMode?.itemsPerPage || DEFAULT_PAGE_SIZE;
try {
const [books, series] = await Promise.all([
const [books, series, isFavorite] = await Promise.all([
SeriesService.getSeriesBooks(seriesId, currentPage - 1, effectivePageSize, unreadOnly),
SeriesService.getSeries(seriesId),
FavoriteService.isFavorite(seriesId),
]);
return (
@@ -48,6 +50,7 @@ export default async function SeriesPage({ params, searchParams }: PageProps) {
preferences={preferences}
unreadOnly={unreadOnly}
pageSize={effectivePageSize}
initialIsFavorite={isFavorite}
/>
</SeriesClientWrapper>
);

View File

@@ -1,7 +1,8 @@
import { ConfigDBService } from "@/lib/services/config-db.service";
import { LibraryService } from "@/lib/services/library.service";
import { ClientSettings } from "@/components/settings/ClientSettings";
import type { Metadata } from "next";
import type { KomgaConfig } from "@/types/komga";
import type { KomgaConfig, KomgaLibrary } from "@/types/komga";
import logger from "@/lib/logger";
export const dynamic = "force-dynamic";
@@ -13,6 +14,7 @@ export const metadata: Metadata = {
export default async function SettingsPage() {
let config: KomgaConfig | null = null;
let libraries: KomgaLibrary[] = [];
try {
// Récupérer la configuration Komga
@@ -26,10 +28,12 @@ export default async function SettingsPage() {
password: null,
};
}
libraries = await LibraryService.getLibraries();
} catch (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
}
return <ClientSettings initialConfig={config} />;
return <ClientSettings initialConfig={config} initialLibraries={libraries} />;
}