Merge branch 'main' into feat/debugmode
This commit is contained in:
@@ -15,7 +15,9 @@
|
|||||||
"@radix-ui/react-progress": "^1.1.2",
|
"@radix-ui/react-progress": "^1.1.2",
|
||||||
"@radix-ui/react-slot": "1.0.2",
|
"@radix-ui/react-slot": "1.0.2",
|
||||||
"@radix-ui/react-toast": "1.1.5",
|
"@radix-ui/react-toast": "1.1.5",
|
||||||
|
"@types/bcrypt": "^5.0.2",
|
||||||
"@types/mongoose": "5.11.97",
|
"@types/mongoose": "5.11.97",
|
||||||
|
"bcrypt": "^5.1.1",
|
||||||
"class-variance-authority": "^0.7.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"clsx": "2.1.0",
|
"clsx": "2.1.0",
|
||||||
"lucide-react": "0.323.0",
|
"lucide-react": "0.323.0",
|
||||||
|
|||||||
15
src/app/api/komga/cache/clear/route.ts
vendored
15
src/app/api/komga/cache/clear/route.ts
vendored
@@ -1,15 +1,8 @@
|
|||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import { serverCacheService } from "@/lib/services/server-cache.service";
|
import { getServerCacheService } from "@/lib/services/server-cache.service";
|
||||||
|
|
||||||
export async function POST() {
|
export async function POST() {
|
||||||
try {
|
const cacheService = await getServerCacheService();
|
||||||
serverCacheService.clear();
|
cacheService.clear();
|
||||||
return NextResponse.json({ message: "Cache serveur supprimé avec succès" });
|
return NextResponse.json({ message: "Cache cleared" });
|
||||||
} catch (error) {
|
|
||||||
console.error("Erreur lors de la suppression du cache serveur:", error);
|
|
||||||
return NextResponse.json(
|
|
||||||
{ error: "Erreur lors de la suppression du cache serveur" },
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/app/api/komga/cache/mode/route.ts
vendored
10
src/app/api/komga/cache/mode/route.ts
vendored
@@ -1,8 +1,9 @@
|
|||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import { serverCacheService } from "@/lib/services/server-cache.service";
|
import { getServerCacheService } from "@/lib/services/server-cache.service";
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
return NextResponse.json({ mode: serverCacheService.getCacheMode() });
|
const cacheService = await getServerCacheService();
|
||||||
|
return NextResponse.json({ mode: cacheService.getCacheMode() });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
export async function POST(request: Request) {
|
||||||
@@ -15,8 +16,9 @@ export async function POST(request: Request) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
serverCacheService.setCacheMode(mode);
|
const cacheService = await getServerCacheService();
|
||||||
return NextResponse.json({ mode: serverCacheService.getCacheMode() });
|
cacheService.setCacheMode(mode);
|
||||||
|
return NextResponse.json({ mode: cacheService.getCacheMode() });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Erreur lors de la mise à jour du mode de cache:", error);
|
console.error("Erreur lors de la mise à jour du mode de cache:", error);
|
||||||
return NextResponse.json({ error: "Invalid request" }, { status: 400 });
|
return NextResponse.json({ error: "Invalid request" }, { status: 400 });
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ async function refreshLibrary(libraryId: string) {
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await LibraryService.clearLibrarySeriesCache(libraryId);
|
await LibraryService.invalidateLibrarySeriesCache(libraryId);
|
||||||
|
|
||||||
revalidatePath(`/libraries/${libraryId}`);
|
revalidatePath(`/libraries/${libraryId}`);
|
||||||
return { success: true };
|
return { success: true };
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ async function refreshHome() {
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await HomeService.clearHomeCache();
|
await HomeService.invalidateHomeCache();
|
||||||
revalidatePath("/");
|
revalidatePath("/");
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ async function refreshSeries(seriesId: string) {
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await SeriesService.clearSeriesBooksCache(seriesId);
|
await SeriesService.invalidateSeriesBooksCache(seriesId);
|
||||||
await SeriesService.clearSeriesCache(seriesId);
|
await SeriesService.invalidateSeriesCache(seriesId);
|
||||||
revalidatePath(`/series/${seriesId}`);
|
revalidatePath(`/series/${seriesId}`);
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState, useCallback } from "react";
|
||||||
import { KomgaBook } from "@/types/komga";
|
import { KomgaBook } from "@/types/komga";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
import { Card } from "@/components/ui/card";
|
import { Card } from "@/components/ui/card";
|
||||||
@@ -31,12 +31,11 @@ export function DownloadManager() {
|
|||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const getStorageKey = (bookId: string) => `book-status-${bookId}`;
|
const getStorageKey = useCallback((bookId: string) => `book-status-${bookId}`, []);
|
||||||
|
|
||||||
const loadDownloadedBooks = async () => {
|
const loadDownloadedBooks = useCallback(async () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
// Récupère tous les livres du localStorage
|
|
||||||
const books: DownloadedBook[] = [];
|
const books: DownloadedBook[] = [];
|
||||||
for (let i = 0; i < localStorage.length; i++) {
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
const key = localStorage.key(i);
|
const key = localStorage.key(i);
|
||||||
@@ -70,9 +69,9 @@ export function DownloadManager() {
|
|||||||
} finally {
|
} finally {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
};
|
}, [toast]);
|
||||||
|
|
||||||
const updateBookStatuses = () => {
|
const updateBookStatuses = useCallback(() => {
|
||||||
setDownloadedBooks((prevBooks) => {
|
setDownloadedBooks((prevBooks) => {
|
||||||
return prevBooks.map((downloadedBook) => {
|
return prevBooks.map((downloadedBook) => {
|
||||||
const status = JSON.parse(
|
const status = JSON.parse(
|
||||||
@@ -87,29 +86,25 @@ export function DownloadManager() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
}, [getStorageKey]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadDownloadedBooks();
|
loadDownloadedBooks();
|
||||||
|
|
||||||
// Écoute les changements de statut des livres
|
|
||||||
const handleStorageChange = (e: StorageEvent) => {
|
const handleStorageChange = (e: StorageEvent) => {
|
||||||
if (e.key?.startsWith("book-status-")) {
|
if (e.key?.startsWith("book-status-")) {
|
||||||
updateBookStatuses();
|
updateBookStatuses();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Écoute les changements dans d'autres onglets
|
|
||||||
window.addEventListener("storage", handleStorageChange);
|
window.addEventListener("storage", handleStorageChange);
|
||||||
|
|
||||||
// Écoute les changements dans l'onglet courant
|
|
||||||
const interval = setInterval(updateBookStatuses, 1000);
|
const interval = setInterval(updateBookStatuses, 1000);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener("storage", handleStorageChange);
|
window.removeEventListener("storage", handleStorageChange);
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [loadDownloadedBooks, updateBookStatuses]);
|
||||||
|
|
||||||
const handleDeleteBook = async (book: KomgaBook) => {
|
const handleDeleteBook = async (book: KomgaBook) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import { HeroSection } from "./HeroSection";
|
|||||||
import { MediaRow } from "./MediaRow";
|
import { MediaRow } from "./MediaRow";
|
||||||
import { KomgaBook, KomgaSeries } from "@/types/komga";
|
import { KomgaBook, KomgaSeries } from "@/types/komga";
|
||||||
import { RefreshButton } from "@/components/library/RefreshButton";
|
import { RefreshButton } from "@/components/library/RefreshButton";
|
||||||
|
import { BookOpenCheck, History, Sparkles, Clock } from "lucide-react";
|
||||||
|
|
||||||
interface HomeData {
|
interface HomeData {
|
||||||
ongoing: KomgaSeries[];
|
ongoing: KomgaSeries[];
|
||||||
recentlyRead: KomgaBook[];
|
recentlyRead: KomgaBook[];
|
||||||
onDeck: KomgaBook[];
|
onDeck: KomgaBook[];
|
||||||
|
latestSeries: KomgaSeries[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface HomeContentProps {
|
interface HomeContentProps {
|
||||||
@@ -61,15 +63,35 @@ export function HomeContent({ data, refreshHome }: HomeContentProps) {
|
|||||||
{/* Sections de contenu */}
|
{/* Sections de contenu */}
|
||||||
<div className="space-y-12">
|
<div className="space-y-12">
|
||||||
{data.ongoing && data.ongoing.length > 0 && (
|
{data.ongoing && data.ongoing.length > 0 && (
|
||||||
<MediaRow title="Continuer la lecture" items={optimizeSeriesData(data.ongoing)} />
|
<MediaRow
|
||||||
|
title="Continuer la lecture"
|
||||||
|
items={optimizeSeriesData(data.ongoing)}
|
||||||
|
icon={<BookOpenCheck className="w-6 h-6" />}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{data.onDeck && data.onDeck.length > 0 && (
|
{data.onDeck && data.onDeck.length > 0 && (
|
||||||
<MediaRow title="À suivre" items={optimizeBookData(data.onDeck)} />
|
<MediaRow
|
||||||
|
title="À suivre"
|
||||||
|
items={optimizeBookData(data.onDeck)}
|
||||||
|
icon={<Clock className="w-6 h-6" />}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{data.latestSeries && data.latestSeries.length > 0 && (
|
||||||
|
<MediaRow
|
||||||
|
title="Dernières séries"
|
||||||
|
items={optimizeSeriesData(data.latestSeries)}
|
||||||
|
icon={<Sparkles className="w-6 h-6" />}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{data.recentlyRead && data.recentlyRead.length > 0 && (
|
{data.recentlyRead && data.recentlyRead.length > 0 && (
|
||||||
<MediaRow title="Ajouts récents" items={optimizeBookData(data.recentlyRead)} />
|
<MediaRow
|
||||||
|
title="Ajouts récents"
|
||||||
|
items={optimizeBookData(data.recentlyRead)}
|
||||||
|
icon={<History className="w-6 h-6" />}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -26,9 +26,10 @@ interface OptimizedBook extends BaseItem {
|
|||||||
interface MediaRowProps {
|
interface MediaRowProps {
|
||||||
title: string;
|
title: string;
|
||||||
items: (OptimizedSeries | OptimizedBook)[];
|
items: (OptimizedSeries | OptimizedBook)[];
|
||||||
|
icon?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MediaRow({ title, items }: MediaRowProps) {
|
export function MediaRow({ title, items, icon }: MediaRowProps) {
|
||||||
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
const scrollContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const [showLeftArrow, setShowLeftArrow] = useState(false);
|
const [showLeftArrow, setShowLeftArrow] = useState(false);
|
||||||
const [showRightArrow, setShowRightArrow] = useState(true);
|
const [showRightArrow, setShowRightArrow] = useState(true);
|
||||||
@@ -58,7 +59,10 @@ export function MediaRow({ title, items }: MediaRowProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h2 className="text-2xl font-bold tracking-tight">{title}</h2>
|
<div className="flex items-center gap-2">
|
||||||
|
{icon}
|
||||||
|
<h2 className="text-2xl font-bold tracking-tight">{title}</h2>
|
||||||
|
</div>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
{/* Bouton de défilement gauche */}
|
{/* Bouton de défilement gauche */}
|
||||||
{showLeftArrow && (
|
{showLeftArrow && (
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { Download, Check, Loader2 } from "lucide-react";
|
import { Download, Check, Loader2 } from "lucide-react";
|
||||||
import { Button } from "./button";
|
import { Button } from "./button";
|
||||||
import { useToast } from "./use-toast";
|
import { useToast } from "./use-toast";
|
||||||
@@ -27,156 +27,141 @@ export function BookOfflineButton({ book, className }: BookOfflineButtonProps) {
|
|||||||
const [downloadProgress, setDownloadProgress] = useState(0);
|
const [downloadProgress, setDownloadProgress] = useState(0);
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const getStorageKey = (bookId: string) => `book-status-${bookId}`;
|
const getStorageKey = useCallback((bookId: string) => `book-status-${bookId}`, []);
|
||||||
|
|
||||||
const getBookStatus = (bookId: string): BookDownloadStatus => {
|
const getBookStatus = useCallback(
|
||||||
try {
|
(bookId: string): BookDownloadStatus => {
|
||||||
const status = localStorage.getItem(getStorageKey(bookId));
|
try {
|
||||||
return status ? JSON.parse(status) : { status: "idle", progress: 0, timestamp: 0 };
|
const status = localStorage.getItem(getStorageKey(bookId));
|
||||||
} catch {
|
return status ? JSON.parse(status) : { status: "idle", progress: 0, timestamp: 0 };
|
||||||
return { status: "idle", progress: 0, timestamp: 0 };
|
} catch {
|
||||||
}
|
return { status: "idle", progress: 0, timestamp: 0 };
|
||||||
};
|
|
||||||
|
|
||||||
const setBookStatus = (bookId: string, status: BookDownloadStatus) => {
|
|
||||||
localStorage.setItem(getStorageKey(bookId), JSON.stringify(status));
|
|
||||||
};
|
|
||||||
|
|
||||||
const downloadBook = async (startFromPage: number = 1) => {
|
|
||||||
try {
|
|
||||||
const cache = await caches.open("stripstream-books");
|
|
||||||
|
|
||||||
// Marque le début du téléchargement
|
|
||||||
setBookStatus(book.id, {
|
|
||||||
status: "downloading",
|
|
||||||
progress: ((startFromPage - 1) / book.media.pagesCount) * 100,
|
|
||||||
timestamp: Date.now(),
|
|
||||||
lastDownloadedPage: startFromPage - 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ajoute le livre au cache si on commence depuis le début
|
|
||||||
if (startFromPage === 1) {
|
|
||||||
const pagesResponse = await fetch(`/api/komga/images/books/${book.id}/pages/1`);
|
|
||||||
if (!pagesResponse.ok) throw new Error("Erreur lors de la récupération des pages");
|
|
||||||
await cache.put(`/api/komga/images/books/${book.id}/pages`, pagesResponse.clone());
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
[getStorageKey]
|
||||||
|
);
|
||||||
|
|
||||||
// Cache chaque page avec retry
|
const setBookStatus = useCallback(
|
||||||
let failedPages = 0;
|
(bookId: string, status: BookDownloadStatus) => {
|
||||||
for (let i = startFromPage; i <= book.media.pagesCount; i++) {
|
localStorage.setItem(getStorageKey(bookId), JSON.stringify(status));
|
||||||
let retryCount = 0;
|
},
|
||||||
const maxRetries = 3;
|
[getStorageKey]
|
||||||
|
);
|
||||||
|
|
||||||
while (retryCount < maxRetries) {
|
const downloadBook = useCallback(
|
||||||
try {
|
async (startFromPage: number = 1) => {
|
||||||
const pageResponse = await fetch(`/api/komga/images/books/${book.id}/pages/${i}`);
|
try {
|
||||||
if (!pageResponse.ok) {
|
const cache = await caches.open("stripstream-books");
|
||||||
|
|
||||||
|
// Marque le début du téléchargement
|
||||||
|
setBookStatus(book.id, {
|
||||||
|
status: "downloading",
|
||||||
|
progress: ((startFromPage - 1) / book.media.pagesCount) * 100,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
lastDownloadedPage: startFromPage - 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ajoute le livre au cache si on commence depuis le début
|
||||||
|
if (startFromPage === 1) {
|
||||||
|
const pagesResponse = await fetch(`/api/komga/images/books/${book.id}/pages/1`);
|
||||||
|
if (!pagesResponse.ok) throw new Error("Erreur lors de la récupération des pages");
|
||||||
|
await cache.put(`/api/komga/images/books/${book.id}/pages`, pagesResponse.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache chaque page avec retry
|
||||||
|
let failedPages = 0;
|
||||||
|
for (let i = startFromPage; i <= book.media.pagesCount; i++) {
|
||||||
|
let retryCount = 0;
|
||||||
|
const maxRetries = 3;
|
||||||
|
|
||||||
|
while (retryCount < maxRetries) {
|
||||||
|
try {
|
||||||
|
const pageResponse = await fetch(`/api/komga/images/books/${book.id}/pages/${i}`);
|
||||||
|
if (!pageResponse.ok) {
|
||||||
|
retryCount++;
|
||||||
|
if (retryCount === maxRetries) {
|
||||||
|
failedPages++;
|
||||||
|
console.error(
|
||||||
|
`Échec du téléchargement de la page ${i} après ${maxRetries} tentatives`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 1000)); // Attendre 1s avant de réessayer
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
await cache.put(
|
||||||
|
`/api/komga/images/books/${book.id}/pages/${i}`,
|
||||||
|
pageResponse.clone()
|
||||||
|
);
|
||||||
|
break; // Sortir de la boucle si réussi
|
||||||
|
} catch (error) {
|
||||||
retryCount++;
|
retryCount++;
|
||||||
if (retryCount === maxRetries) {
|
if (retryCount === maxRetries) {
|
||||||
failedPages++;
|
failedPages++;
|
||||||
console.error(
|
console.error(`Erreur lors du téléchargement de la page ${i}:`, error);
|
||||||
`Échec du téléchargement de la page ${i} après ${maxRetries} tentatives`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
await new Promise((resolve) => setTimeout(resolve, 1000)); // Attendre 1s avant de réessayer
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
await cache.put(`/api/komga/images/books/${book.id}/pages/${i}`, pageResponse.clone());
|
}
|
||||||
break; // Sortir de la boucle si réussi
|
|
||||||
} catch (error) {
|
// Mise à jour du statut
|
||||||
retryCount++;
|
const progress = (i / book.media.pagesCount) * 100;
|
||||||
if (retryCount === maxRetries) {
|
setDownloadProgress(progress);
|
||||||
failedPages++;
|
setBookStatus(book.id, {
|
||||||
console.error(`Erreur lors du téléchargement de la page ${i}:`, error);
|
status: "downloading",
|
||||||
}
|
progress,
|
||||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
timestamp: Date.now(),
|
||||||
|
lastDownloadedPage: i,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Vérifier si le statut a changé pendant le téléchargement
|
||||||
|
const currentStatus = getBookStatus(book.id);
|
||||||
|
if (currentStatus.status === "idle") {
|
||||||
|
// Le téléchargement a été annulé
|
||||||
|
throw new Error("Téléchargement annulé");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mise à jour du statut
|
if (failedPages > 0) {
|
||||||
const progress = (i / book.media.pagesCount) * 100;
|
// Si des pages ont échoué, on supprime tout le cache pour ce livre
|
||||||
setDownloadProgress(progress);
|
await cache.delete(`/api/komga/images/books/${book.id}/pages`);
|
||||||
setBookStatus(book.id, {
|
for (let i = 1; i <= book.media.pagesCount; i++) {
|
||||||
status: "downloading",
|
await cache.delete(`/api/komga/images/books/${book.id}/pages/${i}`);
|
||||||
progress,
|
}
|
||||||
timestamp: Date.now(),
|
setIsAvailableOffline(false);
|
||||||
lastDownloadedPage: i,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Vérifier si le statut a changé pendant le téléchargement
|
|
||||||
const currentStatus = getBookStatus(book.id);
|
|
||||||
if (currentStatus.status === "idle") {
|
|
||||||
// Le téléchargement a été annulé
|
|
||||||
throw new Error("Téléchargement annulé");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failedPages > 0) {
|
|
||||||
// Si des pages ont échoué, on supprime tout le cache pour ce livre
|
|
||||||
await cache.delete(`/api/komga/images/books/${book.id}/pages`);
|
|
||||||
for (let i = 1; i <= book.media.pagesCount; i++) {
|
|
||||||
await cache.delete(`/api/komga/images/books/${book.id}/pages/${i}`);
|
|
||||||
}
|
|
||||||
setIsAvailableOffline(false);
|
|
||||||
setBookStatus(book.id, { status: "error", progress: 0, timestamp: Date.now() });
|
|
||||||
toast({
|
|
||||||
title: "Erreur",
|
|
||||||
description: `${failedPages} page(s) n'ont pas pu être téléchargées. Le livre ne sera pas disponible hors ligne.`,
|
|
||||||
variant: "destructive",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setIsAvailableOffline(true);
|
|
||||||
setBookStatus(book.id, { status: "available", progress: 100, timestamp: Date.now() });
|
|
||||||
toast({
|
|
||||||
title: "Livre téléchargé",
|
|
||||||
description: "Le livre est maintenant disponible hors ligne",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Erreur lors du téléchargement:", error);
|
|
||||||
// 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() });
|
|
||||||
toast({
|
|
||||||
title: "Erreur",
|
|
||||||
description: "Une erreur est survenue lors du téléchargement",
|
|
||||||
variant: "destructive",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
setDownloadProgress(0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Vérifie si le livre est déjà disponible hors ligne
|
|
||||||
useEffect(() => {
|
|
||||||
const checkStatus = async () => {
|
|
||||||
const storedStatus = getBookStatus(book.id);
|
|
||||||
|
|
||||||
// Si le livre est marqué comme en cours de téléchargement
|
|
||||||
if (storedStatus.status === "downloading") {
|
|
||||||
// Si le téléchargement a commencé il y a plus de 5 minutes, on considère qu'il a échoué
|
|
||||||
if (Date.now() - storedStatus.timestamp > 5 * 60 * 1000) {
|
|
||||||
setBookStatus(book.id, { status: "error", progress: 0, timestamp: Date.now() });
|
setBookStatus(book.id, { status: "error", progress: 0, timestamp: Date.now() });
|
||||||
setIsLoading(false);
|
toast({
|
||||||
setDownloadProgress(0);
|
title: "Erreur",
|
||||||
|
description: `${failedPages} page(s) n'ont pas pu être téléchargées. Le livre ne sera pas disponible hors ligne.`,
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// On reprend le téléchargement là où il s'était arrêté
|
setIsAvailableOffline(true);
|
||||||
setIsLoading(true);
|
setBookStatus(book.id, { status: "available", progress: 100, timestamp: Date.now() });
|
||||||
setDownloadProgress(storedStatus.progress);
|
toast({
|
||||||
const startFromPage = (storedStatus.lastDownloadedPage || 0) + 1;
|
title: "Livre téléchargé",
|
||||||
downloadBook(startFromPage);
|
description: "Le livre est maintenant disponible hors ligne",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Erreur lors du téléchargement:", error);
|
||||||
|
// 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() });
|
||||||
|
toast({
|
||||||
|
title: "Erreur",
|
||||||
|
description: "Une erreur est survenue lors du téléchargement",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
setDownloadProgress(0);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
[book.id, book.media.pagesCount, getBookStatus, setBookStatus, toast]
|
||||||
|
);
|
||||||
|
|
||||||
await checkOfflineAvailability();
|
const checkOfflineAvailability = useCallback(async () => {
|
||||||
};
|
|
||||||
|
|
||||||
checkStatus();
|
|
||||||
}, [book.id]);
|
|
||||||
|
|
||||||
const checkOfflineAvailability = async () => {
|
|
||||||
if (!("caches" in window)) return;
|
if (!("caches" in window)) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -209,7 +194,30 @@ export function BookOfflineButton({ book, className }: BookOfflineButtonProps) {
|
|||||||
console.error("Erreur lors de la vérification du cache:", error);
|
console.error("Erreur lors de la vérification du cache:", error);
|
||||||
setBookStatus(book.id, { status: "error", progress: 0, timestamp: Date.now() });
|
setBookStatus(book.id, { status: "error", progress: 0, timestamp: Date.now() });
|
||||||
}
|
}
|
||||||
};
|
}, [book.id, book.media.pagesCount, setBookStatus]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkStatus = async () => {
|
||||||
|
const storedStatus = getBookStatus(book.id);
|
||||||
|
|
||||||
|
if (storedStatus.status === "downloading") {
|
||||||
|
if (Date.now() - storedStatus.timestamp > 5 * 60 * 1000) {
|
||||||
|
setBookStatus(book.id, { status: "error", progress: 0, timestamp: Date.now() });
|
||||||
|
setIsLoading(false);
|
||||||
|
setDownloadProgress(0);
|
||||||
|
} else {
|
||||||
|
setIsLoading(true);
|
||||||
|
setDownloadProgress(storedStatus.progress);
|
||||||
|
const startFromPage = (storedStatus.lastDownloadedPage || 0) + 1;
|
||||||
|
downloadBook(startFromPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await checkOfflineAvailability();
|
||||||
|
};
|
||||||
|
|
||||||
|
checkStatus();
|
||||||
|
}, [book.id, checkOfflineAvailability, downloadBook, getBookStatus, setBookStatus]);
|
||||||
|
|
||||||
const handleToggleOffline = async () => {
|
const handleToggleOffline = async () => {
|
||||||
if (!("caches" in window)) {
|
if (!("caches" in window)) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { cookies } from "next/headers";
|
import { cookies } from "next/headers";
|
||||||
import connectDB from "@/lib/mongodb";
|
import connectDB from "@/lib/mongodb";
|
||||||
import { UserModel } from "@/lib/models/user.model";
|
import { UserModel } from "@/lib/models/user.model";
|
||||||
|
import bcrypt from "bcrypt";
|
||||||
|
|
||||||
interface UserData {
|
interface UserData {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -10,6 +11,8 @@ interface UserData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class AuthServerService {
|
export class AuthServerService {
|
||||||
|
private static readonly SALT_ROUNDS = 10;
|
||||||
|
|
||||||
static async createUser(email: string, password: string): Promise<UserData> {
|
static async createUser(email: string, password: string): Promise<UserData> {
|
||||||
await connectDB();
|
await connectDB();
|
||||||
|
|
||||||
@@ -24,10 +27,13 @@ export class AuthServerService {
|
|||||||
throw new Error("EMAIL_EXISTS");
|
throw new Error("EMAIL_EXISTS");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hash password
|
||||||
|
const hashedPassword = await bcrypt.hash(password, this.SALT_ROUNDS);
|
||||||
|
|
||||||
// Create new user
|
// Create new user
|
||||||
const user = await UserModel.create({
|
const user = await UserModel.create({
|
||||||
email: email.toLowerCase(),
|
email: email.toLowerCase(),
|
||||||
password,
|
password: hashedPassword,
|
||||||
roles: ["ROLE_USER"],
|
roles: ["ROLE_USER"],
|
||||||
authenticated: true,
|
authenticated: true,
|
||||||
});
|
});
|
||||||
@@ -41,6 +47,7 @@ export class AuthServerService {
|
|||||||
|
|
||||||
return userData;
|
return userData;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isPasswordStrong(password: string): boolean {
|
static isPasswordStrong(password: string): boolean {
|
||||||
//check if password is strong
|
//check if password is strong
|
||||||
if (password.length < 8) {
|
if (password.length < 8) {
|
||||||
@@ -52,9 +59,9 @@ export class AuthServerService {
|
|||||||
if (!/[0-9]/.test(password)) {
|
if (!/[0-9]/.test(password)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!/[!@#$%^&*]/.test(password)) {
|
// if (!/[!@#$%^&*]/.test(password)) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +102,8 @@ export class AuthServerService {
|
|||||||
throw new Error("INVALID_CREDENTIALS");
|
throw new Error("INVALID_CREDENTIALS");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.password !== password) {
|
const isPasswordValid = await bcrypt.compare(password, user.password);
|
||||||
|
if (!isPasswordValid) {
|
||||||
throw new Error("INVALID_CREDENTIALS");
|
throw new Error("INVALID_CREDENTIALS");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { AuthConfig } from "@/types/auth";
|
import { AuthConfig } from "@/types/auth";
|
||||||
import { serverCacheService } from "./server-cache.service";
|
import { getServerCacheService } from "./server-cache.service";
|
||||||
import { ConfigDBService } from "./config-db.service";
|
import { ConfigDBService } from "./config-db.service";
|
||||||
import { DebugService } from "./debug.service";
|
import { DebugService } from "./debug.service";
|
||||||
|
|
||||||
@@ -52,10 +52,11 @@ export abstract class BaseApiService {
|
|||||||
fetcher: () => Promise<T>,
|
fetcher: () => Promise<T>,
|
||||||
type: CacheType = "DEFAULT"
|
type: CacheType = "DEFAULT"
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
|
const cacheService = await getServerCacheService();
|
||||||
const startTime = performance.now();
|
const startTime = performance.now();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await serverCacheService.getOrSet(key, fetcher, type);
|
const result = await cacheService.getOrSet(key, fetcher, type);
|
||||||
const endTime = performance.now();
|
const endTime = performance.now();
|
||||||
|
|
||||||
// Log la requête avec l'indication du cache
|
// Log la requête avec l'indication du cache
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { cookies } from "next/headers";
|
|
||||||
import connectDB from "@/lib/mongodb";
|
import connectDB from "@/lib/mongodb";
|
||||||
import { KomgaConfig } from "@/lib/models/config.model";
|
import { KomgaConfig } from "@/lib/models/config.model";
|
||||||
import { TTLConfig } from "@/lib/models/ttl-config.model";
|
import { TTLConfig } from "@/lib/models/ttl-config.model";
|
||||||
@@ -34,6 +33,24 @@ export class ConfigDBService {
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async saveConfig(data: KomgaConfigData) {
|
||||||
|
const user = this.getCurrentUser();
|
||||||
|
await connectDB();
|
||||||
|
|
||||||
|
const config = await KomgaConfig.findOneAndUpdate(
|
||||||
|
{ userId: user.id },
|
||||||
|
{
|
||||||
|
userId: user.id,
|
||||||
|
url: data.url,
|
||||||
|
username: data.username,
|
||||||
|
password: data.password,
|
||||||
|
},
|
||||||
|
{ upsert: true, new: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
static async getConfig() {
|
static async getConfig() {
|
||||||
const user = this.getCurrentUser();
|
const user = this.getCurrentUser();
|
||||||
await connectDB();
|
await connectDB();
|
||||||
@@ -44,25 +61,6 @@ export class ConfigDBService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static async saveConfig(data: KomgaConfigData) {
|
|
||||||
const user = this.getCurrentUser();
|
|
||||||
await connectDB();
|
|
||||||
|
|
||||||
return DebugService.measureMongoOperation("saveConfig", async () => {
|
|
||||||
const config = await KomgaConfig.findOneAndUpdate(
|
|
||||||
{ userId: user.id },
|
|
||||||
{
|
|
||||||
userId: user.id,
|
|
||||||
url: data.url,
|
|
||||||
username: data.username,
|
|
||||||
password: data.password,
|
|
||||||
},
|
|
||||||
{ upsert: true, new: true }
|
|
||||||
);
|
|
||||||
return config;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getTTLConfig() {
|
static async getTTLConfig() {
|
||||||
const user = this.getCurrentUser();
|
const user = this.getCurrentUser();
|
||||||
await connectDB();
|
await connectDB();
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { cookies } from "next/headers";
|
|
||||||
import connectDB from "@/lib/mongodb";
|
import connectDB from "@/lib/mongodb";
|
||||||
import { FavoriteModel } from "@/lib/models/favorite.model";
|
import { FavoriteModel } from "@/lib/models/favorite.model";
|
||||||
import { DebugService } from "./debug.service";
|
import { DebugService } from "./debug.service";
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
import { BaseApiService } from "./base-api.service";
|
import { BaseApiService } from "./base-api.service";
|
||||||
import { KomgaBook, KomgaSeries } from "@/types/komga";
|
import { KomgaBook, KomgaSeries } from "@/types/komga";
|
||||||
import { LibraryResponse } from "@/types/library";
|
import { LibraryResponse } from "@/types/library";
|
||||||
import { serverCacheService } from "./server-cache.service";
|
import { getServerCacheService } from "./server-cache.service";
|
||||||
|
|
||||||
interface HomeData {
|
interface HomeData {
|
||||||
ongoing: KomgaSeries[];
|
ongoing: KomgaSeries[];
|
||||||
recentlyRead: KomgaBook[];
|
recentlyRead: KomgaBook[];
|
||||||
onDeck: KomgaBook[];
|
onDeck: KomgaBook[];
|
||||||
|
latestSeries: KomgaSeries[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HomeService extends BaseApiService {
|
export class HomeService extends BaseApiService {
|
||||||
static async getHomeData(): Promise<HomeData> {
|
static async getHomeData(): Promise<HomeData> {
|
||||||
try {
|
try {
|
||||||
// Appels API parallèles avec cache individuel
|
// Appels API parallèles avec cache individuel
|
||||||
const [ongoing, recentlyRead, onDeck] = await Promise.all([
|
const [ongoing, recentlyRead, onDeck, latestSeries] = await Promise.all([
|
||||||
this.fetchWithCache<LibraryResponse<KomgaSeries>>(
|
this.fetchWithCache<LibraryResponse<KomgaSeries>>(
|
||||||
"home-ongoing",
|
"home-ongoing",
|
||||||
async () =>
|
async () =>
|
||||||
@@ -55,21 +56,36 @@ export class HomeService extends BaseApiService {
|
|||||||
}),
|
}),
|
||||||
"HOME"
|
"HOME"
|
||||||
),
|
),
|
||||||
|
this.fetchWithCache<LibraryResponse<KomgaSeries>>(
|
||||||
|
"home-latest-series",
|
||||||
|
async () =>
|
||||||
|
this.fetchFromApi<LibraryResponse<KomgaSeries>>({
|
||||||
|
path: "series/latest",
|
||||||
|
params: {
|
||||||
|
page: "0",
|
||||||
|
size: "10",
|
||||||
|
media_status: "READY",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
"HOME"
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
ongoing: ongoing.content || [],
|
ongoing: ongoing.content || [],
|
||||||
recentlyRead: recentlyRead.content || [],
|
recentlyRead: recentlyRead.content || [],
|
||||||
onDeck: onDeck.content || [],
|
onDeck: onDeck.content || [],
|
||||||
|
latestSeries: latestSeries.content || [],
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return this.handleError(error, "Impossible de récupérer les données de la page d'accueil");
|
return this.handleError(error, "Impossible de récupérer les données de la page d'accueil");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async clearHomeCache() {
|
static async invalidateHomeCache(): Promise<void> {
|
||||||
serverCacheService.delete("home-ongoing");
|
const cacheService = await getServerCacheService();
|
||||||
serverCacheService.delete("home-recently-read");
|
cacheService.delete("home-ongoing");
|
||||||
serverCacheService.delete("home-on-deck");
|
cacheService.delete("home-recently-read");
|
||||||
|
cacheService.delete("home-on-deck");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { BaseApiService } from "./base-api.service";
|
import { BaseApiService } from "./base-api.service";
|
||||||
import { Library, LibraryResponse } from "@/types/library";
|
import { Library, LibraryResponse } from "@/types/library";
|
||||||
import { Series } from "@/types/series";
|
import { Series } from "@/types/series";
|
||||||
import { serverCacheService } from "./server-cache.service";
|
import { getServerCacheService } from "./server-cache.service";
|
||||||
|
|
||||||
export class LibraryService extends BaseApiService {
|
export class LibraryService extends BaseApiService {
|
||||||
static async getLibraries(): Promise<Library[]> {
|
static async getLibraries(): Promise<Library[]> {
|
||||||
@@ -134,7 +134,8 @@ export class LibraryService extends BaseApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async clearLibrarySeriesCache(libraryId: string) {
|
static async invalidateLibrarySeriesCache(libraryId: string): Promise<void> {
|
||||||
serverCacheService.delete(`library-${libraryId}-all-series`);
|
const cacheService = await getServerCacheService();
|
||||||
|
cacheService.delete(`library-${libraryId}-all-series`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { cookies } from "next/headers";
|
|
||||||
import { PreferencesModel } from "@/lib/models/preferences.model";
|
import { PreferencesModel } from "@/lib/models/preferences.model";
|
||||||
import { AuthServerService } from "./auth-server.service";
|
import { AuthServerService } from "./auth-server.service";
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { KomgaBook, KomgaSeries } from "@/types/komga";
|
|||||||
import { BookService } from "./book.service";
|
import { BookService } from "./book.service";
|
||||||
import { ImageService } from "./image.service";
|
import { ImageService } from "./image.service";
|
||||||
import { PreferencesService } from "./preferences.service";
|
import { PreferencesService } from "./preferences.service";
|
||||||
import { serverCacheService } from "./server-cache.service";
|
import { getServerCacheService } from "./server-cache.service";
|
||||||
|
|
||||||
export class SeriesService extends BaseApiService {
|
export class SeriesService extends BaseApiService {
|
||||||
static async getSeries(seriesId: string): Promise<KomgaSeries> {
|
static async getSeries(seriesId: string): Promise<KomgaSeries> {
|
||||||
@@ -19,8 +19,9 @@ export class SeriesService extends BaseApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async clearSeriesCache(seriesId: string) {
|
static async invalidateSeriesCache(seriesId: string): Promise<void> {
|
||||||
serverCacheService.delete(`series-${seriesId}`);
|
const cacheService = await getServerCacheService();
|
||||||
|
cacheService.delete(`series-${seriesId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getAllSeriesBooks(seriesId: string): Promise<KomgaBook[]> {
|
static async getAllSeriesBooks(seriesId: string): Promise<KomgaBook[]> {
|
||||||
@@ -125,8 +126,9 @@ export class SeriesService extends BaseApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async clearSeriesBooksCache(seriesId: string) {
|
static async invalidateSeriesBooksCache(seriesId: string): Promise<void> {
|
||||||
serverCacheService.delete(`series-${seriesId}-all-books`);
|
const cacheService = await getServerCacheService();
|
||||||
|
cacheService.delete(`series-${seriesId}-all-books`);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getFirstBook(seriesId: string): Promise<string> {
|
static async getFirstBook(seriesId: string): Promise<string> {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
import { PreferencesService } from "./preferences.service";
|
||||||
|
|
||||||
type CacheMode = "file" | "memory";
|
type CacheMode = "file" | "memory";
|
||||||
|
|
||||||
@@ -37,6 +38,17 @@ class ServerCacheService {
|
|||||||
this.cacheDir = path.join(process.cwd(), ".cache");
|
this.cacheDir = path.join(process.cwd(), ".cache");
|
||||||
this.ensureCacheDirectory();
|
this.ensureCacheDirectory();
|
||||||
this.cleanExpiredCache();
|
this.cleanExpiredCache();
|
||||||
|
this.initializeCacheMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async initializeCacheMode(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const preferences = await PreferencesService.getPreferences();
|
||||||
|
this.setCacheMode(preferences.cacheMode);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error initializing cache mode from preferences:", error);
|
||||||
|
// Keep default memory mode if preferences can't be loaded
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ensureCacheDirectory(): void {
|
private ensureCacheDirectory(): void {
|
||||||
@@ -117,9 +129,10 @@ class ServerCacheService {
|
|||||||
cleanDirectory(this.cacheDir);
|
cleanDirectory(this.cacheDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getInstance(): ServerCacheService {
|
public static async getInstance(): Promise<ServerCacheService> {
|
||||||
if (!ServerCacheService.instance) {
|
if (!ServerCacheService.instance) {
|
||||||
ServerCacheService.instance = new ServerCacheService();
|
ServerCacheService.instance = new ServerCacheService();
|
||||||
|
await ServerCacheService.instance.initializeCacheMode();
|
||||||
}
|
}
|
||||||
return ServerCacheService.instance;
|
return ServerCacheService.instance;
|
||||||
}
|
}
|
||||||
@@ -376,4 +389,15 @@ class ServerCacheService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const serverCacheService = ServerCacheService.getInstance();
|
// Créer une instance initialisée du service
|
||||||
|
let initializedInstance: Promise<ServerCacheService>;
|
||||||
|
|
||||||
|
export const getServerCacheService = async (): Promise<ServerCacheService> => {
|
||||||
|
if (!initializedInstance) {
|
||||||
|
initializedInstance = ServerCacheService.getInstance();
|
||||||
|
}
|
||||||
|
return initializedInstance;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Exporter aussi la classe pour les tests
|
||||||
|
export { ServerCacheService };
|
||||||
|
|||||||
265
yarn.lock
265
yarn.lock
@@ -256,6 +256,21 @@
|
|||||||
"@jridgewell/resolve-uri" "^3.1.0"
|
"@jridgewell/resolve-uri" "^3.1.0"
|
||||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||||
|
|
||||||
|
"@mapbox/node-pre-gyp@^1.0.11":
|
||||||
|
version "1.0.11"
|
||||||
|
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa"
|
||||||
|
integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==
|
||||||
|
dependencies:
|
||||||
|
detect-libc "^2.0.0"
|
||||||
|
https-proxy-agent "^5.0.0"
|
||||||
|
make-dir "^3.1.0"
|
||||||
|
node-fetch "^2.6.7"
|
||||||
|
nopt "^5.0.0"
|
||||||
|
npmlog "^5.0.1"
|
||||||
|
rimraf "^3.0.2"
|
||||||
|
semver "^7.3.5"
|
||||||
|
tar "^6.1.11"
|
||||||
|
|
||||||
"@mongodb-js/saslprep@^1.1.0", "@mongodb-js/saslprep@^1.1.9":
|
"@mongodb-js/saslprep@^1.1.0", "@mongodb-js/saslprep@^1.1.9":
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.2.0.tgz"
|
resolved "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.2.0.tgz"
|
||||||
@@ -695,6 +710,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
|
"@types/bcrypt@^5.0.2":
|
||||||
|
version "5.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/bcrypt/-/bcrypt-5.0.2.tgz#22fddc11945ea4fbc3655b3e8b8847cc9f811477"
|
||||||
|
integrity sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/json5@^0.0.29":
|
"@types/json5@^0.0.29":
|
||||||
version "0.0.29"
|
version "0.0.29"
|
||||||
resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz"
|
resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz"
|
||||||
@@ -707,6 +729,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
mongoose "*"
|
mongoose "*"
|
||||||
|
|
||||||
|
"@types/node@*":
|
||||||
|
version "22.13.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.5.tgz#23add1d71acddab2c6a4d31db89c0f98d330b511"
|
||||||
|
integrity sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==
|
||||||
|
dependencies:
|
||||||
|
undici-types "~6.20.0"
|
||||||
|
|
||||||
"@types/node@20.11.16":
|
"@types/node@20.11.16":
|
||||||
version "20.11.16"
|
version "20.11.16"
|
||||||
resolved "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz"
|
resolved "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz"
|
||||||
@@ -880,6 +909,11 @@
|
|||||||
resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz"
|
resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz"
|
||||||
integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==
|
integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==
|
||||||
|
|
||||||
|
abbrev@1:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||||
|
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
||||||
|
|
||||||
acorn-jsx@^5.3.2:
|
acorn-jsx@^5.3.2:
|
||||||
version "5.3.2"
|
version "5.3.2"
|
||||||
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
||||||
@@ -890,6 +924,13 @@ acorn@^8.9.0:
|
|||||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz"
|
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz"
|
||||||
integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
|
integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
|
||||||
|
|
||||||
|
agent-base@6:
|
||||||
|
version "6.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
|
||||||
|
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
|
||||||
|
dependencies:
|
||||||
|
debug "4"
|
||||||
|
|
||||||
ajv@^6.12.4:
|
ajv@^6.12.4:
|
||||||
version "6.12.6"
|
version "6.12.6"
|
||||||
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
|
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
|
||||||
@@ -935,6 +976,19 @@ anymatch@~3.1.2:
|
|||||||
normalize-path "^3.0.0"
|
normalize-path "^3.0.0"
|
||||||
picomatch "^2.0.4"
|
picomatch "^2.0.4"
|
||||||
|
|
||||||
|
"aproba@^1.0.3 || ^2.0.0":
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc"
|
||||||
|
integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==
|
||||||
|
|
||||||
|
are-we-there-yet@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c"
|
||||||
|
integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==
|
||||||
|
dependencies:
|
||||||
|
delegates "^1.0.0"
|
||||||
|
readable-stream "^3.6.0"
|
||||||
|
|
||||||
arg@^5.0.2:
|
arg@^5.0.2:
|
||||||
version "5.0.2"
|
version "5.0.2"
|
||||||
resolved "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz"
|
resolved "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz"
|
||||||
@@ -1094,6 +1148,14 @@ balanced-match@^1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
|
||||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||||
|
|
||||||
|
bcrypt@^5.1.1:
|
||||||
|
version "5.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-5.1.1.tgz#0f732c6dcb4e12e5b70a25e326a72965879ba6e2"
|
||||||
|
integrity sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==
|
||||||
|
dependencies:
|
||||||
|
"@mapbox/node-pre-gyp" "^1.0.11"
|
||||||
|
node-addon-api "^5.0.0"
|
||||||
|
|
||||||
binary-extensions@^2.0.0:
|
binary-extensions@^2.0.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz"
|
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz"
|
||||||
@@ -1207,6 +1269,11 @@ chokidar@^3.5.3:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.2"
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
|
chownr@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
|
||||||
|
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
|
||||||
|
|
||||||
class-variance-authority@^0.7.0:
|
class-variance-authority@^0.7.0:
|
||||||
version "0.7.1"
|
version "0.7.1"
|
||||||
resolved "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz"
|
resolved "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz"
|
||||||
@@ -1249,6 +1316,11 @@ color-string@^1.9.0:
|
|||||||
color-name "^1.0.0"
|
color-name "^1.0.0"
|
||||||
simple-swizzle "^0.2.2"
|
simple-swizzle "^0.2.2"
|
||||||
|
|
||||||
|
color-support@^1.1.2:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
|
||||||
|
integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==
|
||||||
|
|
||||||
color@^4.2.3:
|
color@^4.2.3:
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.npmjs.org/color/-/color-4.2.3.tgz"
|
resolved "https://registry.npmjs.org/color/-/color-4.2.3.tgz"
|
||||||
@@ -1267,6 +1339,11 @@ concat-map@0.0.1:
|
|||||||
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
|
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
|
||||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
||||||
|
|
||||||
|
console-control-strings@^1.0.0, console-control-strings@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
|
||||||
|
integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==
|
||||||
|
|
||||||
cookie@^0.5.0:
|
cookie@^0.5.0:
|
||||||
version "0.5.0"
|
version "0.5.0"
|
||||||
resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz"
|
resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz"
|
||||||
@@ -1323,7 +1400,7 @@ data-view-byte-offset@^1.0.1:
|
|||||||
es-errors "^1.3.0"
|
es-errors "^1.3.0"
|
||||||
is-data-view "^1.0.1"
|
is-data-view "^1.0.1"
|
||||||
|
|
||||||
debug@4.x, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7:
|
debug@4, debug@4.x, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7:
|
||||||
version "4.4.0"
|
version "4.4.0"
|
||||||
resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz"
|
resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz"
|
||||||
integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
|
integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
|
||||||
@@ -1360,7 +1437,12 @@ define-properties@^1.1.3, define-properties@^1.2.1:
|
|||||||
has-property-descriptors "^1.0.0"
|
has-property-descriptors "^1.0.0"
|
||||||
object-keys "^1.1.1"
|
object-keys "^1.1.1"
|
||||||
|
|
||||||
detect-libc@^2.0.2:
|
delegates@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||||
|
integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
|
||||||
|
|
||||||
|
detect-libc@^2.0.0, detect-libc@^2.0.2:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz"
|
resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz"
|
||||||
integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==
|
integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==
|
||||||
@@ -1888,6 +1970,13 @@ fraction.js@^4.3.7:
|
|||||||
resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz"
|
resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz"
|
||||||
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
|
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
|
||||||
|
|
||||||
|
fs-minipass@^2.0.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||||
|
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
|
||||||
|
dependencies:
|
||||||
|
minipass "^3.0.0"
|
||||||
|
|
||||||
fs.realpath@^1.0.0:
|
fs.realpath@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||||
@@ -1920,6 +2009,21 @@ functions-have-names@^1.2.3:
|
|||||||
resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz"
|
resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz"
|
||||||
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
|
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
|
||||||
|
|
||||||
|
gauge@^3.0.0:
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395"
|
||||||
|
integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==
|
||||||
|
dependencies:
|
||||||
|
aproba "^1.0.3 || ^2.0.0"
|
||||||
|
color-support "^1.1.2"
|
||||||
|
console-control-strings "^1.0.0"
|
||||||
|
has-unicode "^2.0.1"
|
||||||
|
object-assign "^4.1.1"
|
||||||
|
signal-exit "^3.0.0"
|
||||||
|
string-width "^4.2.3"
|
||||||
|
strip-ansi "^6.0.1"
|
||||||
|
wide-align "^1.1.2"
|
||||||
|
|
||||||
get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7:
|
get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7:
|
||||||
version "1.2.7"
|
version "1.2.7"
|
||||||
resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz"
|
resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz"
|
||||||
@@ -2092,6 +2196,11 @@ has-tostringtag@^1.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
has-symbols "^1.0.3"
|
has-symbols "^1.0.3"
|
||||||
|
|
||||||
|
has-unicode@^2.0.1:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||||
|
integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==
|
||||||
|
|
||||||
hasown@^2.0.2:
|
hasown@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz"
|
resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz"
|
||||||
@@ -2099,6 +2208,14 @@ hasown@^2.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
function-bind "^1.1.2"
|
function-bind "^1.1.2"
|
||||||
|
|
||||||
|
https-proxy-agent@^5.0.0:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
|
||||||
|
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
|
||||||
|
dependencies:
|
||||||
|
agent-base "6"
|
||||||
|
debug "4"
|
||||||
|
|
||||||
ignore@^5.2.0, ignore@^5.3.1:
|
ignore@^5.2.0, ignore@^5.3.1:
|
||||||
version "5.3.2"
|
version "5.3.2"
|
||||||
resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz"
|
resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz"
|
||||||
@@ -2125,7 +2242,7 @@ inflight@^1.0.4:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
inherits@2:
|
inherits@2, inherits@^2.0.3:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
@@ -2527,6 +2644,13 @@ lucide-react@0.323.0:
|
|||||||
resolved "https://registry.npmjs.org/lucide-react/-/lucide-react-0.323.0.tgz"
|
resolved "https://registry.npmjs.org/lucide-react/-/lucide-react-0.323.0.tgz"
|
||||||
integrity sha512-rTXZFILl2Y4d1SG9p1Mdcf17AcPvPvpc/egFIzUrp7IUy60MUQo3Oi1mu8LGYXUVwuRZYsSMt3csHRW5mAovJg==
|
integrity sha512-rTXZFILl2Y4d1SG9p1Mdcf17AcPvPvpc/egFIzUrp7IUy60MUQo3Oi1mu8LGYXUVwuRZYsSMt3csHRW5mAovJg==
|
||||||
|
|
||||||
|
make-dir@^3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
|
||||||
|
integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
|
||||||
|
dependencies:
|
||||||
|
semver "^6.0.0"
|
||||||
|
|
||||||
math-intrinsics@^1.1.0:
|
math-intrinsics@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz"
|
resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz"
|
||||||
@@ -2576,11 +2700,36 @@ minimist@^1.2.0, minimist@^1.2.6:
|
|||||||
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz"
|
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz"
|
||||||
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||||
|
|
||||||
|
minipass@^3.0.0:
|
||||||
|
version "3.3.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
|
||||||
|
integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
|
||||||
|
dependencies:
|
||||||
|
yallist "^4.0.0"
|
||||||
|
|
||||||
|
minipass@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
|
||||||
|
integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
|
||||||
|
|
||||||
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2:
|
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2:
|
||||||
version "7.1.2"
|
version "7.1.2"
|
||||||
resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz"
|
resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz"
|
||||||
integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
|
integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
|
||||||
|
|
||||||
|
minizlib@^2.1.1:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
|
||||||
|
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
|
||||||
|
dependencies:
|
||||||
|
minipass "^3.0.0"
|
||||||
|
yallist "^4.0.0"
|
||||||
|
|
||||||
|
mkdirp@^1.0.3:
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||||
|
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||||
|
|
||||||
mongodb-connection-string-url@^3.0.0:
|
mongodb-connection-string-url@^3.0.0:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz"
|
resolved "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz"
|
||||||
@@ -2712,11 +2861,30 @@ next@14.1.0:
|
|||||||
"@next/swc-win32-ia32-msvc" "14.1.0"
|
"@next/swc-win32-ia32-msvc" "14.1.0"
|
||||||
"@next/swc-win32-x64-msvc" "14.1.0"
|
"@next/swc-win32-x64-msvc" "14.1.0"
|
||||||
|
|
||||||
|
node-addon-api@^5.0.0:
|
||||||
|
version "5.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762"
|
||||||
|
integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==
|
||||||
|
|
||||||
|
node-fetch@^2.6.7:
|
||||||
|
version "2.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||||
|
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
||||||
|
dependencies:
|
||||||
|
whatwg-url "^5.0.0"
|
||||||
|
|
||||||
node-releases@^2.0.19:
|
node-releases@^2.0.19:
|
||||||
version "2.0.19"
|
version "2.0.19"
|
||||||
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz"
|
resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz"
|
||||||
integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==
|
integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==
|
||||||
|
|
||||||
|
nopt@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
|
||||||
|
integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==
|
||||||
|
dependencies:
|
||||||
|
abbrev "1"
|
||||||
|
|
||||||
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz"
|
resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz"
|
||||||
@@ -2727,6 +2895,16 @@ normalize-range@^0.1.2:
|
|||||||
resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz"
|
resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz"
|
||||||
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
|
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
|
||||||
|
|
||||||
|
npmlog@^5.0.1:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0"
|
||||||
|
integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==
|
||||||
|
dependencies:
|
||||||
|
are-we-there-yet "^2.0.0"
|
||||||
|
console-control-strings "^1.1.0"
|
||||||
|
gauge "^3.0.0"
|
||||||
|
set-blocking "^2.0.0"
|
||||||
|
|
||||||
oauth@^0.9.15:
|
oauth@^0.9.15:
|
||||||
version "0.9.15"
|
version "0.9.15"
|
||||||
resolved "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz"
|
resolved "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz"
|
||||||
@@ -3105,6 +3283,15 @@ read-cache@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
pify "^2.3.0"
|
pify "^2.3.0"
|
||||||
|
|
||||||
|
readable-stream@^3.6.0:
|
||||||
|
version "3.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
|
||||||
|
integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
|
||||||
|
dependencies:
|
||||||
|
inherits "^2.0.3"
|
||||||
|
string_decoder "^1.1.1"
|
||||||
|
util-deprecate "^1.0.1"
|
||||||
|
|
||||||
readdirp@~3.6.0:
|
readdirp@~3.6.0:
|
||||||
version "3.6.0"
|
version "3.6.0"
|
||||||
resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz"
|
resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz"
|
||||||
@@ -3201,6 +3388,11 @@ safe-array-concat@^1.1.3:
|
|||||||
has-symbols "^1.1.0"
|
has-symbols "^1.1.0"
|
||||||
isarray "^2.0.5"
|
isarray "^2.0.5"
|
||||||
|
|
||||||
|
safe-buffer@~5.2.0:
|
||||||
|
version "5.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
|
|
||||||
safe-push-apply@^1.0.0:
|
safe-push-apply@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz"
|
||||||
@@ -3225,16 +3417,21 @@ scheduler@^0.23.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
|
|
||||||
semver@^6.3.1:
|
semver@^6.0.0, semver@^6.3.1:
|
||||||
version "6.3.1"
|
version "6.3.1"
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
|
resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
|
||||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||||
|
|
||||||
semver@^7.5.4, semver@^7.6.0, semver@^7.6.3:
|
semver@^7.3.5, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3:
|
||||||
version "7.7.1"
|
version "7.7.1"
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz"
|
resolved "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz"
|
||||||
integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
|
integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
|
||||||
|
|
||||||
|
set-blocking@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||||
|
integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
|
||||||
|
|
||||||
set-function-length@^1.2.2:
|
set-function-length@^1.2.2:
|
||||||
version "1.2.2"
|
version "1.2.2"
|
||||||
resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz"
|
resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz"
|
||||||
@@ -3357,6 +3554,11 @@ sift@17.1.3:
|
|||||||
resolved "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz"
|
resolved "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz"
|
||||||
integrity sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==
|
integrity sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==
|
||||||
|
|
||||||
|
signal-exit@^3.0.0:
|
||||||
|
version "3.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||||
|
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||||
|
|
||||||
signal-exit@^4.0.1:
|
signal-exit@^4.0.1:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz"
|
resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz"
|
||||||
@@ -3405,7 +3607,7 @@ streamsearch@^1.1.0:
|
|||||||
is-fullwidth-code-point "^3.0.0"
|
is-fullwidth-code-point "^3.0.0"
|
||||||
strip-ansi "^6.0.1"
|
strip-ansi "^6.0.1"
|
||||||
|
|
||||||
string-width@^4.1.0:
|
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.3:
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
@@ -3491,6 +3693,13 @@ string.prototype.trimstart@^1.0.8:
|
|||||||
define-properties "^1.2.1"
|
define-properties "^1.2.1"
|
||||||
es-object-atoms "^1.0.0"
|
es-object-atoms "^1.0.0"
|
||||||
|
|
||||||
|
string_decoder@^1.1.1:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
|
||||||
|
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "~5.2.0"
|
||||||
|
|
||||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||||
@@ -3599,6 +3808,18 @@ tapable@^2.2.0:
|
|||||||
resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz"
|
resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz"
|
||||||
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
|
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
|
||||||
|
|
||||||
|
tar@^6.1.11:
|
||||||
|
version "6.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"
|
||||||
|
integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==
|
||||||
|
dependencies:
|
||||||
|
chownr "^2.0.0"
|
||||||
|
fs-minipass "^2.0.0"
|
||||||
|
minipass "^5.0.0"
|
||||||
|
minizlib "^2.1.1"
|
||||||
|
mkdirp "^1.0.3"
|
||||||
|
yallist "^4.0.0"
|
||||||
|
|
||||||
text-table@^0.2.0:
|
text-table@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz"
|
resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz"
|
||||||
@@ -3640,6 +3861,11 @@ tr46@^5.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.3.1"
|
punycode "^2.3.1"
|
||||||
|
|
||||||
|
tr46@~0.0.3:
|
||||||
|
version "0.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||||
|
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
|
||||||
|
|
||||||
ts-api-utils@^1.0.1:
|
ts-api-utils@^1.0.1:
|
||||||
version "1.4.3"
|
version "1.4.3"
|
||||||
resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz"
|
resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz"
|
||||||
@@ -3747,6 +3973,11 @@ undici-types@~5.26.4:
|
|||||||
resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz"
|
resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz"
|
||||||
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||||
|
|
||||||
|
undici-types@~6.20.0:
|
||||||
|
version "6.20.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
|
||||||
|
integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==
|
||||||
|
|
||||||
update-browserslist-db@^1.1.1:
|
update-browserslist-db@^1.1.1:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz"
|
resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz"
|
||||||
@@ -3777,7 +4008,7 @@ use-sidecar@^1.1.2:
|
|||||||
detect-node-es "^1.1.0"
|
detect-node-es "^1.1.0"
|
||||||
tslib "^2.0.0"
|
tslib "^2.0.0"
|
||||||
|
|
||||||
util-deprecate@^1.0.2:
|
util-deprecate@^1.0.1, util-deprecate@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
|
||||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||||
@@ -3787,6 +4018,11 @@ uuid@^8.3.2:
|
|||||||
resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz"
|
resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz"
|
||||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||||
|
|
||||||
|
webidl-conversions@^3.0.0:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||||
|
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
||||||
|
|
||||||
webidl-conversions@^7.0.0:
|
webidl-conversions@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz"
|
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz"
|
||||||
@@ -3800,6 +4036,14 @@ webidl-conversions@^7.0.0:
|
|||||||
tr46 "^5.0.0"
|
tr46 "^5.0.0"
|
||||||
webidl-conversions "^7.0.0"
|
webidl-conversions "^7.0.0"
|
||||||
|
|
||||||
|
whatwg-url@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
||||||
|
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
|
||||||
|
dependencies:
|
||||||
|
tr46 "~0.0.3"
|
||||||
|
webidl-conversions "^3.0.0"
|
||||||
|
|
||||||
which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1:
|
which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz"
|
resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz"
|
||||||
@@ -3859,6 +4103,13 @@ which@^2.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
isexe "^2.0.0"
|
isexe "^2.0.0"
|
||||||
|
|
||||||
|
wide-align@^1.1.2:
|
||||||
|
version "1.1.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
|
||||||
|
integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==
|
||||||
|
dependencies:
|
||||||
|
string-width "^1.0.2 || 2 || 3 || 4"
|
||||||
|
|
||||||
word-wrap@^1.2.5:
|
word-wrap@^1.2.5:
|
||||||
version "1.2.5"
|
version "1.2.5"
|
||||||
resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz"
|
resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz"
|
||||||
|
|||||||
Reference in New Issue
Block a user