From 52350a43d93bf46d02fd3d510dab53f1a1773d01 Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Sun, 26 Oct 2025 06:15:47 +0100 Subject: [PATCH] feat: add logging enhancements by integrating pino and pino-pretty for improved error tracking and debugging across the application --- next.config.js | 2 +- package.json | 2 + pnpm-lock.yaml | 172 ++++++++++++++++++ src/app/account/page.tsx | 3 +- src/app/admin/page.tsx | 3 +- src/app/api/admin/stats/route.ts | 3 +- .../admin/users/[userId]/password/route.ts | 3 +- src/app/api/admin/users/[userId]/route.ts | 5 +- src/app/api/admin/users/route.ts | 3 +- src/app/api/auth/register/route.ts | 3 +- .../[bookId]/pages/[pageNumber]/route.ts | 3 +- .../books/[bookId]/read-progress/route.ts | 5 +- src/app/api/komga/books/[bookId]/route.ts | 3 +- .../clear/[libraryId]/[seriesId]/route.ts | 3 +- src/app/api/komga/cache/clear/route.ts | 3 +- src/app/api/komga/cache/entries/route.ts | 3 +- src/app/api/komga/cache/mode/route.ts | 5 +- src/app/api/komga/cache/size/route.ts | 3 +- src/app/api/komga/config/route.ts | 5 +- src/app/api/komga/favorites/route.ts | 7 +- src/app/api/komga/home/route.ts | 5 +- .../[bookId]/pages/[pageNumber]/route.ts | 5 +- .../pages/[pageNumber]/thumbnail/route.ts | 5 +- .../images/books/[bookId]/thumbnail/route.ts | 5 +- .../series/[seriesId]/first-page/route.ts | 5 +- .../series/[seriesId]/thumbnail/route.ts | 6 +- .../komga/libraries/[libraryId]/scan/route.ts | 3 +- .../libraries/[libraryId]/series/route.ts | 5 +- src/app/api/komga/libraries/route.ts | 3 +- src/app/api/komga/random-book/route.ts | 3 +- .../komga/series/[seriesId]/books/route.ts | 5 +- src/app/api/komga/series/[seriesId]/route.ts | 3 +- src/app/api/komga/test/route.ts | 3 +- src/app/api/komga/ttl-config/route.ts | 5 +- src/app/api/preferences/route.ts | 5 +- src/app/api/user/password/route.ts | 3 +- src/app/api/user/profile/route.ts | 3 +- src/app/layout.tsx | 3 +- .../[libraryId]/ClientLibraryPage.tsx | 7 +- .../series/[seriesId]/ClientSeriesPage.tsx | 7 +- src/app/settings/page.tsx | 3 +- src/components/downloads/DownloadManager.tsx | 7 +- src/components/home/ClientHomePage.tsx | 5 +- src/components/home/HeroSection.tsx | 2 +- src/components/home/HomeContent.tsx | 2 +- src/components/layout/ClientLayout.tsx | 3 +- src/components/layout/Sidebar.tsx | 7 +- src/components/library/ScanButton.tsx | 3 +- src/components/reader/ClientBookPage.tsx | 3 +- .../reader/components/Thumbnail.tsx | 5 +- src/components/reader/hooks/useFullscreen.ts | 5 +- src/components/reader/hooks/useImageLoader.ts | 3 +- .../reader/hooks/usePageNavigation.ts | 3 +- src/components/series/SeriesHeader.tsx | 5 +- src/components/settings/AdvancedSettings.tsx | 7 +- .../settings/BackgroundSettings.tsx | 19 +- src/components/settings/CacheModeSwitch.tsx | 3 +- src/components/settings/CacheSettings.tsx | 13 +- src/components/settings/DisplaySettings.tsx | 5 +- src/components/settings/KomgaSettings.tsx | 5 +- src/components/ui/ErrorMessage.tsx | 3 +- src/components/ui/InstallPWA.tsx | 3 +- src/components/ui/book-offline-button.tsx | 11 +- src/components/ui/mark-as-read-button.tsx | 3 +- src/components/ui/mark-as-unread-button.tsx | 3 +- src/contexts/ImageCacheContext.tsx | 4 +- src/contexts/PreferencesContext.tsx | 5 +- src/hooks/useBookOfflineStatus.ts | 3 +- src/hooks/useDisplayPreferences.ts | 5 +- src/hooks/usePullToRefresh.ts | 3 +- src/lib/auth.ts | 3 +- src/lib/logger.ts | 34 ++++ src/lib/middleware-auth.ts | 3 +- src/lib/registerSW.ts | 6 +- src/lib/services/base-api.service.ts | 16 +- src/lib/services/book.service.ts | 3 +- src/lib/services/circuit-breaker.service.ts | 11 +- src/lib/services/favorite.service.ts | 3 +- src/lib/services/image.service.ts | 3 +- src/lib/services/request-monitor.service.ts | 9 +- src/lib/services/request-queue.service.ts | 3 +- src/lib/services/series.service.ts | 5 +- src/lib/services/server-cache.service.ts | 51 +++--- src/lib/services/test.service.ts | 3 +- 84 files changed, 455 insertions(+), 177 deletions(-) create mode 100644 src/lib/logger.ts diff --git a/next.config.js b/next.config.js index 640de31..579295c 100644 --- a/next.config.js +++ b/next.config.js @@ -8,7 +8,7 @@ const nextConfig = { return config; }, // Configuration pour améliorer la résolution DNS - serverExternalPackages: ['dns'], + serverExternalPackages: ['dns', 'pino', 'pino-pretty'], // Optimisations pour Docker dev experimental: { turbo: { diff --git a/package.json b/package.json index e53df67..0b98168 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,8 @@ "next-auth": "5.0.0-beta.29", "next-themes": "0.2.1", "photoswipe": "^5.4.4", + "pino": "^10.1.0", + "pino-pretty": "^13.1.2", "react": "19.2.0", "react-dom": "19.2.0", "react-i18next": "^15.4.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac6b034..58fedfd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -80,6 +80,12 @@ importers: photoswipe: specifier: ^5.4.4 version: 5.4.4 + pino: + specifier: ^10.1.0 + version: 10.1.0 + pino-pretty: + specifier: ^13.1.2 + version: 13.1.2 react: specifier: 19.2.0 version: 19.2.0 @@ -553,6 +559,9 @@ packages: '@panva/hkdf@1.2.1': resolution: {integrity: sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==} + '@pinojs/redact@0.4.0': + resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -1337,6 +1346,10 @@ packages: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + autoprefixer@10.4.17: resolution: {integrity: sha512-/cpVNRLSfhOtcGflT13P2794gVSgmPgTR+erw5ifnMLZb0UnSlkK4tquLmkd3BhA+nLo5tX8Cu0upUsGKvKbmg==} engines: {node: ^10 || ^12 || >=14} @@ -1464,6 +1477,9 @@ packages: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} engines: {node: '>=12.5.0'} + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -1505,6 +1521,9 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -1595,6 +1614,9 @@ packages: resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} engines: {node: '>=14'} + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + es-abstract@1.24.0: resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} engines: {node: '>= 0.4'} @@ -1785,6 +1807,9 @@ packages: resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} engines: {node: '>=8.0.0'} + fast-copy@3.0.2: + resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -1802,6 +1827,9 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -1965,6 +1993,9 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + html-parse-stringify@3.0.1: resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} @@ -2148,6 +2179,10 @@ packages: jose@6.1.0: resolution: {integrity: sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==} + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -2415,6 +2450,10 @@ packages: ohash@2.0.11: resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -2489,6 +2528,20 @@ packages: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-pretty@13.1.2: + resolution: {integrity: sha512-3cN0tCakkT4f3zo9RXDIhy6GTvtYD6bK4CRBLN9j3E/ePqN1tugAXD5rGVfoChW6s0hiek+eyYlLNqc/BG7vBQ==} + hasBin: true + + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + + pino@10.1.0: + resolution: {integrity: sha512-0zZC2ygfdqvqK8zJIr1e+wT1T/L+LF6qvqvbzEQ6tiMAoTqEVK9a1K3YRu8HEUvGEvNqZyPJTtb2sNIoTkB83w==} + hasBin: true + pirates@4.0.7: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} @@ -2567,9 +2620,15 @@ packages: typescript: optional: true + process-warning@5.0.0: + resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==} + prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + pump@3.0.3: + resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -2580,6 +2639,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + rc9@2.1.2: resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} @@ -2652,6 +2714,10 @@ packages: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -2700,9 +2766,16 @@ packages: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + secure-json-parse@4.1.0: + resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -2767,6 +2840,9 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + sonic-boom@4.2.0: + resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -2774,6 +2850,10 @@ packages: sparse-bitfield@3.0.3: resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + stable-hash@0.0.5: resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} @@ -2832,6 +2912,10 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strip-json-comments@5.0.3: + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} + styled-jsx@5.1.6: resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} engines: {node: '>= 12.0.0'} @@ -2881,6 +2965,9 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + tinyexec@1.0.1: resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} @@ -3386,6 +3473,8 @@ snapshots: '@panva/hkdf@1.2.1': {} + '@pinojs/redact@0.4.0': {} + '@pkgjs/parseargs@0.11.0': optional: true @@ -4218,6 +4307,8 @@ snapshots: async-function@1.0.0: {} + atomic-sleep@1.0.0: {} + autoprefixer@10.4.17(postcss@8.4.33): dependencies: browserslist: 4.26.3 @@ -4358,6 +4449,8 @@ snapshots: color-convert: 2.0.1 color-string: 1.9.1 + colorette@2.0.20: {} + commander@4.1.1: {} concat-map@0.0.1: {} @@ -4396,6 +4489,8 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 + dateformat@4.6.3: {} + debug@3.2.7: dependencies: ms: 2.1.3 @@ -4467,6 +4562,10 @@ snapshots: empathic@2.0.0: {} + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + es-abstract@1.24.0: dependencies: array-buffer-byte-length: 1.0.2 @@ -4804,6 +4903,8 @@ snapshots: dependencies: pure-rand: 6.1.0 + fast-copy@3.0.2: {} + fast-deep-equal@3.1.3: {} fast-glob@3.3.1: @@ -4826,6 +4927,8 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-safe-stringify@2.1.1: {} + fastq@1.19.1: dependencies: reusify: 1.1.0 @@ -5005,6 +5108,8 @@ snapshots: dependencies: function-bind: 1.1.2 + help-me@5.0.0: {} + html-parse-stringify@3.0.1: dependencies: void-elements: 3.1.0 @@ -5190,6 +5295,8 @@ snapshots: jose@6.1.0: {} + joycon@3.1.1: {} + js-tokens@4.0.0: {} js-yaml@4.1.0: @@ -5413,6 +5520,8 @@ snapshots: ohash@2.0.11: {} + on-exit-leak-free@2.1.2: {} + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -5475,6 +5584,42 @@ snapshots: pify@2.3.0: {} + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-pretty@13.1.2: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 3.0.2 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pump: 3.0.3 + secure-json-parse: 4.1.0 + sonic-boom: 4.2.0 + strip-json-comments: 5.0.3 + + pino-std-serializers@7.0.0: {} + + pino@10.1.0: + dependencies: + '@pinojs/redact': 0.4.0 + atomic-sleep: 1.0.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + pirates@4.0.7: {} pkg-types@2.3.0: @@ -5545,18 +5690,27 @@ snapshots: transitivePeerDependencies: - magicast + process-warning@5.0.0: {} + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 react-is: 16.13.1 + pump@3.0.3: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + punycode@2.3.1: {} pure-rand@6.1.0: {} queue-microtask@1.2.3: {} + quick-format-unescaped@4.0.4: {} + rc9@2.1.2: dependencies: defu: 6.1.4 @@ -5618,6 +5772,8 @@ snapshots: readdirp@4.1.2: {} + real-require@0.2.0: {} + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -5683,8 +5839,12 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.1 + safe-stable-stringify@2.5.0: {} + scheduler@0.27.0: {} + secure-json-parse@4.1.0: {} + semver@6.3.1: {} semver@7.7.3: {} @@ -5806,12 +5966,18 @@ snapshots: slash@3.0.0: {} + sonic-boom@4.2.0: + dependencies: + atomic-sleep: 1.0.0 + source-map-js@1.2.1: {} sparse-bitfield@3.0.3: dependencies: memory-pager: 1.5.0 + split2@4.2.0: {} + stable-hash@0.0.5: {} stop-iteration-iterator@1.1.0: @@ -5895,6 +6061,8 @@ snapshots: strip-json-comments@3.1.1: {} + strip-json-comments@5.0.3: {} + styled-jsx@5.1.6(react@19.2.0): dependencies: client-only: 0.0.1 @@ -5959,6 +6127,10 @@ snapshots: dependencies: any-promise: 1.3.0 + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + tinyexec@1.0.1: {} tinyglobby@0.2.15: diff --git a/src/app/account/page.tsx b/src/app/account/page.tsx index ed88667..01465c5 100644 --- a/src/app/account/page.tsx +++ b/src/app/account/page.tsx @@ -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() { ); } catch (error) { - console.error("Erreur lors du chargement du compte:", error); + logger.error({ err: error }, "Erreur lors du chargement du compte:"); redirect("/login"); } } diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index bde809e..d436ab8 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -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 ; } 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("/"); } } diff --git a/src/app/api/admin/stats/route.ts b/src/app/api/admin/stats/route.ts index 2f3cff6..d94cba1 100644 --- a/src/app/api/admin/stats/route.ts +++ b/src/app/api/admin/stats/route.ts @@ -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( diff --git a/src/app/api/admin/users/[userId]/password/route.ts b/src/app/api/admin/users/[userId]/password/route.ts index 5aa56eb..d7110f2 100644 --- a/src/app/api/admin/users/[userId]/password/route.ts +++ b/src/app/api/admin/users/[userId]/password/route.ts @@ -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( diff --git a/src/app/api/admin/users/[userId]/route.ts b/src/app/api/admin/users/[userId]/route.ts index ba373b1..5d30637 100644 --- a/src/app/api/admin/users/[userId]/route.ts +++ b/src/app/api/admin/users/[userId]/route.ts @@ -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( diff --git a/src/app/api/admin/users/route.ts b/src/app/api/admin/users/route.ts index 2dcd849..334a8d8 100644 --- a/src/app/api/admin/users/route.ts +++ b/src/app/api/admin/users/route.ts @@ -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( diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts index 524b9a2..eae0e00 100644 --- a/src/app/api/auth/register/route.ts +++ b/src/app/api/auth/register/route.ts @@ -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( diff --git a/src/app/api/komga/books/[bookId]/pages/[pageNumber]/route.ts b/src/app/api/komga/books/[bookId]/pages/[pageNumber]/route.ts index 2b038a2..4cd1aa5 100644 --- a/src/app/api/komga/books/[bookId]/pages/[pageNumber]/route.ts +++ b/src/app/api/komga/books/[bookId]/pages/[pageNumber]/route.ts @@ -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( { diff --git a/src/app/api/komga/books/[bookId]/read-progress/route.ts b/src/app/api/komga/books/[bookId]/read-progress/route.ts index c2cd360..fac8df0 100644 --- a/src/app/api/komga/books/[bookId]/read-progress/route.ts +++ b/src/app/api/komga/books/[bookId]/read-progress/route.ts @@ -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( { diff --git a/src/app/api/komga/books/[bookId]/route.ts b/src/app/api/komga/books/[bookId]/route.ts index bb88be0..b91d49c 100644 --- a/src/app/api/komga/books/[bookId]/route.ts +++ b/src/app/api/komga/books/[bookId]/route.ts @@ -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( { diff --git a/src/app/api/komga/cache/clear/[libraryId]/[seriesId]/route.ts b/src/app/api/komga/cache/clear/[libraryId]/[seriesId]/route.ts index 1f37cd2..9d1aab6 100644 --- a/src/app/api/komga/cache/clear/[libraryId]/[seriesId]/route.ts +++ b/src/app/api/komga/cache/clear/[libraryId]/[seriesId]/route.ts @@ -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: { diff --git a/src/app/api/komga/cache/clear/route.ts b/src/app/api/komga/cache/clear/route.ts index bf3131f..2dcfec6 100644 --- a/src/app/api/komga/cache/clear/route.ts +++ b/src/app/api/komga/cache/clear/route.ts @@ -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: { diff --git a/src/app/api/komga/cache/entries/route.ts b/src/app/api/komga/cache/entries/route.ts index 398723a..4a19fc5 100644 --- a/src/app/api/komga/cache/entries/route.ts +++ b/src/app/api/komga/cache/entries/route.ts @@ -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: { diff --git a/src/app/api/komga/cache/mode/route.ts b/src/app/api/komga/cache/mode/route.ts index 39aa701..a6e2d04 100644 --- a/src/app/api/komga/cache/mode/route.ts +++ b/src/app/api/komga/cache/mode/route.ts @@ -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: { diff --git a/src/app/api/komga/cache/size/route.ts b/src/app/api/komga/cache/size/route.ts index 79580fe..f807f16 100644 --- a/src/app/api/komga/cache/size/route.ts +++ b/src/app/api/komga/cache/size/route.ts @@ -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: { diff --git a/src/app/api/komga/config/route.ts b/src/app/api/komga/config/route.ts index daf2a8d..ffcf62c 100644 --- a/src/app/api/komga/config/route.ts +++ b/src/app/api/komga/config/route.ts @@ -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( diff --git a/src/app/api/komga/favorites/route.ts b/src/app/api/komga/favorites/route.ts index 355fd0b..98c6018 100644 --- a/src/app/api/komga/favorites/route.ts +++ b/src/app/api/komga/favorites/route.ts @@ -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( { diff --git a/src/app/api/komga/home/route.ts b/src/app/api/komga/home/route.ts index 5822904..42b4267 100644 --- a/src/app/api/komga/home/route.ts +++ b/src/app/api/komga/home/route.ts @@ -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( { diff --git a/src/app/api/komga/images/books/[bookId]/pages/[pageNumber]/route.ts b/src/app/api/komga/images/books/[bookId]/pages/[pageNumber]/route.ts index ff319cd..fda3fd9 100644 --- a/src/app/api/komga/images/books/[bookId]/pages/[pageNumber]/route.ts +++ b/src/app/api/komga/images/books/[bookId]/pages/[pageNumber]/route.ts @@ -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: { diff --git a/src/app/api/komga/images/books/[bookId]/pages/[pageNumber]/thumbnail/route.ts b/src/app/api/komga/images/books/[bookId]/pages/[pageNumber]/thumbnail/route.ts index 05189e1..f053e1f 100644 --- a/src/app/api/komga/images/books/[bookId]/pages/[pageNumber]/thumbnail/route.ts +++ b/src/app/api/komga/images/books/[bookId]/pages/[pageNumber]/thumbnail/route.ts @@ -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: { diff --git a/src/app/api/komga/images/books/[bookId]/thumbnail/route.ts b/src/app/api/komga/images/books/[bookId]/thumbnail/route.ts index 0e49368..76d03b8 100644 --- a/src/app/api/komga/images/books/[bookId]/thumbnail/route.ts +++ b/src/app/api/komga/images/books/[bookId]/thumbnail/route.ts @@ -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: { diff --git a/src/app/api/komga/images/series/[seriesId]/first-page/route.ts b/src/app/api/komga/images/series/[seriesId]/first-page/route.ts index 7ac5deb..31b0429 100644 --- a/src/app/api/komga/images/series/[seriesId]/first-page/route.ts +++ b/src/app/api/komga/images/series/[seriesId]/first-page/route.ts @@ -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: { diff --git a/src/app/api/komga/images/series/[seriesId]/thumbnail/route.ts b/src/app/api/komga/images/series/[seriesId]/thumbnail/route.ts index b0196fd..102994c 100644 --- a/src/app/api/komga/images/series/[seriesId]/thumbnail/route.ts +++ b/src/app/api/komga/images/series/[seriesId]/thumbnail/route.ts @@ -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: { diff --git a/src/app/api/komga/libraries/[libraryId]/scan/route.ts b/src/app/api/komga/libraries/[libraryId]/scan/route.ts index 83112a9..54ddd80 100644 --- a/src/app/api/komga/libraries/[libraryId]/scan/route.ts +++ b/src/app/api/komga/libraries/[libraryId]/scan/route.ts @@ -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( { diff --git a/src/app/api/komga/libraries/[libraryId]/series/route.ts b/src/app/api/komga/libraries/[libraryId]/series/route.ts index 0638a5e..6704082 100644 --- a/src/app/api/komga/libraries/[libraryId]/series/route.ts +++ b/src/app/api/komga/libraries/[libraryId]/series/route.ts @@ -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( { diff --git a/src/app/api/komga/libraries/route.ts b/src/app/api/komga/libraries/route.ts index 69e15c5..6d3657d 100644 --- a/src/app/api/komga/libraries/route.ts +++ b/src/app/api/komga/libraries/route.ts @@ -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( { diff --git a/src/app/api/komga/random-book/route.ts b/src/app/api/komga/random-book/route.ts index 61b3a8f..65a5600 100644 --- a/src/app/api/komga/random-book/route.ts +++ b/src/app/api/komga/random-book/route.ts @@ -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( { diff --git a/src/app/api/komga/series/[seriesId]/books/route.ts b/src/app/api/komga/series/[seriesId]/books/route.ts index e2d7552..f694a4b 100644 --- a/src/app/api/komga/series/[seriesId]/books/route.ts +++ b/src/app/api/komga/series/[seriesId]/books/route.ts @@ -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( { diff --git a/src/app/api/komga/series/[seriesId]/route.ts b/src/app/api/komga/series/[seriesId]/route.ts index 9000875..9da49a1 100644 --- a/src/app/api/komga/series/[seriesId]/route.ts +++ b/src/app/api/komga/series/[seriesId]/route.ts @@ -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( { diff --git a/src/app/api/komga/test/route.ts b/src/app/api/komga/test/route.ts index 3801e76..d5aab3b 100644 --- a/src/app/api/komga/test/route.ts +++ b/src/app/api/komga/test/route.ts @@ -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: { diff --git a/src/app/api/komga/ttl-config/route.ts b/src/app/api/komga/ttl-config/route.ts index f0e01da..150eab2 100644 --- a/src/app/api/komga/ttl-config/route.ts +++ b/src/app/api/komga/ttl-config/route.ts @@ -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) diff --git a/src/app/api/preferences/route.ts b/src/app/api/preferences/route.ts index 33819b3..9586f21 100644 --- a/src/app/api/preferences/route.ts +++ b/src/app/api/preferences/route.ts @@ -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( { diff --git a/src/app/api/user/password/route.ts b/src/app/api/user/password/route.ts index ce62236..7330cc7 100644 --- a/src/app/api/user/password/route.ts +++ b/src/app/api/user/password/route.ts @@ -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( diff --git a/src/app/api/user/profile/route.ts b/src/app/api/user/profile/route.ts index de6a55c..759428e 100644 --- a/src/app/api/user/profile/route.ts +++ b/src/app/api/user/profile/route.ts @@ -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( diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 2a86b96..6ff8c15 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -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 ( diff --git a/src/app/libraries/[libraryId]/ClientLibraryPage.tsx b/src/app/libraries/[libraryId]/ClientLibraryPage.tsx index 2dba7a0..d7843bf 100644 --- a/src/app/libraries/[libraryId]/ClientLibraryPage.tsx +++ b/src/app/libraries/[libraryId]/ClientLibraryPage.tsx @@ -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); diff --git a/src/app/series/[seriesId]/ClientSeriesPage.tsx b/src/app/series/[seriesId]/ClientSeriesPage.tsx index bb1eb5a..f2697b2 100644 --- a/src/app/series/[seriesId]/ClientSeriesPage.tsx +++ b/src/app/series/[seriesId]/ClientSeriesPage.tsx @@ -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); diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index 6786681..cf4e110 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -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 } diff --git a/src/components/downloads/DownloadManager.tsx b/src/components/downloads/DownloadManager.tsx index b1bb3c5..22e372c 100644 --- a/src/components/downloads/DownloadManager.tsx +++ b/src/components/downloads/DownloadManager.tsx @@ -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"), diff --git a/src/components/home/ClientHomePage.tsx b/src/components/home/ClientHomePage.tsx index 35114fe..45a3697 100644 --- a/src/components/home/ClientHomePage.tsx +++ b/src/components/home/ClientHomePage.tsx @@ -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" }; } }; diff --git a/src/components/home/HeroSection.tsx b/src/components/home/HeroSection.tsx index 71665db..89f3f78 100644 --- a/src/components/home/HeroSection.tsx +++ b/src/components/home/HeroSection.tsx @@ -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], // }); diff --git a/src/components/home/HomeContent.tsx b/src/components/home/HomeContent.tsx index 11df128..fd295a0 100644 --- a/src/components/home/HomeContent.tsx +++ b/src/components/home/HomeContent.tsx @@ -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, diff --git a/src/components/layout/ClientLayout.tsx b/src/components/layout/ClientLayout.tsx index 9d2cfc3..2688ad1 100644 --- a/src/components/layout/ClientLayout.tsx +++ b/src/components/layout/ClientLayout.tsx @@ -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]); diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 1a1f928..1f96d9e 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -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", diff --git a/src/components/library/ScanButton.tsx b/src/components/library/ScanButton.tsx index 3bd6200..0f397d6 100644 --- a/src/components/library/ScanButton.tsx +++ b/src/components/library/ScanButton.tsx @@ -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"), diff --git a/src/components/reader/ClientBookPage.tsx b/src/components/reader/ClientBookPage.tsx index 339c749..9c73aaf 100644 --- a/src/components/reader/ClientBookPage.tsx +++ b/src/components/reader/ClientBookPage.tsx @@ -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); diff --git a/src/components/reader/components/Thumbnail.tsx b/src/components/reader/components/Thumbnail.tsx index 732e9e6..ce77871 100644 --- a/src/components/reader/components/Thumbnail.tsx +++ b/src/components/reader/components/Thumbnail.tsx @@ -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( ( @@ -73,7 +74,7 @@ export const Thumbnail = forwardRef( 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( }); }, delay); } else { - console.error( + logger.error( `Échec du chargement de l'image pour la page ${pageNumber} après ${maxAttempts} tentatives` ); setHasError(true); diff --git a/src/components/reader/hooks/useFullscreen.ts b/src/components/reader/hooks/useFullscreen.ts index a803e72..e57177a 100644 --- a/src/components/reader/hooks/useFullscreen.ts +++ b/src/components/reader/hooks/useFullscreen.ts @@ -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:"); } }; diff --git a/src/components/reader/hooks/useImageLoader.ts b/src/components/reader/hooks/useImageLoader.ts index 536f664..a862a13 100644 --- a/src/components/reader/hooks/useImageLoader.ts +++ b/src/components/reader/hooks/useImageLoader.ts @@ -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]); diff --git a/src/components/reader/hooks/usePageNavigation.ts b/src/components/reader/hooks/usePageNavigation.ts index 6e39b49..058a410 100644 --- a/src/components/reader/hooks/usePageNavigation.ts +++ b/src/components/reader/hooks/usePageNavigation.ts @@ -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] diff --git a/src/components/series/SeriesHeader.tsx b/src/components/series/SeriesHeader.tsx index 9e762c6..35b6308 100644 --- a/src/components/series/SeriesHeader.tsx +++ b/src/components/series/SeriesHeader.tsx @@ -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: diff --git a/src/components/settings/AdvancedSettings.tsx b/src/components/settings/AdvancedSettings.tsx index 993720e..e482318 100644 --- a/src/components/settings/AdvancedSettings.tsx +++ b/src/components/settings/AdvancedSettings.tsx @@ -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"), diff --git a/src/components/settings/BackgroundSettings.tsx b/src/components/settings/BackgroundSettings.tsx index f7bbea8..9ece3da 100644 --- a/src/components/settings/BackgroundSettings.tsx +++ b/src/components/settings/BackgroundSettings.tsx @@ -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:"); } }; diff --git a/src/components/settings/CacheModeSwitch.tsx b/src/components/settings/CacheModeSwitch.tsx index 4f135cb..76af928 100644 --- a/src/components/settings/CacheModeSwitch.tsx +++ b/src/components/settings/CacheModeSwitch.tsx @@ -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", diff --git a/src/components/settings/CacheSettings.tsx b/src/components/settings/CacheSettings.tsx index 1a6c9cf..882a769 100644 --- a/src/components/settings/CacheSettings.tsx +++ b/src/components/settings/CacheSettings.tsx @@ -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"), diff --git a/src/components/settings/DisplaySettings.tsx b/src/components/settings/DisplaySettings.tsx index bd5c438..e9b1e3c 100644 --- a/src/components/settings/DisplaySettings.tsx +++ b/src/components/settings/DisplaySettings.tsx @@ -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"), diff --git a/src/components/settings/KomgaSettings.tsx b/src/components/settings/KomgaSettings.tsx index 6f64620..447fcdb 100644 --- a/src/components/settings/KomgaSettings.tsx +++ b/src/components/settings/KomgaSettings.tsx @@ -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"), diff --git a/src/components/ui/ErrorMessage.tsx b/src/components/ui/ErrorMessage.tsx index 0c9337b..4ab55d0 100644 --- a/src/components/ui/ErrorMessage.tsx +++ b/src/components/ui/ErrorMessage.tsx @@ -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") { diff --git a/src/components/ui/InstallPWA.tsx b/src/components/ui/InstallPWA.tsx index e3c2393..fd41e95 100644 --- a/src/components/ui/InstallPWA.tsx +++ b/src/components/ui/InstallPWA.tsx @@ -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; @@ -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); diff --git a/src/components/ui/book-offline-button.tsx b/src/components/ui/book-offline-button.tsx index 393f26d..0cbf262 100644 --- a/src/components/ui/book-offline-button.tsx +++ b/src/components/ui/book-offline-button.tsx @@ -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", diff --git a/src/components/ui/mark-as-read-button.tsx b/src/components/ui/mark-as-read-button.tsx index 7260f7a..4a8e60e 100644 --- a/src/components/ui/mark-as-read-button.tsx +++ b/src/components/ui/mark-as-read-button.tsx @@ -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"), diff --git a/src/components/ui/mark-as-unread-button.tsx b/src/components/ui/mark-as-unread-button.tsx index 9c90750..c5b206c 100644 --- a/src/components/ui/mark-as-unread-button.tsx +++ b/src/components/ui/mark-as-unread-button.tsx @@ -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"), diff --git a/src/contexts/ImageCacheContext.tsx b/src/contexts/ImageCacheContext.tsx index 295dd40..df03437 100644 --- a/src/contexts/ImageCacheContext.tsx +++ b/src/contexts/ImageCacheContext.tsx @@ -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( diff --git a/src/contexts/PreferencesContext.tsx b/src/contexts/PreferencesContext.tsx index a1ad0bf..31820e6 100644 --- a/src/contexts/PreferencesContext.tsx +++ b/src/contexts/PreferencesContext.tsx @@ -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; } }, []); diff --git a/src/hooks/useBookOfflineStatus.ts b/src/hooks/useBookOfflineStatus.ts index 1b6fc4f..9dd8e12 100644 --- a/src/hooks/useBookOfflineStatus.ts +++ b/src/hooks/useBookOfflineStatus.ts @@ -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); diff --git a/src/hooks/useDisplayPreferences.ts b/src/hooks/useDisplayPreferences.ts index ec648a7..baf8780 100644 --- a/src/hooks/useDisplayPreferences.ts +++ b/src/hooks/useDisplayPreferences.ts @@ -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"); } }; diff --git a/src/hooks/usePullToRefresh.ts b/src/hooks/usePullToRefresh.ts index 8faf2ee..5d51298 100644 --- a/src/hooks/usePullToRefresh.ts +++ b/src/hooks/usePullToRefresh.ts @@ -1,6 +1,7 @@ "use client"; import { useEffect, useRef, useState } from "react"; +import logger from "@/lib/logger"; interface UsePullToRefreshOptions { onRefresh: () => Promise; @@ -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 diff --git a/src/lib/auth.ts b/src/lib/auth.ts index eef9478..58ef9e7 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -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; } }, diff --git a/src/lib/logger.ts b/src/lib/logger.ts new file mode 100644 index 0000000..a751067 --- /dev/null +++ b/src/lib/logger.ts @@ -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; + diff --git a/src/lib/middleware-auth.ts b/src/lib/middleware-auth.ts index a1189d1..7af2e59 100644 --- a/src/lib/middleware-auth.ts +++ b/src/lib/middleware-auth.ts @@ -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; } } diff --git a/src/lib/registerSW.ts b/src/lib/registerSW.ts index 3dee270..c082d06 100644 --- a/src/lib/registerSW.ts +++ b/src/lib/registerSW.ts @@ -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:"); } }; diff --git a/src/lib/services/base-api.service.ts b/src/lib/services/base-api.service.ts index 502e9c8..ff274c0 100644 --- a/src/lib/services/base-api.service.ts +++ b/src/lib/services/base-api.service.ts @@ -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, diff --git a/src/lib/services/book.service.ts b/src/lib/services/book.service.ts index 5113cd0..0663f59 100644 --- a/src/lib/services/book.service.ts +++ b/src/lib/services/book.service.ts @@ -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 { @@ -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 } } diff --git a/src/lib/services/circuit-breaker.service.ts b/src/lib/services/circuit-breaker.service.ts index 93e8595..b450d50 100644 --- a/src/lib/services/circuit-breaker.service.ts +++ b/src/lib/services/circuit-breaker.service.ts @@ -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'); } } diff --git a/src/lib/services/favorite.service.ts b/src/lib/services/favorite.service.ts index 74c790b..0499604 100644 --- a/src/lib/services/favorite.service.ts +++ b/src/lib/services/favorite.service.ts @@ -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; } } diff --git a/src/lib/services/image.service.ts b/src/lib/services/image.service.ts index 4aed256..43d3efb 100644 --- a/src/lib/services/image.service.ts +++ b/src/lib/services/image.service.ts @@ -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); } } diff --git a/src/lib/services/request-monitor.service.ts b/src/lib/services/request-monitor.service.ts index 8c6c541..1623994 100644 --- a/src/lib/services/request-monitor.service.ts +++ b/src/lib/services/request-monitor.service.ts @@ -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`); } } } diff --git a/src/lib/services/request-queue.service.ts b/src/lib/services/request-queue.service.ts index 512b46d..c2f3752 100644 --- a/src/lib/services/request-queue.service.ts +++ b/src/lib/services/request-queue.service.ts @@ -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 { execute: () => Promise; @@ -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; } } diff --git a/src/lib/services/series.service.ts b/src/lib/services/series.service.ts index 8414105..9d19353 100644 --- a/src/lib/services/series.service.ts +++ b/src/lib/services/series.service.ts @@ -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 { @@ -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); } } diff --git a/src/lib/services/server-cache.service.ts b/src/lib/services/server-cache.service.ts index 73dffac..e7a4dc1 100644 --- a/src/lib/services/server-cache.service.ts +++ b/src/lib/services/server-cache.service.ts @@ -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}`); } } }; diff --git a/src/lib/services/test.service.ts b/src/lib/services/test.service.ts index bc02012..ed7f926 100644 --- a/src/lib/services/test.service.ts +++ b/src/lib/services/test.service.ts @@ -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; }